dectalk express.

frankiec at unforgettable.com frankiec at unforgettable.com
Wed May 31 03:43:09 EDT 2000


Hi Bart

Well actually I am quite suprised that that doesn't work.  I am actually
wondering if it is just hanging your machine.  I am suspecting that that
is what happens because I have seen that before many times.  

Here is the latest driver.  If you wait until tomorrow speakup-0.09 will
probably be out and all the support will be right there.  Some other
things will be fixed also.  But if your iching for this to get working
drop this file in /usr/src/linux/drivers/chars/speakup.  And call it
'speakup_dectlk.c'.  

Another thing is are you trying to patch 2.2.15 with the standard
speakup-0.08?  Cause that won't work.  I am sure you would have seen it
blow up and would have complained about that though.

So here is the latest driver.  

Have fun
Frank
PS. haven't seen you on the reflector in quite sometime.


/*
 * speakup_dectlk.c - Dectalk Express driver for Linux kernel 2.3.x and speakup
 * 
 * author: Kirk Reiser <kirk at braille.uwo.ca>

    Copyright (C) 1998-99  Kirk Reiser.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Kirk Reiser <kirk at braille.uwo.ca>
    261 Trott dr. London, Ontario, Canada. N6G 1B6
    */


/* These routines are written to control the Dectalk Express speech
   synthesizer by Digital Equipment Corp.  They are not ment to be
   thought of as a device driver in that they do not register
   themselves as a chr device and there is no file_operations
   structure.  They are strictly to provide an interface to the
   Dectalk Express from the speakup screen review package.  */

#define KERNEL
#include <linux/config.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>		/* for verify_area */
#include <linux/errno.h>	/* for -EBUSY */
#include <linux/ioport.h>	/* for check_region, request_region */
#include <linux/delay.h>	/* for loops_per_sec */
#include <asm/segment.h>	/* for put_user_byte */
#include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc... */
#include <linux/wait.h>		/* for wait_queue */
#include <linux/vt_kern.h> /* kd_mksound */
#include <linux/init.h> /* for __init */
#include <linux/serial.h> 	/* for rs_table, serial constants & 
					serial_uart_config */
#include <linux/serial_reg.h> 	/* for more serial constants */
#include <asm/serial.h>
#include <linux/version.h>

#define SYNTH_CLEAR 0x03 /* synth flush char */
#define PROCSPEECH 0x0b /* start synth processing char */
#define synth_ver "Version-0.5"
static int full_status = 0;
#define synth_full() (full_status = (inb_p(synth_port_tts) == 0x13))
#define synthBufferSize 8192  /* currently 8K bytes */
#define JIFFY_DELTA 5	/* number of jiffies do_catch_up is allowed to run */
#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */
#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */
#define SPK_LO_TTY 0	/* check ttyS0 ... ttyS3 */
#define SPK_HI_TTY 3
#define NUM_DISABLE_TIMEOUTS 3	/* # of timeouts permitted before disable */

static int dectlk_alive = 0;
#define INIT_LEN 62
static char INIT_STRING[] = "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk Express found\n";
#define REINIT_LEN 58
static char REINIT_STRING[] = "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk restarted\n"; 
                            /* 160 ms delay and ctrl-x as flush */
int synth_port_tts;
static volatile int synth_timer_active = 0; /* indicates when a timer is set */
 #if (LINUX_VERSION_CODE < 0x20300) /* is it a 2.2.x kernel? */
static struct wait_queue *synth_sleeping_list = NULL; 
#else /* nope it's 2.3.x */
static DECLARE_WAIT_QUEUE_HEAD (synth_sleeping_list);
#endif
static struct timer_list synth_timer;
static unsigned short delay_time = 500; /* time to schedule handler */
static unsigned short trigger_time = 4000; /* initial time to start speech */
static unsigned synth_full_time = 1000; /* wait how long on full synth? */
extern struct spk_t *this[];

#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
char synth_buffering = 1;  /* flag to indicate we're buffering */
static unsigned char buffer[synthBufferSize];  /* guess what this is for! */
static unsigned short end_of_buffer = synthBufferSize;
static volatile unsigned short int queued_bytes = 0, sent_bytes = 0; 
/* queued_bytes points to top of chars queued,
 * sent_bytes points at top of bytes sent by do_catch_up() */

static struct serial_state rs_table[] __initdata = {
	SERIAL_PORT_DFNS
};

/* sleep for ms milliseconds */
static inline void synth_delay(int ms)
{
  synth_timer.expires = jiffies + (ms*HZ + 1000 - HZ)/1000;
  if (! synth_timer.prev) add_timer(&synth_timer);
  synth_timer_active++;
}

static inline void synth_stop_timer(void)
{
  if (synth_timer_active)
      del_timer(&synth_timer);
}

static int timeouts = 0;	/* sequential number of timeouts */

