McMajan Library Pack  v 2.00
Improve your Arduino !
Ss_McAir24.cpp
Go to the documentation of this file.
1 #include "Ss_McAir24.h"
2 
4 
5 // =============================================================================
6 void ss_nrf24::transferSync(uint8_t *dataout,uint8_t *datain,uint8_t len)
7 {
8  for(uint8_t i = 0;i < len;i++) datain[i] = SPI.transfer(dataout[i]);
9 }
10 // =============================================================================
11 void ss_nrf24::transmitSync(uint8_t *dataout,uint8_t len)
12 {
13  //for(uint8_t i = 0;i < len;i++) SPI.transfer(dataout[i]);
14  while (len--) SPI.transfer(*dataout++);
15 }
16 
17 // =============================================================================
18 /*! Initialize the nrf24 library
19 \param ce ce pin
20 \param scn csn pin
21 \return return false if some initializing errors was found
22 */
23 
24 bool ss_nrf24::init(uint8_t ce,uint8_t csn)
25 // Should be called in the early initializing phase at startup.
26 {
27 
28  csnPin = csn;
29  cePin=ce;
30  pinMode(cePin,OUTPUT);
31  pinMode(csnPin,OUTPUT);
32 
33  ceLow();
34  csnHi();
35 
36  pinMode(SCK, OUTPUT);
37  pinMode(MOSI, OUTPUT);
38  // Wait for NRF24 POR (up to 100msec)
39  delay(100);
40 
41  SPI.begin();
42  SPI.setDataMode(SPI_MODE0);
43  SPI.setBitOrder(MSBFIRST);
44  #ifdef __AVR__
45  SPI.setClockDivider(SPI_CLOCK_DIV2);
46  #else //#ifdef _SAM3XA_
47  SPI.setClockDivider(21);
48  #endif
49 
50 
52  flushTx();
53  flushRx();
54 
55  return powerUpRx();
56 }
57 
58 // =============================================================================
59 /*! Set rf channel
60 \param channel is the channel number from 0 to 127. Every channel adds a 1MHz (or a bit more, related to the speed setting) to the basic 2.4GHz frequency.
61 Warning: In some countries you can have some limitation, for example in USA the last legal channel is 84.
62 
63 */
64 void ss_nrf24::setChannel(uint8_t channel)
65 {
66  configRegister(RF_CH,channel);
67 }
68 
69 // =============================================================================
70 /*! Set payload size
71 
72 Note: if you don't use my McAirData protocol, you MUST set this and please remember that payload size MUST be the same in server and client module.
73 \param payload_size is the size of payload.
74 */
75 void ss_nrf24::setPayLoadSize(uint8_t payload_size)
76 { // Set length of incoming payload
77  configRegister(RX_PW_P0, payload_size);
78  configRegister(RX_PW_P1, payload_size);
79  payload=payload_size;
80 }
81 
82 // =============================================================================
83 /*! Set receiver address (local module)
84 \param adr is a 5byte address.
85 
86 */
87 void ss_nrf24::setRADDR(uint8_t * adr)
88 { // Sets the receiving address
89  ceLow();
90  writeRegister(RX_ADDR_P1,adr,McAir24_ADDR_LEN);
91  ceHi();
92 }
93 // =============================================================================
94 /*! Set trasmitter address (remote module)
95 \param adr is the 5bytes address.
96 */
97 void ss_nrf24::setTADDR(uint8_t * adr)
98 // Sets the transmitting address
99 {
100  //RX_ADDR_P0 must be set to the sending addr for auto ack to work.
101  writeRegister(RX_ADDR_P0,adr,McAir24_ADDR_LEN);
102  writeRegister(TX_ADDR,adr,McAir24_ADDR_LEN);
103 }
104 // =============================================================================
105 /*! Checks if data is available for reading
106 \return This function return true if you have data ready, or false if data aren't ready
107 
108 */
110 //
111 {
112  // See note in getData() function - just checking RX_DR isn't good enough
113  uint8_t status = getStatus();
114 
115  // We can short circuit on RX_DR, but if it's not set, we still need
116  // to check the FIFO for any pending packets
117  if(status & McAir24_RX_DR) return 1;
118 // VERIFICARE
119 // // Manual says that messages > 32 octets should be discarded
120 // if (spiRead(NRF24_COMMAND_R_RX_PL_WID) > 32)
121 // {
122 // flushRx();
123 // return false;
124 // }
125  return !rxFifoEmpty();
126 }
127 
128 // =============================================================================
130 {
131  uint8_t fifoStatus;
132  readRegister(McAir24_Reg17_FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
133  return (fifoStatus & McAir24_RX_EMPTY); //1 fifo empty / 0 fifo data
134 }
135 
136 // =============================================================================
137 /*! Reads data from module and transfert it to Arduino's buffer
138 \param data is the buffer where you want to copy the data. Please remember that data buffer MUST be at least as payload size.
139 */
140 void ss_nrf24::getData(uint8_t * data)
141 // Reads payload bytes into data array
142 {
143  csnLow(); // Pull down chip select
144  SPI.transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
145  transferSync(data,data,payload); // Read payload
146  csnHi(); // Pull up chip select
147  // NVI: per product spec, p 67, note c:
148  // "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
149  // for handling this interrupt should be: 1) read payload through SPI,
150  // 2) clear RX_DR IRQ, 3) read McAir24_Reg17_FIFO_STATUS to check if there are more
151  // payloads available in RX FIFO, 4) if there are more data in RX FIFO,
152  // repeat from step 1)."
153  // So if we're going to clear RX_DR here, we need to check the RX FIFO
154  // in the dataReady() function
155  configRegister(McAir24_Reg07_STATUS,McAir24_RX_DR); // Reset status register
156 }
157 // =============================================================================
159 {
160  csnLow();
161  uint8_t status=SPI.transfer(McAir24_W_REGISTER | (McAir24_REGISTER_MASK & reg));
162  SPI.transfer(value); //vale solo per un byte
163  csnHi();
164  return(status);
165 }
166 // =============================================================================
167 void ss_nrf24::writeRegister(uint8_t reg, uint8_t * value, uint8_t len)
168 { // Writes an array of bytes into inte the McAir24 registers.
169  csnLow();
170  SPI.transfer(McAir24_W_REGISTER | (McAir24_REGISTER_MASK & reg));
171  transmitSync(value,len); //bytes multipli
172  csnHi();
173 }
174 // =============================================================================
176 { // Reads an array of bytes from the given start position in the McAir24 registers.
177  csnLow();
178  uint8_t status=SPI.transfer(McAir24_R_REGISTER | (McAir24_REGISTER_MASK & reg));
179  transferSync(value,value,1);
180  csnHi();
181  return(status);}
182 
183 // =============================================================================
184 uint8_t ss_nrf24::readRegister(uint8_t reg)
185 {
186  csnLow();
187  SPI.transfer(McAir24_R_REGISTER | (McAir24_REGISTER_MASK & reg));
188  uint8_t status=SPI.transfer(0xff);
189  csnHi();
190  return(status);
191 }
192 
193 // =============================================================================
194 /*! Send data to remote module
195  \param value is the buffer of data. The lenght is not specificated because it's used the payload size.
196 */
197 void ss_nrf24::send(uint8_t * value)
198 {
199  uint8_t status;
200  status = getStatus();
201  while (PTX)
202  { // Wait until last paket is send
203  status = getStatus();
204  if(status & (McAir24_MASK_TX_DS | McAir24_MASK_MAX_RT))
205  {
206  PTX = 0;
207  break;
208  }
209  }
210 
211  ceLow();
212  powerUpTx(); // Set to transmitter mode , Power up
213  spiCommand(McAir24_FLUSH_TX);
214 
215  csnLow(); // Pull down chip select
216  SPI.transfer( W_TX_PAYLOAD ); // Write cmd to write payload
217  //W_TX_PAYLOAD=0xa0, per fare no ACK usa 0xb0
218 
219 
220  transmitSync(value,payload); // Write payload
221  csnHi(); // Pull up chip select
222 
223 
224  ceHi(); // Start transmission
225  //while(isSending()){}
226 }
227 
228 // =============================================================================
230 {
231  uint8_t status;
232  if(PTX){
233  status = getStatus();
234  if(status & (McAir24_TX_DS | McAir24_MAX_RT)) // if sending successful (TX_DS) or max retries exceded (MAX_RT).
235  {
236  powerUpRx();
237  return false;
238  }
239 
240  return true;
241  }
242  return false;
243 }
244 // =============================================================================
246  uint8_t rv;
247  readRegister(McAir24_Reg07_STATUS,&rv,1);
248  return rv;
249 }
250 // =============================================================================
252 {
253  PTX = 0;
254  ceLow();
255  delayMicroseconds(200);
256  // PRIM_RX set=receiver / not set=transmitter
257  //EN_CRC: crc activated | CRCO->if set 2bytes crc, else 1byte crc.
258  bool status=configRegister(McAir24_Reg00_CONFIG, McAir24_EN_CRC | McAir24_PWR_UP | McAir24_PRIM_RX);
259  //configRegister(McAir24_Reg01_EN_AA,0x41);// test abilitazione auto ACK
260 
261  ceHi();
262  configRegister(McAir24_Reg07_STATUS,McAir24_TX_DS | McAir24_MAX_RT); //clear interrupt
263 
264  flushTx(); // Aggiunta io
265  return(status);
266 }
267 // =============================================================================
269 {
270  csnLow();
271  uint8_t status = SPI.transfer(command);
272  csnHi();
273  return status;
274 }
275 // =============================================================================
277 {
278  csnLow();
279  SPI.transfer(command); // Send the address, discard status
280  uint8_t val = SPI.transfer(0); // The MOSI value is ignored, value is read
281  csnHi();
282  return val;
283 }
284 // =============================================================================
286 {
287  csnLow();
288  uint8_t status = SPI.transfer(command);
289  SPI.transfer(val); // New register value follows
290  csnHi();
291  return status;
292 }
293 // =============================================================================
295 {
296  return spiCommand(McAir24_FLUSH_RX);
297 }
298 // =============================================================================
300 {
301  return spiCommand(McAir24_FLUSH_TX);
302 }
303 // =============================================================================
305  PTX = 1;
306  //configRegister(McAir24_Reg00_CONFIG, McAir24_Base | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
308  delayMicroseconds(200);
309 }
310 // =============================================================================
311 void ss_nrf24::ceHi(){
312  digitalWrite(cePin,HIGH);
313 }
314 // =============================================================================
315 void ss_nrf24::ceLow(){
316  digitalWrite(cePin,LOW);
317 }
318 // =============================================================================
319 void ss_nrf24::csnHi(){
320  digitalWrite(csnPin,HIGH);
321 }
322 // =============================================================================
323 void ss_nrf24::csnLow(){
324  digitalWrite(csnPin,LOW);
325 }
326 // =============================================================================
328 {// nella nrf24 sono invertite
329  ceLow();
330  configRegister(McAir24_Reg00_CONFIG, McAir24_Base );
331 }
332 
333 // =============================================================================
334 /*!Set the speed and power of the transmitter
335 \param sp is a mix of signal power and speed of the transmitter. You can combine them using ! symbol. The option you can combine are:<br>
336 In this first list you can see the transmission power and relative consumption.
337  <ul>
338  <li>McAir24_PWR_18dB - 11.3mA (Maximum power)</li>
339  <li>McAir24_PWR_12dB - 9mA</li>
340  <li>McAir24_PWR_6dB - 7.5mA</li>
341  <li>McAir24_PWR_0dB - 7mA</li>
342 </ul>
343 In this second list you can see the speed setting from 250K to 2M
344  <ul>
345  <li>McAir24_SPD_250K (only nrf24l01+, whith plus)</li>
346  <li>McAir24_SPD_1M</li>
347  <li>McAir24_SPD_2M</li>
348 </ul>
349 
350 \code
351  McAir24.Set_Speed_Power(McAir24_SPD_1M | McAir24_PWR_18dB);
352 \endcode
353 */
354 
355 
356 bool ss_nrf24::Set_Speed_Power(uint8_t sp)
357 {
358  bool res=false;
359  uint8_t val=0;
360  configRegister(McAir24_Reg06_RF_SETUP,sp);
361  readRegister(McAir24_Reg06_RF_SETUP,&val,1);
362 
363  if (val == sp ) res = true;
364 
366  {
367  configRegister(McAir24_Reg04_SETUP_RETR,0x47); //1250u / 5 retr. 0x47
368  }
369  else configRegister(McAir24_Reg04_SETUP_RETR,0x13); //500u / 3 retr.
370  return(res);
371 }
372 
373 // =============================================================================
374 bool ss_nrf24::waitAvailableTimeout(uint16_t timeout)
375 {
376  while(isSending()){}
377  powerUpRx();
378  unsigned long starttime = millis();
379  while ((millis() - starttime) < timeout) if (dataReady()) return true;
380  return false;
381 }
382 // =============================================================================
383 /*! This function sensds data (char) using McAirData protocol
384 \param group is the grop of data (0 to 255)
385 \param elemnt is a element of the specific group (0 to 255)
386 \param dato is the char you want to send
387 \del is optional (default=30). It's a little delay in milliseconds after data send. It's necessary to prevent buffer overflow if yo are using intensive transmission.
388 If you send only a single data you can set to 0 for a faster transmission.
389 */
390 void ss_nrf24::SendAirData(uint8_t group,uint8_t element,char dato,uint8_t del)
391 {
392  RefData.IO.Data.datachar[0]=dato;
393  SetGE(group,element);
394  SendData(del);
395 
396 }
397 // =============================================================================
398 /*! This function sensds data (int) using McAirData protocol
399 \param group is the grop of data (0 to 255)
400 \param elemnt is a element of the specific group (0 to 255)
401 \param dato is the int you want to send
402 \del is optional (default=30). It's a little delay in milliseconds after data send. It's necessary to prevent buffer overflow if yo are using intensive transmission.
403 If you send only a single data you can set to 0 for a faster transmission.
404 */
405 void ss_nrf24::SendAirData(uint8_t group,uint8_t element,int dato,uint8_t del)
406 {
407  RefData.IO.Data.dataint[0]=dato;
408  SetGE(group,element);
409  SendData(del);
410 }
411 // =============================================================================
412 /*! This function sensds data (float) using McAirData protocol
413 \param group is the grop of data (0 to 255)
414 \param elemnt is a element of the specific group (0 to 255)
415 \param dato is the float you want to send
416 \del is optional (default=30). It's a little delay in milliseconds after data send. It's necessary to prevent buffer overflow if yo are using intensive transmission.
417 If you send only a single data you can set to 0 for a faster transmission.
418 */
419 void ss_nrf24::SendAirData(uint8_t group,uint8_t element,float dato,uint8_t del)
420 {
422  SetGE(group,element);
423  SendData(del);
424 }
425 // =============================================================================
426 /*! This function sensds data (unsigned long) using McAirData protocol
427 \param group is the grop of data (0 to 255)
428 \param elemnt is a element of the specific group (0 to 255)
429 \param dato is the unsigned long you want to send
430 \del is optional (default=30). It's a little delay in milliseconds after data send. It's necessary to prevent buffer overflow if yo are using intensive transmission.
431 If you send only a single data you can set to 0 for a faster transmission.
432 */
433 void ss_nrf24::SendAirData(uint8_t group,uint8_t element,unsigned long dato,uint8_t del)
434 {
436  SetGE(group,element);
437  SendData(del);
438 }
439 
440 // =============================================================================
441 /** \brief Send data using McAir protocol
442  * \param del is a optional delay in milli seconds (default is 30 if not specificated)
443  */
444 void ss_nrf24::SendData(uint8_t del)
445 {
446  if(payload!=6) setPayLoadSize(6);
447  send((byte *)RefData.databuffer);
448  while(isSending()){}
449  delay(del);
450 }
451 // =============================================================================
452 
453 // =============================================================================
454 
455 void ss_nrf24::SetGE(uint8_t group,uint8_t element)
456 {
457  RefData.IO.Group=group;
458  RefData.IO.Element=element;
459 }
460 // =============================================================================
461 /*! If there are data ready, this function copies data to internal buffer
462 
463 After you used this function you can read the internal buffer in very simple mode. You can read Group Element and Data sent by some simple macros:<br>
464 McAirGroup: contains the group<br>
465 McAirElement: contains the element of the specific group<br>
466 For the data you can use some macros depending the type of data you want to read (char, int, float, unsigned long). These are:<br>
467 <ul>
468 <li>McAirDataChar</li>
469 <li>McAirDataInt</li>
470 <li>McAirDataFloat</li>
471 <li>McAirDataLong</li>
472 </ul>
473 
474 \code
475 
476 
477 if(McAir24.GetAirData()) // check iv data ready
478 {
479  if(McAirGroup=='T') // group 'T'
480  {
481  Serial.print("ok received number: ");
482  Serial.print((int)McAirElement); //this is the element of specific group
483  Serial.print(" - content: ");
484  Serial.println(McAirDataFloat); //this is the float value transmitted in the specific group and element
485  }
486 }
487 \endcode
488 \return This function return true if data was read, else return false
489 
490 */
492 {
493  if(!isSending() && dataReady()) // controllo se ho ricevuto dati rf24
494  {
495  getData((uint8_t *)RefData.databuffer); //RefData è un puntatore al buffer
496  return(true);
497  }
498  return false;
499 
500 }
501 
502 
503 // =============================================================================
504 /*!Show internal registers in hex and binary format. useful for debug.
505 */
507 {
508  uint8_t registro;
509  for(int kk=0;kk<0x17;kk++)
510  {
511  registro=0;
512  McAir24.readRegister( kk, &registro, sizeof(registro) );
513  Serial.print( "Register 0x" );
514  Serial.print(kk,HEX);
515 
516  Serial.print( " = " );
517 
518  Serial.print( registro, BIN );
519  Serial.print( " - 0x" );
520  Serial.println( registro, HEX );
521  }
522 
523 }
524 // =============================================================================
525 /*! RPD: Receive Power Detector: This function tell you if the spicificated channel has a sufficient signal power
526 \return true if signal is present
527 */
528 bool ss_nrf24::isSignal(void)
529 {
530  //setta solo il primo bit per segnali >-64dBm
531  //delayMicroseconds(200); //need 170
532  delay(1);
533  return ( readRegister(McAir24_Reg09_RPD) & 1 );
534 }
535 
536 
537 // =============================================================================
bool Set_Speed_Power(uint8_t)
Definition: Ss_McAir24.cpp:356
unsigned long datalong
Definition: Ss_McAir24.h:40
#define McAir24_MASK_MAX_RT
Definition: Ss_nrf24.h:15
void writeRegister(uint8_t reg, uint8_t *value, uint8_t len)
Definition: Ss_McAir24.cpp:167
uint8_t getStatus()
Definition: Ss_McAir24.cpp:245
void getData(uint8_t *data)
Definition: Ss_McAir24.cpp:140
#define McAir24_Base
Definition: Ss_nrf24.h:10
void Print_Internal_Registers()
Definition: Ss_McAir24.cpp:506
#define McAir24_W_REGISTER
Definition: Ss_nrf24.h:129
#define McAir24_R_REGISTER
Definition: Ss_nrf24.h:128
bool powerUpRx()
Definition: Ss_McAir24.cpp:251
void powerUpTx()
Definition: Ss_McAir24.cpp:304
void transmitSync(uint8_t *dataout, uint8_t len)
Definition: Ss_McAir24.cpp:11
#define McAir24_Reg09_RPD
Definition: Ss_nrf24.h:56
uint8_t spiCommand(uint8_t)
Definition: Ss_McAir24.cpp:268
struct McMajanData IO
Definition: Ss_McAir24.h:53
#define McAir24_Reg06_RF_SETUP
Definition: Ss_nrf24.h:37
#define McAir24_RX_EMPTY
Definition: Ss_nrf24.h:76
bool isSending()
Definition: Ss_McAir24.cpp:229
uint8_t flushTx()
Definition: Ss_McAir24.cpp:299
union DataMix Data
Definition: Ss_McAir24.h:47
void setChannel(uint8_t)
Definition: Ss_McAir24.cpp:64
void SendData(uint8_t del=30)
Send data using McAir protocol.
Definition: Ss_McAir24.cpp:444
uint8_t readRegister(uint8_t reg, uint8_t *value, uint8_t len)
Definition: Ss_McAir24.cpp:175
bool dataReady()
Definition: Ss_McAir24.cpp:109
char datachar[4]
Definition: Ss_McAir24.h:37
#define McAir24_EN_CRC
Definition: Ss_nrf24.h:16
#define McAir24_RX_DR
Definition: Ss_nrf24.h:49
#define R_RX_PAYLOAD
Definition: Ss_nrf24.h:131
void SendAirData(uint8_t, uint8_t, char, uint8_t del=30)
Definition: Ss_McAir24.cpp:390
void csnLow()
Definition: Ss_McAir24.cpp:323
void powerDown()
Definition: Ss_McAir24.cpp:327
void setTADDR(uint8_t *adr)
Definition: Ss_McAir24.cpp:97
#define RX_ADDR_P1
Definition: Ss_nrf24.h:59
#define McAir24_MAX_RT
Definition: Ss_nrf24.h:51
#define RX_PW_P1
Definition: Ss_nrf24.h:66
void setRADDR(uint8_t *adr)
Definition: Ss_McAir24.cpp:87
dataRF24 RefData
Definition: Ss_McAir24.h:56
#define McAir24_Reg04_SETUP_RETR
Definition: Ss_nrf24.h:33
void ceLow()
Definition: Ss_McAir24.cpp:315
#define McAir24_SPD_250K
Definition: Ss_nrf24.h:43
#define McAir24_Reg17_FIFO_STATUS
Definition: Ss_nrf24.h:72
#define RF_CH
Definition: Ss_nrf24.h:35
bool rxFifoEmpty()
Definition: Ss_McAir24.cpp:129
uint8_t spiWrite(uint8_t, uint8_t)
Definition: Ss_McAir24.cpp:285
#define RX_ADDR_P0
Definition: Ss_nrf24.h:58
bool isSignal(void)
Definition: Ss_McAir24.cpp:528
#define McAir24_FLUSH_TX
Definition: Ss_nrf24.h:133
void SetGE(uint8_t, uint8_t)
Definition: Ss_McAir24.cpp:455
#define RX_PW_P0
Definition: Ss_nrf24.h:65
bool waitAvailableTimeout(uint16_t)
Definition: Ss_McAir24.cpp:374
#define McAir24_Reg00_CONFIG
Definition: Ss_nrf24.h:12
#define McAir24_ADDR_LEN
Definition: Ss_McAir24.h:12
ss_nrf24 McAir24
Definition: Ss_McAir24.cpp:3
bool init(uint8_t, uint8_t)
Definition: Ss_McAir24.cpp:24
void csnHi()
Definition: Ss_McAir24.cpp:319
bool GetAirData()
Definition: Ss_McAir24.cpp:491
#define W_TX_PAYLOAD
Definition: Ss_nrf24.h:132
#define McAir24_MASK_TX_DS
Definition: Ss_nrf24.h:14
#define TX_ADDR
Definition: Ss_nrf24.h:64
void transferSync(uint8_t *dataout, uint8_t *datain, uint8_t len)
Definition: Ss_McAir24.cpp:6
#define McAir24_TX_DS
Definition: Ss_nrf24.h:50
#define McAir24_REGISTER_MASK
Definition: Ss_nrf24.h:130
#define McAir24_FLUSH_RX
Definition: Ss_nrf24.h:134
void setPayLoadSize(uint8_t)
Definition: Ss_McAir24.cpp:75
#define McAir24_Reg07_STATUS
Definition: Ss_nrf24.h:48
void send(uint8_t *value)
Definition: Ss_McAir24.cpp:197
uint8_t configRegister(uint8_t reg, uint8_t value)
Definition: Ss_McAir24.cpp:158
uint8_t readRegister(uint8_t reg)
Definition: Ss_McAir24.cpp:184
void ceHi()
Definition: Ss_McAir24.cpp:311
uint8_t flushRx()
Definition: Ss_McAir24.cpp:294
uint8_t spiRead(uint8_t)
Definition: Ss_McAir24.cpp:276
#define McAir24_PWR_UP
Definition: Ss_nrf24.h:18
#define McAir24_PRIM_RX
Definition: Ss_nrf24.h:19