;---------------------------------------------------------------------- ; | ; NOM: HBRFlink.asm | ; Date: 18/12/2004 | ; Version: V1.8 | ; Circuit: liaison RF with XTR-434-50Kbps | ; Auteur: JPI | ; Copyright: JPI | ; | ; PIC 16F628-20 MHz RF Serial communication program | ; Handy Board Version | ; Use AUREL XTR-434-50L Transceiver | ; | ;---------------------------------------------------------------------- ; V1.8 18/12/2004 - Version pour carte RF HB (test) | ; | ; V1.7 14/12/2004 - Version homogène HB - PC | ; | ; V1.6-4 12/12/2004 - fonctionne PC -> HB avec instrumentation code | ; version filaire et carte experimentation | ; CD simulé par RB7 | ; | ; V1.6-2 28/11/2004 - reception rs232 et re-emission rs232 OK | ; | ; V1.5 27/11/2004 - No more period detection because not accurate | ; enough, suppose period is constant and 100 clk | ; | ; V1.4 14/11/2004 - Big modif of A tasks: addition of new task: | ; a wait task and complete re-organisation | ; V1.3 06/11/2004 - Some modifications | ; - C task Checked | ; - B task Checked | ; | ; V1.2 23/10/2004 - Some modifications | ; V1.1 30/12/2003 - Some modifications | ; V1.0 06/06/2003 - First version | ; | ;---------------------------------------------------------------------- ; RF Link PC <--| ~ ~ ~ ~|--> robot | ; PC board version: RS232 control possible via CTS - RTS (not impl.)| ; | ;---------------------------------------------------------------------- ; Required File : P16F628.inc | ;---------------------------------------------------------------------- ; | ; Notes: | ; - simulates Real Time job | ; - multitask : Reception RF & RS232 simultaneously | ; Emission RF et RS232 simultaneously | ; - use PIC 16F628 - 20 Mhz | ; | ; - RB0: _CD | ; - RB1: RX data from RS232 (Usart) | ; - RB2: TX data to RS232 (Usart) | ; | ; - RB3: _RX Enable | ; - RB4: RX data from XTR-434 | ; - RB5: TX data to XTR-434 | ; - RB6: _TX Enable | ; | ; - RA4: CTS Clear To Send (input from RS232) | ; - RB7: RTS Request to send (output to RS232) | ; | ; INDICATING LED | ; - RA0: RX_Enable LED | ; - RA1: RX data to XTR-434 LED | ; - RA2: TX_Enable LED | ; - RA3: TX data to XTR-434 LED | ; | ; RA0 .. RA3 are configurable output LED | ; | ; | ; ON/OFF LED -- O O -- Carrier Detect | ; TX_Data -- O O -- RX_Data | ; TX_Enable -- O O -- RX_Enable | ; | ; | ; WARNING: Board uses MALE SUBD - 9 pin | ; | ; Board for Handy Board is identical LED without CTS - RTS | ; | ; CTS - RTS Not implemented yet | ; Text Tabulation: 8 | ; | ;---------------------------------------------------------------------- ; ******************************************************************** ; A VERIFIER ; ******************************************************************** ; | ; - Transmission RS232 OK | ; - Reception RS232 OK | ; - Activation taches RS232 reception et emission OK | ; | ; - appel boucle attente 2 3 ms apres chanque chgt etat RF rmit ou reception ; - fonctionnement correct meme en cas de taches multiples | ; - verifier fct OK dans tous les cas d'interruptions | ; x tester avec liaison serie reception - emission uniquement | ; x reverifier les adresses d'initialisation | ; x modifier les adresses de remplissage des buffers | ; - verifier connection led pour allumage extinction | ; - verifier l'implantation des adresses des buffers : il y a 1 pb ! | ; | ; | ;---------------------------------------------------------------------- ; Error List | ; | ; 01 - A7 "0-1-1-1" received instead of "0-1-1-0" | ; 02 - A7 "0-1-1-0" never detected after end of time | ; 03 - A8 Byte check Data equal but parity different ! ! | ; 04 - A5 preamble error: less than 25 transitions in 6000 clk | ; 05 - A5 RF transmission period is over max possible | ; 06 - A7 0111 start stop bit detected instead of 0110 | ; 07 - A8 Data different but parity equal | ; 08 - A8 Data different and parity NOK | ; 09 - A8 Start-Stop bit not detected | ; 10 - A3 bit 0 received instead of 1 | ; 11 - A3 bit 1 received instead of 0 | ; 12 - A3 bit "1-0" not received after 256 clk | ; 13 - A3 bit 0 in "1-0" not received after 100 clk | ; 14 - A8 Error in start Stop bit | ; | ;---------------------------------------------------------------------- LIST p=16F628 ; processor definition ; LIST p=PIC16F628A #include ; constant def and register adr ; errorlevel -302 ; suppress warning message not in bank 0 __CONFIG _BODEN_OFF &_CP_OFF &_PWRTE_ON &_WDT_OFF &_LVP_OFF &_MCLRE_ON &_HS_OSC ; '__CONFIG' : encoded parameters into processor when programming EEPROM ; definitions are in include file ; Values and Definitions : (cf ch 14 p95 doc 16F628) ; _BODEN_ON Brown-Out Detect Enable bit ON ; _BODEN_OFF Brown-Out Detect Enable bit OFF ; _CP_ALL Code protection ON (2K) ; _CP_75 0200-07FF (2K) - 0200-03FF (1K) protege ; _CP_50 0400-07FF (2K) - 0400-03FF (1K) protege ; _CP_OFF Code protection OFF ; &H3EFF Data Code Protection ON ; _PWRTE_ON Timer reset sur power on en service ; _PWRTE_OFF Timer reset hors-service ; _WDT_ON Watch-dog en service ; _WDT_OFF Watch-dog hors service ; _LVP_ON Low Voltage Programming ON (RB4=PGM) ; _LVP_OFF Low Voltage Programming OFF (RB4=I/O) ; _MCLRE_ON RA5=MCLRE ; _MCLRE_OFF RA5=I/O ;External resistor (RA7): ER ; _ER_OSC_CLKOUT RA6 = CLKOUT ; _ER_OSC_NOCLKOUT RA6 = I/O ;Internal Resistor & Capacitor: INTRC ; _INTRC_OSC_CLKOUT RA6 = CLKOUT ; _INTRC_OSC_NOCLKOUT RA6 = I/O ;External Clock IN ; _EXTCLK_OSC RA6 = I/O, RA7 = CLKIN ;Oscillateur Quartz ; _LP_OSC Oscillateur quartz basse vitesse ; _XT_OSC Oscillateur quartz moyenne vitesse ; _HS_OSC Oscillateur quartz grande vitesse ;--------------------------------------------------------------------- ; ASSIGNATIONS : personal constants definition | ;--------------------------------------------------------------------- ;--------- Configuration ports ----------- ; Bits: 8,4,2,1 - 8,4,2,1 ; OPTIONVAL: 1 0 0 0 1 0 1 0 = &H8A ;----------------------------------------- ; b7: RBPU 1: RB Pull Up resistor OFF [Active Low] ; b6: INTEDG 0: Interrupt on falling edge front RB0/INT ; b5: TOCS 0: Timer Mode for TMR0 ; b4: TOSE 0: RB4 rising edge for TMR0 ; b3: PSA 1: Prescaler to WatchDog ; b2: PS2 0: PSA bit2 ; b1: PS1 1: PSA bit1 ; b0: PS0 0: PSA bit0 ; WatchDog MUST be on otherwise timer0 will not work ; without prescaler ! ;----------------------------------------- OPTIONVAL EQU H'008A' ;------ Configuration INTERRUPTIONS ------ ; Bits: 8,4,2,1 - 8,4,2,1 ; INTERMASK: 0 0 0 0 0 0 0 0 = &H00 ;----------------------------------------- ; b7: GIE 0: Global Interrupt OFF ; b6: PEIE 0: Peripheral Interrupt OFF ; b5: T0IE 0: Timer0 Interrupt OFF ; b4: INTE 0: RB0 Interrupt OFF ; b3: RBIE 0: RB4-7 change Int OFF ; b2: T0IF 0: Clear Flag ; b1: INTF 0: Clear Flag ; b0: RBIF 0: Clear Flag ;----------------------------------------- INTERMASK EQU H'0000' BIT_PERIOD EQU H'BC' ; = 176 = 256 - (100 - retard) clk/bit by default ;***** il faut retirer la durée de traitement de l'interruption *********** PORTAMASK EQU H'10' ; pin 7: output 0 QRZ ; pin 6: output 0 QRZ ; pin 5: output 0 MCLR ; pin 4: input 1 ; pin 3: output 0 ; pin 2: output 0 ; pin 1: output 0 ; pin 0: output 0 ; 0001-0000 = &H10 ; all PORTA pin output PORTBMASK EQU H'13' ; pin 7: output 0 ; pin 6: output 0 ; pin 5: output 0 ; pin 4: input 1 ; pin 3: output 0 ; pin 2: output 0 ; pin 1: input 1 ; pin 0: input 1 ; 0001-0011 = &H13 ;--------------------------------------------------------------------- ; DEFINE : directives | ;--------------------------------------------------------------------- #DEFINE CD_pin PORTB,0 ; CD pin #DEFINE RS_Rcv PORTB,1 ; RS232 RX pin (input) #DEFINE RS_Trs PORTB,2 ; RS232 TX pin (output) #DEFINE Rx_En PORTB,3 ; RF Receive Enable pin (active low) output #DEFINE RF_RX PORTB,4 ; RF RX data from XTR434 (input) #DEFINE RF_TX PORTB,5 ; RF TX data to XTR-434 (ouptut) #DEFINE Tx_En PORTB,6 ; RF Transmit Enable pin (active low) output #DEFINE RS_RTS PORTB,7 ; RTS RS232 output ; ********* remove after test ******************* #DEFINE SIMUCD PORTA,0 ; Simulate RF CD [HAUT 2 eme DROITE] ; *********************************************** ;#DEFINE RxenLED PORTA,0 ; RX_Enable LED #DEFINE RxdaLED PORTA,1 ; RX_data LED #DEFINE TxenLED PORTA,2 ; TX_Enable LED ;#DEFINE TxdaLED PORTA,3 ; TX_data LED #DEFINE LED PORTA,3 ; Error MSG LED #DEFINE RS_CTS PORTA,4 ; CTS RS232 input ; PORTA,5: MCLR input ; PORTA,6: QRZ Osc ; PORTA,7: QRZ Osc ;--------------------------------------------------------------------- ; MACRO | ;--------------------------------------------------------------------- BANK0 macro bcf STATUS,RP0 ; switch to Bank 0 bcf STATUS,RP1 endm BANK1 macro bsf STATUS,RP0 ; switch to Bank 1 bcf STATUS,RP1 endm BANK2 macro bcf STATUS,RP0 ; switch to Bank 2 bsf STATUS,RP1 endm BANK3 macro bsf STATUS,RP0 ; switch to Bank 3 bsf STATUS,RP1 endm LEDON macro bsf LED endm LEDOFF macro bcf LED endm ; ------- macro READEE for 16F628 ---------- ; IN : read adress ; OUT: W= read value ; Sortie: Bank0 ; ------------------------------------------ READEE macro adeeprom ; macro with parameter movlw adeeprom ; load eeprom adress BANK1 ; switch to Banque 1 movwf EEADR ; read adr into EEADR bsf EECON1 , RD ; launch eeprom read movf EEDATA , w ; load read value into W BANK0 ; switch to Bank 0 endm ; macro end ; ------- macro WRITEE for 16F628 --------- ; IN: W=data ; parameter=address ; EEADR in bank1 instead of 0 ; EEDATA in bank1 instead of 0 ; EEIF in PIR1 bank0 EEPROM Write flag ; EEIE in PIE1 bank1 EEPROM Interrupt Enable bit ; PEIE in INTCON any bank ; ------------------------------------------ WRITEE macro addwrite ; la donnée se trouve into W BANK1 ; car registres en Banque 1 movwf EEDATA ; placer data into registre movlw addwrite ; charger adresse d'écriture movwf EEADR ; placer into registre ;-------- procedure BIGONOFF ----------------- bcf INTCON , GIE ; interdire interrupts BANK1 ; passer en bank1 bcf EECON1 , EEIF ; clear flag fin d'écriture bsf EECON1 , WREN ; autoriser accès écriture movlw 0x55 ; charger 0x55 movwf EECON2 ; envoyer commande movlw 0xAA ; charger 0xAA movwf EECON2 ; envoyer commande bsf EECON1 , WR ; lancer cycle d'écriture bcf EECON1 , WREN ; verrouiller prochaine écriture bsf INTCON , GIE ; réautoriser interrupts BANK0 ; repasser en bank0 endm ;--------------------------------------------------------------------- ; VARIABLES DECLARATION | ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ; Zone 1: [0x020-0x06F] - 80 bytes ;--------------------------------------------------------------------- CBLOCK 0x020 ; start zone 1 of 96 bytes variables ; A Task variables --------------------------------------------------------- RFr_ptr :1 ; RF buffer ptr RFr_buffer :25 ; RF buffer for receive data 0x21-0x39 afb :1 ; task A flag bit : 0x40 ; 0 : waited bit in reception (0 ou 1) ; 1 : read bit value by TIMER0 ; 2 : read flag bit ; 3 : first parity bit ; 4 : second parity bit ; 5 : ; 6 : ; 7 : chk_error_flag :1 ; error Flag possible Manchester reception ; bit ; 0 : Manchester data not equal ; 1 : Parity 1 not equal ; 2 : Parity 2 not equal ; 3 : P1=P2 ? 0 if yes, 1 if not ; 4 : 0: use M1, 1:use M2 ; 5 : ; 6 : ; 7 : cmptb :1 ; task B counter STBnb :1 ; n° Under Task B to execute ; D Task variables --------------------------------------------------------- cmptd :1 ; task D counter STDnb :1 ; n° Under Task D to execute ; RSe_ptr :1 ; RS1 buffer ptr ; RSe_buffer :24 ; RS1 buffer for emit RS232 data : 0x47-0x5F tempd :1 ; tempdata for D task : 0x60 gva :1 ; global register for non bank 1 variables ; B task variables ---------------------------------------------------------- tempdata :1 ; byte to send parity :1 ; used by Task B to calculate parity msglength :1 ; message bytes length ; C task variables ---------------------------------------------------------- RSr_ptr :1 ; RS reveive buffer ptr RSr_buffer :25 ; RS reveive buffer for receive RS232 data : 0xC1-0xD8 STCnb :1 ; C under Task to execute Cbyte_cntr :1 ; byte counter for Task C cfb :1 ; C Task flag bits, initialise to 0000 0000 ; 0 : new byte read by interrupt ; 1 : 2nd byte read also ; 2 : all MSG bytes read ; 3 : ; 4 : ; 5 : ; 6 : ; 7 : tempc :1 ; tempdata for C task ; for test only ---------------------------------------------------------- cpt1 :1 cpt2 :1 cpt3 :1 ; ------------------------------------------------------------------------ ; reste 11 octets dispo: 0x65 à 0x6F ENDC ; End zone 1 ;--------------------------------------------------------------------- ; 4 Bank Common Zone: [0x070-0x07F] - 16 bytes ;--------------------------------------------------------------------- CBLOCK 0x070 ; start 4 bank COMMON ZONE w_temp :1 ; 1 byte status_temp :1 ; 1 byte ; - General variables ----------------------------------------------- task_fb :1 ; Task Flag Bit : indicates actives tasks ; Bits: 7 6 5 4 - 3 2 1 0 ; 0 0 0 0 - A B C D ; A : Reception RF bit3: On/Off bit7: Error Flag ; B : Emission RF bit2: On/Off bit6: Error Flag ; C : Reception RS232 bit1: On/Off bit5: Error Flag ; D : Emission RS232 bit0: On/Off bit4: Error Flag gfb :1 ; global flag bit ; 0 : XTR-434 used by A or B ; 1 : ; 2 : ; 3 : errnb :1 ; error ident nb (255 possible) ; 1 : RX=0 waited too long: 256 clk instead of 100 ; 2 : ; 3 : ; 4 : error into stop-start bit detection ; 05 : Manchester Start bit false : 0111 ; 06 : ; 10 : bit stop received is 0 instead of 1 ; 11 : bit start received is 1 instead of 0 ; 12 : wait more that 256 clk for 0 bit in "1-0" bit detection ; 13 : wait mode than 100 clk for 0 bit in "1-0" bit detection period :1 ; 1 bit period (in clk) halfperiod :1 ; real half period to go to midle bit ; Warning: check exact period duration ; TIMEER0 interrupt of 30 clk to take into account ! ; for correct timing ; think to change duration to be in midle of transmited bit instead of start ; no risk with TIMER0 interrupt duration !!! ; A Task variables --------------------------------------------------------- cmpta :1 ; task A counter atemp :1 ; temporary for Task A calltask :1 ; stores calling task ident for read bit task A4 STAnb :1 ; A undertask nb to execute STAnxtnb :1 ; next A Task to execute after read bit parity_temp :1 ; low nible : Manchester parity data 1 : max is 1000 - 1000 ; high nible : Manchester parity data 2 ; B flag bits bfb :1 ; B Task flag bits, initialise to 0000 0000 ; 0 : bit to write by TIMER0 ; 1 : write bit done ; 2 : Manchester 2nd bit also sent ; 3 : ; 4 : ; 5 : ; 6 : ; 7 : ; reste 0x7E-0x7F - 2 bytes ENDC ; Common zone END ;--------------------------------------------------------------------- ; Zone 2: [0x0A0-0x0EF] ;--------------------------------------------------------------------- ; Before reading variables, BANK 1 must be selected ! ; variable can be copied into gloreg of bank 1 CBLOCK 0x0A0 ; start zone 2 : 80 bytes variables ; B Task variables --------------------------------------------------------- ; RFe_ptr :1 ; RF emit buffer ptr ; RFe_buffer :24 ; RF emit buffer : 0xA1-0xB8 ; --------------------------------------------------------- C Task variables ERRbuffer :16 ; Error message buffer: 0xDA-0xE9 ERRbuf_ptr :1 ; error msg ptr 0xEA ; reste 0xEB - 0xEF: 5 bytes ENDC ; Zone 2 END ;--------------------------------------------------------------------- ; Zone 3: [0x120-0x14F] - 48 bytes ;--------------------------------------------------------------------- CBLOCK 0x120 ; START zone 3 48 bytes variables ENDC ; Zone 3 END ; ------------------------------------------------------------------- ; variables initialisation ; ------------------------------------------------------------------- RFr_adr EQU H'21' ; adresse debut buffer RFr_buffer RSr_adr EQU H'46' ; adresse debut buffer RSr_buffer BANK 1 Err_adr EQU H'A0' ; adresse debut buffer ERRbuffer ; ------------------------------------------------------------------- ; DECLARATION ZONE EEPROM ; ------------------------------------------------------------------- org 0x2100 ; start EEPROM adress ; DE 0x03 ; comment: not used ;--------------------------------------------------------------------- ; RESET START | ;--------------------------------------------------------------------- org 0x000 ; Start Adress after reset goto init ; Adress 0: initialise ;---------------------------------------------------------------------- ; INTERRUPTS ROUTINES | ;---------------------------------------------------------------------- ;save registers ;-------------- org 0x004 ; adresse d'interrupt movwf w_temp ; sauver registre W swapf STATUS,w ; swap status avec resultat into w movwf status_temp ; sauver status swappe zone commune ; interrupt switch ; ---------------- ; Timer0 : RF Emit & receive btfsc INTCON,T0IE ; tester si interrupt timer autorisee btfss INTCON,T0IF ; oui,tester si interrupt timer en cours goto intsw1 ; non test suivant call inttimer ; oui, traiter interrupt timer bcf INTCON,T0IF ; clear flag interrupt timer goto restorereg ; et fin d'interrupt intsw1 ; RB0 : RF Carrier Detect btfsc INTCON,INTE ; tester si interrupt RB0 autorisee btfss INTCON,INTF ; oui,tester si interrupt RB0 en cours goto intsw2 ; non sauter au test suivant call intrb0 ; oui, traiter interrupt RB0 bcf INTCON,INTF ; clear flag interupt RB0 goto restorereg ; et fin d'interrupt intsw2 ; TX Register empty BANK1 ; passer en bank 1 btfss PIE1,TXIE ; tester si interrupt TX autorisee goto intsw21 ; non : suite BANK0 ; passer en bank 0 btfss PIR1,TXIF ; oui,tester si interrupt TX en cours goto intsw3 ; non sauter test suivant call inttx ; oui, traiter interrupt TX ; flag TXIF non effacable (automatique) goto restorereg ; et fin d'interrupt intsw21 BANK0 ; passer en bank 0 ; et continuer tests intsw3 ; RC RS232 Reception Register full BANK1 ; passer en bank 1 btfss PIE1,RCIE ; tester si interrupt RC autorisee goto intsw31 ; non : suite BANK0 ; passer en bank 0 btfss PIR1,RCIF ; oui,tester si interrupt RC en cours goto intsw4 ; non sauter call intrx ; oui, traiter interrupt RC ; flag RCIF non effacable (automatique) intsw31 ; fin des interruptions BANK0 ; passer en bank 0 goto restorereg ; et fin d'interrupt intsw4 ; ------------- SPECIAL 16F628 (bits et Registres modifiés)---------- ; bit PEIE in reg INTCON, bank 0-3 : External interrupt Enable bit ; bit EEIE in reg PIE1, bank 1 : Write EEPROM interrupt Enable bit ; bit EEIF in reg PIR1, bank 0 : Write EEPROM flag bit ; sort en BANK0 btfss INTCON,PEIE ; tester si External interrupt autorisée goto restorereg ; non sauter fin BANK1 ; passer en bank 1 btfss PIE1,EEIE ; tester si Write EEPROM interrupt autorisée goto restorereg ; non sauter BANK0 ; passer en bank 0 btfss PIR1,EEIF ; oui,tester si Write EEPROM goto restorereg ; non sauter call inteep ; traiter interrupt eeprom ;restore registers ;------------------- restorereg BANK0 ; passer en bank 0 swapf status_temp,w ; swap ancien status, resultat into w movwf STATUS ; restaurer status -> banks swapf w_temp,f ; Inversion L et H de l'ancien w ; sans modifier Z swapf w_temp,w ; Reinversion de L et H into w ; w restaure sans modifier status retfie ; return from interrupt ;--------------------------------------------------------------------- ; INTERRUPTION TIMER 0 | ;--------------------------------------------------------------------- ; Used for automatic repetitive actions (read RX or write TX pins) ; period contains frequence for reading or writing ; bit 1 of afb is red bit value ; bit 2 of afb is flag bit red ; if RX flag = 1 -> read RX port ; if TX flag = 1 -> write TX port ; if tmr0use = 1 -> indiquer erreur reception ; emetre message RS232 erreur reception cause 1 ; attendre fin CD=0 pour reactiver INT inttimer ; tester si RX flag=1 -> lire RX ; tester si TX flag=1 -> ecrire TX movf period,w ; restore read period movwf TMR0 ; to counter btfsc task_fb,3 ; RF receive activated ? goto inttimer0read ; yes btfsc task_fb,2 ; RF emit activated ? goto inttimer0write ; yes return ; else unknown inttimer0read ; read routine bcf afb,1 ; read bit =0 (supposed) nop ; for timing btfsc RF_RX ; read RF_RX pin [clk +12] bsf afb,1 ; in fact value is 1 bsf afb,2 ; set read flag bit value return ; fin d'interrupt timer inttimer0write ; write bit routine ; copy value of bfb into gloreg movf bfb,w ; read value movwf gva ; write to user variables btfss gva,0 ; bit =0 ? bcf RF_TX ; write 0 nop ; for timing purpose (by test) btfsc gva,0 ; bit =1 ? bsf RF_TX ; write 1 bsf gva,1 ; set write done flag bit movf gva,w ; read value movwf bfb ; write to variable in bank 1 movlw BIT_PERIOD ; restore read period movwf TMR0 ; to counter return ; fin d'interrupt timer ;--------------------------------------------------------------------- ; INTERRUPTION RB0/INT | ;--------------------------------------------------------------------- ; Detection de porteuse RF ; déclancher task A1: detection porteuse RF Manchester ; si task B non active (utilise XTR-434) ; + désactiver interrupt RB0/INT ; RF carrier detection ; Triggers A1 Task: RF Manchester Carrier detection ; if B Task not active (use XTR-434) ; must disactive interrupt RB0/INT ; will be reactivated at end of RF receive intrb0 btfsc task_fb,2 ; task B active ? goto intrb01 ; yes : abandon bsf task_fb,3 ; No : Activate Task A: RF Receive ; movlw 01 ; n° under task ; movwf STAnb ; stored into registre ; desactiver interrupt RB0/INT intrb01 bcf INTCON,INTE ; Disable RB0 interrupt while RF on return ; end RB0/INT interrupt ; ******************************************* ; remove after Test ; attente 1 sec TEMPO movlw 20 movwf cpt3 bcl3 clrf cpt2 bcl2 clrf cpt1 bcl1 nop decfsz cpt1,f goto bcl1 decfsz cpt2,f goto bcl2 decfsz cpt3,f goto bcl3 return TEMPO2 movlw 10 movwf cpt3 bcl32 clrf cpt2 bcl22 clrf cpt1 bcl12 nop decfsz cpt1,f goto bcl12 decfsz cpt2,f goto bcl22 decfsz cpt3,f goto bcl32 return ; ******************************************* ;--------------------------------------------------------------------- ; INTERRUPTION TX byte empty | ;--------------------------------------------------------------------- ; interrupt TXIF: ; once every 10 bits at 9600 bds ; <-> once every 5200 clk ! ; read RS1buf_ptr pointed data ; write this value into TXREG ; increment RFrbuf_ptr ; return inttx movf RFr_ptr,w ; read buffer pointer movwf FSR ; to pointer movf INDF,w ; read data movwf TXREG ; put data into transmit buffer incf RFr_ptr,f ; point to next data decfsz cmptd,f ; check data left ? return ; yes TXint1 BANK1 bcf PIE1,TXIE ; Disable TXREG interrupt (transmission end) BANK0 return ; TX interrupt ;--------------------------------------------------------------------- ; INTERRUPTION RX byte full | ;--------------------------------------------------------------------- ; --------------- ; INTERRUPT on Byte received buffer full ; up to 26 clk ; --------------- ; set to 1 the global C Task activation bit ; don't care if already done ; useful if task not active (awakening of Reception task) ; transfer reception register into reception buffer ; at adress pointed by RSr_ptr that must be correct: next free adress ; il faut lire d'abord le statut du bit OERR et indiquer une erreur et re activer ; sinon risque de rester bloqué ; CREN pour re-activer intrx ; activate C task if first byte bsf task_fb,1 ; activate C task (task n°2 or 3 waiting) ; read adress pointer movf RSr_ptr,w ; RS232 receive buffer adr BANK 0 movwf FSR ; to pointer int1 ; Read received RCREG byte movf RCREG,w ; read byte movwf INDF ; store read byte bsf cfb,0 ; 1 byte received by int incf RSr_ptr,f ; next free adr decf Cbyte_cntr,f ; 1 more byte done btfsc STATUS,Z ; all done ? bsf cfb,2 ; yes: set all done flag bit btfss PIR1,RCIF ; RCREG stack empty ? goto int11 ; yes: lecture terminée bsf cfb,1 ; 2nd byte also received incf FSR,f ; new adress also goto int1 ; continue return ; End of TX interrupt int11 ; check OverRun Error (nearly impossible at 20 Mhz but ...) btfss RCSTA,OERR ; Overrun Error occured ? goto int12 ; no: end bcf RCSTA,CREN ; yes: disable RS232 bsf RCSTA,CREN ; then re-enable RS232 int12 return ;--------------------------------------------------------------------- ; INTERRUPTION RB0/RB4 - not used | ;--------------------------------------------------------------------- intrb4 return ; End of RB0/RB4 interrupt ;--------------------------------------------------------------------- ; INTERRUPTION EEprom - not used | ;--------------------------------------------------------------------- inteep return ; End of EEprom interrupt ;--------------------------------------------------------------------- ; INITIALISATIONS | ;--------------------------------------------------------------------- init ; ----- Hardware Initialisation --------------- ;------ Inhiber les comparateurs -------------- movlw 0x07 ; w = 0000 0111 movwf CMCON ; CMCON=w : comparateurs sont inhibés ;------ Appliquer les options ----------------- BANK1 ; bank 1 select movlw OPTIONVAL ; load mask movwf OPTION_REG ; initialise option register BANK0 ; select bank 0 clrwdt ; clear watchdog clrf TMR0 ; ----- I/O port initialisation --------------- BANK1 movlw PORTAMASK movwf TRISA movlw PORTBMASK movwf TRISB BANK0 ; ----- Initialise outputs --------------- clrf PORTA ; portA output set to 0 ; RA0-RA3 LED output ; RA4 RTS input (not used) ;******* vérifier apres conception carte ************ movlw 0 ; Port B output Mask: movwf PORTB ; set PORT B = 0 and XTR-434 module OFF bsf Tx_En ; disable TX bsf Rx_En ; disable RX bsf TxenLED ; TX_en LED OFF ; bsf RxenLED ; RX_en LED OFF ; ----- RS232 Asynchronous serial link Initialisation ---------- ; configure RB1 and RB2 as asynchronous serial link BANK1 bcf TXSTA,SYNC ; set asynchronous mode BANK0 bsf RCSTA,SPEN ; serial port Enabled ; initialise baud rate generator BANK1 bsf TXSTA,BRGH ; set baud rate High movlw 129 ; to movwf SPBRG ; 9600 bds BANK0 ; ------------------------------- ; clear RAM Bank 0: 0x20 à 0x7F ; ------------------------------- clrf STATUS ; IRP=0, RP10=00, C=0 movlw 0x20 ; initialisation pointer RAM 16F628 movwf FSR ; indirect pointer adress init_ram0 clrf INDF ; clear RAM incf FSR,f ; point to next btfss FSR,7 ; check if end zone reached (=0x80) goto init_ram0 ; no, do it again ; ------------------------------- ; clear RAM Bank 1: 0xA0 à 0xFF ; (with re-clear of 0x70-0x7F) ; ------------------------------- movlw 0xA0 ; init pointer RAM 16F628 movwf FSR ; pointeur d'adressage indirect init_ram1 clrf INDF ; clear RAM 16F628 incf FSR,f ; next btfss STATUS,Z ; End of current bank ? (FSR=0x00, C=1) goto init_ram1 ; continue if not 0 ; -------------------------------- ; clear RAM Bank 2: 0x120 à 0x14F (48 bytes) ; (with re-clear of 0x70-0x7F) ; -------------------------------- bsf STATUS,IRP ; switch to bank 2-3 for INDF movlw 0x20 ; init pointer RAM 16F628 movwf FSR ; indirect adress pointer init_ram2 clrf INDF ; clear RAM 16F628 incf FSR,f ; next btfss FSR,7 ; check if end zone (=0x80) goto init_ram2 ; continue if not 0 bcf STATUS,IRP ; back to bank 0-1 for INDF ; ---------- Buffers ptr Initialisation --------------- movlw RFr_adr ; RF_reception buffer adress movwf RFr_ptr movlw RSr_adr ; RS_reception buffer adress movwf RSr_ptr movlw Err_adr ; Error buffer adress BANK1 movwf ERRbuf_ptr BANK0 ;--------------------------------------------------------------------- ; MAIN PROGRAM | ;--------------------------------------------------------------------- ; The principle of the program ; This program implement a sort of "real time" RF link. It means that it can emit or receive data ; from the RS232 and simultaneously emit or receive data by the RF device. ; This can be done by a sort of real time scheduler. The idea is to process information before the ; hardware needs it. ; ; The program is divided into 4 High Level Tasks: ; - A: RF Receive Data ; - B: RF Emit Data ; - C: RS232 Receive Data ; - D: RS232 Emit Data ; ; Each High Level Task is divided into several Low Level Under Tasks. ; Each low level tasks requires only a few CPU time and when finished will activate the next under task ; if it does not requires an other execution. ; A byte flag (task_fb) indicates which high level tasks are active. This byte is periodically checked. ; One byte by high level task indicates which under task (low level) is active and must be executed. ; The low level task of each High level Task are sequentially executed. ; They set the number of the low level task to be executed next time when the high level task ; receive CPU time for execution. ; ; the High and low level tasks are: ; - Reception RF --> Manchester decoding --> RS232 Transmission ; - Reception RS232 --> Manchester encoding --> RF Emission ; ; Each high level task has ONE low level task (STI) that can be activated by interrupt ; This low level task triggers the high level task global activity ; This special low level task must long very short (not to empeach other STI) ; Others low level tasks (ST) are subordonated to the STI task ; The execution date of this STI low level task can be very important (RF E/R) ; The RF link speed is 50 Kbps: 100 clk each bit at 20 Mhz. ; The RS232 link is at 9600 bps (bauds) by 16F628 USART so just one interrupt is needed ; by each transmited byte so about 5730 clk by each transmited byte ! ; The RF link is CRITICAL for timing whereas RS232 one is tolerant ; The simultaneous active tasks: ; ONE RF task and the 2 RS232 Tasks: Emission and Reception ; Both RF tasks are mutually exclusives because the XTR-434 is half duplex ! ; The encoding / decoding belongs to the associated reception task ; Each RF task must long 1/5 th of RS232 task as transmission speed is about 5 time faster ; (50 000 for 9600) ; ; While RF receive task, the preamble ident task may use ALL the CPU so that multitasking will be ; impossible. ; But if the RF Preamble identification task is triggered, it means that the RF Emit task is over. ; The only possible other tasks are RS232 Emit or Receive. Knowing that USART interrupt period is ; about 5700 clk, we suppose that the USART interrupt will not occur during the Preamble Identification ; Task or that if it happens, it wil not last long enough to cause an RS232 error. ; Timer0 Read interrupt : 30 clk ; read done at int + 15 clk ; - VERIFIER DUREE TACHE IDENTIFICATION PREAMBULE RF ; - vérifier si peut décaler transmission RS232 ? ; - Oui si octet reçu plein et buffer pas vidé ? ; - On a une marge de 2 octets ? ; s'assurer que l'on ne reste pas bloqué dans cette tache d'identification (cas d'emissions parasites) ; The program is divided into 4 High Level Tasks: ; - A: RF Receive Data ; - B: RF Emit Data ; - C: RS232 Receive Data ; - D: RS232 Emit Data ; ; A task (RF receive) is triggerer by RB0 interrupt (carrier detect) ; RB0 interrupt is then disabled until message emited on RS232 ; this allows no RF reception while previous message received not sent ; RB0 interrupt is also disabled when entering RF emit Task because unuseful ; and because XTR434 ise used for emission ; ******************************************* ; allumer pour tester OK ; remove after Test ; allume led + attente 1 sec LEDON call TEMPO2 LEDOFF ; ******************************************* ; Program Start ; ------------- ; Initialise RF Receive mode by A1 Task in order to detect Carrier via RB0 interrupt ; RS232 receive task enabled in order to be ready for first RS232 reception ; RS232 RXREG full interrupt Enabled clrf task_fb ; clear all active bit tasks ; Activate C task bsf task_fb,1 ; activate C Task: RS232 receive initialisation task movlw 01 ; Select C1 Task : RS232 reception active by default movwf STCnb ; launch C1 under task ; Activate A task bsf task_fb,3 ; Activate A Task: RF receive initialisation task movlw 01 ; Select A1 Task : RF reception active by default movwf STAnb ; launch A1 under task ; ************* TEST PURPOSE ********************** ;; bcf task_fb,1 ; Disable RS232 Receive Task ; movlw 01 ; Select C1 Task : ; movwf STCnb ; launch C under task ; ************************************************** ; ******************************************************************************************** ; REMOVE AFTER TEST bsf SIMUCD ; simulate NO RF emission for Carrier detect ; ******************************************************************************************** ; Set XTR434 in RF reception active bsf Tx_En ; DISABLE RF EMIT bsf Rx_En ; DISABLE RF RECEIVE ; bsf RxenLED ; RX En Led OFF bsf TxenLED ; TX En Led OFF ;---------- Activates INTERRUPTION ---------- movlw INTERMASK ; masque interrupt (all interrupt off) movwf INTCON ; load interrupt control bsf INTCON,PEIE ; Enable Peripheral interrupts (TX, RX, EEprom, ...) ; activate preamble detection 434Mhz bsf INTCON,GIE ; Enable Global Interrupt ;--------------------------------------------------------------------- ; Principal Prog: loop to activate sequentially the low level tasks ;--------------------------------------------------------------------- ; don't use of "call" in order not to use the stack ; we must be able to give CPU to any Task start btfsc task_fb,3 ; task A: Reception RF active ? goto RFreceive RFrcv_ret btfsc task_fb,2 ; task B: Emission RF active ? goto RFemit RFemit_ret btfsc task_fb,1 ; task C: Reception RS232 active ? goto RSreceive RSrcv_ret btfsc task_fb,0 ; task D: Emission RS232 active ? goto RSemit RSemit_ret clrwdt ; clear WatchDog goto start ; loop ; ==================================================== ; task A : RF Reception ; ==================================================== org 0x0FB ; Jump Adress after 0x00FF RFreceive ; execute appropriate under Task movlw 01 ; actual code is in first memory 256 bytes movwf PCLATH ; set PCLATH for PCL operation movf STAnb,w ; read under A Task nb addwf PCL,f ; jump to under Task goto RFrcv_ret ; return if no task ; ----------------------------------------------------- goto A1 ; Preamble detection RF 50Kbps ; + calculate bit period goto A2 ; Check "0-1" start transition for 1 ms goto A3 ; "M-start bit" detection : "1-0" goto A4 ; - special task- Read bit goto A5 ; Read & decode first Manchester Data : message Length goto A6 ; unuseful period detection goto A7 ; - special task- stop-start bit detection goto A8 ; CD detection end goto A9 ; RF termination delay goto A10 ; goto A11 ; goto A12 ; Abnormal termination ; ==================================================================== ; task B : RF Emission ; ==================================================================== RFemit ; execute appropriate under Task movlw 01 ; code is in SECOND 256 bytes memory movwf PCLATH ; set PCLATH for PCL operation movf STBnb,w ; read under B Task nb addwf PCL,f ; jump to under Task goto RFemit_ret ; return if no task ; ----------------------------------------------------- goto B1 ; Special Task Send Manchester bits goto B2 ; preamble Emission "0-1" for 3 ms goto B3 ; data Emission goto B4 ; ==================================================================== ; task C : RS232 Reception ; ==================================================================== RSreceive ; execute appropriate under Task movlw 01 ; actual code is AFTER first 256 bytes ! movwf PCLATH ; set PCLATH for PCL operation movf STCnb,w ; read under C Task nb addwf PCL,f ; jump to under Task goto RSrcv_ret ; return if no task ; ----------------------------------------------------- goto C1 ; Authorise RS232 reception goto C2 ; Read first byte : msg length goto C3 ; read bytes while MSG not full goto C4 ; tranfert data from RS232 buffer to RF emit buffer goto C5 ; tranfert data from RS232 buffer to RF emit buffer goto C6 ; activates B task: RF Emission goto C7 ; ***** test purpose only ********* ; ==================================================================== ; task D : RS232 Emission ; ==================================================================== RSemit ; execute appropriate under Task movlw 01 ; actual code is in second 256 bytes memory movwf PCLATH ; set PCLATH for PCL operation movf STDnb,w ; read under A Task nb addwf PCL,f ; jump to under Task goto RSemit_ret ; return if no task ; ----------------------------------------------------- goto D1 ; prepare and Enable transmission goto D2 ; wait for end of transmission (cmptd=0) goto D3 ; ***** test purpose only ********* goto D4 ; ***** test purpose only ********* goto D5 ; ***** test purpose only ********* ;--------------------------------------------------------------------- ; task A : RF Reception : 12 low level tasks ;--------------------------------------------------------------------- ; A1 is global A Task initialisation ; A2 to A4 are secondary low level tasks called by others ; A5 to A11 are principal A low level Tasks ; A12 is special error receive task ; ; A1 must be called once to initialise RF reception mode ; A5 is then triggered by RF preamble detection: INT/RB0 ; ; STAnb = nb low level task to execute ; wbit : wait until bit received by Timer0 ; readbit*: wait for waited bit to be read ; ssb_chk*: ; Await* : wait for a specific time to be passed ; Low level tasks: ; A1 - Global A Task initialisation : wait for XTR not to be used in order ; to set it to reception mode ; A2 - Readbit* task - use Timer0 ; - wbit used by task 4 - use timer0 to read bit ; A3 - ssb_chk*: Stop-Start bit check - use timer0 to read bit ; A4 - Await*: used for waiting time - use timer0 to read bit ; A5 - Wait for 25 "0-1" transition ; - wbit ; - ssb_chk* ; A6 - Preamble and frequence detection ; - 2 wbit ; A7 - M start bit detection ; - 3 Readbit* ; - 1 wbit ; A8 - Read Manchester Data bit ; - ssb_chk* ; - 3 readbit* ; - 1 manchestercheck ; - 1 Await* ;- manchestercheck - check if valid manchester data ; A9 - wait for data transfered to RS buffer ; A10 - Prepare RF termination Delay ; A11 - Wait for RF termination Delay ; A12 - Abnormal termination ; WARNING: ; The RF pin reading must be done at a specific time ; in order not to bother with that, the TIMER0 interrupt will read the RF pin ; But in order not to use the CPU to wait, a specific "check read bit task" is created. ; This task can be CALLED from various A task (but only ONCE at a time) and return execution ; to the TASK MANAGER so that the CALL "return" adress is still stored to the stack. ; Then when process time will be given back to the A task and so on, to the "check bit task" ; it will detect that the RF pin HAS BEEN red (if it has) and WILL RETURN to the appropriate ; calling line from the appropriate Low Level Under Task. ; This allows not to have to have to store the calling line in order to return at the appropriate ; line of the under-task. ; This can ONLY be done ONCE at a time in a prog otherwise there will be a "return line" confusion ; This is not a problem as is should ONLY be used ONCE in each RF tasks that are MUTUALLY exclusives. ; May be this could be done by manually reading, storing and modifying the PCL value. ; In that case interrupts should be disabled when doing this not to mess it all. ; ==================================================== ; Low level task A1: Wait for RF receive activation ; ==================================================== ; duration ; 3 clk if wait ; 25 if wait again ; 26 if finished ; wait until XTR-434 not used by RF Emit in order to reset it to Reception mode A1 btfsc task_fb, 2 ; RF Emit task active ? goto RFrcv_ret ; Yes, wait again ; No, activate RF receive task bcf Rx_En ; ENABLE RF RECEIVE ; bcf RxenLED ; RX En Led ON ; TIMER1 wait 1 ms routine <-> 200 clk call Await ; call wait routine movlw 05 ; next A task preamble detection movwf STAnb bcf task_fb, 3 ; Clear RF receive task ; will be activated by CD Int bsf INTCON,INTE ; Enable RB0 interrupt while RF on goto RFrcv_ret ; RF task CPU over ; ------------------------------------------------- ; Wait Bit Routine ; Warning : can wait forever - MUST CHANGE THIS NOT TO BE BLOCKED - Interrupt ? ; IN: bit0 of afb is waited bit value ; ------------------------------------------------- ; min: 10 clk ; +7 clk after detected bit wbit ; wait for bit0 of afb and count time btfss afb,0 ; wait for bit=0 ? goto wbit0 ; yes wbit1 ; wait for bit=1 btfss RF_RX ; bit=1 ? goto wbit1 ; no wait again bcf afb,0 ; next time wait for bit=0 goto wbit2 ; next treatment wbit0 ; wait for bit=0 btfsc RF_RX ; bit=0 ? goto wbit0 ; no wait again bsf afb,0 ; next time wait for bit=1 goto wbit2 ; useful for same timing only wbit2 return ; +7 clk after detected bit ; ------------------------------------------------- ; ==================================================== ; SPECIAL Under Task A2 : Check Read Bit by TIMER0 INT ; ==================================================== readbit ; suppose TIMER0 interrupt set to read bit ; initialisation part: executed once ; ident and store which calling task ; store this task id to Task Manager ; initialisation movf STAnb,w ; read calling A Task movwf calltask ; and store to var to restore afterwards movlw 02 ; set actual Task movwf STAnb ; in Task Manager A2 ; execute each CPU given btfss afb,2 ; check if bit read ? goto RFrcv_ret ; no: give CPU to next task ; return to global TaskManager but use GOTO instead of RETURN ; in order to keep the calling adress into the stack ; while bit is not read ; ---------- WORKS ONLY IF USED ONCE AT A TIME ---------------- bcf afb,2 ; reset flag for next time ; restore intial Task movf calltask,w ; read stored task nb movwf STAnb ; read calling A Task return ; to initial calling line from any undertask from A task ; ==================================================== ; ==================================================== ; SPECIAL Under Task A3 : wait & check start stop bit detection "1-0" ; ==================================================== ; - read bit and check if 1 otherwise error ; - wait until RF_RX = 0 ; then check period value ; disable and re-enable timer0 int ; If error detected : Global A Task error flag bit set (task_fb,7) ; and error number in errnb ; if OK : timer0 enabled and bit synchronised ; if NOK: - timer0 disabled ; - global A task error flag bit set (task_fb,7) ; - error number in errnb ssb_chk ; suppose TIMER0 interrupt set to read bit ; suppose period variable contains exact period &FF-100 clk ; initialisation part: executed once ; ident and store which calling task ; store this task id to Task Manager movf STAnb,w ; read calling A Task movwf calltask ; and store to var to restore afterwards movlw 03 ; set actual Task movwf STAnb ; in Task Manager A3 ; execute each CPU given btfss afb,2 ; check if bit read ? goto RFrcv_ret ; no: give CPU to next task ; -------------------------------------------------- bcf afb,2 ; reset flag for next time btfss afb,1 ; bit should be 1 if not error goto A38 ; error routine clrf TMR0 ; clear Timer0 to count clk bcf INTCON,T0IE ; disable Timer0 interrupt bcf INTCON,T0IF ; clear interrupt flag A31 btfsc RF_RX ; now wait for bit 0 goto A31 ; wait again ; bit 0 received ; timer0 should be < 100 clk ; timer0 int bit should be cleared btfsc INTCON,T0IF ; check if timer did overflow ? goto A36 ; yes movf TMR0,w ; read timer0 value sublw 105 ; check if < 100 ? btfss STATUS,C ; yes ? goto A35 ; no ; now all is good, restart TIMER0 with appropriate value ; movlw 150 ; read period 255 - 100 movlw 160 ; read period 255 - 100 movwf TMR0 movlw 15 ; 15 clk ; 10 clk since bit changed ; +15 clk for waiting ; +15 clk for interrupt read delay ; =40 clk for a 100 clk period subwf TMR0,f ; wait half period more to go into midle bit bsf INTCON,T0IE ; enable TIMER0 interrupt return ; to initial calling line from any undertask ; error detected : bit 0 instead of 1 A38 movlw 10 ; error id number goto A37 ; error detected : bit 1 instead of 0 A39 movlw 11 ; error id number goto A37 ; error detected wait too long for bit 0 in "1-0" tranition : more that 256 clk A36 movlw 12 ; error id number goto A37 ; error detected : waited more than 100 clk for bit 0 in "1-0" bit transition A35 movlw 13 ; error id number goto A37 A37 movwf errnb bsf task_fb,7 ; set global A Task error flag return ; return to calling routine ; ==================================================== ; SPECIAL A4 Under Task : wait for delay ; TIMER1 wait 1 ms routine <-> 5000 clk ; TIMER1 set to timer mode: count cycle instr ; ==================================================== Await ; initialisation part: executed once ; ident and store which calling task ; store this task id to Task Manager movf STAnb,w ; read calling A Task movwf calltask ; and store to var to restore afterwards movlw 04 ; set actual Task movwf STAnb ; in Task Manager ; ------------------------------------------------- BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf PIR1, TMR1IF ; Clear Timer1 Flag bcf T1CON, TMR1CS ; select TIMER mode ; wait for 5000 clk movlw 236 movwf TMR1H ; H = movlw 120 movwf TMR1L ; L = bsf T1CON, TMR1ON ; start TIMER A4 btfss PIR1,TMR1IF ; Overflow flag set ? goto RFrcv_ret ; no: wait again ; ------------------------------------------------- bcf T1CON, TMR1ON ; stop TIMER1 bcf PIR1, TMR1IF ; Clear Timer1 Flag ; restore intial Task movf calltask,w ; read stored task nb movwf STAnb ; read calling A Task return ; to initial calling line from any undertask from A task ; --------------------------------------------------------- ;---------------- ; under Task A5 : Preamble check ;---------------- ; duration : ??? clk ; Triggered by interrupt RB0/Int (RF Carrier Detect) ; Interrupt RB0/Int (RF Carrier Detect) now disabled ; End: launch A6 A5 ; first wait time for 25 transitions "0-1" at 50kbps ; 50 bits <-> 5000 clk <-> 1 ms ; ----------------------------------------- call Await ; wait for 5000 clk ; ----------------------------------------- ; attendre 25 transitions "0-1" ; pendant une durée raisonnable ; Si pas recues (moins de 25 ou signal terminé) ; alors soit emission incorrecte soit autre signal ; si attente trop longue alors eliminer fausse alarme ; relancer tache A1 de re-initialisation dès que XTR-434 dispo movlw 50 ; 50 bits (25 "0-1") movwf cmpta ; set cmpta ; ---------------------------------------- ; init Timer 1 for 6000 clk ; (1000 clk more than expected) ; ---------------------------------------- movlw 232 movwf TMR1H ; H = 232 movlw 144 movwf TMR1L ; L = 144 bsf T1CON, TMR1ON ; start TIMER1 ; ---------------------------------------- ; init Timer 0 at supposed frequence of 50K bps ; ---------------------------------------- movlw 157 ; &xFF-period(100)+late(2) movwf TMR0 ; will effect in 2 clk movlw 0xAB ; &xFF-period(100) (value obtained by test !) movwf period ; used by Timer0 int bcf INTCON, T0IF ; Clear Timer0 Flag bsf INTCON, T0IE ; Enable TIMER0 Interrupt ; -------- wait for bit -------------- A56; call readbit ; wait until one bit read btfss afb,2 ; check if bit read ? goto A56 ; no: wait again bcf afb,2 ; reset flag for next time decf cmpta,f ; one done ; ---------------------------------------- bsf afb,0 ; suppose next bit is 1 btfsc afb,1 ; red bit = 1 bcf afb,0 ; yes : next bit should be 0 ; -------- wait for other bit -------------- A51; call readbit ; wait until one bit read btfss afb,2 ; check if bit read ? goto A51 ; no: wait again bcf afb,2 ; reset flag for next time ; ---------------------------------------- ; compare received bits btfsc afb,0 ; waited bit is 0 ? goto A52 ; no ; waited bit is 0 nop ; for exact timing purpose btfss afb,1 ; received bit = 0 ? goto A53 ; OK same goto A54 ; wrong bit A52 ; waited bit is 1 btfsc afb,1 ; received bit = 1 ? goto A53 ; OK same A54 ; wrong bits or other bits to read ; check if time left nop ; for exact timing purpose btfss PIR1, TMR1IF ; check if time left goto A51 ; yes: once again read 2 bits ; no time overpassed, inform bsf task_fb,7 ; set RF receive errorflag movlw 04 movwf errnb ; set error number goto A5error ; launch error task A53 ; same bits ; wait for other bit movlw 0x01 ; Mask 0000 0001 xorwf afb,f ; change last bit decfsz cmpta,f ; all done ? goto A54 ; no: once again A55 ; all done bcf INTCON,T0IE ; disable Timer0 INT bcf T1CON,TMR1ON ; stop Timer1 bcf PIR1,TMR1IF ; Clear Timer1 Flag ; 25 transitions detected in time : continue movlw 07 ; next A task movwf STAnb ; store task number ; return to Task Manager goto RFrcv_ret ; RF task CPU over A5error ; n° erreur into errnb et bit déjà rempli movlw 12 ; error task movwf STAnb ; goto RFrcv_ret ; return to Task Manager ; --------------------------------------------------------- ;---------------- ; Under Task A6 : Period detection ;---------------- ; Unuseful, not accurate enough ! ! ! ; --------------------------------------------------------- A6 movlw 07 ; next A task movwf STAnb ; store task number goto RFrcv_ret ; RF task CPU over ; --------------------------------------------------------- ;---------------- ; Under Task A7 : "M-start bit" detection "1-0" after a "0-1" ;---------------- ; wait for bit 0 ; detect bit1 ; wait 150 clk for other bit ; if 1 check for bit 0 after 100 clk ; if 0 restart ; wait 100 times otherwise error A7 ; préparation bcf PIR1, TMR1IF ; Clear Timer1 Flag bcf T1CON, TMR1ON ; stop TIMER1 clrf TMR1H ; H = 000 movlw 108 movwf period movwf TMR1L ; L = FF - (150 - retard) movlw 100 ; 100 bit maxi to read movwf cmpta ; attendre un 0 pour detecter le bit 1 ; wait for bit 0 ; ---------------------------------------- A71 btfsc RF_RX ; bit = 0 ? goto A71 ; no wait again ; detecter bit 1 ; ---------------------------------------- A72 btfss RF_RX ; bit = 1 ? goto A72 ; no wait again ; ---------------------------------------- ; "1" received, now wait 150 clk bsf T1CON, TMR1ON ; start TIMER1 A73 btfss TMR1H,0 ; TMR1L overflow ? goto A73 ; no ; 150 clk passed ; Read bit: 1 or 0 ? ; ---------------------------------------- btfsc RF_RX ; bit = 0 ? goto A74 ; no: continue test ; ---------------------------------------- ; Bit is 0 ; reset period and restart again bcf T1CON, TMR1ON ; stop TIMER1 movf period,w ; reset period movwf TMR1L ; L = 150 - retard bcf TMR1H,0 ; H = 000 decfsz cmpta,f ; one more done goto A72 ; wait 1 again goto A79 ; waited more than expected ; ---------------------------------------- A74 ; "0-1-1" received ; ---------------------------------------- ; reset period and wait again for bit 0 bcf TMR1H,0 ; H = 000 movlw 161 ; reset period movwf TMR1L ; L = 100 clk - retard ; ---------------------------------------- A75 btfss TMR1H,0 ; TMR1L overflow ? goto A75 ; no ; 100 clk passed ; Read bit: 1 or 0 ? ; ---------------------------------------- btfsc RF_RX ; bit = 0 ? goto A78 ; no: "0-1-1-1" error ; "0-1-1-0" received ; prepare next task movlw 08 ; next A task ; ******************************************* ; movlw 09 ; next A task ; ******************************************* movwf STAnb ; store task number goto A8 ; goto A8 Task ; ******************************************* ; goto A9 ; goto A8 Task ; ******************************************* A78 ; error "0-1-1-1" received bcf T1CON, TMR1ON ; stop TIMER1 bsf task_fb,7 ; set global A Task error flag movlw 01 movwf errnb ; set error number = 06 movlw 12 ; next A task : error end movwf STAnb ; store task number goto RFrcv_ret ; goto Task Manager A79 ; error "0-1-1-0" waited too long bcf T1CON, TMR1ON ; stop TIMER1 bsf task_fb,7 ; set global A Task error flag movlw 02 movwf errnb ; set error number = 06 movlw 12 ; next A task : error end movwf STAnb ; store task number goto RFrcv_ret ; goto Task Manager ;---------------------------------------------------------- ; manchestercheck bcf task_fb,7 ; clear global A Task error bit comf INDF,w ; complement 1 Manchester data movwf cmpta ; save to temp incf FSR,f ; point to 2nd manchester data movf INDF,w ; read data subwf cmpta,w ; compare both data btfss STATUS,Z ; equal ? bsf chk_error_flag,0; no return ; ;---------------------------------------------------------- ; ==================================================== ; Under Task A8 : Read Manchester data bit ; special action if first data read : message length ; ==================================================== ; use ssb_chk ; Byte sent lsb first ; Manchester data send bit and opposite ; Stop - Start bits : "1-0" ; 1 byte : 16 bytes (8 data and 8 Manchester) ; 2 parity bits A8 clrf afb ; clear variable clrf cmpta ; clear counter bsf cmpta,7 ; special flag for 1st read movlw RFr_adr ; RF receive buffer start adress movwf FSR ; to indirect ptr ; ************************************* clrf cpt1 incf cpt1,f ; ************************************* ; need to read first next byte ; ---------------------------------------- ; reset period and wait again 100 clk for bit bcf TMR1H,0 ; H = 000 movlw 178 ; reset period movwf TMR1L ; L = 100 clk - retard bsf T1CON, TMR1ON ; start TIMER1 ; ---------------------------------------- A8a1 btfss TMR1H,0 ; TMR1L overflow ? goto A8a1 ; no ; 100 clk passed since last read bcf T1CON, TMR1ON ; stop TIMER1 btfsc RF_RX ; read bit bsf afb,1 ; bit is 1 bsf afb,2 ; indicate bit read movlw 171 ; 255 - (100 clk - retard) movwf period ; used by TIMER0 A801 ; ---------------------------------------- call ssb_chk ; check if for Stop - Start Bit "1-0" and synchronise ; ---------------------------------------- btfsc task_fb,7 ; error detected ? goto A88 ; yes movlw 8 ; 8 bit to read movwf atemp ; to temp var ; receive first byte: message length clrf parity_temp ; clear parity data A81 ; ---------------------------------------- ; call readbit ; readbit or give back CPU btfss afb,2 ; check if bit read ? goto A81 ; no bcf afb,2 ; reset flag for next time ; ---------------------------------------- ; now store read bit bcf STATUS,C ; clear CARRY bit btfss afb,1 ; value read 0 ? goto A811 ; yes : continue bsf STATUS,C ; set CARRY bit incf parity_temp,F ; and calc Even parity A811 rrf INDF,f ; Insert bit fom carry LSB send first ; point to next byte buffer by INDF to receive 2nd Manchester bit incf FSR,f ; point to next buffer (17 bytes needed) swapf parity_temp,F ; switch to Manchester data 2 parity temp ; ---------------------------------------- ; call readbit ; readbit or give back CPU A814 btfss afb,2 ; check if bit read ? goto A814 ; no bcf afb,2 ; reset flag for next time ; ---------------------------------------- bcf STATUS,C ; clear CARRY bit btfss afb,1 ; value read 0 ? goto A812 ; yes continue bsf STATUS,C ; set CARRY bit incf parity_temp,F ; no: calc Even parity A812 rrf INDF,f ; Insert bit fom carry LSB send first decf FSR,f ; point back to 1st Manchester byte swapf parity_temp,F ; switch to Manchester data 1 parity temp decfsz atemp,f ; check if all read ? goto A81 ; no read 2 bits again ; now read parity into flagbit ; afb,bits 3 et 4 bcf afb,3 ; clear bit 1 bcf afb,4 ; clear bit 2 ; ---------------------------------------- ; call readbit ; readbit or give back CPU A813 btfss afb,2 ; check if bit read ? goto A813 ; no bcf afb,2 ; reset flag for next time ; ---------------------------------------- btfsc afb,1 ; value read 1 ? bsf afb,3 ; yes 1st parity is 1 ; ---------------------------------------- ; call readbit ; readbit or give back CPU A815 btfss afb,2 ; check if bit read ? goto A815 ; no bcf afb,2 ; reset flag for next time ; ---------------------------------------- btfsc afb,1 ; value read 1 ? bsf afb,4 ; yes 2nd parity is 1 ; now check parity ; 32 clk since last given CPU movlw 0x11 ; mask value andwf parity_temp,f ; keep only bits 0 and 4 clrf atemp ; clear file btfsc afb,3 ; Data parity is 1 ? bsf atemp,0 ; yes: copy to bit0 btfsc afb,4 ; Manchester Data parity is 1 ? bsf atemp,4 ; yes: copy to bit 4 movf atemp,w ; check if received parity equal to calculated one xorwf parity_temp,f bcf chk_error_flag,1; reset error flag bcf chk_error_flag,2; reset error flag btfsc parity_temp,0 ; parity 1 equal? bsf chk_error_flag,1; no: set error flag btfsc parity_temp,4 ; parity 2 equal? bsf chk_error_flag,2; no: set error flag ; now check both Manchester values: bcf task_fb,7 ; clear global A Task error bit comf INDF,w ; complement 1 Manchester data movwf tempdata ; save to temp incf FSR,f ; point to 2nd manchester data movf INDF,w ; read data decf FSR,f ; point to 1st data subwf tempdata,w ; compare both data btfss STATUS,Z ; equal ? bsf chk_error_flag,0; no ; calculate check result ~ 12 clk bcf chk_error_flag,4; Use M1 ; Data Identical ? btfss chk_error_flag,0; M1 = M2 ? goto A85 ; Yes: use M1 A82 ; M1 <> M2 - check if M1 good data btfss chk_error_flag,1; Parity 1 OK ? goto A85 ; Yes: use M1 ; check if M2 good data ? btfsc chk_error_flag,1; else Parity 2 OK ? goto A83 ; No: Error bsf chk_error_flag,4; Yes: use M2 goto A85 ; Yes: use M2 A85 ; Data to use indicated by bit 4 of chk_error_flag btfss chk_error_flag,4; use M1 ? goto A86 ; yes incf FSR,f ; no: use M2 ; movf INDF,w ; read manchester data 2 comf INDF,w ; complement 1 Manchester data decf FSR,f ; ptr to manchester data 1 movwf INDF ; store correct data ; check if first byte read: byte is message length A86 movf INDF,w ; read data btfsc cmpta,7 ; first byte read ? movwf cmpta ; yes, store data to counter ; now ready for other data to read ! incf FSR,f ; next free space ; *************************** incf cpt1,f ; *************************** decfsz cmpta,f ; goto A801 ; once again ; All message data read : Disable RF Reception device bcf INTCON, T0IE ; disable TIMER0 interrupt bcf INTCON, INTE ; disable CD interrupt bsf Rx_En ; DISABLE RF RECEIVE bsf Tx_En ; DISABLE RF EMIT ; bcf RxenLED ; RX En Led OFF bcf TxenLED ; TX En Led OFF ; TIMER1 wait 1 ms routine <-> 200 clk call Await ; wait routine ; prepare next task movlw 10 ; next A task movwf STAnb ; store task number goto RFrcv_ret ; goto Task Manager A83 ; error: same data but parity are different bsf task_fb,7 ; set global A Task error flag movlw 03 movwf errnb ; set error number = goto A8end A84 ; error: data different but parity same bsf task_fb,7 ; set global A Task error flag movlw 07 movwf errnb ; set error number = goto A8end A87 ; error: data different and parity NOK bsf task_fb,7 ; set global A Task error flag movlw 08 movwf errnb ; set error number = goto A8end A88 ; Error in start Stop bit ; bsf task_fb,7 ; set global A Task error flag ; movlw 09 ; error number 9 ; ************* remove after test *********** ; movwf cpt1 ; movlw 50 ; addwf cpt1,w ; addlw 60 ; ******************************************* ; w contains error number from ssb_chk ; movwf errnb ; set error number = ; goto A8end movlw RFr_adr ; RF receive buffer start adress movwf FSR ; to indirect ptr movf cpt1,w movwf INDF clrf STAnb ; no more A undertask bcf task_fb,3 ; disable RF Task A clrf afb ; A task flag bits cleared ; WARNING : In order not to reactivate by itself if lots of 434 Mhz emission exists ; Carrier Detect re-activated ONLY after end of Task D: RS232 transmisson ! ; disable RF reception task ; activate RS send (D) Task bsf task_fb,0 ; Enable global RS232 emit Task movlw 01 ; first D Under-Task movwf STDnb ; indicated goto RFrcv_ret ; last return ; error number is stored into errnb ; disable receive task ; disable timer0 ; reset all pointers ; prepare error message for rs232 ; prepare special RF termination waiting for RF carrier detect closed ; then send RS232 error received message A8end movlw 12 ; next A task movwf STAnb ; store task number goto RFrcv_ret ; goto Task Manager ; ------------------------------------------------- ;---------------- ; Under Task A9 : for test only: receive and transmit ALL received bits ;---------------- A9 clrf afb ; clear variable clrf cmpta ; clear counter movlw RFr_adr ; RF receive buffer start adress movwf FSR ; to indirect ptr movlw 05 ; store length movwf INDF incf FSR,f ; point to next clrf cpt1 clrf cpt2 movlw 5 movwf cpt1 movlw 8 movwf cpt2 movlw 171 ; 255 - (100 clk - retard) movwf period ; used by TIMER0 movwf TMR0 bcf INTCON, T0IF ; Clear Timer0 Flag bsf INTCON, T0IE ; Enable TIMER0 Interrupt A92 movlw 8 movwf cpt2 ;--------------------------------------------- A91 btfss afb,2 ; 2nd bit is red ? goto A91 ; ;--------------------------------------------- bcf afb,2 ; clear for reset bcf STATUS,C ; clear CARRY bit btfsc afb,1 ; read bit bsf STATUS,C ; set CARRY bit rrf INDF,f ; Insert bit fom carry LSB send first decfsz cpt2,f goto A91 incf FSR,f ; point to next buffer decfsz cpt1,f goto A92 bcf INTCON,T0IE ; disable Timer0 INT movlw RFr_adr ; RF receive buffer start adress movwf FSR ; to indirect ptr clrf STAnb ; no more A undertask bcf task_fb,3 ; disable RF Task A clrf afb ; A task flag bits cleared bsf task_fb,0 ; Enable global RS232 emit Task movlw 01 ; first D Under-Task movwf STDnb ; indicated goto RFrcv_ret ; last return ; ------------------------------------------------- ;---------------- ; Under Task A10 :Prepare end termination delay ;---------------- A10 ; TIMER1 set to timer mode: count cycle instr BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf T1CON, TMR1CS ; select TIMER mode clrf TMR1H ; clear timer1 H clrf TMR1L ; clear timer1 L bsf T1CON, TMR1ON ; start TIMER ; prepare next task movlw 11 ; next A task movwf STAnb ; store task number goto RFrcv_ret ; goto Task Manager ; ------------------------------------------------- ;---------------- ; Under Task A11 : RF receive termination delay ;---------------- ; wait for 8192 clk - 1.64 ms A11 ; no more 434 Mhz Carrier Detect btfss TMR1H,6 ; 8192 clk reached ? goto A11 ; no: wait again bcf T1CON, TMR1ON ; stop TIMER1 clrf STAnb ; no more A undertask bcf task_fb,3 ; disable RF Task A clrf afb ; A task flag bits cleared ; WARNING : In order not to reactivate by itself if lots of 434 Mhz emission exists ; Carrier Detect re-activated ONLY after end of Task D: RS232 transmisson ! ; disable RF reception task ; activate RS send (D) Task bsf task_fb,0 ; Enable global RS232 emit Task movlw 01 ; first D Under-Task movwf STDnb ; indicated goto RFrcv_ret ; last return ; ------------------------------------------------- ;---------------- ; Sous task A12 : Abnormal termination (Erreur) ;---------------- ; trigered by error detection ; timer0 for ex. ; error nb into errnb A12 ; All message data read : Disable RF Reception device bcf INTCON, T0IE ; disable TIMER0 interrupt bcf INTCON, INTE ; disable CD interrupt bsf Rx_En ; DISABLE RF RECEIVE bsf Tx_En ; DISABLE RF EMIT ; bsf RxenLED ; RX En Led OFF bsf TxenLED ; TX En Led OFF ; ******************************************* ; remove after Test ; allume led + attente 1 sec LEDON call TEMPO2 LEDOFF ; ******************************************* ; TIMER1 wait 1 ms routine <-> 200 clk call Await ; wait routine movf RFr_ptr,w ; read first data adr movwf FSR ; store to pointer movlw 07 movwf INDF incf FSR,f movlw 0x45 movwf INDF incf FSR,f movlw 0x52 movwf INDF incf FSR,f movlw 0x52 movwf INDF incf FSR,f movlw 0x20 movwf INDF incf FSR,f ; convert errnb to ascII clrf cmpta clrf atemp movf errnb,w movwf tempdata A121 incf cmpta,f movlw 10 subwf tempdata,f btfsc STATUS,C ; < 0 ? goto A121 ; no ; yes addwf tempdata,f decf cmpta,f movlw 0x30 addwf cmpta,w movwf INDF ; store ascII value incf FSR,f ; next data ; ----------------------------------- clrf cmpta A122 incf cmpta,f movlw 01 subwf tempdata,f btfsc STATUS,C ; < 0 ? goto A122 ; no ; yes decf cmpta,f movlw 0x30 addwf cmpta,w movwf INDF ; store ascII value ; error message done ; disable RF reception task clrf STAnb ; no more A undertask bcf task_fb,3 ; Disable A Task bcf task_fb,7 ; clear global A Task error flag for next time ; activate RS send (D) Task bsf task_fb,0 ; Enable global RS232 emit Task movlw 01 ; first D Under-Task movwf STDnb ; indicated goto RFrcv_ret ; last return ; ==================================================================== ; task B : Emission RF ; ==================================================================== ; - launched by C task end: RS232 reception ; ; low level tasks: ; ; B1 - Manchester bits Emission triggered by Timer0 interrupt ; B2 - Preamble Emission ; - "M-start bit" Emission ; B3 - Data and parity bit Emission ; B4 - RF task Emission Elimination ; WARNING ; use special SENBIT routine ; sendbit send bit stored into bit 0 of bfb ; AND send also the opposite bit (Special Manchester transparent coding) ! ; ==================================================== ; SPECIAL Under Task B1 : Send bit triggereg by TIMER0 INT ! ; ==================================================== ; IN : bit 0 of bfg ; OUT: nothing sendbit ; suppose TIMER0 interrupt set to send bit ; initialisation part: executed once ; ident and store which calling task ; store this task id to Task Manager movf STBnb,w ; read calling B Task movwf calltask ; and store to var to restore afterwards movlw 01 ; set actual Task movwf STBnb ; in Task Manager B1 ; execute each time CPU given btfss bfb,1 ; check if bit send ? goto RFemit_ret ; no: give CPU to next task bcf bfb,1 ; reset flag for next time btfsc bfb,2 ; 2nd bit also sent ? goto B11 ; yes: end ; no : prepare 2nd bit nop nop movlw 0x01 ; MASK value xorwf bfb,f ; invert only bit 0 ; wait again for complement bit sent bsf bfb,2 ; 2nd bit flag bit goto B1 ; wait again B11 bcf bfb,2 ; reset 2nd bit flag bit ; restore intial Task movf calltask,w ; read stored task nb movwf STBnb ; read calling B Task return ; to initial calling line from any undertask ; ==================================================== ; -------------- ; Under Task B2: 5 ms preamble emission ; -------------- ; activate Radio Frequency send routine ; ********************* change to 3 ms ****************** ; send "0-1" for 5 ms ; 250 bits sent, 125 of each ; ******************************************************* B2 ; activate timer0 send bit routine ; use bfb flag bit ; set XTR-434 in emission mode bsf Rx_En ; DISABLE RF RECEIVE bcf Tx_En ; ENABLE RF EMIT ; bsf RxenLED ; RX En Led OFF bcf TxenLED ; TX En Led ON ; TIMER1 wait 1 ms routine <-> 5000 clk ; 256 clk <--> 1.28 ms ; TIMER1 set to timer mode: count cycle instr BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf T1CON, TMR1CS ; select TIMER mode ; wait for 5000 clk : 8192 - 5000 = 3192 = [12] [120] movlw 12 movwf TMR1H ; timer1 H = 12 movlw 120 movwf TMR1L ; timer1 L = 120 bsf T1CON, TMR1ON ; start TIMER Z5 btfss TMR1H,5 ; 5000 clk ? goto Z5 ; no: wait again bcf T1CON, TMR1ON ; stop TIMER1 movlw BIT_PERIOD ; standard value movwf TMR0 ; initialise variable ; ******************************************************************************************** ; REMOVE AFTER TEST bcf SIMUCD ; simulate RF emission for Carrier detect ; ******************************************************************************************** ; enable TIMER0 interrupt bcf INTCON,T0IF ; clear timer0 interrupt flag bsf INTCON,T0IE ; enable timer0 interrupt movlw 125 ; initialise counter movwf cmptb ; to 125 B21 bcf bfb,0 ; send 0 then 1 call sendbit ; give back CPU until send time arrived decfsz cmptb,f ; finished ? goto B21 ; no: do again ; ---------------------------------------------------------------------- ; preamble done, now send global message STOP - START bit bsf bfb,0 ; send 1 then 0 : stop-start bit call sendbit ; give back CPU until send bit done ; ---------------------------------------------------------------------- ; preamble done, now send real data movlw 03 ; next B task movwf STBnb ; store task number ; goto RFemit_ret ; give back CPU goto B3 ; -------------- ; Under Task B3: data emission ; -------------- ; read 1st data : MSG length ; send start-stop bit ; code manchester data ; send data ; calculate parity ; send parity ; check if still data ; do again or stop B3 ; initialise pointer data movlw RSr_adr ; RF emit Buffer adress movwf RSr_ptr ; to data pointer ; read message length and initialise counter movwf FSR ; store to pointer movf INDF,w ; read data movwf msglength ; store to variable B35 ; ---------- SEND DATA ------------------------------------- movlw 08 ; initialise counter movwf cmptb ; to 8 bit clrf parity ; reset parity bsf bfb,0 ; send 1 then 0 : stop-start bit call sendbit ; give back CPU until send bit done B31 movf RSr_ptr,w ; read adress movwf FSR ; store to pointer movf INDF,w ; read data movwf tempdata ; store to variable B32 bcf bfb,0 ; write bit = 0 btfss tempdata,0 ; check if LSB = 0 goto B33 ; yes nop bsf bfb,0 ; no: write bit = 1 incf parity,f ; calculate new parity B33 ; --------- Write Bit -------------------- call sendbit ; give back CPU until send bit done rrf tempdata,f ; rotate to send next bit decfsz cmptb,f ; finished ? goto B32 ; no ; now have to send parity bit bcf bfb,0 ; write bit = 0 btfss parity,0 ; check if LSB = 0 goto B34 ; yes bsf bfb,0 ; no: write bit = 1 B34 ; --------- Write Parity Bit -------------------- call sendbit ; give back CPU until send bit done decfsz msglength,f ; finished ? goto B37 ; no B36 ; message finished ; disable Timer0 Interrupt ; wait a few ms ; end Radio Freq emission Task ; give back CPU bcf INTCON,T0IE ; disable timer0 interrupt flag bcf T1CON, TMR1CS ; select TIMER mode for TIMER1 clrf TMR1H clrf TMR1L bsf T1CON, TMR1ON ; start TIMER movlw 04 ; next B task movwf STBnb ; store task number goto RFemit_ret ; goto Task Manager B37 incf RSr_ptr,f ; no: next data goto B35 ; do again ;---------------- ; Under Task B4 : RF emit termination delay ;---------------- B4 btfss TMR1H,3 ; 2048 clk reached ? <-> goto RFemit_ret ; no:goto Task Manager clrf STBnb ; no more B undertask bcf task_fb,2 ; disable RF Task bsf Tx_En ; DISABLE RF EMIT ; ************************************************************************************* ; REMOVE AFTER TEST bsf SIMUCD ; simulate end of RF Carrier Emission on pin RB7 ; ************************************************************************************* ; TIMER1 wait 1 ms routine <-> 200 clk ; 256 clk <--> 1.28 ms ; TIMER1 set to timer mode: count cycle instr BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf T1CON, TMR1CS ; select TIMER mode ; wait for 5000 clk movlw 12 movwf TMR1H ; H = 12 movlw 120 movwf TMR1L ; L = 120 bsf T1CON, TMR1ON ; start TIMER Z6 btfss TMR1H,5 ; 5000 clk ? goto Z6 ; no: wait again bcf T1CON, TMR1ON ; stop TIMER1 bcf Rx_En ; ENABLE RF RECEIVE ; bcf RxenLED ; RX En Led ON bsf TxenLED ; TX En Led OFF ; TIMER1 wait 1 ms routine <-> 5000 clk ; TIMER1 set to timer mode: count cycle instr BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf T1CON, TMR1CS ; select TIMER mode ; wait for 5000 clk movlw 12 movwf TMR1H ; H = 12 movlw 120 movwf TMR1L ; L = 120 bsf T1CON, TMR1ON ; start TIMER Z7 btfss TMR1H,5 ; 5000 clk ? goto Z7 ; no: wait again bcf T1CON, TMR1ON ; stop TIMER1 bsf INTCON,INTE ; Re-Enable RB0 interrupt for carrier detect movlw 01 ; Re-init C1 task: RS232 receive movwf STCnb ; store task number bsf task_fb,1 ; Enable C Task goto RFemit_ret ; give back CPU ; *************** remove after test ************************ ; envoi de 5 octets identifiés ; *************************************** B5 movlw RSr_adr ; RF emit Buffer adress movwf RSr_ptr ; to data pointer ; read message length and initialise counter movwf FSR ; store to pointer movf INDF,w ; read data movwf msglength ; store to variable B55 ; ---------- SEND DATA ------------------------------------- movlw 08 ; initialise counter movwf cmptb ; to 8 bit B51 movf RSr_ptr,w ; read adress movwf FSR ; store to pointer movf INDF,w ; read data movwf tempdata ; store to variable B52 bcf bfb,0 ; write bit = 0 bcf bfb,1 ; flag bit = 0 btfss tempdata,0 ; check if LSB = 0 goto B53 ; yes nop bsf bfb,0 ; no: write bit = 1 B53 ; --------- Write Bit -------------------- B58 btfss bfb,1 ; check if bit send ? goto B58 ; for test bcf bfb,1 ; flag bit = 0 rrf tempdata,f ; rotate to send next bit decfsz cmptb,f ; finished ? goto B52 ; no decfsz msglength,f ; finished ? goto B57 ; no B56 ; message finished bcf INTCON,T0IE ; disable timer0 interrupt flag bcf T1CON, TMR1CS ; select TIMER mode for TIMER1 clrf TMR1H clrf TMR1L bsf T1CON, TMR1ON ; start TIMER movlw 04 ; next B task movwf STBnb ; store task number goto RFemit_ret ; goto Task Manager B57 incf RSr_ptr,f ; no: next data goto B55 ; do again ; *************************************** ; ==================================================================== ; task C : Reception RS232 ; ==================================================================== ; - Triggered by interrupt: RX byte full ; low level tasks: ; C1 - Initialisation : reception authorisation ; - Activation task if not already active ; - first byte read = MSG length ; - While legnth not reached, read bytes ; - if length reached, reset buffer pointer ; - to prepare other MSG reception ; Reception MUST be authorized at PIC start ; task 1 is executed at start ; --------------- ; Under Task C1 : authorise RS232 reception ; --------------- C1 ; initialiser pointeur buffer au debut movlw RSr_adr ; RS232 reception buffer start adress movwf RSr_ptr ; RS232 receive buffer ptr movlw 255 ; movwf Cbyte_cntr ; special value for check purpose BANK1 ; Enable interrupt on reception bsf PIE1,RCIE ; Enable interrupt on received byte bcf TXSTA,TX9 ; set 8 bit transmission BANK0 ; Enable Reception bsf RCSTA,CREN ; Enable continuous receive ; Initialisation complete: set next task movlw 02 ; next C task movwf STCnb ; store task number bcf task_fb,1 ; No more C task active goto RSrcv_ret ; --------------- ; Under Task C2 ; --------------- ; task activation by RX byte full ;- read first byte = length ;- set flags and various variables ;- activate task 3 for reception monitoring C2 ; wait for 1st byte read btfss cfb,0 ; test if first byte read goto C21 ; no: wait again ; yes : read first byte = MSG length movlw RSr_adr ; buffer start adress movwf FSR ; to read pointer movf INDF,w ; read data=MSG Length movwf Cbyte_cntr ; store to counter decf Cbyte_cntr,f ; first byte read ; test if < 22 bytes ? movlw 23 ; max remaining bytes subwf Cbyte_cntr,w ; check if over btfss STATUS,C ; > 22 ? goto C22 ; no ; set min nb possible movlw 02 ; max remaining bytes movwf Cbyte_cntr ; store to counter C22 btfsc cfb,1 ; 2nd bytes read also ? decf Cbyte_cntr,f ; yes: adjust msg counter ; set next task movlw 03 ; next C task movwf STCnb ; store task number C21 goto RSrcv_ret ; --------------- ; Under Task C3 ; --------------- ; launched by Under Task 2 ; check all bytes received (till end of message) ; Then will launch Under Task C4 C3 btfss cfb,2 ; check if all MSG bytes read goto C31 ; no: wait again ; all bytes received ; reset all pointers to initial values ; then transfert data to RF Buffer ; and launch B Task : Radio Freq Emission ; re-init buffer pointers movlw RSr_adr ; RS232 reception start buffer adress movwf RSr_ptr ; read receive buffer ptr ; set next task movlw 04 ; next C task movwf STCnb ; store task number C31 goto RSrcv_ret ; --------------- ; Under Task C4 ; --------------- ; if RF buffer not used by RF task ; transfert 1st bytes from RS232 receive buffer to RF buffer C4 ; set next task movlw 06 ; next C task movwf STCnb ; store task number ; *********** Remove after test ***************** ; set next task : send back RS232 msg ; movlw 05 ; next C task ; movwf STCnb ; store task number ; *********** remove after test ***************** goto RSrcv_ret ; --------------- ; Under Task C5 *********** test purpose only ************* ; --------------- ; *********** Remove after test ***************** ; transfert bytes from RS232 receive buffer to RF buffer C5 ; nb of bytes to transfer movlw 23 ; 23 bytes max movwf cmptd ; to counter ; reset both buffer pointers movlw RFr_adr ; read RF buffer adr movwf RFr_ptr ; write buffer ptr movlw RSr_adr ; read RS buffer adr movwf RSr_ptr ; write receive buffer ptr C51 movf RSr_ptr,w ; read adr output movwf FSR ; store adr to ptr movf INDF,w ; Read Data movwf tempc ; store to variable movf RFr_ptr,w ; read adr output movwf FSR ; store to ptr movf tempc,w ; read temp data movwf INDF ; store data to dest incf RFr_ptr,f incf RSr_ptr,f decfsz cmptd,f ; data left ? goto C51 ; yes : next time ; ************************************************* ; set next task movlw 06 ; next C task movwf STCnb ; store task number ; *********** Remove after test ***************** ; set next task : send back RS232 msg movlw 07 ; next C task movwf STCnb ; store task number ; *********** remove after test ***************** goto RSrcv_ret ; --------------- ; Under Task C6 ; --------------- ; ask for activating Task B-2 C6 btfsc task_fb,3 ; check RF receive active ? goto RSrcv_ret ; yes: wait ; transfert complete bcf INTCON, INTE ; disable RF CD detection interrupt bcf task_fb,1 ; Disable C Task : clrf STCnb ; no more Under Task number clrf cfb ; C task flag bits cleared BANK1 bcf PIE1, RCIE ; disable RS232 reception BANK0 ; Disable Reception bcf RCSTA,CREN ; Disable continuous receive RS232 bsf task_fb,2 ; Enable B Task : Radio Freq Emission movlw 02 ; next B task movwf STBnb ; store task number goto RSrcv_ret ; *********** remove after test ***************** ; --------------- ; Under Task C7 ******** FOR TEST ONLY *********** ; --------------- ; ask for activating Task D-1 C7 bcf task_fb,1 ; Disable C Task : bsf task_fb,0 ; Enable D Task : RS232 emit clrf STCnb ; no more Under Task number clrf cfb ; C task flag bits cleared ; BANK1 ; bcf PIE1, RCIE ; disable RS232 reception ; BANK0 ; Disable Reception movlw 01 ; next B task movwf STDnb ; store task number goto RSrcv_ret ; *********** remove after test ***************** ; ==================================================================== ; task D : RS232 Emission ; ==================================================================== ; - Triggered by : RF reception task (A) end ; RS232 emission done by USART ; Buffer emptied by interrupt "byte transmited" ; ; low level tasks: ; D1: prepare & launch RS232 emission task ; D2: wait until buffer empty then stop task ; ; D1: prepare and configure transmission ; read first data : msg length ; store length to counter ; enable interrupt on transmit register empty ; this interrupt load a new data and decrement counter ; if counter is zero, last data is transmited then disable this interrupt ; D2 Task wait for counter = 0 ; when reached, wait for trmt bit set that indicate last bit transmited ; then disable transmission and disable D Task terminated ;---------------- ; Under Task D1 : prepare transmission ;---------------- D1 ; ************* remove after test ************* bcf INTCON, T0IE ; disable TIMER0 interrupt bcf INTCON, INTE ; disable CD interrupt bsf Rx_En ; DISABLE RF RECEIVE bsf Tx_En ; DISABLE RF EMIT BANK1 ; bsf TRISB,2 ; output bsf PIE1,TXIE ; Enable TXREG interrupt ; initialise baud rate generator bsf TXSTA,BRGH ; set baud rate movlw 129 ; to movwf SPBRG ; 9600 bds ; configure to asynchronous bcf TXSTA,SYNC ; set asynchronous mode bcf TXSTA,TX9 ; set 8 bit transmission BANK0 ; bsf RCSTA,SPEN ; serial port Enabled movlw RFr_adr ; restore adr pointer movwf RFr_ptr movf RFr_ptr,w ; read first data adr movwf FSR ; store to pointer movf INDF,w ; read data = message length movwf cmptd ; store to counter movlw 02 ; next D task movwf STDnb ; store task number BANK1 ; bsf TXSTA,TXEN ; enable transmission BANK0 ; goto RSemit_ret ; goto Task Manager ;---------------- ; Under Task D2 : check end transmission ;---------------- D2 movf cmptd,w ; set STATUS register btfss STATUS,Z ; cmptd = 0 ? goto RSemit_ret ; no give back CPU BANK1 ; btfss TXSTA,TRMT ; transmission end ? goto D21 ; No : continue ; Yes End RS232 transmission task bcf TXSTA,TXEN ; Disable transmission BANK0 ; clrf STDnb ; no more D undertask bcf task_fb,0 ; disable RS232 emit Task ; Do not Re-activate CD detect and RF Receive mode because we ; can be in RF emission mode ; CD detect will be re-enabled at re start of A Task movlw RFr_adr ; restore Buffer adr movwf RFr_ptr movlw 01 ; next A task movwf STAnb ; store task number bsf task_fb,3 ; Re-Enable RF Receive Task ; ***************** remove after test *************************** ; clrf STAnb ; bcf task_fb,3 ; disable RF Receive Task ; bsf task_fb,1 ; Re-Enable RS receive Task ; movlw 01 ; next C task ; movwf STCnb ; store task number ; ***************** remove after test *************************** goto RSemit_ret ; goto Task Manager D21 BANK0 ; goto RSemit_ret ; no give back CPU ;---------------- ; Under Task D3 : for TEST only ;---------------- ; increment counter ; reset message adr ; relaunch RS232 Emission D3 movlw 0x27 movwf FSR ; store to pointer incf INDF,f ; increment file movlw 0x3A subwf INDF,w btfss STATUS,C ; > 9 ? goto D31 ; no ; yes ; put "0" movlw 0x30 ; "0" movwf INDF ; store to message ; increment FSR - 1 and test decf FSR,f ; point to first character incf INDF,f ; increment file ; test if > 9 ? movlw 0x3A subwf INDF,w btfss STATUS,C ; > 9 ? goto D31 ; no ; if >9 put 0 also movlw 0x30 movwf INDF ; store to message incf FSR,f ; point to first character D31 ; send new message movlw 05 ; next D task movwf STDnb ; store task number goto RSemit_ret ; goto Task Manager ;---------------- ; Under Task D4 : for TEST only ;---------------- D4 ; *************** prepare message buffer ************** movlw 0x21 movwf RFr_ptr movf RFr_ptr,w ; read first data adr movwf FSR ; store to pointer movlw 23 movwf INDF incf FSR,f movlw 0x4E movwf INDF incf FSR,f movlw 0x42 movwf INDF incf FSR,f movlw 0x3A movwf INDF incf FSR,f movlw 0x20 movwf INDF incf FSR,f movlw 0x30 movwf INDF incf FSR,f movlw 0x30 movwf INDF movlw 01 ; next D task movwf STDnb ; store task number goto RSemit_ret ; goto Task Manager ; ************** remove after test ************** ;---------------- ; Under Task D5 : for TEST only ;---------------- D5 ; *************** wait for 1 second ************** movlw 150 movwf cmptd BANK1 bcf PIE1, TMR1IE ; insure Timer1 int disabled BANK0 bcf PIR1, TMR1IF ; Clear Timer1 Flag bcf T1CON, TMR1CS ; select TIMER mode D52 clrf TMR1H clrf TMR1L bsf T1CON, TMR1ON ; start TIMER D51 btfss PIR1,TMR1IF ; Overflow flag set ? goto D51 ; no: wait again ; ------------------------------------------------- bcf T1CON, TMR1ON ; stop TIMER1 bcf PIR1, TMR1IF ; Clear Timer1 Flag incfsz cmptd,f goto D52 movlw 01 ; next D task movwf STDnb ; store task number goto RSemit_ret ; goto Task Manager ; ************** remove after test ************** END ; End program directive ; *********** penser à verifier que l'attente des timer1 ne risque pas ; de perturber les taches notamment leur durées ! ! ! ; ; redonner la main et verifier une fois tache passée par presence flag ; interrption ; ; verifier qu'aucune tache simultanée n'utilise pas le timer1 pour attendre ! ; A* --> D ; C --> B* ;Emission RF ;Emission RS232 ; Z1: initialisation ; Z8: NEW A1 Wait for Activation XTR434 in Receive mode ; Z2: A5 reception RF ; Z4: A10 fin reception RF sur erreur ; Z5: B2 Debut Emission RF ; Z6: B4 Fin Emission RF ; Z7: B4 Fin Emission RF