Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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#ifdef MODEM_LED
34#include "led.h"
35#endif
36
37#include "modules/core/abi.h"
38
39// for memset
40#include <string.h>
41
42#ifndef BLUEGIGA_SPI_DEV
43#error "bluegiga: must define a BLUEGIGA_SPI_DEV"
44#endif
45
46// Bluegiga: DRDY defaults to SuperbitRf DRDY
47#ifndef BLUEGIGA_DRDY_GPIO
48#define BLUEGIGA_DRDY_GPIO SUPERBITRF_DRDY_PORT
49#endif
50
51#ifndef BLUEGIGA_DRDY_GPIO_PIN
52#define BLUEGIGA_DRDY_GPIO_PIN SUPERBITRF_DRDY_PIN
53#endif
54
55#define TxStrengthOfSender(x) (x[1])
56#define RssiOfSender(x) (x[2])
57#define Pprz_StxOfMsg(x) (x[3])
58#define SenderIdOfBGMsg(x) (x[5])
59
63
65
67void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data);
68void bluegiga_receive(struct spi_transaction *trans);
69
70// Functions for the generic link device device API
71static int dev_check_free_space(struct bluegiga_periph *p, long *fd __attribute__((unused)), uint16_t len)
72{
73 // check if there is enough space for message
74 // NB if BLUEGIGA_BUFFER_SIZE is smaller than 256 then an additional check is needed that len < BLUEGIGA_BUFFER_SIZE
75 if (len - 1 <= ((p->tx_extract_idx - p->tx_insert_idx - 1 + BLUEGIGA_BUFFER_SIZE) % BLUEGIGA_BUFFER_SIZE)) {
76 return true;
77 }
78
79 return false;
80}
81static void dev_put_buffer(struct bluegiga_periph *p, long fd __attribute__((unused)), uint8_t *data, uint16_t len)
82{
83 int i;
84 for (i = 0; i < len; i++) {
85 bluegiga_transmit(p, data[i]);
86 }
87}
88static void dev_put_byte(struct bluegiga_periph *p, long fd __attribute__((unused)), uint8_t byte)
89{
90 bluegiga_transmit(p, byte);
91}
92static void dev_send_message(struct bluegiga_periph *p, long fd __attribute__((unused)))
93{
94 p->end_of_msg = p->tx_insert_idx;
95}
97{
99}
100
101// note, need to run dev_char_available first
103{
104 uint8_t ret = p->rx_buf[p->rx_extract_idx];
105 bluegiga_increment_buf(&p->rx_extract_idx, 1);
106 return ret;
107}
108
109// Functions for the generic spi device API
110static void trans_cb(struct spi_transaction *trans)
111{
112 bluegiga_receive(trans);
113}
114
115/* check if character available in receive buffer */
117{
118 return (p->rx_extract_idx != p->rx_insert_idx);
119}
120
121/* safe increment of circular buffer */
123{
124 *buf_idx = (*buf_idx + len) % BLUEGIGA_BUFFER_SIZE;
125}
126
128#if PERIODIC_TELEMETRY
130
132static void send_bluegiga(struct transport_tx *trans, struct link_device *dev)
133{
135
136 if (now_ts > last_ts) {
138 uint32_t a2a_rate = 1000 * a2a_msgs / (now_ts - last_ts);
139 pprz_msg_send_BLUEGIGA(trans, dev, AC_ID, &rate, &a2a_rate);
140
141 a2a_msgs = 0;
143 last_ts = now_ts;
144 }
145}
146#endif
147
149{
150#ifdef MODEM_LED
152#endif
153
154 // configure the SPI bus
155 bluegiga_spi.input_buf = p->work_rx;
156 bluegiga_spi.output_buf = p->work_tx;
159 bluegiga_spi.slave_idx = 0; // Not used for SPI-Slave: always NSS pin
167
168 // Configure generic link device
169 p->device.periph = (void *)(p);
170 p->device.check_free_space = (check_free_space_t) dev_check_free_space;
171 p->device.put_byte = (put_byte_t) dev_put_byte;
172 p->device.put_buffer = (put_buffer_t) dev_put_buffer;
173 p->device.send_message = (send_message_t) dev_send_message;
174 p->device.char_available = (char_available_t) dev_char_available;
175 p->device.get_byte = (get_byte_t) dev_get_byte;
176
177 // initialize peripheral variables
178 p->rx_insert_idx = 0;
179 p->rx_extract_idx = 0;
180 p->tx_insert_idx = 0;
181 p->tx_extract_idx = 0;
182
183 memset(p->work_rx, 0, bluegiga_spi.input_length);
184 memset(p->work_tx, 0, bluegiga_spi.output_length);
185
186 memset(broadcast_msg, 0, 19);
187
188 p->bytes_recvd_since_last = 0;
189 p->end_of_msg = p->tx_insert_idx;
190 p->connected = 0;
191
192 // set DRDY interrupt pin for spi master triggered on falling edge
195
197
198#if PERIODIC_TELEMETRY
200#endif
201
202 // register spi slave read for transaction
204}
205
206/* Add one byte to the end of tx circular buffer */
208{
209 long fd = 0;
211 p->tx_buf[p->tx_insert_idx] = data;
212 bluegiga_increment_buf(&p->tx_insert_idx, 1);
213 }
214}
215
216/* Load waiting data into tx peripheral buffer */
218{
220 // check data available in buffer to send
221 packet_len = ((p->end_of_msg - p->tx_extract_idx + BLUEGIGA_BUFFER_SIZE) % BLUEGIGA_BUFFER_SIZE);
222 if (packet_len > 19) {
223 packet_len = 19;
224 }
225
227 uint8_t i;
228 // attach header with data length of real data in 20 char data string
229 p->work_tx[0] = packet_len;
230
231 // copy data from working buffer to spi output buffer
232 for (i = 0; i < packet_len; i++) {
233 p->work_tx[i + 1] = p->tx_buf[(p->tx_extract_idx + i) % BLUEGIGA_BUFFER_SIZE];
234 }
235 bluegiga_increment_buf(&p->tx_extract_idx, packet_len);
236
237 // clear unused bytes
238 for (i = packet_len + 1; i < BLUEGIGA_SPI_BUF_SIZE; i++) {
239 p->work_tx[i] = 0;
240 }
241
243 }
244}
245
246/* read data from dma if available, set as call back of successful spi exchange
247 *
248 * TODO Remove use of bluegiga_p global in following function
249 */
251{
252 if (trans->status == SPITransSuccess) {
253 // handle successful msg send
255 // empty transfer buffer
256 for (uint8_t i = 0; i < trans->output_length; i++) {
257 trans->output_buf[i] = 0;
258 }
260 // sending second half of broadcast message
261 for (uint8_t i = 0; i < broadcast_msg[0]; i++) {
262 trans->output_buf[i] = broadcast_msg[i];
263 }
265 return;
266 }
267
268 /*
269 * >235 data package from broadcast mode
270 * 0x50 communication lost with ground station
271 * 0x51 interrupt handled
272 * <20 data package from connection
273 */
274
276 uint8_t read_offset = 0;
277 switch (trans->input_buf[0]) {
278 case 0x50: // communication status changed
279 bluegiga_p.connected = trans->input_buf[1];
280 if (bluegiga_p.connected) {
281 //telemetry_mode_Main = TELEMETRY_PROCESS_Main;
282 } else {
283 //telemetry_mode_Main = NB_TELEMETRY_MODES; // send no periodic telemetry
284 }
286 break;
287 case 0x51: // Interrupt handled
288 gpio_set(BLUEGIGA_DRDY_GPIO, BLUEGIGA_DRDY_GPIO_PIN); // Reset interrupt pin
289 break;
290 default:
292 // compute length of transmitted message
293 if (trans->input_buf[0] < trans->input_length) { // normal connection mode
294 packet_len = trans->input_buf[0];
295 read_offset = 1;
296 } else if (trans->input_buf[0] > 0xff - trans->input_length) { // broadcast mode
297 packet_len = 0xff - trans->input_buf[0];
298
299 if (packet_len > 3)
300 {
301#ifdef MODEM_LED
303#endif
304
305 int8_t tx_strength = TxStrengthOfSender(trans->input_buf);
307 uint8_t ac_id = SenderIdOfBGMsg(trans->input_buf);
308
309 if (Pprz_StxOfMsg(trans->input_buf) == PPRZ_STX) {
310 AbiSendMsgRSSI(RSSI_BLUEGIGA_ID, ac_id, tx_strength, rssi);
311 }
312 a2a_msgs++;
313 }
314
315 read_offset = 3;
316 }
317 }
318
319 // handle incoming datalink message
320 if (packet_len > 0 && packet_len <= trans->input_length - read_offset) {
321//#ifdef MODEM_LED
322// LED_TOGGLE(MODEM_LED);
323//#endif
324 // Handle received message
325 for (uint8_t i = 0; i < packet_len; i++) {
326 bluegiga_p.rx_buf[(bluegiga_p.rx_insert_idx + i) % BLUEGIGA_BUFFER_SIZE] = trans->input_buf[i + read_offset];
327 }
330 }
331
332 // load next message to be sent into work buffer, needs to be loaded before calling spi_slave_register
334
335 // register spi slave read for next transaction
337 }
338}
339
340/* Send data for broadcast message to the bluegiga module
341 * maximum size of message is 22 bytes
342 */
344{
345 if (msg_len == 0 || msg_len > 22) {
346 return;
347 }
348
349 uint8_t max_length = 20;
350 p->work_tx[0] = msg_len;
351
352 if (msg_len < max_length) {
353 for (uint8_t i = 0; i < msg_len; i++) {
354 p->work_tx[i + 1] = msg[i];
355 }
357 } else {
358 for (uint8_t i = 0; i < max_length - 1; i++) {
359 p->work_tx[i + 1] = msg[i];
360 }
361
362 memcpy(broadcast_msg, msg + max_length - 1, msg_len - (max_length - 1));
364 }
365
366 // trigger bluegiga to read direct command
368}
Main include for ABI (AirBorneInterface).
#define RSSI_BLUEGIGA_ID
#define BLUEGIGA_DRDY_GPIO_PIN
Definition bluegiga.c:52
uint32_t last_ts
Definition bluegiga.c:131
#define TxStrengthOfSender(x)
Definition bluegiga.c:55
static void dev_put_byte(struct bluegiga_periph *p, long fd, uint8_t byte)
Definition bluegiga.c:88
static void send_bluegiga(struct transport_tx *trans, struct link_device *dev)
Definition bluegiga.c:132
static uint8_t dev_get_byte(struct bluegiga_periph *p)
Definition bluegiga.c:102
void bluegiga_broadcast_msg(struct bluegiga_periph *p, char *msg, uint8_t msg_len)
Definition bluegiga.c:343
static void dev_send_message(struct bluegiga_periph *p, long fd)
Definition bluegiga.c:92
#define SenderIdOfBGMsg(x)
Definition bluegiga.c:58
static void dev_put_buffer(struct bluegiga_periph *p, long fd, uint8_t *data, uint16_t len)
Definition bluegiga.c:81
void bluegiga_receive(struct spi_transaction *trans)
Definition bluegiga.c:250
#define Pprz_StxOfMsg(x)
Definition bluegiga.c:57
enum BlueGigaStatus coms_status
Definition bluegiga.c:60
#define BLUEGIGA_DRDY_GPIO
Definition bluegiga.c:48
bool bluegiga_ch_available(struct bluegiga_periph *p)
Definition bluegiga.c:116
static int dev_check_free_space(struct bluegiga_periph *p, long *fd, uint16_t len)
Definition bluegiga.c:71
struct spi_transaction bluegiga_spi
Definition bluegiga.c:62
static void trans_cb(struct spi_transaction *trans)
Definition bluegiga.c:110
uint8_t broadcast_msg[20]
Definition bluegiga.c:64
void bluegiga_load_tx(struct bluegiga_periph *p)
Definition bluegiga.c:217
static int dev_char_available(struct bluegiga_periph *p)
Definition bluegiga.c:96
uint32_t a2a_msgs
Definition bluegiga.c:127
void bluegiga_transmit(struct bluegiga_periph *p, uint8_t data)
Definition bluegiga.c:207
struct bluegiga_periph bluegiga_p
Definition bluegiga.c:61
void bluegiga_init(struct bluegiga_periph *p)
Definition bluegiga.c:148
#define RssiOfSender(x)
Definition bluegiga.c:56
void bluegiga_increment_buf(uint8_t *buf_idx, uint8_t len)
Definition bluegiga.c:122
Bluegiga Bluetooth chip I/O.
BlueGigaStatus
Definition bluegiga.h:35
@ BLUEGIGA_SENDING_BROADCAST
The com is switched from data link to rssi scanning.
Definition bluegiga.h:39
@ BLUEGIGA_IDLE
The com is in idle.
Definition bluegiga.h:37
@ BLUEGIGA_UNINIT
The com isn't initialized.
Definition bluegiga.h:36
@ BLUEGIGA_SENDING
The com is sending.
Definition bluegiga.h:38
#define BLUEGIGA_SPI_BUF_SIZE
Definition bluegiga.h:50
uint8_t connected
Definition bluegiga.h:70
uint8_t rx_buf[BLUEGIGA_BUFFER_SIZE]
Definition bluegiga.h:54
uint8_t rx_insert_idx
Definition bluegiga.h:55
uint32_t bytes_recvd_since_last
Definition bluegiga.h:68
#define BLUEGIGA_BUFFER_SIZE
Definition bluegiga.h:43
static uint16_t rssi
Definition cc2500_rx.c:85
#define LED_INIT(i)
Definition led_hw.h:50
#define LED_TOGGLE(i)
Definition led_hw.h:53
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
uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
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
SPICallback after_cb
NULL or function called after the transaction.
Definition spi.h:161
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
void(* SPICallback)(struct spi_transaction *trans)
SPI Callback function.
Definition spi.h:136
bool spi_slave_register(struct spi_periph *periph, struct spi_transaction *trans)
Register a spi transaction in slave mode (only one transaction can be registered).
Definition spi_arch.c:1624
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:75
@ SPITransSuccess
Definition spi.h:99
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:84
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:63
@ SPIMSBFirst
Definition spi.h:112
@ SPIDiv256
Definition spi.h:127
@ SPIDss8bit
Definition spi.h:90
SPI transaction structure.
Definition spi.h:148
uint8_t msg[10]
Buffer used for general comunication over SPI (out buffer)
static float p[2][2]
arch independent LED (Light Emitting Diodes) API
uint16_t foo
Definition main_demo5.c:58
int fd
Definition serial.c:26
Architecture independent SPI (Serial Peripheral Interface) API.
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
Architecture independent timing functions.
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.