APM:Libraries
AP_Radio_cypress.h
Go to the documentation of this file.
1 /*
2  This program is free software: you can redistribute it and/or modify
3  it under the terms of the GNU General Public License as published by
4  the Free Software Foundation, either version 3 of the License, or
5  (at your option) any later version.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 #pragma once
16 
17 /*
18  AP_Radio implementation for Cypress 2.4GHz radio.
19 
20  With thanks to the SuperBitRF project
21  See http://wiki.paparazziuav.org/wiki/SuperbitRF
22 
23  This implementation uses the DSMX protocol on a CYRF6936
24  */
25 
26 #include "AP_Radio_backend.h"
27 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
28 #include <nuttx/arch.h>
29 #include <systemlib/systemlib.h>
30 #include <drivers/drv_hrt.h>
31 #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
32 #include "hal.h"
33 #endif
34 #include "telem_structure.h"
35 
37 {
38 public:
40 
41  // init - initialise radio
42  bool init(void) override;
43 
44  // rest radio
45  bool reset(void) override;
46 
47  // send a packet
48  bool send(const uint8_t *pkt, uint16_t len) override;
49 
50  // start bind process as a receiver
51  void start_recv_bind(void) override;
52 
53  // return time in microseconds of last received R/C packet
54  uint32_t last_recv_us(void) override;
55 
56  // return number of input channels
57  uint8_t num_channels(void) override;
58 
59  // return current PWM of a channel
60  uint16_t read(uint8_t chan) override;
61 
62  // handle a data96 mavlink packet for fw upload
63  void handle_data_packet(mavlink_channel_t chan, const mavlink_data96_t &m) override;
64 
65  // update status
66  void update(void) override;
67 
68  // get TX fw version
69  uint32_t get_tx_version(void) override {
70  // pack date into 16 bits for vendor_id in AUTOPILOT_VERSION
71  return (uint16_t(dsm.tx_firmware_year)<<12) + (uint16_t(dsm.tx_firmware_month)<<8) + dsm.tx_firmware_day;
72  }
73 
74  // get radio statistics structure
75  const AP_Radio::stats &get_stats(void) override;
76 
77  // set the 2.4GHz wifi channel used by companion computer, so it can be avoided
78  void set_wifi_channel(uint8_t channel) {
79  t_status.wifi_chan = channel;
80  }
81 
82 private:
85 
86  void radio_init(void);
87 
88  void dump_registers(uint8_t n);
89 
90  void force_initial_state(void);
91  void set_channel(uint8_t channel);
92  uint8_t read_status_debounced(uint8_t adr);
93 
94  uint8_t read_register(uint8_t reg);
95  void write_register(uint8_t reg, uint8_t value);
96  void write_multiple(uint8_t reg, uint8_t n, const uint8_t *data);
97 
98  enum {
105  } state;
106 
107  struct config {
108  uint8_t reg;
109  uint8_t value;
110  };
111  static const uint8_t pn_codes[5][9][8];
112  static const uint8_t pn_bind[];
113  static const config cyrf_config[];
114  static const config cyrf_bind_config[];
115  static const config cyrf_transfer_config[];
116 
117 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
118  sem_t irq_sem;
119  struct hrt_call wait_call;
120 #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
121  virtual_timer_t timeout_vt;
122  static thread_t *_irq_handler_ctx;
123 #endif
124  void radio_set_config(const struct config *config, uint8_t size);
125 
126  void start_receive(void);
127 
128  // main IRQ handler
129  void irq_handler(void);
130 
131  // IRQ handler for packet receive
132  void irq_handler_recv(uint8_t rx_status);
133 
134  // handle timeout IRQ
135  void irq_timeout(void);
136 
137  // trampoline functions to take us from static IRQ function to class functions
138 
139 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
140  static int irq_radio_trampoline(int irq, void *context);
141  static int irq_timeout_trampoline(int irq, void *context);
142 #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
143  static void irq_handler_thd(void* arg);
144  static void trigger_irq_radio_event(void);
145  static void trigger_timeout_event(void *arg);
146 #endif
147 
148  static const uint8_t max_channels = 16;
149 
151 
152  void print_debug_info(void);
153 
156 
158  DSM_NONE = 0, // not bound yet
159  DSM_DSM2_1 = 0x01, // The original DSM2 protocol with 1 packet of data
160  DSM_DSM2_2 = 0x02, // The original DSM2 protocol with 2 packets of data
161  DSM_DSMX_1 = 0xA2, // The original DSMX protocol with 1 packet of data
162  DSM_DSMX_2 = 0xB2, // The original DSMX protocol with 2 packets of data
163  };
164 
165  enum dsm2_sync {
169  };
170 
171  // semaphore between ISR and main thread
173 
174  // dsm config data and status
175  struct {
176  uint8_t channels[23];
178  uint8_t mfg_id[4];
181  uint16_t crc_seed;
182  uint8_t sop_col;
183  uint8_t data_col;
184  uint8_t last_sop_code[8];
185  uint8_t last_data_code[16];
186 
189 
190  uint32_t last_recv_us;
191  uint32_t last_parse_us;
192  uint32_t last_recv_chan;
194  uint16_t num_channels;
198  uint32_t crc_errors;
199  float rssi;
202  uint32_t send_irq_count;
203  uint32_t send_count;
204  uint16_t pkt_time1 = 3000;
205  uint16_t pkt_time2 = 7000;
209  int8_t forced_channel = -1;
210  uint8_t tx_rssi;
211  uint8_t tx_pps;
215  uint8_t tx_bl_version;
216  } dsm;
217 
218  struct {
219  mavlink_channel_t chan;
220  bool need_ack;
221  uint8_t counter;
222  uint8_t sequence;
223  uint32_t offset;
224  uint32_t length;
225  uint32_t acked;
226  uint8_t len;
228  uint8_t pending_data[92];
229  } fwupload;
230 
231  // bind structure saved to storage
232  static const uint16_t bind_magic = 0x43F6;
233  struct PACKED bind_info {
234  uint16_t magic;
235  uint8_t mfg_id[4];
237  };
238 
240 
241  // DSM specific functions
242  void dsm_set_channel(uint8_t channel, bool is_dsm2, uint8_t sop_col, uint8_t data_col, uint16_t crc_seed);
243 
244  // generate DSMX channels
245  void dsm_generate_channels_dsmx(uint8_t mfg_id[4], uint8_t channels[23]);
246 
247  // setup for DSMX transfers
248  void dsm_setup_transfer_dsmx(void);
249 
250  // choose channel to receive on
251  void dsm_choose_channel(void);
252 
253  // map for mode1/mode2
254  void map_stick_mode(uint16_t *channels);
255 
256  // parse DSM channels from a packet
257  bool parse_dsm_channels(const uint8_t *data);
258 
259  // process an incoming packet
260  void process_packet(const uint8_t *pkt, uint8_t len);
261 
262  // process an incoming bind packet
263  void process_bind(const uint8_t *pkt, uint8_t len);
264 
265  // load bind info from storage
266  void load_bind_info(void);
267 
268  // save bind info to storage
269  void save_bind_info(void);
270 
271  bool is_DSM2(void);
272 
273  // send a 16 byte packet
274  void transmit16(const uint8_t data[16]);
275 
276  void send_telem_packet(void);
277  void irq_handler_send(uint8_t tx_status);
278 
279  void send_FCC_test_packet(void);
280 
281  // check sending of fw upload ack
282  void check_fw_ack(void);
283 
284  // re-sync DSM2
285  void dsm2_start_sync(void);
286 
287  // check for double binding
288  void check_double_bind(void);
289 
290  // setup a timeout handler
291  void setup_timeout(uint32_t timeout_ms);
292 };
293 
void dsm_set_channel(uint8_t channel, bool is_dsm2, uint8_t sop_col, uint8_t data_col, uint16_t crc_seed)
struct telem_status t_status
bool init(void) override
void start_recv_bind(void) override
enum AP_Radio_cypress::@170 state
void send_telem_packet(void)
static const uint8_t max_channels
void start_receive(void)
void send_FCC_test_packet(void)
bool send(const uint8_t *pkt, uint16_t len) override
void write_multiple(uint8_t reg, uint8_t n, const uint8_t *data)
static const uint16_t bind_magic
void save_bind_info(void)
uint32_t last_chan_change_us
uint16_t pwm_channels[max_channels]
uint8_t num_channels(void) override
AP_Radio_cypress(AP_Radio &radio)
void dsm_setup_transfer_dsmx(void)
static AP_Radio_cypress * radio_instance
uint8_t read_register(uint8_t reg)
void set_channel(uint8_t channel)
void handle_data_packet(mavlink_channel_t chan, const mavlink_data96_t &m) override
static const uint8_t pn_bind[]
bool parse_dsm_channels(const uint8_t *data)
static const uint8_t pn_codes[5][9][8]
void transmit16(const uint8_t data[16])
void radio_init(void)
void irq_handler_send(uint8_t tx_status)
uint32_t last_debug_print_ms
static const config cyrf_transfer_config[]
void process_bind(const uint8_t *pkt, uint8_t len)
void check_double_bind(void)
static const config cyrf_bind_config[]
void radio_set_config(const struct config *config, uint8_t size)
uint16_t read(uint8_t chan) override
static const config cyrf_config[]
uint8_t last_sop_code[8]
void print_debug_info(void)
void irq_timeout(void)
void irq_handler(void)
void dsm_choose_channel(void)
struct hrt_call wait_call
telem_type
void update(void) override
struct AP_Radio_cypress::@171 dsm
mavlink_channel_t chan
uint32_t last_autobind_send
void process_packet(const uint8_t *pkt, uint8_t len)
void setup_timeout(uint32_t timeout_ms)
void load_bind_info(void)
void set_wifi_channel(uint8_t channel)
uint8_t channels[23]
uint32_t receive_timeout_msec
bool is_DSM2(void)
void write_register(uint8_t reg, uint8_t value)
void force_initial_state(void)
AP_Radio::stats stats
uint32_t get_tx_version(void) override
#define PACKED
Definition: AP_Common.h:28
void dsm_generate_channels_dsmx(uint8_t mfg_id[4], uint8_t channels[23])
float value
AP_HAL::OwnPtr< AP_HAL::SPIDevice > dev
uint8_t read_status_debounced(uint8_t adr)
AP_Radio::stats last_stats
void check_fw_ack(void)
static int irq_timeout_trampoline(int irq, void *context)
struct AP_Radio_cypress::@172 fwupload
enum telem_type fw_type
void dsm2_start_sync(void)
uint8_t pending_data[92]
enum dsm2_sync sync
static int irq_radio_trampoline(int irq, void *context)
bool reset(void) override
void dump_registers(uint8_t n)
uint32_t last_recv_us(void) override
AP_HAL::Semaphore * sem
uint8_t wifi_chan
const AP_Radio::stats & get_stats(void) override
void map_stick_mode(uint16_t *channels)
enum dsm_protocol protocol
void irq_handler_recv(uint8_t rx_status)
uint8_t last_data_code[16]