feat: Add support for SpaceMouse mod (6D input knob) (#1853)

Use `-DSPACEMOUSE=YES` CMake option to activate on Horus color targets.
Co-authored-by: Niel Horne (elecpower), Raphael Coeffic (raphaelcoeffic) and Peter Feerick (pfeerick).
This commit is contained in:
Risto
2022-09-18 09:23:48 +02:00
committed by GitHub
co-authored by Niel Horne (elecpower), Raphael Coeffic (raphaelcoeffic) and Peter Feerick (pfeerick).
parent 3765e678b9
commit 9dc4065525
42 changed files with 491 additions and 47 deletions
+1
View File
@@ -48,6 +48,7 @@
#define CPN_MAX_SENSORS 60
#define CPN_MAX_SCRIPTS 9
#define CPN_MAX_SCRIPT_INPUTS 10
#define CPN_MAX_SPACEMOUSE 6
#define CPN_STR_APP_NAME QCoreApplication::translate("Companion", "EdgeTX Companion")
#define CPN_STR_TTL_INFO QCoreApplication::translate("Companion", "Information") // shared Title Case words, eg. for a window title or section heading
@@ -112,6 +112,7 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_SPACEMOUSE, RawSource::SourcesGroup, CPN_MAX_SPACEMOUSE);
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches));
addItems(SOURCE_TYPE_FUNCTIONSWITCH, RawSource::SwitchesGroup, board->getCapability(Board::FunctionSwitches));
@@ -83,6 +83,7 @@ const YamlLookupTable uartModeLut = {
{ GeneralSettings::AUX_SERIAL_CLI, "CLI" },
{ GeneralSettings::AUX_SERIAL_GPS, "GPS" },
{ GeneralSettings::AUX_SERIAL_DEBUG, "DEBUG" },
{ GeneralSettings::AUX_SERIAL_SPACEMOUSE, "SPACEMOUSE" },
};
const YamlLookupTable antennaModeLut = {
@@ -21,6 +21,16 @@
#include "yaml_rawsource.h"
#include "eeprominterface.h"
static const YamlLookupTable spacemouseLut = {
{ 0, "SPACEMOUSE_A" },
{ 1, "SPACEMOUSE_B" },
{ 2, "SPACEMOUSE_C" },
{ 3, "SPACEMOUSE_D" },
{ 4, "SPACEMOUSE_E" },
{ 5, "SPACEMOUSE_F" },
};
std::string YamlRawSourceEncode(const RawSource& rhs)
{
std::string src_str;
@@ -97,6 +107,11 @@ std::string YamlRawSourceEncode(const RawSource& rhs)
src_str += std::to_string(rhs.index / 3);
src_str += ")";
break;
case SOURCE_TYPE_SPACEMOUSE:
src_str = "SPACEMOUSE_";
c += rhs.index;
src_str += c;
break;
default:
src_str = "NONE";
break;
@@ -165,7 +180,7 @@ RawSource YamlRawSourceDecode(const std::string& src_str)
val[0] == 'f' &&
val[1] == 's' &&
val[2] == '(') {
std::stringstream src(src_str.substr(3));
int fs = 0;
src >> fs;
@@ -259,6 +274,15 @@ RawSource YamlRawSourceDecode(const std::string& src_str)
rhs.index = sp_idx;
}
if (node.IsScalar() && node.as<std::string>().size() == 12 && node.as<std::string>().substr(0, 11) == "SPACEMOUSE_") {
int sm_idx;
node >> spacemouseLut >> sm_idx;
if (sm_idx >= 0) {
rhs.type = SOURCE_TYPE_SPACEMOUSE;
rhs.index = sm_idx;
}
}
if (node.IsScalar() && node.as<std::string>() == "MAX") {
rhs.type = SOURCE_TYPE_MAX;
rhs.index = 0;
+5 -2
View File
@@ -501,6 +501,8 @@ QString GeneralSettings::serialModeToString(int value)
return tr("GPS");
case AUX_SERIAL_DEBUG:
return tr("Debug");
case AUX_SERIAL_SPACEMOUSE:
return tr("SpaceMouse");
default:
return CPN_STR_UNKNOWN_ITEM;
}
@@ -576,8 +578,9 @@ AbstractStaticItemModel * GeneralSettings::serialModeItemModel(int port_nr)
if (port_nr == SP_VCP &&
(i == AUX_SERIAL_TELE_IN ||
i == AUX_SERIAL_SBUS_TRAINER ||
i == AUX_SERIAL_GPS)) {
// These 3 are disabled on VCP
i == AUX_SERIAL_GPS ||
i == AUX_SERIAL_SPACEMOUSE)) {
// These are disabled on VCP
continue;
}
mdl->appendToItemList(serialModeToString(i), i);
@@ -141,6 +141,7 @@ class GeneralSettings {
AUX_SERIAL_CLI,
AUX_SERIAL_GPS,
AUX_SERIAL_DEBUG,
AUX_SERIAL_SPACEMOUSE,
AUX_SERIAL_COUNT
};
+9
View File
@@ -248,6 +248,9 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
else
return GVarData().nameToString(index);
case SOURCE_TYPE_SPACEMOUSE:
return tr("sm%1").arg(QChar('A' + index));
default:
return QString(CPN_STR_UNKNOWN_ITEM);
}
@@ -352,6 +355,12 @@ bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings
if (type == SOURCE_TYPE_TRIM && index >= b.getCapability(Board::NumTrims))
return false;
if (type == SOURCE_TYPE_SPACEMOUSE &&
(index >= CPN_MAX_SPACEMOUSE ||
(!(gs->serialPort[GeneralSettings::SP_AUX1] == GeneralSettings::AUX_SERIAL_SPACEMOUSE ||
gs->serialPort[GeneralSettings::SP_AUX2] == GeneralSettings::AUX_SERIAL_SPACEMOUSE))))
return false;
return true;
}
+1
View File
@@ -177,6 +177,7 @@ enum RawSourceType {
SOURCE_TYPE_GVAR,
SOURCE_TYPE_SPECIAL,
SOURCE_TYPE_TELEMETRY,
SOURCE_TYPE_SPACEMOUSE,
MAX_SOURCE_TYPE
};
+24
View File
@@ -1472,6 +1472,27 @@ int cliGps(const char ** argv)
}
#endif
#if defined(SPACEMOUSE)
int cliSpaceMouse(const char ** argv)
{
#if defined(DEBUG)
if (!strcmp(argv[1], "trace")) {
spacemouseTraceEnabled = !spacemouseTraceEnabled;
} else
#endif
if (!strcmp(argv[1], "poll")) {
spacemousePoll();
} else if (!strcmp(argv[1], "tare")) {
spacemouseTare();
} else if (!strcmp(argv[1], "startstreaming")) {
spacemouseStartStreaming();
} else if (!strcmp(argv[1], "stopstreaming")) {
spacemouseStopStreaming();
}
return 0;
}
#endif
#if defined(BLUETOOTH)
int cliBlueTooth(const char ** argv)
{
@@ -1579,6 +1600,9 @@ const CliCommand cliCommands[] = {
#if defined(INTERNAL_GPS)
{ "gps", cliGps, "<baudrate>|$<command>|trace" },
#endif
#if defined(SPACEMOUSE)
{ "spacemouse", cliSpaceMouse, "poll | tare | startstreaming | stopstreaming | trace" },
#endif
#if defined(BLUETOOTH)
{ "bt", cliBlueTooth, "<baudrate>|<command>" },
#endif
+12
View File
@@ -237,6 +237,7 @@ enum UartModes {
UART_MODE_CLI,
UART_MODE_GPS,
UART_MODE_DEBUG,
UART_MODE_SPACEMOUSE,
UART_MODE_COUNT SKIP,
UART_MODE_MAX SKIP = UART_MODE_COUNT-1
};
@@ -652,6 +653,17 @@ enum MixSources {
MIXSRC_TILT_Y, LUA_EXPORT("tilty", "Tilt Y")
#endif
#if defined(PCBHORUS)
MIXSRC_FIRST_SPACEMOUSE SKIP,
MIXSRC_SPACEMOUSE_A = MIXSRC_FIRST_SPACEMOUSE, LUA_EXPORT("sma", "SpaceMouse A")
MIXSRC_SPACEMOUSE_B, LUA_EXPORT("smb", "SpaceMouse B")
MIXSRC_SPACEMOUSE_C, LUA_EXPORT("smc", "SpaceMouse C")
MIXSRC_SPACEMOUSE_D, LUA_EXPORT("smd", "SpaceMouse D")
MIXSRC_SPACEMOUSE_E, LUA_EXPORT("sme", "SpaceMouse E")
MIXSRC_SPACEMOUSE_F, LUA_EXPORT("smf", "SpaceMouse F")
MIXSRC_LAST_SPACEMOUSE SKIP = MIXSRC_SPACEMOUSE_F,
#endif
MIXSRC_MAX, LUA_EXPORT("max", "MAX")
MIXSRC_FIRST_HELI SKIP,
+27 -27
View File
@@ -207,37 +207,37 @@ void DebugTimer::stop()
DebugTimer debugTimers[DEBUG_TIMERS_COUNT];
const char * const debugTimerNames[DEBUG_TIMERS_COUNT] = {
"Pulses int." // debugTimerIntPulses,
,"Pulses dur." // debugTimerIntPulsesDuration,
,"10ms dur. " // debugTimerPer10ms,
,"10ms period" // debugTimerPer10msPeriod,
,"Rotary enc." // debugTimerRotEnc,
,"Haptic " // debugTimerHaptic,
,"Mixer calc " // debugTimerMixer,
,"Tel. wakeup" // debugTimerTelemetryWakeup,
,"perMain dur" // debugTimerPerMain,
," perMain s1" // debugTimerPerMain1,
," guiMain " // debugTimerGuiMain,
," LUA " // debugTimerLua,
," LCD wait " // debugTimerLcdRefreshWait,
," LCD refr." // debugTimerLcdRefresh,
," Menus " // debugTimerMenus,
," Menu hnd" // debugTimerMenuHandlers,
,"Menu Vers. " // debugTimerVersion,
,"Menu simple" // debugTimerSimpleMenu,
,"Menu drawte" // debugTimerDrawText,
,"Menu drawt1" // debugTimerDrawText1,
,"Mix ADC " // debugTimerGetAdc,
,"Mix getsw " // debugTimerGetSwitches,
,"Mix eval " // debugTimerEvalMixes,
,"Mix 10ms " // debugTimerMixes10ms,
,"ADC read " // debugTimerAdcRead,
"Pulses int." // debugTimerIntPulses
,"Pulses dur." // debugTimerIntPulsesDuration
,"10ms dur. " // debugTimerPer10ms
,"10ms period" // debugTimerPer10msPeriod
,"Rotary enc." // debugTimerRotEnc
,"Haptic " // debugTimerHaptic
,"Mixer calc " // debugTimerMixer
,"Tel. wakeup" // debugTimerTelemetryWakeup
,"perMain dur" // debugTimerPerMain
," perMain s1" // debugTimerPerMain1
," guiMain " // debugTimerGuiMain
," LUA " // debugTimerLua
," LCD wait " // debugTimerLcdRefreshWait
," LCD refr." // debugTimerLcdRefresh
," Menus " // debugTimerMenus
," Menu hnd" // debugTimerMenuHandlers
,"Menu Vers. " // debugTimerVersion
,"Menu simple" // debugTimerSimpleMenu
,"Menu drawte" // debugTimerDrawText
,"Menu drawt1" // debugTimerDrawText1
,"Mix ADC " // debugTimerGetAdc
,"Mix getsw " // debugTimerGetSwitches
,"Mix eval " // debugTimerEvalMixes
,"Mix 10ms " // debugTimerMixes10ms
,"ADC read " // debugTimerAdcRead
,"mix-pulses " // debugTimerMixerCalcToUsage
,"mix-int. " // debugTimerMixerIterval
,"Audio int. " // debugTimerAudioIterval
,"Audio dur. " // debugTimerAudioDuration
," A. consume" // debugTimerAudioConsume,
," A. consume" // debugTimerAudioConsume
,"SpaceMouse " // debugTimerSpaceMouseWakeup
};
#endif
+4
View File
@@ -391,6 +391,10 @@ enum DebugTimers {
debugTimerAudioConsume,
debugTimerYamlScan,
#if defined(SPACEMOUSE)
debugTimerSpacemouseWakeup,
#endif
DEBUG_TIMERS_COUNT
};
+18
View File
@@ -195,6 +195,15 @@ bool isSourceAvailable(int source)
return false;
#endif
#if defined(PCBHORUS) && !defined(SPACEMOUSE)
if (source >= MIXSRC_FIRST_SPACEMOUSE && source <= MIXSRC_LAST_SPACEMOUSE)
return false;
#elif defined(PCBHORUS) && defined(SPACEMOUSE)
if ((hasSerialMode(UART_MODE_SPACEMOUSE) == -1) &&
(source >= MIXSRC_FIRST_SPACEMOUSE && source <= MIXSRC_LAST_SPACEMOUSE))
return false;
#endif
if (source >= MIXSRC_FIRST_SWITCH && source <= MIXSRC_LAST_SWITCH) {
return SWITCH_EXISTS(source - MIXSRC_FIRST_SWITCH);
}
@@ -410,6 +419,15 @@ bool isSerialModeAvailable(uint8_t port_nr, int mode)
return false;
#endif
#if !defined(SPACEMOUSE)
if (mode == UART_MODE_SPACEMOUSE)
return false;
#elif defined(USB_SERIAL)
// SPACEMOUSE is not supported on VCP
if (port_nr == SP_VCP && mode == UART_MODE_SPACEMOUSE)
return false;
#endif
#if !defined(LUA)
if (mode == UART_MODE_LUA)
return false;
+6
View File
@@ -330,6 +330,12 @@ getvalue_t getValue(mixsrc_t i)
}
#endif
#if defined(SPACEMOUSE)
else if (i >= MIXSRC_FIRST_SPACEMOUSE && i <= MIXSRC_LAST_SPACEMOUSE) {
return get_spacemouse_value(i - MIXSRC_FIRST_SPACEMOUSE);
}
#endif
else if (i == MIXSRC_MAX) {
return 1024;
}
+5
View File
@@ -547,6 +547,11 @@ bool inputsMoved()
sum += getValue(MIXSRC_TILT_X+i) >> INAC_STICKS_SHIFT;
#endif
#if defined(SPACEMOUSE)
for (uint8_t i=0; i<(MIXSRC_LAST_SPACEMOUSE - MIXSRC_FIRST_SPACEMOUSE); i++)
sum += get_spacemouse_value(i) >> INAC_STICKS_SHIFT;
#endif
if (abs((int8_t)(sum-inactivity.sum)) > 1) {
inactivity.sum = sum;
return true;
+4
View File
@@ -1177,6 +1177,10 @@ extern Clipboard clipboard;
#include "gps.h"
#endif
#if defined(SPACEMOUSE)
#include "spacemouse.h"
#endif
#if defined(JACK_DETECT_GPIO)
enum JackMode {
JACK_UNSELECTED_MODE,
+3
View File
@@ -62,6 +62,9 @@ static const char * const options[] = {
#if defined(INTERNAL_GPS)
"internalgps",
#endif
#if defined(SPACEMOUSE)
"spacemouse",
#endif
#if defined(INTERNAL_MODULE_PPM)
"internalppm",
#endif
+12
View File
@@ -212,6 +212,11 @@ static void serialSetCallBacks(int mode, void* ctx, const etx_serial_port_t* por
gpsSetSerialDriver(ctx, drv);
break;
#endif
#if defined(SPACEMOUSE)
case UART_MODE_SPACEMOUSE:
spacemouseSetSerialDriver(ctx, drv);
break;
#endif
#endif
}
}
@@ -267,6 +272,13 @@ static void serialSetupPort(int mode, etx_serial_init& params)
params.rx_enable = true;
break;
#endif
#if defined(SPACEMOUSE)
case UART_MODE_SPACEMOUSE:
params.baudrate = SPACEMOUSE_BAUDRATE;
params.rx_enable = true;
break;
#endif
#endif
}
}
+218
View File
@@ -0,0 +1,218 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include "opentx.h"
#include <ctype.h>
#if !defined(SIMU)
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/timers.h>
#endif
struct spacemousedata_t
{
signed short axisValues[SPACEMOUSE_CHANNEL_COUNT];
};
enum class sm_bytetype
{
SM_START,
SM_DATA,
SM_CHECKSUMHB,
SM_CHECKSUMLB,
SM_FOOTER,
};
struct spacemouseTelegram_t
{
unsigned char data[SPACEMOUSE_LENGTH_TELEGRAM];
unsigned short checkSumReceived;
unsigned short checkSumCalc;
unsigned char dataIndex;
sm_bytetype parsestate;
unsigned char recevied;
};
static spacemouseTelegram_t spaceMouseTelegram = { {0} };
spacemousedata_t spacemouseData;
void spacemouseWakeup();
#if !defined(SIMU)
static TimerHandle_t spacemouseTimer = nullptr;
static StaticTimer_t spacemouseTimerBuffer;
static void spacemouseTimerCb(TimerHandle_t xTimer)
{
if (!s_pulses_paused) {
DEBUG_TIMER_START(debugTimerSpacemouseWakeup);
spacemousePoll();
spacemouseWakeup();
DEBUG_TIMER_STOP(debugTimerSpacemouseWakeup);
}
}
void spacemouseStart()
{
if (!spacemouseTimer) {
spacemouseTimer =
xTimerCreateStatic("SpaceM", 10 / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
spacemouseTimerCb, &spacemouseTimerBuffer);
}
if (spacemouseTimer) {
if( xTimerStart( spacemouseTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
}
}
}
void spacemouseStop()
{
if (spacemouseTimer) {
if( xTimerStop( spacemouseTimer, 12 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be stopped. */
}
}
}
#endif
void spacemouseParseNewData(uint8_t c)
{
switch (spaceMouseTelegram.parsestate) {
case sm_bytetype::SM_START: {
if (c == SPACEMOUSE_PROTO_HEADER) {
spaceMouseTelegram.checkSumCalc = c;
spaceMouseTelegram.parsestate = sm_bytetype::SM_DATA;
spaceMouseTelegram.dataIndex = 0;
}
break;
}
case sm_bytetype::SM_DATA: {
spaceMouseTelegram.data[spaceMouseTelegram.dataIndex++] = c;
spaceMouseTelegram.checkSumCalc += c;
if (spaceMouseTelegram.dataIndex >= SPACEMOUSE_LENGTH_DATA) {
spaceMouseTelegram.checkSumReceived = 0;
spaceMouseTelegram.dataIndex = 0;
spaceMouseTelegram.parsestate = sm_bytetype::SM_CHECKSUMHB;
}
break;
}
case sm_bytetype::SM_CHECKSUMHB: {
spaceMouseTelegram.checkSumReceived = c << 7;
spaceMouseTelegram.parsestate = sm_bytetype::SM_CHECKSUMLB;
break;
}
case sm_bytetype::SM_CHECKSUMLB: {
spaceMouseTelegram.checkSumReceived += c;
spaceMouseTelegram.parsestate = sm_bytetype::SM_FOOTER;
break;
}
case sm_bytetype::SM_FOOTER: {
if ((c == SPACEMOUSE_PROTO_FOOTER) &&
(spaceMouseTelegram.checkSumReceived == (spaceMouseTelegram.checkSumCalc & 0x3FFF))) {
for ( uint8_t channel = 0; channel < SPACEMOUSE_CHANNEL_COUNT; channel++ )
{
// The values are 7-bit in LSByte and MSByte only. Set MSBit is reserved for start, stop & commands.
spacemouseData.axisValues[channel] = ((spaceMouseTelegram.data[channel*2] << 7) + spaceMouseTelegram.data[(channel*2)+1]) - SPACEMOUSE_INPUT_OFFSET;
}
}
spaceMouseTelegram.checkSumCalc = 0;
spaceMouseTelegram.parsestate = sm_bytetype::SM_START;
break;
}
}
}
static const etx_serial_driver_t* spacemouseSerialDrv = nullptr;
static void* spacemouseSerialCtx = nullptr;
#if defined(DEBUG)
bool spacemouseTraceEnabled = false;
#endif
void spacemouseSetSerialDriver(void* ctx, const etx_serial_driver_t* drv)
{
spacemouseSerialCtx = ctx;
spacemouseSerialDrv = drv;
spaceMouseTelegram.parsestate = sm_bytetype::SM_START;
#if !defined(SIMU)
spacemouseStart();
#endif
}
int16_t get_spacemouse_value(uint8_t ch)
{
if (ch >= SPACEMOUSE_CHANNEL_COUNT) {
return 0;
}
return (int16_t)(((float)spacemouseData.axisValues[ch])*SPACEMOUSE_OUTPUT_CONV_FACTOR);
}
void spacemouseWakeup()
{
if (!spacemouseSerialDrv) return;
auto _getByte = spacemouseSerialDrv->getByte;
if (!_getByte) return;
uint8_t byte;
while (_getByte(spacemouseSerialCtx, &byte)) {
#if defined(DEBUG)
if (spacemouseTraceEnabled) {
dbgSerialPutc(byte);
}
#endif
spacemouseParseNewData(byte);
}
}
void spacemouseSendCommand(const uint8_t cmd)
{
if (!spacemouseSerialDrv) return;
auto _sendByte = spacemouseSerialDrv->sendByte;
if (!_sendByte) return;
TRACE_NOCRLF("spacemouse> 0x%x", cmd);
_sendByte(spacemouseSerialCtx, cmd);
}
void spacemousePoll()
{
spacemouseSendCommand(SPACEMOUSE_CMD_REQUEST_DATA);
}
void spacemouseTare()
{
spacemouseSendCommand(SPACEMOUSE_CMD_SET_ZERO_POSITION);
}
void spacemouseStartStreaming()
{
spacemouseSendCommand(SPACEMOUSE_CMD_AUTO_DATA_ON);
}
void spacemouseStopStreaming()
{
spacemouseSendCommand(SPACEMOUSE_CMD_AUTO_DATA_OFF);
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#ifndef _SPACEMOUSE_H_
#define _SPACEMOUSE_H_
#include <inttypes.h>
#define SPACEMOUSE_BAUDRATE ( 38400 )
#define SPACEMOUSE_CHANNEL_COUNT ( 6 )
#define SPACEMOUSE_INPUT_OFFSET ( 8192 )
#define SPACEMOUSE_OUTPUT_RANGE ( 700.0f )
#define SPACEMOUSE_OUTPUT_OFFSET ( 350 )
#define SPACEMOUSE_OUTPUT_CONV_FACTOR ( 2048.0f / SPACEMOUSE_OUTPUT_RANGE ) /* Internal channel resolution / SPACEMOUSE_OUTPUT_RANGE */
#define SPACEMOUSE_PROTO_HEADER 0x96
#define SPACEMOUSE_PROTO_FOOTER 0x8D
#define SPACEMOUSE_CMD_REQUEST_DATA 0xAC
#define SPACEMOUSE_CMD_SET_ZERO_POSITION 0xAD
#define SPACEMOUSE_CMD_AUTO_DATA_ON 0xAE
#define SPACEMOUSE_CMD_AUTO_DATA_OFF 0xAF
#define SPACEMOUSE_LENGTH_HEADER 1
#define SPACEMOUSE_LENGTH_DATA (2*SPACEMOUSE_CHANNEL_COUNT)
#define SPACEMOUSE_LENGTH_CHECKSUM 2
#define SPACEMOUSE_LENGTH_FOOTER 1
#define SPACEMOUSE_LENGTH_TELEGRAM (SPACEMOUSE_LENGTH_HEADER + SPACEMOUSE_LENGTH_DATA + SPACEMOUSE_LENGTH_CHECKSUM + SPACEMOUSE_LENGTH_FOOTER)
#if defined(DEBUG)
extern bool spacemouseTraceEnabled;
#endif
// Setup SpaceMouse serial port
void spacemouseSetSerialDriver(void* ctx, const etx_serial_driver_t* drv);
// Fetch SpaceMouse data
int16_t get_spacemouse_value(uint8_t ch);
// Periodic processing
void spacemouseStart();
void spacemouseStop();
void spacemousePoll();
void spacemouseTare();
void spacemouseStartStreaming();
void spacemouseStopStreaming();
#endif // _SPACEMOUSE_H_
@@ -1855,6 +1855,7 @@ static const struct YamlIdStr enum_UartModes[] = {
{ UART_MODE_CLI, "CLI" },
{ UART_MODE_GPS, "GPS" },
{ UART_MODE_DEBUG, "DEBUG" },
{ UART_MODE_SPACEMOUSE, "SPACEMOUSE" },
{ 0, NULL }
};
@@ -130,6 +130,12 @@ const struct YamlIdStr enum_MixSources[] = {
{ MIXSRC_MOUSE2, "MOUSE2" },
{ MIXSRC_TILT_X, "TILT_X" },
{ MIXSRC_TILT_Y, "TILT_Y" },
{ MIXSRC_SPACEMOUSE_A, "SPACEMOUSE_A" },
{ MIXSRC_SPACEMOUSE_B, "SPACEMOUSE_B" },
{ MIXSRC_SPACEMOUSE_C, "SPACEMOUSE_C" },
{ MIXSRC_SPACEMOUSE_D, "SPACEMOUSE_D" },
{ MIXSRC_SPACEMOUSE_E, "SPACEMOUSE_E" },
{ MIXSRC_SPACEMOUSE_F, "SPACEMOUSE_F" },
{ MIXSRC_MAX, "MAX" },
{ MIXSRC_CYC1, "CYC1" },
{ MIXSRC_CYC2, "CYC2" },
@@ -128,6 +128,12 @@ const struct YamlIdStr enum_MixSources[] = {
{ MIXSRC_MOUSE2, "MOUSE2" },
{ MIXSRC_TILT_X, "TILT_X" },
{ MIXSRC_TILT_Y, "TILT_Y" },
{ MIXSRC_SPACEMOUSE_A, "SPACEMOUSE_A" },
{ MIXSRC_SPACEMOUSE_B, "SPACEMOUSE_B" },
{ MIXSRC_SPACEMOUSE_C, "SPACEMOUSE_C" },
{ MIXSRC_SPACEMOUSE_D, "SPACEMOUSE_D" },
{ MIXSRC_SPACEMOUSE_E, "SPACEMOUSE_E" },
{ MIXSRC_SPACEMOUSE_F, "SPACEMOUSE_F" },
{ MIXSRC_MAX, "MAX" },
{ MIXSRC_CYC1, "CYC1" },
{ MIXSRC_CYC2, "CYC2" },
+7
View File
@@ -7,6 +7,7 @@ option(AFHDS3 "AFHDS3 TX Module" ON)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
option(GHOST "Ghost TX Module" ON)
option(HARDWARE_EXTERNAL_ACCESS_MOD "Support for R9M 2019 hardware mod" OFF)
option(SPACEMOUSE "Support for SpaceMouse" OFF)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F4)
@@ -246,6 +247,12 @@ if(INTERNAL_GPS)
message("-- Internal GPS enabled")
endif()
if(SPACEMOUSE)
add_definitions(-DSPACEMOUSE)
set(SRC ${SRC} spacemouse.cpp)
message("-- SpaceMouse enabled")
endif()
set(GVAR_SCREEN model_gvars.cpp)
if(HARDWARE_TOUCH)
+1
View File
@@ -335,6 +335,7 @@ void rotaryEncoderCheck();
#define STORAGE_NUM_SLIDERS 4
enum Analogs {
STICK1,
STICK2,
+1 -1
View File
@@ -169,7 +169,7 @@ void telemetryStop()
{
if (telemetryTimer) {
if( xTimerStop( telemetryTimer, 5 / RTOS_MS_PER_TICK ) != pdPASS ) {
/* The timer could not be set into the Active state. */
/* The timer could not be stopped. */
}
}
}
+1 -1
View File
@@ -427,7 +427,7 @@ TEST(Conversions, ConversionX12SFrom23)
EXPECT_STRNEQ("Tes", g_model.telemetrySensors[0].label);
EXPECT_EQ(10, g_model.telemetrySensors[0].id);
EXPECT_EQ(9, g_model.telemetrySensors[0].frskyInstance.physID);
EXPECT_EQ((NUM_POTS + NUM_SLIDERS + 3), g_model.thrTraceSrc); // CH3
EXPECT_EQ(source2ThrottleSource(MIXSRC_CH3), g_model.thrTraceSrc); // CH3
simuFatfsSetPaths("","");
}
+1 -1
View File
@@ -37,7 +37,7 @@
#define TR_TRNMODE "关","相加","替换"
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "调试","回传镜像","回传输入","SBUS教练","LUA脚本","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "调试","回传镜像","回传输入","SBUS教练","LUA脚本","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "无","回弹","2段","3段"
#define TR_POTTYPES "无","有中点旋钮","多段旋钮","无中点旋钮"
#define TR_SLIDERTYPES "无","侧滑块"
+1 -1
View File
@@ -39,7 +39,7 @@
#define TR_VBLMODE TR("Vyp","Vypnuto"),TR("Kláv.","Klávesy"),"Páky","Vše",TR("Zap","Zapnuto")
#define TR_TRNMODE "X","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "VYP","Telem Mirror","Telemetry In","SBUS Trenér","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "VYP","Telem Mirror","Telemetry In","SBUS Trenér","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Žádný","Bez aretace","2-polohový","3-polohový"
#define TR_POTTYPES "Žádný",TR("Pot s aret.","Pot s aretací"),TR("Vícepol př.","Vícepol. přep."),TR("Pot","Potenciometr")
#define TR_SLIDERTYPES "Žádný","Slider"
+1 -1
View File
@@ -37,7 +37,7 @@
#define TR_TRNMODE "FRA","+=",":="
#define TR_TRNCHN "KA1","KA2","KA3","KA4"
#define TR_AUX_SERIAL_MODES "FRA","Telem spejle","Telemetri ind","SBUS træner","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "FRA","Telem spejle","Telemetri ind","SBUS træner","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Ingen","Toggle","2POS","3POS"
#define TR_POTTYPES "Ingen",TR("Drejekontakt med det","Drejekontakt"),TR("Multipos","Multipos kontakt"),"Drejekontakt"
#define TR_SLIDERTYPES "Ingen","Skyder"
+1 -1
View File
@@ -39,7 +39,7 @@
#define TR_VBLMODE "AUS","Taste","Stks","Beide","EIN"
#define TR_TRNMODE "AUS","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "AUS","Telem Mirror","Telemetry In","SBUS Eingang","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "AUS","Telem Mirror","Telemetry In","SBUS Eingang","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Kein","Taster","2POS","3POS"
#define TR_POTTYPES "Kein",TR("Poti m.Ras","Poti mit Raste"),TR("Stufens.","Stufen-Schalter"),TR("Pot","Poti ohne Raste")
#define TR_SLIDERTYPES "Keine","Slider"
+1 -1
View File
@@ -37,7 +37,7 @@
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "OFF","Telem Mirror","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "OFF","Telem Mirror","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "None","Toggle","2POS","3POS"
#define TR_POTTYPES "None",TR("Pot w. det","Pot with detent"),TR("Multipos","Multipos Switch"),"Pot"
#define TR_SLIDERTYPES "None","Slider"
+1 -1
View File
@@ -39,7 +39,7 @@
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetría","Entrenador SBUS","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetría","Entrenador SBUS","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Nada","Palanca","2POS","3POS"
#define TR_POTTYPES "Nada",TR("Pot con fij","Pot con fijador"),TR("Multipos","Switch multipos"),"Pot"
#define TR_SLIDERTYPES "Nada","Slider"
+1 -1
View File
@@ -39,7 +39,7 @@
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "POIS","S-Port Pelik","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "POIS","S-Port Pelik","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "None","Toggle","2POS","3POS"
#define TR_POTTYPES "None", TR("Pot w. det","Pot with detent"),TR("Multipos","Monias. Kytkin"),TR("Pot","Potikka")
#define TR_SLIDERTYPES "Rien","Slider"
+1 -1
View File
@@ -40,7 +40,7 @@
#define TR_VBLMODE "OFF",TR("Btns","Touches"),TR("Ctrl","Controles"),"Tous","ON"
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "OFF","Recopie Telem","Télémétrie In","Ecolage SBUS","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "OFF","Recopie Telem","Télémétrie In","Ecolage SBUS","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Rien","Levier","2-POS","3-POS"
#define TR_POTTYPES "Rien",TR("Pot av. ctr","Pot avec centre"),TR("Multipos","Inter multi-pos""Potentiomètre"),TR("Pot","Potentiomètre")
#define TR_SLIDERTYPES "Rien","Slider"
+1 -1
View File
@@ -40,7 +40,7 @@
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "OFF","Replica S-Port","Telemetria","SBUS Trainer","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "OFF","Replica S-Port","Telemetria","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Disab.","Toggle","2POS","3POS"
#define TR_POTTYPES "Disab.",TR("Pot c. fer","Pot. con centro"),TR("Multipos","Inter. Multipos"),TR("Pot","Potenziometro")
#define TR_SLIDERTYPES "Disab.","Slider"
+1 -1
View File
@@ -40,7 +40,7 @@
#define TR_TRNMODE "UIT","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetry In","SBUS Leerling","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetry In","SBUS Leerling","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Geen","Wissel","2POS","3POS"
#define TR_POTTYPES "Geen",TR("Pot w. det","Pot met Klik"),TR("Multipos","Standenschakelaar"),TR("Pot", "Pot zonder Klik")
#define TR_SLIDERTYPES "Geen","Schuif"
+1 -1
View File
@@ -38,7 +38,7 @@
#define TR_VBLMODE TR("Wył","Wyłącz"),TR("Przy","Przycisk"),TR("Drąż","Drązki"),"Oba",TR("Zał","Włącz")
#define TR_TRNMODE "Wył","+=",":="
#define TR_TRNCHN "KN1","KN2","KN3","KN4"
#define TR_AUX_SERIAL_MODES "Wyłącz","S-Port Kopia","Telemetria","Trener SBUS","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "Wyłącz","S-Port Kopia","Telemetria","Trener SBUS","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Brak","Chwil.","2POZ","3POZ"
#define TR_POTTYPES TR("Pot w. det","Poten z zapadką"),TR("Multipos","Przeł.Wielopoz."),TR("Pot","Potencjometr")
#define TR_SLIDERTYPES "Brak","Suwak"
+1 -1
View File
@@ -37,7 +37,7 @@
#define TR_VBLMODE "OFF","Chav","Stks","Tudo","ON\0"
#define TR_TRNMODE "OFF","+=",":="
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "OFF","S-Port Mirror","Telemetry","SBUS Trainer","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "OFF","S-Port Mirror","Telemetry","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "None","Toggle","2POS","3POS"
#define TR_POTTYPES "None",TR("Pot w. det","Pot with detent"),TR("Multipos","Multipos Switch"),"Pot"
#define TR_SLIDERTYPES "Rien","Slider"
+1 -1
View File
@@ -40,7 +40,7 @@
#define TR_VBLMODE "Av",TR("Knapp","Knappar"),TR("Spak","Spakar"),"Allt","PÅ"
#define TR_TRNMODE "Av","+=",":="
#define TR_TRNCHN "KA1","KA2","KA3","KA4"
#define TR_AUX_SERIAL_MODES "AV","Speglad telemetri","Telemetri in","SBUS Lärare","LUA","CLI","GPS","Debug"
#define TR_AUX_SERIAL_MODES "AV","Speglad telemetri","Telemetri in","SBUS Lärare","LUA","CLI","GPS","Debug","SpaceMouse"
#define TR_SWTYPES "Ingen",TR("Flipp","2 pos momentan"),"2 pos","3 pos"
#define TR_POTTYPES "Ingen",TR("Vred m. mitt","Vred med mittläge"),TR("Multipos","Flerlägesväljare"),"Vred"
#define TR_SLIDERTYPES "Inga","Reglage"
+1 -1
View File
@@ -37,7 +37,7 @@
#define TR_TRNMODE "關","相加","替換"
#define TR_TRNCHN "CH1","CH2","CH3","CH4"
#define TR_AUX_SERIAL_MODES "禁用","回傳鏡像","回傳輸入","SBUS教練","LUA腳本","CLI","GPS","調試"
#define TR_AUX_SERIAL_MODES "禁用","回傳鏡像","回傳輸入","SBUS教練","LUA腳本","CLI","GPS","調試","SpaceMouse"
#define TR_SWTYPES "無","回彈","2段","3段"
#define TR_POTTYPES "無","有中點旋鈕","多段旋鈕","無中點旋鈕"
#define TR_SLIDERTYPES "無","側滑塊"
+7 -1
View File
@@ -88,7 +88,13 @@
TR_VTRAINER_MASTER_SBUS_MODULE, TR_VTRAINER_MASTER_CPPM_MODULE, \
TR_VTRAINER_MASTER_BATTERY, TR_VTRAINER_BLUETOOTH, TR_VTRAINER_MULTI
#define TR_VSRCRAW "---", TR_STICKS_VSRCRAW, TR_POTS_VSRCRAW, TR_IMU_VSRCRAW "MAX", TR_CYC_VSRCRAW, TR_TRIMS_VSRCRAW, TR_SW_VSRCRAW, TR_EXTRA_VSRCRAW
#if defined(PCBHORUS)
#define TR_SM_VSRCRAW "smA","smB","smC","smD","smE","smF",
#else
#define TR_SM_VSRCRAW
#endif
#define TR_VSRCRAW "---", TR_STICKS_VSRCRAW, TR_POTS_VSRCRAW, TR_IMU_VSRCRAW TR_SM_VSRCRAW "MAX", TR_CYC_VSRCRAW, TR_TRIMS_VSRCRAW, TR_SW_VSRCRAW, TR_EXTRA_VSRCRAW
#define TR_CRSF_BAUDRATE "115k","400k","921k","1.87M","3.75M","5.25M"