;************************************************************************* ; TX A7105 2.4Ghz protocol Flysky/turnigy 9x (v2) ; look at thread: http://www.rcgroups.com/forums/showthread.php?t=1626362 ; many thanks to: PhracturedBlue, Dave1993, Surfbreizh, CristiV... ; autor: Thierry Pébayle ;************************************************************************* ; include PIC reg definitions. include ;uncomment to use PIC18F14K22 PROCESSOR PIC18F14K22 ;uncomment to use PIC18F14K22 ;include ;uncomment to use PIC18F14K50 ;PROCESSOR PIC18F14K50 ;uncomment to use PIC18F14K50 ;configuration bits ; ;Background Debug: CONFIG DEBUG = ON ;Enabled ; CONFIG DEBUG = OFF ;Disabled ;Oscillator Selection bits: ; CONFIG FOSC = LP ; LP oscillator ; CONFIG FOSC = XT ; XT oscillator ; CONFIG FOSC = HS ; HS oscillator ; CONFIG FOSC = ERCCLKOUT ; External RC oscillator, CLKOUT function on OSC2 ; CONFIG FOSC = ECCLKOUTH ; EC, CLKOUT function on OSC2 (high) ; CONFIG FOSC = ECH ; EC (high) ; CONFIG FOSC = ERC ; External RC oscillator CONFIG FOSC = IRC ; Internal RC oscillator ; CONFIG FOSC = IRCCLKOUT ; Internal RC oscillator, CLKOUT function on OSC2 ; CONFIG FOSC = ECCLKOUTM ; EC, CLKOUT function on OSC2 (medium) ; CONFIG FOSC = ECM ; EC (medium) ; CONFIG FOSC = ECCLKOUTL ; EC, CLKOUT function on OSC2 (low) ; CONFIG FOSC = ECL ; EC (low) ; 4 X PLL Enable bit: CONFIG PLLEN = OFF ; PLL is under software control ; CONFIG PLLEN = ON ; Oscillator multiplied by 4 ; Primary Clock Enable Bit: CONFIG PCLKEN = OFF ; Primary clock is under software control ; CONFIG PCLKEN = ON ; Primary clock enabled ; Fail-Safe Clock Monitor Enable bit: CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled ; CONFIG FCMEN = ON ; Fail-Safe Clock Monitor enabled ; Internal/External Oscillator Switchover bit: CONFIG IESO = OFF ; Oscillator Switchover mode disabled ; CONFIG IESO = ON ; Oscillator Switchover mode enabled ; Power-up Timer Enable bit: ; CONFIG PWRTEN = ON ; PWRT enabled CONFIG PWRTEN = OFF ; PWRT disabled ; Brown-out Reset Enable bits: CONFIG BOREN = OFF ; Brown-out Reset disabled in hardware and software ; CONFIG BOREN = ON ; Brown-out Reset enabled and controlled by software (SBOREN is enabled) ; CONFIG BOREN = NOSLP ; Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled) ; CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled) ; Brown Out Voltage: ; CONFIG BORV = 30 ; VBOR set to 2.85 V nominal CONFIG BORV = 27 ; VBOR set to 2.5 V nominal ; CONFIG BORV = 22 ; VBOR set to 2.2 V nominal ; CONFIG BORV = 19 ; VBOR set to 1.9 V nominal ; Watchdog Timer Enable bit: CONFIG WDTEN = OFF ; WDT is controlled by SWDTEN bit of the WDTCON reg ; CONFIG WDTEN = ON ; WDT is always enabled. SWDTEN bit has no effect. ; Watchdog Timer Postscale Select bits: ; CONFIG WDTPS = 1 ; 1:1 ; CONFIG WDTPS = 2 ; 1:2 ; CONFIG WDTPS = 4 ; 1:4 ; CONFIG WDTPS = 8 ; 1:8 ; CONFIG WDTPS = 16 ; 1:16 ; CONFIG WDTPS = 32 ; 1:32 ; CONFIG WDTPS = 64 ; 1:64 ; CONFIG WDTPS = 128 ; 1:128 ; CONFIG WDTPS = 256 ; 1:256 ; CONFIG WDTPS = 512 ; 1:512 CONFIG WDTPS = 1024 ; 1:1024 x 4 ms = about 4 seconds ; CONFIG WDTPS = 2048 ; 1:2048 ; CONFIG WDTPS = 4096 ; 1:4096 ; CONFIG WDTPS = 8192 ; 1:8192 ; CONFIG WDTPS = 16384 ; 1:16384 ; CONFIG WDTPS = 32768 ; 1:32768 ; MCLR Pin Enable bit: ; CONFIG MCLRE = OFF ; RA3 input pin enabled CONFIG MCLR disabled CONFIG MCLRE = ON ; MCLR pin enabled, RA3 input pin disabled ; HFINTOSC Fast Start-up bit: CONFIG HFOFST = OFF ; The system clock is held off until the HFINTOSC is stable. ; CONFIG HFOFST = ON ; HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize. ; Stack Full/Underflow Reset Enable bit: CONFIG STVREN = OFF ; Stack full/underflow will not cause Reset ; CONFIG STVREN = ON ; Stack full/underflow will cause Reset ; Single-Supply ICSP Enable bit: CONFIG LVP = OFF ; Single-Supply ICSP disabled ; CONFIG LVP = ON ; Single-Supply ICSP enabled ; Boot Block Size Select Bit: CONFIG BBSIZ = OFF ; 1kW boot block size ; CONFIG BBSIZ = ON ; 2kW boot block size ; Extended Instruction Set Enable bit: CONFIG XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode) ; CONFIG XINST = ON ; Instruction set extension and Indexed Addressing mode enabled ; Code Protection bit: ; CONFIG CP0 = ON ; Block 0 code-protected CONFIG CP0 = OFF ; Block 0 not code-protected ; Code Protection bit: ; CONFIG CP1 = ON ; Block 1 code-protected CONFIG CP1 = OFF ; Block 1 not code-protected ; Boot Block Code Protection bit: ; CONFIG CPB = ON ; Boot block code-protected CONFIG CPB = OFF ; Boot block not code-protected ; Data EEPROM Code Protection bit: ; CONFIG CPD = ON ; Data EEPROM code-protected CONFIG CPD = OFF ; Data EEPROM not code-protected ; Write Protection bit: ; CONFIG WRT0 = ON ; Block 0 write-protected CONFIG WRT0 = OFF ; Block 0 not write-protected ; Write Protection bit: ; CONFIG WRT1 = ON ; Block 1 write-protected CONFIG WRT1 = OFF ; Block 1 not write-protected ; Boot Block Write Protection bit: ; CONFIG WRTB = ON ; Boot block write-protected CONFIG WRTB = OFF ; Boot block not write-protected ; Configuration Register Write Protection bit: ; CONFIG WRTC = ON ; Configuration regs write-protected CONFIG WRTC = OFF ; Configuration regs not write-protected ; Data EEPROM Write Protection bit: ; CONFIG WRTD = ON ; Data EEPROM write-protected CONFIG WRTD = OFF ; Data EEPROM not write-protected ; Table Read Protection bit: ; CONFIG EBTR0 = ON ; Block 0 protected from table reads executed in other blocks CONFIG EBTR0 = OFF ; Block 0 not protected from table reads executed in other blocks ; Table Read Protection bit: ; CONFIG EBTR1 = ON ; Block 1 protected from table reads executed in other blocks CONFIG EBTR1 = OFF ; Block 1 not protected from table reads executed in other blocks ; Boot Block Table Read Protection bit: ; CONFIG EBTRB = ON ; Boot block protected from table reads executed in other blocks CONFIG EBTRB = OFF ; Boot block not protected from table reads executed in other blocks ;****************************************************************************** ; MACRO ;****************************************************************************** ;move literal into register through W ;literal -> W -> register movlwf MACRO valeur, reg movlw valeur movwf reg ENDM ;start timer3 for N us count before overflow startTimer3Nus MACRO duration bcf T3CON, TMR3ON ;stops timer3 movlw high duration movwf TMR3H comf TMR3H, f ;complement high byte movlw low duration movwf TMR3L comf TMR3L, f ;complement low byte bcf PIR2, TMR3IF ;clear timer3 flag bsf T3CON, TMR3ON ;starts timer3 ENDM ;pause_10ms pause_10ms MACRO startTimer3Nus .10000 ;start timer3 for 10ms btfss PIR2, TMR3IF ;test timer3 overflow ? yes -> end macro goto $-2 ;no -> test again ENDM ;init table read adress initTableRead MACRO adrTable movlw high adrTable movwf TBLPTRH movlw low adrTable movwf TBLPTRL ENDM ;one clock pulse for spi com SCK_SPI_PULSE MACRO ;one clock (rising edge then falling edge) bsf SCK_SPI bcf SCK_SPI ENDM ;SPI write MACRO (adr = register, val = register) spi_write_fadr_fval MACRO fadr, fval SPI_ON movff fadr, spiReg call spi_write movff fval, spiReg call spi_write SPI_OFF ENDM ;SPI write MACRO (adr = register, val = literal) spi_write_fadr_lval MACRO fadr, lval SPI_ON movff fadr, spiReg call spi_write movlw lval movwf spiReg call spi_write SPI_OFF ENDM ;SPI write MACRO (adr = literal, val = register) spi_write_ladr_fval MACRO ladr, fval SPI_ON movlw ladr movwf spiReg call spi_write movff fval, spiReg call spi_write SPI_OFF ENDM ;SPI write MACRO (adr = literal, val = literal) spi_write_ladr_lval MACRO ladr, lval SPI_ON movlw ladr movwf spiReg call spi_write movlw lval movwf spiReg call spi_write SPI_OFF ENDM ;SPI write strobe command (lval = literal) spi_write_strobe_command MACRO lval SPI_ON movlw lval movwf spiReg call spi_write SPI_OFF ENDM ;SPI read MACRO (adr = registers) spi_read_fadr MACRO fadr SPI_ON movff fadr, spiReg bsf spiReg, 6 call spi_write nop call spi_read SPI_OFF ENDM ;SPI read MACRO (adr = literal) spi_read_ladr MACRO ladr SPI_ON movlw ladr movwf spiReg bsf spiReg, 6 call spi_write nop call spi_read SPI_OFF ENDM ;****************************************************************************** ; CONSTANTES ;****************************************************************************** ;LED #define LED PORTC, 6 #define LED_TRIS TRISC, 6 ;com spi A7105 #define CS_SPI PORTA,4 ;chip select SPI #define SCK_SPI PORTA,5 ;serial clock SPI #define SDIO_SPI PORTC,5 ;serial data input/output SPI #define GIO PORTC,0 ;GIO output A7105 #define CS_SPI_TRIS TRISA,4 ;chip select SPI #define SCK_SPI_TRIS TRISA,5 ;serial clock SPI #define SDIO_SPI_TRIS TRISC,5 ;serial data input/output SPI #define GIO_TRIS TRISC,0 ;GIO output A7105 #define SPI_ON bcf CS_SPI ;enable SPI A7105 #define SPI_OFF bsf CS_SPI ;desable SPI A7105 ;PPM input #define PPMinput PORTB, 6 #define PPMinput_TRIS TRISB, 6 ;****************************************************************************** ; VARIABLES ;****************************************************************************** CBLOCK 0x60 ; Sample GPR variable reg allocations ;init A7105 cptReg ;spi_write, spi_read cptBit, spiReg, adressReg ;write_eeprom_pic, read_eeprom_pic adr_pic, data_pic ;global variables channel ;tx channel no cpt256x ;counts bind packets sent cptServo ;counts servos output ;id0, id1, id2, id3 ;TX id found in current RX packet txid0, txid1, txid2, txid3 ;TX id cptChannel ;RX channel sequence counter (goes from 16 to 1) sequenceOffset ;offset sequence in tableSequence bind_packet ;bit0 = 1 -> bind packet, bit0 = 0 -> TX packet op1l, op1h ;Output Pulse duration for servo 1 to 8 (high,low) op2l, op2h ; = pulse duration in TX packet in us op3l, op3h op4l, op4h op5l, op5h op6l, op6h op7l, op7h op8l, op8h ip0l, ip0h ;(servo 0 does not exist but it simplify code) ip1l, ip1h ;Input Pulse duration for servo 1 to 8 (high,low) ip2l, ip2h ; = pulse duration read in PPM in us ip3l, ip3h ip4l, ip4h ip5l, ip5h ip6l, ip6h ip7l, ip7h ip8l, ip8h ENDC W_TEMP EQU 0x000 ; w reg for context saving (ACCESS) STATUS_TEMP EQU 0x001 ; status used for context saving BSR_TEMP EQU 0x002 ; bank select used for ISR context saving ;****************************************************************************** ; EEPROM INITIALIZATION ; ; The 18F14K22 has 256 bytes of non-volatile EEPROM starting at 0xF00000 ; ;****************************************************************************** DATAEE ORG 0xF00000 ; Starting address for EEPROM for 18F14K22 DE "MCHP" ; Place 'M' 'C' 'H' 'P' at address 0,1,2,3 ;****************************************************************************** ; RESET VECTOR ;****************************************************************************** RES_VECT ORG 0x0000 ; processor reset vector GOTO START ; go to beginning of program ;****************************************************************************** ; HIGH PRIORITY INTERRUPT VECTOR ;****************************************************************************** ISRH ORG 0x0008 ; Run the High Priority Interrupt Service Routine GOTO HIGH_ISR ;****************************************************************************** ; LOW PRIORITY INTERRUPT VECTOR ;****************************************************************************** ISRL ORG 0x0018 ; Run the High Priority Interrupt Service Routine GOTO LOW_ISR ;****************************************************************************** ; HIGH PRIORITY INTERRUPT SERVICE ROUTINE ;****************************************************************************** HIGH_ISR ; Insert High Priority ISR Here ; in "compatibility mode" (RCON,IPEN = 0) all interrupts goes here !!! ; timer2 sends TX packet(685Hz), ; timer0 counts interval between rising edges of PPM signal (PORTB6 interrupt on change) ;PPM isr PPM_isr btfss PPMinput ;if falling edge led off bcf LED ; btfss PPMinput ;if falling edge quit interrupt goto quit_PPM_isr bsf LED ;rising edge -> led on movf TMR0L, w ;must read low byte to update high byte of timer ! movlw 0xF0 ;test interval > 4.095ms andwf TMR0H, w ; btfss STATUS, Z ; LFSR 0, ip0l ;yes -> reset indirect register on servo 0 ;(servo 0 does not exist but it simplify code...) bcf T0CON, TMR0ON ;timer0 off movff TMR0L, POSTINC0 ;update current servo duration, low byte movff TMR0H, POSTINC0 ;update current servo duration, high byte clrf TMR0H ;reset timer 0 clrf TMR0L ; bsf T0CON, TMR0ON ;timer0 on quit_PPM_isr movf PORTB, f ;in order to have LATB = PORTB bcf INTCON, RABIF ;clear flag "interrupt on change port A&B" RETFIE FAST ;quit interrupt, automatic context saving (W, STATUS, BSR) ;****************************************************************************** ; LOW PRIORITY INTERRUPT SERVICE ROUTINE ;****************************************************************************** LOW_ISR ; Context Saving for Low ISR ;MOVWF W_TEMP ; save W reg ;MOVFF STATUS, STATUS_TEMP ; save status reg ;MOVFF BSR, BSR_TEMP ; save bankselect reg ; Insert Low Priority ISR Here ; Context Saving for Low ISR ;MOVFF BSR_TEMP, BSR ; restore bankselect reg ;MOVF W_TEMP, W ; restore W reg ;MOVFF STATUS_TEMP, STATUS ; restore status reg RETFIE ;**************************************** ; spi_write ; entrée: ; spiReg: valeur du registre à écrire ;**************************************** spi_write movlwf .8, cptBit boucleWriteReg btfss spiReg, 7 bcf SDIO_SPI btfsc spiReg, 7 bsf SDIO_SPI nop SCK_SPI_PULSE rlcf spiReg, f decfsz cptBit, f goto boucleWriteReg; return ;********************************* ; spi_read ; sortie: ; spiReg: valeur du registre lu ;********************************* spi_read bsf SDIO_SPI_TRIS ;SDIO input movlwf .8, cptBit clrf spiReg bcf STATUS, C boucleReadReg rlcf spiReg, f btfsc SDIO_SPI bsf spiReg, 0 SCK_SPI_PULSE decfsz cptBit, f goto boucleReadReg bcf SDIO_SPI_TRIS ;SDIO output return ;******************* ; write_packet_FIFO ;******************* write_packet_FIFO movlwf .8, cptServo ;copy input ppm values into output packetvalues for each servo LFSR 1, ip1l ;init indirect register 1 on ppm_in 1 LFSR 2, op1l ;init indirect register 2 on ppm_out 1 loopCopyInOut bcf INTCON, GIE ;disable interrupts movff POSTINC1, POSTINC2 ;ipxl -> opxl movff POSTINC1, POSTINC2 ;ipxh -> opxh bsf INTCON, GIE ;enable interrupts decfsz cptServo, f ;loop again ? goto loopCopyInOut SPI_ON movlwf 0x05, spiReg call spi_write btfsc bind_packet, 0 ;bind packet or TX packet ? movlw 0xAA ;bind packet -> 0xAA btfss bind_packet, 0 ;bind packet or TX packet ? movlw 0x55 ;TX packet -> 0x55 movwf spiReg ;sync = 0xAA or 0x55 call spi_write movff txid0, spiReg ;id0 TX (lsb) call spi_write movff txid1, spiReg ;id1 TX call spi_write movff txid2, spiReg ;id2 TX call spi_write movff txid3, spiReg ;id3 TX call spi_write movff op1l, spiReg ;pulse duration 1 call spi_write movff op1h, spiReg call spi_write movff op2l, spiReg ;pulse duration 2 call spi_write movff op2h, spiReg call spi_write movff op3l, spiReg ;pulse duration 3 call spi_write movff op3h, spiReg call spi_write movff op4l, spiReg ;pulse duration 4 call spi_write movff op4h, spiReg call spi_write movff op5l, spiReg ;pulse duration 5 call spi_write movff op5h, spiReg call spi_write movff op6l, spiReg ;pulse duration 6 call spi_write movff op6h, spiReg call spi_write movff op7l, spiReg ;pulse duration 7 call spi_write movff op7h, spiReg call spi_write movff op8l, spiReg ;pulse duration 8 call spi_write movff op8h, spiReg call spi_write SPI_OFF return ;************** ; init_A7105 ;************** init_A7105 ;reset A7105 spi_write_ladr_lval 0x00, 0x00 ;ID A7105 <- 0x2AC57554 SPI_ON movlwf 0x06, spiReg call spi_write movlwf 0x54, spiReg ;id0 call spi_write movlwf 0x75, spiReg ;id1 call spi_write movlwf 0xC5, spiReg ;id2 call spi_write movlwf 0x2A, spiReg ;id3 call spi_write SPI_OFF ;read ID A7105 -> id0..id3 ;SPI_ON ;movff 0x46, spiReg ;call spi_write ;call spi_read ;movff spiReg, id0 ;call spi_read ;movff spiReg, id1 ;call spi_read ;movff spiReg, id2 ;call spi_read ;movff spiReg, id3 ;SPI_OFF ;Put the A7105 into the 'Standby' state (Strobe = 0xa0) spi_write_strobe_command 0xA0 ;A0 -> standby mode ;init A7105 regs initTableRead tableInitReg movlwf 0xFF, adressReg ;init reg adress -1 movlwf 0x33, cptReg ;init loop counter BoucleInitReg incf adressReg, f ;increment reg adress tblrd*+ ;read byte and increment table adress incf TABLAT, w ;test byte == 0xFF ? bz BoucleInitReg ;yes -> skip reg init spi_write_fadr_fval adressReg, TABLAT decfsz cptReg, f ;test loop end ? goto BoucleInitReg ;no -> loop ;IF Filter Bank Calibration spi_write_ladr_lval 0x02, 0x01 waitCalibrationFilter ;wait calibration end spi_read_ladr 0x02 btfsc spiReg, 0 goto waitCalibrationFilter ;test calibration ok ? ;VCO Current Calibration spi_write_ladr_lval 0x24, 0x013 ;VCO Bank Calibration spi_write_ladr_lval 0x26, 0x03B ;VCO Bank Calibrate channel 0x00? spi_write_ladr_lval 0x0F, 0x00 ;Set Channel 0 spi_write_ladr_lval 0x02, 0x02 ;VCO Calibration waitCalibrationVCO ;wait calibration end spi_read_ladr 0x02 btfsc spiReg, 1 goto waitCalibrationVCO ;test calibration ok ? ;VCO Bank Calibrate channel 0xa0? spi_write_ladr_lval 0x0F, 0xA0 ;Set Channel 0xa0 spi_write_ladr_lval 0x02, 0x02 ;VCO Calibration waitCalibrationVCObis ;wait calibration end spi_read_ladr 0x02 btfsc spiReg, 1 goto waitCalibrationVCObis ;test calibration ok ? ;Reset VCO Band calibration spi_write_ladr_lval 0x25, 0x08 return ;************** ; bind_RX ;************** bind_RX ;send bind packet for about 2,5s on channel 0 ;(256 loops, 10ms each loop) clrf cpt256x ;init bind packet counter bsf bind_packet, 0 ;TX packet is a "bind packet" loopSendBindPacket spi_write_strobe_command 0xA0 ;A0 -> standby mode spi_write_strobe_command 0xE0 ;E0 -> reset TX FIFO spi_write_ladr_lval 0x0F, 0x01 ;Set Channel 1 call write_packet_FIFO ;init packet values spi_write_strobe_command 0xD0 ;D0 -> get into TX mode pause_10ms ;wait for 10ms btfsc cpt256x, 3 ;12Hz blinking LED while binding bcf LED ;LED OFF btfss cpt256x, 3 bsf LED ;LED ON decfsz cpt256x, f ;decremente time out counter, roll-off? goto loopSendBindPacket return ;*********************** ; readNextChannelNumber ;*********************** readNextChannelNumber decfsz cptChannel ;decrement channel counter goto tableReadChannel ;cptChannel > 0 => skip sequence reset resetChannelSequence movlwf .16, cptChannel ;cptChannel = 16 initTableRead tableChannels ;load adress of tableChannels movf sequenceOffset, w addwf TBLPTRL, f ;add sequence offset in table btfsc STATUS, C incf TBLPTRH, f tableReadChannel tblrd*+ ;read channel number in table and increment table adress movff TABLAT, channel swapf txid0, w ;substract txid0 high nibble from channel number andlw 0x0F subwf channel, f return ;************** ;************** ; MAIN PROGRAM ;************** ;************** START ; set internal oscillator speed Fosc=16Mhz ; => internal instruction cycle speed = Fosc/4 = 4Mhz ; 111=16MHz, 110=8 MHz, 101=4MHz, 100=2MHz, 011= 1MHz(default after reset) ; 010=500kHz, 001=250kHz, 000=32kHz (LFINTOSC) bsf OSCCON, IRCF2 bsf OSCCON, IRCF1 bsf OSCCON, IRCF0 ;wait frequency is stable waitFreqStable btfss OSCCON, HFIOFS goto waitFreqStable ;config port A,B,C clrf PORTA clrf PORTB clrf PORTC bsf LED ;LED ON bcf LED_TRIS bsf CS_SPI ;CS default HIGH bcf CS_SPI_TRIS ;CS digital output bsf SDIO_SPI ;SDIO default HIGH bcf SDIO_SPI_TRIS ;SDIO digital output bcf SCK_SPI ;SCK default LOW bcf SCK_SPI_TRIS ;SCK digital output ;disable analog inputs to enable digital inputs clrf ANSEL clrf ANSELH ;set timer0 ( counts servos pulse duration, 1us step ) ;16 bit timer clrf T0CON ; reset timer0 control register bsf T0CON, T0PS0 ; prescaler 1:4 (1us period) bcf INTCON, TMR0IF ; clear flag interrupt timer0 ;set timer2 ( sends TX packet every 1,46ms = 685hz interrupt ) ;8 bits timer with comparator register movlwf .72, PR2 ; Timer2 comparator register => 4Mhz/16/(72+1)/5=685hz clrf T2CON ; reset timer2 control register bsf T2CON, T2OUTPS2 ; 1:5 postscaler bsf T2CON, T2CKPS1 ; 1:16 prescaler bcf PIR1, TMR2IF ; clear flag interrupt timer2 ;bsf PIE1, TMR2IE ; enable interrupt timer2 ;bsf IPR1, TMR2IP ; high priority ;bsf INTCON, PEIE ; enable low interrupt (usefull ?) ;bsf INTCON, GIE ; enable global interrupt ;set timer3 ( count delays ) ;16 bit timer clrf T3CON ; reset timer3 control register bsf T3CON, RD16 ; set TMR3 bsf T3CON, T3CKPS1 ; 1:4 prescaler (1us period) bcf PIR2, TMR3IF ; clear flag interrupt timer3 ;init servo position middle movlw low .1500 ;1500us (low byte) movwf ip1l movwf ip2l movwf ip3l movwf ip4l movwf ip5l movwf ip6l movwf ip7l movwf ip8l movlw high .1500 ;1500us (high byte) movwf ip1h movwf ip2h movwf ip3h movwf ip4h movwf ip5h movwf ip6h movwf ip7h movwf ip8h ;wait 10ms to be sure A7105 wake up pause_10ms ;init A7105 call init_A7105 ;init TX id 0x30 00 00 06 movlwf 0x06, txid0 movlwf 0x00, txid1 movlwf 0x00, txid2 movlwf 0x30, txid3 ;bind with RX call bind_RX clrf bind_packet ;next TX packets are not "bind packet" ;init table read channel sequence swapf txid0, w ;compute sequenceOffset <- (id0 & 0x0F)*16 andlw 0xF0 movwf sequenceOffset movlwf 0x01, cptChannel ;init channel counter (goes from 16 to 1) ;enable PPM decode with interrupt & timer 0 bsf INTCON, RABIE ;enable "interrupt on change" for port A & B bsf IOCB, 6 ;enable "interrupt on change" portb, 6 = PPM input bsf T0CON, TMR0ON ;timer0 on bsf INTCON, GIE ;enable global interrupt ;starts timer 2 at 685Hz bsf T2CON, TMR2ON ;************ ; MAIN LOOP ;************ ;poll timer 2 flag (685hz) waitFlagTimer2 btfss PIR1, TMR2IF goto waitFlagTimer2 ;clear flag and send packet bcf PIR1, TMR2IF spi_write_strobe_command 0xA0 ;A0 -> standby mode spi_write_strobe_command 0xE0 ;E0 -> reset TX FIFO call readNextChannelNumber ;read next channel number in tableChannels spi_write_ladr_fval 0x0F, channel ;set channel call write_packet_FIFO ;write packet into FIFO spi_write_strobe_command 0xD0 ;D0 -> get into TX mode goto waitFlagTimer2 ;********************************************************** ;*********************** TABLES *************************** ;********************************************************** tableInitReg db 0xFF, 0x42, 0x00, 0x14, 0x00, 0xFF, 0xFF ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50 db 0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f db 0x13, 0xc3, 0x00, 0xFF, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00 db 0x01, 0x0f, 0xFF ;TX channels numbers ... tableChannels db 0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0 db 0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a db 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82 db 0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a db 0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96 db 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28 db 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64 db 0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50 db 0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64 db 0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50 db 0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64 db 0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46 db 0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82 db 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46 db 0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64 db 0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46 ;*********************** F I N ********************** END