;This code is listed here for entertainment value only, it should ;not be used for anything important. Do not use this for a saleable product. ;Feel free to pass this on to others in it's entirety. along with this message. ;No Guarantees implicit or otherwise are implied, your mileage may vary. $RB(0) $RB(1) $NOMOD51 INCLUDE(87C752.pdf) $INCLUDE(common.inc) ; Put Character routine CLIBC SEGMENT CODE RSEG CLIBC PUBLIC INTCHAR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; INTCHAR ; Timing dependent ASSuME 5 cycles average to get here. ; best case is 38 clock ticks worst case is 86 clock ticks. ; *(R1) contains character read. ; ; CPB is cycles per bit defined in common.inc, see common.inc for explanation. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INTCHAR: ;5 cycles (average) to get here. CLR EA ; 1 cycle Turn off interrupts PUSH ACC ; 2 cycles PUSH R06 ; 2 cycles PUSH R07 ; 2 cycles PUSH B ; 2 cycles PUSH PSW ; 2 cycles ; use bank 0 CLR RS0 ; 1 cycle CLR RS1 ; 1 cycle ;read first (one) bit. Load a with number of samples left on start bit ;make sure at least 50% of the time the signal is (low) or bail ;18 cycles to get here. MOV R6,#9 ; 1 cycle; 8 bits in, 1 stop bit. MOV R7,#((CPB-21)/6) ; 1 cycle MOV A,#(((CPB-21)/6)/2) ; 1 cycle ;21 cycles to get here + 6 cycles each loop. SAMPLE: MOV C,SRD ; 1 cycle SUBB A,#0 ; 1 cycles JB ACC.7,RETGETC ; 2 cycles who cares it's noise. DJNZ R7,SAMPLE ; 2 cycles go for another sample. ;Up to 5 cycles off of the target here, in the case of 9600 baud we are 3 cycles ;too fast here. If we don't sync up here we occasionally garble last bit. MOV A,#0 ; 1 cycle reset character repository. IF ((CPB-21) MOD 6) > 1 REPT (((CPB-21) MOD 6)-1) NOP ; Waste time to get to CPB cycles. ENDM ENDIF ;Now we should be at CPB cycles. ; R7 will contain the time necessary to match 9600 baud. GNEXTBIT: MOV B,A ; 1 cycle save result of rrc or start. MOV R7,#(CPB-8)/4 ; 1 cycle MOV A,#(((CPB-8)/4)/2) ; 1 cycle ; should be basecycles HERE! ; loops = (baseloops-8)/4 NEXTSAMPLE: MOV C,SRD ; 1 cycle SUBB A,#0 ; 1 cycle DJNZ R7,NEXTSAMPLE ; 2 cycles go for another sample. IF ((CPB-8) MOD 4) > 0 REPT (((CPB-8) MOD 4)) NOP ; Waste time to get to CPB cycles. ENDM ENDIF MOV C,ACC.7 ; 1 cycles MOV A,B ; 1 cycle RRC A ; 1 cycle DJNZ R6,GNEXTBIT ; 2 cycles ; Check stop bit, should be a 0 JNB ACC.7,RETGETC ; Bailout, the stop bit is wrong. ;Should check the parity eventually. ; should be 10*basecycles HERE! ; Check for special broadcast chars MOV A,B ; Get 8 bits in. CLR C SUBB A,#BCAST_ON ; See if broadcast on is sent JZ SET_BROADCAST ; It is a broadcast pay attention. CLR C ; See if broadcast off is sent SUBB A,#(BCAST_OFF-BCAST_ON) JZ CLEAR_BROADCAST ; It is the end of a broadcast MOV A,MYSW ; Even if CTS is high, check for ; Broadcast mode. JB ACC.BROADCAST,ITS_FOR_US ; In broadcast mode, read character. JNB CTS,ITS_FOR_US ; If CTS is low it's for us, otherwise ; This keypad is selected, read character. SJMP RETGETC ; If we get to here, this isn't a ; broadcast message either so bail ; Set a bit in MYSW to indicate we are listening to a broadcast. SET_BROADCAST: MOV A,MYSW SETB ACC.BROADCAST MOV MYSW,A SJMP RETGETC ; Special character don't actually do ; anything else with it. ; Clear a bit in MYSW to indicate we are no longer listening to a broadcast. CLEAR_BROADCAST: MOV A,MYSW CLR ACC.BROADCAST MOV MYSW,A SJMP RETGETC ; Special character don't actually do ; anything else with it. ITS_FOR_US: ; Result is put in *R1 MOV A,B ; Get 8 bits in. MOV @R1,A ; Store character in input buffer. INC R1 ; Update input buffer CJNE R1,#IBUFEND,RETGETC ; Wrap input buffer head pointer, if we MOV R1,#IBUFSTART ; are at the end of the buffer. ; Restore registers and turn on all interrupts. RETGETC: POP PSW POP B POP R07 POP R06 POP ACC SETB EA RETI $EJECT END