PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/mirf_usb/mirf.c

https://bitbucket.org/duventj/nrfasp
C | 234 lines | 147 code | 35 blank | 52 comment | 23 complexity | 168026f757bf4ab39ca4cd95151842b9 MD5 | raw file
  1. /*
  2. Copyright (c) 2013 Mehdi MAAREF <mehdi.maaref@hotmail.fr>
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use, copy,
  7. modify, merge, publish, distribute, sublicense, and/or sell copies
  8. of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be
  11. included in all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  16. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  17. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. DEALINGS IN THE SOFTWARE.
  20. $Id$
  21. */
  22. #include <avr/io.h>
  23. #include <avr/interrupt.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "mirf.h"
  27. #include "mirf_config.h"
  28. #include "nRF24L01.h"
  29. #define SPI_FLAG (SPSR & (1<<SPIF))
  30. uint8_t *mirf_buffer;
  31. static uint8_t _mirf_buffer[BUFFER_SZ];
  32. static uint8_t mirf_cmd_len[CMD_BUFFER_SZ]; // len of each command
  33. volatile uint8_t _cmd_len=0; // works also as a busy flag
  34. /**
  35. * @return the length of the spi buffer when finished
  36. */
  37. uint8_t _spi_transfert(void) {
  38. static uint8_t i=0;
  39. uint8_t r=0;
  40. if ((MIRF_CSN_ISHI) && i == 0) {
  41. // init transaction
  42. MIRF_CSN_LO;
  43. do {SPDR = mirf_buffer[i];} while (SPSR & 1<<WCOL);
  44. } else if (SPI_FLAG) {
  45. // save read byte
  46. mirf_buffer[i] = SPDR;
  47. i++;
  48. if(i < _cmd_len) {
  49. // send next byte
  50. do {SPDR = mirf_buffer[i];} while (SPSR & 1<<WCOL);
  51. r=0;
  52. } else {
  53. // last byte is sent
  54. r = _cmd_len;
  55. i = 0;
  56. MIRF_CSN_HI;
  57. }
  58. }
  59. return r;
  60. }
  61. uint8_t mirfPoll(uint8_t *dataBuffer) {
  62. uint8_t r = 0;
  63. static uint8_t cnt=0;
  64. if(_cmd_len > 0) {
  65. r = _spi_transfert(); // if len == 0 CSN is HI
  66. if ( r > 0) {
  67. // cmd transfert has just finished during mirf_spi_transfert()
  68. memcpy(dataBuffer, mirf_buffer, r);
  69. // is the last command ?
  70. _cmd_len = (cnt < CMD_BUFFER_SZ-1) ? mirf_cmd_len[cnt+1] : 0;
  71. switch(_cmd_len) {
  72. case 0x00:
  73. // transaction is finished
  74. cnt = 0;
  75. mirf_buffer = _mirf_buffer; // reset mirf_buffer
  76. break;
  77. case 0xff:
  78. // close command transaction
  79. MIRF_CE_HI;
  80. _cmd_len = 0;
  81. cnt = 0;
  82. mirf_buffer = _mirf_buffer;
  83. break;
  84. case 0xfe:
  85. MIRF_CE_HI;
  86. // loop while tx data is not finished
  87. if(mirf_buffer[0] & (1 << TX_DS | 1 << MAX_RT)) {
  88. cnt = 0;
  89. _cmd_len = 0;
  90. mirf_buffer = _mirf_buffer; // reset mirf_buffer
  91. // mirf_config();
  92. } else {
  93. mirf_buffer[0] = NOP;
  94. _cmd_len = 1;
  95. }
  96. break;
  97. case 0xf0:
  98. // hide command data
  99. r=0;
  100. default:
  101. mirf_buffer = &mirf_buffer[mirf_cmd_len[cnt]];
  102. cnt++;
  103. break;
  104. }
  105. return r;
  106. } else {
  107. // spare time during the spi transfert, can work with status byte
  108. }
  109. } else {
  110. // _cmd_len = 0 so spi is not busy and CSN is HI
  111. r=0;
  112. }
  113. return r;
  114. }
  115. // request multiple consecutive commands
  116. uint8_t mirf_spi_mul_cmd(const uint8_t *buffer, const uint8_t* len) {
  117. uint8_t i=0, r=0;
  118. if(_cmd_len == 0) {
  119. for(i=0; (i<CMD_BUFFER_SZ) ; i++) {
  120. // cp table of lengths
  121. mirf_cmd_len[i] = len[i];
  122. if(len[i]<BUFFER_SZ)
  123. r += len[i];
  124. }
  125. if(r>BUFFER_SZ) {
  126. r=0;
  127. } else {
  128. mirf_buffer = _mirf_buffer; // reset mirf_buffer
  129. memcpy(mirf_buffer, buffer, r); // copy data to internal buffer
  130. _cmd_len = len[0]; // trigger the spi transfert
  131. }
  132. }
  133. return r;
  134. }
  135. uint8_t mirf_spi_low_cmd(const uint8_t *buffer, const uint8_t* len) {
  136. uint8_t r = 0;
  137. r = mirf_spi_mul_cmd(buffer, len);
  138. if(r) {
  139. MIRF_CE_LO;
  140. }
  141. return r;
  142. }
  143. inline void spi_init(void)
  144. // Initialize pins for spi communication
  145. {
  146. DDR_SPI &= ~((1<<DD_MOSI)|(1<<DD_MISO)|(1<<DD_SS)|(1<<DD_SCK));
  147. // Define the following pins as output
  148. DDR_SPI |= ((1<<DD_MOSI)|(1<<DD_SS)|(1<<DD_SCK));
  149. SPCR = ((1<<SPE)| // SPI Enable
  150. (0<<SPIE)| // SPI Interupt Enable
  151. (0<<DORD)| // Data Order (0:MSB first / 1:LSB first)
  152. (1<<MSTR)| // Master/Slave select
  153. (0<<SPR1)|(0<<SPR0)| // SPI Clock Rate
  154. (0<<CPOL)| // Clock Polarity (0:SCK low / 1:SCK hi when idle)
  155. (0<<CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling)
  156. SPSR = (1<<SPI2X); // Double Clock Rate
  157. }
  158. void mirf_init(void) {
  159. uint8_t i=0;
  160. // Define CSN and CE as Output and set them to default
  161. DDR_CE |= (1<<CE);
  162. DDR_CSN |= (1<<CSN);
  163. MIRF_CE_LO;
  164. MIRF_CSN_HI;
  165. mirf_buffer = _mirf_buffer;
  166. _cmd_len = 0;
  167. for(i=0;i<CMD_BUFFER_SZ;i++)
  168. mirf_cmd_len[i] = 0;
  169. // memset(mirf_cmd_len,0,8);
  170. spi_init();
  171. }
  172. uint8_t mirf_config(void) {
  173. uint8_t cfg_len_buff[] = { 2, 2, 6, 2, 2, 2, 0xff, 0};
  174. uint8_t cfg_payload[] =
  175. { // Set RF channel
  176. W_REGISTER | (REGISTER_MASK & RF_CH),
  177. MIRF_CH,
  178. // RX_POWERUP
  179. W_REGISTER | (REGISTER_MASK & CONFIG),
  180. MIRF_CONFIG | ((1<<PWR_UP) | (1<<PRIM_RX)),
  181. // Set rx adress
  182. W_REGISTER | (REGISTER_MASK & RX_ADDR_P0),
  183. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
  184. // Set length of incoming payload
  185. W_REGISTER | (REGISTER_MASK & RX_PW_P0),
  186. MIRF_PAYLOAD_SZ,
  187. // reset TX_DS and MAX_RT
  188. W_REGISTER | (REGISTER_MASK & STATUS),
  189. 0x30,
  190. // read config
  191. R_REGISTER | (REGISTER_MASK & CONFIG),
  192. 0x00
  193. };
  194. return mirf_spi_low_cmd(cfg_payload, cfg_len_buff);
  195. }