Fix some dosctrings errors and trailing whitespaces
[contrib/upm.git] / src / nrf24l01 / nrf24l01.cxx
1 /*
2  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <iostream>
26 #include <unistd.h>
27 #include <stdlib.h>
28
29 #include "nrf24l01.h"
30
31 using namespace upm;
32
33 NRF24l01::NRF24l01 (uint8_t cs) {
34     mraa_init();
35     nrfInitModule (cs, 8);
36 }
37
38 NRF24l01::~NRF24l01 () {
39     mraa_result_t error = MRAA_SUCCESS;
40     error = mraa_spi_stop(m_spi);
41     if (error != MRAA_SUCCESS) {
42         mraa_result_print(error);
43     }
44     error = mraa_gpio_close (m_cePinCtx);
45     if (error != MRAA_SUCCESS) {
46         mraa_result_print(error);
47     }
48     error = mraa_gpio_close (m_csnPinCtx);
49     if (error != MRAA_SUCCESS) {
50         mraa_result_print(error);
51     }
52 }
53
54 void
55 NRF24l01::nrfInitModule (uint8_t chip_select, uint8_t chip_enable) {
56     mraa_result_t error = MRAA_SUCCESS;
57
58     m_csn         = chip_select;
59     m_ce         = chip_enable;
60     m_channel     = 1;
61
62     m_csnPinCtx = mraa_gpio_init (m_csn);
63     if (m_csnPinCtx == NULL) {
64         fprintf (stderr, "Are you sure that pin%d you requested is valid on your platform?", m_csn);
65         exit (1);
66     }
67
68     m_cePinCtx = mraa_gpio_init (m_ce);
69     if (m_cePinCtx == NULL) {
70         fprintf (stderr, "Are you sure that pin%d you requested is valid on your platform?", m_ce);
71         exit (1);
72     }
73
74     error = mraa_gpio_dir (m_csnPinCtx, MRAA_GPIO_OUT);
75     if (error != MRAA_SUCCESS) {
76         mraa_result_print (error);
77     }
78
79     error = mraa_gpio_dir (m_cePinCtx, MRAA_GPIO_OUT);
80     if (error != MRAA_SUCCESS) {
81         mraa_result_print (error);
82     }
83
84     nrfCELow ();
85     m_spi = mraa_spi_init (0);
86 }
87
88 void
89 NRF24l01::nrfConfigModule() {
90     /* Set RF channel */
91     nrfConfigRegister (RF_CH, m_channel);
92
93     /* Set length of incoming payload */
94     nrfConfigRegister (RX_PW_P0, m_payload);
95     nrfConfigRegister (RX_PW_P1, m_payload);
96     /* Set length of incoming payload for broadcast */
97     nrfConfigRegister (RX_PW_P2, m_payload);
98
99     /* Start receiver */
100     nrfPowerUpRX ();
101     nrfFlushRX ();
102 }
103
104 /* Clocks only one byte into the given MiRF register */
105 void
106 NRF24l01::nrfConfigRegister(uint8_t reg, uint8_t value) {
107     nrfCSOn ();
108     mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
109     mraa_spi_write (m_spi, value);
110     nrfCSOff ();
111 }
112
113 void
114 NRF24l01::nrfPowerUpRX() {
115     m_ptx = 0;
116     nrfCELow();
117     nrfConfigRegister(CONFIG, NRF_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) );
118     nrfCEHigh();
119     nrfConfigRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
120 }
121
122 void
123 NRF24l01::nrfFlushRX() {
124     nrfCSOn ();
125     mraa_spi_write (m_spi, FLUSH_RX);
126     nrfCSOff ();
127 }
128
129 /* Sets the receiving address */
130 void
131 NRF24l01::nrfSetRXaddr(uint8_t * addr) {
132     nrfCELow();
133     nrfWriteRegister(RX_ADDR_P1, addr, ADDR_LEN);
134     nrfCEHigh();
135 }
136
137 /* Sets the transmitting address */
138 void
139 NRF24l01::nrfSetTXaddr(uint8_t * addr)
140 {
141     /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
142     nrfWriteRegister (RX_ADDR_P0, addr, ADDR_LEN);
143     nrfWriteRegister (TX_ADDR, addr, ADDR_LEN);
144 }
145
146 /* The broadcast address should be 0xFFFFF */
147 void
148 NRF24l01::nrfSetBroadcastAddr (uint8_t * addr) {
149     nrfCELow ();
150     nrfWriteRegister (RX_ADDR_P2, addr, ADDR_LEN);
151     nrfCEHigh ();
152 }
153
154 void
155 NRF24l01::nrfSetPayload (uint8_t load) {
156     m_payload = load;
157 }
158
159 void
160 NRF24l01::nrfWriteRegister(uint8_t reg, uint8_t * value, uint8_t len)
161 {
162     nrfCSOn ();
163     mraa_spi_write (m_spi, W_REGISTER | (REGISTER_MASK & reg));
164     nrfTransmitSync(value, len);
165     nrfCSOff ();
166 }
167
168 void
169 NRF24l01::nrfTransmitSync(uint8_t *dataout, uint8_t len){
170     uint8_t i;
171     for(i = 0; i < len; i++) {
172         mraa_spi_write (m_spi, dataout[i]);
173     }
174 }
175
176 /* Checks if data is available for reading */
177 bool
178 NRF24l01::nrfDataReady() {
179     uint8_t status = nrfGetStatus();
180     if ( status & (1 << RX_DR) ) {
181         return 1;
182     }
183
184     return !nrfRXFifoEmpty();
185 }
186
187 uint8_t
188 NRF24l01::nrfGetStatus () {
189     uint8_t rv;
190     nrfReadRegister (STATUS, &rv, 1);
191     return rv;
192 }
193
194 /* Reads an array of bytes from the given start position in the MiRF registers. */
195 void
196 NRF24l01::nrfReadRegister (uint8_t reg, uint8_t * value, uint8_t len)
197 {
198     nrfCSOn ();
199     mraa_spi_write (m_spi, R_REGISTER | (REGISTER_MASK & reg));
200     nrfTransferSync (value, value, len);
201     nrfCSOff ();
202 }
203
204 void
205 NRF24l01::nrfTransferSync (uint8_t *dataout,uint8_t *datain,uint8_t len) {
206     uint8_t i;
207     for(i = 0;i < len;i++) {
208         datain[i] = mraa_spi_write (m_spi, dataout[i]);
209     }
210 }
211
212 bool
213 NRF24l01::nrfRXFifoEmpty () {
214     uint8_t fifo_status;
215     nrfReadRegister (FIFO_STATUS, &fifo_status, sizeof(fifo_status));
216     return (fifo_status & (1 << RX_EMPTY));
217 }
218
219 /* Reads payload bytes into data array */
220 void
221 NRF24l01::nrfGetData (uint8_t * data)
222 {
223     nrfCSOn ();
224     /* Send cmd to read rx payload */
225     mraa_spi_write (m_spi, R_RX_PAYLOAD);
226     /* Read payload */
227     nrfTransferSync(data, data, m_payload);
228     nrfCSOff ();
229     nrfConfigRegister(STATUS, (1<<RX_DR));
230 }
231
232 /* Sends a data package to the default address. Be sure to send the correct
233  * amount of bytes as configured as payload on the receiver. */
234 void
235 NRF24l01::nrfSend(uint8_t * value) {
236     uint8_t status;
237     status = nrfGetStatus();
238
239     while (m_ptx) {
240         status = nrfGetStatus();
241
242         if((status & ((1 << TX_DS)  | (1 << MAX_RT)))){
243             m_ptx = 0;
244             break;
245         }
246     } // Wait until last paket is send
247
248     nrfCELow();
249     nrfPowerUpTX();                            // Set to transmitter mode , Power up
250     nrfCSOn ();
251     mraa_spi_write (m_spi, FLUSH_TX);        // Write cmd to flush tx fifo
252     nrfCSOff ();
253
254     nrfCSOn ();
255     mraa_spi_write (m_spi, W_TX_PAYLOAD);     // Write cmd to write payload
256     nrfTransmitSync(value, m_payload);        // Write payload
257     nrfCSOff ();
258     nrfCEHigh();                            // Start transmission
259 }
260
261 void
262 NRF24l01::nrfSend () {
263     nrfSend (m_txBuffer);
264 }
265
266 bool
267 NRF24l01::nrfIsSending () {
268     uint8_t status;
269     if (m_ptx)    { // Sending mode.
270         status = nrfGetStatus();
271         /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
272         if((status & ((1 << TX_DS)  | (1 << MAX_RT)))){
273             nrfPowerUpRX();
274             return false;
275         }
276         return true;
277     }
278     return false;
279 }
280
281 void
282 NRF24l01::nrfPowerUpTX () {
283     m_ptx = 1;
284     nrfConfigRegister (CONFIG, NRF_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
285 }
286
287 void
288 NRF24l01::nrfPowerDown () {
289     nrfCELow ();
290     nrfConfigRegister (CONFIG, NRF_CONFIG);
291 }
292
293 mraa_result_t
294 NRF24l01::nrfCEHigh () {
295     return mraa_gpio_write (m_cePinCtx, HIGH);
296 }
297
298 mraa_result_t
299 NRF24l01::nrfCELow () {
300     return mraa_gpio_write (m_cePinCtx, LOW);
301 }
302
303 mraa_result_t
304 NRF24l01::nrfCSOn () {
305     return mraa_gpio_write (m_csnPinCtx, LOW);
306 }
307
308 mraa_result_t
309 NRF24l01::nrfCSOff () {
310     return mraa_gpio_write (m_csnPinCtx, HIGH);
311 }
312
313 void
314 NRF24l01::nrfListenForChannel() {
315     if(!nrfIsSending() && nrfDataReady()) {
316         nrfGetData(m_rxBuffer);
317         dataRecievedHandler(); /* let know that data arrived */
318     }
319 }