* * Communications program for the Radio Shack Color Computer 1,2 * Receives up to 48K of data at 38400 baud * Times out after 4 minutes with no incoming data, * and after a 10 second gap after recieving any * See "interesting results" for return values other than buffer * * 13-Sep-1986 101am WJY * 31-Jan-1996 1248nn WJY * 21-Feb-1998 2am WJY - brought in synch with comm5s19 * 25-Sep-1999 345am WJY - from COMM4 * 29-Sep-1999 3am WJY - fixed sample timing * 29-Sep-1999 330am WJY - at end, rlast = .x, not .y * - also fixed time-out delays * noopt include "coco.asm" BUFBEG equ $4000 ; buffer beginning address BUFEND equ $FF00 ; ending S_IN_A equ PIA1BD ; serial input address S_IN_B equ $01 ; serial input mask byte W1 equ 255 ; start-bit delays - gazillionths W2 equ 183 ; - jillionths W3 equ 240 ; - seconds org $3000 begin bra rstart fcb $99,$09,$29,$03,$30 ; revision date & time fcc "COMM6 V0.3" rstart sty y_tmp ; save .y and .u stu u_tmp orcc #(IRQ|FIRQ) ; ignore interrupts sta SAMTYP+1 ; use 64K of RAM ldx #BUFBEG ldu #S_IN_A ; constant ldb #S_IN_B lda #W3 sta wait3 * Watch for the start bit. * Sample the incoming bit at least once every 12 cycles * Whatever other work we do here, such as counting down for * a time-out, must be interleaved with start-bit sampling. * initialize counters st2 bitb ,u ; test for start bit 4 \ beq strtbt ; 3 |- 9 lda #W2 ; 2 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 sta wait2 ; 5 / st1 bitb ,u ; test again 4 \ beq strtbt ; 3 |- 9 lda #W1 ; 2 / * count down in .a s_str1 bitb ,u ; test again 4 \_ 7 beq strtbt ; 3 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 deca ; W1 loops 2 | bne s_str1 ; 3 / * count down in wait2 bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 lda wait2 ; 5 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 9 deca ; times W2 2 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 sta wait2 ; 5 / bitb ,u ; test again 4 \ beq strtbt ; 3 |_ 12 tsta ; 2 | bne st1 ; 3 / * increment the activity indicator bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 lda ACTIND ; activity indicator 5 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 9 inca ; 2 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 sta ACTIND ; 5 / * count down in wait3 bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 lda wait3 ; 5 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 9 deca ; 2 / bitb ,u ; test again 4 \ beq strtbt ; 3 |- 12 sta wait3 ; 5 / bitb ,u ; test again 4 \ beq strtbt ; 3 |_ 12 tsta ; 2 | bne st2 ; times W3 3 / * all three counters went to zero; time-out lbra rdone ; no data, timed out, return * 894886.2 clock cycles per second / 38400 bits per second. * Need exactly 23.3043281 clock cycles between bits. * Call it 23.3, and try to minimize error in successive bits. * The sample that noticed the start bit could be anywhere * from 1 to 12 cycles into that. In addition to the time * we pass to let the rest of the start bit go by, pass * half of the slack time so the eight data bits will be * sampled near their centers. * But each bit sample is taken 7 clock cycles late, after * a 'bsr'. So compensate by starting the sampling 7 cycles * earlier. * Ie: 23.3 - 12 = 11.3 slack, half of that is 5.65. * 7 cycles have already passed since the start of the * start-bit sample (bitb & beq), so there are 16.3 cycles * left in the start bit. * delay 16.3 + 5.65 - 7 = 14.95 cycles. strtbt cmpx rlast ; 7 \_ 15 cmpy rlast ; 8 / * bit 1: bsr getbit ; get a bit 21 \_ 23 nop ; pass some time 2 / * wanted to pass 23.3 cycles, actually passed only 23 * we are now .3 cycles early * bit 2: bsr getbit ; get a bit 21 \_ 24 brn getbit ; pass some time 3 / * wanted to pass 23.6 cycles, actually passed 24 * we are now .4 cycles late * bit 3: bsr getbit ; get a bit 21 \_ 23 nop ; pass some time 2 / * wanted to pass 22.9 cycles, actually passed 23 * we are now .1 cycles late * bit 4: bsr getbit ; get a bit 21 \_ 23 nop ; pass some time 2 / * wanted to pass 23.2 cycles, actually passed only 23 * we are now .2 cycles early * bit 5: bsr getbit ; get a bit 21 \_ 23 nop ; pass some time 2 / * wanted to pass 23.5 cycles, actually passed only 23 * we are now .5 cycles early * bit 6: bsr getbit ; get a bit 21 \_ 24 brn getbit ; pass some time 3 / * wanted to pass 23.8 cycles, actually passed 24 * we are now .2 cycles late * bit 7: bsr getbit ; get a bit 21 \_ 23 nop ; pass some time 2 / * wanted to pass 23.1 cycles, actually passed only 23 * we are now .1 cycles early * bit 8: cmpx rlast ; pass as much time as bsr 7 \ ldb S_IN_A ; sample incoming bit 5 |_ 16 rorb ; move incoming bit to .cc.c 2 | rora ; shift bit into byte 2 / * wanted to pass 23.4 cycles, actually passed only 16 * we are now 7.4 cycles early * Plus, all 8 sample 'bsr's were 7 cycles early, so we * have 7 extra cycles to fool around here, making a grand * total of 14.4 cycles early. * We have at least one stop bit, or 23.3 cycles * since we arrived so early, we actually have at * least 37.7 cycles. Being earlier is better here; * It is no problem if we get back to watching for * a start bit before this stop bit is completed. sta ,x+ ; save 'em 6 \ sta ACTIND ; show the data as it arrives 5 | ldd #(10<<8)|S_IN_B ; 3 |_ 29 sta wait3 ; timeout is now 10 seconds 5 | cmpx #BUFEND ; 4 | lbne st2 ; if buffer isn't full, go get more 6 / rdone stx rlast ; note how much we got done ldy y_tmp ; restore registers .y and .u ldu u_tmp sta SAMTYP ; use ROMs again andcc #~(IRQ|FIRQ) ; re-enable interrupts rts * bsr getbit ; 7 \ getbit ldb S_IN_A ; sample incoming bit 5 | rorb ; move incoming bit to .cc.c 2 |- 21 rora ; shift bit into byte 2 | rts ; 5 / org $3100 * interesting results rlast rmb 2 ; one past last buffer address received * internal temporary storage byte rmb 1 ; the byte being recieved y_tmp rmb 2 ; hold .y and .u while running u_tmp rmb 2 wait2 rmb 1 ; delay counters wait3 rmb 1 end begin