You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
6.1 KiB
230 lines
6.1 KiB
/* |
|
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_PWM_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; |
|
} |
|
|
|
// static probe function for device detection |
|
static bool probe(void); |
|
|
|
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_PWM_CHANNELS]; |
|
|
|
Radio_CC2500 cc2500; |
|
|
|
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; |
|
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; |
|
int8_t auto_bindOffset; |
|
uint8_t search_count; |
|
uint8_t last_wifi_channel; |
|
|
|
uint32_t timeTunedMs; |
|
uint32_t autobind_start_recv_ms; |
|
|
|
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 setChannelRX(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 = 0x120c; |
|
struct PACKED bind_info { |
|
uint16_t magic; |
|
uint8_t bindTxId[2]; |
|
int8_t bindOffset; |
|
uint8_t wifi_chan; |
|
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_GFSK[]; |
|
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_cc2500 t_status; |
|
uint32_t last_pps_ms; |
|
uint8_t tx_rssi; |
|
uint8_t tx_pps; |
|
bool have_tx_pps; |
|
uint8_t last_fcc_chan; |
|
uint32_t telem_send_count; |
|
|
|
bool handle_D16_packet(const uint8_t *packet); |
|
bool handle_SRT_packet(const uint8_t *packet); |
|
bool handle_autobind_packet(const uint8_t *packet, uint8_t lqi); |
|
bool have_channel(uint8_t channel, uint8_t count, uint8_t loop); |
|
void setup_hopping_table_SRT(void); |
|
uint8_t map_RSSI_to_dBm(uint8_t rssi_raw); |
|
|
|
// check sending of fw upload ack |
|
void check_fw_ack(void); |
|
void map_stick_mode(uint16_t *channels); |
|
void set_fcc_channel(void); |
|
|
|
// check for double binding |
|
void check_double_bind(void); |
|
}; |
|
|
|
|
|
#endif // CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS |
|
|
|
|