Advertisement
Guest User

Untitled

a guest
Sep 13th, 2015
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 23.26 KB | None | 0 0
  1. /*************************************************************
  2. ************* nRF24 Cheerson CX-10 Tx Code  ******************
  3. *************     (Green & Blue boards)     ******************
  4. **************************************************************
  5.  
  6. by goebish on RCgroups.com
  7.  
  8. Thanks to:
  9. PhracturedBlue, victzh, hexfet, closedsink, midelic, Hasi ...
  10.  
  11. This program is free software: you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation, either version 3 of the License, or
  14. (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License.
  22. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24.  
  25. #include <util/atomic.h>
  26.  
  27. ///////////////////
  28. // pinout
  29.  
  30. #define PPM_pin   2             // PPM in
  31. //Spi Comm.pins with nRF24l01
  32. #define MOSI_pin  5             // MOSI-D5
  33. #define SCK_pin   4             // SCK-D4
  34. #define CS_pin    6             // CS-D6
  35. #define CE_pin    3             // CE-D3
  36. #define MISO_pin  7             // MISO-D7
  37.  
  38. //---------------------------------
  39. // spi outputs
  40. #define  CS_on PORTD |= 0x40    // PORTD6
  41. #define  CS_off PORTD &= 0xBF   // PORTD6
  42. #define  CE_on PORTD |= 0x08    // PORTD3
  43. #define  CE_off PORTD &= 0xF7   // PORTD3
  44. //
  45. #define  SCK_on PORTD |= 0x10   // PORTD4
  46. #define  SCK_off PORTD &= 0xEF  // PORTD4
  47. #define  MOSI_on PORTD |= 0x20  // PORTD5
  48. #define  MOSI_off PORTD &= 0xDF // PORTD5
  49. // spi input
  50. #define  MISO_on (PIND & 0x80)  // PORTD7
  51.  
  52. //
  53. #define _NOP() __asm__ __volatile__("nop")
  54. #define BV(bit) (1 << bit)
  55.  
  56. #define GREEN_PACKET_LENGTH 15
  57. #define BLUE_PACKET_LENGTH 19
  58. #define RF_BIND_CHANNEL 0x02
  59. #define BIND_COUNT 3000
  60. #define NUM_RF_CHANNELS    4
  61. #define BLUE_PACKET_PERIOD 6000
  62. #define GREEN_PACKET_PERIOD 1500
  63. static const uint8_t tx_rx_id[] = {0xCC,0xCC,0xCC,0xCC,0xCC};
  64.  
  65. #define PPM_MIN 1000
  66. #define PPM_MIN_COMMAND 1250
  67. #define PPM_MID 1500
  68. #define PPM_MAX_COMMAND 1750
  69. #define PPM_MAX 2000
  70.  
  71. // PPM stream settings
  72. #define CHANNELS 6
  73. enum chan_order{  // TAER -> Spektrum chan order
  74.     THROTTLE,
  75.     AILERON,
  76.     ELEVATOR,
  77.     RUDDER,
  78.     AUX1,  // mode (3 positions, highest position is headless on CX10-A)
  79.     AUX2,  // flip control
  80. };
  81.  
  82. enum{
  83.     CX10_GREEN,
  84.     CX10_BLUE, // also compatible with CX10-A, CX12
  85. };
  86.  
  87. ////////////////
  88. // Variables
  89. static uint8_t board_type = CX10_GREEN; // board type, change as required
  90.  
  91. static uint8_t txid[4]; // transmitter ID
  92. static uint8_t freq[4]; // frequency hopping table
  93. static uint8_t packet[BLUE_PACKET_LENGTH];
  94. static uint8_t packet_length;
  95. static uint32_t packet_period;
  96. volatile uint16_t Servo_data[CHANNELS] = {0,};
  97. static uint16_t ppm[CHANNELS] = {PPM_MIN,PPM_MIN,PPM_MIN,PPM_MIN,};
  98. static uint8_t current_chan = 0;
  99. static uint8_t ledPin = 13;
  100.  
  101. ////////////////
  102. // nRF24 Register map
  103. enum {
  104.     NRF24L01_00_CONFIG      = 0x00,
  105.     NRF24L01_01_EN_AA       = 0x01,
  106.     NRF24L01_02_EN_RXADDR   = 0x02,
  107.     NRF24L01_03_SETUP_AW    = 0x03,
  108.     NRF24L01_04_SETUP_RETR  = 0x04,
  109.     NRF24L01_05_RF_CH       = 0x05,
  110.     NRF24L01_06_RF_SETUP    = 0x06,
  111.     NRF24L01_07_STATUS      = 0x07,
  112.     NRF24L01_08_OBSERVE_TX  = 0x08,
  113.     NRF24L01_09_CD          = 0x09,
  114.     NRF24L01_0A_RX_ADDR_P0  = 0x0A,
  115.     NRF24L01_0B_RX_ADDR_P1  = 0x0B,
  116.     NRF24L01_0C_RX_ADDR_P2  = 0x0C,
  117.     NRF24L01_0D_RX_ADDR_P3  = 0x0D,
  118.     NRF24L01_0E_RX_ADDR_P4  = 0x0E,
  119.     NRF24L01_0F_RX_ADDR_P5  = 0x0F,
  120.     NRF24L01_10_TX_ADDR     = 0x10,
  121.     NRF24L01_11_RX_PW_P0    = 0x11,
  122.     NRF24L01_12_RX_PW_P1    = 0x12,
  123.     NRF24L01_13_RX_PW_P2    = 0x13,
  124.     NRF24L01_14_RX_PW_P3    = 0x14,
  125.     NRF24L01_15_RX_PW_P4    = 0x15,
  126.     NRF24L01_16_RX_PW_P5    = 0x16,
  127.     NRF24L01_17_FIFO_STATUS = 0x17,
  128.     NRF24L01_1C_DYNPD       = 0x1C,
  129.     NRF24L01_1D_FEATURE     = 0x1D,
  130.     //Instructions
  131.     NRF24L01_61_RX_PAYLOAD  = 0x61,
  132.     NRF24L01_A0_TX_PAYLOAD  = 0xA0,
  133.     NRF24L01_E1_FLUSH_TX    = 0xE1,
  134.     NRF24L01_E2_FLUSH_RX    = 0xE2,
  135.     NRF24L01_E3_REUSE_TX_PL = 0xE3,
  136.     NRF24L01_50_ACTIVATE    = 0x50,
  137.     NRF24L01_60_R_RX_PL_WID = 0x60,
  138.     NRF24L01_B0_TX_PYLD_NOACK = 0xB0,
  139.     NRF24L01_FF_NOP         = 0xFF,
  140.     NRF24L01_A8_W_ACK_PAYLOAD0 = 0xA8,
  141.     NRF24L01_A8_W_ACK_PAYLOAD1 = 0xA9,
  142.     NRF24L01_A8_W_ACK_PAYLOAD2 = 0xAA,
  143.     NRF24L01_A8_W_ACK_PAYLOAD3 = 0xAB,
  144.     NRF24L01_A8_W_ACK_PAYLOAD4 = 0xAC,
  145.     NRF24L01_A8_W_ACK_PAYLOAD5 = 0xAD,
  146. };
  147.  
  148. // Bit mnemonics
  149. enum {
  150.     NRF24L01_00_MASK_RX_DR  = 6,
  151.     NRF24L01_00_MASK_TX_DS  = 5,
  152.     NRF24L01_00_MASK_MAX_RT = 4,
  153.     NRF24L01_00_EN_CRC      = 3,
  154.     NRF24L01_00_CRCO        = 2,
  155.     NRF24L01_00_PWR_UP      = 1,
  156.     NRF24L01_00_PRIM_RX     = 0,
  157.  
  158.     NRF24L01_07_RX_DR       = 6,
  159.     NRF24L01_07_TX_DS       = 5,
  160.     NRF24L01_07_MAX_RT      = 4,
  161.  
  162.     NRF2401_1D_EN_DYN_ACK   = 0,
  163.     NRF2401_1D_EN_ACK_PAY   = 1,
  164.     NRF2401_1D_EN_DPL       = 2,
  165. };
  166.  
  167. // Bitrates
  168. enum {
  169.     NRF24L01_BR_1M = 0,
  170.     NRF24L01_BR_2M,
  171.     NRF24L01_BR_250K,
  172.     NRF24L01_BR_RSVD
  173. };
  174.  
  175. enum TXRX_State {
  176.     TXRX_OFF,
  177.     TX_EN,
  178.     RX_EN,
  179. };
  180.  
  181. /////////////////
  182. // setup
  183. void setup() {
  184.     randomSeed((analogRead(A0) & 0x1F) | (analogRead(A1) << 5));
  185.     for(uint8_t i=0;i<4;i++) {
  186.         txid[i] = random();
  187.     }
  188.     pinMode(ledPin, OUTPUT);
  189.     //PPM input from transmitter port
  190.     pinMode(PPM_pin, INPUT);
  191.     //RF module pins
  192.     pinMode(MOSI_pin, OUTPUT);
  193.     pinMode(SCK_pin, OUTPUT);
  194.     pinMode(CS_pin, OUTPUT);
  195.     pinMode(CE_pin, OUTPUT);
  196.     pinMode(MISO_pin, INPUT);
  197.     digitalWrite(ledPin, LOW);//start LED off
  198.     CS_on;//start CS high
  199.     CE_on;//start CE high
  200.     MOSI_on;//start MOSI high
  201.     SCK_on;//start sck high
  202.     delay(70);//wait 70ms
  203.     CS_off;//start CS low
  204.     CE_off;//start CE low
  205.     MOSI_off;//start MOSI low
  206.     SCK_off;//start sck low
  207.     delay(100);
  208.     CS_on;//start CS high
  209.     delay(10);
  210.    
  211.     NRF24L01_Reset();
  212.     NRF24L01_Initialize();
  213.     delay(150);
  214.     CX10_init();
  215.     delay(50);
  216.     //Bind to Receiver
  217.     CX10_bind();
  218. }
  219.  
  220. ///////////////
  221. // main loop
  222. void loop() {
  223.     uint32_t timeout;
  224.    
  225.     timeout = process_CX10();
  226.     while(micros() < timeout)
  227.     {   };
  228. }
  229.  
  230. ///////////////
  231. // CX10 functions
  232. void CX10_init()
  233. {
  234.     txid[1] %= 0x30;
  235.     freq[0] = (txid[0] & 0x0F) + 0x03;
  236.     freq[1] = (txid[0] >> 4) + 0x16;
  237.     freq[2] = (txid[1] & 0x0F) + 0x2D;
  238.     freq[3] = (txid[1] >> 4) + 0x40;
  239.    
  240.     if(board_type == CX10_BLUE) {
  241.         packet_length = BLUE_PACKET_LENGTH;
  242.         packet_period = BLUE_PACKET_PERIOD;
  243.         for(uint8_t i=0; i<4; i++)
  244.             packet[5+i] = 0xff;
  245.     }
  246.     else if(board_type == CX10_GREEN) {
  247.         packet_length = GREEN_PACKET_LENGTH;
  248.         packet_period = GREEN_PACKET_PERIOD;
  249.     }          
  250.        
  251.     current_chan = 0;
  252.     NRF24L01_Reset();
  253.     NRF24L01_Initialize();
  254.     NRF24L01_SetTxRxMode(TX_EN);
  255.     //delay(1000);
  256.     //XN297_SetTXAddr(tx_rx_id,5);
  257.     //XN297_SetRXAddr(tx_rx_id,5);
  258.     delay(500);
  259.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  260.     NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
  261.     NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
  262.     NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x77);
  263.     NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x22);
  264.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x10);
  265.     NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);
  266.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
  267.     NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
  268.     NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
  269.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x4e);
  270.     NRF24L01_WriteReg(0x1D, 0x00);
  271.     NRF24L01_WriteReg(0x50, 0x73);
  272.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  273.  
  274.     NRF24L01_Activate(0x53); // magic for BK2421 bank switch
  275.  
  276.     NRF24L01_WriteRegisterMulti(0x00, (u8 *) "\x40\x4B\x01\xE2", 4);
  277.     NRF24L01_WriteRegisterMulti(0x01, (u8 *) "\xC0\x4B\x00\x00", 4);
  278.     NRF24L01_WriteRegisterMulti(0x02, (u8 *) "\xD0\xFC\x8C\x02", 4);
  279.     NRF24L01_WriteRegisterMulti(0x03, (u8 *) "\x99\x00\x39\x21", 4);
  280.     NRF24L01_WriteRegisterMulti(0x04, (u8 *) "\xD9\x96\x8A\xDB", 4);
  281.     NRF24L01_WriteRegisterMulti(0x05, (u8 *) "\x24\x06\x0F\xB6", 4);
  282.     NRF24L01_WriteRegisterMulti(0x06, (u8 *) "\x00\x00\x00\x00", 4);
  283.     NRF24L01_WriteRegisterMulti(0x07, (u8 *) "\x00\x00\x00\x00", 4);
  284.     NRF24L01_WriteRegisterMulti(0x08, (u8 *) "\x00\x00\x00\x00", 4);
  285.     NRF24L01_WriteRegisterMulti(0x09, (u8 *) "\x00\x00\x00\x00", 4);
  286.     NRF24L01_WriteRegisterMulti(0x0A, (u8 *) "\x00\x00\x00\x00", 4);
  287.     NRF24L01_WriteRegisterMulti(0x0B, (u8 *) "\x00\x00\x00\x00", 4);
  288.     NRF24L01_WriteRegisterMulti(0x0C, (u8 *) "\x00\x12\x73\x00", 4);
  289.     NRF24L01_WriteRegisterMulti(0x0D, (u8 *) "\x36\xB4\x80\x00", 4);
  290.     NRF24L01_WriteRegisterMulti(0x0E, (u8 *) "\x41\x20\x08\x04\x81\x20\xCF\xF7\xFE\xFF\xFF", 11);
  291.    
  292.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  293.     NRF24L01_Activate(0x53);
  294.  
  295.     // write 00
  296.     // write 00
  297.  
  298.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\xAB\xAC\xAD\xAE\xAF", 5);
  299.    
  300.     // here its actually transmiting something .... but i am guessing we can skip that
  301.     delay(500);
  302. }
  303.  
  304. void CX10_bind()
  305. {
  306.     uint16_t counter=BIND_COUNT;
  307.     bool bound=false;
  308.     uint32_t timeout;
  309.  
  310.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  311.     NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
  312.     NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
  313.     NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x77);
  314.     NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x27);
  315.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x10);
  316.     NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);
  317.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
  318.     NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
  319.     NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
  320.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x4e);
  321.     NRF24L01_WriteReg(0x1D, 0x00);
  322.     NRF24L01_WriteReg(0x50, 0x73);
  323.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  324.  
  325.     NRF24L01_Activate(0x53); // magic for BK2421 bank switch
  326.  
  327.     NRF24L01_WriteRegisterMulti(0x00, (u8 *) "\x40\x4B\x01\xE2", 4);
  328.     NRF24L01_WriteRegisterMulti(0x01, (u8 *) "\xC0\x4B\x00\x00", 4);
  329.     NRF24L01_WriteRegisterMulti(0x02, (u8 *) "\xD0\xFC\x8C\x02", 4);
  330.     NRF24L01_WriteRegisterMulti(0x03, (u8 *) "\x99\x00\x39\x21", 4);
  331.     NRF24L01_WriteRegisterMulti(0x04, (u8 *) "\xF9\x96\x8A\xDB", 4);
  332.     NRF24L01_WriteRegisterMulti(0x05, (u8 *) "\x24\x06\x0F\xB6", 4);
  333.     NRF24L01_WriteRegisterMulti(0x06, (u8 *) "\x00\x00\x00\x00", 4);
  334.     NRF24L01_WriteRegisterMulti(0x07, (u8 *) "\x00\x00\x00\x00", 4);
  335.     NRF24L01_WriteRegisterMulti(0x08, (u8 *) "\x00\x00\x00\x00", 4);
  336.     NRF24L01_WriteRegisterMulti(0x09, (u8 *) "\x00\x00\x00\x00", 4);
  337.     NRF24L01_WriteRegisterMulti(0x0A, (u8 *) "\x00\x00\x00\x00", 4);
  338.     NRF24L01_WriteRegisterMulti(0x0B, (u8 *) "\x00\x00\x00\x00", 4);
  339.     NRF24L01_WriteRegisterMulti(0x0C, (u8 *) "\x00\x12\x73\x00", 4);
  340.     NRF24L01_WriteRegisterMulti(0x0D, (u8 *) "\x36\xB4\x80\x00", 4);
  341.     NRF24L01_WriteRegisterMulti(0x0E, (u8 *) "\x41\x20\x08\x04\x81\x20\xCF\xF7\xFE\xFF\xFF", 11);
  342.    
  343.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  344.     NRF24L01_Activate(0x53);
  345.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\x47\x57\x30\xF4\xA1", 5);
  346.  
  347.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x21);
  348.     //NRF24L01_FlushTx();
  349.  
  350.     NRF24L01_WritePayload((u8 *) "\x00\x00\x00\x00\x00\x45\x00\x21\x00\xb9", 10);
  351.    
  352.    
  353.     /*while(!bound) {
  354.         NRF24L01_SetTxRxMode(TX_EN);
  355.         XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
  356.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
  357.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  358.         NRF24L01_FlushTx();
  359.         CX10_Write_Packet(0xAA); // send bind packet
  360.         switch(board_type) {
  361.             case CX10_GREEN:
  362.                 if(counter==0)
  363.                     bound = true;
  364.                 delayMicroseconds(packet_period);
  365.                 break;
  366.             case CX10_BLUE:    
  367.                 delay(1);
  368.                 CE_off;
  369.                 NRF24L01_SetTxRxMode(RX_EN);
  370.                 NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  371.                 NRF24L01_FlushRx();
  372.                 XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_PRIM_RX));
  373.                 CE_on;
  374.                 timeout = millis()+5;
  375.                 while(millis()<timeout) {
  376.                     if(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) { // data received from aircraft
  377.                         XN297_ReadPayload(packet, packet_length);
  378.                         if( packet[9] == 0x01)
  379.                             bound = true;
  380.                         break;
  381.                     }
  382.                 }                
  383.                 break;
  384.         }
  385.         digitalWrite(ledPin, counter-- & 0x10);
  386.     }
  387.     digitalWrite(ledPin, HIGH);*/
  388. }
  389.  
  390. uint32_t process_CX10()
  391. {
  392.     uint32_t nextPacket = micros() + 5000;
  393.     //XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
  394.     //NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);     // Clear data ready, data sent, and retransmit
  395.     //NRF24L01_FlushTx();
  396.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x21);
  397.     current_chan %= NUM_RF_CHANNELS;
  398.  
  399.     NRF24L01_WritePayload((u8 *) "\x00\x00\x00\x00\x00\x45\x00\x21\x00\xb9", 10);
  400.     //CX10_Write_Packet(0x55);
  401.     return nextPacket;
  402. }
  403.  
  404.  
  405. ///////////////
  406. // SPI
  407.  
  408. void Read_Packet(uint8_t *data, uint8_t length)
  409. {
  410.     uint8_t i;
  411.     CS_off;
  412.     _spi_write(0x61); // Read RX payload
  413.     for (i=0;i<length;i++) {
  414.         data[i]=_spi_read();
  415.     }
  416.     CS_on;
  417. }
  418.  
  419. uint8_t _spi_write(uint8_t command)
  420. {
  421.     uint8_t result=0;
  422.     uint8_t n=8;
  423.     SCK_off;
  424.     MOSI_off;
  425.     while(n--) {
  426.         if(command & 0x80)
  427.             MOSI_on;
  428.         else
  429.             MOSI_off;
  430.         if(MISO_on)
  431.             result |= 0x01;
  432.         SCK_on;
  433.         _NOP();
  434.         SCK_off;
  435.         command = command << 1;
  436.         result = result << 1;
  437.     }
  438.     MOSI_on;
  439.     return result;
  440. }
  441.  
  442. void _spi_write_address(uint8_t address, uint8_t data)
  443. {
  444.     CS_off;
  445.     _spi_write(address);
  446.     _NOP();
  447.     _spi_write(data);
  448.     CS_on;
  449. }
  450.  
  451. uint8_t _spi_read()
  452. {
  453.     uint8_t result=0;
  454.     uint8_t i;
  455.     MOSI_off;
  456.     _NOP();
  457.     for(i=0;i<8;i++) {
  458.         if(MISO_on) // if MISO is HIGH
  459.             result = (result<<1)|0x01;
  460.         else
  461.             result = result<<1;
  462.         SCK_on;
  463.         _NOP();
  464.         SCK_off;
  465.         _NOP();
  466.     }
  467.     return result;
  468. }
  469.  
  470. uint8_t _spi_read_address(uint8_t address)
  471. {
  472.     uint8_t result;
  473.     CS_off;
  474.     _spi_write(address);
  475.     result = _spi_read();
  476.     CS_on;
  477.     return(result);
  478. }
  479.  
  480. ///////////////
  481. // nRF24
  482.  
  483. /* Instruction Mnemonics */
  484. #define R_REGISTER    0x00
  485. #define W_REGISTER    0x20
  486. #define REGISTER_MASK 0x1F
  487. #define ACTIVATE      0x50
  488. #define R_RX_PL_WID   0x60
  489. #define R_RX_PAYLOAD  0x61
  490. #define W_TX_PAYLOAD  0xA0
  491. #define W_ACK_PAYLOAD 0xA8
  492. #define FLUSH_TX      0xE1
  493. #define FLUSH_RX      0xE2
  494. #define REUSE_TX_PL   0xE3
  495. #define NOP           0xFF
  496.  
  497. static uint8_t rf_setup;
  498.  
  499. uint8_t NRF24L01_WriteReg(uint8_t address, uint8_t data)
  500. {
  501.     CS_off;
  502.     _spi_write_address(address | W_REGISTER, data);
  503.     CS_on;
  504.     return 1;
  505. }
  506.  
  507. void NRF24L01_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t len)
  508. {
  509.     delayMicroseconds(5);
  510.     CS_off;
  511.     _spi_write(address | W_REGISTER);
  512.     for(uint8_t i=0;i<len;i++)
  513.         _spi_write(data[i]);
  514.     CS_on;
  515.     delayMicroseconds(5);
  516. }
  517.  
  518. void NRF24L01_Initialize()
  519. {
  520.     rf_setup = 0x0F;
  521. }
  522.  
  523. uint8_t NRF24L01_FlushTx()
  524. {
  525.     return Strobe(FLUSH_TX);
  526. }
  527.  
  528. uint8_t NRF24L01_FlushRx()
  529. {
  530.     return Strobe(FLUSH_RX);
  531. }
  532.  
  533. static uint8_t Strobe(uint8_t state)
  534. {
  535.     uint8_t result;
  536.     CS_off;
  537.     result = _spi_write(state);
  538.     CS_on;
  539.     return result;
  540. }
  541.  
  542. uint8_t NRF24L01_WritePayload(uint8_t *data, uint8_t length)
  543. {
  544.     CE_off;
  545.     CS_off;
  546.     _spi_write(W_TX_PAYLOAD);
  547.     for(uint8_t i=0; i<length; i++)
  548.         _spi_write(data[i]);
  549.     CS_on;
  550.     CE_on; // transmit
  551.     return 1;
  552. }
  553.  
  554. uint8_t NRF24L01_ReadPayload(uint8_t *data, uint8_t length)
  555. {
  556.     uint8_t i;
  557.     CS_off;
  558.     _spi_write(R_RX_PAYLOAD); // Read RX payload
  559.     for (i=0;i<length;i++) {
  560.         data[i]=_spi_read();
  561.     }
  562.     CS_on;
  563.     return 1;
  564. }
  565.  
  566. uint8_t NRF24L01_ReadReg(uint8_t reg)
  567. {
  568.     CS_off;
  569.     uint8_t data = _spi_read_address(reg);
  570.     CS_on;
  571.     return data;
  572. }
  573.  
  574. uint8_t NRF24L01_Activate(uint8_t code)
  575. {
  576.     CS_off;
  577.     _spi_write(ACTIVATE);
  578.     _spi_write(code);
  579.     CS_on;
  580.     return 1;
  581. }
  582.  
  583. void NRF24L01_SetTxRxMode(uint8_t mode)
  584. {
  585.     if(mode == TX_EN) {
  586.         CE_off;
  587.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  588.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  589.                   | (1 << NRF24L01_07_TX_DS)
  590.                   | (1 << NRF24L01_07_MAX_RT));
  591.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  592.                     (1 << NRF24L01_00_EN_CRC)   // switch to TX mode
  593.                   | (1 << NRF24L01_00_CRCO)
  594.                   | (1 << NRF24L01_00_PWR_UP));
  595.         delayMicroseconds(130);
  596.         CE_on;
  597.     } else if (mode == RX_EN) {
  598.         CE_off;
  599.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);        // reset the flag(s)
  600.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);        // switch to RX mode
  601.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  602.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  603.                   | (1 << NRF24L01_07_TX_DS)
  604.                   | (1 << NRF24L01_07_MAX_RT));
  605.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  606.                     (1 << NRF24L01_00_EN_CRC)   // switch to RX mode
  607.                   | (1 << NRF24L01_00_CRCO)
  608.                   | (1 << NRF24L01_00_PWR_UP)
  609.                   | (1 << NRF24L01_00_PRIM_RX));
  610.         delayMicroseconds(130);
  611.         CE_on;
  612.     } else {
  613.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)); //PowerDown
  614.         CE_off;
  615.     }
  616. }
  617.  
  618. uint8_t NRF24L01_Reset()
  619. {
  620.     NRF24L01_FlushTx();
  621.     NRF24L01_FlushRx();
  622.     uint8_t status1 = Strobe(0xFF); // NOP
  623.     uint8_t status2 = NRF24L01_ReadReg(0x07);
  624.     NRF24L01_SetTxRxMode(TXRX_OFF);
  625.     return (status1 == status2 && (status1 & 0x0f) == 0x0e);
  626. }
  627.  
  628. // Power is in range 0..3 for nRF24L01
  629. uint8_t NRF24L01_SetPower(uint8_t power)
  630. {
  631.     rf_setup = (rf_setup & 0xF9) | ((power & 0x03) << 1);
  632.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  633. }
  634.  
  635. uint8_t NRF24L01_SetBitrate(uint8_t bitrate)
  636. {
  637.     // Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
  638.     // for nRF24L01+. There is no way to programmatically tell it from
  639.     // older version, nRF24L01, but the older is practically phased out
  640.     // by Nordic, so we assume that we deal with with modern version.
  641.  
  642.     // Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
  643.     rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
  644.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  645. }
  646.  
  647. ///////////////
  648. // XN297 emulation layer
  649.  
  650. static uint8_t xn297_addr_len;
  651. static uint8_t xn297_tx_addr[5];
  652. static uint8_t xn297_rx_addr[5];
  653. static uint8_t xn297_crc = 0;
  654.  
  655. static const uint8_t xn297_scramble[] = {
  656.     0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66,
  657.     0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f,
  658.     0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc,
  659.     0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
  660.     0x8e, 0xc5, 0x2f};
  661.  
  662. static const uint16_t xn297_crc_xorout[] = {
  663.     0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
  664.     0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
  665.     0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
  666.     0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
  667.     0x2138, 0x129F, 0xB3A0, 0x2988};
  668.  
  669. static uint8_t bit_reverse(uint8_t b_in)
  670. {
  671.     uint8_t b_out = 0;
  672.     for (int i = 0; i < 8; ++i) {
  673.         b_out = (b_out << 1) | (b_in & 1);
  674.         b_in >>= 1;
  675.     }
  676.     return b_out;
  677. }
  678.  
  679. static const uint16_t polynomial = 0x1021;
  680. static const uint16_t initial    = 0xb5d2;
  681. static uint16_t crc16_update(uint16_t crc, unsigned char a)
  682. {
  683.     crc ^= a << 8;
  684.     for (int i = 0; i < 8; ++i) {
  685.         if (crc & 0x8000) {
  686.             crc = (crc << 1) ^ polynomial;
  687.             } else {
  688.             crc = crc << 1;
  689.         }
  690.     }
  691.     return crc;
  692. }
  693.  
  694. void XN297_SetTXAddr(const uint8_t* addr, int len)
  695. {
  696.     if (len > 5) len = 5;
  697.     if (len < 3) len = 3;
  698.     uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
  699.     xn297_addr_len = len;
  700.     if (xn297_addr_len < 4) {
  701.         for (int i = 0; i < 4; ++i) {
  702.             buf[i] = buf[i+1];
  703.         }
  704.     }
  705.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
  706.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
  707.     // Receive address is complicated. We need to use scrambled actual address as a receive address
  708.     // but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
  709.     // first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
  710.     // instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
  711.     // with receiving signals.
  712.     memcpy(xn297_tx_addr, addr, len);
  713. }
  714.  
  715. void XN297_SetRXAddr(const uint8_t* addr, int len)
  716. {
  717.     if (len > 5) len = 5;
  718.     if (len < 3) len = 3;
  719.     uint8_t buf[] = { 0, 0, 0, 0, 0 };
  720.     memcpy(buf, addr, len);
  721.     memcpy(xn297_rx_addr, addr, len);
  722.     for (int i = 0; i < xn297_addr_len; ++i) {
  723.         buf[i] = xn297_rx_addr[i] ^ xn297_scramble[xn297_addr_len-i-1];
  724.     }
  725.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
  726.     NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
  727. }
  728.  
  729. void XN297_Configure(uint8_t flags)
  730. {
  731.     xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC));
  732.     flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
  733.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags);
  734. }
  735.  
  736. uint8_t XN297_WritePayload(uint8_t* msg, int len)
  737. {
  738.     uint8_t buf[32];
  739.     uint8_t res;
  740.     int last = 0;
  741.     if (xn297_addr_len < 4) {
  742.         // If address length (which is defined by receive address length)
  743.         // is less than 4 the TX address can't fit the preamble, so the last
  744.         // byte goes here
  745.         buf[last++] = 0x55;
  746.     }
  747.     for (int i = 0; i < xn297_addr_len; ++i) {
  748.         buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i];
  749.     }
  750.  
  751.     for (int i = 0; i < len; ++i) {
  752.         // bit-reverse bytes in packet
  753.         uint8_t b_out = bit_reverse(msg[i]);
  754.         buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i];
  755.     }
  756.     if (xn297_crc) {
  757.         int offset = xn297_addr_len < 4 ? 1 : 0;
  758.         uint16_t crc = initial;
  759.         for (int i = offset; i < last; ++i) {
  760.             crc = crc16_update(crc, buf[i]);
  761.         }
  762.         crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len];
  763.         buf[last++] = crc >> 8;
  764.         buf[last++] = crc & 0xff;
  765.     }
  766.     res = NRF24L01_WritePayload(buf, last);
  767.     return res;
  768. }
  769.  
  770. uint8_t XN297_ReadPayload(uint8_t* msg, int len)
  771. {
  772.     uint8_t res = NRF24L01_ReadPayload(msg, len);
  773.     for(uint8_t i=0; i<len; i++)
  774.         msg[i] = bit_reverse(msg[i]) ^ bit_reverse(xn297_scramble[i+xn297_addr_len]);
  775.     return res;
  776. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement