Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions radio/src/datastructs_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,10 @@ PACK(struct ModuleData {
rx_freq[1] = value >> 8;
}
} afhds3));
NOBACKUP(struct {
uint8_t raw12bits:1;
uint8_t spare1:7 SKIP;
} ghost);
} NAME(mod) FUNC(select_mod_type);

// Helper functions to set both of the rfProto protocol at the same time
Expand Down
4 changes: 4 additions & 0 deletions radio/src/gui/128x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1651,6 +1651,10 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE);
putsVolts(lcdLastRightPos, y, getBatteryVoltage(), attr | PREC2 | LEFT);
}
else if (isModuleGhost(moduleIdx)) {
auto & module = g_model.moduleData[moduleIdx];
module.ghost.raw12bits = editCheckBox(module.ghost.raw12bits , MODEL_SETUP_2ND_COLUMN, y, INDENT "Raw 12 bits", attr, event);
}
break;
}

Expand Down
4 changes: 4 additions & 0 deletions radio/src/gui/212x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,10 @@ void menuModelSetup(event_t event)
lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE);
putsVolts(lcdLastRightPos, y, getBatteryVoltage(), attr | PREC2 | LEFT);
}
else if (isModuleGhost(moduleIdx)) {
auto & module = g_model.moduleData[moduleIdx];
module.ghost.raw12bits = editCheckBox(module.ghost.raw12bits , MODEL_SETUP_2ND_COLUMN, y, INDENT "Raw 12 bits", attr, event);
}
}
break;

Expand Down
5 changes: 5 additions & 0 deletions radio/src/gui/colorlcd/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,11 @@ class ModuleWindow : public FormGroup {
grid.nextLine();
}

if (isModuleGhost(moduleIdx)) {
new StaticText(this, grid.getLabelSlot(true), "Raw 12 bits", 0, COLOR_THEME_PRIMARY1);
new CheckBox(this, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.moduleData[moduleIdx].ghost.raw12bits));
}

auto par = getParent();
par->moveWindowsTop(top() + 1, adjustHeight());
par->adjustInnerHeight();
Expand Down
2 changes: 2 additions & 0 deletions radio/src/gui/gui_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
return TITLE_ROW;
if(isModuleAFHDS3(moduleIdx))
return HIDDEN_ROW;
if(isModuleGhost(moduleIdx))
return 0;
return MULTIMODULE_OPTIONS_ROW(moduleIdx);
}

Expand Down
96 changes: 53 additions & 43 deletions radio/src/pulses/ghost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,73 @@
uint8_t createGhostMenuControlFrame(uint8_t * frame, int16_t * pulses)
{
uint8_t * buf = frame;
#if SPORT_MAX_BAUDRATE < 400000
*buf++ = g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_400K ? GHST_ADDR_MODULE_SYM : GHST_ADDR_MODULE_ASYM;
#else
*buf++ = GHST_ADDR_MODULE_SYM;
#endif

*buf++ = GHST_UL_RC_CHANS_SIZE;
uint8_t * crc_start = buf;
*buf++ = GHST_UL_MENU_CTRL;
*buf++ = getGhostModuleAddr(); // addr
*buf++ = GHST_UL_RC_CHANS_SIZE; // length
const uint8_t * crc_start = buf;
*buf++ = GHST_UL_MENU_CTRL; // type

// payload
*buf++ = reusableBuffer.ghostMenu.buttonAction; // Joystick states, Up, Down, Left, Right, Press
*buf++ = reusableBuffer.ghostMenu.menuAction; // menu control, open, close, etc.

for (uint8_t i = 0; i < 8; i++)
for (uint8_t i = 0; i < 8; i++) {
*buf++ = 0; // padding to make this the same size as the pulses packet
}

// crc
*buf++ = crc8(crc_start, GHST_UL_RC_CHANS_SIZE - 1);

return buf - frame;
}

