33 #ifdef PIOS_INCLUDE_OPENLRS
49 #include "flightstatus.h"
50 #include "flightbatterystate.h"
51 #include "manualcontrolsettings.h"
52 #include "openlrsstatus.h"
56 #define STACK_SIZE_BYTES 900
57 #define TASK_PRIORITY PIOS_THREAD_PRIO_HIGH
59 #define RF22B_PWRSTATE_POWERDOWN 0x00
60 #define RF22B_PWRSTATE_READY (RFM22_opfc1_xton | RFM22_opfc1_pllon)
61 #define RF22B_PWRSTATE_RX (RFM22_opfc1_rxon | RFM22_opfc1_xton)
62 #define RF22B_PWRSTATE_TX (RFM22_opfc1_txon | RFM22_opfc1_xton)
64 static OpenLRSStatusData openlrs_status;
66 static pios_openlrs_t pios_openlrs_alloc();
67 static bool pios_openlrs_validate(pios_openlrs_t openlrs_dev);
68 static void pios_openlrs_rx_task(
void *parameters);
69 static void pios_openlrs_tx_task(
void *parameters);
70 static void pios_openlrs_do_hop(pios_openlrs_t openlrs_dev);
72 static void rfm22_init(pios_openlrs_t openlrs_dev, uint8_t isbind);
73 static void rfm22_disable(pios_openlrs_t openlrs_dev);
74 static void rfm22_set_frequency(pios_openlrs_t openlrs_dev, uint32_t
f);
75 static uint8_t rfm22_get_rssi(pios_openlrs_t openlrs_dev);
76 static void rfm22_tx_packet(pios_openlrs_t openlrs_dev,
77 void *pkt, uint8_t size);
78 static bool rfm22_rx_packet(pios_openlrs_t openlrs_dev,
79 void *whence, uint32_t size);
80 static int rfm22_rx_packet_variable(pios_openlrs_t openlrs_dev,
81 void *whence, uint32_t max_size);
82 static void rfm22_set_channel(pios_openlrs_t openlrs_dev, uint8_t ch);
83 static void rfm22_rx_reset(pios_openlrs_t openlrs_dev,
bool pause_long);
84 static void rfm22_check_hang(pios_openlrs_t openlrs_dev);
87 static void rfm22_assert_cs(pios_openlrs_t openlrs_dev);
88 static void rfm22_deassert_cs(pios_openlrs_t openlrs_dev);
89 static void rfm22_claim_bus(pios_openlrs_t openlrs_dev);
90 static void rfm22_release_bus(pios_openlrs_t openlrs_dev);
91 static void rfm22_write_claim(pios_openlrs_t openlrs_dev,
92 uint8_t addr, uint8_t
data);
93 static void rfm22_write(pios_openlrs_t openlrs_dev, uint8_t addr,
95 static uint8_t rfm22_read_claim(pios_openlrs_t openlrs_dev,
97 static uint8_t rfm22_read(pios_openlrs_t openlrs_dev,
99 static void rfm22_get_it_status(pios_openlrs_t openlrs_dev);
100 static void rfm22_beacon_send(pios_openlrs_t openlrs_dev,
bool static_tone);
103 const struct rfm22_modem_regs {
105 uint8_t r_1c, r_1d, r_1e, r_20, r_21, r_22, r_23, r_24, r_25, r_2a, r_6e, r_6f, r_70, r_71, r_72;
107 { 4800, 0x1a, 0x40, 0x0a, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x1b, 0x1e, 0x27, 0x52, 0x2c, 0x23, 0x30 },
108 { 9600, 0x05, 0x40, 0x0a, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x20, 0x24, 0x4e, 0xa5, 0x2c, 0x23, 0x30 },
109 { 19200, 0x06, 0x40, 0x0a, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x7b, 0x28, 0x9d, 0x49, 0x2c, 0x23, 0x30 },
110 { 57600, 0x05, 0x40, 0x0a, 0x45, 0x01, 0xd7, 0xdc, 0x03, 0xb8, 0x1e, 0x0e, 0xbf, 0x00, 0x23, 0x2e },
111 { 125000, 0x8a, 0x40, 0x0a, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x1e, 0x20, 0x00, 0x00, 0x23, 0xc8 },
120 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_4800 != 0, InvModemParams);
121 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_9600 != 1, InvModemParams2);
122 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_19200 != 2, InvModemParams3);
123 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_57600 != 3, InvModemParams4);
124 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_125000 != 4, InvModemParams5);
125 DONT_BUILD_IF(OPENLRS_MODEM_PARAMS_MAXOPTVAL != 4, InvModemParams6);
127 #define OPENLRS_BIND_PARAMS (OPENLRS_MODEM_PARAMS_9600)
128 #define BINDING_POWER (OPENLRS_RF_POWER_50 - 1)
131 static uint8_t count_set_bits(uint16_t x)
133 return __builtin_popcount(x);
136 static bool wait_interrupt_until(pios_openlrs_t openlrs_dev, uint32_t expiry,
145 our_rssi = rfm22_get_rssi(openlrs_dev);
158 static bool wait_interrupt(pios_openlrs_t openlrs_dev, uint32_t delay)
161 return wait_interrupt_until(openlrs_dev, expiry, NULL);
167 pios_openlrs_t openlrs_dev = (pios_openlrs_t) olrs_id;
171 openlrs_dev->rx_in_cb = rx_in_cb;
172 openlrs_dev->rx_in_context = context;
178 pios_openlrs_t openlrs_dev = (pios_openlrs_t) olrs_id;
182 openlrs_dev->tx_out_cb = tx_out_cb;
183 openlrs_dev->tx_out_context = context;
186 static bool olrs_available(uintptr_t olrs_id)
188 pios_openlrs_t openlrs_dev = (pios_openlrs_t) olrs_id;
192 if (openlrs_dev->linkLossTimeMs) {
196 if (!openlrs_dev->link_acquired) {
205 .bind_rx_cb = olrs_bind_rx,
206 .available = olrs_available,
209 const uint32_t packet_rssi_time_us = 2700;
211 static uint32_t min_freq(HwSharedRfBandOptions band)
215 case HWSHARED_RFBAND_433:
216 return MIN_RFM_FREQUENCY_433;
217 case HWSHARED_RFBAND_868:
218 return MIN_RFM_FREQUENCY_868;
219 case HWSHARED_RFBAND_915:
220 return MIN_RFM_FREQUENCY_915;
224 static uint32_t max_freq(HwSharedRfBandOptions band)
228 case HWSHARED_RFBAND_433:
229 return MAX_RFM_FREQUENCY_433;
230 case HWSHARED_RFBAND_868:
231 return MAX_RFM_FREQUENCY_868;
232 case HWSHARED_RFBAND_915:
233 return MAX_RFM_FREQUENCY_915;
237 static uint32_t def_carrier_freq(HwSharedRfBandOptions band)
241 case HWSHARED_RFBAND_433:
242 return DEFAULT_CARRIER_FREQUENCY_433;
243 case HWSHARED_RFBAND_868:
244 return DEFAULT_CARRIER_FREQUENCY_868;
245 case HWSHARED_RFBAND_915:
246 return DEFAULT_CARRIER_FREQUENCY_915;
250 static uint32_t binding_freq(HwSharedRfBandOptions band)
254 case HWSHARED_RFBAND_433:
255 return BINDING_FREQUENCY_433;
256 case HWSHARED_RFBAND_868:
257 return BINDING_FREQUENCY_868;
258 case HWSHARED_RFBAND_915:
259 return BINDING_FREQUENCY_915;
267 static uint8_t get_control_packet_size(
struct bind_data *bd)
269 return openlrs_pktsizes[(bd->flags & 0x07)];
282 #define BYTES_AT_BAUD_TO_USEC(bytes, bps, div) ((uint32_t)((bytes) + (div ? 20 : 15)) * 8 * 1025000L / (uint32_t)(bps))
284 static uint32_t get_control_packet_time(
struct bind_data *bd)
286 return (BYTES_AT_BAUD_TO_USEC(get_control_packet_size(bd),
287 modem_params[bd->modem_params].bps,
288 bd->flags & DIVERSITY_ENABLED) + 2000);
291 static uint32_t get_nominal_packet_interval(
struct bind_data *bd,
294 uint32_t ret = get_control_packet_time(bd);
296 uint32_t pre_slop = ret - 2000;
298 if (bd->flags & TELEMETRY_MASK) {
299 ret += (BYTES_AT_BAUD_TO_USEC(TELEMETRY_PACKETSIZE, modem_params[bd->modem_params].bps, bd->flags&DIVERSITY_ENABLED) + 1000);
303 ret = ((ret + 999) / 1000) * 1000;
313 *rx_slop = (ret - pre_slop) / 2;
323 static int pack_channels(uint8_t
config, int16_t *ppm, uint8_t *buf)
330 for (
int i = 0;
i <= (config/2);
i++) {
336 ((ppm[0] & 0x300) >> 8) |
337 ((ppm[1] & 0x300) >> 6) |
338 ((ppm[2] & 0x300) >> 4) |
339 ((ppm[3] & 0x300) >> 2);
346 uint8_t packed_sw = 0;
348 for (
int i = 0;
i < 4;
i++) {
351 if (ppm[0] < (166 + 12)) {
354 }
else if (ppm[0] < (550 + 12)) {
360 }
else if (ppm[0] < (833 + 12)) {
376 static void txscale_channels(int16_t *chan, int16_t nominal_min, int16_t nominal_max)
378 if (nominal_min == nominal_max) {
383 for (uint32_t
i = 0;
i < OPENLRS_PPM_NUM_CHANNELS;
i++) {
397 scaled -= nominal_min;
398 scaled /= (nominal_max - nominal_min);
400 const float scale_edge = (12*16) / 1000.0
f;
402 if (scaled < -scale_edge) {
404 }
else if (scaled < 0) {
406 x = ((scaled + scale_edge) / scale_edge) * 12;
407 }
else if (scaled < 1) {
409 x = scaled * 1000 + 12;
410 }
else if (scaled < (1 + scale_edge)) {
412 x = ((scaled - 1) / scale_edge) * 12 + 1011;
421 DONT_BUILD_IF(OPENLRS_PPM_NUM_CHANNELS < 20, NotEnoughChannelSpaceForAllConfigs);
423 static void unpack_channels(uint8_t config, int16_t *ppm, uint8_t *p)
435 for (
int i = 0;
i<=(config/2);
i++) {
436 ppm[0] = ((p[4] << 8) & 0x300) | p[0];
437 ppm[1] = ((p[4] << 6) & 0x300) | p[1];
438 ppm[2] = ((p[4] << 4) & 0x300) | p[2];
439 ppm[3] = ((p[4] << 2) & 0x300) | p[3];
445 ppm[0] = ((p[0] >> 6) & 3) * 333 + 12;
446 ppm[1] = ((p[0] >> 4) & 3) * 333 + 12;
447 ppm[2] = ((p[0] >> 2) & 3) * 333 + 12;
448 ppm[3] = ((p[0] >> 0) & 3) * 333 + 12;
453 static void rxscale_channels(int16_t control[])
455 for (uint32_t
i = 0;
i < OPENLRS_PPM_NUM_CHANNELS;
i++) {
456 int16_t x = control[
i];
461 }
else if (x < 1012) {
463 }
else if (x < 1024) {
464 ret = 2000 + (x - 1011) * 16;
473 static int pios_openlrs_form_telemetry(pios_openlrs_t openlrs_dev,
474 uint8_t *tx_buf, uint8_t rssi,
bool only_serial,
481 int max_data_len = TELEMETRY_PACKETSIZE - 1;
483 if (openlrs_dev->bind_data.ext_flags & EXT_FLAG_FASTDATA) {
487 max_data_len += data_len_adjust;
489 if (max_data_len < 1) {
492 }
else if (max_data_len >= MAX_PACKET_SIZE) {
493 max_data_len = MAX_PACKET_SIZE - 1;
496 if (data_len_adjust < 0) {
504 if (openlrs_dev->tx_out_cb) {
506 bool need_yield =
false;
507 bytes = (openlrs_dev->tx_out_cb)(openlrs_dev->tx_out_context,
508 &tx_buf[1], max_data_len, NULL, &need_yield);
512 if (bytes < (TELEMETRY_PACKETSIZE - 1)) {
513 tx_buf[0] |= (0x37 +
bytes);
518 if (openlrs_dev->bind_data.ext_flags & EXT_FLAG_FASTDATA) {
524 for (
int i = bytes+1;
i < TELEMETRY_PACKETSIZE;
i++) {
528 len = TELEMETRY_PACKETSIZE;
530 }
else if (only_serial) {
535 if (FlightBatteryStateHandle()) {
536 FlightBatteryStateData bat;
537 FlightBatteryStateGet(&bat);
541 if (bat.DetectedCellCount) {
545 tx_buf[2] = (uint8_t) (bat.Voltage / bat.DetectedCellCount / 5.0f * 255);
547 tx_buf[2] = (uint8_t) (bat.Voltage / 25.0f * 255);
549 tx_buf[3] = (uint8_t) (bat.Current / 60.0f * 255);
561 tx_buf[6] = count_set_bits(openlrs_status.LinkQuality & 0x7fff);
565 len = TELEMETRY_PACKETSIZE;
571 static uint32_t millis()
580 static uint8_t beaconGetRSSI(pios_openlrs_t openlrs_dev)
582 uint16_t rssiSUM = 0;
584 rfm22_set_frequency(openlrs_dev, openlrs_dev->beacon_frequency);
587 rssiSUM += rfm22_get_rssi(openlrs_dev);
589 rssiSUM += rfm22_get_rssi(openlrs_dev);
591 rssiSUM += rfm22_get_rssi(openlrs_dev);
593 rssiSUM += rfm22_get_rssi(openlrs_dev);
595 rfm22_set_frequency(openlrs_dev, openlrs_dev->bind_data.rf_frequency);
600 static bool binding_button_pushed(pios_openlrs_t openlrs_dev)
602 static bool button_history[3];
604 if (!openlrs_dev->cfg.bind_button) {
608 bool truth_value = GPIO_ReadInputDataBit(
609 openlrs_dev->cfg.bind_button->gpio,
610 openlrs_dev->cfg.bind_button->init.GPIO_Pin) !=
613 if (!openlrs_dev->cfg.bind_active_high) {
614 truth_value = !truth_value;
617 button_history[2] = button_history[1];
618 button_history[1] = button_history[0];
619 button_history[0] = truth_value;
622 return button_history[0] && button_history[1] &&
623 (!button_history[2]);
630 static bool pios_openlrs_bind_transmit_step(pios_openlrs_t openlrs_dev)
632 if (openlrs_dev->bind_data.version != BINDING_VERSION) {
637 uint32_t
start = millis();
640 rfm22_init(openlrs_dev,
true);
643 rfm22_tx_packet(openlrs_dev,
644 &openlrs_dev->bind_data,
645 sizeof(openlrs_dev->bind_data));
647 rfm22_rx_reset(openlrs_dev,
false);
651 while ((millis() - start) < 200) {
652 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
657 bool have_interrupt = wait_interrupt(openlrs_dev, 15);
659 if (have_interrupt) {
664 if (rfm22_rx_packet(openlrs_dev, &recv_byte, 1) &&
665 (recv_byte ==
'B')) {
671 rfm22_rx_reset(openlrs_dev,
false);
679 static void pios_openlrs_config_to_port_config(pios_openlrs_t openlrs_dev)
681 uintptr_t *target = NULL;
686 if (config.role == OPENLRS_ROLE_DISABLED) {
690 switch (config.data_source) {
691 case OPENLRS_DATA_SOURCE_UAVOTELEMETRY:
692 if (config.role == OPENLRS_ROLE_TX) {
693 #ifdef PIOS_COM_RADIOBRIDGE
699 #if defined(PIPXTREME) && defined(PIOS_COM_RADIOBRIDGE)
711 case OPENLRS_DATA_SOURCE_COMBRIDGE:
714 case OPENLRS_DATA_SOURCE_DISABLED:
724 (uintptr_t)openlrs_dev, 128, 288)) {
731 static bool pios_openlrs_config_to_bind_data(pios_openlrs_t openlrs_dev)
738 if ((config.version == BINDING_VERSION) &&
739 (config.rf_power > OPENLRS_RF_POWER_0)) {
740 openlrs_dev->bind_data.hdr =
'b';
741 openlrs_dev->bind_data.version = config.version;
742 openlrs_dev->bind_data.reserved[0] = 0;
743 openlrs_dev->bind_data.reserved[1] = 0;
744 openlrs_dev->bind_data.reserved[2] = 0;
745 openlrs_dev->bind_data.rf_frequency = config.rf_frequency;
746 openlrs_dev->bind_data.rf_magic = config.rf_magic;
747 openlrs_dev->bind_data.rf_power = config.rf_power - 1;
748 openlrs_dev->bind_data.rf_channel_spacing = config.rf_channel_spacing;
750 if (config.modem_params <= OPENLRS_MODEM_PARAMS_MAXOPTVAL) {
751 openlrs_dev->bind_data.modem_params = config.modem_params;
753 openlrs_dev->bind_data.flags = config.flags;
754 openlrs_dev->bind_data.ext_flags = config.ext_flags;
755 for (uint32_t
i = 0;
i < OPENLRS_HOPCHANNEL_NUMELEM;
i++)
756 openlrs_dev->bind_data.hopchannel[
i] = config.hopchannel[
i];
757 }
else if (config.role == OPENLRS_ROLE_TX) {
761 openlrs_dev->bind_data.hdr =
'b';
762 openlrs_dev->bind_data.version = BINDING_VERSION;
763 openlrs_dev->bind_data.reserved[0] = 0;
764 openlrs_dev->bind_data.reserved[1] = 0;
765 openlrs_dev->bind_data.reserved[2] = 0;
766 openlrs_dev->bind_data.rf_frequency =
767 def_carrier_freq(openlrs_dev->band);
769 openlrs_dev->bind_data.rf_power = OPENLRS_RF_POWER_100 - 1;
770 openlrs_dev->bind_data.rf_channel_spacing = 1;
772 openlrs_dev->bind_data.modem_params =
773 OPENLRS_MODEM_PARAMS_57600;
774 openlrs_dev->bind_data.flags = 10;
777 openlrs_dev->bind_data.ext_flags = EXT_FLAG_FASTDATA;
779 for (uint32_t
i = 0;
i < OPENLRS_HOPCHANNEL_NUMELEM;
i++) {
788 openlrs_dev->bind_data.hopchannel[
i] =
791 openlrs_dev->bind_data.hopchannel[
i] = 0;
797 openlrs_dev->beacon_frequency = config.beacon_frequency;
798 openlrs_dev->beacon_delay = config.beacon_delay;
799 openlrs_dev->beacon_period = config.beacon_period;
801 openlrs_dev->scale_min = config.tx_scale_min;
802 openlrs_dev->scale_max = config.tx_scale_max;
804 openlrs_dev->tx_source = config.tx_source;
805 openlrs_dev->tx_startup_bind_duration = config.tx_startup_bind_duration;
806 openlrs_dev->tx_bind_button_duration = config.tx_bind_button_duration;
811 static bool pios_openlrs_bind_data_to_config(pios_openlrs_t openlrs_dev)
813 if (openlrs_dev->bind_data.hdr ==
'b') {
814 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE)
818 DEBUG_PRINTF(2,
" version: %d\r\n", openlrs_dev->bind_data.version);
820 DEBUG_PRINTF(2,
" rf_frequency: %d\r\n", openlrs_dev->bind_data.rf_frequency);
822 DEBUG_PRINTF(2,
" rf_power: %d\r\n", openlrs_dev->bind_data.rf_power);
824 DEBUG_PRINTF(2,
" rf_channel_spacing: %d\r\n", openlrs_dev->bind_data.rf_channel_spacing);
826 DEBUG_PRINTF(2,
" modem_params: %d\r\n", openlrs_dev->bind_data.modem_params);
828 DEBUG_PRINTF(2,
" flags: %d\r\n", openlrs_dev->bind_data.flags);
831 for (uint32_t
i = 0;
i < MAXHOPS;
i++) {
832 DEBUG_PRINTF(2,
" hop channel: %d\r\n", openlrs_dev->bind_data.hopchannel[
i]);
838 if (openlrs_dev->bind_data.version == BINDING_VERSION) {
839 if (openlrs_dev->bind_data.rf_power >=
840 OPENLRS_RF_POWER_MAXOPTVAL) {
845 if (openlrs_dev->bind_data.modem_params >
846 OPENLRS_MODEM_PARAMS_MAXOPTVAL) {
851 OpenLRSGet(&binding);
852 binding.version = openlrs_dev->bind_data.version;
853 binding.rf_frequency = openlrs_dev->bind_data.rf_frequency;
854 binding.rf_magic = openlrs_dev->bind_data.rf_magic;
855 binding.rf_power = openlrs_dev->bind_data.rf_power + 1;
856 binding.rf_channel_spacing = openlrs_dev->bind_data.rf_channel_spacing;
857 binding.modem_params = openlrs_dev->bind_data.modem_params;
858 binding.flags = openlrs_dev->bind_data.flags;
859 binding.ext_flags = openlrs_dev->bind_data.ext_flags;
860 for (uint32_t
i = 0;
i < OPENLRS_HOPCHANNEL_NUMELEM;
i++)
861 binding.hopchannel[
i] = openlrs_dev->bind_data.hopchannel[
i];
862 binding.beacon_frequency = openlrs_dev->beacon_frequency;
863 binding.beacon_delay = openlrs_dev->beacon_delay;
864 binding.beacon_period = openlrs_dev->beacon_period;
866 if ((openlrs_dev->bind_data.ext_flags &
867 EXT_FLAG_FASTDATA) &&
868 (binding.data_source ==
869 OPENLRS_DATA_SOURCE_DISABLED)) {
873 binding.data_source =
874 OPENLRS_DATA_SOURCE_UAVOTELEMETRY;
877 OpenLRSSet(&binding);
881 #if defined(PIOS_LED_LINK)
892 static bool pios_openlrs_bind_receive(pios_openlrs_t openlrs_dev,
895 uint32_t start = millis();
897 rfm22_init(openlrs_dev,
true);
898 rfm22_rx_reset(openlrs_dev,
true);
903 while ((!timeout) || ((millis() - start) < timeout)) {
906 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
911 if (i++ % 100 == 0) {
914 if (openlrs_dev->rf_mode == Received) {
917 bool ok = rfm22_rx_packet(openlrs_dev,
918 &openlrs_dev->bind_data,
919 sizeof(openlrs_dev->bind_data));
921 if (ok && pios_openlrs_bind_data_to_config(openlrs_dev)) {
926 rfm22_tx_packet(openlrs_dev, &txb, 1);
927 rfm22_tx_packet(openlrs_dev, &txb, 1);
928 rfm22_tx_packet(openlrs_dev, &txb, 1);
932 rfm22_init(openlrs_dev,
false);
942 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE)
943 static void printVersion(uint16_t v)
946 ver[0] =
'0' + ((v >> 8) & 0x0f);
948 ver[2] =
'0' + ((v >> 4) & 0x0f);
951 ver[4] =
'0' + (v & 0x0f);
964 static void pios_openlrs_setup(pios_openlrs_t openlrs_dev)
968 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE)
969 printVersion(OPENLRSNG_VERSION);
975 openlrs_dev->hopcount = 0;
976 while ((openlrs_dev->hopcount < MAXHOPS) &&
977 (openlrs_dev->bind_data.hopchannel[openlrs_dev->hopcount] != 0)) {
978 openlrs_dev->hopcount++;
982 rfm22_init(openlrs_dev,
false);
984 pios_openlrs_do_hop(openlrs_dev);
986 openlrs_dev->link_acquired =
false;
992 static void pios_openlrs_rx_update_rssi(pios_openlrs_t openlrs_dev,
993 uint8_t rssi,
bool have_frame)
995 openlrs_status.LinkQuality <<= 1;
996 openlrs_status.LinkQuality |= !!have_frame;
999 openlrs_status.LastRSSI =
rssi;
1005 openlrs_status.LastRSSI >>= 1;
1009 static bool pios_openlrs_rx_frame(pios_openlrs_t openlrs_dev, uint8_t rssi)
1011 uint8_t *tx_buf = openlrs_dev->tx_buf;
1012 uint8_t rx_buf[MAX_PACKET_SIZE];
1014 int ctrl_size = get_control_packet_size(&openlrs_dev->bind_data);
1017 int size = rfm22_rx_packet_variable(openlrs_dev, rx_buf,
1024 pios_openlrs_rx_update_rssi(openlrs_dev, rssi,
true);
1026 #if defined(PIOS_LED_LINK)
1030 if ((rx_buf[0] & 0x3e) == 0x00) {
1033 if (size != ctrl_size) {
1039 unpack_channels(openlrs_dev->bind_data.flags,
1040 openlrs_dev->ppm, rx_buf + 1);
1041 rxscale_channels(openlrs_dev->ppm);
1044 if (openlrs_dev->openlrs_rcvr_id) {
1045 #if defined(PIOS_INCLUDE_OPENLRS_RCVR)
1047 openlrs_dev->openlrs_rcvr_id,
1051 }
else if ((rx_buf[0] & 0x3f) == 0x02) {
1060 if (rx_buf[0] & 0x80) {
1061 openlrs_dev->tx_buf[0] |= 0x80;
1063 openlrs_dev->tx_buf[0] &= ~0x80;
1067 if (((rx_buf[0] & 0x38) == 0x38) &&
1068 ((rx_buf[0] ^ tx_buf[0]) & 0x80)) {
1071 uint8_t data_len = (rx_buf[0] & 7) + 1;
1073 if ((data_len + 1) > size) {
1077 if (data_len < (size - 1)) {
1079 data_len = size - 1;
1082 if (openlrs_dev->rx_in_cb) {
1083 (openlrs_dev->rx_in_cb)(openlrs_dev->rx_in_context,
1084 &rx_buf[1], data_len,
1085 NULL, &rx_need_yield);
1090 if (rx_buf[0] & 0x80) {
1091 openlrs_dev->tx_buf[0] |= 0x80;
1093 openlrs_dev->tx_buf[0] &= ~0x80;
1098 if (openlrs_dev->bind_data.flags & TELEMETRY_MASK) {
1099 if ((tx_buf[0] ^ rx_buf[0]) & 0x40) {
1104 if ((tx_buf[0] & 0x3F) == 0) {
1106 openlrs_dev->telem_len =
1107 pios_openlrs_form_telemetry(
1108 openlrs_dev, tx_buf, rssi,
1109 false, ctrl_size - size);
1113 openlrs_dev->telem_len = pios_openlrs_form_telemetry(
1114 openlrs_dev, tx_buf, rssi,
false,
1118 if (openlrs_dev->telem_len == 0) {
1120 openlrs_dev->telem_len = 1;
1124 rfm22_tx_packet(openlrs_dev, tx_buf, openlrs_dev->telem_len);
1128 rfm22_rx_reset(openlrs_dev,
false);
1133 static void pios_openlrs_do_hop(pios_openlrs_t openlrs_dev)
1135 openlrs_dev->rf_channel++;
1137 if (openlrs_dev->rf_channel >= openlrs_dev->hopcount) {
1138 openlrs_dev->rf_channel = 0;
1141 if (openlrs_dev->beacon_armed) {
1144 uint8_t rssi = beaconGetRSSI(openlrs_dev) << 2;
1146 if ((openlrs_dev->beacon_rssi_avg + 80) < rssi) {
1147 openlrs_dev->nextBeaconTimeMs =
1151 openlrs_dev->beacon_rssi_avg =
1152 (openlrs_dev->beacon_rssi_avg * 3 +
rssi) >> 2;
1155 rfm22_set_channel(openlrs_dev, openlrs_dev->rf_channel);
1158 static void pios_openlrs_rx_after_receive(pios_openlrs_t openlrs_dev,
1161 uint32_t timeUs, timeMs;
1166 bool willhop =
true;
1168 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
1178 uint32_t interval = get_nominal_packet_interval(
1179 &openlrs_dev->bind_data, NULL);
1187 openlrs_dev->link_acquired =
true;
1189 openlrs_dev->beacon_armed =
false;
1190 openlrs_dev->numberOfLostPackets = 0;
1191 openlrs_dev->nextBeaconTimeMs = 0;
1194 openlrs_dev->lastPacketTimeUs = timeUs;
1195 openlrs_dev->linkLossTimeMs = 0;
1196 }
else if (openlrs_dev->numberOfLostPackets < openlrs_dev->hopcount) {
1198 openlrs_dev->numberOfLostPackets);
1200 openlrs_dev->numberOfLostPackets++;
1201 openlrs_dev->lastPacketTimeUs += interval;
1203 (interval * (openlrs_dev->hopcount + 1)))) {
1204 #if defined(PIOS_LED_LINK)
1220 openlrs_dev->lastPacketTimeUs = timeUs;
1222 if (!openlrs_dev->linkLossTimeMs) {
1223 openlrs_dev->linkLossTimeMs = timeMs;
1227 if (openlrs_dev->link_acquired && openlrs_dev->linkLossTimeMs) {
1228 if (!openlrs_dev->nextBeaconTimeMs) {
1229 openlrs_dev->nextBeaconTimeMs = timeMs +
1230 openlrs_dev->beacon_delay * 1000UL;
1231 }
else if ((openlrs_dev->beacon_frequency) &&
1232 ((timeMs - openlrs_dev->nextBeaconTimeMs)
1236 openlrs_dev->beacon_armed =
true;
1238 DEBUG_PRINTF(2,
"Beacon time: %d\r\n", openlrs_dev->nextBeaconTimeMs);
1243 FlightStatusArmedGet(&armed);
1244 if (armed == FLIGHTSTATUS_ARMED_DISARMED) {
1245 rfm22_beacon_send(openlrs_dev,
false);
1246 rfm22_init(openlrs_dev,
false);
1247 rfm22_rx_reset(openlrs_dev,
false);
1248 openlrs_dev->nextBeaconTimeMs = (timeMs + 1000UL * openlrs_dev->beacon_period) | 1;
1254 pios_openlrs_do_hop(openlrs_dev);
1255 rfm22_rx_reset(openlrs_dev,
false);
1259 OpenLRSStatusSet(&openlrs_status);
1262 uint8_t PIOS_OpenLRS_RSSI_Get(
void)
1265 if (OpenLRSHandle() == NULL)
1269 OpenLRSRSSI_TypeGet(&rssi_type);
1271 uint16_t LQ = count_set_bits(openlrs_status.LinkQuality & 0x7fff);
1273 switch (rssi_type) {
1274 case OPENLRS_RSSI_TYPE_COMBINED:
1276 return (openlrs_status.LastRSSI >> 1)+128;
1277 }
else if (LQ == 0) {
1281 (openlrs_status.LastRSSI >> 5);
1283 case OPENLRS_RSSI_TYPE_RSSI:
1284 return openlrs_status.LastRSSI;
1285 case OPENLRS_RSSI_TYPE_LINKQUALITY:
1302 void PIOS_OpenLRS_RegisterRcvr(pios_openlrs_t openlrs_dev,
1303 uintptr_t openlrs_rcvr_id)
1307 openlrs_dev->openlrs_rcvr_id = openlrs_rcvr_id;
1322 int32_t PIOS_OpenLRS_Init(pios_openlrs_t *openlrs_id,
pios_spi_t spi_id,
1323 uint32_t slave_num,
const struct pios_openlrs_cfg *
cfg,
1324 HwSharedRfBandOptions rf_band,
1325 HwSharedMaxRfPowerOptions rf_power)
1331 pios_openlrs_t openlrs_dev = pios_openlrs_alloc();
1337 openlrs_dev->slave_num = slave_num;
1338 openlrs_dev->spi_id = spi_id;
1341 openlrs_dev->band = rf_band;
1342 openlrs_dev->max_power = rf_power;
1346 if (device_type != 0x08)
1349 OpenLRSInitialize();
1350 OpenLRSStatusInitialize();
1353 openlrs_dev->cfg = *
cfg;
1357 pios_openlrs_config_to_port_config(openlrs_dev);
1359 if (pios_openlrs_config_to_bind_data(openlrs_dev)) {
1361 pios_openlrs_bind_data_to_config(openlrs_dev);
1364 if (cfg->bind_button) {
1365 GPIO_Init(cfg->bind_button->gpio,
1366 (GPIO_InitTypeDef *) &(cfg->bind_button->init));
1369 *openlrs_id = openlrs_dev;
1374 int32_t PIOS_OpenLRS_Start(pios_openlrs_t openlrs_dev)
1376 if (openlrs_dev->max_power == HWSHARED_MAXRFPOWER_0) {
1390 OpenLRSroleOptions role;
1392 OpenLRSroleGet(&role);
1395 case OPENLRS_ROLE_RX:
1396 openlrs_dev->taskHandle =
1401 openlrs_dev->taskHandle);
1403 case OPENLRS_ROLE_TX:
1404 openlrs_dev->taskHandle =
1409 openlrs_dev->taskHandle);
1411 case OPENLRS_ROLE_DISABLED:
1413 rfm22_disable(openlrs_dev);
1420 static int pios_openlrs_form_control_frame(pios_openlrs_t openlrs_dev,
1423 int16_t channels[OPENLRS_PPM_NUM_CHANNELS];
1427 for (
int i = 0; i < OPENLRS_PPM_NUM_CHANNELS; i++) {
1431 for (
int i = 0; i < 4; i++) {
1435 if (channels[i] < 0) {
1440 for (
int i = 4; i < OPENLRS_PPM_NUM_CHANNELS; i++) {
1444 if (channels[i] < 0) {
1445 channels[
i] = (openlrs_dev->scale_min +
1446 openlrs_dev->scale_max) / 2;
1450 txscale_channels(channels, openlrs_dev->scale_min, openlrs_dev->scale_max);
1452 int len = pack_channels(openlrs_dev->bind_data.flags,
1453 channels, tx_buf+1);
1459 static bool pios_openlrs_tx_receive_telemetry(pios_openlrs_t openlrs_dev)
1461 uint8_t rx_buf[MAX_PACKET_SIZE];
1464 int len = rfm22_rx_packet_variable(openlrs_dev, rx_buf,
1471 if (((rx_buf[0] & 0x3f) == 0) && (len == TELEMETRY_PACKETSIZE)) {
1476 openlrs_status.LastRSSI = rx_buf[1];
1477 openlrs_status.LinkQuality = (1 << (rx_buf[6])) - 1;
1479 OpenLRSStatusSet(&openlrs_status);
1480 }
else if (((rx_buf[0] & 0x38) == 0x38) &&
1481 ((rx_buf[0] ^ openlrs_dev->tx_buf[0]) & 0x40)) {
1483 uint8_t data_len = (rx_buf[0] & 7) + 1;
1485 if ((data_len + 1) > len) {
1489 if (data_len < (len - 1)) {
1494 if (openlrs_dev->rx_in_cb) {
1495 (openlrs_dev->rx_in_cb)(openlrs_dev->rx_in_context,
1496 &rx_buf[1], data_len,
1497 NULL, &rx_need_yield);
1501 #if defined(PIOS_LED_LINK)
1506 if (rx_buf[0] & 0x40) {
1507 openlrs_dev->tx_buf[0] |= 0x40;
1509 openlrs_dev->tx_buf[0] &= ~0x40;
1512 openlrs_dev->tx_prev_rxtelem_hdr = rx_buf[0];
1517 static void pios_openlrs_tx_wait_and_transmit(pios_openlrs_t openlrs_dev,
1518 uint32_t interval, uint8_t *tx_buf,
int len)
1526 openlrs_dev->lastPacketTimeUs += interval;
1528 rfm22_tx_packet(openlrs_dev, tx_buf, len);
1531 static void pios_openlrs_tx_frame(pios_openlrs_t openlrs_dev)
1533 rfm22_rx_reset(openlrs_dev,
false);
1537 get_nominal_packet_interval(&openlrs_dev->bind_data, &rx_slop);
1539 pios_openlrs_do_hop(openlrs_dev);
1541 bool telem_uplink =
false;
1543 openlrs_dev->tx_buf[0] &= 0xc0;
1549 uint8_t tx_buf[MAX_PACKET_SIZE];
1551 tx_buf[0] = openlrs_dev->tx_buf[0];
1553 int len = pios_openlrs_form_control_frame(openlrs_dev, tx_buf);
1555 if ((!len) || openlrs_dev->tx_ok_to_telemeter) {
1556 openlrs_dev->tx_ok_to_telemeter =
false;
1558 if (openlrs_dev->telem_len &&
1559 ((openlrs_dev->tx_buf[0] ^
1560 openlrs_dev->tx_prev_rxtelem_hdr) & 0x80)) {
1562 telem_uplink =
true;
1565 get_control_packet_size(&openlrs_dev->bind_data);
1568 openlrs_dev->telem_len =
1569 pios_openlrs_form_telemetry(openlrs_dev,
1570 openlrs_dev->tx_buf, 0,
true,
1571 ctrl_size - TELEMETRY_PACKETSIZE +
1572 TELEMETRY_PACKETSIZE / 2);
1583 if (openlrs_dev->telem_len) {
1585 telem_uplink =
true;
1586 openlrs_dev->tx_buf[0] ^= 0x80;
1592 pios_openlrs_tx_wait_and_transmit(openlrs_dev, interval,
1593 openlrs_dev->tx_buf, openlrs_dev->telem_len);
1594 }
else if (len > 0) {
1598 pios_openlrs_tx_wait_and_transmit(openlrs_dev, interval,
1606 pios_openlrs_tx_wait_and_transmit(openlrs_dev, interval,
1610 if (!(openlrs_dev->bind_data.flags & TELEMETRY_MASK)) {
1614 rfm22_rx_reset(openlrs_dev,
false);
1617 uint32_t expiry = openlrs_dev->lastPacketTimeUs + interval +
1621 bool have_interrupt = wait_interrupt_until(openlrs_dev, expiry,
1624 bool got_packet =
false;
1626 if (have_interrupt) {
1627 if (pios_openlrs_tx_receive_telemetry(openlrs_dev)) {
1628 if (!telem_uplink) {
1633 openlrs_dev->tx_ok_to_telemeter =
true;
1642 if (openlrs_dev->numberOfLostPackets < openlrs_dev->hopcount) {
1643 openlrs_dev->numberOfLostPackets++;
1645 #if defined(PIOS_LED_LINK)
1649 if (!openlrs_dev->linkLossTimeMs) {
1650 openlrs_dev->linkLossTimeMs =
1655 openlrs_dev->numberOfLostPackets = 0;
1656 openlrs_dev->linkLossTimeMs = 0;
1657 openlrs_dev->link_acquired =
true;
1661 static void pios_openlrs_tx_task(
void *parameters)
1663 pios_openlrs_t openlrs_dev = (pios_openlrs_t)parameters;
1666 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
1672 pios_openlrs_setup(openlrs_dev);
1676 pios_openlrs_setup(openlrs_dev);
1678 int i = openlrs_dev->tx_startup_bind_duration * 5;
1683 if (binding_button_pushed(openlrs_dev)) {
1684 i = openlrs_dev->tx_bind_button_duration * 5;
1694 if (pios_openlrs_bind_transmit_step(openlrs_dev)) {
1700 }
else if (i == 0) {
1701 rfm22_init(openlrs_dev,
false);
1706 pios_openlrs_tx_frame(openlrs_dev);
1710 static void pios_openlrs_rx_step(pios_openlrs_t openlrs_dev)
1712 rfm22_check_hang(openlrs_dev);
1716 uint32_t interval, slop;
1718 interval = get_nominal_packet_interval(&openlrs_dev->bind_data,
1735 uint32_t expiry = openlrs_dev->lastPacketTimeUs + interval + slop;
1737 bool have_frame =
false;
1739 if (wait_interrupt_until(openlrs_dev, expiry, &rssi)) {
1741 have_frame = pios_openlrs_rx_frame(openlrs_dev, rssi);
1749 "ISR Timeout. Missed packet: %d %d\r\n",
1754 pios_openlrs_rx_update_rssi(openlrs_dev, rssi,
1759 pios_openlrs_rx_after_receive(openlrs_dev, have_frame);
1769 static void pios_openlrs_rx_task(
void *parameters)
1771 pios_openlrs_t openlrs_dev = (pios_openlrs_t)parameters;
1774 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
1780 pios_openlrs_setup(openlrs_dev);
1787 if ((!openlrs_dev->link_acquired) &&
1788 binding_button_pushed(openlrs_dev)) {
1789 openlrs_dev->bind_data.version = 0;
1792 while (openlrs_dev->bind_data.version != BINDING_VERSION) {
1793 pios_openlrs_bind_receive(openlrs_dev, 0);
1796 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
1801 pios_openlrs_rx_step(openlrs_dev);
1805 bool PIOS_OpenLRS_EXT_Int(pios_openlrs_t openlrs_dev)
1809 if (openlrs_dev->rf_mode == Transmit) {
1810 openlrs_dev->rf_mode = Transmitted;
1811 }
else if (openlrs_dev->rf_mode == Receive) {
1812 openlrs_dev->rf_mode = Received;
1825 static pios_openlrs_t pios_openlrs_alloc(
void)
1827 pios_openlrs_t openlrs_dev;
1829 openlrs_dev = (pios_openlrs_t)
PIOS_malloc(
sizeof(*openlrs_dev));
1835 *openlrs_dev = (
struct pios_openlrs_dev) {
1836 .magic = PIOS_OPENLRS_DEV_MAGIC,
1841 if (!openlrs_dev->sema_isr) {
1854 static bool pios_openlrs_validate(pios_openlrs_t openlrs_dev)
1856 return openlrs_dev != NULL
1857 && openlrs_dev->magic == PIOS_OPENLRS_DEV_MAGIC;
1860 static void rfm22_set_channel(pios_openlrs_t openlrs_dev, uint8_t ch)
1864 uint8_t magicLSB = (openlrs_dev->bind_data.rf_magic & 0xff) ^ ch;
1865 rfm22_claim_bus(openlrs_dev);
1869 rfm22_release_bus(openlrs_dev);
1872 static uint8_t rfm22_get_rssi(pios_openlrs_t openlrs_dev)
1874 return rfm22_read_claim(openlrs_dev, 0x26);
1877 static void rfm22_set_modem_regs(pios_openlrs_t openlrs_dev,
const struct rfm22_modem_regs *r)
1897 static void rfm22_beacon_tone(pios_openlrs_t openlrs_dev, int16_t hz, int16_t len)
1900 uint32_t
d = 500000000 / hz;
1904 #if defined(PIOS_LED_LINK)
1908 rfm22_claim_bus(openlrs_dev);
1910 GPIO_TypeDef *gpio = openlrs_dev->cfg.spi_cfg->mosi.gpio;
1911 uint16_t pin_source = openlrs_dev->cfg.spi_cfg->mosi.init.GPIO_Pin;
1916 #if defined(STM32F10X_MD)
1917 GPIO_InitTypeDef init = {
1918 .GPIO_Speed = GPIO_Speed_50MHz,
1919 .GPIO_Mode = GPIO_Mode_Out_PP,
1920 .GPIO_Pin = pin_source,
1923 GPIO_InitTypeDef init = {
1924 .GPIO_Speed = GPIO_Speed_50MHz,
1925 .GPIO_Mode = GPIO_Mode_OUT,
1926 .GPIO_OType = GPIO_OType_PP,
1927 .GPIO_PuPd = GPIO_PuPd_UP,
1928 .GPIO_Pin = pin_source,
1932 GPIO_PinAFConfig(gpio, pin_source, 0);
1935 GPIO_Init(gpio, &init);
1937 uint32_t cycles = (len * hz) / 5;
1941 for (int16_t i = 0; i < cycles / 4; i++) {
1942 GPIO_SetBits(gpio, pin_source);
1944 GPIO_ResetBits(gpio, pin_source);
1946 GPIO_SetBits(gpio, pin_source);
1948 GPIO_ResetBits(gpio, pin_source);
1950 GPIO_SetBits(gpio, pin_source);
1952 GPIO_ResetBits(gpio, pin_source);
1954 GPIO_SetBits(gpio, pin_source);
1956 GPIO_ResetBits(gpio, pin_source);
1960 GPIO_Init(gpio, (GPIO_InitTypeDef *) &openlrs_dev->cfg.spi_cfg->mosi.init);
1962 #if !defined(STM32F10X_MD)
1963 GPIO_PinAFConfig(gpio, pin_source, openlrs_dev->cfg.spi_cfg->remap);
1966 rfm22_release_bus(openlrs_dev);
1968 #if defined(PIOS_LED_LINK)
1973 static void rfm22_disable(pios_openlrs_t openlrs_dev)
1975 rfm22_claim_bus(openlrs_dev);
1981 rfm22_get_it_status(openlrs_dev);
1983 rfm22_release_bus(openlrs_dev);
1986 static void rfm22_beacon_send(pios_openlrs_t openlrs_dev,
bool static_tone)
1989 rfm22_claim_bus(openlrs_dev);
1990 rfm22_get_it_status(openlrs_dev);
1991 rfm22_write(openlrs_dev, 0x06, 0x00);
1992 rfm22_write(openlrs_dev, 0x07, RF22B_PWRSTATE_READY);
1993 rfm22_write(openlrs_dev, 0x09, 0x7f);
1994 rfm22_write(openlrs_dev, 0x0a, 0x05);
1995 rfm22_write(openlrs_dev, 0x0b, 0x12);
1996 rfm22_write(openlrs_dev, 0x0c, 0x15);
1997 rfm22_write(openlrs_dev, 0x0d, 0xfd);
1998 rfm22_write(openlrs_dev, 0x0e, 0x00);
2000 rfm22_write(openlrs_dev, 0x70, 0x2C);
2002 rfm22_write(openlrs_dev, 0x30, 0x00);
2004 rfm22_write(openlrs_dev, 0x79, 0);
2006 rfm22_write(openlrs_dev, 0x7a, 0x05);
2008 rfm22_write(openlrs_dev, 0x71, 0x12);
2009 rfm22_write(openlrs_dev, 0x72, 0x02);
2011 rfm22_write(openlrs_dev, 0x73, 0x00);
2012 rfm22_write(openlrs_dev, 0x74, 0x00);
2013 rfm22_release_bus(openlrs_dev);
2015 rfm22_set_frequency(openlrs_dev, openlrs_dev->beacon_frequency);
2017 rfm22_write_claim(openlrs_dev, 0x6d, 0x07);
2021 rfm22_write_claim(openlrs_dev, 0x07, RF22B_PWRSTATE_TX);
2025 rfm22_beacon_tone(openlrs_dev, 440, 20);
2027 rfm22_beacon_tone(openlrs_dev, 784, 1);
2029 rfm22_write(openlrs_dev, 0x6d, 0x05);
2031 rfm22_beacon_tone(openlrs_dev, 699, 1);
2033 rfm22_write(openlrs_dev, 0x6d, 0x04);
2035 rfm22_beacon_tone(openlrs_dev, 659, 1);
2037 rfm22_write(openlrs_dev, 0x6d, 0x02);
2039 rfm22_beacon_tone(openlrs_dev, 659,1);
2041 rfm22_write(openlrs_dev, 0x6d, 0x00);
2043 rfm22_beacon_tone(openlrs_dev, 699, 3);
2046 rfm22_write_claim(openlrs_dev, 0x07, RF22B_PWRSTATE_READY);
2049 static void rfm22_tx_packet(pios_openlrs_t openlrs_dev,
void *pkt,
2052 if (openlrs_dev->max_power == HWSHARED_MAXRFPOWER_0) {
2057 openlrs_dev->rf_mode = Transmit;
2059 rfm22_claim_bus(openlrs_dev);
2067 rfm22_get_it_status(openlrs_dev);
2071 rfm22_assert_cs(openlrs_dev);
2074 rfm22_deassert_cs(openlrs_dev);
2081 rfm22_release_bus(openlrs_dev);
2083 bool ok = wait_interrupt(openlrs_dev, 60000);
2085 rfm22_claim_bus(openlrs_dev);
2086 rfm22_get_it_status(openlrs_dev);
2087 rfm22_release_bus(openlrs_dev);
2089 #if defined(PIOS_INCLUDE_WDG) && defined(PIOS_WDG_RFM22B)
2095 DEBUG_PRINTF(2,
"OLRS ERR: rfm22_tx_packet timeout\r\n");
2096 rfm22_init(openlrs_dev,
false);
2100 static void rfm22_rx_packet_sizeknown(pios_openlrs_t openlrs_dev,
2101 void *whence, uint32_t size)
2105 rfm22_assert_cs(openlrs_dev);
2109 rfm22_deassert_cs(openlrs_dev);
2112 static bool rfm22_rx_packet(pios_openlrs_t openlrs_dev,
2113 void *whence, uint32_t size)
2115 rfm22_claim_bus(openlrs_dev);
2121 rfm22_rx_packet_sizeknown(openlrs_dev, whence, size);
2126 rfm22_release_bus(openlrs_dev);
2131 static int rfm22_rx_packet_variable(pios_openlrs_t openlrs_dev,
2132 void *whence, uint32_t max_size)
2134 rfm22_claim_bus(openlrs_dev);
2139 if ((size <= max_size) && (size > 0)) {
2140 rfm22_rx_packet_sizeknown(openlrs_dev, whence, size);
2145 rfm22_release_bus(openlrs_dev);
2151 static void rfm22_rx_reset(pios_openlrs_t openlrs_dev,
bool pause_long)
2153 openlrs_dev->rf_mode = Receive;
2158 rfm22_claim_bus(openlrs_dev);
2160 rfm22_get_it_status(openlrs_dev);
2161 rfm22_release_bus(openlrs_dev);
2165 rfm22_claim_bus(openlrs_dev);
2171 rfm22_get_it_status(openlrs_dev);
2179 rfm22_release_bus(openlrs_dev);
2182 DONT_BUILD_IF(HWSHARED_MAXRFPOWER_MAXOPTVAL != 8, InvRfPowerOptions);
2183 DONT_BUILD_IF(HWSHARED_MAXRFPOWER_0 != 0, InvRfPowerOptions2);
2184 DONT_BUILD_IF(HWSHARED_MAXRFPOWER_125 != 1, InvRfPowerOptions3);
2185 DONT_BUILD_IF(HWSHARED_MAXRFPOWER_100 != 8, InvRfPowerOptions4);
2187 static void rfm22_init(pios_openlrs_t openlrs_dev, uint8_t isbind)
2194 DEBUG_PRINTF(2,
" version: %d\r\n", openlrs_dev->bind_data.version);
2196 DEBUG_PRINTF(2,
" rf_frequency: %d\r\n", openlrs_dev->bind_data.rf_frequency);
2198 DEBUG_PRINTF(2,
" rf_power: %d\r\n", openlrs_dev->bind_data.rf_power);
2200 DEBUG_PRINTF(2,
" rf_channel_spacing: %d\r\n", openlrs_dev->bind_data.rf_channel_spacing);
2202 DEBUG_PRINTF(2,
" modem_params: %d\r\n", openlrs_dev->bind_data.modem_params);
2204 DEBUG_PRINTF(2,
" flags: %d\r\n", openlrs_dev->bind_data.flags);
2213 rfm22_claim_bus(openlrs_dev);
2218 switch (openlrs_dev->cfg.gpio_direction) {
2219 case GPIO0_TX_GPIO1_RX:
2223 case GPIO0_RX_GPIO1_TX:
2232 rfm22_set_modem_regs(openlrs_dev, &modem_params[OPENLRS_BIND_PARAMS]);
2234 rfm22_set_modem_regs(openlrs_dev, &modem_params[openlrs_dev->bind_data.modem_params]);
2241 rfm22_write(openlrs_dev,
RFM22_preamble_length, (openlrs_dev->bind_data.flags & DIVERSITY_ENABLED) ? 0x14 : 0x0a);
2248 uint32_t
magic = isbind ? BIND_MAGIC : openlrs_dev->bind_data.rf_magic;
2249 for (uint8_t i = 0; i < 4; i++) {
2267 MIN(openlrs_dev->max_power - 1, BINDING_POWER));
2270 MIN(openlrs_dev->max_power - 1,
2271 openlrs_dev->bind_data.rf_power));
2279 rfm22_release_bus(openlrs_dev);
2281 rfm22_rx_reset(openlrs_dev,
true);
2283 rfm22_set_frequency(openlrs_dev,
2284 isbind ? binding_freq(openlrs_dev->band) :
2285 openlrs_dev->bind_data.rf_frequency);
2288 static void rfm22_set_frequency(pios_openlrs_t openlrs_dev, uint32_t
f)
2293 if ((f < min_freq(openlrs_dev->band)) ||
2294 (f > max_freq(openlrs_dev->band))) {
2295 f = def_carrier_freq(openlrs_dev->band);
2299 uint16_t fb, fc, hbsel;
2300 if (f < 480000000) {
2302 fb = f / 10000000 - 24;
2303 fc = (f - (fb + 24) * 10000000) * 4 / 625;
2306 fb = f / 20000000 - 24;
2307 fc = (f - (fb + 24) * 20000000) * 2 / 625;
2309 rfm22_claim_bus(openlrs_dev);
2314 rfm22_release_bus(openlrs_dev);
2318 static void rfm22_get_it_status(pios_openlrs_t openlrs_dev)
2324 static void rfm22_check_hang(pios_openlrs_t openlrs_dev)
2327 if (rfm22_read_claim(openlrs_dev, 0x0C) == 0) {
2329 rfm22_init(openlrs_dev,
false);
2342 static void rfm22_assert_cs(pios_openlrs_t openlrs_dev)
2346 openlrs_dev->slave_num, 0);
2354 static void rfm22_deassert_cs(pios_openlrs_t openlrs_dev)
2357 openlrs_dev->slave_num, 1);
2365 static void rfm22_claim_bus(pios_openlrs_t openlrs_dev)
2375 static void rfm22_release_bus(pios_openlrs_t openlrs_dev)
2387 static void rfm22_write(pios_openlrs_t openlrs_dev, uint8_t addr,
2390 rfm22_assert_cs(openlrs_dev);
2391 uint8_t buf[2] = { addr | 0x80, data };
2393 rfm22_deassert_cs(openlrs_dev);
2403 static uint8_t rfm22_read(pios_openlrs_t openlrs_dev, uint8_t addr)
2405 uint8_t out[2] = { addr & 0x7F, 0xFF };
2408 rfm22_assert_cs(openlrs_dev);
2410 rfm22_deassert_cs(openlrs_dev);
2421 static void rfm22_write_claim(pios_openlrs_t openlrs_dev,
2422 uint8_t addr, uint8_t
data)
2424 rfm22_claim_bus(openlrs_dev);
2425 rfm22_write(openlrs_dev, addr, data);
2426 rfm22_release_bus(openlrs_dev);
2436 static uint8_t rfm22_read_claim(pios_openlrs_t openlrs_dev, uint8_t addr)
2440 rfm22_claim_bus(openlrs_dev);
2441 ret = rfm22_read(openlrs_dev, addr);
2442 rfm22_release_bus(openlrs_dev);
uint32_t PIOS_Thread_Systime(void)
uint32_t PIOS_DELAY_GetuS()
Query the Delay timer for the current uS.
Main PiOS header to include all the compiled in PiOS options.
#define RFM22_header_control1
struct usb_configuration_desc config
#define RFM22_header_enable2
#define RFM22_data_access_control
void(* bind_tx_cb)(uintptr_t id, pios_com_callback tx_out_cb, uintptr_t context)
int32_t PIOS_SPI_RC_PinSet(pios_spi_t spi_dev, uint32_t slave_id, bool pin_value)
int32_t PIOS_EXTI_Init(const struct pios_exti_cfg *cfg)
#define RFM22_afc_limiter
#define RFM22_clk_recovery_timing_loop_gain0
int32_t PIOS_SPI_ClaimBus(pios_spi_t spi_dev)
#define RFM22_cpu_output_clk
uintptr_t pios_com_debug_id
static uint32_t PIOS_INLINEDELAY_NsToCycles(uint32_t ns)
bool PIOS_WDG_RegisterFlag(uint16_t flag_requested)
Register a module against the watchdog.
#define PIOS_DEBUG_Assert(test)
uint32_t PIOS_DELAY_GetuSExpired(uint32_t t)
Calculates whether a given time has passed.
bool PIOS_WDG_UpdateFlag(uint16_t flag)
Function called by modules to indicate they are still running.
void * PIOS_malloc(size_t size)
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
#define RFM22_tx_data_rate0
int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId)
int32_t PIOS_OpenLRS_Rcvr_UpdateChannels(uintptr_t openlrs_rcvr_id, int16_t *channels)
#define RFM22_gpio0_config_txstate
uint32_t PIOS_DELAY_GetuSSince(uint32_t t)
Calculate time in microseconds since a previous time.
#define RFM22_interrupt_status1
void PIOS_ANNUNC_Off(uint32_t annunc_id)
#define DEBUG_PRINTF(level,...)
#define RFM22_frequency_deviation
#define RFM22_clk_recovery_offset1
#define RFM22_io_port_config
#define RFM22_frequency_hopping_channel_select
#define RFM22_header_enable0
#define RFM22_tx_data_rate1
uint8_t data[XFER_BYTES_PER_PACKET]
#define RFM22_check_header3
static struct flyingpicmd_cfg_fa cfg
#define PIOS_COM_TELEM_SER
#define RFM22_gpio0_config_rxstate
#define RFM22_frequency_offset2
#define RFM22_preamble_detection_ctrl1
#define RFM22_transmit_header3
#define RFM22_opfc1_swres
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
uint8_t PIOS_SPI_TransferByte(pios_spi_t spi_dev, uint8_t b)
#define RFM22_gpio0_config
#define RFM22_header_enable3
#define RFM22_interrupt_enable2
int32_t PIOS_SPI_TransferBlock(pios_spi_t spi_dev, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
#define RFM22_nominal_carrier_frequency1
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
uint32_t randomize_int(uint32_t interval)
#define RFM22_modulation_mode_control2
void PIOS_ANNUNC_On(uint32_t annunc_id)
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
#define RFM22_gpio1_config_rxstate
#define RFM22_frequency_hopping_step_size
#define RFM22_clk_recovery_timing_loop_gain1
#define RFM22_clk_recovery_offset0
#define RFM22_xtal_osc_load_cap
#define RFM22_frequency_offset1
#define RFM22_ie1_enpkvalid
static void PIOS_INLINEDELAY_TillCycleCnt(uint32_t whence)
#define RFM22_fifo_access
void PIOS_free(void *buf)
void PIOS_Thread_Sleep(uint32_t time_ms)
#define RFM22_op_and_func_ctrl1
void PIOS_ANNUNC_Toggle(uint32_t annunc_id)
int32_t PIOS_RCVR_Read(uintptr_t rcvr_id, uint8_t channel)
#define RFM22_frequency_band_select
uintptr_t PIOS_HAL_GetReceiver(int receiver_type)
#define RFM22_if_filter_bandwidth
#define RFM22_interrupt_enable1
static uint32_t PIOS_INLINEDELAY_GetCycleCnt()
int32_t PIOS_COM_Init(uintptr_t *com_id, const struct pios_com_driver *driver, uintptr_t lower_id, uint16_t rx_buffer_len, uint16_t tx_buffer_len)
#define RFM22_preamble_length
#define RFM22_clk_recovery_oversampling_ratio
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
#define PIOS_COM_RADIOBRIDGE
#define DONT_BUILD_IF(COND, MSG)
#define RFM22_ie1_enpksent
#define RFM22_op_and_func_ctrl2
#define RFM22_gpio1_config_txstate
#define RFM22_modulation_mode_control1
int32_t PIOS_SPI_ReleaseBus(pios_spi_t spi_dev)
void system_annunc_custom_string(const char *string)
#define RFM22_header_enable1
#define RFM22_DEVICE_TYPE
#define RFM22_interrupt_status2
#define RFM22_afc_timing_control
#define RFM22_header_control2
#define RFM22_gpio2_config
#define RFM22_clk_recovery_offset2
#define RFM22_transmit_packet_length
if(BaroAltitudeHandle()!=NULL)
#define RFM22_nominal_carrier_frequency0
#define PIOS_Assert(test)
#define RFM22_gpio1_config
#define RFM22_io_port_default
#define RFM22_afc_loop_gearshift_override
int32_t PIOS_DELAY_WaituS(uint32_t uS)
uint16_t(* pios_com_callback)(uintptr_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *task_woken)
Implements an OpenLRS driver for the RFM22B.
#define RFM22_received_packet_length