Skip to content

Commit

Permalink
Merge pull request #438 from 4ms/simulator-ext-plugin
Browse files Browse the repository at this point in the history
Allow external plugins as built-ins in Simulator
  • Loading branch information
danngreen authored Dec 23, 2024
2 parents 4115595 + efd49f6 commit c658355
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 7 deletions.
2 changes: 1 addition & 1 deletion firmware/lib/esp-serial-flasher
Submodule esp-serial-flasher updated 73 files
+47 −0 .github/ISSUE_TEMPLATE/bug_report.yml
+34 −0 .github/ISSUE_TEMPLATE/feature_request.yml
+2 −1 .gitignore
+139 −0 .gitlab-ci.yml
+49 −14 CMakeLists.txt
+18 −0 Kconfig
+49 −31 README.md
+ examples/binaries/Hello-world/ESP32/bootloader.bin
+ examples/binaries/Hello-world/ESP32/hello-world.bin
+ examples/binaries/Hello-world/ESP32/hello_world.bin
+ examples/binaries/Hello-world/ESP32_C2/bootloader.bin
+ examples/binaries/Hello-world/ESP32_C2/hello_world.bin
+ examples/binaries/Hello-world/ESP32_C2/partition-table.bin
+ examples/binaries/Hello-world/ESP32_C3/bootloader.bin
+ examples/binaries/Hello-world/ESP32_C3/hello_world.bin
+ examples/binaries/Hello-world/ESP32_C3/partition-table.bin
+ examples/binaries/Hello-world/ESP32_C6/bootloader.bin
+ examples/binaries/Hello-world/ESP32_C6/hello_world.bin
+ examples/binaries/Hello-world/ESP32_C6/partition-table.bin
+ examples/binaries/Hello-world/ESP32_H2/bootloader.bin
+ examples/binaries/Hello-world/ESP32_H2/hello_world.bin
+ examples/binaries/Hello-world/ESP32_H2/partition-table.bin
+ examples/binaries/Hello-world/ESP32_S2/bootloader.bin
+ examples/binaries/Hello-world/ESP32_S2/hello-world.bin
+ examples/binaries/Hello-world/ESP32_S2/hello_world.bin
+ examples/binaries/Hello-world/ESP32_S3/bootloader.bin
+ examples/binaries/Hello-world/ESP32_S3/hello_world.bin
+ examples/binaries/Hello-world/ESP32_S3/partition-table.bin
+ examples/binaries/RAM_APP/ESP32/app.bin
+ examples/binaries/RAM_APP/ESP32_C2/app.bin
+ examples/binaries/RAM_APP/ESP32_C3/app.bin
+ examples/binaries/RAM_APP/ESP32_C6/app.bin
+ examples/binaries/RAM_APP/ESP32_H2/app.bin
+ examples/binaries/RAM_APP/ESP32_S2/app.bin
+ examples/binaries/RAM_APP/ESP32_S3/app.bin
+15 −0 examples/binaries/RAM_APP/source/CMakeLists.txt
+2 −0 examples/binaries/RAM_APP/source/main/CMakeLists.txt
+16 −0 examples/binaries/RAM_APP/source/main/main.c
+11 −0 examples/binaries/RAM_APP/source/sdkconfig.defaults
+1 −1 examples/common/bin2array.cmake
+91 −9 examples/common/example_common.c
+4 −0 examples/esp32_example/partitions.csv
+1 −0 examples/esp32_example/sdkconfig.defaults
+1 −1 examples/esp32_load_ram_example/main/main.c
+7 −0 examples/esp32_spi_load_ram_example/CMakeLists.txt
+80 −0 examples/esp32_spi_load_ram_example/README.md
+14 −0 examples/esp32_spi_load_ram_example/main/CMakeLists.txt
+97 −0 examples/esp32_spi_load_ram_example/main/main.c
+4 −0 examples/esp32_spi_load_ram_example/sdkconfig.defaults
+3 −0 examples/zephyr_example/CMakeLists.txt
+1 −1 idf_component.yml
+26 −81 include/esp_loader.h
+7 −0 include/esp_loader_io.h
+0 −12 port/custom_port.h
+14 −31 port/esp32_port.c
+298 −0 port/esp32_spi_port.c
+60 −0 port/esp32_spi_port.h
+11 −14 port/raspberry_port.c
+11 −33 port/stm32_port.c
+22 −0 port/zephyr_port.c
+11 −23 private_include/protocol.h
+31 −0 private_include/protocol_prv.h
+50 −111 src/esp_loader.c
+49 −4 src/esp_targets.c
+7 −178 src/protocol_common.c
+312 −0 src/protocol_spi.c
+114 −0 src/protocol_uart.c
+2 −2 src/slip.c
+7 −2 test/CMakeLists.txt
+2 −1 test/qemu_test.cpp
+23 −0 test/serial_io_tcp.cpp
+8 −0 test/test.cpp
+4 −1 zephyr/CMakeLists.txt
2 changes: 1 addition & 1 deletion firmware/lib/patch-serial
2 changes: 1 addition & 1 deletion firmware/vcv_plugin/export/src/plugin/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Plugin::~Plugin() {
// In VCV Rack: don't delete model because it's allocated once and referenced by a global.

// In MetaModule: we need to delete the models when the Plugin is removed
pr_dbg("Deleting Model %s\n", model->slug.c_str());
pr_trace("Deleting Model %s\n", model->slug.c_str());
delete model;

MetaModule::ModuleFactory::unregisterBrand(slug);
Expand Down
6 changes: 5 additions & 1 deletion firmware/vcv_ports/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ target_include_directories(vcv_ports INTERFACE
${CMAKE_CURRENT_LIST_DIR}/glue
)

if (NOT TARGET simulator)
target_include_directories(vcv_ports INTERFACE ${CMAKE_CURRENT_LIST_DIR}/glue/ext_plugin)
endif()

# Get list of brands
include(${CMAKE_CURRENT_LIST_DIR}/brands.cmake)

Expand Down Expand Up @@ -72,7 +76,7 @@ foreach(brand ${brands})

target_link_libraries(_vcv_ports_internal PUBLIC ${brand}Library)

endif()
endif()

endforeach()

3 changes: 3 additions & 0 deletions firmware/vcv_ports/glue/ext_plugin/ext_plugin_builtin.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// do nothing in firmware:
inline void load_ext_builtin_plugins(auto &internal_plugins) {
}
2 changes: 2 additions & 0 deletions firmware/vcv_ports/internal_plugin_manager.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "convert_plugins.hh"
#include "ext_plugin_builtin.hh"
#include "fat_file_io.hh"
#include "fs/asset_drive/asset_fs.hh"
#include "fs/asset_drive/untar.hh"
Expand Down Expand Up @@ -27,6 +28,7 @@ struct InternalPluginManager {
prepare_ramdisk();
load_internal_assets();
load_internal_plugins();
load_ext_builtin_plugins(internal_plugins);
}

void prepare_ramdisk() {
Expand Down
6 changes: 4 additions & 2 deletions simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_subdirectory(lvgl_drv)
# #################### LVGL ############################################

get_filename_component(LV_CONF_DIR ${LV_CONF_PATH} DIRECTORY)
cmake_policy(SET CMP0177 OLD)
include(${LVGL_DIR}/CMakeLists.txt)
target_include_directories(lvgl PRIVATE
${FWDIR}/lib/fatfs/source
Expand Down Expand Up @@ -165,7 +166,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Ap
set(DEBUG_COMMAND ${CMAKE_DEBUGGER_BINARY} $<TARGET_FILE:simulator> --
--sdcarddir ${CMAKE_CURRENT_LIST_DIR}/patches
--flashdir ${CMAKE_CURRENT_LIST_DIR}/../patches/default
--assets ${CMAKE_CURRENT_LIST_DIR}/../firmware/build/assets.uimg
--assets ${CMAKE_CURRENT_LIST_DIR}/build/assets.uimg
)


Expand All @@ -178,7 +179,7 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
--args $<TARGET_FILE:simulator>
--sdcarddir ${CMAKE_CURRENT_LIST_DIR}/patches
--flashdir ${CMAKE_CURRENT_LIST_DIR}/../shared/patch/default
--assets ${CMAKE_CURRENT_LIST_DIR}/../firmware/build/assets.uimg
--assets ${CMAKE_CURRENT_LIST_DIR}/build/assets.uimg
)
else ()
set(DEBUG_COMMAND echo "Compiler is ${CMAKE_CXX_COMPILER_ID}, but must be Clang, AppleClang, or GNU to debug")
Expand All @@ -191,3 +192,4 @@ add_custom_target(
USES_TERMINAL
)

include(ext-plugins.cmake)
65 changes: 65 additions & 0 deletions simulator/ext-plugins.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Two steps to build an external plugin into the simulator:
#
# 1. Copy/paste the two `list APPEND commands` below, puttting in the path to the
# plugin (where the CMakeLists.txt lives), and the plugin cmake library name
#
# 2. In the plugin, find the file where init(rack::Plugin*) is defined, and rename it to init_Brand
# You can use #if defined(METAMODULE_BUILTIN) so that it's still called init() when building as a plugin for Rack or MM.
# `Brand` in init_Brand must match the plugin cmake library name you used in step 1.

# Example with Venom:
# list(APPEND ext_builtin_brand_paths "${CMAKE_CURRENT_LIST_DIR}/../../metamodule-plugin-examples/Venom")
# list(APPEND ext_builtin_brand_libname "Venom")


#
# Asset dir
#

cmake_path(SET ASSET_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets")
set(ASSET_IMG_FILENAME assets.uimg)
cmake_path(APPEND ASSET_IMG_PATH "${CMAKE_CURRENT_BINARY_DIR}" "${ASSET_IMG_FILENAME}")

message("set ASSET_DIR to ${ASSET_DIR}")
message("set ASSET_IMG_PATH to ${ASSET_IMG_PATH}")

add_custom_command(
OUTPUT ${ASSET_DIR}
COMMAND ${CMAKE_COMMAND} -E echo Copying "${FWDIR}/assets" to "${ASSET_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${FWDIR}/assets" "${ASSET_DIR}"
COMMENT "Copying assets/ dir from ${FWDIR}/assets to ${ASSET_DIR}"
VERBATIM USES_TERMINAL
)

add_custom_command(
OUTPUT ${ASSET_IMG_PATH}
COMMAND cd ${ASSET_DIR} && ${CMAKE_COMMAND} -E tar -cf ${ASSET_IMG_PATH}.tar .
COMMAND cd ${FWDIR} && flashing/uimg_header.py --name Assets ${ASSET_IMG_PATH}.tar ${ASSET_IMG_PATH}
COMMENT "Creating assets uimg file at ${ASSET_IMG_PATH}"
DEPENDS ${ASSET_DIR}
VERBATIM USES_TERMINAL
)

add_custom_target(asset-image ALL
DEPENDS ${ASSET_IMG_PATH}
)

set(EXT_PLUGIN_INIT_CALLS "")

foreach(branddir brand IN ZIP_LISTS ext_builtin_brand_paths ext_builtin_brand_libname)
set(METAMODULE_SDK_DIR ${CMAKE_CURRENT_LIST_DIR})
add_subdirectory(${branddir} ${CMAKE_CURRENT_BINARY_DIR}/builtins/${brand})

target_link_libraries(${brand} PRIVATE metamodule::vcv-plugin-interface)
target_link_libraries(${brand} PRIVATE cpputil::cpputil)
target_compile_definitions(${brand} PRIVATE METAMODULE METAMODULE_BUILTIN)

target_link_libraries(_vcv_ports_internal PUBLIC ${brand})
add_dependencies(asset-image ${brand}-assets)

string(APPEND EXT_PLUGIN_INIT_CALLS "\textern void init_${brand}(rack::plugin::Plugin *);\n\tinit_${brand}(&internal_plugins.emplace_back(\"${brand}\"));")
endforeach()

configure_file(src/ext_plugin_builtin.hh.in ${CMAKE_CURRENT_BINARY_DIR}/ext_plugin/ext_plugin_builtin.hh)
target_include_directories(simulator PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/ext_plugin)

41 changes: 41 additions & 0 deletions simulator/plugin.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# TODO: Get cmake to copy the source file that contains init() and rename that function to init_BRAND()
# Also see if Cmake can generate the calls to init (currently manually written into simulator/src/ext_plugin_builtin.hh)

# file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake"
# [=[
# file(READ "${SOURCE}" TEXT)
# string(REPLACE "foo" "bar" TEXT "${TEXT}")
# file(WRITE "${TARGET}" "${TEXT}")
# ]=])

# add_custom_command(
# OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp"
# COMMAND "${CMAKE_COMMAND}"
# "-DSOURCE=${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp"
# "-DTARGET=${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp"
# -P "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake"
# DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp" "${CMAKE_CURRENT_BINARY_DIR}/replace.cmake"
# )


function(create_plugin)
message("Building ${brand} as built-in plugin (create_plugin)")

# target_sources(${PLUGIN_OPTIONS_SOURCE_LIB} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp)

set(oneValueArgs SOURCE_LIB SOURCE_ASSETS DESTINATION PLUGIN_NAME PLUGIN_JSON)
cmake_parse_arguments(PLUGIN_OPTIONS "" "${oneValueArgs}" "" ${ARGN} )

add_custom_command(
OUTPUT "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${PLUGIN_OPTIONS_SOURCE_ASSETS}" "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}"
COMMENT "Copying ${PLUGIN_OPTIONS_SOURCE_ASSETS} to ${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}"
VERBATIM
)

add_custom_target(${PLUGIN_OPTIONS_SOURCE_LIB}-assets
DEPENDS "${ASSET_DIR}/${PLUGIN_OPTIONS_PLUGIN_NAME}"
)


endfunction()
3 changes: 3 additions & 0 deletions simulator/src/ext_plugin_builtin.hh.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
inline void load_ext_builtin_plugins(auto &internal_plugins) {
${EXT_PLUGIN_INIT_CALLS}
}
2 changes: 1 addition & 1 deletion simulator/src/settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ struct Settings {
unsigned zoom = 100;
std::string sdcard_path = "patches/";
std::string flash_path = "../patches/default/";
std::string asset_file = "../firmware/build/assets.uimg";
std::string asset_file = "build/assets.uimg";
int audioout_dev = 0;

void parse(int argc, char *argv[]) {
Expand Down

0 comments on commit c658355

Please sign in to comment.