From 262d29d9e94d25707edd4904acc42edacdab808a Mon Sep 17 00:00:00 2001 From: Elvin Luff Date: Sun, 22 Jun 2025 15:13:31 +0200 Subject: [PATCH 1/4] feat: add (WIP) eggrider compatibility option --- src/firmware/app.c | 17 +++- src/firmware/app.h | 1 + src/firmware/extcom.c | 168 ++++++++++++++++++++-------------------- src/firmware/extcom.h | 1 - src/firmware/fwconfig.h | 14 +++- 5 files changed, 111 insertions(+), 90 deletions(-) diff --git a/src/firmware/app.c b/src/firmware/app.c index 1c6b52fa..a430e9e8 100644 --- a/src/firmware/app.c +++ b/src/firmware/app.c @@ -257,6 +257,21 @@ void app_set_lights(bool on) } } +void app_set_speed_limit_operation_mode(uint16_t display_speed_limit_rpm) +{ + if (SPEED_LIMIT_SPORT_SWITCH_KPH != 0) + { + if (display_speed_limit_rpm == convert_wheel_speed_kph_to_rpm(SPEED_LIMIT_SPORT_SWITCH_KPH)) + { + app_set_operation_mode(OPERATION_MODE_SPORT); + } + else + { + app_set_operation_mode(OPERATION_MODE_DEFAULT); + } + } +} + void app_set_operation_mode(uint8_t mode) { if (operation_mode != mode) @@ -546,7 +561,7 @@ bool apply_speed_limit(uint8_t* target_current, uint8_t throttle_percent, bool p // global throttle speed limit applies if enabled in configuration, PAS is not engaged and throttle is used bool global_throttle_limit_active = - !pas_engaged && + !pas_engaged && throttle_percent > 0 && g_config.throttle_global_spd_lim_percent > 0 && ( diff --git a/src/firmware/app.h b/src/firmware/app.h index 66b3164f..29d242ff 100644 --- a/src/firmware/app.h +++ b/src/firmware/app.h @@ -63,6 +63,7 @@ void app_set_lights(bool on); void app_set_operation_mode(uint8_t mode); void app_set_wheel_max_speed_rpm(uint16_t value); +void app_set_speed_limit_operation_mode(uint16_t display_speed_limit_rpm); uint8_t app_get_assist_level(); uint8_t app_get_lights(); diff --git a/src/firmware/extcom.c b/src/firmware/extcom.c index bf0d5c79..364b4838 100644 --- a/src/firmware/extcom.c +++ b/src/firmware/extcom.c @@ -17,7 +17,7 @@ #include "app.h" #include "util.h" #include "version.h" -#include "intellisense.h" +#include "intellisense.h" #include "fwconfig.h" #include @@ -28,7 +28,7 @@ #define DISCARD -1 -#define BUFFER_SIZE 192 +#define BUFFER_SIZE 192 #define DISCARD_TIMEOUT_MS 50 #define REQUEST_TYPE_READ 0x01 @@ -122,7 +122,7 @@ static int16_t process_bafang_display_write_speed_limit(); void extcom_init() { msg_len = 0; - last_recv_ms = 0; + last_recv_ms = 0; discard_until_ms = 0; // Bafang standard baud rate @@ -155,9 +155,9 @@ void extcom_process() else { msgbuf[msg_len++] = uart_read(); - last_recv_ms = now; + last_recv_ms = now; discard_until_ms = 0; - } + } } if (msg_len > 0 && now - last_recv_ms > 100) @@ -170,10 +170,10 @@ void extcom_process() if (res == DISCARD) { msg_len = 0; - last_recv_ms = 0; - // Discard received data for the next DISCARD_TIMEOUT_MS milliseconds - discard_until_ms = now + DISCARD_TIMEOUT_MS; - + last_recv_ms = 0; + // Discard received data for the next DISCARD_TIMEOUT_MS milliseconds + discard_until_ms = now + DISCARD_TIMEOUT_MS; + eventlog_write(EVT_ERROR_EXTCOM_DISCARD); } else if (res > 0) @@ -354,7 +354,7 @@ static int16_t process_read_fw_version() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -378,7 +378,7 @@ static int16_t process_read_evtlog_enable() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -410,7 +410,7 @@ static int16_t process_read_config() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -442,7 +442,7 @@ static int16_t process_write_evtlog_enable() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -481,7 +481,7 @@ static int16_t process_write_config() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -508,7 +508,7 @@ static int16_t process_write_reset_config() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -541,7 +541,7 @@ static int16_t process_write_adc_voltage_calibration() } else { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); return DISCARD; } @@ -662,10 +662,10 @@ static int16_t process_bafang_display_read_range() { return KEEP; } - - uint16_t value = 0; - -#if DISPLAY_RANGE_FIELD_DATA == DISPLAY_RANGE_FIELD_TEMPERATURE + + uint16_t value = 0; + +#if DISPLAY_RANGE_FIELD_DATA == DISPLAY_RANGE_FIELD_TEMPERATURE value = app_get_temperature(); if (g_config.use_freedom_units) { @@ -675,24 +675,24 @@ static int16_t process_bafang_display_read_range() // F_miles = 2.9C + 50.5 value = ((290u * value) + 5050u) / 100u; - } -#elif DISPLAY_RANGE_FIELD_DATA == DISPLAY_RANGE_FIELD_POWER - if (app_get_lights()) - { - value = motor_get_battery_current_x10(); - } - else - { - uint16_t max_current_amp_x10 = g_config.max_current_amps * 10; - value = MAP32(motor_get_target_current(), 0, 100, 0, max_current_amp_x10); - } - - if (g_config.use_freedom_units) - { - // compensate for km -> miles conversion the display will do - value = (value * 161u) / 100u; - } -#endif + } +#elif DISPLAY_RANGE_FIELD_DATA == DISPLAY_RANGE_FIELD_POWER + if (app_get_lights()) + { + value = motor_get_battery_current_x10(); + } + else + { + uint16_t max_current_amp_x10 = g_config.max_current_amps * 10; + value = MAP32(motor_get_target_current(), 0, 100, 0, max_current_amp_x10); + } + + if (g_config.use_freedom_units) + { + // compensate for km -> miles conversion the display will do + value = (value * 161u) / 100u; + } +#endif uint8_t checksum = 0; @@ -758,13 +758,13 @@ static int16_t process_bafang_display_write_pas() if (msg_len < 4) { return KEEP; - } - - if (compute_checksum(msgbuf, 3) == msgbuf[3]) - { + } + + if (compute_checksum(msgbuf, 3) == msgbuf[3]) + { switch (msgbuf[2]) { - case 0x00: + case 0x00: app_set_assist_level(ASSIST_0); break; case 0x01: @@ -796,16 +796,16 @@ static int16_t process_bafang_display_write_pas() break; case 0x06: app_set_assist_level(ASSIST_PUSH); - break; - default: - // Unsupported level, ignore break; - } + default: + // Unsupported level, ignore + break; + } } - else - { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); - return DISCARD; + else + { + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + return DISCARD; } return 4; @@ -817,26 +817,26 @@ static int16_t process_bafang_display_write_mode() { return KEEP; } - - if (compute_checksum(msgbuf, 3) == msgbuf[3]) - { + + if (compute_checksum(msgbuf, 3) == msgbuf[3]) + { switch (msgbuf[2]) { - case 0x02: + case 0x02: app_set_operation_mode(OPERATION_MODE_DEFAULT); break; case 0x04: app_set_operation_mode(OPERATION_MODE_SPORT); - break; - default: - // Unsupported mode, ignore break; - } - } - else - { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); - return DISCARD; + default: + // Unsupported mode, ignore + break; + } + } + else + { + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + return DISCARD; } return 4; @@ -848,8 +848,8 @@ static int16_t process_bafang_display_write_lights() { return KEEP; } - - // No checksum + + // No checksum switch (msgbuf[2]) { @@ -858,8 +858,8 @@ static int16_t process_bafang_display_write_lights() break; case 0xf1: app_set_lights(true); - break; - default: + break; + default: return DISCARD; // unsupported state, assume communication error } @@ -868,26 +868,24 @@ static int16_t process_bafang_display_write_lights() static int16_t process_bafang_display_write_speed_limit() { - if (msg_len < 5) + if (compute_checksum(msgbuf, 4) == msgbuf[4]) { - return KEEP; + uint16_t value = ((msgbuf[2] << 8) | msgbuf[3]); + + // Enable sport mode if the display sets the speed limit to + // the specified value + app_set_speed_limit_operation_mode(value); + + // Ignoring speed limit requested by display, + // Global speed limit is configured in firmware config tool. + + // app_set_wheel_max_speed_rpm(value); } - - /* - if (compute_checksum(msgbuf, 4) == msgbuf[4]) + else { - // Ignoring speed limit requested by display, - // Global speed limit is configured in firmware config tool. - - uint16_t value = ((msgbuf[2] << 8) | msgbuf[3]); - app_set_wheel_max_speed_rpm(value); - } - else - { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); - return DISCARD; - } - */ + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + return DISCARD; + } return 5; } diff --git a/src/firmware/extcom.h b/src/firmware/extcom.h index ad51279b..27287a8b 100644 --- a/src/firmware/extcom.h +++ b/src/firmware/extcom.h @@ -13,4 +13,3 @@ void extcom_init(); void extcom_process(); #endif - diff --git a/src/firmware/fwconfig.h b/src/firmware/fwconfig.h index 45821ff5..43c03000 100644 --- a/src/firmware/fwconfig.h +++ b/src/firmware/fwconfig.h @@ -64,7 +64,7 @@ // No battery percent mapping #define BATTERY_PERCENT_MAP_NONE 0 // Map battery percent to provide a linear relationship on the -// 5-bar battery indicator of the SW102 display. +// 5-bar battery indicator of the SW102 display. #define BATTERY_PERCENT_MAP_SW102 1 // Select battery percent mapping @@ -120,7 +120,7 @@ 72, 73, 74, 76, 77, 78, 80, 81, 83, 84, \ 85, 87, 88, 90, 91, 93, 94, 96, 97, 99, \ 100 - + // This value is used when assist level is configured with throttle cadence // override flag in config tool. Default is 100%. @@ -167,6 +167,14 @@ #else #define DISPLAY_RANGE_FIELD_DATA DISPLAY_RANGE_FIELD_POWER #endif -#endif +#endif + +// Eggrider compatibility. When the display sets the speed limit +// to a certain value, use sport mode. The actual speed limit of the motor +// remains unchanged. This is a workaround; it is not possible to +// program the controller using an Eggrider as it doesn't understand the +// bbs-fw protocol. In the app set the "Bafang switch mode" to "Only live data" +// and set "Max speed OffRoad" to the value set below. +#define SPEED_LIMIT_SPORT_SWITCH_KPH 0 // speed in km/h. Setting to 0 disables this feature #endif From b91192e9292d6ebc9183f7ac6636b04a837cdbd9 Mon Sep 17 00:00:00 2001 From: Elvin Luff Date: Tue, 24 Jun 2025 08:35:37 +0200 Subject: [PATCH 2/4] fix: add back in KEEP return --- src/firmware/extcom.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/firmware/extcom.c b/src/firmware/extcom.c index 364b4838..3bdb7308 100644 --- a/src/firmware/extcom.c +++ b/src/firmware/extcom.c @@ -868,6 +868,11 @@ static int16_t process_bafang_display_write_lights() static int16_t process_bafang_display_write_speed_limit() { + if (msg_len < 5) + { + return KEEP; + } + if (compute_checksum(msgbuf, 4) == msgbuf[4]) { uint16_t value = ((msgbuf[2] << 8) | msgbuf[3]); From 5d74442567daebbf965f806d52571bee58931a53 Mon Sep 17 00:00:00 2001 From: Elvin Luff Date: Tue, 24 Jun 2025 09:28:01 +0200 Subject: [PATCH 3/4] feat: add additional info to make Eggrider work --- src/firmware/fwconfig.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/firmware/fwconfig.h b/src/firmware/fwconfig.h index 43c03000..8c2f5680 100644 --- a/src/firmware/fwconfig.h +++ b/src/firmware/fwconfig.h @@ -173,8 +173,12 @@ // to a certain value, use sport mode. The actual speed limit of the motor // remains unchanged. This is a workaround; it is not possible to // program the controller using an Eggrider as it doesn't understand the -// bbs-fw protocol. In the app set the "Bafang switch mode" to "Only live data" -// and set "Max speed OffRoad" to the value set below. +// bbs-fw protocol. App configuration: +// - Set "Bafang switch mode" to "Only live data" +// - Make sure the bbs-fw wheel diameter in inches matches the Eggrider +// wheel circumference in mm. Formula: +// circumference (mm) = diameter * π * 25.4 +// - Set "Max speed OffRoad" to the value set below. #define SPEED_LIMIT_SPORT_SWITCH_KPH 0 // speed in km/h. Setting to 0 disables this feature #endif From 4dade6800462a606576a5c9259366eaf0a8bda6b Mon Sep 17 00:00:00 2001 From: Elvin Luff Date: Tue, 24 Jun 2025 09:56:16 +0200 Subject: [PATCH 4/4] feat: use preprocessor macro instead to enable functionality --- src/firmware/app.c | 15 ++++++--------- src/firmware/extcom.c | 34 +++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/firmware/app.c b/src/firmware/app.c index a430e9e8..0e98effd 100644 --- a/src/firmware/app.c +++ b/src/firmware/app.c @@ -259,16 +259,13 @@ void app_set_lights(bool on) void app_set_speed_limit_operation_mode(uint16_t display_speed_limit_rpm) { - if (SPEED_LIMIT_SPORT_SWITCH_KPH != 0) + if (display_speed_limit_rpm == convert_wheel_speed_kph_to_rpm(SPEED_LIMIT_SPORT_SWITCH_KPH)) { - if (display_speed_limit_rpm == convert_wheel_speed_kph_to_rpm(SPEED_LIMIT_SPORT_SWITCH_KPH)) - { - app_set_operation_mode(OPERATION_MODE_SPORT); - } - else - { - app_set_operation_mode(OPERATION_MODE_DEFAULT); - } + app_set_operation_mode(OPERATION_MODE_SPORT); + } + else + { + app_set_operation_mode(OPERATION_MODE_DEFAULT); } } diff --git a/src/firmware/extcom.c b/src/firmware/extcom.c index 3bdb7308..63fe41af 100644 --- a/src/firmware/extcom.c +++ b/src/firmware/extcom.c @@ -873,24 +873,28 @@ static int16_t process_bafang_display_write_speed_limit() return KEEP; } - if (compute_checksum(msgbuf, 4) == msgbuf[4]) - { - uint16_t value = ((msgbuf[2] << 8) | msgbuf[3]); + #if (SPEED_LIMIT_SPORT_SWITCH_KPH > 0) + if (compute_checksum(msgbuf, 4) == msgbuf[4]) + { + uint16_t value = ((msgbuf[2] << 8) | msgbuf[3]); - // Enable sport mode if the display sets the speed limit to - // the specified value - app_set_speed_limit_operation_mode(value); + // Enable sport mode if the display sets the speed limit to + // the specified value - // Ignoring speed limit requested by display, - // Global speed limit is configured in firmware config tool. + app_set_speed_limit_operation_mode(value); - // app_set_wheel_max_speed_rpm(value); - } - else - { - eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); - return DISCARD; - } + + // Ignoring speed limit requested by display, + // Global speed limit is configured in firmware config tool. + + // app_set_wheel_max_speed_rpm(value); + } + else + { + eventlog_write(EVT_ERROR_EXTCOM_CHEKSUM); + return DISCARD; + } + #endif return 5; }