list P=PIC16F690 #include "p16F690.inc" __config(_CP_OFF & _CPD_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _HS_OSC) errorlevel -302 ;Init(): ;// Configure pins ;// - turn off all analog functions (ANSEL & ANSELH = 0) ;// - clear TRISA ;// - set TRISC<0> = outputs //putting line high ;// - set TRISB input for Rx (B5) ;// clear PORTC to initialize outputs ;12.1.2.8 Asynchronous Reception Set-up: ;1. Initialize the SPBRGH, SPBRG register pair and the BRGH and BRG16 bits to achieve the desired baud rate (see Section 12.3 “EUSART Baud Rate Generator (BRG)”). ;8N1 Asynch ;9600 baud: ;Load BAUD generators (SPBRG(H)); for 9600 Baud on a 20 MHz oscillator, we want SPBRG = 129, SPBRGH = 0, prescaler = 16 and the following bits: SYNC=0, BRG16=1, BRGH=0. This gives an error of 0.16%. SYNC, BRG16, BRGH are taken care of below ;2. Enable the serial port by setting the SPEN bit. The SYNC bit must be clear for asynchronous operation. ;RCSTA = 10010000 [SPEN is bit 7] ;TXSTA = 00000000 [SYNC is bit 4, BRGH is bit 2] ;BAUDCTL = 00001000 [BRG16 is Bit 3] ;Bit 4 is SCKP. Do we want to invert the data? Probably doesn’t matter – we aren’t transmitting. ;Bit 1 is WUE. For Asynch, should the receiver wait for a falling edge? Goes away when RCIF is set. This is consistent with bringing the line low, but not sure it is the same thing. ;Bit 0 is ABDEN. I don’t think we need to auto-detect the baud (we’ve agreed to 9600) ;3. If interrupts are desired, set the RCIE interrupt enable bit and set the GIE and PEIE bits of the INTCON register. ;Do we want to wait for interrupt, or just sample? If we sample and the query was unsuccessful, we should get 0x00, which wouldn’t pass the checksum test anyway. Probably should sample though – timing the 8 different bytes could be hard. Still can base off the RCIF flag, says Cam, citing their MI6 success; ; movlw 0x20 ;00000010, does not enable RCIE. We can just look at RCIF (which we don’t need to set). Include TMR2IE so we can wait 1ms to bring the line low agai;n ; movwf PIE1 ; movlw 0xC0 ;1100000, enables GIE and PEIE ; movwf INTCON ;4. If 9-bit reception is desired, set the RX9 bit. ;Nope. ;5. Enable reception by setting the CREN bit. ;CREN is bit 4 of RCSTA ;6. The RCIF interrupt flag bit will be set when a character is transferred from the receive shift register to the receive buffer. An interrupt will be generated if the RCIE interrupt enable bit was also set. ;Again, yes, we want this because we want to act every time the receive line is full I think? ;7. Read the RCSTA register to get the error flags and, if 9-bit data reception is enabled, the ninth data bit. ;K ;8. Get the received 8 Least Significant data bits from the receive buffer by reading the RCREG register. ;K ;9. If an overrun occurred, clear the OERR flag by clearing the CREN receiver enable bit. ;Eh. ;movlw 0xFB ;X111 101X 1:16 postscaler, tmr2 off, 16 prescaler ;movwf T2CON ;We need to use this timer for holding the line high. Why is tmr2 off? Maybe just to start. AA equ 0x20 ;init to 0x00 IntactAA equ 0x21 ;init to 0x48 PoppedAA equ 0x22 ;init to 0x5A Header equ 0x23 ;init to 0x02 Footer equ 0x24 ;init to 0x03 RxBytes equ 0x25 ;init to 0x00 Index equ 0x26 ;init to 0x00 CurrentSum equ 0x27 ;init to 0x00 DataRcvd equ 0x28 ;init to 0x00 org 0 goto Main org 5 InitRegs: ; Analog pin clearing banksel ANSEL ; clrf ANSEL ; AN0-7 are digital clrf ANSELH ; AN8-11 are digital ; Initialize port A banksel PORTA clrf PORTA ;Init PORTA bsf STATUS,RP0 ;Bank 1 clrf TRISA ;We need A0 to be an output, so this is good. bcf STATUS,RP0 ;Bank 0 ; Initialize ports B and C banksel PORTB clrf PORTB ;Init PORTB bsf STATUS,RP0 ;Bank 1 movlw 0x20 ;Set RB<5> as input so we can receive data transfer movwf TRISB ; bcf STATUS,RP0 ;Bank 0 banksel PORTC clrf PORTC ;Init PORTC bsf STATUS,RP0 clrf TRISC ;Set RC<0> as output (which we probably don't actually need to do...let's just make them all output bcf STATUS,RP0 ;Select Bank 0 banksel PORTC bsf PORTC, 0 ;pull C0 high to start (query line) ; Init baud bsf STATUS,RP0 ;Bank 1 movlw 0x20 ;br 9615 movwf SPBRG clrf SPBRGH ;probably unnecessary movlw 0x00 ;00001000 BRG16 (16bit baud rate) movwf BAUDCTL clrf TXSTA ;bit 1 is read only, so this comes out 0x02;00000000 TXEN transmit disabled bcf STATUS,RP0 ;Bank 0 movlw 0x90 ;10010000 SPEN and CREN serial port enable and continuous receieve enable movwf RCSTA ;movlw 0xFB ;X111 101X 1:16 postscaler, tmr2 off, 16 prescaler ;movwf T2CON ;I think this is unnecessary because we don't have a timer! bsf STATUS,RP0 ;Bank 1 ;movlw 0x09 ;movwf PR2 ;500us timer 2 module ;disable interrupts ;movlw 0x06 ;00000000 ;movwf PIE1 clrf PIE1 ;we dont need to enable any interrupts -- RCIF will happen regardless, that's all we need (no timer) bcf STATUS, RP0 ;Bank 0 ;movlw 0xC0 ;1100000, enables GIE and PEIE ;movwf INTCON clrf INTCON clrf PIR1 ;set register ref values that don't change movlw 0x48 movwf IntactAA ;init to 0x48 movlw 0x5A movwf PoppedAA ;init to 0x5A movlw 0x02 movwf Header ;init to 0x02 movlw 0x03 movwf Footer ;init to 0x03 RETURN ResetValues: clrf RxBytes ;reset to 0x00 RxBytes and Index can probably be combined... clrf Index ;reset to 0x00 clrf CurrentSum ;reset to 0x00 clrf AA ;reset to 0x00 ;bsf PORTC, 0 ;set PORTC0 high again because we've started to receive data RETURN Main: call InitRegs MainLoop: call ResetValues banksel PORTC bcf PORTC, 0 ;Pull C0 low ; movf RCREG, W ;???no timer;Call QueryMonitor //this will take at least 1ms. Guess we do need the timer. Or not… CheckIF: banksel PIR1 btfss PIR1, RCIF goto CheckIF ; loop if no flag movf RCREG, W movwf DataRcvd bsf PORTC, 0 ;set PORTC0 high again because we've started to receive data movf RxBytes, 1 ;move RxBytes into itself to check if it is zero (0x00) btfsc STATUS, Z call HeaderComp ;this sends back to top so that xor doesn’t happen if 0. Make sure to... ;btfss RxBytes, 1 ;if this is byte 1 (AA), save it! code won't get here on byte 0, so this is the only time RxBytes[1] will not be set movlw 0x01 xorwf RxBytes, 0 ;compare RxBytes to 0x01 btfsc STATUS, Z ;if they are equal, Z will be set, so save AA. Skip if clear (not equal) call UpdateAA movlw 0x07 xorwf RxBytes, 0 ;compare RxBytes to 0x08 and keep in in working reg btfsc STATUS, Z ;if RxBytes dne 0x07, Z will be clear. so skip FooterComp call FooterComp ;this sends back to MainLoop, unless we got a popped signal, so that xor doesn’t happen if 7 incf RxBytes, 1 movf DataRcvd, w xorwf CurrentSum, 1 ;this should put the xorwf result back in currentsum, which is what we want goto CheckIF UpdateAA: movf DataRcvd, w movwf AA return HeaderComp: movf DataRcvd, w xorwf Header, 0 ;Compare working register to Header (puts back in w to preserve header) btfss STATUS, Z ;if they are not equal, Z will be clear, so abort goto MainLoop ;this assume we can pull the line low while it is transmitting. I think we can, because it will have to hold for 1ms before the balloon monitor will want to send again, which is way longer than it takes to send. ;bsf RxBytes, 0 ;we received the first bit, so we don’t want to check again incf RxBytes, 1 ;we received a valid byte, so increase RxBytes and keep it in RxBytes goto CheckIF ;if the zero bit is set, then we had a match for our header. Go back and wait for the next byte FooterComp: movf DataRcvd, w xorwf Footer, 0 ;Compare working register to Footer btfss STATUS, Z goto MainLoop ;the footer didn't match, ABORT. ;clrw ;no input! so cool! let's do our checksum checking! ;xorlw CurrentSum ;xor, ior, add, sub, and should all do the same thing... CheckSum: movf CurrentSum, 1 ;this should affect status bit Z without changing anything else by moving CurrentSum to CurrentSum btfss STATUS, Z ;if z is set, our CurrentSum is 0! yay! goto MainLoop ;otherwise, bail CheckStatus: ;why bother checking if it is intact? we only want to change if popped, not if garbage or confirmed intact ;movf IntactAA, 0 ;check if our message says intact by moving intact into working reg ;xorwf AA, 0 ;(make sure this is value, not address!) put back into working reg ;btfss STATUS, Z ;if Z is set, then we are intact. if it is clear, check popped (otherwise don't do anything) ;goto MainLoop ;try again movf PoppedAA, 0 ; now check popped xorwf AA, 0 ; compare, put in working reg (maintain popped) btfss STATUS, Z ; if it does NOT equal popped, fail, go back to beginning bcf PORTA, 0 btfsc STATUS, Z bsf PORTA, 0 ;it matched the popped valid. uh-oh! we're popped! goto MainLoop ; not valid, i suppose END