Advertisement
Guest User

Untitled

a guest
Sep 13th, 2015
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.75 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,0x41,0x41};
  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_ReadReg(0x1D);
  266.     NRF24L01_Activate(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.     NRF24L01_ReadReg(NRF24L01_00_CONFIG);
  291.  
  292.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\xAB\xAC\xAD\xAE\xAF", 5);
  293.    
  294.    
  295.     delayMicroseconds(4000);
  296.  
  297.     for (i = 0; i < 12; i++) {
  298.  
  299.       for (j = 0; j < 8; j++) {
  300.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq1[current_chan++]);
  301.         current_chan %= 8;
  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.         current_chan %= 8;
  308.         NRF24L01_WritePayload((u8 *) "\x0A\x1A\x2A\x3A\x12\x22\x32\x42\xB1\x46", 10);  
  309.         delayMicroseconds(4200);
  310.       }
  311.     }
  312. }
  313.  
  314. void CX10_bind()
  315. {
  316.     uint16_t counter=BIND_COUNT;
  317.     bool bound=false;
  318.     uint32_t timeout;
  319.  
  320.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  321.     NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
  322.     NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
  323.     NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x77);
  324.     NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x27);
  325.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x10);
  326.     NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00);
  327.     NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
  328.     NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
  329.     NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
  330.     NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x4e);
  331.     NRF24L01_ReadReg(0x1D);
  332.     NRF24L01_Activate(0x73);
  333.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  334.  
  335.     NRF24L01_Activate(0x53); // magic for BK2421 bank switch
  336.  
  337.     /*NRF24L01_WriteRegisterMulti(0x00, (u8 *) "\x40\x4B\x01\xE2", 4);
  338.     NRF24L01_WriteRegisterMulti(0x01, (u8 *) "\xC0\x4B\x00\x00", 4);
  339.     NRF24L01_WriteRegisterMulti(0x02, (u8 *) "\xD0\xFC\x8C\x02", 4);
  340.     NRF24L01_WriteRegisterMulti(0x03, (u8 *) "\x99\x00\x39\x21", 4);
  341.     NRF24L01_WriteRegisterMulti(0x04, (u8 *) "\xF9\x96\x8A\xDB", 4);
  342.     NRF24L01_WriteRegisterMulti(0x05, (u8 *) "\x24\x06\x0F\xB6", 4);
  343.     NRF24L01_WriteRegisterMulti(0x06, (u8 *) "\x00\x00\x00\x00", 4);
  344.     NRF24L01_WriteRegisterMulti(0x07, (u8 *) "\x00\x00\x00\x00", 4);
  345.     NRF24L01_WriteRegisterMulti(0x08, (u8 *) "\x00\x00\x00\x00", 4);
  346.     NRF24L01_WriteRegisterMulti(0x09, (u8 *) "\x00\x00\x00\x00", 4);
  347.     NRF24L01_WriteRegisterMulti(0x0A, (u8 *) "\x00\x00\x00\x00", 4);
  348.     NRF24L01_WriteRegisterMulti(0x0B, (u8 *) "\x00\x00\x00\x00", 4);
  349.     NRF24L01_WriteRegisterMulti(0x0C, (u8 *) "\x00\x12\x73\x00", 4);
  350.     NRF24L01_WriteRegisterMulti(0x0D, (u8 *) "\x36\xB4\x80\x00", 4);
  351.     NRF24L01_WriteRegisterMulti(0x0E, (u8 *) "\x41\x20\x08\x04\x81\x20\xCF\xF7\xFE\xFF\xFF", 11);*/
  352.    
  353.     NRF24L01_ReadReg(NRF24L01_07_STATUS);
  354.     NRF24L01_Activate(0x53);
  355.     NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (u8 *) "\x47\x57\x30\xF4\xA1", 5);
  356.  
  357.     u8 packet[10] = {0x00,0x00,0x00,0x00,0x00,0x45,0x00,0x21,0x00,0x00};
  358.     packet[9] = checksum(packet);
  359.  
  360.     for (int i = 0; i< 25; i++) {
  361.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq2[current_chan++]);
  362.     current_chan %= 8;
  363.  
  364.     NRF24L01_WritePayload(packet, 10);
  365.     delay(4);
  366.     }
  367.  
  368.     //NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq2[current_chan++]);
  369.     //current_chan %= 8;
  370.     //NRF24L01_FlushTx();
  371.  
  372.     //NRF24L01_WritePayload((u8 *) "\x00\x00\x00\x00\x00\x45\x00\x21\x00\xb9", 10);
  373.    
  374.    
  375.     /*while(!bound) {
  376.         NRF24L01_SetTxRxMode(TX_EN);
  377.         XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
  378.         NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
  379.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  380.         NRF24L01_FlushTx();
  381.         CX10_Write_Packet(0xAA); // send bind packet
  382.         switch(board_type) {
  383.             case CX10_GREEN:
  384.                 if(counter==0)
  385.                     bound = true;
  386.                 delayMicroseconds(packet_period);
  387.                 break;
  388.             case CX10_BLUE:    
  389.                 delay(1);
  390.                 CE_off;
  391.                 NRF24L01_SetTxRxMode(RX_EN);
  392.                 NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
  393.                 NRF24L01_FlushRx();
  394.                 XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_PRIM_RX));
  395.                 CE_on;
  396.                 timeout = millis()+5;
  397.                 while(millis()<timeout) {
  398.                     if(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) { // data received from aircraft
  399.                         XN297_ReadPayload(packet, packet_length);
  400.                         if( packet[9] == 0x01)
  401.                             bound = true;
  402.                         break;
  403.                     }
  404.                 }                
  405.                 break;
  406.         }
  407.         digitalWrite(ledPin, counter-- & 0x10);
  408.     }
  409.     digitalWrite(ledPin, HIGH);*/
  410. }
  411.  
  412. static u8 checksum(u8 *data) {
  413.     u8 sum = data[0];
  414.  
  415.     for (int i=1; i < 10; i++)
  416.             sum ^= data[i];
  417.    
  418.     return sum + 0x55;
  419.  
  420. }
  421. uint32_t process_CX10()
  422. {
  423.     u8 packet[10] = {0x55,0x00,0x00,0x00,0x00,0x45,0x00,0x21,0x00,0x00};
  424.     packet[9] = checksum(packet);
  425.    
  426.     uint32_t nextPacket = micros() + 4200;
  427.  
  428.     NRF24L01_WriteReg(NRF24L01_05_RF_CH, freq2[current_chan++]);
  429.     current_chan %= 8;
  430.  
  431.     NRF24L01_WritePayload(packet, 10);
  432.     return nextPacket;
  433. }
  434.  
  435.  
  436. ///////////////
  437. // SPI
  438.  
  439. void Read_Packet(uint8_t *data, uint8_t length)
  440. {
  441.     uint8_t i;
  442.     CS_off;
  443.     _spi_write(0x61); // Read RX payload
  444.     for (i=0;i<length;i++) {
  445.         data[i]=_spi_read();
  446.     }
  447.     CS_on;
  448. }
  449.  
  450. uint8_t _spi_write(uint8_t command)
  451. {
  452.     uint8_t result=0;
  453.     uint8_t n=8;
  454.     SCK_off;
  455.     MOSI_off;
  456.     while(n--) {
  457.         if(command & 0x80)
  458.             MOSI_on;
  459.         else
  460.             MOSI_off;
  461.         if(MISO_on)
  462.             result |= 0x01;
  463.         SCK_on;
  464.         _NOP();
  465.         SCK_off;
  466.         command = command << 1;
  467.         result = result << 1;
  468.     }
  469.     MOSI_on;
  470.     return result;
  471. }
  472.  
  473. void _spi_write_address(uint8_t address, uint8_t data)
  474. {
  475.     CS_off;
  476.     _spi_write(address);
  477.     _NOP();
  478.     _spi_write(data);
  479.     CS_on;
  480. }
  481.  
  482. uint8_t _spi_read()
  483. {
  484.     uint8_t result=0;
  485.     uint8_t i;
  486.     MOSI_off;
  487.     _NOP();
  488.     for(i=0;i<8;i++) {
  489.         if(MISO_on) // if MISO is HIGH
  490.             result = (result<<1)|0x01;
  491.         else
  492.             result = result<<1;
  493.         SCK_on;
  494.         _NOP();
  495.         SCK_off;
  496.         _NOP();
  497.     }
  498.     return result;
  499. }
  500.  
  501. uint8_t _spi_read_address(uint8_t address)
  502. {
  503.     uint8_t result;
  504.     CS_off;
  505.     _spi_write(address);
  506.     result = _spi_read();
  507.     CS_on;
  508.     return(result);
  509. }
  510.  
  511. ///////////////
  512. // nRF24
  513.  
  514. /* Instruction Mnemonics */
  515. #define R_REGISTER    0x00
  516. #define W_REGISTER    0x20
  517. #define REGISTER_MASK 0x1F
  518. #define ACTIVATE      0x50
  519. #define R_RX_PL_WID   0x60
  520. #define R_RX_PAYLOAD  0x61
  521. #define W_TX_PAYLOAD  0xA0
  522. #define W_ACK_PAYLOAD 0xA8
  523. #define FLUSH_TX      0xE1
  524. #define FLUSH_RX      0xE2
  525. #define REUSE_TX_PL   0xE3
  526. #define NOP           0xFF
  527.  
  528. static uint8_t rf_setup;
  529.  
  530. uint8_t NRF24L01_WriteReg(uint8_t address, uint8_t data)
  531. {
  532.     CS_off;
  533.     _spi_write_address(address | W_REGISTER, data);
  534.     CS_on;
  535.     return 1;
  536. }
  537.  
  538. void NRF24L01_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t len)
  539. {
  540.     delayMicroseconds(5);
  541.     CS_off;
  542.     _spi_write(address | W_REGISTER);
  543.     for(uint8_t i=0;i<len;i++)
  544.         _spi_write(data[i]);
  545.     CS_on;
  546.     delayMicroseconds(5);
  547. }
  548.  
  549. void NRF24L01_Initialize()
  550. {
  551.     rf_setup = 0x0F;
  552. }
  553.  
  554. uint8_t NRF24L01_FlushTx()
  555. {
  556.     return Strobe(FLUSH_TX);
  557. }
  558.  
  559. uint8_t NRF24L01_FlushRx()
  560. {
  561.     return Strobe(FLUSH_RX);
  562. }
  563.  
  564. static uint8_t Strobe(uint8_t state)
  565. {
  566.     uint8_t result;
  567.     CS_off;
  568.     result = _spi_write(state);
  569.     CS_on;
  570.     return result;
  571. }
  572.  
  573. uint8_t NRF24L01_WritePayload(uint8_t *data, uint8_t length)
  574. {
  575.     CE_off;
  576.     CS_off;
  577.     _spi_write(W_TX_PAYLOAD);
  578.     for(uint8_t i=0; i<length; i++)
  579.         _spi_write(data[i]);
  580.     CS_on;
  581.     CE_on; // transmit
  582.     return 1;
  583. }
  584.  
  585. uint8_t NRF24L01_ReadPayload(uint8_t *data, uint8_t length)
  586. {
  587.     uint8_t i;
  588.     CS_off;
  589.     _spi_write(R_RX_PAYLOAD); // Read RX payload
  590.     for (i=0;i<length;i++) {
  591.         data[i]=_spi_read();
  592.     }
  593.     CS_on;
  594.     return 1;
  595. }
  596.  
  597. uint8_t NRF24L01_ReadReg(uint8_t reg)
  598. {
  599.     CS_off;
  600.     uint8_t data = _spi_read_address(reg);
  601.     CS_on;
  602.     return data;
  603. }
  604.  
  605. uint8_t NRF24L01_Activate(uint8_t code)
  606. {
  607.     CS_off;
  608.     _spi_write(ACTIVATE);
  609.     _spi_write(code);
  610.     CS_on;
  611.     return 1;
  612. }
  613.  
  614. void NRF24L01_SetTxRxMode(uint8_t mode)
  615. {
  616.     if(mode == TX_EN) {
  617.         CE_off;
  618.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  619.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  620.                   | (1 << NRF24L01_07_TX_DS)
  621.                   | (1 << NRF24L01_07_MAX_RT));
  622.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  623.                     (1 << NRF24L01_00_EN_CRC)   // switch to TX mode
  624.                   | (1 << NRF24L01_00_CRCO)
  625.                   | (1 << NRF24L01_00_PWR_UP));
  626.         delayMicroseconds(130);
  627.         CE_on;
  628.     } else if (mode == RX_EN) {
  629.         CE_off;
  630.         NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);        // reset the flag(s)
  631.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);        // switch to RX mode
  632.         NRF24L01_WriteReg(NRF24L01_07_STATUS,
  633.                     (1 << NRF24L01_07_RX_DR)    //reset the flag(s)
  634.                   | (1 << NRF24L01_07_TX_DS)
  635.                   | (1 << NRF24L01_07_MAX_RT));
  636.         NRF24L01_WriteReg(NRF24L01_00_CONFIG,
  637.                     (1 << NRF24L01_00_EN_CRC)   // switch to RX mode
  638.                   | (1 << NRF24L01_00_CRCO)
  639.                   | (1 << NRF24L01_00_PWR_UP)
  640.                   | (1 << NRF24L01_00_PRIM_RX));
  641.         delayMicroseconds(130);
  642.         CE_on;
  643.     } else {
  644.         NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)); //PowerDown
  645.         CE_off;
  646.     }
  647. }
  648.  
  649. uint8_t NRF24L01_Reset()
  650. {
  651.     NRF24L01_FlushTx(); //E1
  652.     NRF24L01_FlushRx(); //E2
  653.     uint8_t status1 = Strobe(0xFF); // NOP
  654.     uint8_t status2 = NRF24L01_ReadReg(0x07);  // read status 0x07 00
  655.     NRF24L01_SetTxRxMode(TXRX_OFF); // 20 08
  656.     return (status1 == status2 && (status1 & 0x0f) == 0x0e);
  657. }
  658.  
  659. // Power is in range 0..3 for nRF24L01
  660. uint8_t NRF24L01_SetPower(uint8_t power)
  661. {
  662.     rf_setup = (rf_setup & 0xF9) | ((power & 0x03) << 1);
  663.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  664. }
  665.  
  666. uint8_t NRF24L01_SetBitrate(uint8_t bitrate)
  667. {
  668.     // Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
  669.     // for nRF24L01+. There is no way to programmatically tell it from
  670.     // older version, nRF24L01, but the older is practically phased out
  671.     // by Nordic, so we assume that we deal with with modern version.
  672.  
  673.     // Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
  674.     rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
  675.     return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
  676. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement