Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
cyrf6936.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
27 #include "cyrf6936.h"
28 #include "mcu_periph/spi.h"
29 #include "mcu_periph/gpio.h"
30 #include "mcu_periph/sys_time.h"
32 
33 #include "mcu_periph/uart.h"
34 #include "pprzlink/messages.h"
36 
37 /* Static functions used in the different statuses */
38 static bool cyrf6936_write_register(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data);
39 static bool cyrf6936_write_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data[],
40  const uint8_t length);
41 static bool cyrf6936_read_register(struct Cyrf6936 *cyrf, const uint8_t addr);
42 static bool cyrf6936_read_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t length);
43 
47 void cyrf6936_init(struct Cyrf6936 *cyrf, struct spi_periph *spi_p, const uint8_t slave_idx, const uint32_t rst_port,
48  const uint16_t rst_pin)
49 {
50  /* Set spi_peripheral and the status */
51  cyrf->spi_p = spi_p;
52  cyrf->status = CYRF6936_UNINIT;
53  cyrf->has_irq = false;
54 
55  /* Set the spi transaction */
56  cyrf->spi_t.cpol = SPICpolIdleLow;
57  cyrf->spi_t.cpha = SPICphaEdge1;
58  cyrf->spi_t.dss = SPIDss8bit;
59  cyrf->spi_t.bitorder = SPIMSBFirst;
60  cyrf->spi_t.cdiv = SPIDiv64;
61 
62  cyrf->spi_t.input_length = 0;
63  cyrf->spi_t.output_length = 0;
64  cyrf->spi_t.input_buf = cyrf->input_buf;
65  cyrf->spi_t.output_buf = cyrf->output_buf;
66  cyrf->spi_t.slave_idx = slave_idx;
68  cyrf->spi_t.status = SPITransDone;
69 
70  /* Reset the CYRF6936 chip (busy waiting) */
71  gpio_setup_output(rst_port, rst_pin);
72  gpio_set(rst_port, rst_pin);
73  sys_time_usleep(100);
74  gpio_clear(rst_port, rst_pin);
75  sys_time_usleep(100);
76 
77  /* Get the MFG ID */
79  cyrf->buffer_idx = 0;
81 }
82 
86 void cyrf6936_event(struct Cyrf6936 *cyrf)
87 {
88  int i;
89  // Check if cyrf is initialized
90  if (cyrf->status == CYRF6936_UNINIT) {
91  return;
92  }
93 
94  // Check if there is still a transaction in progress
95  if (cyrf->spi_t.status == SPITransPending || cyrf->spi_t.status == SPITransRunning) {
96  return;
97  }
98 
99  /* Check the status of the cyrf */
100  switch (cyrf->status) {
101 
102  /* Getting the MFG id */
103  case CYRF6936_GET_MFG_ID:
104  // When the last transaction isn't failed send the next
105  if (cyrf->spi_t.status != SPITransFailed) {
106  cyrf->buffer_idx++;
107  }
108 
109  cyrf->spi_t.status = SPITransDone;
110 
111  // Switch for the different states
112  switch (cyrf->buffer_idx) {
113  case 0:
115  break;
116  case 1:
118  break;
119  case 2:
120  // Copy the MFG id
121  for (i = 0; i < 6; i++) {
122  cyrf->mfg_id[i] = cyrf->input_buf[i + 1];
123  }
124 
126  break;
127  default:
128  cyrf->status = CYRF6936_IDLE;
129  break;
130  }
131  break;
132 
133  /* Do a multi write */
134  case CYRF6936_MULTIWRITE:
135  // When the last transaction isn't failed send the next
136  if (cyrf->spi_t.status != SPITransFailed) {
137  cyrf->buffer_idx++;
138  }
139 
140  cyrf->spi_t.status = SPITransDone;
141 
142  // When we are done writing
143  if (cyrf->buffer_idx == cyrf->buffer_length) {
144  cyrf->status = CYRF6936_IDLE;
145  break;
146  }
147 
148  // Write the next register from the buffer
150  ((uint8_t ( *)[2])cyrf->buffer)[cyrf->buffer_idx][0],
151  ((uint8_t ( *)[2])cyrf->buffer)[cyrf->buffer_idx][1]);
152  break;
153 
154  /* Do a write of the data code */
155  case CYRF6936_DATA_CODE:
156  break;
157 
158  /* Do a write of channel, sop, data and crc */
160  // When the last transaction isn't failed send the next
161  if (cyrf->spi_t.status != SPITransFailed) {
162  cyrf->buffer_idx++;
163  }
164 
165  cyrf->spi_t.status = SPITransDone;
166 
167  // Switch for the different states
168  switch (cyrf->buffer_idx) {
169  case 0: // Write the CRC LSB
171  break;
172  case 1: // Write the CRC MSB
174  break;
175  case 2: // Write the SOP code
176  cyrf6936_write_block(cyrf, CYRF_SOP_CODE, &(cyrf->buffer[2]), 8);
177  break;
178  case 3: // Write the DATA code
179  cyrf6936_write_block(cyrf, CYRF_DATA_CODE, &(cyrf->buffer[10]), 16);
180  break;
181  case 4: // Write the Channel
182  cyrf6936_write_register(cyrf, CYRF_CHANNEL, cyrf->buffer[26]);
183  break;
184  default:
185  cyrf->status = CYRF6936_IDLE;
186  break;
187  }
188  break;
189 
190  /* Do a read of the receive irq status, receive status and the receive packet */
192  // When the last transaction isn't failed send the next
193  if (cyrf->spi_t.status != SPITransFailed) {
194  cyrf->buffer_idx++;
195  }
196 
197  cyrf->spi_t.status = SPITransDone;
198 
199  // Switch for the different states
200  switch (cyrf->buffer_idx) {
201  case 0: // Read the receive IRQ status
203  break;
204  case 1: // Read the send IRQ status
205  cyrf->rx_irq_status = cyrf->input_buf[1];
207  break;
208  case 2: // Read the receive status
209  cyrf->tx_irq_status = cyrf->input_buf[1];
211  break;
212  case 3: // Set the packet length
213  cyrf->rx_status = cyrf->input_buf[1];
215  break;
216  case 4: // Read the receive packet
217  cyrf->rx_count = cyrf->input_buf[1];
219  break;
220  default:
221  // Copy the receive packet
222  for (i = 0; i < 16; i++) {
223  cyrf->rx_packet[i] = cyrf->input_buf[i + 1];
224  }
225 
226  cyrf->has_irq = true;
227  cyrf->status = CYRF6936_IDLE;
228  break;
229  }
230  break;
231 
232  /* The CYRF6936 is busy sending a packet */
233  case CYRF6936_SEND:
234  // When the last transaction isn't failed send the next
235  if (cyrf->spi_t.status != SPITransFailed) {
236  cyrf->buffer_idx++;
237  }
238 
239  cyrf->spi_t.status = SPITransDone;
240 
241  // Switch for the different states
242  switch (cyrf->buffer_idx) {
243  case 0: // Set the packet length
245  break;
246  case 1: // Clear the TX buffer
248  break;
249  case 2: // Write the send packet
250  cyrf6936_write_block(cyrf, CYRF_TX_BUFFER, &cyrf->buffer[1], 16);
251  break;
252  case 3: // Send the packet
254  break;
255  default:
256  cyrf->status = CYRF6936_IDLE;
257  break;
258  }
259  break;
260 
261  /* This should not happen */
262  default:
263  break;
264  }
265 }
266 
270 static bool cyrf6936_write_register(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data)
271 {
272  return cyrf6936_write_block(cyrf, addr, &data, 1);
273 }
274 
278 static bool cyrf6936_write_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data[],
279  const uint8_t length)
280 {
281  uint8_t i;
282  /* Check if there is already a SPI transaction busy */
283  if (cyrf->spi_t.status != SPITransDone) {
284  return false;
285  }
286 
287  /* Set the buffer and commit the transaction */
288  cyrf->spi_t.output_length = length + 1;
289  cyrf->spi_t.input_length = 0;
290  cyrf->output_buf[0] = addr | CYRF_DIR;
291 
292  // Copy the data
293  for (i = 0; i < length; i++) {
294  cyrf->output_buf[i + 1] = data[i];
295  }
296 
297  // Submit the transaction
298  return spi_submit(cyrf->spi_p, &(cyrf->spi_t));
299 }
300 
304 static bool cyrf6936_read_register(struct Cyrf6936 *cyrf, const uint8_t addr)
305 {
306  return cyrf6936_read_block(cyrf, addr, 1);
307 }
308 
312 static bool cyrf6936_read_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t length)
313 {
314  if (cyrf->spi_t.status != SPITransDone) {
315  return false;
316  }
317 
318  /* Set the buffer and commit the transaction */
319  cyrf->spi_t.output_length = 1;
320  cyrf->spi_t.input_length = length + 1;
321  cyrf->output_buf[0] = addr;
322 
323  // Submit the transaction
324  return spi_submit(cyrf->spi_p, &(cyrf->spi_t));
325 }
326 
330 bool cyrf6936_write(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data)
331 {
332  const uint8_t data_multi[][2] = {
333  {addr, data}
334  };
335  return cyrf6936_multi_write(cyrf, data_multi, 1);
336 }
337 
341 bool cyrf6936_multi_write(struct Cyrf6936 *cyrf, const uint8_t data[][2], const uint8_t length)
342 {
343  uint8_t i;
344  /* Check if the cyrf6936 isn't busy */
345  if (cyrf->status != CYRF6936_IDLE) {
346  return false;
347  }
348 
349  // Set the status
350  cyrf->status = CYRF6936_MULTIWRITE;
351 
352  /* Set the multi write */
353  cyrf->buffer_length = length;
354  cyrf->buffer_idx = 0;
355 
356  // Copy the buffer
357  for (i = 0; i < length; i++) {
358  cyrf->buffer[i * 2] = data[i][0];
359  cyrf->buffer[i * 2 + 1] = data[i][1];
360  }
361 
362  /* Write the first regiter */
363  if (length > 0) {
364  cyrf6936_write_register(cyrf, data[0][0], data[0][1]);
365  }
366 
367  return true;
368 }
369 
373 bool cyrf6936_write_chan_sop_data_crc(struct Cyrf6936 *cyrf, const uint8_t chan, const uint8_t sop_code[],
374  const uint8_t data_code[], const uint16_t crc_seed)
375 {
376  uint8_t i;
377  /* Check if the cyrf6936 isn't busy */
378  if (cyrf->status != CYRF6936_IDLE) {
379  return false;
380  }
381 
382  // Set the status
384 
385  // Copy the CRC
386  cyrf->buffer[0] = crc_seed & 0xFF;
387  cyrf->buffer[1] = (crc_seed >> 8) & 0xFF;
388 
389  // Copy the SOP code
390  for (i = 0; i < 8; i++) {
391  cyrf->buffer[i + 2] = sop_code[i];
392  }
393 
394  // Copy the DATA code
395  for (i = 0; i < 16; i++) {
396  cyrf->buffer[i + 10] = data_code[i];
397  }
398 
399  // Copy the channel
400  cyrf->buffer[26] = chan;
401 
402  /* Try to write the CRC LSB */
403  cyrf->buffer_idx = 0;
405 
406  return true;
407 }
408 
413 {
414  /* Check if the cyrf6936 isn't busy */
415  if (cyrf->status != CYRF6936_IDLE) {
416  return false;
417  }
418 
419  // Set the status
421 
422  /* Try to read the RX status */
423  cyrf->buffer_idx = 0;
425 
426  return true;
427 }
428 
432 bool cyrf6936_send(struct Cyrf6936 *cyrf, const uint8_t data[], const uint8_t length)
433 {
434  int i;
435 
436  /* Check if the cyrf6936 isn't busy */
437  if (cyrf->status != CYRF6936_IDLE) {
438  return false;
439  }
440 
441  // Set the status
442  cyrf->status = CYRF6936_SEND;
443 
444  // Copy the length and the data
445  cyrf->buffer[0] = length;
446  for (i = 0; i < length; i++) {
447  cyrf->buffer[i + 1] = data[i];
448  }
449 
450  /* Try to set the packet length */
451  cyrf->buffer_idx = 0;
453 
454  return true;
455 }
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_arch.c:33
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
Definition: gpio_arch.h:104
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
Definition: gpio_arch.h:114
void sys_time_usleep(uint32_t us)
sys_time_usleep(uint32_t us)
void cyrf6936_event(struct Cyrf6936 *cyrf)
The on event call for the CYRF6936 chip.
Definition: cyrf6936.c:86
void cyrf6936_init(struct Cyrf6936 *cyrf, struct spi_periph *spi_p, const uint8_t slave_idx, const uint32_t rst_port, const uint16_t rst_pin)
Initializing the cyrf chip.
Definition: cyrf6936.c:47
bool cyrf6936_multi_write(struct Cyrf6936 *cyrf, const uint8_t data[][2], const uint8_t length)
Write to multiple registers one byte.
Definition: cyrf6936.c:341
bool cyrf6936_write_chan_sop_data_crc(struct Cyrf6936 *cyrf, const uint8_t chan, const uint8_t sop_code[], const uint8_t data_code[], const uint16_t crc_seed)
Set the channel, SOP code, DATA code and the CRC seed.
Definition: cyrf6936.c:373
bool cyrf6936_write(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data)
Write to one register.
Definition: cyrf6936.c:330
static bool cyrf6936_write_register(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data)
Write a byte to a register.
Definition: cyrf6936.c:270
bool cyrf6936_read_rx_irq_status_packet(struct Cyrf6936 *cyrf)
Read the RX IRQ status register, the rx status register and the rx packet.
Definition: cyrf6936.c:412
bool cyrf6936_send(struct Cyrf6936 *cyrf, const uint8_t data[], const uint8_t length)
Send a packet with a certain length.
Definition: cyrf6936.c:432
static bool cyrf6936_read_register(struct Cyrf6936 *cyrf, const uint8_t addr)
Read a byte from a register.
Definition: cyrf6936.c:304
static bool cyrf6936_write_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data[], const uint8_t length)
Write multiple bytes to a register.
Definition: cyrf6936.c:278
static bool cyrf6936_read_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t length)
Read multiple bytes from a register.
Definition: cyrf6936.c:312
Driver for the cyrf6936 2.4GHz radio chip.
struct spi_transaction spi_t
The SPI transaction used for the writing and reading of registers.
Definition: cyrf6936.h:50
@ CYRF6936_DATA_CODE
The chip is writing a data code.
Definition: cyrf6936.h:41
@ CYRF6936_IDLE
The chip is idle and can be used.
Definition: cyrf6936.h:38
@ CYRF6936_GET_MFG_ID
The chip is busy with getting the manufacturer ID.
Definition: cyrf6936.h:39
@ CYRF6936_MULTIWRITE
The chip is writing multiple registers.
Definition: cyrf6936.h:40
@ CYRF6936_RX_IRQ_STATUS_PACKET
The chip is getting the receive irq status, receive status and the receive packet.
Definition: cyrf6936.h:43
@ CYRF6936_UNINIT
The chip isn't initialized.
Definition: cyrf6936.h:37
@ CYRF6936_SEND
The chip is busy sending a packet.
Definition: cyrf6936.h:44
@ CYRF6936_CHAN_SOP_DATA_CRC
The chip is setting the channel, SOP code, DATA code and the CRC seed.
Definition: cyrf6936.h:42
struct spi_periph * spi_p
The SPI peripheral for the connection.
Definition: cyrf6936.h:49
uint8_t rx_status
The last receive status.
Definition: cyrf6936.h:63
uint8_t buffer_idx
The index of the buffer used for MULTIWRITE and used as sub-status for other statuses.
Definition: cyrf6936.h:57
uint8_t rx_count
The length of the received packet.
Definition: cyrf6936.h:64
uint8_t buffer_length
The length of the buffer used for MULTIWRITE.
Definition: cyrf6936.h:56
enum Cyrf6936Status status
The status of the CYRF6936 chip.
Definition: cyrf6936.h:51
bool has_irq
When the CYRF6936 is done reading the irq.
Definition: cyrf6936.h:59
uint8_t buffer[CYRF6936_MAX_BUFFER]
The buffer used to write/read multiple registers.
Definition: cyrf6936.h:55
uint8_t input_buf[17]
The input buffer for the SPI transaction.
Definition: cyrf6936.h:52
uint8_t tx_irq_status
The last send interrupt status.
Definition: cyrf6936.h:61
uint8_t mfg_id[6]
The manufacturer id of the CYRF6936 chip.
Definition: cyrf6936.h:60
uint8_t output_buf[17]
The output buffer for the SPI transaction.
Definition: cyrf6936.h:53
uint8_t rx_packet[16]
The last received packet.
Definition: cyrf6936.h:65
uint8_t rx_irq_status
The last receive interrupt status.
Definition: cyrf6936.h:62
#define CYRF_TXE_IRQEN
#define CYRF_TX_CLR
#define CYRF_DIR
Bit for enabling writing.
Definition: cyrf6936_regs.h:78
#define CYRF_TX_GO
#define CYRF_TXC_IRQEN
@ CYRF_CHANNEL
Definition: cyrf6936_regs.h:32
@ CYRF_SOP_CODE
Definition: cyrf6936_regs.h:66
@ CYRF_MFG_ID
Definition: cyrf6936_regs.h:69
@ CYRF_RX_COUNT
Definition: cyrf6936_regs.h:41
@ CYRF_CRC_SEED_LSB
Definition: cyrf6936_regs.h:53
@ CYRF_TX_LENGTH
Definition: cyrf6936_regs.h:33
@ CYRF_TX_CTRL
Definition: cyrf6936_regs.h:34
@ CYRF_CRC_SEED_MSB
Definition: cyrf6936_regs.h:54
@ CYRF_RX_IRQ_STATUS
Definition: cyrf6936_regs.h:39
@ CYRF_RX_STATUS
Definition: cyrf6936_regs.h:40
@ CYRF_DATA_CODE
Definition: cyrf6936_regs.h:67
@ CYRF_TX_BUFFER
Definition: cyrf6936_regs.h:64
@ CYRF_TX_IRQ_STATUS
Definition: cyrf6936_regs.h:36
@ CYRF_RX_BUFFER
Definition: cyrf6936_regs.h:65
Some architecture independent helper functions for GPIOs.
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:155
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:156
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:154
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:157
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:150
uint16_t input_length
number of data words to read
Definition: spi.h:151
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:159
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:149
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:153
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:158
uint16_t output_length
number of data words to write
Definition: spi.h:152
enum SPITransactionStatus status
Definition: spi.h:162
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:533
@ SPICphaEdge1
CPHA = 0.
Definition: spi.h:74
@ SPITransFailed
Definition: spi.h:100
@ SPITransRunning
Definition: spi.h:98
@ SPITransPending
Definition: spi.h:97
@ SPITransDone
Definition: spi.h:101
@ SPICpolIdleLow
CPOL = 0.
Definition: spi.h:83
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition: spi.h:63
@ SPIMSBFirst
Definition: spi.h:112
@ SPIDiv64
Definition: spi.h:125
@ SPIDss8bit
Definition: spi.h:90
SPI peripheral structure.
Definition: spi.h:174
Generic interface for radio control modules.
Architecture independent SPI (Serial Peripheral Interface) API.
Architecture independent timing functions.
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98