diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index beb637a0f..3c34e019c 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -37,7 +37,6 @@ #if defined(PCBHORUS) #define MAX_MODELS 60 - #define MAX_RECEIVERS_PER_MODULE 5 #define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32 #define MAX_FLIGHT_MODES 9 #define MAX_MIXERS 64 @@ -51,7 +50,6 @@ #define MAX_CUSTOM_SCREENS 5 #elif defined(PCBTARANIS) #define MAX_MODELS 60 - #define MAX_RECEIVERS_PER_MODULE 2 #define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32 #define MAX_FLIGHT_MODES 9 #define MAX_MIXERS 64 @@ -64,7 +62,6 @@ #define MAX_TELEMETRY_SENSORS 32 #elif defined(PCBSKY9X) #define MAX_MODELS 60 - #define MAX_RECEIVERS_PER_MODULE 2 #define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32 #define MAX_FLIGHT_MODES 9 #define MAX_MIXERS 64 @@ -127,6 +124,14 @@ enum CurveType { #define MAX_CURVE_POINTS 512 #endif +#if defined(PCBHORUS) + #define NUM_RECEIVERS 10 + #define MAX_RECEIVERS_PER_MODULE 5 +#else + #define NUM_RECEIVERS 4 + #define MAX_RECEIVERS_PER_MODULE 4 +#endif + #if defined(PCBTARANIS) || defined(PCBSKY9X) || defined(PCBHORUS) #define NUM_MODULES 2 #else diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 1c74bd98b..2aaf97a6d 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -25,6 +25,7 @@ #include "board.h" #include "dataconstants.h" #include "definitions.h" +#include "bitfield.h" #if defined(PCBTARANIS) #define N_TARANIS_FIELD(x) @@ -415,10 +416,13 @@ PACK(struct TrainerModuleData { */ PACK(struct ReceiverData { - uint8_t enabled:1; + uint8_t used:1; uint8_t telemetry:1; - uint8_t spare:6; - uint64_t channelMapping; // each receiver output (16) can be assigned to one of the 16 channels + uint8_t spare:2; + // 5 bits per receiver output (24) as it can be assigned to one of the 24 channels + uint64_t channelMapping0:60; + uint64_t channelMapping1:64; + char name[8]; }); /* @@ -478,8 +482,24 @@ PACK(struct ModuleData { NOBACKUP(struct { uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W uint8_t external_antenna:1; // false = internal antenna, true = external antenna +#if defined(PCBHORUS) uint8_t spare:5; - ReceiverData receivers[MAX_RECEIVERS_PER_MODULE]; + uint32_t receivers; // max 5 receivers per module and 10 receivers in total (4bits per receiver with 0 = unused) +#else + uint8_t spare:1; + uint16_t receivers:12; // max 4 receivers per module and 4 receivers in total (3bits per receiver with 0 = unused) +#endif + NOBACKUP(inline uint8_t getReceiverSlot(uint8_t receiver) { + return (receivers >> (3 * receiver)) & 0b111; + }) + + NOBACKUP(inline void setReceiverSlot(uint8_t receiver, uint8_t slot) { + receivers = BF_SET(receivers, slot, 3 * receiver, 3); + }) + + NOBACKUP(inline void clearReceiverSlot(uint8_t receiver) { + setReceiverSlot(receiver, 0); + }) } pxx2); }; @@ -490,12 +510,10 @@ PACK(struct ModuleData { return ((uint8_t) (rfProtocol & 0x0f)) + (multi.rfProtocolExtra << 4); }) - NOBACKUP(inline void setMultiProtocol(uint8_t proto) - { + NOBACKUP(inline void setMultiProtocol(uint8_t proto) { rfProtocol = (uint8_t) (proto & 0x0f); multi.rfProtocolExtra = (proto & 0x30) >> 4; }) - }); /* @@ -610,6 +628,7 @@ PACK(struct ModelData { NOBACKUP(uint8_t spare:6); NOBACKUP(uint8_t potsWarnMode:2); ModuleData moduleData[NUM_MODULES]; + ReceiverData receiverData[NUM_RECEIVERS]; int16_t failsafeChannels[MAX_OUTPUT_CHANNELS]; TrainerModuleData trainerData; diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index ee9bdeff2..a5beddc11 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -91,6 +91,14 @@ enum MenuModelSetupItems { ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_PINMAP, ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_TELEM, ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_LABEL, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_PINMAP, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_TELEM, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_4_LABEL, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_4_PINMAP, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_4_TELEM, + ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_4_BIND_SHARE, #endif ITEM_MODEL_EXTERNAL_MODULE_LABEL, ITEM_MODEL_EXTERNAL_MODULE_MODE, @@ -123,6 +131,14 @@ enum MenuModelSetupItems { ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_PINMAP, ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_TELEM, ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_LABEL, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_PINMAP, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_TELEM, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_4_LABEL, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_4_PINMAP, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_4_TELEM, + ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_4_BIND_SHARE, #if defined(PCBSKY9X) && !defined(REVA) ITEM_MODEL_EXTRA_MODULE_LABEL, ITEM_MODEL_EXTRA_MODULE_CHANNELS, @@ -159,11 +175,11 @@ enum MenuModelSetupItems { #define IF_PXX2_MODULE(module, xxx) (isModulePXX2(module) ? (uint8_t)(xxx) : HIDDEN_ROW) #define IF_NOT_PXX2_MODULE(module, xxx) (isModulePXX2(module) ? HIDDEN_ROW : (uint8_t)(xxx)) -#define IF_PXX2_RECEIVER_DISPLAYED(module, idx, xxx) ((isModulePXX2(module) && g_model.moduleData[module].pxx2.receivers[idx].enabled) ? (uint8_t)(xxx) : HIDDEN_ROW) +#define IF_PXX2_RECEIVER_DISPLAYED(module, idx, xxx) ((isModulePXX2(module) && g_model.moduleData[module].pxx2.getReceiverSlot(idx)) ? (uint8_t)(xxx) : HIDDEN_ROW) #if defined(PCBTARANIS) #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE) - #define CURRENT_RECEIVER_EDITED(k) (k >= (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_LABEL : ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_LABEL) ? 1 : 0) + #define CURRENT_RECEIVER_EDITED(k) ((k - (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_LABEL : ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_LABEL)) / 4) #elif defined(PCBSKY9X) && !defined(REVA) #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE) #else @@ -361,6 +377,16 @@ inline bool isDefaultModelRegistrationID() return memcmp(g_model.modelRegistrationID, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID) == 0; } +uint8_t findEmptyReceiverSlot() +{ + for (uint8_t slot=0; slot 0) { - if (receiverIdx == 0) { - memcpy(&g_model.moduleData[moduleIdx].pxx2.receivers[0], &g_model.moduleData[moduleIdx].pxx2.receivers[1], sizeof(ReceiverData)); - } - memclear(&g_model.moduleData[moduleIdx].pxx2.receivers[1], sizeof(ReceiverData)); // we always remove the second receiver data + g_model.moduleData[moduleIdx].pxx2.receivers = (g_model.moduleData[moduleIdx].pxx2.receivers & BF_MASK(0, receiverIdx * 3)) | ((g_model.moduleData[moduleIdx].pxx2.receivers & BF_MASK((receiverIdx + 1) * 3, (MAX_RECEIVERS_PER_MODULE - 1 - receiverIdx) * 3)) >> 3); + memclear(&g_model.receiverData[receiverSlot], sizeof(ReceiverData)); s_editMode = 0; killEvents(event); storageDirty(EE_MODEL); @@ -1217,18 +1263,14 @@ void menuModelSetup(event_t event) else { lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_RXADD_BUTTON, attr); if (attr && s_editMode > 0) { - if (g_model.moduleData[moduleIdx].pxx2.receivers[0].enabled) { - g_model.moduleData[moduleIdx].pxx2.receivers[1].enabled = 0x01; - memcpy(&g_model.moduleData[moduleIdx].pxx2.receivers[1].channelMapping, DEFAULT_CHANNEL_MAPPING, sizeof(uint64_t)); - } - else { - g_model.moduleData[moduleIdx].pxx2.receivers[0].enabled = 0x01; - memcpy(&g_model.moduleData[moduleIdx].pxx2.receivers[0].channelMapping, DEFAULT_CHANNEL_MAPPING, sizeof(uint64_t)); - } - menuVerticalPosition += 3; s_editMode = 0; killEvents(event); - storageDirty(EE_MODEL); + uint8_t slot = findEmptyReceiverSlot(); + if (slot > 0) { + g_model.moduleData[moduleIdx].pxx2.receivers |= slot << (receiverIdx * 3); + g_model.receiverData[receiverSlot - 1].used = 1; + storageDirty(EE_MODEL); + } } } } @@ -1258,7 +1300,7 @@ void menuModelSetup(event_t event) case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_TELEM: { uint8_t receiverIdx = CURRENT_RECEIVER_EDITED(k); - g_model.moduleData[INTERNAL_MODULE].pxx2.receivers[receiverIdx].telemetry = editCheckBox(g_model.moduleData[INTERNAL_MODULE].pxx2.receivers[receiverIdx].telemetry, MODEL_SETUP_2ND_COLUMN, y, INDENT INDENT "Telemetry", attr, event); + // g_model.moduleData[INTERNAL_MODULE].pxx2.receivers[receiverIdx].telemetry = editCheckBox(g_model.moduleData[INTERNAL_MODULE].pxx2.receivers[receiverIdx].telemetry, MODEL_SETUP_2ND_COLUMN, y, INDENT INDENT "Telemetry", attr, event); } break; diff --git a/radio/src/pulses/modules.h b/radio/src/pulses/modules.h index 1d8fd157f..8b07460b6 100644 --- a/radio/src/pulses/modules.h +++ b/radio/src/pulses/modules.h @@ -208,12 +208,12 @@ constexpr int8_t MAX_EXTRA_MODULE_CHANNELS_M8 = 8; // only 16ch PPM inline uint8_t getPinOuput(uint8_t receiverIdx, uint8_t moduleIdx, uint8_t pin) { - return ((g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping >> (pin + ((pin & 0x01) ? -1 : 1 )) * 4) & 0x0F); + // TODO return ((g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping >> (pin + ((pin & 0x01) ? -1 : 1 )) * 4) & 0x0F); } inline void setPinOuput(uint8_t receiverIdx, uint8_t moduleIdx, uint8_t pin, uint8_t chan) { - g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping = BF_SET(g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping, chan, (pin + ((pin & 0x01) ? -1 : 1 )) * 4, 4); + // TODO g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping = BF_SET(g_model.moduleData[moduleIdx].pxx2.receivers[receiverIdx].channelMapping, chan, (pin + ((pin & 0x01) ? -1 : 1 )) * 4, 4); } inline int8_t maxModuleChannels_M8(uint8_t idx)