From 8d4b004b65fa2e7a19d4fe117c48886cddd73e7e Mon Sep 17 00:00:00 2001 From: Michael Dewberry Date: Sun, 27 Aug 2023 19:10:05 -0400 Subject: [PATCH] Add teletype 4 and 5 firmware, add switching menu --- .gitmodules | 6 +- Makefile | 3 +- firmware/mock_hardware/mock_hardware_api.h | 2 +- .../modules/teletype/adapter_teletype.c | 11 +++ .../modules/teletype/usb_disk_mode.c | 10 +++ firmware/teletype | 1 - firmware/teletype.mk | 76 +++++++++---------- firmware/teletype4 | 1 + firmware/teletype5 | 1 + src/ansible/AnsibleModule.hpp | 2 +- src/common/core/FirmwareManager.cpp | 7 +- src/common/core/FirmwareManager.hpp | 6 +- src/common/core/LibAVR32Module.cpp | 26 +++++-- src/common/core/LibAVR32Module.hpp | 8 +- src/common/core/LibAVR32ModuleWidget.cpp | 35 +++++++++ src/earthsea/EarthseaModule.hpp | 2 +- src/meadowphysics/MeadowphysicsModule.hpp | 2 +- src/teletype/TeletypeModule.cpp | 2 +- src/whitewhale/WhiteWhaleModule.hpp | 2 +- 19 files changed, 143 insertions(+), 60 deletions(-) create mode 100644 firmware/mock_hardware/modules/teletype/usb_disk_mode.c delete mode 160000 firmware/teletype create mode 160000 firmware/teletype4 create mode 160000 firmware/teletype5 diff --git a/.gitmodules b/.gitmodules index f072541..da1e433 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/Dewb/whitewhale branch = vcvrack_pr [submodule "firmware/teletype"] - path = firmware/teletype + path = firmware/teletype4 url = https://github.com/Dewb/teletype branch = vcvrack-4.0.0 [submodule "firmware/meadowphysics"] @@ -17,3 +17,7 @@ [submodule "firmware/ansible"] path = firmware/ansible url = https://github.com/Dewb/ansible +[submodule "firmware/firmware/teletype-5"] + path = firmware/teletype5 + url = https://github.com/Dewb/teletype + branch = vcvrack-5 diff --git a/Makefile b/Makefile index 1c58362..71008ed 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,8 @@ firmware-build: firmware/*.mk firmware/**/*.c firmware/**/*.h firmware/**/**/*.r cd firmware && $(MAKE) -f whitewhale.mk cd firmware && $(MAKE) -f meadowphysics.mk cd firmware && $(MAKE) -f earthsea.mk - cd firmware && $(MAKE) -f teletype.mk + cd firmware && $(MAKE) -f teletype.mk TARGET_NAME=teletype4 + cd firmware && $(MAKE) -f teletype.mk TARGET_NAME=teletype5 cd firmware && $(MAKE) -f ansible.mk firmware-clean: diff --git a/firmware/mock_hardware/mock_hardware_api.h b/firmware/mock_hardware/mock_hardware_api.h index a63d920..c1fb4fe 100644 --- a/firmware/mock_hardware/mock_hardware_api.h +++ b/firmware/mock_hardware/mock_hardware_api.h @@ -1,5 +1,5 @@ #ifndef MOCK_API_SKIP_TYPES -#include "../teletype/src/serializer.h" +#include "../teletype4/src/serializer.h" #include #include #endif diff --git a/firmware/mock_hardware/modules/teletype/adapter_teletype.c b/firmware/mock_hardware/modules/teletype/adapter_teletype.c index bf2cf04..f06a80e 100644 --- a/firmware/mock_hardware/modules/teletype/adapter_teletype.c +++ b/firmware/mock_hardware/modules/teletype/adapter_teletype.c @@ -1,5 +1,6 @@ #include "mock_hardware_api.h" #include "mock_hardware_api_private.h" +#include "flashc.h" #include "module/edit_mode.h" #include "module/flash.h" @@ -11,6 +12,16 @@ #include "src/teletype_io.h" #include "types.h" +extern nvram_data_t f; +extern scene_state_t scene_state; + +#ifdef DECLARE_NVRAM +DECLARE_NVRAM(&f, sizeof(nvram_data_t)) +#endif +#ifdef DECLARE_VRAM +DECLARE_VRAM(&scene_state, sizeof(scene_state)) +#endif + void clock_null(uint8_t phase) { } typedef void (*clock_pulse_t)(uint8_t phase); volatile uint8_t clock_external; diff --git a/firmware/mock_hardware/modules/teletype/usb_disk_mode.c b/firmware/mock_hardware/modules/teletype/usb_disk_mode.c new file mode 100644 index 0000000..e189ea8 --- /dev/null +++ b/firmware/mock_hardware/modules/teletype/usb_disk_mode.c @@ -0,0 +1,10 @@ +#include + +void handler_usb_PollADC(int32_t data) { +} + +void handler_usb_Front(int32_t data) { +} + +void handler_usb_ScreenRefresh(int32_t data) { +} \ No newline at end of file diff --git a/firmware/teletype b/firmware/teletype deleted file mode 160000 index efd6503..0000000 --- a/firmware/teletype +++ /dev/null @@ -1 +0,0 @@ -Subproject commit efd6503778573c0268886ed8758468d61ebaceab diff --git a/firmware/teletype.mk b/firmware/teletype.mk index 0f326da..50653c3 100644 --- a/firmware/teletype.mk +++ b/firmware/teletype.mk @@ -1,59 +1,57 @@ -TARGET_NAME := teletype - FLAGS += \ -D__AVR32_UC3B0512__ \ -Imock_hardware \ -Imock_hardware/include \ - -Iteletype/libavr32/src \ - -Iteletype/libavr32/src/usb/midi \ - -Iteletype/libavr32/src/usb/hid \ - -Iteletype/libavr32/src/usb/cdc \ - -Iteletype/libavr32/src/usb/ftdi \ - -Iteletype/libavr32/conf \ - -Iteletype/libavr32/conf/teletype \ - -Iteletype/libavr32/asf/common/services/usb \ - -Iteletype/libavr32/asf/common/services/usb/uhc \ - -Iteletype/libavr32/asf/common/services/usb/class/hid \ - -Iteletype/src \ - -Iteletype/src/ops \ - -Iteletype/ \ + -I$(TARGET_NAME)/libavr32/src \ + -I$(TARGET_NAME)/libavr32/src/usb/midi \ + -I$(TARGET_NAME)/libavr32/src/usb/hid \ + -I$(TARGET_NAME)/libavr32/src/usb/cdc \ + -I$(TARGET_NAME)/libavr32/src/usb/ftdi \ + -I$(TARGET_NAME)/libavr32/conf \ + -I$(TARGET_NAME)/libavr32/conf/teletype \ + -I$(TARGET_NAME)/libavr32/asf/common/services/usb \ + -I$(TARGET_NAME)/libavr32/asf/common/services/usb/uhc \ + -I$(TARGET_NAME)/libavr32/asf/common/services/usb/class/hid \ + -I$(TARGET_NAME)/src \ + -I$(TARGET_NAME)/src/ops \ + -I$(TARGET_NAME)/ \ SOURCES = \ - $(wildcard teletype/src/*.c) \ - teletype/src/scanner.c \ - teletype/src/match_token.c \ - teletype/module/gitversion.c \ - $(wildcard teletype/src/ops/*.c) \ - $(wildcard teletype/module/*.c) \ - teletype/libavr32/src/events.c \ - teletype/libavr32/src/timers.c \ - teletype/libavr32/src/util.c \ - teletype/libavr32/src/font.c \ - teletype/libavr32/src/kbd.c \ - teletype/libavr32/src/region.c \ - teletype/libavr32/src/random.c \ - teletype/libavr32/src/usb/hid/hid.c \ - teletype/libavr32/src/music.c \ - teletype/libavr32/src/midi_common.c \ - $(wildcard teletype/libavr32/src/euclidean/*.c) \ + $(wildcard $(TARGET_NAME)/src/*.c) \ + $(TARGET_NAME)/src/scanner.c \ + $(TARGET_NAME)/src/match_token.c \ + $(TARGET_NAME)/module/gitversion.c \ + $(wildcard $(TARGET_NAME)/src/ops/*.c) \ + $(wildcard $(TARGET_NAME)/module/*.c) \ + $(TARGET_NAME)/libavr32/src/events.c \ + $(TARGET_NAME)/libavr32/src/timers.c \ + $(TARGET_NAME)/libavr32/src/util.c \ + $(TARGET_NAME)/libavr32/src/font.c \ + $(TARGET_NAME)/libavr32/src/kbd.c \ + $(TARGET_NAME)/libavr32/src/region.c \ + $(TARGET_NAME)/libavr32/src/random.c \ + $(TARGET_NAME)/libavr32/src/usb/hid/hid.c \ + $(TARGET_NAME)/libavr32/src/music.c \ + $(TARGET_NAME)/libavr32/src/midi_common.c \ + $(wildcard $(TARGET_NAME)/libavr32/src/euclidean/*.c) \ $(wildcard mock_hardware/*.c) \ $(wildcard mock_hardware/common/*.c) \ $(wildcard mock_hardware/modules/teletype/*.c) \ -SOURCES := $(filter-out teletype/module/usb_disk_mode.c, $(SOURCES)) +SOURCES := $(filter-out $(TARGET_NAME)/module/usb_disk_mode.c, $(SOURCES)) RAGEL ?= ragel # Add a rule to build match_token.c from match_token.rl -teletype/src/match_token.c: teletype/src/match_token.rl - $(RAGEL) -C -G2 teletype/src/match_token.rl -o teletype/src/match_token.c +$(TARGET_NAME)/src/match_token.c: $(TARGET_NAME)/src/match_token.rl + $(RAGEL) -C -G2 $(TARGET_NAME)/src/match_token.rl -o $(TARGET_NAME)/src/match_token.c # Add a rule to build scanner.c from scanner.rl -teletype/src/scanner.c: teletype/src/scanner.rl - $(RAGEL) -C -G2 teletype/src/scanner.rl -o teletype/src/scanner.c +$(TARGET_NAME)/src/scanner.c: $(TARGET_NAME)/src/scanner.rl + $(RAGEL) -C -G2 $(TARGET_NAME)/src/scanner.rl -o $(TARGET_NAME)/src/scanner.c # Add the git commit id to a file for use when printing out the version -teletype/module/gitversion.c: teletype - echo "const char *git_version = \"$(shell cut -d '-' -f 1 <<< $(shell cd teletype; git describe --tags | cut -c 1-)) $(shell cd teletype; git describe --always --dirty --exclude '*' | tr '[a-z]' '[A-Z]')\";" > $@ +$(TARGET_NAME)/module/gitversion.c: $(TARGET_NAME) + echo "const char *git_version = \"$(shell cut -d '-' -f 1 <<< $(shell cd $(TARGET_NAME); git describe --tags | cut -c 1-)) $(shell cd $(TARGET_NAME); git describe --always --dirty --exclude '*' | tr '[a-z]' '[A-Z]')\";" > $@ include common.mk diff --git a/firmware/teletype4 b/firmware/teletype4 new file mode 160000 index 0000000..407c6e7 --- /dev/null +++ b/firmware/teletype4 @@ -0,0 +1 @@ +Subproject commit 407c6e720ad2b080917f266c98996014e1671d36 diff --git a/firmware/teletype5 b/firmware/teletype5 new file mode 160000 index 0000000..75e3b7d --- /dev/null +++ b/firmware/teletype5 @@ -0,0 +1 @@ +Subproject commit 75e3b7d8f69b229936d77845a8a704e9b8e74652 diff --git a/src/ansible/AnsibleModule.hpp b/src/ansible/AnsibleModule.hpp index 4a1f560..8e3c3b2 100644 --- a/src/ansible/AnsibleModule.hpp +++ b/src/ansible/AnsibleModule.hpp @@ -54,7 +54,7 @@ struct AnsibleModule : LibAVR32Module rack::dsp::SchmittTrigger inputTriggers[2]; AnsibleModule() - : LibAVR32Module("ansible") + : LibAVR32Module("ansible", "ansible") { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configButton(KEY1_PARAM, "KEY 1"); diff --git a/src/common/core/FirmwareManager.cpp b/src/common/core/FirmwareManager.cpp index 9fa9986..61cd2c1 100644 --- a/src/common/core/FirmwareManager.cpp +++ b/src/common/core/FirmwareManager.cpp @@ -230,16 +230,17 @@ FirmwareManager::~FirmwareManager() delete impl; } -bool FirmwareManager::load(std::string modulePath) +bool FirmwareManager::load(std::string firmwareName) { delete impl; impl = new FirmwareManagerImpl(); - if (!impl->load(modulePath)) + if (!impl->load(firmwareName)) { impl = nullptr; - WARN("Could not load firmware %s", modulePath.c_str()); + WARN("Could not load firmware %s", firmwareName.c_str()); return false; } + loadedName = firmwareName; return true; } diff --git a/src/common/core/FirmwareManager.hpp b/src/common/core/FirmwareManager.hpp index 603168e..cc84dc1 100644 --- a/src/common/core/FirmwareManager.hpp +++ b/src/common/core/FirmwareManager.hpp @@ -16,9 +16,11 @@ struct FirmwareManager FirmwareManager(); ~FirmwareManager(); - bool load(std::string firmwarePath); + bool load(std::string firmwareName); void unload(); + const std::string& getLoadedName() const { return loadedName; } + void setClockPeriod(float seconds); void advanceClock(float seconds); @@ -30,4 +32,6 @@ struct FirmwareManager #include "mock_hardware_api.h" struct FirmwareManagerImpl* impl; +protected: + std::string loadedName; }; \ No newline at end of file diff --git a/src/common/core/LibAVR32Module.cpp b/src/common/core/LibAVR32Module.cpp index b836bbb..65d1ba0 100644 --- a/src/common/core/LibAVR32Module.cpp +++ b/src/common/core/LibAVR32Module.cpp @@ -3,10 +3,12 @@ #include "base64.h" #include -LibAVR32Module::LibAVR32Module(std::string firmwareName) +LibAVR32Module::LibAVR32Module(std::string firmwarePrefix, std::string defaultFirmwareName) : lastConnectedDeviceId("") , currentConnectedDeviceId("") -, firmwareName(firmwareName) +, firmwarePrefix(firmwarePrefix) +, firmwareName(defaultFirmwareName) +, defaultFirmwareName(defaultFirmwareName) , usbParamId(-1) , theme(GridTheme::Yellow) { @@ -274,16 +276,21 @@ void LibAVR32Module::readSerialMessages() } } -void LibAVR32Module::requestReloadFirmware(bool preserveMemory) +void LibAVR32Module::requestReloadFirmware(bool preserveMemory, const std::string& firmwareName) { - audioThreadActions.push([this, preserveMemory]() { this->reloadFirmware(preserveMemory); }); + audioThreadActions.push([this, preserveMemory, firmwareName]() { this->reloadFirmware(preserveMemory, firmwareName); }); } -void LibAVR32Module::reloadFirmware(bool preserveMemory) +void LibAVR32Module::reloadFirmware(bool preserveMemory, const std::string& newName) { void *data, *nvram_copy, *vram_copy = 0; uint32_t nvram_size, vram_size = 0; + firmwareName = newName.empty() ? firmware.getLoadedName() : newName; + if (firmwareName != firmware.getLoadedName()) { + preserveMemory = false; + } + if (preserveMemory) { firmware.readNVRAM(&data, &nvram_size); nvram_copy = malloc(nvram_size); @@ -351,6 +358,7 @@ json_t* LibAVR32Module::dataToJson() } json_t* rootJ = json_object(); + json_object_set_new(rootJ, "firmwareName", json_string(firmwareName.c_str())); json_object_set_new(rootJ, "connectedDeviceId", json_string(deviceId.c_str())); json_object_set_new(rootJ, "connectionOwned", json_boolean(connectionOwned)); json_object_set_new(rootJ, "inputRate", json_integer(inputRate)); @@ -376,6 +384,14 @@ json_t* LibAVR32Module::dataToJson() void LibAVR32Module::dataFromJson(json_t* rootJ) { + json_t* jsonFirmwareName = json_object_get(rootJ, "firmwareName"); + std::string newFirmwareName = jsonFirmwareName ? json_string_value(jsonFirmwareName) : defaultFirmwareName; + + if (newFirmwareName != firmwareName) + { + reloadFirmware(false, newFirmwareName); + } + json_t* id = json_object_get(rootJ, "connectedDeviceId"); if (id) { diff --git a/src/common/core/LibAVR32Module.hpp b/src/common/core/LibAVR32Module.hpp index ba0b954..ca79be2 100644 --- a/src/common/core/LibAVR32Module.hpp +++ b/src/common/core/LibAVR32Module.hpp @@ -34,7 +34,7 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer { FirmwareManager firmware; - LibAVR32Module(std::string firmwareName); + LibAVR32Module(std::string firmwarePrefix, std::string defaultFirmwareName); ~LibAVR32Module(); // Rack module methods @@ -58,7 +58,7 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer void userToggleGridConnection(Grid* grid); virtual void readSerialMessages(); - void requestReloadFirmware(bool preserveMemory); + void requestReloadFirmware(bool preserveMemory, const std::string& firmwareName = ""); float dacToVolts(uint16_t adc); uint16_t voltsToAdc(float volts); @@ -67,7 +67,9 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer std::string currentConnectedDeviceId; bool connectionOwned; + std::string firmwarePrefix; std::string firmwareName; + std::string defaultFirmwareName; int inputRate; int outputRate; @@ -77,7 +79,7 @@ struct LibAVR32Module : rack::engine::Module, GridConsumer virtual uint8_t* getScreenBuffer() { return 0; } protected: - void reloadFirmware(bool preserveMemory); + void reloadFirmware(bool preserveMemory, const std::string& newFirmware = ""); void toggleGridConnection(Grid* grid); Grid* gridConnection; diff --git a/src/common/core/LibAVR32ModuleWidget.cpp b/src/common/core/LibAVR32ModuleWidget.cpp index 6619851..2de8a76 100644 --- a/src/common/core/LibAVR32ModuleWidget.cpp +++ b/src/common/core/LibAVR32ModuleWidget.cpp @@ -31,6 +31,33 @@ struct ReloadFirmwareItem : rack::ui::MenuItem } }; +struct SwitchFirmwareItem : rack::ui::MenuItem +{ + LibAVR32Module* module; + + ui::Menu* createChildMenu() override + { + ui::Menu* menu = new ui::Menu; + + // TODO: populate this from looking in the firmware folder for binaries starting with the module basename + std::string names[] = { "teletype4", "teletype5" }; + + for (int i = 0; i < 2; i++) + { + menu->addChild(createCheckMenuItem( + names[i], + "", + [=]() + { return module->firmware.getLoadedName() == names[i]; }, + [=]() + { module->requestReloadFirmware(false, names[i]); } + )); + } + + return menu; + } +}; + struct ioRateItem : rack::ui::MenuItem { int* target = nullptr; @@ -91,6 +118,14 @@ struct FirmwareSubmenuItem : MenuItem menu->addChild(new MenuSeparator()); + // TODO: enable for other modules + if (m->firmwarePrefix == "teletype") { + menu->addChild(construct( + &MenuItem::text, "Switch Firmware", &MenuItem::rightText, RIGHT_ARROW, + &SwitchFirmwareItem::module, m + )); + } + auto reloadItem = new ReloadFirmwareItem(); reloadItem->text = "Reload & Restart"; reloadItem->module = m; diff --git a/src/earthsea/EarthseaModule.hpp b/src/earthsea/EarthseaModule.hpp index 0bf0dc5..55830f0 100644 --- a/src/earthsea/EarthseaModule.hpp +++ b/src/earthsea/EarthseaModule.hpp @@ -40,7 +40,7 @@ struct EarthseaModule : LibAVR32Module }; EarthseaModule() - : LibAVR32Module("earthsea") + : LibAVR32Module("earthsea", "earthsea") { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); diff --git a/src/meadowphysics/MeadowphysicsModule.hpp b/src/meadowphysics/MeadowphysicsModule.hpp index 4511dc4..ac395cb 100644 --- a/src/meadowphysics/MeadowphysicsModule.hpp +++ b/src/meadowphysics/MeadowphysicsModule.hpp @@ -50,7 +50,7 @@ struct MeadowphysicsModule : LibAVR32Module rack::dsp::SchmittTrigger clockTrigger; MeadowphysicsModule() - : LibAVR32Module("meadowphysics") + : LibAVR32Module("meadowphysics", "meadowphysics") { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configButton(BUTTON_PARAM, "PRESET"); diff --git a/src/teletype/TeletypeModule.cpp b/src/teletype/TeletypeModule.cpp index 17ceed4..10c39e1 100644 --- a/src/teletype/TeletypeModule.cpp +++ b/src/teletype/TeletypeModule.cpp @@ -32,7 +32,7 @@ struct TTParamQuantity : rack::engine::ParamQuantity }; TeletypeModule::TeletypeModule() -: LibAVR32Module("teletype") +: LibAVR32Module("teletype", "teletype4") , _iiDevice(this) , screenBuffer{} { diff --git a/src/whitewhale/WhiteWhaleModule.hpp b/src/whitewhale/WhiteWhaleModule.hpp index 7b17bfb..323fee4 100644 --- a/src/whitewhale/WhiteWhaleModule.hpp +++ b/src/whitewhale/WhiteWhaleModule.hpp @@ -47,7 +47,7 @@ struct WhiteWhaleModule : LibAVR32Module rack::dsp::SchmittTrigger clockTrigger; WhiteWhaleModule() - : LibAVR32Module("whitewhale") + : LibAVR32Module("whitewhale", "whitewhale") { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configButton(BUTTON_PARAM, "PRESET");