// Range for pulses (channels output) is [-1024:+1024]
uint8_t createGhostChannelsFrame(uint8_t * frame, int16_t * pulses)
uint8_t createGhostChannelsFrame(uint8_t * frame, int16_t * pulses, bool raw12bits)
{
static uint8_t lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8;
static uint8_t lastGhostFrameId = 0;
uint8_t ghostUpper4Offset = 0;

switch (lastGhostFrameId) {
case GHST_UL_RC_CHANS_HS4_5TO8:
ghostUpper4Offset = 0;
break;
case GHST_UL_RC_CHANS_HS4_9TO12:
case GHST_UL_RC_CHANS_HS4_12_5TO8:
lastGhostFrameId = raw12bits ? GHST_UL_RC_CHANS_HS4_12_9TO12 : GHST_UL_RC_CHANS_HS4_9TO12;
ghostUpper4Offset = 4;
break;

case GHST_UL_RC_CHANS_HS4_9TO12:
case GHST_UL_RC_CHANS_HS4_12_9TO12:
lastGhostFrameId = raw12bits ? GHST_UL_RC_CHANS_HS4_12_13TO16 : GHST_UL_RC_CHANS_HS4_13TO16;
ghostUpper4Offset = 8;
break;

case GHST_UL_RC_CHANS_HS4_13TO16:
ghostUpper4Offset = 8;
case GHST_UL_RC_CHANS_HS4_12_13TO16:
lastGhostFrameId = raw12bits ? GHST_UL_RC_CHANS_HS4_12_5TO8 : GHST_UL_RC_CHANS_HS4_5TO8;
ghostUpper4Offset = 0;
break;

default: // We don't have known previous state so init
lastGhostFrameId = raw12bits ? GHST_UL_RC_CHANS_HS4_12_5TO8 : GHST_UL_RC_CHANS_HS4_5TO8;
ghostUpper4Offset = 0;
break;
}

uint8_t * buf = frame;
#if SPORT_MAX_BAUDRATE < 400000
*buf++ = g_eeGeneral.telemetryBaudrate == GHST_TELEMETRY_RATE_400K ? GHST_ADDR_MODULE_SYM : GHST_ADDR_MODULE_ASYM;
#else
*buf++ = GHST_ADDR_MODULE_SYM;
#endif
*buf++ = GHST_UL_RC_CHANS_SIZE;
*buf++ = getGhostModuleAddr(); // addr
*buf++ = GHST_UL_RC_CHANS_SIZE; // len
uint8_t * crc_start = buf;
*buf++ = lastGhostFrameId;
*buf++ = lastGhostFrameId; // type

// payload
// first 4 high speed, 12 bit channels (11 relevant bits with openTx)
uint32_t bits = 0;
uint8_t bitsavailable = 0;
for (int i = 0; i < 4; i++) {
uint32_t value = limit(0, GHST_RC_CTR_VAL_12BIT + (((pulses[i] + 2 * PPM_CH_CENTER(i) - 2 * PPM_CENTER) << 3) / 5), 2 * GHST_RC_CTR_VAL_12BIT);
uint32_t value;
if(raw12bits) {
value = limit(0, (1024 + (pulses[i] + 2 * PPM_CH_CENTER(i) - 2 * PPM_CENTER)) << 1, 0xFFF);
} else {
value = limit(0, GHST_RC_CTR_VAL_12BIT + (((pulses[i] + 2 * PPM_CH_CENTER(i) - 2 * PPM_CENTER) << 3) / 5), 2 * GHST_RC_CTR_VAL_12BIT);
}
bits |= value << bitsavailable;
bitsavailable += GHST_CH_BITS_12;
while (bitsavailable >= 8) {
Expand All @@ -89,35 +103,31 @@ uint8_t createGhostChannelsFrame(uint8_t * frame, int16_t * pulses)
// second 4 lower speed, 8 bit channels
for (int i = 4; i < 8; ++i) {
uint8_t channelIndex = i + ghostUpper4Offset;
*buf++ = limit(0, GHST_RC_CTR_VAL_8BIT + (((pulses[channelIndex] + 2 * PPM_CH_CENTER(channelIndex) - 2 * PPM_CENTER) >> 1) / 5), 2 * GHST_RC_CTR_VAL_8BIT);
uint8_t value;
if(raw12bits) {
value = limit(0, 128 + ((pulses[channelIndex] + 2 * PPM_CH_CENTER(channelIndex) - 2 * PPM_CENTER) >> 3), 0xFF);
} else {
value = limit(0, GHST_RC_CTR_VAL_8BIT + (((pulses[channelIndex] + 2 * PPM_CH_CENTER(channelIndex) - 2 * PPM_CENTER) >> 1) / 5), 2 * GHST_RC_CTR_VAL_8BIT);
}
*buf++ = value;
}

// crc
*buf++ = crc8(crc_start, GHST_UL_RC_CHANS_SIZE - 1);

switch (lastGhostFrameId) {
case GHST_UL_RC_CHANS_HS4_5TO8:
lastGhostFrameId = GHST_UL_RC_CHANS_HS4_9TO12;
break;
case GHST_UL_RC_CHANS_HS4_9TO12:
lastGhostFrameId = GHST_UL_RC_CHANS_HS4_13TO16;
break;
case GHST_UL_RC_CHANS_HS4_13TO16:
lastGhostFrameId = GHST_UL_RC_CHANS_HS4_5TO8;
break;
}

return buf - frame;
}

void setupPulsesGhost()
{
if (telemetryProtocol == PROTOCOL_TELEMETRY_GHOST) {
uint8_t * pulses = extmodulePulsesData.ghost.pulses;
if (moduleState[EXTERNAL_MODULE].counter == GHST_MENU_CONTROL)
extmodulePulsesData.ghost.length = createGhostMenuControlFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]);
else
extmodulePulsesData.ghost.length = createGhostChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]);