static int wait_for_xmitr(void)
{
int check, tmout = SPK_XMITR_TIMEOUT;

  if ((dectlk_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) {
    dectlk_alive = 0; 
    return 0; 
  }

	/* holding register empty? */
  do {
    check = inb_p(synth_port_tts + UART_LSR);
    if (--tmout == 0) {
      printk("Dectalk Express:  timed out\n");
      timeouts++;
      return 0;
    }
  } while ((check & BOTH_EMPTY) != BOTH_EMPTY);

  tmout = SPK_XMITR_TIMEOUT;
	/* CTS */
	do {
		check = inb_p(synth_port_tts + UART_MSR);
    		if (--tmout == 0) {
    			timeouts++;
    			return 0;
    		}
	} while ((check & UART_MSR_CTS) != UART_MSR_CTS);

  timeouts = 0;
  return 1;
}

static inline int spk_serial_out(const char ch) 
{
  if (dectlk_alive && synth_port_tts) {
    if (wait_for_xmitr()) {
    	outb_p(ch, synth_port_tts);
    	return 1;
    }
  }
  return 0;
}

static unsigned char __init spk_serial_in(void) 
{
int lsr, tmout = SPK_SERIAL_TIMEOUT;
int c;

  do {
    lsr = inb_p(synth_port_tts + UART_LSR);
    if (--tmout == 0) return 0xff;
  } while (!(lsr & UART_LSR_DR));
  c = inb_p(synth_port_tts + UART_RX);
  return (unsigned char) c;
}

static void do_catch_up(unsigned long data)
{
unsigned long jiff_in = jiffies;

synth_stop_timer();
while ((sent_bytes < queued_bytes) && !synth_full())
  {
    if (!spk_serial_out(*(buffer+sent_bytes))) {
    	synth_delay(synth_full_time);
    	return;
    }
    sent_bytes++;
    if (jiffies >= jiff_in+JIFFY_DELTA && *(buffer+sent_bytes-1) == ' ') { 
      spk_serial_out(PROCSPEECH);
      synth_delay(delay_time); 
      return; 
    }
  }

    if (full_status) {
      synth_delay(synth_full_time);
      return;
    }
sent_bytes = queued_bytes = 0;
trigger_time = 50;
spk_serial_out(PROCSPEECH);
synth_timer_active = 0;
if (waitqueue_active(&synth_sleeping_list))
  wake_up_interruptible(&synth_sleeping_list);
return;
}

static inline void buffer_it(char ch)
{
if (queued_bytes+1 == end_of_buffer-100 
    && (! waitqueue_active(&synth_sleeping_list)))
  { /* someone needs to take a nap for a while. */
    interruptible_sleep_on(&synth_sleeping_list);
  }
*(buffer+queued_bytes++) = ch;
return;
}

static inline void clear_it(char ch)
{
  while ((inb_p(synth_port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY);
  outb_p(ch, synth_port_tts);
}

static inline void synth_immediate_tts(const char *buf, size_t count)
{
  while (count--) spk_serial_out(*buf++);
return;
}

void synth_write_tts(char ch)
{
int i = SPK_SERIAL_TIMEOUT;
static char last='[';

  if (!dectlk_alive) return;
  if (ch < 0x00) return; /* don't want unprintable chars */
  if (ch == 0x0a) /* turn lf into <cr> to force talking. */
    ch = 0x0D;
  if (strchr("-'", ch)) ch = ' ';
  if (ch == SYNTH_CLEAR) {		/* clear all and wake sleeping */
    spk_serial_out(ch);
    /*while(spk_serial_in() != 0x01 && i-- > 0);*/
    trigger_time = 100;;
    if (waitqueue_active(&synth_sleeping_list))
      wake_up_interruptible(&synth_sleeping_list);
    if (synth_timer.prev) synth_stop_timer();
    synth_timer_active = queued_bytes = sent_bytes = 0;
    return;
  }

buffer_it(ch);
if ((last != '[') && strchr(",_.@!?/-:", ch)) buffer_it(PROCSPEECH);
last = ch;
if (synth_buffering) return;
if (synth_timer_active == 0) synth_delay( trigger_time );
return;
}

void synth_write(const char *buf, size_t count)
{
  while (count--) synth_write_tts(*buf++);
return;
}

static int __init serprobe(int index)
{
	struct serial_state *ser = NULL;
	unsigned char test=0;

 	if (synth_port_tts) {
          for (test=0; test <= SPK_HI_TTY; test++)
            if ( (rs_table+test)->port == synth_port_tts) {
              ser = rs_table+test;
              break;
            }
        } else  ser = rs_table + index;

	/* don't do output yet... */
	if (check_region(ser->port,8))
		return -1;

	outb_p(0x00, ser->port+UART_MCR);
	outb_p(0, ser->port + UART_IER);
	outb_p(UART_LCR_WLEN8|UART_LCR_DLAB, ser->port + UART_LCR);/* set DLAB */
	outb_p(12, ser->port);		/* set baud rate (9600) */
	outb_p(UART_LCR_WLEN8, ser->port + UART_LCR);	/* reset DLAB */
	outb_p(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
	test = inb_p(ser->port);			/* clear holding register */
	mdelay(1);
	outb(0x0d, ser->port);
	
  dectlk_alive = 1;
	/* ignore any error results, if port was forced */
        if (synth_port_tts) 
		return 0;

	synth_port_tts = ser->port;
	/* check for dectalk express now... */
	if (spk_serial_out(0x03)) {
	  while (spk_serial_in() != 0x01);
	  return 0;  
	}

  timeouts = dectlk_alive = synth_port_tts = 0; /* not ignoring */
  return -1;
}

static int __init synth_dev_probe(void)
{
int i=0;

  printk("Probing for Dectalk Express.\n");
  if (synth_port_tts)
    printk("probe forced to 0x%x by kernel command line\n", synth_port_tts);

	/* check ttyS0-ttyS3 */
  for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) {
    if (serprobe(i) == 0) break; /* found it */
  }

  if (dectlk_alive) {
    /*request_region(synth_port_tts, 8, "dectlk");*/
	  /* found 'em */
    printk("Dectalk Express: %03x-%03x, Driver Version %s,\n",
	   synth_port_tts, synth_port_tts+7, synth_ver);
    synth_immediate_tts(INIT_STRING, INIT_LEN);
    return 0;
  }

  printk("Dectalk Express:  not found\n");
  return -ENODEV;
}

int __init synth_init(void)
{
  if (synth_dev_probe() < 0)
    {
      printk("Dectalk Express:  device probe failed\n");
      return -ENODEV;
    }
  init_timer(&synth_timer); 
  synth_timer.function = do_catch_up;
#if (LINUX_VERSION_CODE >= 0x20300) /* it's a 2.3.x kernel */
  init_waitqueue_head(&synth_sleeping_list);
#else /* it's a 2.2.x kernel */
  init_waitqueue(&synth_sleeping_list);
#endif
  return  0;
}

int synth_alive(void)
{
  if (dectlk_alive)
    return 1; /* already on */
  else if ((!dectlk_alive) && (synth_port_tts)) {
    if (wait_for_xmitr() > 0) { /* restart */
      dectlk_alive = 1;
      synth_write(REINIT_STRING, REINIT_LEN);
      return 2;  /* reenabled */
    } else printk("Dectalk Express: can't restart synth\n");
  }
  return 0;
}

On Wed, 31 May 2000, bart bunting wrote:

> hi,
> 
> that is very nice, it made lilo talk.
> 
> but speakup still can't find the dectalk.
> what is the option to force a serial port?
> and if i use it does it check for the synth still or just assume it's there?
> 
> Bart
> 
> frankiec at unforgettable.com writes:
>  > Yup.  I know all about this problem.  
>  > 
>  > One thing is you will want the latest driver which will be included in
>  > speakup 0.09.  This should be available in the next few days.  
>  > 
>  > However this isn't the fix for your problem.  I would try puting the
>  > 'serial=0,9600N8' in your lilo.conf at the top.  Run lilo, reboot, and
>  > watch it work.
>  > 
>  > HTH
>  > FC
>  > 
>  > 
>  > On Wed, 31 May 2000, bart bunting wrote:
>  > 
>  > > 
>  > > hi Kirk and all,
>  > > 
>  > > A while back Kirk gave me a copy of the new dec express driver, and
>  > > someone else, I forget who, also gave me a copy of the old sluggish
>  > > one.
>  > > 
>  > > I am sad to say I have had no luck after much trying to get either of them to work.  my dectalk isn't found, no matter which machine or driver i try it on.  The dectalk, works perfectly however with emacspeak.  has anyone else had this problem?
>  > > 
>  > > any suggestions apreciated!
>  > > 
>  > > i'm using dectalk firmware 4 2 cd nov 8 96.
>  > > 
>  > > thanks in advance.
>  > > 
>  > > Bart
>  > >  
>  > > 
>  > > _______________________________________________
>  > > Speakup mailing list
>  > > Speakup at braille.uwo.ca
>  > > http://speech.braille.uwo.ca/mailman/listinfo/speakup
>  > > 
>  > 
>  > 
>  > _______________________________________________
>  > Speakup mailing list
>  > Speakup at braille.uwo.ca
>  > http://speech.braille.uwo.ca/mailman/listinfo/speakup
> 
> _______________________________________________
> Speakup mailing list
> Speakup at braille.uwo.ca
> http://speech.braille.uwo.ca/mailman/listinfo/speakup
> 





More information about the Speakup mailing list