; ; led-ctrl.asm ; ; Accept serial data at 9600 8N1 and interpret it ; If a '1' is received, turn on an LED connected to RB4 ; If a '0' is received, turn off the LED connected to RB4 ; ; Serial TX line is connected via a 10K resistor to RA0 ; ; PORT MAP ; ; PORTA ; 0 Input Serial ; ; PORTB ; 4 Output LED ; ; Based on code by Tom Coonan ; ; Mark Crosbie 9/29/98 ; include p16c84.inc radix dec processor 16c84 SERIAL_BIT equ 0 ; Bit 0 on PORTA LED_BIT equ 4 ; Bit 4 on PORTB ;**** Application's Memory Variables INCHAR equ 0xc ; Input character COUNTHI equ 0x10 ; Counter for Delay routine (MSB) COUNTLO equ 0x11 ; Counter for Delay routine (LSB) DELAYHI equ 0x12 ; Argument for DELAY subroutine (MSB) DELAYLO equ 0x13 ; Argument for DELAY subroutine (LSB) MASK equ 0x14 ; Mask register for each serial bit input TEMP equ 0x15 ; ; After the baud rates are established through the jumpers, the right ; delay constants are written into here. These are the constants ; used in all the run-time delays for serial. ; DELAY_HALF_SERIAL_HI equ 20 ; DELAY_HALF_SERIAL_LO equ 21 ; DELAY_FULL_SERIAL_HI equ 22 ; DELAY_FULL_SERIAL_LO equ 23 ; ;*** End MEMORY Registers ********************************** ; DELAY Constants. ; ; Delays were set emperically - using a Logic Analyzer and ; looking at peek signals for bit timing. ASSUMES the ; current design's 4MHz crystal, of course. DELAY_FULL_9600_HI equ 1 DELAY_FULL_9600_LO equ 25 DELAY_HALF_9600_HI equ 1 DELAY_HALF_9600_LO equ 12 DELAY_50MS_HI equ 0x34 DELAY_50MS_LO equ 0x95 org 0 ; Reset Vector goto Start ; Main entry point of program ;**************************************** ; * ; Start Up Initializtion Stuff * ; * ;**************************************** ; Remember, INCHAR started out as all zeros.. ; Therefore, we only need to SET bits (when PORTA:0 = 0V) ; Also, remember, serial is inverted: ; 0V on PORTA:0 indicates a logic '1' ; 5V on PORTA:0 indicates a logic '0' ; ; The MASK variable is maintained by caller. ; ; GetSerialBit nop nop btfsc PORTA, SERIAL_BIT ; Get PORTA with a 'POSITIVE' serial bit on it retlw 0 ; Do nothing if we got 5V, or logic '0' GetSerialBitIsClr movf MASK, W iorwf INCHAR, f ; SET the bit retlw 0 ;*********************************************************** ; * ; Specific Delay Functions. These are specific delays * ; which load specific delay counts. These routines then * ; call the generic DELAY subroutine. * ; * ;*********************************************************** DelayHalfSerial movf DELAY_HALF_SERIAL_HI, W movwf DELAYHI movf DELAY_HALF_SERIAL_LO, W movwf DELAYLO retlw 0 DelayFullSerial ; Baud rate is 9600, so set up accorsingly movf DELAY_FULL_SERIAL_HI, W movwf DELAYHI movf DELAY_FULL_SERIAL_LO, W movwf DELAYLO retlw 0 Delay50MS movlw DELAY_50MS_HI movwf DELAYHI movlw DELAY_50MS_LO movwf DELAYLO retlw 0 InitDelay200MS call Delay50MS call Delay call Delay50MS call Delay call Delay50MS call Delay call Delay50MS call Delay retlw 0 ; General DELAY routine ; Inputs: ; DELAYHI - Initial Countdown value MSB ; DELAYLO - Initial Countdown value LSB ; Uses: ; COUNTHI - Counter value MSB ; COUNTLO - Counter value LSB Delay movf DELAYHI, W movwf COUNTHI movf DELAYLO, W movwf COUNTLO DelayLoop decfsz COUNTLO goto DelayLoop decfsz COUNTHI goto DelaySetup2 goto DelayDone DelaySetup2 movf DELAYLO, W movwf COUNTLO goto DelayLoop DelayDone retlw 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ***** Main Program Entry !!! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Start clrf PORTA clrf PORTB ; Set up input and output bits bsf STATUS, RP0 bsf TRISA, SERIAL_BIT ; PORTA.0 is input bcf TRISB, LED_BIT ; PORTB.4 is output bcf STATUS, RP0 call Delay50MS ; Wait for tristate to settle...?... call Delay ;** Set up Baud Constants, based on BAUD jumper. movlw DELAY_FULL_9600_HI movwf DELAY_FULL_SERIAL_HI movlw DELAY_FULL_9600_LO movwf DELAY_FULL_SERIAL_LO movlw DELAY_HALF_9600_HI movwf DELAY_HALF_SERIAL_HI movlw DELAY_HALF_9600_LO movwf DELAY_HALF_SERIAL_LO call InitDelay200MS ;******* START Main Loop Here ************** ; Loop and read characters WaitChar ; Wait for start bit clrf INCHAR ; clear the input character movlw B'00000001' ; start out at bit 0 movwf MASK btfss PORTA, SERIAL_BIT ; If we get a '1' or a START bit, skip! goto WaitChar ; Nope.. no start bit. Keep looking ; Got an edge! nop nop call DelayHalfSerial ; Delay half a bit call Delay btfss PORTA, SERIAL_BIT ; Serial bit *should* be zero. goto WaitChar ; False alarm.. BitLoop ; Delay one bit time call DelayFullSerial call Delay call GetSerialBit ; Get Bit into INCHAR bcf STATUS, C ; Clear the carry bit rlf MASK, F ; shift mask left one bit, thru carry btfss STATUS, C ; is the carry set? goto BitLoop ; Delay one bit time for the STOP bit call DelayFullSerial call Delay ; See if the character is 0, if so, turn off the LED movf INCHAR, w sublw '0' btfsc STATUS, Z bcf PORTB, LED_BIT ; turn off the LED btfss STATUS, Z bsf PORTB, LED_BIT ; turn on the LED ; A small pause between each sample call Delay50MS call Delay goto WaitChar end