auto & module = g_model.moduleData[EXTERNAL_MODULE];
if (moduleState[EXTERNAL_MODULE].counter == GHST_MENU_CONTROL) {
extmodulePulsesData.ghost.length = createGhostMenuControlFrame(pulses, &channelOutputs[module.channelsStart]);
} else {
extmodulePulsesData.ghost.length = createGhostChannelsFrame(pulses, &channelOutputs[module.channelsStart], module.ghost.raw12bits);
}
moduleState[EXTERNAL_MODULE].counter = GHST_FRAME_CHANNEL;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ bool w_zov_color(void* user, uint8_t* data, uint32_t bitoffs,
}
#endif

uint8_t select_mod_type(void* user, uint8_t* data, uint32_t bitoffs)
static uint8_t select_mod_type(void* user, uint8_t* data, uint32_t bitoffs)
{
data += bitoffs >> 3UL;
data -= offsetof(ModuleData, ppm);
Expand Down
34 changes: 32 additions & 2 deletions radio/src/storage/yaml/yaml_datastructs_funcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ namespace yaml_conv_220 {
bool w_vbat_max(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque);

uint8_t select_zov(void* user, uint8_t* data, uint32_t bitoffs);
uint8_t select_mod_type(void* user, uint8_t* data, uint32_t bitoffs);
uint8_t select_script_input(void* user, uint8_t* data, uint32_t bitoffs);
uint8_t select_id1(void* user, uint8_t* data, uint32_t bitoffs);
uint8_t select_id2(void* user, uint8_t* data, uint32_t bitoffs);
Expand Down Expand Up @@ -433,7 +432,38 @@ bool w_zov_color(void* user, uint8_t* data, uint32_t bitoffs,

static uint8_t select_mod_type(void* user, uint8_t* data, uint32_t bitoffs)
{
return yaml_conv_220::select_mod_type(user, data, bitoffs);
data += bitoffs >> 3UL;
data -= offsetof(ModuleData, ppm);

ModuleData* mod_data = reinterpret_cast<ModuleData*>(data);
switch (mod_data->type) {
case MODULE_TYPE_NONE:
case MODULE_TYPE_PPM:
case MODULE_TYPE_DSM2:
case MODULE_TYPE_CROSSFIRE:
return 1;
case MODULE_TYPE_MULTIMODULE:
return 2;
case MODULE_TYPE_XJT_PXX1:
case MODULE_TYPE_R9M_PXX1:
case MODULE_TYPE_R9M_LITE_PXX1:
return 3;
case MODULE_TYPE_SBUS:
return 4;
case MODULE_TYPE_ISRM_PXX2:
case MODULE_TYPE_R9M_PXX2:
case MODULE_TYPE_R9M_LITE_PXX2:
case MODULE_TYPE_R9M_LITE_PRO_PXX2:
case MODULE_TYPE_XJT_LITE_PXX2:
return 5;
case MODULE_TYPE_FLYSKY:
if (mod_data->subType == FLYSKY_SUBTYPE_AFHDS2A) return 6;
if (mod_data->subType == FLYSKY_SUBTYPE_AFHDS3) return 7;
break;
case MODULE_TYPE_GHOST:
return 8;
}
return 0;
}

static uint8_t select_script_input(void* user, uint8_t* data, uint32_t bitoffs)
Expand Down
42 changes: 24 additions & 18 deletions radio/src/storage/yaml/yaml_datastructs_nv14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,11 @@ static const struct YamlNode struct_anonymous_11[] = {
YAML_UNSIGNED( "reserved", 6 ),
YAML_END
};
static const struct YamlNode struct_anonymous_12[] = {
YAML_UNSIGNED( "raw12bits", 1 ),
YAML_PADDING( 7 ),
YAML_END
};
static const struct YamlNode union_anonymous_4_elmts[] = {
YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL),
YAML_STRUCT("ppm", 16, struct_anonymous_5, NULL),
Expand All @@ -673,6 +678,7 @@ static const struct YamlNode union_anonymous_4_elmts[] = {
YAML_STRUCT("pxx2", 200, struct_anonymous_9, NULL),
YAML_STRUCT("flysky", 56, struct_anonymous_10, NULL),
YAML_STRUCT("afhds3", 64, struct_anonymous_11, NULL),
YAML_STRUCT("ghost", 8, struct_anonymous_12, NULL),
YAML_END
};
static const struct YamlNode struct_ModuleData[] = {
Expand Down Expand Up @@ -720,61 +726,61 @@ static const struct YamlNode struct_string_32[] = {
YAML_STRING("val", 4),
YAML_END
};
static const struct YamlNode union_anonymous_12_elmts[] = {
static const struct YamlNode union_anonymous_13_elmts[] = {
YAML_UNSIGNED( "id", 16 ),
YAML_UNSIGNED( "persistentValue", 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_14[] = {
static const struct YamlNode struct_anonymous_15[] = {
YAML_UNSIGNED( "physID", 5 ),
YAML_UNSIGNED( "rxIndex", 3 ),
YAML_END
};
static const struct YamlNode union_anonymous_13_elmts[] = {
YAML_STRUCT("frskyInstance", 8, struct_anonymous_14, NULL),
static const struct YamlNode union_anonymous_14_elmts[] = {
YAML_STRUCT("frskyInstance", 8, struct_anonymous_15, NULL),
YAML_UNSIGNED( "instance", 8 ),
YAML_ENUM("formula", 8, enum_TelemetrySensorFormula),
YAML_END
};
static const struct YamlNode struct_anonymous_16[] = {
static const struct YamlNode struct_anonymous_17[] = {
YAML_UNSIGNED( "ratio", 16 ),
YAML_SIGNED( "offset", 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_17[] = {
static const struct YamlNode struct_anonymous_18[] = {
YAML_UNSIGNED( "source", 8 ),
YAML_UNSIGNED( "index", 8 ),
YAML_PADDING( 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_18[] = {
static const struct YamlNode struct_anonymous_19[] = {
YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL),
YAML_END
};
static const struct YamlNode struct_anonymous_19[] = {
static const struct YamlNode struct_anonymous_20[] = {
YAML_UNSIGNED( "source", 8 ),
YAML_PADDING( 24 ),
YAML_END
};
static const struct YamlNode struct_anonymous_20[] = {
static const struct YamlNode struct_anonymous_21[] = {
YAML_UNSIGNED( "gps", 8 ),
YAML_UNSIGNED( "alt", 8 ),
YAML_PADDING( 16 ),
YAML_END
};
static const struct YamlNode union_anonymous_15_elmts[] = {
YAML_STRUCT("custom", 32, struct_anonymous_16, NULL),
YAML_STRUCT("cell", 32, struct_anonymous_17, NULL),
YAML_STRUCT("calc", 32, struct_anonymous_18, NULL),
YAML_STRUCT("consumption", 32, struct_anonymous_19, NULL),
YAML_STRUCT("dist", 32, struct_anonymous_20, NULL),
static const struct YamlNode union_anonymous_16_elmts[] = {
YAML_STRUCT("custom", 32, struct_anonymous_17, NULL),
YAML_STRUCT("cell", 32, struct_anonymous_18, NULL),
YAML_STRUCT("calc", 32, struct_anonymous_19, NULL),
YAML_STRUCT("consumption", 32, struct_anonymous_20, NULL),
YAML_STRUCT("dist", 32, struct_anonymous_21, NULL),
YAML_UNSIGNED( "param", 32 ),
YAML_END
};
static const struct YamlNode struct_TelemetrySensor[] = {
YAML_IDX,
YAML_UNION("id1", 16, union_anonymous_12_elmts, select_id1),
YAML_UNION("id2", 8, union_anonymous_13_elmts, select_id2),
YAML_UNION("id1", 16, union_anonymous_13_elmts, select_id1),
YAML_UNION("id2", 8, union_anonymous_14_elmts, select_id2),
YAML_STRING("label", 4),
YAML_UNSIGNED( "subId", 8 ),
YAML_ENUM("type", 1, enum_TelemetrySensorType),
Expand All @@ -787,7 +793,7 @@ static const struct YamlNode struct_TelemetrySensor[] = {
YAML_UNSIGNED( "persistent", 1 ),
YAML_UNSIGNED( "onlyPositive", 1 ),
YAML_PADDING( 1 ),
YAML_UNION("cfg", 32, union_anonymous_15_elmts, select_sensor_cfg),
YAML_UNION("cfg", 32, union_anonymous_16_elmts, select_sensor_cfg),
YAML_END
};
static const struct YamlNode struct_WidgetPersistentData[] = {
Expand Down
Loading