;****************************************************************************** ; * ; Filename: lacrosse_12f675.asm * ; Date: 20.09.06 * ; File Version: 1.0.0 * ; * ; Author: JP ROUBELAT * ; * ;****************************************************************************** ; NOTES: * ; * ; * ;****************************************************************************** ; CHANGE LOG: * ; * ; * ;****************************************************************************** list p=12f675 ; list directive to define processor #include ; processor specific variable definitions __CONFIG(_BODEN_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_ON & _INTRC_OSC_NOCLKOUT) #define len d'10' ; serial input buffer length #define IN_434 GP0 ; GP0 = RX 434 #define IN_868 GP1 ; GP1 = RX 868 #define LED GP4 ; GP4 = LED (active low) #define TXD GP5 ; GP5 = TXD #define BANK0 bcf STATUS,RP0 ; Sel Bank 0 #define BANK1 bsf STATUS,RP0 ; Sel Bank 1 #define LED_ON bcf GPIO,LED ; LED on #define LED_OFF bsf GPIO,LED ; LED off ; Bits for the options (optreg) #define NOERR 0 ; validates timeout error check #define FREQ 1 ; frequency selection #define SIGNAL 2 ; data read on port ;****************************************************************************** ; VARIABLE DEFINITIONS * ;****************************************************************************** cblock 0x20 ;0x20-0x6f banks 0 w_temp ; variable used for context saving status_temp ; variable used for context saving counter_h ; timer high 8 bits counter_l ; timer low 8 bits binary ; Binary save tmpval ; Temporary value tmpbit ; Bit value optreg ; options txdata ; txdata bitcount ; bit counter buffer:len ; data buffer endc #define FREQ_434 bcf optreg,FREQ ; Select input 434 #define FREQ_868 bsf optreg,FREQ ; Select input 868 #define READ_ERR bcf optreg,NOERR ; Select input 434 #define READ_NOERR bsf optreg,NOERR ; Select input 868 READ_SIGNAL macro ; needs 7 cycles local read868, endRead bcf optreg,SIGNAL ; input = 0 btfsc optreg,FREQ goto read868 btfsc GPIO,IN_434 ; test signal bsf optreg,SIGNAL ; input = 1 goto endRead read868 nop btfsc GPIO,IN_868 ; test signal bsf optreg,SIGNAL ; input = 1 endRead endm ;****************************************************************************** ; RESET VECTOR * ;****************************************************************************** ORG 0x000 ; processor reset vector goto _startup ; go to beginning of program ;****************************************************************************** ; INTERRUPT VECTOR * ;****************************************************************************** ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register ; Place ISR (Interrupt Service Routine) if needed here... movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt ;****************************************************************************** ; MAINLINE CODE * ;****************************************************************************** _startup BANK0 clrf GPIO ; clear GPIO data latches movlw 0x07 movwf CMCON ; disable comparator BANK1 ; Select register bank 1 clrf ANSEL ; digital I/O clrf WPU ; no pull-ups movlw 0x0f ; Set GP<0:3> as inputs movwf TRISIO ; and set GP<4:5> as output call 3FFh movwf OSCCAL ; calibrate oscillator movlw 0x8f ; watchdog with prescaler movwf OPTION_REG ; and no pull-ups -> option register BANK0 ; Select register bank 0 bsf GPIO,TXD ; TXD=1 LED_OFF ;==================================================================================== ; Main loop ; _mainLoop movlw d'10' movwf tmpval _startSignal clrwdt ; watchdog movlw d'100' ; Wait 100ms call _tempo LED_ON movlw d'100' ; Wait 100ms call _tempo LED_OFF decfsz tmpval,f ; 10 blinks goto _startSignal call _sendCrLf ; clean the receive buffer _waitSignal1 clrwdt ; watchdog FREQ_434 call _getSignal bz _waitSignal2 ; error call _sendData ; send data _waitSignal2 clrwdt ; watchdog FREQ_868 call _getSignal bz _waitSignal1 ; error call _sendData ; send data goto _waitSignal1 ; endless main loop ;==================================================================================== ; _get_signal ; _getSignal READ_ERR ; not the last quartet READ_SIGNAL btfss optreg,SIGNAL ; test signal = 1 goto _getSignalErr ; signal is 0 call _getQuartet ; Wait for 0x0 bz _getSignalErr movfw tmpval bnz _getSignalErr call _getQuartet ; Wait for 0xa bz _getSignalErr movfw tmpval xorlw 0xa bnz _getSignalErr LED_ON movlw buffer ; beginning of memory movwf FSR ; write channel 0=434 1=868 clrf INDF btfsc optreg,FREQ incf INDF,f incf FSR,f _getSignalLoop call _getQuartet bz _getSignalErr movfw tmpval movwf INDF incf FSR,f movfw FSR xorlw buffer+len-1 ; Test for end memory-1 bnz _getSignalLoop _getSignalCRC READ_NOERR ; last quartet, no error call _getQuartet ; No error test for CRC bz _getSignalErr movfw tmpval movwf INDF LED_OFF clrz ; no error return _getSignalErr LED_OFF setz return ;==================================================================================== ; _get_quartet ; _getQuartet clrf tmpval call _getBit bz _getQuartetErr rlf tmpval,f call _getBit bz _getQuartetErr rlf tmpval,f call _getBit bz _getQuartetErr rlf tmpval,f call _getBit bz _getQuartetErr _getQuartetLastBit rlf tmpval,f clrz ; no error return _getQuartetErr btfsc optreg,NOERR ; No timeout ? goto _getQuartetLastBit setz ; error return ;==================================================================================== ; get_bit ; Signal must be logic 1 when entering the routine ; _getBit clrf tmpbit clrf counter_l ; mesure the length of signal 1 _getBit1 ; loop is 12 uS READ_SIGNAL btfss optreg,SIGNAL ; read signal goto _getBitMesure1 ; signal is now 0 incfsz counter_l,f ; max 2560 uS goto _getBit1 ; loop waiting 0 goto _getBitErr ; too long -> error _getBitMesure1 movfw counter_l sublw d'20' ; smaller than 240uS ? bc _getBitErr ; C=1 is smaller -> spurious movfw counter_l sublw d'75' ; greater than 900uS ? skpnc ; C=0 is greater -> bit=0 incf tmpbit,f ; smaller than 900uS -> bit = 1 clrf counter_h ; mesure the length of signal 0 _getBit0 ; loop = 12 uS READ_SIGNAL btfsc optreg,SIGNAL goto _getBitMesure0 ; signal is now 1 incfsz counter_h,f ; max 2560 uS goto _getBit0 ; loop waiting 0 goto _getBitErr ; too long -> error _getBitMesure0 movfw counter_h sublw d'75' ; smaller than 900uS ? bc _getBitErr ; C=1 is smaller -> spurious movfw tmpbit addlw 0xff clrz goto _getBitEnd _getBitErr movfw tmpbit addlw 0xff setz _getBitEnd return ;==================================================================================== ; memory dump ; _sendData movlw buffer ; beginning of memory movwf FSR _dumpLoop0 movfw INDF call _writeHex incf FSR,f movfw FSR xorlw buffer+len ; Test for end memory bnz _dumpLoop0 _sendCrLf movlw 0x0d call _serialTX ; send [CR] to terminal movlw 0x0a goto _serialTX ; send [LF] to terminal ;==================================================================================== ; Tempo 650uS ; _tempo500 movlw d'160' ; wait 650us movwf counter_l _boucle nop ; loop = 4us decfsz counter_l,f goto _boucle return ;==================================================================================== ; Tempo ; w contents the number of ms to wait ; _tempo movwf counter_h _boucle1 movlw 0xFA ; wait 1ms movwf counter_l _boucle2 nop ; loop = 4us decfsz counter_l,f goto _boucle2 decfsz counter_h,f goto _boucle1 return ;******************************************************************************* ; Write Hex to ASCII ; ; e.g. W = 0000 0110 sends '6' ; Enter with Byte to convert in W ; _writeHex movwf binary ; save W in binary movlw 0x0F ; load bit mask andwf binary,W ; mask out upper 4 bits in W addlw -.10 ; subtract 10 skpnc ; skip if <10 addlw 'A'-'0'-.10 ; add ascii A - (ascii 0) - 10 addlw '0'+.10 ; add ascii 0 + 10 (that we subtracted first) goto _serialTX ; send result ;==================================================================================== ; Send the character held in w at 9600 Bds ; _serialTX movwf txdata movlw .8 ; 8 bits data movwf bitcount ; bit counter call _sendZero ; send start bit _serialLoop rrf txdata,f ; next bit btfsc STATUS,C ; skip if next bit is zero goto _bitOne call _sendZero ; send Zero goto _next _bitOne call _sendOne ; send One nop _next decfsz bitcount,f goto _serialLoop call _sendOne ; send stop bit return ; and return _sendZero bcf GPIO,TXD ; TXD=0 goto _tempoBit _sendOne bsf GPIO,TXD ; TXD=1 goto _tempoBit ;==================================================================================== ; Tempo 1 bit ; _tempoBit movlw d'22' ; wait 104us - delays movwf counter_l _tempoBit1 nop ; loop = 4us decfsz counter_l,f goto _tempoBit1 return END ; 'end of program'