Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
bluegiga.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Kirk Scheper <kirkscheper@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  */
22 
28 #include "mcu_periph/sys_time.h"
30 #include "mcu_periph/gpio.h"
31 #include "mcu_periph/spi.h"
32 
33 // for memset
34 #include <string.h>
35 
36 #ifndef BLUEGIGA_SPI_DEV
37 #error "bluegiga: must define a BLUEGIGA_SPI_DEV"
38 #endif
39 
40 // Bluegiga: DRDY defaults to SuperbitRf DRDY
41 #ifndef BLUEGIGA_DRDY_GPIO
42 #define BLUEGIGA_DRDY_GPIO SUPERBITRF_DRDY_PORT
43 #endif
44 
45 #ifndef BLUEGIGA_DRDY_GPIO_PIN
46 #define BLUEGIGA_DRDY_GPIO_PIN SUPERBITRF_DRDY_PIN
47 #endif
48 
52 
53 signed char bluegiga_rssi[256]; // values initialized with 127
54 unsigned char telemetry_copy[20];
55 
56 void bluegiga_load_tx(struct bluegiga_periph *p);
57 void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data);
58 void bluegiga_receive(struct spi_transaction *trans);
59 
60 // Functions for the generic link device device API
62 {
63  // check if there is enough space for message
64  // NB if BLUEGIGA_BUFFER_SIZE is smaller than 256 then an additional check is needed that len < BLUEGIGA_BUFFER_SIZE
65  if (len - 1 <= ((p->tx_extract_idx - p->tx_insert_idx - 1 + BLUEGIGA_BUFFER_SIZE) % BLUEGIGA_BUFFER_SIZE)) {
66  return TRUE;
67  }
68 
69  return FALSE;
70 }
71 static void dev_put_byte(struct bluegiga_periph *p, uint8_t byte)
72 {
73  bluegiga_transmit(p, byte);
74 }
75 static void dev_send_message(struct bluegiga_periph *p)
76 {
77  p->end_of_msg = p->tx_insert_idx;
78 }
80 {
81  return bluegiga_ch_available(p);
82 }
84 {
85  uint8_t ret = p->rx_buf[p->rx_extract_idx];
87  return ret;
88 }
89 
90 // Functions for the generic spi device API
91 static void trans_cb(struct spi_transaction *trans)
92 {
93  bluegiga_receive(trans);
94 }
95 
96 /* check if character available in receive buffer */
98 {
99  return (p->rx_extract_idx != p->rx_insert_idx);
100 }
101 
102 /* safe increment of circular buffer */
104 {
105  *buf_idx = (*buf_idx + len) % BLUEGIGA_BUFFER_SIZE;
106 }
107 
108 #if PERIODIC_TELEMETRY
110 
111 uint32_t last_ts = 0;
112 static void send_bluegiga(struct transport_tx *trans, struct link_device *dev)
113 {
114  uint32_t now_ts = get_sys_time_msec();
115 
116  if (now_ts > last_ts) {
117  uint32_t rate = 1000 * bluegiga_p.bytes_recvd_since_last / (now_ts - last_ts);
118  pprz_msg_send_BLUEGIGA(trans, dev, AC_ID, &rate, 20, telemetry_copy);
119 
121  last_ts = now_ts;
122  }
123 }
124 #endif
125 
127 {
128 #ifdef MODEM_LED
129  LED_INIT(MODEM_LED);
130 #endif
131 
132  // configure the SPI bus
137  bluegiga_spi.slave_idx = 0; // Not used for SPI-Slave: always NSS pin
145 
146  // Configure generic link device
147  p->device.periph = (void *)(p);
153 
154  // initialize peripheral variables
155  p->rx_insert_idx = 0;
156  p->rx_extract_idx = 0;
157  p->tx_insert_idx = 0;
158  p->tx_extract_idx = 0;
159 
160  for (int i = 0; i < bluegiga_spi.input_length; i++) {
161  p->work_rx[i] = 0;
162  }
163  for (int i = 0; i < bluegiga_spi.output_length; i++) {
164  p->work_tx[i] = 0;
165  }
166  for (int i = 0; i < 255; i++) {
167  bluegiga_rssi[i] = 127;
168  }
169 
170  p->bytes_recvd_since_last = 0;
171  p->end_of_msg = p->tx_insert_idx;
172 
173  // set DRDY interrupt pin for spi master triggered on falling edge
176 
178 
179 #if PERIODIC_TELEMETRY
180  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_BLUEGIGA, send_bluegiga);
181 #endif
182 
183  // register spi slave read for transaction
184  spi_slave_register(&(BLUEGIGA_SPI_DEV), &bluegiga_spi);
185 }
186 
187 /* Add one byte to the end of tx circular buffer */
189 {
191  p->tx_buf[p->tx_insert_idx] = data;
193  }
194 }
195 
196 /* Load waiting data into tx peripheral buffer */
198 {
199  // check data available in buffer to send
201  if (packet_len > 19) {
202  packet_len = 19;
203  }
204 
205  if (packet_len && coms_status == BLUEGIGA_IDLE) {
206  uint8_t i;
207  // attach header with data length of real data in 20 char data string
208  p->work_tx[0] = packet_len;
209 
210  // copy data from working buffer to spi output buffer
211  for (i = 0; i < packet_len; i++) {
212  p->work_tx[i + 1] = p->tx_buf[(p->tx_extract_idx + i) % BLUEGIGA_BUFFER_SIZE];
213  }
214  bluegiga_increment_buf(&p->tx_extract_idx, packet_len);
215 
216  // clear unused bytes
217  for (i = packet_len + 1; i < bluegiga_spi.output_length; i++) {
218  p->work_tx[i] = 0;
219  }
220 
222  }
223 }
224 
225 /* read data from dma if available, set as call back of successful spi exchange
226  *
227  * TODO Remove use of bluegiga_p global in following function
228  */
230 {
231  if (trans->status == SPITransSuccess) {
232  // handle successful msg send
233  if (coms_status == BLUEGIGA_SENDING) {
234  // empty transfer buffer
235  for (uint8_t i = 0; i < trans->output_length; i++) {
236  trans->output_buf[i] = 0;
237  }
238  }
239 
240  /*
241  * 0xff communication lost with ground station
242  * 0xfe RSSI value from broadcaster
243  * 0xfd Change in broadcast mode
244  * 0xfc Receive all recorded RSSI
245  * <=20 Data package from ground station
246  */
247 
248  uint8_t packet_len = 0;
249  uint8_t read_offset = 0;
250  switch (trans->input_buf[0]) {
251  case 0xff: // communication lost with ground station
252 #ifdef MODEM_LED
253  LED_OFF(MODEM_LED);
254 #endif
256  gpio_set(BLUEGIGA_DRDY_GPIO, BLUEGIGA_DRDY_GPIO_PIN); // Reset interrupt pin
257  break;
258  case 0xfe: // RSSI value from broadcaster
259  bluegiga_rssi[trans->input_buf[1]] = trans->input_buf[2];
260  packet_len = trans->input_buf[3];
261  read_offset = 4;
262  break;
263  case 0xfd: // Change in broadcast mode
264  gpio_set(BLUEGIGA_DRDY_GPIO, BLUEGIGA_DRDY_GPIO_PIN); // Reset interrupt pin
265 
266  // fetch scan status
267  if (trans->input_buf[1] == 1) {
269  } else {
271  }
272  break;
273  case 0xfc: // Receive all recorded RSSI
274  for (uint8_t i = 0; i < trans->input_buf[1]; i++) {
275  bluegiga_rssi[trans->input_buf[2] + i] = trans->input_buf[3 + i];
276  }
277  break;
278  default:
279  packet_len = trans->input_buf[0]; // length of transmitted message
280  read_offset = 1;
281  }
282 
283  // handle incoming datalink message
284  if (packet_len > 0 && packet_len <= trans->input_length) {
285  // Handle received message
286  for (uint8_t i = 0; i < packet_len; i++) {
287  bluegiga_p.rx_buf[(bluegiga_p.rx_insert_idx + i) % BLUEGIGA_BUFFER_SIZE] = trans->input_buf[i + read_offset];
288  }
290  bluegiga_p.bytes_recvd_since_last += packet_len;
292 
293  for (uint8_t i = 0; i < trans->input_length; i++) {
294  telemetry_copy[i] = trans->input_buf[i];
295  }
296  } else {
298  }
299 
300  // load next message to be sent into work buffer, needs to be loaded before calling spi_slave_register
302 
303  // register spi slave read for next transaction
304  spi_slave_register(&(BLUEGIGA_SPI_DEV), &bluegiga_spi);
305  }
306 }
307 
308 /* command bluetooth to switch to active scan mode to get rssi values from neighbouring drones */
310 {
311 
312  memset(p->work_tx, 0, 20);
313  p->work_tx[0] = 0xfd; // change broadcast mode header
314 
316 
317  // trigger bluegiga to read direct command
319 }
320 
321 /* Request list of all recorded RSSI */
323 {
324 
325  memset(p->work_tx, 0, 20);
326  p->work_tx[0] = 0xfc;
327 
329 
330  // trigger bluegiga to read direct command
332 }
static uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
Definition: sys_time_arch.h:49
void bluegiga_increment_buf(uint8_t *buf_idx, uint8_t len)
Definition: bluegiga.c:103
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
struct link_device device
Generic device interface.
Definition: bluegiga.h:61
signed char bluegiga_rssi[256]
Definition: bluegiga.c:53
#define BLUEGIGA_BUFFER_SIZE
Definition: bluegiga.h:41
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
Generic transmission transport header.
Definition: transport.h:89
uint16_t output_length
number of data words to write
Definition: spi.h:146
static uint8_t dev_get_byte(struct bluegiga_periph *p)
Definition: bluegiga.c:83
Periodic telemetry system header (includes downlink utility and generated code).
CPHA = 1.
Definition: spi.h:69
The com is sending.
Definition: bluegiga.h:36
BlueGigaStatus
Definition: bluegiga.h:33
Some architecture independent helper functions for GPIOs.
uint8_t rx_buf[BLUEGIGA_BUFFER_SIZE]
Definition: bluegiga.h:50
SPI transaction structure.
Definition: spi.h:142
uint8_t tx_extract_idx
Definition: bluegiga.h:56
struct bluegiga_periph bluegiga_p
Definition: bluegiga.c:50
void(* SPICallback)(struct spi_transaction *trans)
SPI Callback function.
Definition: spi.h:130
CPOL = 1.
Definition: spi.h:78
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
uint8_t tx_insert_idx
Definition: bluegiga.h:55
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
uint32_t bytes_recvd_since_last
Definition: bluegiga.h:64
static void trans_cb(struct spi_transaction *trans)
Definition: bluegiga.c:91
#define BLUEGIGA_DRDY_GPIO
Definition: bluegiga.c:42
#define FALSE
Definition: std.h:5
enum BlueGigaStatus coms_status
Definition: bluegiga.c:49
void bluegiga_init(struct bluegiga_periph *p)
Definition: bluegiga.c:126
Architecture independent SPI (Serial Peripheral Interface) API.
The com is switched from data link to rssi scanning.
Definition: bluegiga.h:37
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
#define LED_INIT(i)
Definition: led_hw.h:41
#define TRUE
Definition: std.h:4
Definition: spi.h:84
void gpio_set(uint32_t port, uint16_t pin)
Set a gpio output to high level.
Definition: gpio_ardrone.c:54
void bluegiga_load_tx(struct bluegiga_periph *p)
Definition: bluegiga.c:197
Architecture independent timing functions.
bool_t bluegiga_ch_available(struct bluegiga_periph *p)
Definition: bluegiga.c:97
static int dev_char_available(struct bluegiga_periph *p)
Definition: bluegiga.c:79
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
void gpio_clear(uint32_t port, uint16_t pin)
Clear a gpio output to low level.
Definition: gpio_ardrone.c:70
uint8_t work_rx[20]
Definition: bluegiga.h:59
unsigned long uint32_t
Definition: types.h:18
uint8_t tx_buf[BLUEGIGA_BUFFER_SIZE]
Definition: bluegiga.h:54
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
uint8_t work_tx[20]
Definition: bluegiga.h:58
void bluegiga_request_all_rssi(struct bluegiga_periph *p)
Definition: bluegiga.c:322
uint8_t rx_extract_idx
Definition: bluegiga.h:52
#define BLUEGIGA_DRDY_GPIO_PIN
Definition: bluegiga.c:46
static int dev_check_free_space(struct bluegiga_periph *p, uint8_t len)
Definition: bluegiga.c:61
uint16_t input_length
number of data words to read
Definition: spi.h:145
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:69
bool_t spi_slave_register(struct spi_periph *p, struct spi_transaction *t)
Register one (and only one) transaction to use spi as slave.
Definition: spi_arch.c:679
void bluegiga_scan(struct bluegiga_periph *p)
Definition: bluegiga.c:309
unsigned char uint8_t
Definition: types.h:14
The com isn't initialized.
Definition: bluegiga.h:34
slave is selected before transaction and unselected after
Definition: spi.h:57
void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data)
Definition: bluegiga.c:188
void bluegiga_receive(struct spi_transaction *trans)
Definition: bluegiga.c:229
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
unsigned char telemetry_copy[20]
Definition: bluegiga.c:54
Definition: spi.h:119
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
static float p[2][2]
struct spi_transaction bluegiga_spi
Definition: bluegiga.c:51
#define LED_OFF(i)
Definition: led_hw.h:43
static void dev_send_message(struct bluegiga_periph *p)
Definition: bluegiga.c:75
void gpio_setup_output(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_ardrone.c:102
The com is in idle.
Definition: bluegiga.h:35
uint8_t rx_insert_idx
Definition: bluegiga.h:51
Bluegiga Bluetooth chip I/O.
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
enum SPITransactionStatus status
Definition: spi.h:156
static void dev_put_byte(struct bluegiga_periph *p, uint8_t byte)
Definition: bluegiga.c:71
uint8_t end_of_msg
Definition: bluegiga.h:65