From 98e5101c31ead4f7bc13fb56475311f92c166e2b Mon Sep 17 00:00:00 2001 From: Siann Date: Mon, 22 Jul 2024 12:20:49 -0400 Subject: [PATCH 1/8] battery monitor tx message --- components/batt/Sconscript.py | 16 ++++++++++++++ components/batt/component.toml | 3 +++ components/batt/src/batt.c | 38 ++++++++++++++++++++++++++++++++++ components/batt/src/batt.h | 4 ++++ 4 files changed, 61 insertions(+) create mode 100644 components/batt/Sconscript.py create mode 100644 components/batt/component.toml create mode 100644 components/batt/src/batt.c create mode 100644 components/batt/src/batt.h diff --git a/components/batt/Sconscript.py b/components/batt/Sconscript.py new file mode 100644 index 000000000..718986cf6 --- /dev/null +++ b/components/batt/Sconscript.py @@ -0,0 +1,16 @@ +# ruff: noqa: F821 + +Import('env') +Import('envs') + + +firmware, flash = env.SConscript( + 'src/SConscript.py', + exports={'env': envs['esp32s3']}, +) + +component, name = env.Component(firmware, env.File('component.toml')) +env.ComponentSubtarget(name, 'flash', flash) + + +Return('component') diff --git a/components/batt/component.toml b/components/batt/component.toml new file mode 100644 index 000000000..f25b2a345 --- /dev/null +++ b/components/batt/component.toml @@ -0,0 +1,3 @@ +[metadata] +name = 'batt' +description = 'battery-monitor' diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c new file mode 100644 index 000000000..64341e650 --- /dev/null +++ b/components/batt/src/batt.c @@ -0,0 +1,38 @@ +#include "batt.h" + +#include "firmware-base/state-machine.h" +#include +#include +#include +#include +#include + +#include +#include + +// hypothetical battery percent data +typedef struct { + uint8_t batteryPercent; +} CAN_Message_BatteryStatus; + +static u_int8_t batterypercent; + +static void batt_1Hz(); + +// task scheduling +ember_rate_funcs_S module_rf = { + .call_1Hz = batt_1Hz, +}; + +static void batt_1Hz() +{ + /* + Do I need any authorizationsfrom SUP? like + CANRX_is_message_battery_percent_data_Authorization_ok() + */ + batteryPercent = 0; +} + + +void CANTX_populate_BATT_BatteryPercentData( + m->batteryPercent = batteryPercent;) diff --git a/components/batt/src/batt.h b/components/batt/src/batt.h new file mode 100644 index 000000000..bafcdb829 --- /dev/null +++ b/components/batt/src/batt.h @@ -0,0 +1,4 @@ +#ifndef BATT_H +#define BATT_H + +#endif // BATT.H From ff4607c18ce613fb5ade0afc7c643ed87ca828e8 Mon Sep 17 00:00:00 2001 From: Siann Date: Mon, 22 Jul 2024 12:40:35 -0400 Subject: [PATCH 2/8] updated --- components/batt/src/batt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c index 64341e650..8f973e69e 100644 --- a/components/batt/src/batt.c +++ b/components/batt/src/batt.c @@ -15,7 +15,7 @@ typedef struct { uint8_t batteryPercent; } CAN_Message_BatteryStatus; -static u_int8_t batterypercent; +static uint8_t batterypercent; static void batt_1Hz(); @@ -33,6 +33,8 @@ static void batt_1Hz() batteryPercent = 0; } - void CANTX_populate_BATT_BatteryPercentData( - m->batteryPercent = batteryPercent;) + struct CAN_Message_BatteryStatus * const m) +{ + m->batteryPercent = batteryPercent; +} From ade072d1825c586cfc471d5ea8f85c6f618b040e Mon Sep 17 00:00:00 2001 From: Siann Date: Sun, 25 Aug 2024 11:17:36 -0400 Subject: [PATCH 3/8] some batt firmware progress still not compiling --- can/network.yml | 9 + components/SConscript.py | 1 + components/batt/src/SConscript.py | 39 +++ components/batt/src/batt.c | 22 +- .../batt/src/firmware-base/SConscript.py | 20 ++ .../batt/src/firmware-base/app-description.c | 12 + components/batt/src/firmware-base/eeprom.c | 240 +++++++++++++ components/batt/src/firmware-base/eeprom.h | 15 + .../batt/src/firmware-base/eeprom_ember.c | 10 + .../batt/src/firmware-base/state-machine.c | 316 ++++++++++++++++++ .../batt/src/firmware-base/state-machine.h | 17 + components/sup/src/firmware-base | 1 - 12 files changed, 683 insertions(+), 19 deletions(-) create mode 100644 components/batt/src/SConscript.py create mode 100644 components/batt/src/firmware-base/SConscript.py create mode 100644 components/batt/src/firmware-base/app-description.c create mode 100644 components/batt/src/firmware-base/eeprom.c create mode 100644 components/batt/src/firmware-base/eeprom.h create mode 100644 components/batt/src/firmware-base/eeprom_ember.c create mode 100644 components/batt/src/firmware-base/state-machine.c create mode 100644 components/batt/src/firmware-base/state-machine.h delete mode 120000 components/sup/src/firmware-base diff --git a/can/network.yml b/can/network.yml index 64c2cc458..9e273f604 100644 --- a/can/network.yml +++ b/can/network.yml @@ -805,3 +805,12 @@ nodes: - bar: description: Bar. width: 40 + - BATT: + messages: + - BatteryStatus: + id: 0x12C + cycletime: 10 + signals: + - batteryPercent: + description: Battery percentage. + width: 10 diff --git a/components/SConscript.py b/components/SConscript.py index 02ec6be97..22d305822 100644 --- a/components/SConscript.py +++ b/components/SConscript.py @@ -13,6 +13,7 @@ 'steer', 'sup', 'throttle', + 'batt', ] ] ) diff --git a/components/batt/src/SConscript.py b/components/batt/src/SConscript.py new file mode 100644 index 000000000..e87bddba3 --- /dev/null +++ b/components/batt/src/SConscript.py @@ -0,0 +1,39 @@ +# ruff: noqa: F821 + +Import('env') + +node = 'BATT' + +opencan = env.OpenCan( + network=env['CAN']['NETWORK'], + node=node, +) + +source = [ + env.StaticObject( + src, + CPPDEFINES=[ + ('EMBER_NODE_IDENTITY', node), + '$CPPDEFINES', + ], + CPPPATH=[ + env.Dir(opencan[0].dir.name), + '$CPPPATH', + ], + ) + for src in [ + 'batt.c', # Ensure this file exists in your source directory + *env['LIBRARIES']['firmware-base'], + ] +] + +# Correct the typo in the variable name +source += opencan +source += env['LIBRARIES']['ember'] +source += env['LIBRARIES']['node-entry'] +source += env['LIBRARIES']['selfdrive'] + +batt = env.StaticLibrary(node.lower(), source)[0] +firmware, flash = env.EspIdf(batt, 'esp32s3') + +Return('firmware', 'flash') diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c index 8f973e69e..9ca1a746e 100644 --- a/components/batt/src/batt.c +++ b/components/batt/src/batt.c @@ -1,40 +1,26 @@ #include "batt.h" -#include "firmware-base/state-machine.h" #include -#include -#include #include #include #include -#include -// hypothetical battery percent data -typedef struct { - uint8_t batteryPercent; -} CAN_Message_BatteryStatus; - -static uint8_t batterypercent; +static uint8_t batteryPercent; static void batt_1Hz(); -// task scheduling ember_rate_funcs_S module_rf = { .call_1Hz = batt_1Hz, }; static void batt_1Hz() { - /* - Do I need any authorizationsfrom SUP? like - CANRX_is_message_battery_percent_data_Authorization_ok() - */ batteryPercent = 0; } -void CANTX_populate_BATT_BatteryPercentData( - struct CAN_Message_BatteryStatus * const m) +void CANTX_populate_BatteryStatus( + struct CAN_Message_BATT_BatteryStatus * const m) { - m->batteryPercent = batteryPercent; + m->BATT_batteryPercent = batteryPercent; } diff --git a/components/batt/src/firmware-base/SConscript.py b/components/batt/src/firmware-base/SConscript.py new file mode 100644 index 000000000..9d6e13fa6 --- /dev/null +++ b/components/batt/src/firmware-base/SConscript.py @@ -0,0 +1,20 @@ +# ruff: noqa: F821 + +Import('env') + + +# since this has to be compiled uniquely for each micro we'll leave this +# as strings so that we can symlink this directory and turn these into +# File() nodes +firmware_base = [ + f'firmware-base/{src}' + for src in [ + 'app-description.c', + 'eeprom.c', + 'eeprom_ember.c', + 'state-machine.c', + ] +] + + +Return('firmware_base') diff --git a/components/batt/src/firmware-base/app-description.c b/components/batt/src/firmware-base/app-description.c new file mode 100644 index 000000000..3dd7c4a0d --- /dev/null +++ b/components/batt/src/firmware-base/app-description.c @@ -0,0 +1,12 @@ +#include + +// stringification macros +#define XSTR(s) STR(s) +#define STR(s) #s + +const IN_DESC_SECTION ember_app_desc_v1_t ember_app_description = { + .ember_magic = EMBER_MAGIC, + .app_desc_version = EMBER_APP_DESC_VERSION, + + .node_identity = XSTR(EMBER_NODE_IDENTITY), +}; diff --git a/components/batt/src/firmware-base/eeprom.c b/components/batt/src/firmware-base/eeprom.c new file mode 100644 index 000000000..4d2aea4eb --- /dev/null +++ b/components/batt/src/firmware-base/eeprom.c @@ -0,0 +1,240 @@ +#include "eeprom.h" + +#include +#include +#include +#include + +#include + +#define EEPROM_PAGESIZ 64 +#define EEPROM_ADDR_I2C (0xa0 | (0x00 << 1)) +#define EEPROM_ADDR_MAX 0x7fff +#define EEPROM_SCL_GPIO NODE_BOARD_PIN_EEPROM_SCL +#define EEPROM_SDA_GPIO NODE_BOARD_PIN_EEPROM_SDA +#define EEPROM_WP_GPIO NODE_BOARD_PIN_EEPROM_WP +#define EEPROM_WP(ENABLE) gpio_set_level(EEPROM_WP_GPIO, ENABLE) + +#define I2C_ESP_INTR_FLAGS 0 +#define I2C_MASTER_FREQ_HZ 100000 +#define I2C_MASTER_NUM 0 +#define I2C_MASTER_RX_BUF 0 +#define I2C_MASTER_TX_BUF 0 +#define I2C_TICK_TIMEOUT 0 +#define I2C_WRITE 0 +#define I2C_READ 1 + +static esp_err_t sel_read(uint16_t addr); + +static uint16_t internal_addr; + +void eeprom_init() +{ + gpio_set_direction(EEPROM_WP_GPIO, GPIO_MODE_OUTPUT); + EEPROM_WP(true); + + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = EEPROM_SDA_GPIO, + .scl_io_num = EEPROM_SCL_GPIO, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_pullup_en = GPIO_PULLUP_DISABLE, + .master.clk_speed = I2C_MASTER_FREQ_HZ, + }; + + i2c_param_config(I2C_MASTER_NUM, &conf); + i2c_driver_install(I2C_MASTER_NUM, + I2C_MODE_MASTER, + I2C_MASTER_RX_BUF, + I2C_MASTER_TX_BUF, + I2C_ESP_INTR_FLAGS); + + // we want to know where we are in EEPROM + // in case of an immediate address read + // the following sets internal_addr to 0 + uint8_t tmp; + eeprom_read(EEPROM_ADDR_MAX, &tmp, 1); +} + +// sel_read attempts a selective read at the given address. +// can be used for acknowledge polling (to ensure EEPROM is not busy) +static esp_err_t sel_read(uint16_t addr) +{ + i2c_cmd_handle_t cmd; + uint8_t buf[2]; + uint8_t data[1]; + esp_err_t val = ESP_OK; + + buf[0] = addr >> 8; + buf[1] = addr & 0xff; + + cmd = i2c_cmd_link_create(); + if (!cmd) return ESP_ERR_NO_MEM; + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); + i2c_master_write(cmd, buf, sizeof(buf), true); + i2c_master_start(cmd); // Missing end signal is intentional + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_READ, true); + i2c_master_read(cmd, data, 1, I2C_MASTER_LAST_NACK); + i2c_master_stop(cmd); + + val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); + i2c_cmd_link_delete(cmd); + + return val; +} + +esp_err_t eeprom_read(uint16_t addr, uint8_t *data, size_t len) +{ + i2c_cmd_handle_t cmd; + uint8_t buf[2]; + esp_err_t val = ESP_OK; + + // mask MSB of the address to ensure + // we can compare w/ internal_addr + addr &= EEPROM_ADDR_MAX; + + buf[0] = addr >> 8; + buf[1] = addr & 0xff; + + // ensure we can read + while (true) { + val = sel_read(internal_addr); + if (val == ESP_OK) break; + + // when the EEPROM is busy writing it will + // not send an ACK, returning ESP_FAIL + if (val != ESP_FAIL) goto error; + } + + cmd = i2c_cmd_link_create(); + if (!cmd) return ESP_ERR_NO_MEM; + + if (internal_addr != addr) { // selective read at the given address + i2c_master_start(cmd); + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); + i2c_master_write(cmd, buf, sizeof(buf), true); + // missing end signal is intentional + } // otherwise, do an immediate access read (address not required) + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_READ, true); + i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK); + i2c_master_stop(cmd); + + val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); + i2c_cmd_link_delete(cmd); + + internal_addr = addr + len; + internal_addr &= EEPROM_ADDR_MAX; + +error: + return val; +} + +esp_err_t eeprom_write(uint16_t addr, const uint8_t *data, size_t len) +{ + i2c_cmd_handle_t cmd; + uint16_t page; + uint8_t offset, write_len; + uint8_t buf[2]; + esp_err_t val = ESP_OK; + + while (len) { + // mask MSB of the address to ensure correct calculations + addr &= EEPROM_ADDR_MAX; + + page = addr / EEPROM_PAGESIZ; + offset = addr % EEPROM_PAGESIZ; + buf[0] = page >> 2; + buf[1] = ((page & 0x03) << 6) | offset; + + // we don't want to write too much + // since we can only write maximum one page at at time + write_len = EEPROM_PAGESIZ - offset; + if (write_len > len) write_len = len; + + // ensure we can write + while (true) { + val = sel_read(internal_addr); + if (val == ESP_OK) break; + + // when the EEPROM is busy writing it will + // not send an ACK, returning ESP_FAIL + if (val != ESP_FAIL) goto error; + } + + cmd = i2c_cmd_link_create(); + if (!cmd) return ESP_ERR_NO_MEM; + + // WP is always enabled after sel_read() call + EEPROM_WP(false); + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); + i2c_master_write(cmd, buf, sizeof(buf), true); + i2c_master_write(cmd, data, write_len, true); + i2c_master_stop(cmd); + + val = i2c_master_cmd_begin( + I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); + i2c_cmd_link_delete(cmd); + if (val != ESP_OK) goto error; + + addr += write_len; + internal_addr = addr; + internal_addr &= EEPROM_ADDR_MAX; + + data += write_len; + len -= write_len; + } + +error: + EEPROM_WP(true); + + return val; +} + +esp_err_t eeprom_write_byte(uint16_t addr, const uint8_t data) +{ + i2c_cmd_handle_t cmd; + uint8_t buf[3]; + esp_err_t val = ESP_OK; + + // ensure we can write + while (true) { + val = sel_read(internal_addr); + if (val == ESP_OK) break; + + // when the EEPROM is busy writing it will + // not send an ACK, returning ESP_FAIL + if (val != ESP_FAIL) goto error; + } + + buf[0] = addr >> 8; + buf[1] = addr & 0xff; + buf[2] = data; + + cmd = i2c_cmd_link_create(); + if (!cmd) return ESP_ERR_NO_MEM; + + // WP is always enabled after sel_read() call + EEPROM_WP(false); + + i2c_master_start(cmd); + i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); + i2c_master_write(cmd, buf, sizeof(buf), true); + i2c_master_stop(cmd); + + val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); + i2c_cmd_link_delete(cmd); + + EEPROM_WP(true); + + internal_addr = addr + 1; + internal_addr &= EEPROM_ADDR_MAX; + +error: + return val; +} diff --git a/components/batt/src/firmware-base/eeprom.h b/components/batt/src/firmware-base/eeprom.h new file mode 100644 index 000000000..ae87e1e75 --- /dev/null +++ b/components/batt/src/firmware-base/eeprom.h @@ -0,0 +1,15 @@ +#ifndef EEPROM_H +#define EEPROM_H + +#include + +#include +#include + +void eeprom_init(void); + +esp_err_t eeprom_read(uint16_t addr, uint8_t *data, size_t len); +esp_err_t eeprom_write(uint16_t addr, const uint8_t *data, size_t len); +esp_err_t eeprom_write_byte(uint16_t addr, uint8_t data); + +#endif // EEPROM_H diff --git a/components/batt/src/firmware-base/eeprom_ember.c b/components/batt/src/firmware-base/eeprom_ember.c new file mode 100644 index 000000000..b1910fe0d --- /dev/null +++ b/components/batt/src/firmware-base/eeprom_ember.c @@ -0,0 +1,10 @@ +#ifdef _EMBER + +#include "eeprom.h" +#include + +ember_rate_funcs_S eeprom_rf = { + .call_init = eeprom_init, +}; + +#endif // _EMBER diff --git a/components/batt/src/firmware-base/state-machine.c b/components/batt/src/firmware-base/state-machine.c new file mode 100644 index 000000000..a8be43909 --- /dev/null +++ b/components/batt/src/firmware-base/state-machine.c @@ -0,0 +1,316 @@ +#include "state-machine.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED +#include +#endif + +#define LED1_PIN NODE_BOARD_PIN_LED1 +#define LED2_PIN NODE_BOARD_PIN_LED2 + +static void set_status_LEDs(); +static void base_init(); +static void base_10Hz(); +static void base_100Hz(); + +static enum sys_states sys_state = SYS_STATE_UNDEF; +static enum sys_states requested_state = SYS_STATE_UNDEF; + +static bool wdt_trigger; + +static RESET_REASON reset_reason; + +#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED +static float tsens_value; +temperature_sensor_handle_t temp_sensor = NULL; +#endif + +ember_rate_funcs_S base_rf = { + .call_init = base_init, + .call_10Hz = base_10Hz, + .call_100Hz = base_100Hz, +}; + +static void base_init() +{ + base_request_state(SYS_STATE_IDLE); + + gpio_config(&(gpio_config_t){ + .pin_bit_mask = BIT64(LED1_PIN) | BIT64(LED2_PIN), + .mode = GPIO_MODE_OUTPUT, + }); + + gpio_set_level(LED1_PIN, 0); + gpio_set_level(LED2_PIN, 0); + + +#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED + temperature_sensor_config_t temp_sensor_config + = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-30, 50); + temperature_sensor_install(&temp_sensor_config, &temp_sensor); + temperature_sensor_enable(temp_sensor); +#endif + + reset_reason = rtc_get_reset_reason(0); +} + +static void base_10Hz() +{ + set_status_LEDs(); + + /* critical section */ + portDISABLE_INTERRUPTS(); + { + if (CANRX_is_node_UPD_ok() + && CANRX_getRaw_UPD_currentIsoTpChunk() == 0U) { + if (sys_state != SYS_STATE_DBW_ACTIVE) { + /* It's update time. No going back; we will + * reboot. */ + + /* + * Set the RTC watchdog timeout to 1 second to + * give us some time since the + * task_wdt_servicer() is not running anymore. + */ + set_up_rtc_watchdog_1sec(); + + /* Reboot */ + esp_restart(); + } + } + } + portENABLE_INTERRUPTS(); +} + +static void base_100Hz() +{ + if (sys_state == SYS_STATE_ESTOP) return; + + if (sys_state == SYS_STATE_IDLE + && requested_state == SYS_STATE_DBW_ACTIVE) { + sys_state = requested_state; + return; + } + + sys_state = requested_state; +} + +static void set_status_LEDs() +{ + static bool led1_state; + static bool led2_state; + static uint timer; + + switch (sys_state) { + case SYS_STATE_UNDEF: + if (!(timer % 2)) { + led1_state = !led1_state; + led2_state = !led2_state; + } + break; + + case SYS_STATE_IDLE: + led1_state = 1; + if (!(timer % 1)) { + led2_state = !led2_state; + } + break; + + case SYS_STATE_DBW_ACTIVE: + led1_state = 1; + if (!(timer % 2)) { + led2_state = !led2_state; + } + break; + + case SYS_STATE_LOST_CAN: + led2_state = 1; + if (!(timer % 2)) { + led1_state = !led1_state; + } + break; + + case SYS_STATE_ESTOP: + led2_state = 1; + led1_state = !led1_state; + break; + + default: + led1_state = !led1_state; + led2_state = !led2_state; + break; + } + + if (wdt_trigger) { + led1_state = 1; + led2_state = 1; + } + + gpio_set_level(LED1_PIN, led1_state); + gpio_set_level(LED2_PIN, led2_state); + + timer++; +} + +enum sys_states base_get_state(void) +{ + return sys_state; +} + +void base_request_state(enum sys_states state) +{ + requested_state = state; +} + +void base_set_wdt_trigger(void) +{ + wdt_trigger = true; +} + +void ember_can_callback_notify_lost_can(void) +{ + sys_state = SYS_STATE_LOST_CAN; +} + +void CANRX_onRxCallback_DBW_ESTOP( + const struct CAN_MessageRaw_DBW_ESTOP * const raw, + const struct CAN_Message_DBW_ESTOP * const dec) +{ + (void) raw; + (void) dec; + + sys_state = SYS_STATE_ESTOP; +} + +void CANTX_populateTemplate_NodeStatus( + struct CAN_TMessage_DBWNodeStatus * const m) +{ + switch (sys_state) { + case SYS_STATE_UNDEF: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_UNDEF; + break; + + case SYS_STATE_INIT: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_INIT; + break; + + case SYS_STATE_IDLE: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_IDLE; + break; + + case SYS_STATE_DBW_ACTIVE: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_ACTIVE; + break; + + case SYS_STATE_LOST_CAN: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_LOST_CAN; + break; + + case SYS_STATE_BAD: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_BAD; + break; + + case SYS_STATE_ESTOP: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_ESTOP; + break; + + default: + m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_UNDEF; + break; + } + + switch (requested_state) { + case SYS_STATE_UNDEF: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_UNDEF; + break; + + case SYS_STATE_INIT: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_INIT; + break; + + case SYS_STATE_IDLE: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_IDLE; + break; + + case SYS_STATE_DBW_ACTIVE: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_ACTIVE; + break; + + case SYS_STATE_LOST_CAN: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_LOST_CAN; + break; + + case SYS_STATE_BAD: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_BAD; + break; + + case SYS_STATE_ESTOP: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_ESTOP; + break; + + default: + m->requestedSysStatus + = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_UNDEF; + break; + } + +#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED + if (temperature_sensor_get_celsius(temp_sensor, &tsens_value) + != ESP_OK) + tsens_value = 0.0; + m->temperature = tsens_value; +#else + m->temperature = -31.0; +#endif + + static typeof(m->counter) counter; + m->counter = counter++; + + switch (reset_reason) { + case POWERON_RESET: + m->resetReason + = CAN_T_DBWNODESTATUS_RESETREASON_POWERON; + break; + case RTC_SW_CPU_RESET: + m->resetReason + = CAN_T_DBWNODESTATUS_RESETREASON_SW_RESET; + break; + case RTCWDT_RTC_RESET: + m->resetReason + = CAN_T_DBWNODESTATUS_RESETREASON_WATCHDOG_RESET; + break; + default: + m->resetReason + = CAN_T_DBWNODESTATUS_RESETREASON_UNKNOWN; + break; + } + + m->esp32ResetReasonCode = reset_reason; +} + +void CANTX_populateTemplate_NodeInfo(struct CAN_TMessage_DBWNodeInfo * const m) +{ + // TODO: reintegrate git + m->gitHash = 0; + m->gitDirty = 0; + + m->eepromIdentity = 0; // no eeprom identity at the moment +} diff --git a/components/batt/src/firmware-base/state-machine.h b/components/batt/src/firmware-base/state-machine.h new file mode 100644 index 000000000..f69c2a5ea --- /dev/null +++ b/components/batt/src/firmware-base/state-machine.h @@ -0,0 +1,17 @@ +#ifndef STATE_MACHINE_H +#define STATE_MACHINE_H + +enum sys_states { + SYS_STATE_UNDEF = 0, + SYS_STATE_INIT, + SYS_STATE_IDLE, + SYS_STATE_DBW_ACTIVE, + SYS_STATE_LOST_CAN, + SYS_STATE_BAD, + SYS_STATE_ESTOP, +}; + +enum sys_states base_get_state(void); +void base_request_state(enum sys_states state); + +#endif // STATE_MACHINE_H diff --git a/components/sup/src/firmware-base b/components/sup/src/firmware-base deleted file mode 120000 index e5db25672..000000000 --- a/components/sup/src/firmware-base +++ /dev/null @@ -1 +0,0 @@ -../../../lib/firmware-base \ No newline at end of file From 0dfd2d038619c2fe4061d82cc45ee55627d47798 Mon Sep 17 00:00:00 2001 From: Siann Date: Wed, 28 Aug 2024 17:24:18 -0400 Subject: [PATCH 4/8] updated BATT and BATTBL in network.yml --- can/network.yml | 29 +++++++++++++++++++++++++++++ components/batt/src/batt.c | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/can/network.yml b/can/network.yml index 9e273f604..39f100a40 100644 --- a/can/network.yml +++ b/can/network.yml @@ -703,6 +703,11 @@ nodes: - THROTTLE_NodeStatus - THROTTLEBL_IsoTpTx - THROTTLEBL_Status + + - BATT_NodeStatus + - BATTBL_IsoTpTx + - BATTBL_Status + messages: - IsoTpTx_BBC: id: 0x531 @@ -714,6 +719,8 @@ nodes: id: 0x534 - IsoTpTx_THROTTLE: id: 0x535 + - IsoTpTx_BATT: + id: 0x536 - UpdateControl_BBC: from_template: UpdateControl id: 0x5A1 @@ -729,6 +736,9 @@ nodes: - UpdateControl_THROTTLE: from_template: UpdateControl id: 0x5A5 + - UpdateControl_BATT: + from_template: UpdateControl + id: 0x5A6 - THROTTLE: rx: @@ -806,7 +816,16 @@ nodes: description: Bar. width: 40 - BATT: + rx: + - DBW_ESTOP + - UPD_UpdateControl_BATT messages: + - NodeInfo: + from_template: DBWNodeInfo + id: 0x12A + - NodeStatus: + from_template: DBWNodeStatus + id: 0x12D - BatteryStatus: id: 0x12C cycletime: 10 @@ -814,3 +833,13 @@ nodes: - batteryPercent: description: Battery percentage. width: 10 + - BATTBL: + rx: + - UPD_IsoTpTx_BATT + - UPD_UpdateControl_BATT + messages: + - IsoTpTx: + id: 0x12E + - Status: + from_template: BlStatus + id: 0x12F diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c index 9ca1a746e..bcb2dccc9 100644 --- a/components/batt/src/batt.c +++ b/components/batt/src/batt.c @@ -19,7 +19,7 @@ static void batt_1Hz() batteryPercent = 0; } -void CANTX_populate_BatteryStatus( +void CANTX_populate_BATT_BatteryStatus( struct CAN_Message_BATT_BatteryStatus * const m) { m->BATT_batteryPercent = batteryPercent; From 239458ff6ea8c7b5a79c9edb0102b17fbec679c1 Mon Sep 17 00:00:00 2001 From: Siann Date: Wed, 28 Aug 2024 17:50:16 -0400 Subject: [PATCH 5/8] firmware-base symlink BATT --- components/batt/src/firmware-base | 1 + .../batt/src/firmware-base/SConscript.py | 20 -- .../batt/src/firmware-base/app-description.c | 12 - components/batt/src/firmware-base/eeprom.c | 240 ------------- components/batt/src/firmware-base/eeprom.h | 15 - .../batt/src/firmware-base/eeprom_ember.c | 10 - .../batt/src/firmware-base/state-machine.c | 316 ------------------ .../batt/src/firmware-base/state-machine.h | 17 - 8 files changed, 1 insertion(+), 630 deletions(-) create mode 120000 components/batt/src/firmware-base delete mode 100644 components/batt/src/firmware-base/SConscript.py delete mode 100644 components/batt/src/firmware-base/app-description.c delete mode 100644 components/batt/src/firmware-base/eeprom.c delete mode 100644 components/batt/src/firmware-base/eeprom.h delete mode 100644 components/batt/src/firmware-base/eeprom_ember.c delete mode 100644 components/batt/src/firmware-base/state-machine.c delete mode 100644 components/batt/src/firmware-base/state-machine.h diff --git a/components/batt/src/firmware-base b/components/batt/src/firmware-base new file mode 120000 index 000000000..4ab11f766 --- /dev/null +++ b/components/batt/src/firmware-base @@ -0,0 +1 @@ +../../../lib/firmware-base/ \ No newline at end of file diff --git a/components/batt/src/firmware-base/SConscript.py b/components/batt/src/firmware-base/SConscript.py deleted file mode 100644 index 9d6e13fa6..000000000 --- a/components/batt/src/firmware-base/SConscript.py +++ /dev/null @@ -1,20 +0,0 @@ -# ruff: noqa: F821 - -Import('env') - - -# since this has to be compiled uniquely for each micro we'll leave this -# as strings so that we can symlink this directory and turn these into -# File() nodes -firmware_base = [ - f'firmware-base/{src}' - for src in [ - 'app-description.c', - 'eeprom.c', - 'eeprom_ember.c', - 'state-machine.c', - ] -] - - -Return('firmware_base') diff --git a/components/batt/src/firmware-base/app-description.c b/components/batt/src/firmware-base/app-description.c deleted file mode 100644 index 3dd7c4a0d..000000000 --- a/components/batt/src/firmware-base/app-description.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -// stringification macros -#define XSTR(s) STR(s) -#define STR(s) #s - -const IN_DESC_SECTION ember_app_desc_v1_t ember_app_description = { - .ember_magic = EMBER_MAGIC, - .app_desc_version = EMBER_APP_DESC_VERSION, - - .node_identity = XSTR(EMBER_NODE_IDENTITY), -}; diff --git a/components/batt/src/firmware-base/eeprom.c b/components/batt/src/firmware-base/eeprom.c deleted file mode 100644 index 4d2aea4eb..000000000 --- a/components/batt/src/firmware-base/eeprom.c +++ /dev/null @@ -1,240 +0,0 @@ -#include "eeprom.h" - -#include -#include -#include -#include - -#include - -#define EEPROM_PAGESIZ 64 -#define EEPROM_ADDR_I2C (0xa0 | (0x00 << 1)) -#define EEPROM_ADDR_MAX 0x7fff -#define EEPROM_SCL_GPIO NODE_BOARD_PIN_EEPROM_SCL -#define EEPROM_SDA_GPIO NODE_BOARD_PIN_EEPROM_SDA -#define EEPROM_WP_GPIO NODE_BOARD_PIN_EEPROM_WP -#define EEPROM_WP(ENABLE) gpio_set_level(EEPROM_WP_GPIO, ENABLE) - -#define I2C_ESP_INTR_FLAGS 0 -#define I2C_MASTER_FREQ_HZ 100000 -#define I2C_MASTER_NUM 0 -#define I2C_MASTER_RX_BUF 0 -#define I2C_MASTER_TX_BUF 0 -#define I2C_TICK_TIMEOUT 0 -#define I2C_WRITE 0 -#define I2C_READ 1 - -static esp_err_t sel_read(uint16_t addr); - -static uint16_t internal_addr; - -void eeprom_init() -{ - gpio_set_direction(EEPROM_WP_GPIO, GPIO_MODE_OUTPUT); - EEPROM_WP(true); - - i2c_config_t conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = EEPROM_SDA_GPIO, - .scl_io_num = EEPROM_SCL_GPIO, - .sda_pullup_en = GPIO_PULLUP_DISABLE, - .scl_pullup_en = GPIO_PULLUP_DISABLE, - .master.clk_speed = I2C_MASTER_FREQ_HZ, - }; - - i2c_param_config(I2C_MASTER_NUM, &conf); - i2c_driver_install(I2C_MASTER_NUM, - I2C_MODE_MASTER, - I2C_MASTER_RX_BUF, - I2C_MASTER_TX_BUF, - I2C_ESP_INTR_FLAGS); - - // we want to know where we are in EEPROM - // in case of an immediate address read - // the following sets internal_addr to 0 - uint8_t tmp; - eeprom_read(EEPROM_ADDR_MAX, &tmp, 1); -} - -// sel_read attempts a selective read at the given address. -// can be used for acknowledge polling (to ensure EEPROM is not busy) -static esp_err_t sel_read(uint16_t addr) -{ - i2c_cmd_handle_t cmd; - uint8_t buf[2]; - uint8_t data[1]; - esp_err_t val = ESP_OK; - - buf[0] = addr >> 8; - buf[1] = addr & 0xff; - - cmd = i2c_cmd_link_create(); - if (!cmd) return ESP_ERR_NO_MEM; - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); - i2c_master_write(cmd, buf, sizeof(buf), true); - i2c_master_start(cmd); // Missing end signal is intentional - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_READ, true); - i2c_master_read(cmd, data, 1, I2C_MASTER_LAST_NACK); - i2c_master_stop(cmd); - - val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); - i2c_cmd_link_delete(cmd); - - return val; -} - -esp_err_t eeprom_read(uint16_t addr, uint8_t *data, size_t len) -{ - i2c_cmd_handle_t cmd; - uint8_t buf[2]; - esp_err_t val = ESP_OK; - - // mask MSB of the address to ensure - // we can compare w/ internal_addr - addr &= EEPROM_ADDR_MAX; - - buf[0] = addr >> 8; - buf[1] = addr & 0xff; - - // ensure we can read - while (true) { - val = sel_read(internal_addr); - if (val == ESP_OK) break; - - // when the EEPROM is busy writing it will - // not send an ACK, returning ESP_FAIL - if (val != ESP_FAIL) goto error; - } - - cmd = i2c_cmd_link_create(); - if (!cmd) return ESP_ERR_NO_MEM; - - if (internal_addr != addr) { // selective read at the given address - i2c_master_start(cmd); - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); - i2c_master_write(cmd, buf, sizeof(buf), true); - // missing end signal is intentional - } // otherwise, do an immediate access read (address not required) - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_READ, true); - i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK); - i2c_master_stop(cmd); - - val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); - i2c_cmd_link_delete(cmd); - - internal_addr = addr + len; - internal_addr &= EEPROM_ADDR_MAX; - -error: - return val; -} - -esp_err_t eeprom_write(uint16_t addr, const uint8_t *data, size_t len) -{ - i2c_cmd_handle_t cmd; - uint16_t page; - uint8_t offset, write_len; - uint8_t buf[2]; - esp_err_t val = ESP_OK; - - while (len) { - // mask MSB of the address to ensure correct calculations - addr &= EEPROM_ADDR_MAX; - - page = addr / EEPROM_PAGESIZ; - offset = addr % EEPROM_PAGESIZ; - buf[0] = page >> 2; - buf[1] = ((page & 0x03) << 6) | offset; - - // we don't want to write too much - // since we can only write maximum one page at at time - write_len = EEPROM_PAGESIZ - offset; - if (write_len > len) write_len = len; - - // ensure we can write - while (true) { - val = sel_read(internal_addr); - if (val == ESP_OK) break; - - // when the EEPROM is busy writing it will - // not send an ACK, returning ESP_FAIL - if (val != ESP_FAIL) goto error; - } - - cmd = i2c_cmd_link_create(); - if (!cmd) return ESP_ERR_NO_MEM; - - // WP is always enabled after sel_read() call - EEPROM_WP(false); - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); - i2c_master_write(cmd, buf, sizeof(buf), true); - i2c_master_write(cmd, data, write_len, true); - i2c_master_stop(cmd); - - val = i2c_master_cmd_begin( - I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); - i2c_cmd_link_delete(cmd); - if (val != ESP_OK) goto error; - - addr += write_len; - internal_addr = addr; - internal_addr &= EEPROM_ADDR_MAX; - - data += write_len; - len -= write_len; - } - -error: - EEPROM_WP(true); - - return val; -} - -esp_err_t eeprom_write_byte(uint16_t addr, const uint8_t data) -{ - i2c_cmd_handle_t cmd; - uint8_t buf[3]; - esp_err_t val = ESP_OK; - - // ensure we can write - while (true) { - val = sel_read(internal_addr); - if (val == ESP_OK) break; - - // when the EEPROM is busy writing it will - // not send an ACK, returning ESP_FAIL - if (val != ESP_FAIL) goto error; - } - - buf[0] = addr >> 8; - buf[1] = addr & 0xff; - buf[2] = data; - - cmd = i2c_cmd_link_create(); - if (!cmd) return ESP_ERR_NO_MEM; - - // WP is always enabled after sel_read() call - EEPROM_WP(false); - - i2c_master_start(cmd); - i2c_master_write_byte(cmd, EEPROM_ADDR_I2C | I2C_WRITE, true); - i2c_master_write(cmd, buf, sizeof(buf), true); - i2c_master_stop(cmd); - - val = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_TICK_TIMEOUT); - i2c_cmd_link_delete(cmd); - - EEPROM_WP(true); - - internal_addr = addr + 1; - internal_addr &= EEPROM_ADDR_MAX; - -error: - return val; -} diff --git a/components/batt/src/firmware-base/eeprom.h b/components/batt/src/firmware-base/eeprom.h deleted file mode 100644 index ae87e1e75..000000000 --- a/components/batt/src/firmware-base/eeprom.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef EEPROM_H -#define EEPROM_H - -#include - -#include -#include - -void eeprom_init(void); - -esp_err_t eeprom_read(uint16_t addr, uint8_t *data, size_t len); -esp_err_t eeprom_write(uint16_t addr, const uint8_t *data, size_t len); -esp_err_t eeprom_write_byte(uint16_t addr, uint8_t data); - -#endif // EEPROM_H diff --git a/components/batt/src/firmware-base/eeprom_ember.c b/components/batt/src/firmware-base/eeprom_ember.c deleted file mode 100644 index b1910fe0d..000000000 --- a/components/batt/src/firmware-base/eeprom_ember.c +++ /dev/null @@ -1,10 +0,0 @@ -#ifdef _EMBER - -#include "eeprom.h" -#include - -ember_rate_funcs_S eeprom_rf = { - .call_init = eeprom_init, -}; - -#endif // _EMBER diff --git a/components/batt/src/firmware-base/state-machine.c b/components/batt/src/firmware-base/state-machine.c deleted file mode 100644 index a8be43909..000000000 --- a/components/batt/src/firmware-base/state-machine.c +++ /dev/null @@ -1,316 +0,0 @@ -#include "state-machine.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED -#include -#endif - -#define LED1_PIN NODE_BOARD_PIN_LED1 -#define LED2_PIN NODE_BOARD_PIN_LED2 - -static void set_status_LEDs(); -static void base_init(); -static void base_10Hz(); -static void base_100Hz(); - -static enum sys_states sys_state = SYS_STATE_UNDEF; -static enum sys_states requested_state = SYS_STATE_UNDEF; - -static bool wdt_trigger; - -static RESET_REASON reset_reason; - -#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED -static float tsens_value; -temperature_sensor_handle_t temp_sensor = NULL; -#endif - -ember_rate_funcs_S base_rf = { - .call_init = base_init, - .call_10Hz = base_10Hz, - .call_100Hz = base_100Hz, -}; - -static void base_init() -{ - base_request_state(SYS_STATE_IDLE); - - gpio_config(&(gpio_config_t){ - .pin_bit_mask = BIT64(LED1_PIN) | BIT64(LED2_PIN), - .mode = GPIO_MODE_OUTPUT, - }); - - gpio_set_level(LED1_PIN, 0); - gpio_set_level(LED2_PIN, 0); - - -#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED - temperature_sensor_config_t temp_sensor_config - = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-30, 50); - temperature_sensor_install(&temp_sensor_config, &temp_sensor); - temperature_sensor_enable(temp_sensor); -#endif - - reset_reason = rtc_get_reset_reason(0); -} - -static void base_10Hz() -{ - set_status_LEDs(); - - /* critical section */ - portDISABLE_INTERRUPTS(); - { - if (CANRX_is_node_UPD_ok() - && CANRX_getRaw_UPD_currentIsoTpChunk() == 0U) { - if (sys_state != SYS_STATE_DBW_ACTIVE) { - /* It's update time. No going back; we will - * reboot. */ - - /* - * Set the RTC watchdog timeout to 1 second to - * give us some time since the - * task_wdt_servicer() is not running anymore. - */ - set_up_rtc_watchdog_1sec(); - - /* Reboot */ - esp_restart(); - } - } - } - portENABLE_INTERRUPTS(); -} - -static void base_100Hz() -{ - if (sys_state == SYS_STATE_ESTOP) return; - - if (sys_state == SYS_STATE_IDLE - && requested_state == SYS_STATE_DBW_ACTIVE) { - sys_state = requested_state; - return; - } - - sys_state = requested_state; -} - -static void set_status_LEDs() -{ - static bool led1_state; - static bool led2_state; - static uint timer; - - switch (sys_state) { - case SYS_STATE_UNDEF: - if (!(timer % 2)) { - led1_state = !led1_state; - led2_state = !led2_state; - } - break; - - case SYS_STATE_IDLE: - led1_state = 1; - if (!(timer % 1)) { - led2_state = !led2_state; - } - break; - - case SYS_STATE_DBW_ACTIVE: - led1_state = 1; - if (!(timer % 2)) { - led2_state = !led2_state; - } - break; - - case SYS_STATE_LOST_CAN: - led2_state = 1; - if (!(timer % 2)) { - led1_state = !led1_state; - } - break; - - case SYS_STATE_ESTOP: - led2_state = 1; - led1_state = !led1_state; - break; - - default: - led1_state = !led1_state; - led2_state = !led2_state; - break; - } - - if (wdt_trigger) { - led1_state = 1; - led2_state = 1; - } - - gpio_set_level(LED1_PIN, led1_state); - gpio_set_level(LED2_PIN, led2_state); - - timer++; -} - -enum sys_states base_get_state(void) -{ - return sys_state; -} - -void base_request_state(enum sys_states state) -{ - requested_state = state; -} - -void base_set_wdt_trigger(void) -{ - wdt_trigger = true; -} - -void ember_can_callback_notify_lost_can(void) -{ - sys_state = SYS_STATE_LOST_CAN; -} - -void CANRX_onRxCallback_DBW_ESTOP( - const struct CAN_MessageRaw_DBW_ESTOP * const raw, - const struct CAN_Message_DBW_ESTOP * const dec) -{ - (void) raw; - (void) dec; - - sys_state = SYS_STATE_ESTOP; -} - -void CANTX_populateTemplate_NodeStatus( - struct CAN_TMessage_DBWNodeStatus * const m) -{ - switch (sys_state) { - case SYS_STATE_UNDEF: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_UNDEF; - break; - - case SYS_STATE_INIT: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_INIT; - break; - - case SYS_STATE_IDLE: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_IDLE; - break; - - case SYS_STATE_DBW_ACTIVE: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_ACTIVE; - break; - - case SYS_STATE_LOST_CAN: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_LOST_CAN; - break; - - case SYS_STATE_BAD: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_BAD; - break; - - case SYS_STATE_ESTOP: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_ESTOP; - break; - - default: - m->sysStatus = CAN_T_DBWNODESTATUS_SYSSTATUS_UNDEF; - break; - } - - switch (requested_state) { - case SYS_STATE_UNDEF: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_UNDEF; - break; - - case SYS_STATE_INIT: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_INIT; - break; - - case SYS_STATE_IDLE: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_IDLE; - break; - - case SYS_STATE_DBW_ACTIVE: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_ACTIVE; - break; - - case SYS_STATE_LOST_CAN: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_LOST_CAN; - break; - - case SYS_STATE_BAD: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_BAD; - break; - - case SYS_STATE_ESTOP: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_ESTOP; - break; - - default: - m->requestedSysStatus - = CAN_T_DBWNODESTATUS_REQUESTEDSYSSTATUS_UNDEF; - break; - } - -#if CONFIG_SOC_TEMP_SENSOR_SUPPORTED - if (temperature_sensor_get_celsius(temp_sensor, &tsens_value) - != ESP_OK) - tsens_value = 0.0; - m->temperature = tsens_value; -#else - m->temperature = -31.0; -#endif - - static typeof(m->counter) counter; - m->counter = counter++; - - switch (reset_reason) { - case POWERON_RESET: - m->resetReason - = CAN_T_DBWNODESTATUS_RESETREASON_POWERON; - break; - case RTC_SW_CPU_RESET: - m->resetReason - = CAN_T_DBWNODESTATUS_RESETREASON_SW_RESET; - break; - case RTCWDT_RTC_RESET: - m->resetReason - = CAN_T_DBWNODESTATUS_RESETREASON_WATCHDOG_RESET; - break; - default: - m->resetReason - = CAN_T_DBWNODESTATUS_RESETREASON_UNKNOWN; - break; - } - - m->esp32ResetReasonCode = reset_reason; -} - -void CANTX_populateTemplate_NodeInfo(struct CAN_TMessage_DBWNodeInfo * const m) -{ - // TODO: reintegrate git - m->gitHash = 0; - m->gitDirty = 0; - - m->eepromIdentity = 0; // no eeprom identity at the moment -} diff --git a/components/batt/src/firmware-base/state-machine.h b/components/batt/src/firmware-base/state-machine.h deleted file mode 100644 index f69c2a5ea..000000000 --- a/components/batt/src/firmware-base/state-machine.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef STATE_MACHINE_H -#define STATE_MACHINE_H - -enum sys_states { - SYS_STATE_UNDEF = 0, - SYS_STATE_INIT, - SYS_STATE_IDLE, - SYS_STATE_DBW_ACTIVE, - SYS_STATE_LOST_CAN, - SYS_STATE_BAD, - SYS_STATE_ESTOP, -}; - -enum sys_states base_get_state(void); -void base_request_state(enum sys_states state); - -#endif // STATE_MACHINE_H From bc81fcafbe85d24049af000ddd979eedac84de77 Mon Sep 17 00:00:00 2001 From: Siann Date: Tue, 3 Sep 2024 17:12:16 -0400 Subject: [PATCH 6/8] sup symlink --- components/sup/src/firmware-base | 1 + 1 file changed, 1 insertion(+) create mode 120000 components/sup/src/firmware-base diff --git a/components/sup/src/firmware-base b/components/sup/src/firmware-base new file mode 120000 index 000000000..e5db25672 --- /dev/null +++ b/components/sup/src/firmware-base @@ -0,0 +1 @@ +../../../lib/firmware-base \ No newline at end of file From 835eb8e70b4b4801762985fe69486e5d7731e388 Mon Sep 17 00:00:00 2001 From: Siann Date: Wed, 16 Oct 2024 21:46:30 -0400 Subject: [PATCH 7/8] added adc task initialization and reading at 256hz (un-working) --- components/batt/src/batt.c | 212 ++++++++++++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 2 deletions(-) diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c index bcb2dccc9..b134b02bd 100644 --- a/components/batt/src/batt.c +++ b/components/batt/src/batt.c @@ -1,21 +1,110 @@ #include "batt.h" #include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#define ADC_TASK_STACK_SIZE 2048 +#define SAMPLING_RATE_HZ 256 +#define SAMPLES 256 +#define FRAME_SAMPLES 128 +#define FRAME_SIZE \ + (sizeof(adc_digi_output_data_t) * FRAME_SAMPLES * ADC_CHANNELS) + +#define SAMPLES_OUT_SIZE 1024 // how to decide the size of the output +#define PREV_SAMPLES_DELAY 0.010 // why is this the delay time +#define PREV_SAMPLES_SIZE (size_t)(PREV_SAMPLES_DELAY * SAMPLING_RATE_HZ) + +#define POOL_SIZE (FRAME_SIZE * 2) + +#define ADC_CONV ADC_CONV_SINGLE_UNIT_1 +#define ADC_DIGI_OUTPUT_FORMAT ADC_DIGI_OUTPUT_FORMAT_TYPE2 + +#define BV_ADC_ATTEN ADC_ATTEN_DB_12 +#define BV_ADC_UNIT ADC_UNIT_2 +#define BV_ADC_CHANNEL ADC_CHANNEL_7 // GPIO_8 +#define BV_ADC_BITWIDTH SOC_ADC_DIGI_MAX_BITWIDTH + +// #define PWM_PIN GPIO_NUM_37 +// #define PWM_FREQUENCY 1000 +// #define PWM_INIT_DUTY_CYCLE 0 +// #define PWM_RESOLUTION 10 + +adc_continuous_handle_t handle = NULL; +static uint16_t out_buf[SAMPLES_OUT_SIZE]; +static size_t readIndex; +static size_t writeIndex; + +// static ledc_timer_config_t pwm_timer = { +// .speed_mode = LEDC_LOW_SPEED_MODE, +// .duty_resolution = PWM_RESOLUTION, +// .timer_num = LEDC_TIMER_0, +// .freq_hz = PWM_FREQUENCY, +// }; +// +// static ledc_channel_config_t pwm_channel = { +// .gpio_num = PWM_PIN, +// .speed_mode = LEDC_LOW_SPEED_MODE, +// .channel = LEDC_CHANNEL_0, +// .intr_type = LEDC_INTR_DISABLE, +// .timer_sel = LEDC_TIMER_0, +// .duty = PWM_INIT_DUTY_CYCLE, +// }; + +enum adc_channel_index { + BV_ADC_CHANNEL_INDEX, + ADC_CHANNELS, +}; + static uint8_t batteryPercent; +static void batt_init(); +static void batt_1Hz(); +static void adc_init(); -static void batt_1Hz(); +static void adc_task(); +static bool adc_callback(adc_continuous_handle_t handle, + const adc_continuous_evt_data_t *cbs, + void *user_data); + +static void samples_out(); + +struct samples { + uint16_t raw[SAMPLES]; + // float filtered[SAMPLES]; + size_t index; +}; + +static struct { + SemaphoreHandle_t sem; + adc_continuous_handle_t handle; + TaskHandle_t task_handle; + struct samples samples[ADC_CHANNELS]; +} adc; ember_rate_funcs_S module_rf = { - .call_1Hz = batt_1Hz, + .call_init = batt_init, + .call_1Hz = batt_1Hz, }; +static void batt_init() +{ + // ledc_timer_config(&pwm_timer); + // ledc_channel_config(&pwm_channel); + adc_init(); +} + static void batt_1Hz() { + printf("hi\n"); batteryPercent = 0; } @@ -24,3 +113,122 @@ void CANTX_populate_BATT_BatteryStatus( { m->BATT_batteryPercent = batteryPercent; } + +// initialization +static void adc_init() +{ + // overflow = false; + adc.sem = xSemaphoreCreateBinary(); + + // create task + xTaskCreatePinnedToCore(adc_task, + "adc_task", + ADC_TASK_STACK_SIZE, + NULL, + 1, + &adc.task_handle, + 1); + + + // adc resource allocation + adc_continuous_handle_cfg_t handle_config = { + .max_store_buf_size = POOL_SIZE, + .conv_frame_size = FRAME_SIZE, + }; + + ESP_ERROR_CHECK( + adc_continuous_new_handle(&handle_config, &adc.handle)); + + // configs for each ADC channel + adc_digi_pattern_config_t adc_pattern = { + .atten = BV_ADC_ATTEN, + .bit_width = BV_ADC_BITWIDTH, + .channel = BV_ADC_CHANNEL, + .unit = BV_ADC_UNIT, + }; + + // adc IO configs to measure analog signal + adc_continuous_config_t io_config = { + .pattern_num = ADC_CHANNELS, + .adc_pattern = &adc_pattern, + .sample_freq_hz = SAMPLING_RATE_HZ, + .conv_mode = ADC_CONV, + .format = ADC_DIGI_OUTPUT_FORMAT, + }; + + // invoking callbacks + adc_continuous_evt_cbs_t evt_cbs = { + .on_conv_done = adc_callback, + //.on_pool_ovf = overflow_callback, + }; + + adc_continuous_register_event_callbacks(handle, &evt_cbs, NULL); + esp_err_t adc_continuous_start(handle); +} + +static void adc_task() +{ +loop: + if (xSemaphoreTake(adc.sem, portMAX_DELAY) != pdTRUE) { + goto loop; + } + + static uint8_t frame_buf[FRAME_SIZE]; + + + static uint32_t out_length; + + if (adc_continuous_read(handle, frame_buf, FRAME_SIZE, &out_length, 0) + != ESP_OK) { + goto loop; + } + + + adc_digi_output_data_t *samples; + size_t samples_count = out_length / sizeof(adc_digi_output_data_t); + + readIndex = (writeIndex - PREV_SAMPLES_SIZE) % SAMPLES_OUT_SIZE; + + for (size_t i = 0; i < samples_count; i++) { + // write catches up with read index + if (writeIndex == readIndex) { + samples_out(); + } + // uint16_t data = samples[i].type2.data; + // out_buf[writeIndex] = data; + writeIndex = (writeIndex + 1) % SAMPLES_OUT_SIZE; + } + + goto loop; +} + +static void samples_out() +{ + printf("DIGI SAMPLES\n"); + + + static size_t total_samples = 0; + for (size_t i = 0; i < SAMPLES_OUT_SIZE; i++) { + printf("%u,%d\n", total_samples + i, out_buf[readIndex]); + readIndex = (readIndex + 1) % SAMPLES_OUT_SIZE; + } + readIndex = SIZE_MAX; +} + +// ADC callback +static bool IRAM_ATTR adc_callback(adc_continuous_handle_t handle, + const adc_continuous_evt_data_t *cbs, + void *user_data) +{ + // give back semaphore + xSemaphoreGiveFromISR(adc.sem, NULL); + + return true; +} + +// overflow callback +// static bool ram_attr overflow_callback(adc_continuous_handle_t handle, const +// adc_continuous_evt_data_t *cbs, void *user_data) { +// overflow = true; +// return true; +// } From b1b6906786da80aa927c45451cce6983605e0cd5 Mon Sep 17 00:00:00 2001 From: siannhan <117297888+siann23@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:31:06 -0400 Subject: [PATCH 8/8] Update components/batt/src/batt.c Co-authored-by: Jacob Koziej --- components/batt/src/batt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/batt/src/batt.c b/components/batt/src/batt.c index b134b02bd..7edf0ad48 100644 --- a/components/batt/src/batt.c +++ b/components/batt/src/batt.c @@ -22,7 +22,7 @@ #define SAMPLES_OUT_SIZE 1024 // how to decide the size of the output #define PREV_SAMPLES_DELAY 0.010 // why is this the delay time -#define PREV_SAMPLES_SIZE (size_t)(PREV_SAMPLES_DELAY * SAMPLING_RATE_HZ) +#define PREV_SAMPLES_SIZE ((size_t) (PREV_SAMPLES_DELAY * SAMPLING_RATE_HZ)) #define POOL_SIZE (FRAME_SIZE * 2)