feat: allow IMU inversion (#7505)
This commit is contained in:
@@ -365,6 +365,7 @@ Node convert<GeneralSettings>::encode(const GeneralSettings& rhs)
|
||||
if (Boards::getCapability(board, Board::HasIMU)) {
|
||||
node["imuMax"] = rhs.imuMax;
|
||||
node["imuOffset"] = rhs.imuOffset;
|
||||
node["imuInvert"] = (rhs.imuInvertX ? 1 : 0) | (rhs.imuInvertY ? 2 : 0);
|
||||
}
|
||||
|
||||
// OneBit sampling (X9D only?)
|
||||
@@ -714,6 +715,10 @@ bool convert<GeneralSettings>::decode(const Node& node, GeneralSettings& rhs)
|
||||
|
||||
node["imuMax"] >> rhs.imuMax;
|
||||
node["imuOffset"] >> rhs.imuOffset;
|
||||
int imuInvert = 0;
|
||||
node["imuInvert"] >> imuInvert;
|
||||
rhs.imuInvertX = imuInvert & 0x1;
|
||||
rhs.imuInvertY = imuInvert & 0x2;
|
||||
|
||||
// OneBit sampling (X9D only?)
|
||||
node["uartSampleMode"] >> rhs.uartSampleMode;
|
||||
|
||||
@@ -384,6 +384,8 @@ class GeneralSettings {
|
||||
char registrationId[REGISTRATION_ID_LEN + 1];
|
||||
int imuMax;
|
||||
int imuOffset;
|
||||
bool imuInvertX;
|
||||
bool imuInvertY;
|
||||
int uartSampleMode;
|
||||
|
||||
int pwrOnSpeed;
|
||||
|
||||
@@ -107,6 +107,25 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
|
||||
addParams();
|
||||
}
|
||||
|
||||
if (Boards::getCapability(board, Board::HasIMU)) {
|
||||
addSection(tr("IMU"));
|
||||
addLabel("");
|
||||
addLabel(tr("Invert"));
|
||||
addParams();
|
||||
|
||||
addLabel(tr("X"));
|
||||
AutoCheckBox *imuInvertX = new AutoCheckBox(this);
|
||||
imuInvertX->setField(generalSettings.imuInvertX, this);
|
||||
params->append(imuInvertX);
|
||||
addParams();
|
||||
|
||||
addLabel(tr("Y"));
|
||||
AutoCheckBox *imuInvertY = new AutoCheckBox(this);
|
||||
imuInvertY->setField(generalSettings.imuInvertY, this);
|
||||
params->append(imuInvertY);
|
||||
addParams();
|
||||
}
|
||||
|
||||
count = Boards::getCapability(board, Board::Inputs);
|
||||
|
||||
if (count > 0) {
|
||||
|
||||
@@ -77,11 +77,15 @@ static inline void check_struct()
|
||||
#endif
|
||||
|
||||
#if defined(PCBXLITES)
|
||||
CHKSIZE(RadioData, 950);
|
||||
CHKSIZE(RadioData, 951);
|
||||
#elif defined(RADIO_ST16) || defined(PCBPA01) || defined(RADIO_TX15) || defined(RADIO_T15PRO) || defined(RADIO_TX16SMK3) || defined(RADIO_T22)
|
||||
CHKSIZE(RadioData, 1181);
|
||||
CHKSIZE(RadioData, 1182);
|
||||
#elif defined(COLORLCD)
|
||||
CHKSIZE(RadioData, 1061);
|
||||
#if defined(IMU)
|
||||
CHKSIZE(RadioData, 1062);
|
||||
#else
|
||||
CHKSIZE(RadioData, 1061);
|
||||
#endif
|
||||
#elif defined(RADIO_GX12)
|
||||
CHKSIZE(RadioData, 1068);
|
||||
#else
|
||||
|
||||
@@ -1128,6 +1128,7 @@ PACK(struct RadioData {
|
||||
#if defined(IMU)
|
||||
NOBACKUP(int8_t imuMax);
|
||||
NOBACKUP(int8_t imuOffset);
|
||||
NOBACKUP(uint8_t imuInvert); // user inversion, default off; XORed with hal.h IMU_INVERT_X/Y at apply time (bit0=X, bit1=Y)
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
|
||||
@@ -25,10 +25,14 @@
|
||||
#include "choice.h"
|
||||
#include "edgetx.h"
|
||||
#include "getset_helpers.h"
|
||||
#if defined(IMU)
|
||||
#include "gyro.h"
|
||||
#endif
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/switch_driver.h"
|
||||
#include "layout.h"
|
||||
#include "static.h"
|
||||
#include "strhelpers.h"
|
||||
#include "switches.h"
|
||||
#include "textedit.h"
|
||||
|
||||
@@ -94,6 +98,25 @@ HWSticks::HWSticks(Window* parent) : Window(parent, {0, 0, LV_PCT(100), LV_SIZE_
|
||||
return std::to_string(value ? 2 << (value - 1) : 0);
|
||||
});
|
||||
#endif
|
||||
|
||||
#if defined(IMU)
|
||||
int imuRow = max_sticks;
|
||||
#if defined(STICK_DEAD_ZONE)
|
||||
imuRow += 1;
|
||||
#endif
|
||||
for (int a = 0; a < 2; a++) {
|
||||
int row = imuRow + a;
|
||||
new StaticText(this, {0, S_Y(row) + yo + PAD_MEDIUM, S_LBL_W, 0},
|
||||
getStringAtIndex(STR_IMU_VSRCRAW, a));
|
||||
new ToggleSwitch(
|
||||
this, {S_INV_X, S_Y(row) + yo, S_INV_W, 0},
|
||||
[=]() -> uint8_t { return (uint8_t)getImuInversion(a); },
|
||||
[=](int8_t newValue) {
|
||||
setImuInversion(a, newValue);
|
||||
SET_DIRTY();
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HWPots::HWPots(Window* parent) :
|
||||
|
||||
@@ -102,6 +102,41 @@ static void gyroFilter(etx_imu_data_t* raw)
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed hardware mounting correction from the target hal.h (X = bit 0, Y = bit 1).
|
||||
// This accounts for how the chip is physically positioned and is always applied.
|
||||
static uint8_t imuHwInvertMask()
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
#if defined(IMU_INVERT_X)
|
||||
mask |= (1 << IMU_AXIS_X);
|
||||
#endif
|
||||
#if defined(IMU_INVERT_Y)
|
||||
mask |= (1 << IMU_AXIS_Y);
|
||||
#endif
|
||||
return mask;
|
||||
}
|
||||
|
||||
// User-selectable inversion, stored verbatim and defaulting to off.
|
||||
bool getImuInversion(uint8_t axis)
|
||||
{
|
||||
return (g_eeGeneral.imuInvert >> axis) & 1;
|
||||
}
|
||||
|
||||
void setImuInversion(uint8_t axis, bool value)
|
||||
{
|
||||
if (value)
|
||||
g_eeGeneral.imuInvert |= (1 << axis);
|
||||
else
|
||||
g_eeGeneral.imuInvert &= ~(1 << axis);
|
||||
}
|
||||
|
||||
// Effective inversion applied to sensor data: hardware correction XOR user choice.
|
||||
static bool imuAxisInverted(uint8_t axis)
|
||||
{
|
||||
uint8_t effective = g_eeGeneral.imuInvert ^ imuHwInvertMask();
|
||||
return (effective >> axis) & 1;
|
||||
}
|
||||
|
||||
void gyroStart(imu_read_fn fn)
|
||||
{
|
||||
readFn = fn;
|
||||
@@ -126,6 +161,15 @@ void gyroWakeup()
|
||||
|
||||
errors = 0;
|
||||
|
||||
if (imuAxisInverted(IMU_AXIS_X)) {
|
||||
raw.accel_x = -raw.accel_x;
|
||||
raw.gyro_x = -raw.gyro_x;
|
||||
}
|
||||
if (imuAxisInverted(IMU_AXIS_Y)) {
|
||||
raw.accel_y = -raw.accel_y;
|
||||
raw.gyro_y = -raw.gyro_y;
|
||||
}
|
||||
|
||||
gyroFilter(&raw);
|
||||
|
||||
raw_ax = (int16_t)filteredAccel[0];
|
||||
|
||||
@@ -29,6 +29,15 @@
|
||||
#define IMU_OFFSET_MIN -30
|
||||
#define IMU_OFFSET_MAX 10
|
||||
|
||||
#define IMU_AXIS_X 0
|
||||
#define IMU_AXIS_Y 1
|
||||
|
||||
// User-selectable IMU axis inversion, stored verbatim and defaulting to off.
|
||||
// The fixed hardware mounting correction (IMU_INVERT_X/Y in the target hal.h) is
|
||||
// applied on top of this internally, so the user setting is independent of it.
|
||||
bool getImuInversion(uint8_t axis);
|
||||
void setImuInversion(uint8_t axis, bool value);
|
||||
|
||||
void gyroStart(imu_read_fn fn);
|
||||
void gyroWakeup();
|
||||
void gyroSetIMU_X(int16_t offset, int16_t range);
|
||||
|
||||
@@ -435,6 +435,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -458,6 +458,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "stickDeadZone", 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -458,6 +458,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "stickDeadZone", 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -443,6 +443,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -458,6 +458,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "stickDeadZone", 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -458,6 +458,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -458,6 +458,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "stickDeadZone", 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -459,6 +459,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -434,6 +434,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_STRING("selectedTheme", 26),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
|
||||
@@ -372,6 +372,7 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "imuMax", 8 ),
|
||||
YAML_SIGNED( "imuOffset", 8 ),
|
||||
YAML_UNSIGNED( "imuInvert", 8 ),
|
||||
YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ),
|
||||
YAML_SIGNED( "radioGFDisabled", 1 ),
|
||||
YAML_SIGNED( "radioTrainerDisabled", 1 ),
|
||||
|
||||
@@ -402,6 +402,8 @@ SAI1_Block_A: PDM_CLOCK (1 MHz bit-clock output on SAI1_CK1 / PE5, !FLYSKY_GIMBA
|
||||
// IMU
|
||||
#define IMU_I2C_BUS I2C_Bus_1
|
||||
#define IMU_INT_GPIO GPIO_PIN(GPIOG, 13) // PG.13
|
||||
#define IMU_INVERT_X // X axis mounted reversed (default, user-overridable)
|
||||
#define IMU_INVERT_Y // Y axis mounted reversed (default, user-overridable)
|
||||
|
||||
// IMU_INT_EXTI IRQ
|
||||
#if !defined(USE_EXTI15_10_IRQ)
|
||||
|
||||
@@ -601,6 +601,8 @@ USART6: INTMODULE_USART
|
||||
|
||||
#define IMU_I2C_BUS I2C_Bus_2
|
||||
#define IMU_INT_GPIO GPIO_PIN(GPIOG, 13) // PG.13
|
||||
#define IMU_INVERT_X // X axis mounted reversed (default, user-overridable)
|
||||
#define IMU_INVERT_Y // Y axis mounted reversed (default, user-overridable)
|
||||
#if !defined(USE_EXTI15_10_IRQ)
|
||||
#define USE_EXTI15_10_IRQ
|
||||
#define EXTI15_10_IRQ_Priority 6
|
||||
|
||||
Reference in New Issue
Block a user