diff --git a/CHANGELOG.md b/CHANGELOG.md index 971f6d4ae..a736bb65d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,16 @@ correction of the `hub.imu.heading()` value ([support#1678]). - Added `update_heading_correction` to interactively set the heading correction value ([support#1678]). +- Added command to start downloaded or builtin user program with a one byte + program identifier. The existing START_PROGRAM and START_REPL are special + cases of this new more generic command, but will remain available for + backwards compatibility. For now, this is added to start various builtin + programs, but it prepares for the ability to start different downloaded + programs too ([pybricks-micropython#254]). ### Changed +- Changed protocol to Pybricks Profile v1.4.0. - When upgrading the firmware to a new version, the user program will now be erased. This avoids issues with incompatible program files ([support#1622]). - The `angular_velocity_threshold`, and `acceleration_threshold` settings @@ -40,6 +47,7 @@ [pybricks-micropython#250]: https://github.com/pybricks/pybricks-micropython/pull/250 [pybricks-micropython#253]: https://github.com/pybricks/pybricks-micropython/pull/253 +[pybricks-micropython#254]: https://github.com/pybricks/pybricks-micropython/pull/254 [support#1429]: https://github.com/pybricks/support/issues/1429 [support#1460]: https://github.com/pybricks/support/issues/1460 [support#1615]: https://github.com/pybricks/support/issues/1615 diff --git a/bricks/_common/micropython.c b/bricks/_common/micropython.c index ef2ca1fd9..6ddc1084d 100644 --- a/bricks/_common/micropython.c +++ b/bricks/_common/micropython.c @@ -117,7 +117,7 @@ static void print_final_exception(mp_obj_t exc) { mp_obj_print_exception(&mp_plat_print, exc); } -#if PYBRICKS_OPT_COMPILER +#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL static void run_repl(void) { readline_init0(); pyexec_system_exit = 0; @@ -145,7 +145,7 @@ static void run_repl(void) { nlr_set_abort(NULL); } -#endif +#endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL // From micropython/py/builtinimport.c, but copied because it is static. static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_t *rc, const mp_module_context_t *mc) { @@ -277,7 +277,7 @@ static void run_user_program(void) { print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val)); - #if PYBRICKS_OPT_COMPILER + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL // On KeyboardInterrupt, drop to REPL for debugging. if (mp_obj_exception_match(MP_OBJ_FROM_PTR(nlr.ret_val), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { @@ -289,47 +289,39 @@ static void run_user_program(void) { // Enter REPL. run_repl(); } - #endif + #endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL } nlr_set_abort(NULL); } -/** - * Builtin Pybricks MicroPython program identifiers. - */ -typedef enum { - /** - * The MicroPython REPL. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_REPL = 0, - /** - * Program that detects attached devices, displays sensor values, and - * relays sensor data to host if connected. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_PORT_VIEW = 1, - /** - * The number of builtin user programs. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_NUMBER_OF_PROGRAMS, -} pybricks_micropython_builtin_user_program_id_t; - pbio_error_t pbsys_main_program_validate(pbsys_main_program_t *program) { - // Validate builtin user programs for existence. - if (program->type == PBSYS_MAIN_PROGRAM_TYPE_BUILTIN) { - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - if (program->id < PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_NUMBER_OF_PROGRAMS) { - return PBIO_SUCCESS; - } - #endif + // For builtin programs, check requested ID against feature flags. + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_REPL) { + return PBIO_SUCCESS; + } + #endif + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW) { + return PBIO_SUCCESS; + } + #endif + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION) { + return PBIO_SUCCESS; + } + #endif + + // Only user program 0 is supported for now. + if (program->id != PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT) { return PBIO_ERROR_NOT_SUPPORTED; } // If requesting a user program, ensure that it exists and is valid. - // Currently, only programs on slot 0 are supported. uint32_t program_size = program->code_end - program->code_start; - if (program->id != 0 || program_size == 0 || program_size > PBSYS_STORAGE_MAX_PROGRAM_SIZE) { + if (program_size == 0 || program_size > PBSYS_STORAGE_MAX_PROGRAM_SIZE) { return PBIO_ERROR_NOT_SUPPORTED; } @@ -361,31 +353,37 @@ void pbsys_main_run_program(pbsys_main_program_t *program) { // Initialize MicroPython. mp_init(); - // Check for run type. - if (program->type == PBSYS_MAIN_PROGRAM_TYPE_USER) { - // Init Pybricks package without auto-import. - pb_package_pybricks_init(false); - // Run loaded user program. - run_user_program(); - } - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - else { - switch (program->id) { - case PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_REPL: - // Run REPL with everything auto-imported. - pb_package_pybricks_init(true); - run_repl(); - break; - case PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_PORT_VIEW: - pyexec_frozen_module("_builtin_port_view.py", false); - break; - default: - // Existence was already validated above, so just quietly exit - // since we can't get here. - break; - } + // Runs the requested downloaded or builtin user program. + switch (program->id) { + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_USER_PROGRAM_ID_REPL: + // Run REPL with everything auto-imported. + pb_package_pybricks_init(true); + run_repl(); + break; + #endif + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW + case PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW: + pb_package_pybricks_init(false); + pyexec_frozen_module("_builtin_port_view.py", false); + break; + #endif + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION + case PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION: + // Todo + break; + #endif + + default: + // Init Pybricks package without auto-import. + pb_package_pybricks_init(false); + // Run loaded user program (just slot 0 for now). + run_user_program(); + break; } - #endif // PYBRICKS_OPT_COMPILER // De-init bluetooth resources (including flushing stdout) that may use // memory allocated by MicroPython before we wipe it. diff --git a/bricks/ev3rt/app.c b/bricks/ev3rt/app.c index 93b5ee486..f559aac67 100644 --- a/bricks/ev3rt/app.c +++ b/bricks/ev3rt/app.c @@ -26,7 +26,7 @@ void main_task(intptr_t unused) { while (true) { pbsys_main_program_t program = { - .type = PBSYS_MAIN_PROGRAM_TYPE_BUILTIN, + .id = PBIO_PYBRICKS_USER_PROGRAM_ID_REPL, .code_end = heap, .data_end = heap + sizeof(heap), }; diff --git a/lib/pbio/include/pbio/protocol.h b/lib/pbio/include/pbio/protocol.h index 6a2b9826d..bae7dbaa6 100644 --- a/lib/pbio/include/pbio/protocol.h +++ b/lib/pbio/include/pbio/protocol.h @@ -39,6 +39,38 @@ PBIO_XSTR(PBIO_PROTOCOL_VERSION_MINOR) "." \ PBIO_XSTR(PBIO_PROTOCOL_VERSION_PATCH) + +/** + * User program identifiers. + * + * 0--127: Downloadabled user programs. + * 128--255: Builtin user programs. + */ +typedef enum { + /** + * First possible downloadable user program. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT = 0, + /** + * Last possible downloadable user program. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_LAST_SLOT = 127, + /** + * Read-eval-print loop (REPL) interface. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_REPL = 128, + /** + * Program that detects attached devices, displays sensor values, and + * relays sensor data to host if connected. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW = 129, + /** + * Program that calibrates the internal inertial measurement unit and saves + * data persistently on the hub. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION = 130, +} pbio_pybricks_user_program_id_t; + /** * Pybricks command types. * @@ -53,36 +85,28 @@ typedef enum { PBIO_PYBRICKS_COMMAND_STOP_USER_PROGRAM = 0, /** - * Requests that a specified user program should be started. - * - * Parameters: - * - id (optional): The identifier of the user program (32-bit little-endian unsigned integer). - * Defaults to 0 if no identifier is provided. - * This optional parameter was introduced in Pybricks Profile v1.4.0 + * Requests that the user program should be started. * * Errors: - * - ::PBIO_PYBRICKS_ERROR_BUSY if a program is already running. - * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the builtin user program is not available (Since Pybricks Profile v1.4.0). + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. * * @since Pybricks Profile v1.2.0 + * @deprecated in Pybricks Profile v1.4.0. + * Use ::PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM instead. */ PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM = 1, /** - * Requests that a specified builtin user program should be started. - * - * Parameters: - * - id (optional): The identifier of the builtin user program (32-bit little-endian unsigned integer). - * Defaults to 0 if no identifier is provided. - * This optional parameter was introduced in Pybricks Profile v1.4.0 + * Requests that the REPL should be started. * * Errors: - * - ::PBIO_PYBRICKS_ERROR_BUSY if a program is already running. - * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the builtin user program is not available (Since Pybricks Profile v1.4.0). + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. * * @since Pybricks Profile v1.2.0 + * @deprecated in Pybricks Profile v1.4.0. + * Use ::PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM instead. */ - PBIO_PYBRICKS_COMMAND_START_BUILTIN_USER_PROGRAM = 2, + PBIO_PYBRICKS_COMMAND_START_REPL = 2, /** * Requests to write user program metadata. @@ -159,8 +183,24 @@ typedef enum { * @since Pybricks Profile v1.4.0 */ PBIO_PYBRICKS_COMMAND_WRITE_APP_DATA = 7, -} pbio_pybricks_command_t; + /** + * Requests that a previously downloaded user program or builtin user + * program is started. + * + * Parameters: + * - payload: Program identifier (one byte). Slots 0--127 are reserved for + * downloaded user programs. Slots 128--255 are for builtin user + * programs. + * + * Errors: + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. + * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the requested program is not available. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM = 8, +} pbio_pybricks_command_t; /** * Application-specific error codes that are used in ATT_ERROR_RSP. */ @@ -310,14 +350,11 @@ typedef enum { // NB: the values are part of the protocol, so don't change the values! /** - * Hub supports builtin user programs, such as an interactive REPL or Port View. - * - * Prior to version 1.4.0 this flag was exclusively used to indicate REPL - * support since there were no other builtin user programs. + * Hub supports interactive REPL. * * @since Pybricks Profile v1.2.0. */ - PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS = 1 << 0, + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_REPL = 1 << 0, /** * Hub supports user program with multiple MicroPython .mpy files ABI v6 * @@ -326,14 +363,26 @@ typedef enum { * * @since Pybricks Profile v1.2.0. */ - PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6 = 1 << 1, + PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6 = 1 << 1, /** * Hub supports user program with multiple MicroPython .mpy files ABI v6.1 * including native module support. * * @since Pybricks Profile v1.3.0. */ - PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE = 1 << 2, + PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE = 1 << 2, + /** + * Hub supports builtin sensor port view monitoring program. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_PORT_VIEW = 1 << 3, + /** + * Hub supports builtin IMU calibration program. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_IMU_CALIBRATION = 1 << 4, } pbio_pybricks_feature_flags_t; void pbio_pybricks_hub_capabilities(uint8_t *buf, diff --git a/lib/pbio/include/pbsys/config.h b/lib/pbio/include/pbsys/config.h index ba27b3dab..5c10a2730 100644 --- a/lib/pbio/include/pbsys/config.h +++ b/lib/pbio/include/pbsys/config.h @@ -11,9 +11,11 @@ #include #define PBSYS_CONFIG_APP_FEATURE_FLAGS (0 \ - + PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS * PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS \ - + PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 * PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6 \ - + PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE * PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_REPL \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_PORT_VIEW \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_IMU_CALIBRATION \ + + PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 * PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6 \ + + PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE * PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE \ ) // When set to (1) PBSYS_CONFIG_STATUS_LIGHT indicates that a hub has a hub status light diff --git a/lib/pbio/include/pbsys/main.h b/lib/pbio/include/pbsys/main.h index e22cc1597..97fe4ebcd 100644 --- a/lib/pbio/include/pbsys/main.h +++ b/lib/pbio/include/pbsys/main.h @@ -16,14 +16,6 @@ #include #include -/** - * Main program types. - */ -typedef enum { - PBSYS_MAIN_PROGRAM_TYPE_USER, // User-defined program - PBSYS_MAIN_PROGRAM_TYPE_BUILTIN // Built-in program -} pbsys_main_program_type_t; - /** * Main application program data information. */ @@ -41,14 +33,9 @@ typedef struct _pbsys_main_program_t { */ void *data_end; /** - * Program identifier (selects one user program or one of the builtins). - */ - uint32_t id; - /** - * Whether to run an application-specific builtin user program instead of the - * program given by the data. The builtin user program may still use the data. + * User program identifier. */ - pbsys_main_program_type_t type; + pbio_pybricks_user_program_id_t id; /** * Whether a request was made to start the program. */ @@ -57,7 +44,7 @@ typedef struct _pbsys_main_program_t { #if PBSYS_CONFIG_MAIN -pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id); +pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id); /** * Validates the program that is being requested to start. @@ -101,7 +88,7 @@ bool pbsys_main_stdin_event(uint8_t c); #else // PBSYS_CONFIG_MAIN -static inline pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id) { +static inline pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id) { return PBIO_ERROR_NOT_SUPPORTED; } diff --git a/lib/pbio/platform/city_hub/pbsysconfig.h b/lib/pbio/platform/city_hub/pbsysconfig.h index aa7459ccb..72ba157de 100644 --- a/lib/pbio/platform/city_hub/pbsysconfig.h +++ b/lib/pbio/platform/city_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/essential_hub/pbsysconfig.h b/lib/pbio/platform/essential_hub/pbsysconfig.h index 9a2ecd785..7726dd886 100644 --- a/lib/pbio/platform/essential_hub/pbsysconfig.h +++ b/lib/pbio/platform/essential_hub/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2021-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (1) #define PBSYS_CONFIG_BATTERY_CHARGER (1) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/ev3/pbsysconfig.h b/lib/pbio/platform/ev3/pbsysconfig.h index 1a82f5535..90a8bba36 100644 --- a/lib/pbio/platform/ev3/pbsysconfig.h +++ b/lib/pbio/platform/ev3/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2024 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_MAIN (1) #define PBSYS_CONFIG_STORAGE (1) #define PBSYS_CONFIG_STORAGE_RAM_SIZE (10 * 1024) diff --git a/lib/pbio/platform/ev3rt/pbsysconfig.h b/lib/pbio/platform/ev3rt/pbsysconfig.h index 0e9900a1a..78bb8d799 100644 --- a/lib/pbio/platform/ev3rt/pbsysconfig.h +++ b/lib/pbio/platform/ev3rt/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (0) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/move_hub/pbsysconfig.h b/lib/pbio/platform/move_hub/pbsysconfig.h index 48ba8fb3f..c26beba8e 100644 --- a/lib/pbio/platform/move_hub/pbsysconfig.h +++ b/lib/pbio/platform/move_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/nxt/pbsysconfig.h b/lib/pbio/platform/nxt/pbsysconfig.h index 381dc993e..b5a11f5e3 100644 --- a/lib/pbio/platform/nxt/pbsysconfig.h +++ b/lib/pbio/platform/nxt/pbsysconfig.h @@ -1,6 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_MAIN (1) #define PBSYS_CONFIG_STORAGE (1) #define PBSYS_CONFIG_STORAGE_RAM_SIZE (10 * 1024) diff --git a/lib/pbio/platform/prime_hub/pbsysconfig.h b/lib/pbio/platform/prime_hub/pbsysconfig.h index bd1684420..d5f744ab9 100644 --- a/lib/pbio/platform/prime_hub/pbsysconfig.h +++ b/lib/pbio/platform/prime_hub/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (1) #define PBSYS_CONFIG_BATTERY_CHARGER (1) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_BLUETOOTH_TOGGLE (1) diff --git a/lib/pbio/platform/technic_hub/pbsysconfig.h b/lib/pbio/platform/technic_hub/pbsysconfig.h index b01ef1e8e..0b77fb356 100644 --- a/lib/pbio/platform/technic_hub/pbsysconfig.h +++ b/lib/pbio/platform/technic_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/test/pbsysconfig.h b/lib/pbio/platform/test/pbsysconfig.h index 3da4eba60..2f3523848 100644 --- a/lib/pbio/platform/test/pbsysconfig.h +++ b/lib/pbio/platform/test/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1) #define PBSYS_CONFIG_MAIN (0) diff --git a/lib/pbio/sys/command.c b/lib/pbio/sys/command.c index 638efc9e5..c9f0a1bdf 100644 --- a/lib/pbio/sys/command.c +++ b/lib/pbio/sys/command.c @@ -37,36 +37,37 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { pbio_pybricks_command_t cmd = data[0]; switch (cmd) { + case PBIO_PYBRICKS_COMMAND_STOP_USER_PROGRAM: pbsys_program_stop(false); return PBIO_PYBRICKS_ERROR_OK; - case PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM: { - uint32_t id = 0; - if (size == (1 + sizeof(uint32_t))) { - id = pbio_get_uint32_le(&data[1]); - } + + case PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM: + // Deprecated. For backwards compatibility with Pybricks + // Profile < v1.4.0, assume we should start user program 0. return pbio_pybricks_error_from_pbio_error( - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_USER, id)); - } - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - case PBIO_PYBRICKS_COMMAND_START_BUILTIN_USER_PROGRAM: { - uint32_t id = 0; - if (size == (1 + sizeof(uint32_t))) { - id = pbio_get_uint32_le(&data[1]); - } + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT)); + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_COMMAND_START_REPL: + // Deprecated. For backwards compatibility with Pybricks + // Profile < v1.4.0, make it work anyway. return pbio_pybricks_error_from_pbio_error( - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_BUILTIN, id)); - } - #endif // PBIO_PYBRICKS_FEATURE_TEST(PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS) + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_REPL)); + #endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_COMMAND_WRITE_USER_PROGRAM_META: return pbio_pybricks_error_from_pbio_error(pbsys_storage_set_program_size( pbio_get_uint32_le(&data[1]))); + case PBIO_PYBRICKS_COMMAND_WRITE_USER_RAM: return pbio_pybricks_error_from_pbio_error(pbsys_storage_set_program_data( pbio_get_uint32_le(&data[1]), &data[5], size - 5)); + case PBIO_PYBRICKS_COMMAND_REBOOT_TO_UPDATE_MODE: pbdrv_reset(PBDRV_RESET_ACTION_RESET_IN_UPDATE_MODE); return PBIO_PYBRICKS_ERROR_OK; + case PBIO_PYBRICKS_COMMAND_WRITE_STDIN: #if PBSYS_CONFIG_BLUETOOTH if (pbsys_bluetooth_rx_get_free() < size - 1) { @@ -76,6 +77,7 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { #endif // If no consumers are configured, goes to "/dev/null" without error return PBIO_PYBRICKS_ERROR_OK; + case PBIO_PYBRICKS_COMMAND_WRITE_APP_DATA: { if (!write_app_data_callback) { // No errors when no consumer is configured. This avoids errors @@ -93,6 +95,15 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { const uint8_t *data_to_write = &data[3]; return pbio_pybricks_error_from_pbio_error(write_app_data_callback(offset, data_size, data_to_write)); } + + case PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM: + // Identifier payload required + if (size != 2) { + return PBIO_PYBRICKS_ERROR_VALUE_NOT_ALLOWED; + } + return pbio_pybricks_error_from_pbio_error( + pbsys_main_program_request_start(data[1])); + default: return PBIO_PYBRICKS_ERROR_INVALID_COMMAND; } diff --git a/lib/pbio/sys/hmi.c b/lib/pbio/sys/hmi.c index 9558e1d39..e26844ce8 100644 --- a/lib/pbio/sys/hmi.c +++ b/lib/pbio/sys/hmi.c @@ -50,9 +50,10 @@ static PT_THREAD(update_program_run_button_wait_state(bool button_pressed)) { PT_WAIT_UNTIL(pt, button_pressed); PT_WAIT_UNTIL(pt, !button_pressed); - // if we made it through a full press and release, without the user - // program running, then start the user program - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_USER, 0); + // If we made it through a full press and release, without the user + // program running, then start the user program. There is no UI for + // multiple programs yet, so start the one and only program. + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT); } PT_END(pt); diff --git a/lib/pbio/sys/main.c b/lib/pbio/sys/main.c index 6636dfcda..a668abbbf 100644 --- a/lib/pbio/sys/main.c +++ b/lib/pbio/sys/main.c @@ -22,8 +22,6 @@ static pbsys_main_program_t program; -#include - /** * Requests to start the main user application program. * @@ -33,14 +31,13 @@ static pbsys_main_program_t program; * ::PBIO_ERROR_NOT_SUPPORTED if the program is not available. * Otherwise ::PBIO_SUCCESS. */ -pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id) { +pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id) { // Can't start new program if already running or new requested. if (pbsys_status_test(PBIO_PYBRICKS_STATUS_USER_PROGRAM_RUNNING) || program.start_requested) { return PBIO_ERROR_BUSY; } - program.type = type; program.id = id; // Builtin user programs are also allowed to access user program,