From c22d6fbf37971d65d4d7110325d11a53aa52afac Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:47:39 +0200 Subject: [PATCH 1/9] add support for custom devices --- .github/workflows/ci.yml | 6 ++ .github/workflows/release.yml | 6 ++ .gitignore | 1 + _Boards/Atmel/Board_Mega/MFBoards.h | 6 ++ _Boards/Atmel/Board_Nano/MFBoards.h | 10 +- _Boards/Atmel/Board_ProMicro/MFBoards.h | 6 ++ _Boards/Atmel/Board_Uno/MFBoards.h | 6 ++ _Boards/RaspberryPi/Pico/MFBoards.h | 7 +- get_CustomDevices.py | 12 +++ get_version.py | 2 +- platformio.ini | 48 +++++---- src/CommandMessenger.cpp | 7 ++ src/Config.cpp | 123 +++++++++++++++--------- src/MF_CustomDevice/CustomDevice.cpp | 86 +++++++++++++++++ src/MF_CustomDevice/CustomDevice.h | 9 ++ src/commandmessenger.h | 1 + src/config.h | 3 +- src/mobiflight.cpp | 15 +++ 18 files changed, 284 insertions(+), 70 deletions(-) create mode 100644 get_CustomDevices.py create mode 100644 src/MF_CustomDevice/CustomDevice.cpp create mode 100644 src/MF_CustomDevice/CustomDevice.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9647c91..698c7aaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,12 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio + - name: Checkout component library + uses: actions/checkout@v3 + with: + repository: MobiFlight/MobiFlight-CustomDevices + path: CustomDevices + - name: Run PlatformIO env: VERSION: "0.0.${{ github.event.number }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 28498d3c..0e94b35f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,12 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio + - name: Checkout component library + uses: actions/checkout@v3 + with: + repository: MobiFlight/MobiFlight-CustomDevices + path: CustomDevices + - name: Extract build version id: get_version uses: battila7/get-version-action@v2 diff --git a/.gitignore b/.gitignore index 310bfad4..5ffa057a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .vscode/launch.json .vscode/ipch .vscode/arduino.json +.CustomDevices diff --git a/_Boards/Atmel/Board_Mega/MFBoards.h b/_Boards/Atmel/Board_Mega/MFBoards.h index 63976fad..a5c24a41 100644 --- a/_Boards/Atmel/Board_Mega/MFBoards.h +++ b/_Boards/Atmel/Board_Mega/MFBoards.h @@ -35,6 +35,9 @@ #define MF_MUX_SUPPORT 1 #define MF_DIGIN_MUX_SUPPORT 1 #endif +#ifndef MF_CUSTOMDEVICE_SUPPORT +#define MF_CUSTOMDEVICE_SUPPORT 1 +#endif #ifndef MAX_OUTPUTS #define MAX_OUTPUTS 40 @@ -69,6 +72,9 @@ #ifndef MAX_DIGIN_MUX #define MAX_DIGIN_MUX 4 #endif +#ifndef MAX_CUSTOM_DEVICES +#define MAX_CUSTOM_DEVICES 5 +#endif #ifndef MOBIFLIGHT_TYPE #define MOBIFLIGHT_TYPE "MobiFlight Mega" diff --git a/_Boards/Atmel/Board_Nano/MFBoards.h b/_Boards/Atmel/Board_Nano/MFBoards.h index 86d0ace3..f3d1e5e5 100644 --- a/_Boards/Atmel/Board_Nano/MFBoards.h +++ b/_Boards/Atmel/Board_Nano/MFBoards.h @@ -35,6 +35,9 @@ #define MF_MUX_SUPPORT 1 #define MF_DIGIN_MUX_SUPPORT 1 #endif +#ifndef MF_CUSTOMDEVICE_SUPPORT +#define MF_CUSTOMDEVICE_SUPPORT 2 +#endif #ifndef MAX_OUTPUTS #define MAX_OUTPUTS 18 @@ -69,10 +72,9 @@ #ifndef MAX_DIGIN_MUX #define MAX_DIGIN_MUX 3 #endif - -#define STEPS 64 -#define STEPPER_SPEED 400 // 300 already worked, 467, too? -#define STEPPER_ACCEL 800 +#ifndef MAX_CUSTOM_DEVICES +#define MAX_CUSTOM_DEVICES 2 +#endif #ifndef MOBIFLIGHT_TYPE #define MOBIFLIGHT_TYPE "MobiFlight Nano" diff --git a/_Boards/Atmel/Board_ProMicro/MFBoards.h b/_Boards/Atmel/Board_ProMicro/MFBoards.h index feadacc4..f62ebcd5 100644 --- a/_Boards/Atmel/Board_ProMicro/MFBoards.h +++ b/_Boards/Atmel/Board_ProMicro/MFBoards.h @@ -35,6 +35,9 @@ #define MF_MUX_SUPPORT 1 #define MF_DIGIN_MUX_SUPPORT 1 #endif +#ifndef MF_CUSTOMDEVICE_SUPPORT +#define MF_CUSTOMDEVICE_SUPPORT 2 +#endif #ifndef MAX_OUTPUTS #define MAX_OUTPUTS 18 @@ -69,6 +72,9 @@ #ifndef MAX_DIGIN_MUX #define MAX_DIGIN_MUX 3 #endif +#ifndef MAX_CUSTOM_DEVICES +#define MAX_CUSTOM_DEVICES 2 +#endif #ifndef MOBIFLIGHT_TYPE #define MOBIFLIGHT_TYPE "MobiFlight Micro" diff --git a/_Boards/Atmel/Board_Uno/MFBoards.h b/_Boards/Atmel/Board_Uno/MFBoards.h index 4b12451a..c3f4ab38 100644 --- a/_Boards/Atmel/Board_Uno/MFBoards.h +++ b/_Boards/Atmel/Board_Uno/MFBoards.h @@ -35,6 +35,9 @@ #define MF_MUX_SUPPORT 1 #define MF_DIGIN_MUX_SUPPORT 1 #endif +#ifndef MF_CUSTOMDEVICE_SUPPORT +#define MF_CUSTOMDEVICE_SUPPORT 2 +#endif #ifndef MAX_OUTPUTS #define MAX_OUTPUTS 18 @@ -69,6 +72,9 @@ #ifndef MAX_DIGIN_MUX #define MAX_DIGIN_MUX 3 #endif +#ifndef MAX_CUSTOM_DEVICES +#define MAX_CUSTOM_DEVICES 2 +#endif #ifndef MOBIFLIGHT_TYPE #define MOBIFLIGHT_TYPE "MobiFlight Uno" diff --git a/_Boards/RaspberryPi/Pico/MFBoards.h b/_Boards/RaspberryPi/Pico/MFBoards.h index a56c2a8c..61dc0831 100644 --- a/_Boards/RaspberryPi/Pico/MFBoards.h +++ b/_Boards/RaspberryPi/Pico/MFBoards.h @@ -63,10 +63,9 @@ #ifndef MAX_DIGIN_MUX #define MAX_DIGIN_MUX 4 #endif - -#define STEPS 64 -#define STEPPER_SPEED 400 // 300 already worked, 467, too? -#define STEPPER_ACCEL 800 +#ifndef MAX_CUSTOM_DEVICES +#define MAX_CUSTOM_DEVICES 5 +#endif #ifndef MOBIFLIGHT_TYPE #define MOBIFLIGHT_TYPE "MobiFlight RaspiPico" diff --git a/get_CustomDevices.py b/get_CustomDevices.py new file mode 100644 index 00000000..c5bc63e9 --- /dev/null +++ b/get_CustomDevices.py @@ -0,0 +1,12 @@ +import os + +Import("env") + +CUSTOMDEVICES_DIR = env.subst("$PROJECT_DIR/CustomDevices") + +if not os.path.exists(CUSTOMDEVICES_DIR): + print ("Cloning Mobiflight-CustomDevices repo ... ") + env.Execute("git clone --depth 100 https://github.com/elral/MobiFlight-CustomDevices $PROJECT_DIR/CustomDevices") +else: + print ("Checking for Mobiflight-CustomDevices repo updates ... ") + env.Execute("git --work-tree=$PROJECT_DIR\CustomDevices --git-dir=$PROJECT_DIR\CustomDevices\.git pull origin main --depth 100") diff --git a/get_version.py b/get_version.py index 3b8cc853..a1f94183 100644 --- a/get_version.py +++ b/get_version.py @@ -23,4 +23,4 @@ ]) # Set the output filename to the name of the board and the version -env.Replace(PROGNAME=f'mobiflight_{env["PIOENV"]}_{firmware_version.replace(".", "_")}') +env.Replace(PROGNAME=f'{env["PIOENV"]}_{firmware_version.replace(".", "_")}') diff --git a/platformio.ini b/platformio.ini index 92f017c8..b5bfea4c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,6 +15,15 @@ ; development use VSCode to change the target to a non-default ; by clicking on the target name in the bottom status bar. [platformio] +; include custom environments to be build +extra_configs = + ./CustomDevices/_template/MyCustomDevice_platformio.ini + ./CustomDevices/KAV_Simulation/EFIS_FCU/EFIS_FCU_platformio.ini + ./CustomDevices/Mobiflight/GNC255/GNC255_platformio.ini + ./CustomDevices/Mobiflight/TM1637/TM1637_platformio.ini + ./CustomDevices/Mobiflight/GenericI2C/GenericI2C_platformio.ini + ./CustomDevices/_all_CustomDevices/all_devices_platformio.ini + ; Common build settings across all devices [env] @@ -48,20 +57,23 @@ build_flags = -I./src/MF_Modules build_src_filter = +<*> + -<./MF_CustomDevice> extra_scripts = pre:get_version.py + pre:get_CustomDevices.py ; Build settings for the Arduino Mega -[env:mega] +[env:mobiflight_mega] platform = atmelavr board = megaatmega2560 framework = arduino build_flags = ${env.build_flags} + -DMF_CUSTOMDEVICE_SUPPORT=0 + '-DMOBIFLIGHT_TYPE="MobiFlight Mega"' -I./_Boards/Atmel/Board_Mega build_src_filter = ${env.build_src_filter} - +<../_Boards/Atmel> lib_deps = ${env.lib_deps} ${env.custom_lib_deps_Atmel} @@ -70,16 +82,17 @@ extra_scripts = ${env.extra_scripts} ; Build settings for the Arduino Pro Micro -[env:micro] +[env:mobiflight_micro] platform = atmelavr board = sparkfun_promicro16 framework = arduino build_flags = ${env.build_flags} + -DMF_CUSTOMDEVICE_SUPPORT=0 + '-DMOBIFLIGHT_TYPE="MobiFlight Micro"' -I./_Boards/Atmel/Board_ProMicro build_src_filter = ${env.build_src_filter} - +<../_Boards/Atmel> lib_deps = ${env.lib_deps} ${env.custom_lib_deps_Atmel} @@ -89,16 +102,17 @@ extra_scripts = ; Build settings for the Arduino Uno -[env:uno] +[env:mobiflight_uno] platform = atmelavr board = uno framework = arduino build_flags = ${env.build_flags} + -DMF_CUSTOMDEVICE_SUPPORT=0 + '-DMOBIFLIGHT_TYPE="MobiFlight Uno"' -I./_Boards/Atmel/Board_Uno build_src_filter = ${env.build_src_filter} - +<../_Boards/Atmel> lib_deps = ${env.lib_deps} ${env.custom_lib_deps_Atmel} @@ -107,16 +121,17 @@ extra_scripts = ${env.extra_scripts} ; Build settings for the Arduino Nano -[env:nano] +[env:mobiflight_nano] platform = atmelavr board = nanoatmega328 framework = arduino build_flags = ${env.build_flags} + -DMF_CUSTOMDEVICE_SUPPORT=0 + '-DMOBIFLIGHT_TYPE="MobiFlight Nano"' -I./_Boards/Atmel/Board_Nano build_src_filter = ${env.build_src_filter} - +<../_Boards/Atmel> lib_deps = ${env.lib_deps} ${env.custom_lib_deps_Atmel} @@ -125,25 +140,24 @@ extra_scripts = ${env.extra_scripts} ; Build settings for the Raspberry Pico original -[env:raspberrypico] +[env:mobiflight_raspberrypico] platform = https://github.com/maxgerhardt/platform-raspberrypi.git board = pico framework = arduino -board_build.core = earlephilhower ; select new core -board_build.filesystem_size = 0M ; configure filesystem size. Default 0 Mbyte. +board_build.core = earlephilhower ; select new core +board_build.filesystem_size = 0M ; configure filesystem size. Default 0 Mbyte. lib_ldf_mode = chain+ -upload_protocol = mbed ; for debugging upoading can be changed to picoprobe -;debug_tool = picoprobe ; and uncomment this for debugging w/ picoprobe +upload_protocol = mbed ; for debugging upoading can be changed to picoprobe +;debug_tool = picoprobe ; and uncomment this for debugging w/ picoprobe build_flags = ${env.build_flags} - -DUSE_INTERRUPT + -DMF_CUSTOMDEVICE_SUPPORT=0 + '-DMOBIFLIGHT_TYPE="MobiFlight RaspiPico"' -I./_Boards/RaspberryPi/Pico - -fpermissive build_src_filter = ${env.build_src_filter} - +<../_Boards/RaspberryPi> lib_deps = ${env.lib_deps} monitor_speed = 115200 extra_scripts = - ${env.extra_scripts} \ No newline at end of file + ${env.extra_scripts} diff --git a/src/CommandMessenger.cpp b/src/CommandMessenger.cpp index a82c526d..5870ae34 100644 --- a/src/CommandMessenger.cpp +++ b/src/CommandMessenger.cpp @@ -33,6 +33,9 @@ #if MF_DIGIN_MUX_SUPPORT == 1 #include "DigInMux.h" #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 +#include "CustomDevice.h" +#endif CmdMessenger cmdMessenger = CmdMessenger(Serial); unsigned long lastCommand; @@ -83,6 +86,10 @@ void attachCommandCallbacks() cmdMessenger.attach(kSetShiftRegisterPins, OutputShifter::OnSet); #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 + cmdMessenger.attach(kSetCustomDevice, CustomDevice::OnSet); +#endif + #ifdef DEBUG2CMDMESSENGER cmdMessenger.sendCmd(kDebug, F("Attached callbacks")); #endif diff --git a/src/Config.cpp b/src/Config.cpp index 0445483e..9b291799 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -38,11 +38,15 @@ #if MF_DIGIN_MUX_SUPPORT == 1 #include "DigInMux.h" #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 +#include "CustomDevice.h" +#endif // The build version comes from an environment variable #define STRINGIZER(arg) #arg #define STR_VALUE(arg) STRINGIZER(arg) #define VERSION STR_VALUE(BUILD_VERSION) + MFEEPROM MFeeprom; #if MF_MUX_SUPPORT == 1 @@ -78,8 +82,7 @@ bool readConfigLength() while (MFeeprom.read_byte(addreeprom++) != 0x00) { configLength++; - if (addreeprom > length) - { + if (addreeprom > length) { cmdMessenger.sendCmd(kStatus, F("Loading config failed")); // text or "-1" like config upload? return false; } @@ -147,6 +150,10 @@ void resetConfig() #if MF_DIGIN_MUX_SUPPORT == 1 DigInMux::Clear(); #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 + CustomDevice::Clear(); +#endif + configLength = 0; configActivated = false; ClearMemory(); @@ -214,8 +221,10 @@ bool readNameFromEEPROM(uint16_t *addreeprom, char *buffer, uint16_t *addrbuffer return true; } -// reads the EEPRROM until end of command which ':' terminated -bool readEndCommandFromEEPROM(uint16_t *addreeprom) +// steps thru the EEPRROM until the delimiter is detected +// it could be ":" for end of one device config +// or "." for end of type/pin/config entry for custom device +bool readEndCommandFromEEPROM(uint16_t *addreeprom, uint8_t delimiter) { char temp = 0; uint16_t length = MFeeprom.get_length(); @@ -223,7 +232,7 @@ bool readEndCommandFromEEPROM(uint16_t *addreeprom) temp = MFeeprom.read_byte((*addreeprom)++); if (*addreeprom > length) // abort if EEPROM size will be exceeded return false; - } while (temp != ':'); // reads until limiter ':' + } while (temp != delimiter); // reads until limiter ':' return true; } @@ -238,7 +247,13 @@ void readConfig() bool copy_success = true; // will be set to false if copying input names to nameBuffer exceeds array dimensions // not required anymore when pins instead of names are transferred to the UI - if (command == 0) // just to be sure, configLength should also be 0 + uint16_t length = MFeeprom.get_length(); + char temp = 0; + uint16_t adrPin = 0; + uint16_t adrType = 0; + uint16_t adrConfig = 0; + + if (command == 0) // just to be sure, configLength should also be 0 return; do // go through the EEPROM until it is NULL terminated @@ -251,43 +266,43 @@ void readConfig() break; case kTypeOutput: - params[0] = readUintFromEEPROM(&addreeprom); // Pin number + params[0] = readUintFromEEPROM(&addreeprom); // Pin number Output::Add(params[0]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #if MF_SEGMENT_SUPPORT == 1 case kTypeLedSegment: - params[0] = readUintFromEEPROM(&addreeprom); // Pin Data number - params[1] = readUintFromEEPROM(&addreeprom); // Pin CS number - params[2] = readUintFromEEPROM(&addreeprom); // Pin CLK number - params[3] = readUintFromEEPROM(&addreeprom); // brightness - params[4] = readUintFromEEPROM(&addreeprom); // number of modules + params[0] = readUintFromEEPROM(&addreeprom); // Pin Data number + params[1] = readUintFromEEPROM(&addreeprom); // Pin CS number + params[2] = readUintFromEEPROM(&addreeprom); // Pin CLK number + params[3] = readUintFromEEPROM(&addreeprom); // brightness + params[4] = readUintFromEEPROM(&addreeprom); // number of modules LedSegment::Add(params[0], params[1], params[2], params[4], params[3]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #endif #if MF_STEPPER_SUPPORT == 1 case kTypeStepperDeprecated1: // this is for backwards compatibility - params[0] = readUintFromEEPROM(&addreeprom); // Pin1 number - params[1] = readUintFromEEPROM(&addreeprom); // Pin2 number - params[2] = readUintFromEEPROM(&addreeprom); // Pin3 number - params[3] = readUintFromEEPROM(&addreeprom); // Pin4 number - params[4] = readUintFromEEPROM(&addreeprom); // Button number + params[0] = readUintFromEEPROM(&addreeprom); // Pin1 number + params[1] = readUintFromEEPROM(&addreeprom); // Pin2 number + params[2] = readUintFromEEPROM(&addreeprom); // Pin3 number + params[3] = readUintFromEEPROM(&addreeprom); // Pin4 number + params[4] = readUintFromEEPROM(&addreeprom); // Button number Stepper::Add(params[0], params[1], params[2], params[3], 0); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; case kTypeStepperDeprecated2: - params[0] = readUintFromEEPROM(&addreeprom); // Pin1 number - params[1] = readUintFromEEPROM(&addreeprom); // Pin2 number - params[2] = readUintFromEEPROM(&addreeprom); // Pin3 number - params[3] = readUintFromEEPROM(&addreeprom); // Pin4 number - params[4] = readUintFromEEPROM(&addreeprom); // Button number + params[0] = readUintFromEEPROM(&addreeprom); // Pin1 number + params[1] = readUintFromEEPROM(&addreeprom); // Pin2 number + params[2] = readUintFromEEPROM(&addreeprom); // Pin3 number + params[3] = readUintFromEEPROM(&addreeprom); // Pin4 number + params[4] = readUintFromEEPROM(&addreeprom); // Button number Stepper::Add(params[0], params[1], params[2], params[3], params[4]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; case kTypeStepper: @@ -302,15 +317,15 @@ void readConfig() // there is an additional 9th parameter stored in the config (profileID) which is not needed in the firmware // and therefor not read in, it is just skipped like the name with reading until end of command Stepper::Add(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #endif #if MF_SERVO_SUPPORT == 1 case kTypeServo: - params[0] = readUintFromEEPROM(&addreeprom); // Pin number + params[0] = readUintFromEEPROM(&addreeprom); // Pin number Servos::Add(params[0]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #endif @@ -319,7 +334,7 @@ void readConfig() params[1] = readUintFromEEPROM(&addreeprom); // Pin2 number Encoder::Add(params[0], params[1], 0, &nameBuffer[addrbuffer]); // MUST be before readNameFromEEPROM because readNameFromEEPROM returns the pointer for the NEXT Name copy_success = readNameFromEEPROM(&addreeprom, nameBuffer, &addrbuffer); // copy the NULL terminated name to nameBuffer and set to next free memory location - // copy_success = readEndCommandFromEEPROM(&addreeprom); // once the nameBuffer is not required anymore uncomment this line and delete the line before + // copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // once the nameBuffer is not required anymore uncomment this line and delete the line before break; case kTypeEncoder: @@ -328,16 +343,16 @@ void readConfig() params[2] = readUintFromEEPROM(&addreeprom); // type Encoder::Add(params[0], params[1], params[2], &nameBuffer[addrbuffer]); // MUST be before readNameFromEEPROM because readNameFromEEPROM returns the pointer for the NEXT Name copy_success = readNameFromEEPROM(&addreeprom, nameBuffer, &addrbuffer); // copy the NULL terminated name to to nameBuffer and set to next free memory location - // copy_success = readEndCommandFromEEPROM(&addreeprom); // once the nameBuffer is not required anymore uncomment this line and delete the line before + // copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // once the nameBuffer is not required anymore uncomment this line and delete the line before break; #if MF_LCD_SUPPORT == 1 case kTypeLcdDisplayI2C: - params[0] = readUintFromEEPROM(&addreeprom); // address - params[1] = readUintFromEEPROM(&addreeprom); // columns - params[2] = readUintFromEEPROM(&addreeprom); // lines + params[0] = readUintFromEEPROM(&addreeprom); // address + params[1] = readUintFromEEPROM(&addreeprom); // columns + params[2] = readUintFromEEPROM(&addreeprom); // lines LCDDisplay::Add(params[0], params[1], params[2]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #endif @@ -347,18 +362,18 @@ void readConfig() params[1] = readUintFromEEPROM(&addreeprom); // sensitivity Analog::Add(params[0], &nameBuffer[addrbuffer], params[1]); // MUST be before readNameFromEEPROM because readNameFromEEPROM returns the pointer for the NEXT Name copy_success = readNameFromEEPROM(&addreeprom, nameBuffer, &addrbuffer); // copy the NULL terminated name to to nameBuffer and set to next free memory location - // copy_success = readEndCommandFromEEPROM(&addreeprom); // once the nameBuffer is not required anymore uncomment this line and delete the line before + // copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // once the nameBuffer is not required anymore uncomment this line and delete the line before break; #endif #if MF_OUTPUT_SHIFTER_SUPPORT == 1 case kTypeOutputShifter: - params[0] = readUintFromEEPROM(&addreeprom); // latch Pin - params[1] = readUintFromEEPROM(&addreeprom); // clock Pin - params[2] = readUintFromEEPROM(&addreeprom); // data Pin - params[3] = readUintFromEEPROM(&addreeprom); // number of daisy chained modules + params[0] = readUintFromEEPROM(&addreeprom); // latch Pin + params[1] = readUintFromEEPROM(&addreeprom); // clock Pin + params[2] = readUintFromEEPROM(&addreeprom); // data Pin + params[3] = readUintFromEEPROM(&addreeprom); // number of daisy chained modules OutputShifter::Add(params[0], params[1], params[2], params[3]); - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name break; #endif @@ -370,7 +385,7 @@ void readConfig() params[3] = readUintFromEEPROM(&addreeprom); // number of daisy chained modules InputShifter::Add(params[0], params[1], params[2], params[3], &nameBuffer[addrbuffer]); copy_success = readNameFromEEPROM(&addreeprom, nameBuffer, &addrbuffer); // copy the NULL terminated name to to nameBuffer and set to next free memory location - // copy_success = readEndCommandFromEEPROM(&addreeprom); // once the nameBuffer is not required anymore uncomment this line and delete the line before + // copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // once the nameBuffer is not required anymore uncomment this line and delete the line before break; #endif @@ -404,8 +419,30 @@ void readConfig() break; #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 + case kTypeCustomDevice: + adrType = addreeprom; // first location of custom Type in EEPROM + copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); + if (!copy_success) + break; + + adrPin = addreeprom; // first location of custom pins in EEPROM + copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); + if (!copy_success) + break; + + adrConfig = addreeprom; // first location of custom config in EEPROM + copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); + if (copy_success) { + CustomDevice::Add(adrPin, adrType, adrConfig); + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of command + } + // cmdMessenger.sendCmd(kDebug, F("CustomDevice loaded")); + break; +#endif + default: - copy_success = readEndCommandFromEEPROM(&addreeprom); // check EEPROM until end of name + copy_success = readEndCommandFromEEPROM(&addreeprom, ':'); // check EEPROM until end of name } command = readUintFromEEPROM(&addreeprom); } while (command && copy_success); diff --git a/src/MF_CustomDevice/CustomDevice.cpp b/src/MF_CustomDevice/CustomDevice.cpp new file mode 100644 index 00000000..ec74a5ed --- /dev/null +++ b/src/MF_CustomDevice/CustomDevice.cpp @@ -0,0 +1,86 @@ +#include +#include "CustomDevice.h" +#include "MFCustomDevice.h" +#include "commandmessenger.h" +#include "MFBoards.h" +#include "allocateMem.h" + +/* ********************************************************************************** + Normally nothing has to be changed in this file + It handles one or multiple custom devices +********************************************************************************** */ +namespace CustomDevice +{ + uint8_t CustomDeviceRegistered = 0; + MFCustomDevice *customDevice[MAX_CUSTOM_DEVICES]; + + void Add(uint16_t adrPin, uint16_t adrType, uint16_t adrConfig) + { + if (CustomDeviceRegistered == MAX_CUSTOM_DEVICES) + return; + if (!FitInMemory(sizeof(MFCustomDevice))) { + // Error Message to Connector + cmdMessenger.sendCmd(kStatus, F("Custom Device does not fit in Memory")); + return; + } + customDevice[CustomDeviceRegistered] = new (allocateMemory(sizeof(MFCustomDevice))) MFCustomDevice(adrPin, adrType, adrConfig); + CustomDeviceRegistered++; +#ifdef DEBUG2CMDMESSENGER + cmdMessenger.sendCmd(kStatus, F("Added Stepper Setpoint")); +#endif + } + + /* ********************************************************************************** + All custom devives gets unregistered if a new config gets uploaded. + The Clear() function from every registerd custom device will be called. + Keep it as it is, mostly nothing must be changed + ********************************************************************************** */ + void Clear() + { + for (int i = 0; i != CustomDeviceRegistered; i++) { + customDevice[i]->detach(); + } + CustomDeviceRegistered = 0; +#ifdef DEBUG2CMDMESSENGER + cmdMessenger.sendCmd(kStatus, F("Cleared Stepper Setpoint")); +#endif + } + + /* ********************************************************************************** + Within in loop() the update() function is called regularly + Within the loop() you can define a time delay where this function gets called + or as fast as possible. See comments in loop() + The update() function from every registerd custom device will be called. + It is only needed if you have to update your custom device without getting + new values from the connector. Otherwise just make a return; + ********************************************************************************** */ + void update() + { + for (int i = 0; i != CustomDeviceRegistered; i++) { + customDevice[i]->update(); + } + } + + /* ********************************************************************************** + If an output for the custom device is defined in the connector, + this function gets called when a new value is available. + In this case the connector sends a messageID followed by a string which is not longer + than 90 Byte (!!check the length of the string!!) limited by the commandMessenger. + The messageID is used to mark the value which has changed. This reduced the serial + communication as not all values has to be send in one (big) string (like for the LCD) + The OnSet() function from every registerd custom device will be called. + ********************************************************************************** */ + void OnSet() + { + int16_t device = cmdMessenger.readInt16Arg(); // get the device number + if (device >= CustomDeviceRegistered) // and do nothing if this device is not registered + return; + int16_t messageID = cmdMessenger.readInt16Arg(); // get the messageID number + char *output = cmdMessenger.readStringArg(); // get the pointer to the new raw string + cmdMessenger.unescape(output); // and unescape the string if escape characters are used + customDevice[device]->set(messageID, output); // send the string to your custom device + + setLastCommandMillis(); + } + +} // end of namespace \ No newline at end of file diff --git a/src/MF_CustomDevice/CustomDevice.h b/src/MF_CustomDevice/CustomDevice.h new file mode 100644 index 00000000..a7f4fbc3 --- /dev/null +++ b/src/MF_CustomDevice/CustomDevice.h @@ -0,0 +1,9 @@ +#pragma once + +namespace CustomDevice +{ + void Add(uint16_t adrPin, uint16_t adrType, uint16_t adrConfig); + void Clear(); + void update(); + void OnSet(); +} \ No newline at end of file diff --git a/src/commandmessenger.h b/src/commandmessenger.h index 4e3382f7..eddfd1a3 100644 --- a/src/commandmessenger.h +++ b/src/commandmessenger.h @@ -44,6 +44,7 @@ enum { kInputShifterChange, // 29 kDigInMuxChange, // 30 kSetStepperSpeedAccel, // 31 + kSetCustomDevice, // 32 kDebug = 0xFF // 255 }; diff --git a/src/config.h b/src/config.h index a882abad..d1d6d5f7 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,8 @@ enum { kTypeInputShifter, // 12 Input shift register support (example: 74HC165) kTypeMuxDriver, // 13 Multiplexer selector support (generates select outputs) kTypeDigInMux, // 14 Digital input multiplexer support (example: 74HCT4067, 74HCT4051) - kTypeStepper // new stepper type with settings for backlash and deactivate output + kTypeStepper, // 15 new stepper type with settings for backlash and deactivate output + kTypeCustomDevice // 16 Custom Device }; void loadConfig(void); diff --git a/src/mobiflight.cpp b/src/mobiflight.cpp index 737df09a..f462a5fa 100644 --- a/src/mobiflight.cpp +++ b/src/mobiflight.cpp @@ -32,6 +32,9 @@ #if MF_DIGIN_MUX_SUPPORT == 1 #include "DigInMux.h" #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 +#include "CustomDevice.h" +#endif #define MF_BUTTON_DEBOUNCE_MS 10 // time between updating the buttons #define MF_ENCODER_DEBOUNCE_MS 1 // time between encoder updates @@ -67,6 +70,9 @@ typedef struct { #if MF_DIGIN_MUX_SUPPORT == 1 uint32_t DigInMux = 0; #endif +#if MF_CUSTOMDEVICE_SUPPORT == 1 + uint32_t CustomDevice = 0; +#endif } lastUpdate_t; lastUpdate_t lastUpdate; @@ -196,6 +202,15 @@ void loop() #if MF_DIGIN_MUX_SUPPORT == 1 timedUpdate(DigInMux::read, &lastUpdate.DigInMux, MF_INMUX_POLL_MS); #endif + +#if MF_CUSTOMDEVICE_SUPPORT == 1 && defined(MF_CUSTOMDEVICE_HAS_UPDATE) +#ifdef MF_CUSTOMDEVICE_POLL_MS + timedUpdate(CustomDevice::update, &lastUpdate.CustomDevice, MF_CUSTOMDEVICE_POLL_MS); +#else + CustomDevice::update(); +#endif +#endif + // lcds, outputs, outputshifters, segments do not need update } } From 048685073a8a08d17d9d545b06c12c5660c95bfc Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Tue, 19 Sep 2023 10:39:39 +0200 Subject: [PATCH 2/9] download custom devices from my repo to get PR compile --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 698c7aaf..1b92c2cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Checkout component library uses: actions/checkout@v3 with: - repository: MobiFlight/MobiFlight-CustomDevices + repository: elral/MobiFlight-CustomDevices path: CustomDevices - name: Run PlatformIO diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e94b35f..83db2c39 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: - name: Checkout component library uses: actions/checkout@v3 with: - repository: MobiFlight/MobiFlight-CustomDevices + repository: elral/MobiFlight-CustomDevices path: CustomDevices - name: Extract build version From 4347b35cdfcc8d306a0df2d60d17d39a3583792e Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:27:06 +0200 Subject: [PATCH 3/9] wrong name of task to execute --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b92c2cb..60b4099f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio - - name: Checkout component library + - name: Checkout custom devices uses: actions/checkout@v3 with: repository: elral/MobiFlight-CustomDevices diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83db2c39..4a550135 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio - - name: Checkout component library + - name: Checkout custom devices uses: actions/checkout@v3 with: repository: elral/MobiFlight-CustomDevices From 7b95d33c0103fcbc799eb63fa1932b89da0a27a3 Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Wed, 20 Sep 2023 06:31:07 +0200 Subject: [PATCH 4/9] copy all .hex/.uf2 files to .zip file --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60b4099f..64a4c747 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,5 +49,5 @@ jobs: with: name: firmware path: | - .pio/build/**/mobiflight*.hex - .pio/build/**/mobiflight*.uf2 + .pio/build/**/*.hex + .pio/build/**/*.uf2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a550135..190ff14e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,8 +52,8 @@ jobs: with: name: firmware path: | - .pio/build/**/mobiflight*.hex - .pio/build/**/mobiflight*.uf2 + .pio/build/**/*.hex + .pio/build/**/*.uf2 - name: Release uses: softprops/action-gh-release@v1 @@ -61,5 +61,5 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: | - .pio/build/**/mobiflight*.hex - .pio/build/**/mobiflight*.uf2 + .pio/build/**/*.hex + .pio/build/**/*.uf2 From 442cd24f00bf810468d99ecf6a2261256a4d5c3c Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Wed, 20 Sep 2023 20:12:50 +0200 Subject: [PATCH 5/9] avoid warnings of unused variables --- src/Config.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 9b291799..fa0b7dc1 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -247,12 +247,6 @@ void readConfig() bool copy_success = true; // will be set to false if copying input names to nameBuffer exceeds array dimensions // not required anymore when pins instead of names are transferred to the UI - uint16_t length = MFeeprom.get_length(); - char temp = 0; - uint16_t adrPin = 0; - uint16_t adrType = 0; - uint16_t adrConfig = 0; - if (command == 0) // just to be sure, configLength should also be 0 return; @@ -420,18 +414,18 @@ void readConfig() #endif #if MF_CUSTOMDEVICE_SUPPORT == 1 - case kTypeCustomDevice: - adrType = addreeprom; // first location of custom Type in EEPROM + case kTypeCustomDevice: { + uint16_t adrType = addreeprom; // first location of custom Type in EEPROM copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); if (!copy_success) break; - adrPin = addreeprom; // first location of custom pins in EEPROM + uint16_t adrPin = addreeprom; // first location of custom pins in EEPROM copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); if (!copy_success) break; - adrConfig = addreeprom; // first location of custom config in EEPROM + uint16_t adrConfig = addreeprom; // first location of custom config in EEPROM copy_success = readEndCommandFromEEPROM(&addreeprom, '.'); if (copy_success) { CustomDevice::Add(adrPin, adrType, adrConfig); @@ -439,6 +433,7 @@ void readConfig() } // cmdMessenger.sendCmd(kDebug, F("CustomDevice loaded")); break; + } #endif default: From 63d2c48c9110494213f1d25467782df841b6905e Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Thu, 21 Sep 2023 05:57:43 +0200 Subject: [PATCH 6/9] template must not be build --- platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b5bfea4c..7d889d16 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,6 @@ [platformio] ; include custom environments to be build extra_configs = - ./CustomDevices/_template/MyCustomDevice_platformio.ini ./CustomDevices/KAV_Simulation/EFIS_FCU/EFIS_FCU_platformio.ini ./CustomDevices/Mobiflight/GNC255/GNC255_platformio.ini ./CustomDevices/Mobiflight/TM1637/TM1637_platformio.ini From f20f703111f8a30c750a1feca353f6634e5fce9c Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Thu, 21 Sep 2023 06:29:17 +0200 Subject: [PATCH 7/9] don't use backslash in file path from script --- get_CustomDevices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get_CustomDevices.py b/get_CustomDevices.py index c5bc63e9..45e471cc 100644 --- a/get_CustomDevices.py +++ b/get_CustomDevices.py @@ -9,4 +9,4 @@ env.Execute("git clone --depth 100 https://github.com/elral/MobiFlight-CustomDevices $PROJECT_DIR/CustomDevices") else: print ("Checking for Mobiflight-CustomDevices repo updates ... ") - env.Execute("git --work-tree=$PROJECT_DIR\CustomDevices --git-dir=$PROJECT_DIR\CustomDevices\.git pull origin main --depth 100") + env.Execute("git --work-tree=$PROJECT_DIR/CustomDevices --git-dir=$PROJECT_DIR/CustomDevices/.git pull origin main --depth 100") From 8d557546bc30451095b5ad0e2015d539eb56a127 Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Sat, 21 Oct 2023 22:24:10 +0200 Subject: [PATCH 8/9] change repo from from elral to MobiFlight --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64a4c747..f460a11a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Checkout custom devices uses: actions/checkout@v3 with: - repository: elral/MobiFlight-CustomDevices + repository: MobiFlight/MobiFlight-CustomDevices path: CustomDevices - name: Run PlatformIO diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 190ff14e..2b99dde0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: - name: Checkout custom devices uses: actions/checkout@v3 with: - repository: elral/MobiFlight-CustomDevices + repository: MobiFlight/MobiFlight-CustomDevices path: CustomDevices - name: Extract build version From 1a00deb554d1cd3f681c25be3a831b71bdebaf09 Mon Sep 17 00:00:00 2001 From: elral <3263285+elral@users.noreply.github.com> Date: Sun, 22 Oct 2023 08:45:16 +0200 Subject: [PATCH 9/9] change repo from elral to Mobiflight --- get_CustomDevices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get_CustomDevices.py b/get_CustomDevices.py index 45e471cc..1e1befd3 100644 --- a/get_CustomDevices.py +++ b/get_CustomDevices.py @@ -6,7 +6,7 @@ if not os.path.exists(CUSTOMDEVICES_DIR): print ("Cloning Mobiflight-CustomDevices repo ... ") - env.Execute("git clone --depth 100 https://github.com/elral/MobiFlight-CustomDevices $PROJECT_DIR/CustomDevices") + env.Execute("git clone --depth 100 https://github.com/MobiFlight/MobiFlight-CustomDevices $PROJECT_DIR/CustomDevices") else: print ("Checking for Mobiflight-CustomDevices repo updates ... ") env.Execute("git --work-tree=$PROJECT_DIR/CustomDevices --git-dir=$PROJECT_DIR/CustomDevices/.git pull origin main --depth 100")