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.63 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"); __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(500);
  210.    
  211.     NRF24L01_Reset();
  212.     delay(500);
  213.     NRF24L01_Initialize();
  214.     delay(150);
  215.     CX10_init();
  216.     delay(50);
  217.     //Bind to Receiver
  218.     CX10_bind();
  219. }
  220.  
  221. ///////////////
  222. // main loop
  223. void loop() {
  224.     uint32_t timeout;
  225.    
  226.     timeout = process_CX10();
  227.     while(micros() < timeout)
  228.     {   };
  229. }
  230.  
  231. char freq1[8] = {0x09,0x09,0x20,0x20,0x30,0x30,0x40,0x40};
  232. char freq2[8] = {0x11,0x11,0x21,0x21,0x31,0x31,0x40,0x40};
  233. ///////////////
  234. // CX10 functions
  235. void CX10_init()
  236. {
  237.     int i = 0;
  238.     int j = 0;
  239.    
  240.     txid[1] %= 0x30;
  241.     /*freq[0] = (txid[0] & 0x0F) + 0x03;
  242.     freq[1] = (txid[0] >> 4) + 0x16;
  243.     freq[2] = (txid[1] & 0x0F) + 0x2D;
  244.     freq[3] = (txid[1] >> 4) + 0x40;*/
  245.        
  246.     current_chan = 0;
  247.     NRF24L01_Reset();
  248.     NRF24L01_Initialize();
  249.     NRF24L01_SetTxRxMode(TX_EN);
  250.     //delay(1000);
  251.     //XN297_SetTXAddr(tx_rx_id,5);
  252.     //XN297_SetRXAddr(tx_rx_id,5);
  253.     delay(500);
  254.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  255.     NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
  256.     NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
  257.     NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x77);
  258.     NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x22);
  259.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x10);
  260.     NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);
  261.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
  262.     NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
  263.     NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
  264.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x4e);
  265.     NRF24L01_WriteReg(0x1D, 0x00);
  266.     NRF24L01_WriteReg(0x50, 0x73);
  267.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  268.  
  269.     NRF24L01_Activate(0x53); // magic for BK2421 bank switch
  270.  
  271.     NRF24L01_WriteRegisterMulti(0x00, (u8 *) "\x40\x4B\x01\xE2", 4);
  272.     NRF24L01_WriteRegisterMulti(0x01, (u8 *) "\xC0\x4B\x00\x00", 4);
  273.     NRF24L01_WriteRegisterMulti(0x02, (u8 *) "\xD0\xFC\x8C\x02", 4);
  274.     NRF24L01_WriteRegisterMulti(0x03, (u8 *) "\x99\x00\x39\x21", 4);
  275.     NRF24L01_WriteRegisterMulti(0x04, (u8 *) "\xD9\x96\x8A\xDB", 4);
  276.     NRF24L01_WriteRegisterMulti(0x05, (u8 *) "\x24\x06\x0F\xB6", 4);
  277.     NRF24L01_WriteRegisterMulti(0x06, (u8 *) "\x00\x00\x00\x00", 4);
  278.     NRF24L01_WriteRegisterMulti(0x07, (u8 *) "\x00\x00\x00\x00", 4);
  279.     NRF24L01_WriteRegisterMulti(0x08, (u8 *) "\x00\x00\x00\x00", 4);
  280.     NRF24L01_WriteRegisterMulti(0x09, (u8 *) "\x00\x00\x00\x00", 4);
  281.     NRF24L01_WriteRegisterMulti(0x0A, (u8 *) "\x00\x00\x00\x00", 4);
  282.     NRF24L01_WriteRegisterMulti(0x0B, (u8 *) "\x00\x00\x00\x00", 4);
  283.     NRF24L01_WriteRegisterMulti(0x0C, (u8 *) "\x00\x12\x73\x00", 4);
  284.     NRF24L01_WriteRegisterMulti(0x0D, (u8 *) "\x36\xB4\x80\x00", 4);
  285.     NRF24L01_WriteRegisterMulti(0x0E, (u8 *) "\x41\x20\x08\x04\x81\x20\xCF\xF7\xFE\xFF\xFF", 11);
  286.    
  287.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  288.     NRF24L01_Activate(0x53);
  289.  
  290.     // write 00
  291.     // write 00
  292.  
  293.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\xAB\xAC\xAD\xAE\xAF", 5);
  294.    
  295.    
  296.     delayMicroseconds(4000);
  297.  
  298.     for (i = 0; i < 8; i++) {
  299.  
  300.       for (j = 0; j < 8; j++) {
  301.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq1[current_chan++]);
  302.         NRF24L01_WritePayload((u8 *) "\xA1\xF4\x30\x57\x47\xAA\xAA\xBB\xB1\xD4", 10);  
  303.         delayMicroseconds(4200);
  304.       }
  305.       for (j = 0; j < 8; j++) {
  306.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq1[current_chan++]);
  307.         NRF24L01_WritePayload((u8 *) "\x0A\x1A\x2A\x3A\x12\x22\x32\x42\xB1\x46", 10);  
  308.         delayMicroseconds(4200);
  309.       }
  310.     }
  311. }
  312.  
  313. void CX10_bind()
  314. {
  315.     uint16_t counter=BIND_COUNT;
  316.     bool bound=false;
  317.     uint32_t timeout;
  318.  
  319.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  320.     NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
  321.     NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
  322.     NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x77);
  323.     NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x27);
  324.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x10);
  325.     NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);
  326.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
  327.     NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
  328.     NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
  329.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x4e);
  330.     NRF24L01_WriteReg(0x1D, 0x00);
  331.     NRF24L01_WriteReg(0x50, 0x73);
  332.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  333.  
  334.     NRF24L01_Activate(0x53); // magic for BK2421 bank switch
  335.  
  336.     NRF24L01_WriteRegisterMulti(0x00, (u8 *) "\x40\x4B\x01\xE2", 4);
  337.     NRF24L01_WriteRegisterMulti(0x01, (u8 *) "\xC0\x4B\x00\x00", 4);
  338.     NRF24L01_WriteRegisterMulti(0x02, (u8 *) "\xD0\xFC\x8C\x02", 4);
  339.     NRF24L01_WriteRegisterMulti(0x03, (u8 *) "\x99\x00\x39\x21", 4);
  340.     NRF24L01_WriteRegisterMulti(0x04, (u8 *) "\xF9\x96\x8A\xDB", 4);
  341.     NRF24L01_WriteRegisterMulti(0x05, (u8 *) "\x24\x06\x0F\xB6", 4);
  342.     NRF24L01_WriteRegisterMulti(0x06, (u8 *) "\x00\x00\x00\x00", 4);
  343.     NRF24L01_WriteRegisterMulti(0x07, (u8 *) "\x00\x00\x00\x00", 4);
  344.     NRF24L01_WriteRegisterMulti(0x08, (u8 *) "\x00\x00\x00\x00", 4);
  345.     NRF24L01_WriteRegisterMulti(0x09, (u8 *) "\x00\x00\x00\x00", 4);
  346.     NRF24L01_WriteRegisterMulti(0x0A, (u8 *) "\x00\x00\x00\x00", 4);
  347.     NRF24L01_WriteRegisterMulti(0x0B, (u8 *) "\x00\x00\x00\x00", 4);
  348.     NRF24L01_WriteRegisterMulti(0x0C, (u8 *) "\x00\x12\x73\x00", 4);
  349.     NRF24L01_WriteRegisterMulti(0x0D, (u8 *) "\x36\xB4\x80\x00", 4);
  350.     NRF24L01_WriteRegisterMulti(0x0E, (u8 *) "\x41\x20\x08\x04\x81\x20\xCF\xF7\xFE\xFF\xFF", 11);
  351.    
  352.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  353.     NRF24L01_Activate(0x53);
  354.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\x47\x57\x30\xF4\xA1", 5);
  355.  
  356.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq2[current_chan++]);
  357.     //NRF24L01_FlushTx();
  358.  
  359.     NRF24L01_WritePayload((u8 *) "\x00\x00\x00\x00\x00\x45\x00\x21\x00\xb9", 10);
  360.    
  361.    
  362.     /*while(!bound) {
  363.         NRF24L01_SetTxRxMode(TX_EN);
  364.         XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
  365.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
  366.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  367.         NRF24L01_FlushTx();
  368.         CX10_Write_Packet(0xAA); // send bind packet
  369.         switch(board_type) {
  370.             case CX10_GREEN:
  371.                 if(counter==0)
  372.                     bound = true;
  373.                 delayMicroseconds(packet_period);
  374.                 break;
  375.             case CX10_BLUE:    
  376.                 delay(1);
  377.                 CE_off;
  378.                 NRF24L01_SetTxRxMode(RX_EN);
  379.                 NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  380.                 NRF24L01_FlushRx();
  381.                 XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_PRIM_RX));
  382.                 CE_on;
  383.                 timeout = millis()+5;
  384.                 while(millis()<timeout) {
  385.                     if(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) { // data received from aircraft
  386.                         XN297_ReadPayload(packet, packet_length);
  387.                         if( packet[9] == 0x01)
  388.                             bound = true;
  389.                         break;
  390.                     }
  391.                 }                
  392.                 break;
  393.         }
  394.         digitalWrite(ledPin, counter-- & 0x10);
  395.     }
  396.     digitalWrite(ledPin, HIGH);*/
  397. }
  398.  
  399. uint32_t process_CX10()
  400. {
  401.     uint32_t nextPacket = micros() + 4200;
  402.     //XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
  403.     //NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);     // Clear data ready, data sent, and retransmit
  404.     //NRF24L01_FlushTx();
  405.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq2[current_chan++]);
  406.     current_chan %= NUM_RF_CHANNELS;
  407.  
  408.     NRF24L01_WritePayload((u8 *) "\x00\x00\x00\x00\x00\x45\x00\x21\x00\xb9", 10);
  409.     //CX10_Write_Packet(0x55);
  410.     return nextPacket;
  411. }
  412.  
  413.  
  414. ///////////////
  415. // SPI
  416.  
  417. void Read_Packet(uint8_t *data, uint8_t length)
  418. {
  419.     uint8_t i;
  420.     CS_off;
  421.     _spi_write(0x61); // Read RX payload
  422.     for (i=0;i<length;i++) {
  423.         data[i]=_spi_read();
  424.     }
  425.     CS_on;
  426. }
  427.  
  428. uint8_t _spi_write(uint8_t command)
  429. {
  430.     uint8_t result=0;
  431.     uint8_t n=8;
  432.     SCK_off;
  433.     MOSI_off;
  434.     while(n--) {
  435.         if(command & 0x80)
  436.             MOSI_on;
  437.         else
  438.             MOSI_off;
  439.         if(MISO_on)
  440.             result |= 0x01;
  441.         SCK_on;
  442.         _NOP();
  443.         SCK_off;
  444.         command = command << 1;
  445.         result = result << 1;
  446.     }
  447.     MOSI_on;
  448.     return result;
  449. }
  450.  
  451. void _spi_write_address(uint8_t address, uint8_t data)
  452. {
  453.     CS_off;
  454.     _spi_write(address);
  455.     _NOP();
  456.     _spi_write(data);
  457.     CS_on;
  458. }
  459.  
  460. uint8_t _spi_read()
  461. {
  462.     uint8_t result=0;
  463.     uint8_t i;
  464.     MOSI_off;
  465.     _NOP();
  466.     for(i=0;i<8;i++) {
  467.         if(MISO_on) // if MISO is HIGH
  468.             result = (result<<1)|0x01;
  469.         else
  470.             result = result<<1;
  471.         SCK_on;
  472.         _NOP();
  473.         SCK_off;
  474.         _NOP();
  475.     }
  476.     return result;
  477. }
  478.  
  479. uint8_t _spi_read_address(uint8_t address)
  480. {
  481.     uint8_t result;
  482.     CS_off;
  483.     _spi_write(address);
  484.     result = _spi_read();
  485.     CS_on;
  486.     return(result);
  487. }
  488.  
  489. ///////////////
  490. // nRF24
  491.  
  492. /* Instruction Mnemonics */
  493. #define R_REGISTER    0x00
  494. #define W_REGISTER    0x20
  495. #define REGISTER_MASK 0x1F
  496. #define ACTIVATE      0x50
  497. #define R_RX_PL_WID   0x60
  498. #define R_RX_PAYLOAD  0x61
  499. #define W_TX_PAYLOAD  0xA0
  500. #define W_ACK_PAYLOAD 0xA8
  501. #define FLUSH_TX      0xE1
  502. #define FLUSH_RX      0xE2
  503. #define REUSE_TX_PL   0xE3
  504. #define NOP           0xFF
  505.  
  506. static uint8_t rf_setup;
  507.  
  508. uint8_t NRF24L01_WriteReg(uint8_t address, uint8_t data)
  509. {
  510.     CS_off;
  511.     _spi_write_address(address | W_REGISTER, data);
  512.     CS_on;
  513.     return 1;
  514. }
  515.  
  516. void NRF24L01_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t len)
  517. {
  518.     delayMicroseconds(5);
  519.     CS_off;
  520.     _spi_write(address | W_REGISTER);
  521.     for(uint8_t i=0;i<len;i++)
  522.         _spi_write(data[i]);
  523.     CS_on;
  524.     delayMicroseconds(5);
  525. }
  526.  
  527. void NRF24L01_Initialize()
  528. {
  529.     rf_setup = 0x0F;
  530. }
  531.  
  532. uint8_t NRF24L01_FlushTx()
  533. {
  534.     return Strobe(FLUSH_TX);
  535. }
  536.  
  537. uint8_t NRF24L01_FlushRx()
  538. {
  539.     return Strobe(FLUSH_RX);
  540. }
  541.  
  542. static uint8_t Strobe(uint8_t state)
  543. {
  544.     uint8_t result;
  545.     CS_off;
  546.     result = _spi_write(state);
  547.     CS_on;
  548.     return result;
  549. }
  550.  
  551. uint8_t NRF24L01_WritePayload(uint8_t *data, uint8_t length)
  552. {
  553.     CE_off;
  554.     CS_off;
  555.     _spi_write(W_TX_PAYLOAD);
  556.     for(uint8_t i=0; i<length; i++)
  557.         _spi_write(data[i]);
  558.     CS_on;
  559.     CE_on; // transmit
  560.     return 1;
  561. }
  562.  
  563. uint8_t NRF24L01_ReadPayload(uint8_t *data, uint8_t length)
  564. {
  565.     uint8_t i;
  566.     CS_off;
  567.     _spi_write(R_RX_PAYLOAD); // Read RX payload
  568.     for (i=0;i<length;i++) {
  569.         data[i]=_spi_read();
  570.     }
  571.     CS_on;
  572.     return 1;
  573. }
  574.  
  575. uint8_t NRF24L01_ReadReg(uint8_t reg)
  576. {
  577.     CS_off;
  578.     uint8_t data = _spi_read_address(reg);
  579.     CS_on;
  580.     return data;
  581. }
  582.  
  583. uint8_t NRF24L01_Activate(uint8_t code)
  584. {
  585.     CS_off;
  586.     _spi_write(ACTIVATE);
  587.     _spi_write(code);
  588.     CS_on;
  589.     return 1;
  590. }
  591.  
  592. void NRF24L01_SetTxRxMode(uint8_t mode)
  593. {
  594.     if(mode == TX_EN) {
  595.         CE_off;
  596.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  597.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  598.                   | (1 << NRF24L01_07_TX_DS)
  599.                   | (1 << NRF24L01_07_MAX_RT));
  600.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  601.                     (1 << NRF24L01_00_EN_CRC)   // switch to TX mode
  602.                   | (1 << NRF24L01_00_CRCO)
  603.                   | (1 << NRF24L01_00_PWR_UP));
  604.         delayMicroseconds(130);
  605.         CE_on;
  606.     } else if (mode == RX_EN) {
  607.         CE_off;
  608.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);        // reset the flag(s)
  609.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);        // switch to RX mode
  610.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  611.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  612.                   | (1 << NRF24L01_07_TX_DS)
  613.                   | (1 << NRF24L01_07_MAX_RT));
  614.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  615.                     (1 << NRF24L01_00_EN_CRC)   // switch to RX mode
  616.                   | (1 << NRF24L01_00_CRCO)
  617.                   | (1 << NRF24L01_00_PWR_UP)
  618.                   | (1 << NRF24L01_00_PRIM_RX));
  619.         delayMicroseconds(130);
  620.         CE_on;
  621.     } else {
  622.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)); //PowerDown
  623.         CE_off;
  624.     }
  625. }
  626.  
  627. uint8_t NRF24L01_Reset()
  628. {
  629.     NRF24L01_FlushTx(); //E1
  630.     NRF24L01_FlushRx(); //E2
  631.     uint8_t status1 = Strobe(0xFF); // NOP
  632.     uint8_t status2 = NRF24L01_ReadReg(0x07);  // read status 0x07 00
  633.     NRF24L01_SetTxRxMode(TXRX_OFF); // 20 08
  634.     return (status1 == status2 && (status1 & 0x0f) == 0x0e);
  635. }
  636.  
  637. // Power is in range 0..3 for nRF24L01
  638. uint8_t NRF24L01_SetPower(uint8_t power)
  639. {
  640.     rf_setup = (rf_setup & 0xF9) | ((power & 0x03) << 1);
  641.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  642. }
  643.  
  644. uint8_t NRF24L01_SetBitrate(uint8_t bitrate)
  645. {
  646.     // Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
  647.     // for nRF24L01+. There is no way to programmatically tell it from
  648.     // older version, nRF24L01, but the older is practically phased out
  649.     // by Nordic, so we assume that we deal with with modern version.
  650.  
  651.     // Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
  652.     rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
  653.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  654. }
  655.  
  656. ///////////////
  657. // XN297 emulation layer
  658.  
  659. static uint8_t xn297_addr_len;
  660. static uint8_t xn297_tx_addr[5];
  661. static uint8_t xn297_rx_addr[5];
  662. static uint8_t xn297_crc = 0;
  663.  
  664. static const uint8_t xn297_scramble[] = {
  665.     0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66,
  666.     0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f,
  667.     0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc,
  668.     0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
  669.     0x8e, 0xc5, 0x2f};
  670.  
  671. static const uint16_t xn297_crc_xorout[] = {
  672.     0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
  673.     0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
  674.     0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
  675.     0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
  676.     0x2138, 0x129F, 0xB3A0, 0x2988};
  677.  
  678. static uint8_t bit_reverse(uint8_t b_in)
  679. {
  680.     uint8_t b_out = 0;
  681.     for (int i = 0; i < 8; ++i) {
  682.         b_out = (b_out << 1) | (b_in & 1);
  683.         b_in >>= 1;
  684.     }
  685.     return b_out;
  686. }
  687.  
  688. static const uint16_t polynomial = 0x1021;
  689. static const uint16_t initial    = 0xb5d2;
  690. static uint16_t crc16_update(uint16_t crc, unsigned char a)
  691. {
  692.     crc ^= a << 8;
  693.     for (int i = 0; i < 8; ++i) {
  694.         if (crc & 0x8000) {
  695.             crc = (crc << 1) ^ polynomial;
  696.             } else {
  697.             crc = crc << 1;
  698.         }
  699.     }
  700.     return crc;
  701. }
  702.  
  703. void XN297_SetTXAddr(const uint8_t* addr, int len)
  704. {
  705.     if (len > 5) len = 5;
  706.     if (len < 3) len = 3;
  707.     uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
  708.     xn297_addr_len = len;
  709.     if (xn297_addr_len < 4) {
  710.         for (int i = 0; i < 4; ++i) {
  711.             buf[i] = buf[i+1];
  712.         }
  713.     }
  714.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
  715.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
  716.     // Receive address is complicated. We need to use scrambled actual address as a receive address
  717.     // but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
  718.     // first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
  719.     // instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
  720.     // with receiving signals.
  721.     memcpy(xn297_tx_addr, addr, len);
  722. }
  723.  
  724. void XN297_SetRXAddr(const uint8_t* addr, int len)
  725. {
  726.     if (len > 5) len = 5;
  727.     if (len < 3) len = 3;
  728.     uint8_t buf[] = { 0, 0, 0, 0, 0 };
  729.     memcpy(buf, addr, len);
  730.     memcpy(xn297_rx_addr, addr, len);
  731.     for (int i = 0; i < xn297_addr_len; ++i) {
  732.         buf[i] = xn297_rx_addr[i] ^ xn297_scramble[xn297_addr_len-i-1];
  733.     }
  734.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
  735.     NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
  736. }
  737.  
  738. void XN297_Configure(uint8_t flags)
  739. {
  740.     xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC));
  741.     flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
  742.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags);
  743. }
  744.  
  745. uint8_t XN297_WritePayload(uint8_t* msg, int len)
  746. {
  747.     uint8_t buf[32];
  748.     uint8_t res;
  749.     int last = 0;
  750.     if (xn297_addr_len < 4) {
  751.         // If address length (which is defined by receive address length)
  752.         // is less than 4 the TX address can't fit the preamble, so the last
  753.         // byte goes here
  754.         buf[last++] = 0x55;
  755.     }
  756.     for (int i = 0; i < xn297_addr_len; ++i) {
  757.         buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i];
  758.     }
  759.  
  760.     for (int i = 0; i < len; ++i) {
  761.         // bit-reverse bytes in packet
  762.         uint8_t b_out = bit_reverse(msg[i]);
  763.         buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i];
  764.     }
  765.     if (xn297_crc) {
  766.         int offset = xn297_addr_len < 4 ? 1 : 0;
  767.         uint16_t crc = initial;
  768.         for (int i = offset; i < last; ++i) {
  769.             crc = crc16_update(crc, buf[i]);
  770.         }
  771.         crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len];
  772.         buf[last++] = crc >> 8;
  773.         buf[last++] = crc & 0xff;
  774.     }
  775.     res = NRF24L01_WritePayload(buf, last);
  776.     return res;
  777. }
  778.  
  779. uint8_t XN297_ReadPayload(uint8_t* msg, int len)
  780. {
  781.     uint8_t res = NRF24L01_ReadPayload(msg, len);
  782.     for(uint8_t i=0; i<len; i++)
  783.         msg[i] = bit_reverse(msg[i]) ^ bit_reverse(xn297_scramble[i+xn297_addr_len]);
  784.     return res;
  785. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement