123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /*
- 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
- #if HAL_RCINPUT_WITH_AP_RADIO
- /*
- AP_Radio implementation for Cypress 2.4GHz radio.
- With thanks to the SuperBitRF project
- See http://wiki.paparazziuav.org/wiki/SuperbitRF
- This implementation uses the DSMX protocol on a CYRF6936
- */
- #include "AP_Radio_backend.h"
- #include "hal.h"
- #include "telem_structure.h"
- class AP_Radio_cypress : public AP_Radio_backend
- {
- public:
- AP_Radio_cypress(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(dsm.tx_firmware_year)<<12) + (uint16_t(dsm.tx_firmware_month)<<8) + dsm.tx_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_cypress *radio_singleton;
- void radio_init(void);
- void dump_registers(uint8_t n);
- void force_initial_state(void);
- void set_channel(uint8_t channel);
- uint8_t read_status_debounced(uint8_t adr);
- uint8_t read_register(uint8_t reg);
- void write_register(uint8_t reg, uint8_t value);
- void write_multiple(uint8_t reg, uint8_t n, const uint8_t *data);
- enum {
- STATE_RECV,
- STATE_BIND,
- STATE_AUTOBIND,
- STATE_SEND_TELEM,
- STATE_SEND_TELEM_WAIT,
- STATE_SEND_FCC
- } state;
- struct config {
- uint8_t reg;
- uint8_t value;
- };
- static const uint8_t pn_codes[5][9][8];
- static const uint8_t pn_bind[];
- static const config cyrf_config[];
- static const config cyrf_bind_config[];
- static const config cyrf_transfer_config[];
- virtual_timer_t timeout_vt;
- static thread_t *_irq_handler_ctx;
- void radio_set_config(const struct config *config, uint8_t size);
- void start_receive(void);
- // main IRQ handler
- void irq_handler(void);
- // IRQ handler for packet receive
- void irq_handler_recv(uint8_t rx_status);
- // handle timeout IRQ
- void irq_timeout(void);
- // trampoline functions to take us from static IRQ function to class functions
- static void irq_handler_thd(void* arg);
- static void trigger_irq_radio_event(void);
- static void trigger_timeout_event(void *arg);
- static const uint8_t max_channels = 16;
- uint32_t last_debug_print_ms;
- void print_debug_info(void);
- AP_Radio::stats stats;
- AP_Radio::stats last_stats;
- enum dsm_protocol {
- DSM_NONE = 0, // not bound yet
- DSM_DSM2_1 = 0x01, // The original DSM2 protocol with 1 packet of data
- DSM_DSM2_2 = 0x02, // The original DSM2 protocol with 2 packets of data
- DSM_DSMX_1 = 0xA2, // The original DSMX protocol with 1 packet of data
- DSM_DSMX_2 = 0xB2, // The original DSMX protocol with 2 packets of data
- };
- enum dsm2_sync {
- DSM2_SYNC_A,
- DSM2_SYNC_B,
- DSM2_OK
- };
- // semaphore between ISR and main thread
- HAL_Semaphore sem;
- // dsm config data and status
- struct {
- uint8_t channels[23];
- enum dsm_protocol protocol;
- uint8_t mfg_id[4];
- uint8_t current_channel;
- uint8_t current_rf_channel;
- uint16_t crc_seed;
- uint8_t sop_col;
- uint8_t data_col;
- uint8_t last_sop_code[8];
- uint8_t last_data_code[16];
- uint32_t receive_start_us;
- uint32_t receive_timeout_msec;
- uint32_t last_recv_us;
- uint32_t last_parse_us;
- uint32_t last_recv_chan;
- uint32_t last_chan_change_us;
- uint16_t num_channels;
- uint16_t pwm_channels[max_channels];
- bool need_bind_save;
- enum dsm2_sync sync;
- uint32_t crc_errors;
- float rssi;
- bool last_discrc;
- uint8_t last_transmit_power;
- uint32_t send_irq_count;
- uint32_t send_count;
- uint16_t pkt_time1 = 3000;
- uint16_t pkt_time2 = 7000;
- uint8_t tx_firmware_year;
- uint8_t tx_firmware_month;
- uint8_t tx_firmware_day;
- int8_t forced_channel = -1;
- uint8_t tx_rssi;
- uint8_t tx_pps;
- uint32_t last_autobind_send;
- bool have_tx_pps;
- uint32_t telem_send_count;
- uint8_t tx_bl_version;
- } dsm;
- 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;
- // bind structure saved to storage
- static const uint16_t bind_magic = 0x43F6;
- struct PACKED bind_info {
- uint16_t magic;
- uint8_t mfg_id[4];
- enum dsm_protocol protocol;
- };
- struct telem_status t_status;
- // DSM specific functions
- void dsm_set_channel(uint8_t channel, bool is_dsm2, uint8_t sop_col, uint8_t data_col, uint16_t crc_seed);
- // generate DSMX channels
- void dsm_generate_channels_dsmx(uint8_t mfg_id[4], uint8_t channels[23]);
- // setup for DSMX transfers
- void dsm_setup_transfer_dsmx(void);
- // choose channel to receive on
- void dsm_choose_channel(void);
- // map for mode1/mode2
- void map_stick_mode(uint16_t *channels);
- // parse DSM channels from a packet
- bool parse_dsm_channels(const uint8_t *data);
- // process an incoming packet
- void process_packet(const uint8_t *pkt, uint8_t len);
- // process an incoming bind packet
- void process_bind(const uint8_t *pkt, uint8_t len);
- // load bind info from storage
- void load_bind_info(void);
- // save bind info to storage
- void save_bind_info(void);
- bool is_DSM2(void);
- // send a 16 byte packet
- void transmit16(const uint8_t data[16]);
- void send_telem_packet(void);
- void irq_handler_send(uint8_t tx_status);
- void send_FCC_test_packet(void);
- // check sending of fw upload ack
- void check_fw_ack(void);
- // re-sync DSM2
- void dsm2_start_sync(void);
- // check for double binding
- void check_double_bind(void);
- // setup a timeout handler
- void setup_timeout(uint32_t timeout_ms);
- };
- #endif
|