' ' Story Teller, Model 3, paper tape reader PICSTIC code ' Tom Jennings ' ' $Id: ptr.bas,v 1.2 2003/05/04 22:06:58 tomj Exp $ ' ' A straight-forward paper tape reader, built around an old ' Plessey reader head, retrofitted with a stepper motor. The door ' is lifted on the reader to install a tape; a switch indicates ' door open/closed status. IT DOES NOT READ YELLOW PAPER TAPE! Only ' opaque tape. ' When a tape is placed in the reader, an attempt is made to read a ' byte from the tape (presumably leader). If a reasonable sequence ' of hole/not hole cannot be detected within a predetermined amount ' of motion, a tape is presumed to not be in place. ' Tape is read and bytes output at 2400 baud as long as there is ' a tape in place and the RS-232 CTS signal is asserted. It is ' designed to handle byte-at-a-time read requests. ' If an error occurs (door open, no tape in place, etc) it outputs ' NULs until tape ready. ' 4 May 2003 ' Coded the read-shift-register routine and the check-door-open ' routine in assembly, which seems to have nearly doubled the speed. ' (There was an interim release of this on wps.com but it was untested ' and buggy.) ' mru 22 Aug 1999 ' Added delay, 2nd try to search for hole/no hole/hole transition, to try ' to accomodate for bouncing supply reel. ' Changed 'steptil' such that it steps before test -- I believe this will ' fix doubled characters if they are caused by marginal (edge of hole) reads ' that satisfy the two tests (no hole, hole) when reading. ' ' mru 9 Mar 1999 ' Changed to 9600 baud, and back when the Model 02 failed. ' ' mru 27 Feb 1999 ' Added optical mask, and removed stepit() call after finding edge of hole ' in steptil(). Massively reduced error rate. Fixed small bug in steptil(); ' when sequential hole reads differed, it reset the max-step-loop counter. ' ' mru 15 Feb 1999 ' Original working code. ' ' new 5 Feb 1999 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' file: c:\tomj\projects\model 01, CPU-IO card\model01.bas '' General purpose definitions and functions for the Model 01 '' CPU I/O card. '' '' '' Tom Jennings '' mru 2 Aug 98 '' written 17 July 98 '' '' For unrevised Model 01 card (prototype) card. '' '' Copyright Tom Jennings, 1998. '' symbol SPEED= N2400 symbol valid= bit1 ' 1 == 'data' valid symbol hole= bit2 ' 1 == value of sprocket hole symbol mphase= b2 ' stepper motor phase bits symbol mtime= b3 ' step delay time symbol data= b4 ' word read from paper tape symbol i= b5 symbol n= b6 ' general purpose regs, used here symbol j= b7 ' PICSTIC I/O pin assignments symbol TXD= 7 ' TxD, to talking box RS-232 symbol CTSpin= pin6 ' Clear To Send, input 'symbol M2pin= pin5 ' Motor phase 1 'symbol M1pin= pin4 ' Motor phase 2 symbol MBITS= %00110000 ' motor phase bit mask symbol MNBITS=%11001111 ' NOT motor phase bit mask symbol MSTATE=%00010000 ' initial motor phase bit states symbol SPRpin= pin3 ' sprocket hole symbol SIpin= pin2 ' 74HC165, SERIAL IN data symbol SI= 2 symbol CP= 1 ' 74HC165, clock (rising edge) symbol PL= 0 ' 74HC165, latch (falling edge) symbol SDpin= pin0 ' Model 01, SR data 'symbol DOOR= PA4 ' 1= door open 'symbol MTRINH= PA3 ' 1= motor power off dirs= %10110011 ' set directions, (1=output) ' MM Motor phase bits! pins= %00010001 ' set initial states mphase= MSTATE ' initial motor phase bits mtime= 4 ' motor step time, peek 133, n : n= n | 16 : poke 133, n ' make PA4 an input, peek 133, n : n= n & 247 : poke 133, n ' make PA3 an output, gosub motoron ' turn motor power on, pause 500 serout TXD, SPEED, (0) ' ' Read words from tape and output to the serial port, until error. ' r0: gosub ptr ' try to read from tape, if valid = 0 then r1 ' failed, wait for tape install. r0a: gosub door : if n = 1 then r1 ' watch for door opening, if CTSpin = 0 then r0a ' wait for talking box request, serout TXD, SPEED, (data) ' write out the word read, goto r0 ' repeat endlessly. ' ' Tape read failed; wait for door to open, then to close (eg. tape installed). ' r1: gosub motoroff ' turn off motor power, r1a: serout TXD, SPEED, (0) : pause 25 gosub door : if n <> 1 then r1a ' wait for open, r1b: serout TXD, SPEED, (0) : pause 25 gosub door : if n <> 0 then r1b ' wait for closed, gosub motoron ' turn motor on again, pause 500 ' respectful pause... goto r0 ' ' Read a word from paper tape. This blithely assumes there is ' a tape in place, and tries to read a word. Returns word read ' and valid=1 if success, else valid=0 if no holes detected after ' adequate tape motion. ptr: valid= 0 ' flag= no data read, n= 0 : gosub steptil ' move past current hole, if i <> 0 then pt1 ' if couldn't move past hole, pause 50 ' maybe taut tape, n= 0 : gosub steptil ' try again to move the tape, if i = 0 then ret ' failure, else no tape. pt1: n= 1 : gosub steptil ' move to next sprocket hole, if i <> 0 then pt2 ' if couldn't find a hole, pause 50 ' do tape-bounce thing again n= 1 : gosub steptil if i = 0 then ret ' failed, no tape in place. pt2: call readSR valid= 1 ' word read, ret: return ' Step until we find the sprocket hole in the state specified ' by N (0 or 1). 0 means no sprocket hole visible; 1 means over a ' sprocket hole. I is used internally as loop counter, and returned ' =0 on failure. steptil: i= 100 ' goodly number of tries, st0: gosub stepit ' move the tape, st1: hole= SPRpin ' read the sprocket-hole sensor, if SPRpin <> hole then st1 ' wait for stable hole read, if hole = n then ret ' if there, done. i= i - 1 : if i > 0 then st0 return ' Motor power control. Only two phase bits are needed to drive ' the motor, since two phases are always exactly the opposite of ' the other two. The two bits directly drive the "front" coils; the ' "back" coils are driven by stealing drive current from the "front" ' coils. Turning the motors off means setting the motor phase bits ' to both off, deenergizing the "front" coils; the motor-inhibit ' bit sinks the drive current from the "back" coil drivers, turning ' them off. motoron: peek 5, n : n= n & 247 : poke 5, n ' PA3 low (motor power on) pins= pins | MSTATE ' motor phase initial state, mphase= MSTATE ' make phase in sync, return ' caller must delay. motoroff: pins= pins & MNBITS ' clear both motor phase bits, peek 5, n : n= n | 8 : poke 5, n ' PA3 high (motor power off) return ' ' Step the motor one half step. The motor must be on. ' stepit: pins= pins ^ mphase ' advance motor phases, mphase= mphase ^ MBITS ' update local phase states, pause mtime ' motor settle. return end asm ; Read the data from the photodiodes via the shift register. ; The 74HC165 output we read is Q7; it is valid after we ; strobe the latch; the first bit available is therefore B7, ; and we shift data in, *then* clock the next (LS) bit in. ; Modifies J. _readSR movlw 8 movwf _J ; bits per byte, bcf portB, _PL ; latch photodiodes into SR, bsf portB, _PL ; (falling edge) rsr1 bcf C ; shift 0's in! rlf _data, f ; shift bits over, LSB now 0; btfsc portB, _SI ; if shift register output is 1, bsf _data, 0 ; put 1 in LSB (eg. xfer data) bsf portB, _CP ; clock data out, bcf portB, _CP ; (rising edge) decfsz _J goto rsr1 goto done ; Return in N the state of PA4 (the tape reader door). _door clrf _N ; assume open, btfsc portA, 4 ; test RA4, bsf _N, 0 ; set N if true, goto done ; Set PA3 high. _PA3hi bsf portA, 4 ; set PA3 high, goto done ; Set PA3 low. _PA3lo bcf portA, 4 goto done endasm