/
AP_Radio_cc2500.h
209 lines (165 loc) · 5.43 KB
/
AP_Radio_cc2500.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/*
AP_Radio implementation for CC2500 2.4GHz radio.
With thanks to cleanflight and betaflight projects
*/
#include "AP_Radio_backend.h"
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
#include "hal.h"
#include "telem_structure.h"
#include "driver_cc2500.h"
#define CC2500_MAX_CHANNELS 16
class AP_Radio_cc2500 : public AP_Radio_backend
{
public:
AP_Radio_cc2500(AP_Radio &radio);
// init - initialise radio
bool init(void) override;
// rest radio
bool reset(void) override;
// send a packet
bool send(const uint8_t *pkt, uint16_t len) override;
// start bind process as a receiver
void start_recv_bind(void) override;
// return time in microseconds of last received R/C packet
uint32_t last_recv_us(void) override;
// return number of input channels
uint8_t num_channels(void) override;
// return current PWM of a channel
uint16_t read(uint8_t chan) override;
// handle a data96 mavlink packet for fw upload
void handle_data_packet(mavlink_channel_t chan, const mavlink_data96_t &m) override;
// update status
void update(void) override;
// get TX fw version
uint32_t get_tx_version(void) override {
// pack date into 16 bits for vendor_id in AUTOPILOT_VERSION
return (uint16_t(tx_date.firmware_year)<<12) + (uint16_t(tx_date.firmware_month)<<8) + tx_date.firmware_day;
}
// get radio statistics structure
const AP_Radio::stats &get_stats(void) override;
// set the 2.4GHz wifi channel used by companion computer, so it can be avoided
void set_wifi_channel(uint8_t channel) override {
// t_status.wifi_chan = channel;
}
private:
AP_HAL::OwnPtr<AP_HAL::SPIDevice> dev;
static AP_Radio_cc2500 *radio_singleton;
static thread_t *_irq_handler_ctx;
static virtual_timer_t timeout_vt;
static void irq_handler_thd(void* arg);
static void trigger_irq_radio_event(void);
static void trigger_timeout_event(void *arg);
void radio_init(void);
// semaphore between ISR and main thread
HAL_Semaphore sem;
AP_Radio::stats stats;
AP_Radio::stats last_stats;
uint16_t pwm_channels[CC2500_MAX_CHANNELS];
Radio_CC2500 cc2500;
uint8_t calData[255][3];
uint8_t bindTxId[2];
int8_t bindOffset;
uint8_t bindHopData[47];
uint8_t rxNum;
uint8_t listLength;
uint8_t channr;
uint8_t chanskip;
int8_t fcc_chan;
uint32_t packet_timer;
static uint32_t irq_time_us;
const uint32_t sync_time_us = 9000;
uint8_t chan_count;
uint32_t lost;
uint32_t timeouts;
bool have_bind_info;
uint8_t packet3;
bool telem_send_rssi;
float rssi_filtered;
uint64_t bind_mask;
uint8_t best_lqi;
int8_t best_bindOffset;
uint32_t timeTunedMs;
void initTuneRx(void);
void initialiseData(uint8_t adr);
void initGetBind(void);
bool tuneRx(uint8_t ccLen, uint8_t *packet);
bool getBindData(uint8_t ccLen, uint8_t *packet);
bool check_best_LQI(void);
void setChannel(uint8_t channel);
void nextChannel(uint8_t skip);
void parse_frSkyX(const uint8_t *packet);
uint16_t calc_crc(const uint8_t *data, uint8_t len);
bool check_crc(uint8_t ccLen, uint8_t *packet);
void send_D16_telemetry(void);
void send_SRT_telemetry(void);
void irq_handler(void);
void irq_timeout(void);
// bind structure saved to storage
static const uint16_t bind_magic = 0x120a;
struct PACKED bind_info {
uint16_t magic;
uint8_t bindTxId[2];
int8_t bindOffset;
uint8_t listLength;
uint8_t bindHopData[47];
};
void save_bind_info(void);
bool load_bind_info(void);
enum {
STATE_INIT = 0,
STATE_BIND,
STATE_BIND_TUNING,
STATE_BIND_BINDING,
STATE_BIND_COMPLETE,
STATE_STARTING,
STATE_DATA,
STATE_TELEMETRY,
STATE_RESUME,
STATE_FCCTEST,
STATE_SEARCH,
} protocolState;
struct config {
uint8_t reg;
uint8_t value;
};
static const config radio_config[];
struct {
mavlink_channel_t chan;
bool need_ack;
uint8_t counter;
uint8_t sequence;
uint32_t offset;
uint32_t length;
uint32_t acked;
uint8_t len;
enum telem_type fw_type;
uint8_t pending_data[92];
} fwupload;
struct {
uint8_t firmware_year;
uint8_t firmware_month;
uint8_t firmware_day;
} tx_date;
struct telem_status t_status;
uint32_t last_pps_ms;
uint8_t tx_rssi;
uint8_t tx_pps;
bool handle_D16_packet(const uint8_t *packet);
bool handle_SRT_packet(const uint8_t *packet);
// check sending of fw upload ack
void check_fw_ack(void);
};
#endif // CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS