' ' WU/WPS Model 102 Simplex Printer driver (strip printer), derived ' from WPS Model 2 Teletype Translator code. ' ' Supports simple "TTY mode" ASCII to ITA2 conversion, and WPS ' record format "S", determined by reading a toggle switch at ' power up. ' ' The following functions are supported: ' ' SO motor off ' FF cut off strip ' EM delay 2 seconds ' VT eject N inches of paper ' ESC FIGS (pass through) ' US LTRS (pass through) ' ' SO turns the motor off immediately, rather than waiting ' for the timeout (currently 30 seconds). ' ' FF pulses the CUTTER line for 2.5 seconds, but since ' there is no cutter installed nothing else happens. ' ' EM delays 2 seconds. ' ' VT ejects enough paper to put the most-recently-printed ' character on the other side of the cutter; basically ' it outputs a bunch of spaces. More wishful thinking as there ' is, alas, no cutter. ' ' ESC and US pass through as FIGS and LTRS, respectively. ' ' When the switch is ON, then record format "S" is expected; ' see the specification for details. The encapsulated data is ' treated the same as in TTY mode. ' ' 16 Apr 2002 ' Workin nearly perfectly, all problems now seem to be simply ' poor paper. A problem of dropped FIGS turns out to be a slight ' rangefinder adjustment. STOPP back to 33 (1.5) and no ' software settle delays, etc. ' ' 5 Apr 02 ' Seems reluctant to pull carriage into FIGS; not fully ' convinced this is a hardware problem. Pause added after ' case char output to let carriage lock. ' ' 25 Mar 02 ' Added VTCNT, made it use AtoB. Added #757 lamps ' hanging off unreg DC, and made loop voltage 32VDC. ' Added ESC/US FIGS/LTRS passthrough. ' ' 18 Mar 02 ' ' Added EM, VT, removed Model 02-style outputting of ' NUL and case char on power up. ' ' 17 Mar 02 ' Re-mapped non-ITA characters (mainly CF, LF, etc). ' Some weird bug involving serin not working, may have ' been debug pulsout's or serout. ' Consider using one serin to init serial? ' ' 15 Mar 02 ' Basically works. ' ' 30 Nov 2001 ' Adapted from Model02.bas. ' ' See model02.bas for revisions before 30 Nov 2001. ' ' Copyright Tom Jennings, 1998, 1999, 2001, 2002. ' ASCII(RS-232) to ITA2 (60mA current loop) interface and translator. ' Based upon a Model 01 CPU-I/O card. ' ' See http://wps.com/texts/codes/index.html#ITA2 ' and p 30.34, 1998 ARRL Handbook for ITA2 and speed info. ' ' DATA STOP SPEED (WPM) ' 22mS 26 60 ' 17 21 75 (UNTESTED) ' 13 16 100 (UNTESTED) ' symbol RXSPEED= N2400 ' RS-232 serial line speed ' ASCII characters symbol NUL= 0 symbol SOH= 1 symbol STX= 2 symbol ETX= 3 symbol BEL= 7 ' ^G ASCII BEL: ring bell symbol VT= 11 ' ^K ASCII VT: eject symbol FF= 12 ' ^L ASCII FF: cut paper symbol SO= 14 ' ^N ASCII SO: motor off symbol SI= 15 ' ^O ASCII SI: symbol EM= 25 ' ^Y ASCII EM: delay 2 seconds ' ITA2 characters symbol SPC=4 ' space symbol FIGS= 27 ' FIGS case char (and state) symbol LTRS= 31 ' LTRS case char (and state) ' Teletype 60 WPM specs. symbol DATAP= 21 ' ITA2 output, data bit width symbol STOPP= 33 ' ITA2 output, stop bit width 'symbol STOPP= 42 ' ITA2 output, stop bit width symbol CSETTLE= 100 ' carriage settle/lock time ' Teletype AC motor timer. symbol TIMEOUT= 38000 ' approx. 10 seconds in geta() symbol TIMEOUT1= 2 ' 10-sec intervals motor-off symbol VTCNT= 62 ' # of spaces for VT symbol TTYMODE= 1 ' MODE switch off: TTY mode symbol FILEMODE= 0 ' MODE switch on: File type A symbol poweron= bit0 ' (b0.0) mimics PWR pin symbol indata= bit1 ' (b0.1) STX..ETX state machine symbol serflag= b1 ' serinp() control/status symbol case= b2 ' (char) FIGS or LTRS character symbol n= b3 symbol i= b4 symbol c= b5 symbol j= b6 symbol unused2= b7 symbol unused= b8 symbol timer2= b9 ' # timer1's for motor-off symbol timer1= w5 ' (b10, b11) 10 second timer symbol BOUTpin= pin0 ' ITA2 serial output (1=idle) symbol PWRpin= pin2 ' relay, teletype AC power symbol CUTTER= 3 ' paper cutter (not installed) symbol CUTpin= pin3 ' paper cutter symbol MODEpin= pin4 ' TTY/WPS mode symbol CTS= 5 ' ASCII Clear To Send symbol CTSpin= pin5 ' ASCII Clear To Send symbol RXD= 7 ' ASCII serial input symbol RXDpin= pin7 ' ASCII serial input symbol DBUG= 3 ' 'scope trigger pin ' 76543210 dirs= %01101111 ' ins and outs... pins= %00000101 ' BOUT high, TXD high, CTS low, pause 1000 ' let everything settle, case= FIGS c= " " : gosub AtoB ' say hello c= " " : gosub AtoB n= FIGS : gosub outITA2 n= FIGS : gosub outITA2 c= BEL : gosub AtoB serflag= 1 ' force serial init ' serin RXD, N2400, c ' DEBUG -- works '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' if MODEpin= FILEMODE then fm1 ' if TTY mode, ' TELETYPE mode tt0: gosub timer ' do motor off timer, call serinp : if serflag = 0 then tt0 gosub AtoB ' output it, goto tt0 ' repeat. ' FILE mode fm1: gosub timer call serinp : if serflag = 0 then fm1 ' wait for SOH, if c <> SOH then fm1 ' fm1a: gosub timer call serinp : if serflag = 0 then fm1a ' wait for 'S', if c <> "S" then fm1 fm2: indata= 0 ' no STX yet, fm2a: gosub timer call serinp : if serflag = 0 then fm2a ' process char stream, branch c, (fm1, fm2a, fm2c, fm2, fm1) ' NUL:res 1:eh 2:STX 3:ETX 4:EOT fm2b: if indata = 0 then fm2a ' wait STX, else fall through, fm2c: indata= 1 ' got STX, (AtoB will ignore it) gosub AtoB ' output data character, goto fm2a ' repeat. ' ' Count down the motor timer. ' timer: timer1= timer1 - 1 ' count down motor timer, if timer1 <> 0 then ret ' exit if not zero yet. timer1= TIMEOUT timer2= timer2 - 1 ' decrement number of ten-sec if timer2 <> 0 then ret ' intervals ' ' Turn motor off. ' off: timer1= TIMEOUT ' reset timer, timer2= TIMEOUT1 if poweron = 1 then of1 ' if motor AC already off, BOUTpin= 0 ' turn off magnet current, of1: PWRpin= 0 : poweron= 0 ' turn off AC motor, ret: return ' ' Convert ASCII character C to ITA2 character N. If the new ' character is not in the current case, issue the right case ' character. The table does all the work; it is the entire US ' TTY ITA2 character set in ASCII order in the lower six bits; ' the upper two bits contain the case the character resides in: ' $80=LTRS, $40=FIGS, 0=both (eg. CR, etc). $ff=unprintable ' character. ' ' Western Union Simplex printer 2-B. ' ' We re-map the following characters: ' ASCII ITA ' LF little comma thing (figs 08) ' CR paragraph |P (figs 13) ' ! / ' = = (figs 02) ' ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 '00 $ff $ff $ff $ff $ff $ff $ff $4b $ff $ff $48 $ff $ff $4d $ff $ff '16 $ff $ff $ff $ff $ff $ff $ff $ff $ff $ff $ff $1b $ff $ff $ff $1f '32 $04 $5c $51 $54 $49 $04 $5a $51 $4f $52 $04 $09 $4c $43 $5c $5d '48 $56 $57 $53 $41 $4a $50 $55 $47 $46 $58 $4e $5e $04 $42 $04 $59 '64 $04 $83 $99 $8e $89 $81 $8d $9a $94 $86 $8b $8f $92 $9c $8c $98 '80 $96 $97 $8a $85 $90 $87 $9e $93 $9d $95 $91 $04 $04 $04 $04 $04 ' ' Keep the above table as master, edit into nasty lookup() command. ' ' Process the character; convert to upper case, determine FIGS or LTRS case ' from the table; if different than the current case, issue case character ' first. ' Modifies N, C, J. ' AtoB: if c = SO then off ' control char SO: motor off if c = VT then eject ' eject paper to cutter if c = EM then delay ' pause 2 seconds if c = FF then cut ' cut paper if c < 96 then ab1 ' if lower case, c= c - 32 ' force to upper case ab1: lookup c, ($ff, $ff, $ff, $ff, $ff, $ff, $ff, $4b, $ff, $ff, $48, $ff, $ff, $4d, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $5b, $ff, $ff, $ff, $9f, $04, $4d, $51, $54, $49, $04, $5a, $51, $4f, $52, $04, $04, $4c, $43, $5c, $5d, $56, $57, $53, $41, $4a, $50, $55, $47, $46, $58, $4e, $5e, $04, $42, $04, $59, $04, $83, $99, $8e, $89, $81, $8d, $9a, $94, $86, $8b, $8f, $92, $9c, $8c, $98, $96, $97, $8a, $85, $90, $87, $9e, $93, $9d, $95, $91, $04, $04, $04, $04, $04), c if c = $FF then ret ' if unprintable, done. if poweron = 1 then ab1a ' else if TTY power off... ' ' The motor is off; turn it on. (The Model 02 code from which this was ' swiped had NUL and case character restart/output; I think it's basically ' a waste and it was removed here.) ' BOUTpin= 1 ' turn on magnet loop current, pause 250 ' let settle >> 1 char time, PWRpin= 1 : poweron= 1 ' turn on big AC motor, pause 1000 ' let it get up to speed, ab1a: timer1= TIMEOUT ' continuously reset the timer, timer2= TIMEOUT1 n= c / 64 ' N= case indicator bits, c= c & $1F ' C= 5-bit ITA2 character, if n = 0 then ab2 ' if char in both cases, output lookup n, (0, FIGS, LTRS, 0), n ' else convert case flag to char if n = 0 then ab2 ' output if char in both cases if n = case then ab2 ' else output if no case change case= n : gosub outITA2 ' else save/output case char, ' An attempt to fix mis-printing in software. Turns out to be ' just the rangefinder. ' pause CSETTLE ' let carriage stop moving, ' n= case : gosub outITA2 ' output twice ab2: n= c ' then output data character. ' fall through... ' ' Output the LS 5 bits of N to the teletype. ' Modifies N, J. ' outITA2: BOUTpin= 0 ' do start bit pulsout DBUG, 4 pause DATAP for j= 1 to 5 ' five data bits, BOUTpin= n : n= n / 2 ' assert data, LS bit first pulsout DBUG, 1 pause DATAP ' generate data bit, next j BOUTpin= 1 ' do stop bit pulsout DBUG, 1 pause STOPP return ' ' Eject some paper. ' eject: for i= 1 to VTCNT ' push out paper c= " " : gosub AtoB ' until last printed next i ' char is beyond cutter return ' ' Operate the paper cutter. TBD, but fake it for now. ' cut: pulsout CUTTER, 10000 return ' ' Pause. ' delay: pause 2000 : return END ASM ; ; Poll for a serial character, returns serflag=1 and character in C ; and CTS 0 if one is present (eg. start bit visible on serial line). If ; serflag=1 on entry, CTS is set and the serin() call arguments are ; set up before the serin() call; if serflag=0 on entry then this is ; skipped, which allows for greater speed in tight loops IFF no other ; serial I/O is done between calls. Note that upon character receipt, ; if serflag is left set then serin() will be initialized properly on ; the first call. ; _serinp movf _serflag, f btfss Z ; if serflag set, goto __sp1 ; go init. btfss portB, _RXD ; else if start bit not present, goto done ; exit now. ; Start bit has been asserted onto the serial line; read the ; character then turn off CTS and prepare for return. __sp2 call serin@W ; read character, bcf portb, _CTS ; deassert CTS, movwf _c ; store W in C, movlw 1 movwf _serflag ; set serflag goto done ; Assert CTS, and ready the args for the later serin() call. __sp1 bsf portB, _CTS ; assert CTS, movlw _RXD ; Rx pin number, call BP@Pin movlw _RXSPEED ; port speed, movwf GOP ; (local to ass'y code?) clrf _serflag ; set serflag false, goto done ENDASM