<commit_before>
#define __MAIN_CPP__
#include "odrive_main.h"
#include "nvm_config.hpp"

#include "usart.h"
#include "freertos_vars.h"
#include "usb_device.h"
#include <communication/interface_usb.h>
#include <communication/interface_uart.h>
#include <communication/interface_i2c.h>
#include <communication/interface_can.hpp>

osSemaphoreId sem_usb_irq;
osSemaphoreId sem_uart_dma;
osSemaphoreId sem_usb_rx;
osSemaphoreId sem_usb_tx;
osSemaphoreId sem_can;

#if defined(STM32F405xx)
// Place FreeRTOS heap in core coupled memory for better performance
__attribute__((section(".ccmram")))
#endif
uint8_t ucHeap[configTOTAL_HEAP_SIZE];

uint32_t _reboot_cookie __attribute__ ((section (".noinit")));
extern char _estack; // provided by the linker script


ODriveCAN::Config_t can_config;
CANSimple *can_simple = nullptr;
ODrive odrv{};


ConfigManager config_manager;

class StatusLedController {
public:
    void update();
};

StatusLedController status_led_controller;

void StatusLedController::update() {
#if HW_VERSION_MAJOR == 4
    uint32_t t = HAL_GetTick();

    bool is_booting = std::any_of(axes.begin(), axes.end(), [](Axis& axis){
        return axis.current_state_ == Axis::AXIS_STATE_UNDEFINED;
    });

    if (is_booting) {
        return;
    }

    bool is_armed = std::any_of(axes.begin(), axes.end(), [](Axis& axis){
        return axis.motor_.is_armed_;
    });
    bool any_error = odrv.any_error();

    if (is_armed) {
        // Fast green pulsating
        const uint32_t period_ms = 256;
        const uint8_t min_brightness = 0;
        const uint8_t max_brightness = 255;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{(uint8_t)(any_error ? brightness / 2 : 0), (uint8_t)brightness, 0});
    } else if (any_error) {
        // Red pulsating
        const uint32_t period_ms = 1024;
        const uint8_t min_brightness = 0;
        const uint8_t max_brightness = 255;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{(uint8_t)brightness, 0, 0});
    } else {
        // Slow blue pulsating
        const uint32_t period_ms = 4096;
        const uint8_t min_brightness = 64;
        const uint8_t max_brightness = 180;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{0, 0, (uint8_t)brightness});
    }
#endif
}

static bool config_read_all() {
    bool success = board_read_config() &&
           config_manager.read(&odrv.config_) &&
           config_manager.read(&can_config);
    for (size_t i = 0; (i < AXIS_COUNT) && success; ++i) {
        success = config_manager.read(&encoders[i].config_) &&
                  config_manager.read(&axes[i].sensorless_estimator_.config_) &&
                  config_manager.read(&axes[i].controller_.config_) &&
                  config_manager.read(&axes[i].trap_traj_.config_) &&
                  config_manager.read(&axes[i].min_endstop_.config_) &&
                  config_manager.read(&axes[i].max_endstop_.config_) &&
                  config_manager.read(&axes[i].mechanical_brake_.config_) &&
                  config_manager.read(&motors[i].config_) &&
                  config_manager.read(&motors[i].fet_thermistor_.config_) &&
                  config_manager.read(&motors[i].motor_thermistor_.config_) &&
                  config_manager.read(&axes[i].config_);
    }
    return success;
}

static bool config_write_all() {
    bool success = board_write_config() &&
           config_manager.write(&odrv.config_) &&
           config_manager.write(&can_config);
    for (size_t i = 0; (i < AXIS_COUNT) && success; ++i) {
        success = config_manager.write(&encoders[i].config_) &&
                  config_manager.write(&axes[i].sensorless_estimator_.config_) &&
                  config_manager.write(&axes[i].controller_.config_) &&
                  config_manager.write(&axes[i].trap_traj_.config_) &&
                  config_manager.write(&axes[i].min_endstop_.config_) &&
                  config_manager.write(&axes[i].max_endstop_.config_) &&
                  config_manager.write(&axes[i].mechanical_brake_.config_) &&
                  config_manager.write(&motors[i].config_) &&
                  config_manager.write(&motors[i].fet_thermistor_.config_) &&
                  config_manager.write(&motors[i].motor_thermistor_.config_) &&
                  config_manager.write(&axes[i].config_);
    }
    return success;
}

static void config_clear_all() {
    odrv.config_ = {};
    can_config = {};
    for (size_t i = 0; i < AXIS_COUNT; ++i) {
        encoders[i].config_ = {};
        axes[i].sensorless_estimator_.config_ = {};
        axes[i].controller_.config_ = {};
        axes[i].controller_.config_.load_encoder_axis = i;
        axes[i].trap_traj_.config_ = {};
        axes[i].min_endstop_.config_ = {};
        axes[i].max_endstop_.config_ = {};
        axes[i].mechanical_brake_.config_ = {};
        motors[i].config_ = {};
        motors[i].fet_thermistor_.config_ = {};
        motors[i].motor_thermistor_.config_ = {};
        axes[i].clear_config();
    }
}
<commit_msg>fix volatility of can config<commit_after>
#define __MAIN_CPP__
#include "odrive_main.h"
#include "nvm_config.hpp"

#include "usart.h"
#include "freertos_vars.h"
#include "usb_device.h"
#include <communication/interface_usb.h>
#include <communication/interface_uart.h>
#include <communication/interface_i2c.h>
#include <communication/interface_can.hpp>

osSemaphoreId sem_usb_irq;
osSemaphoreId sem_uart_dma;
osSemaphoreId sem_usb_rx;
osSemaphoreId sem_usb_tx;
osSemaphoreId sem_can;

#if defined(STM32F405xx)
// Place FreeRTOS heap in core coupled memory for better performance
__attribute__((section(".ccmram")))
#endif
uint8_t ucHeap[configTOTAL_HEAP_SIZE];

uint32_t _reboot_cookie __attribute__ ((section (".noinit")));
extern char _estack; // provided by the linker script


ODrive odrv{};


ConfigManager config_manager;

class StatusLedController {
public:
    void update();
};

StatusLedController status_led_controller;

void StatusLedController::update() {
#if HW_VERSION_MAJOR == 4
    uint32_t t = HAL_GetTick();

    bool is_booting = std::any_of(axes.begin(), axes.end(), [](Axis& axis){
        return axis.current_state_ == Axis::AXIS_STATE_UNDEFINED;
    });

    if (is_booting) {
        return;
    }

    bool is_armed = std::any_of(axes.begin(), axes.end(), [](Axis& axis){
        return axis.motor_.is_armed_;
    });
    bool any_error = odrv.any_error();

    if (is_armed) {
        // Fast green pulsating
        const uint32_t period_ms = 256;
        const uint8_t min_brightness = 0;
        const uint8_t max_brightness = 255;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{(uint8_t)(any_error ? brightness / 2 : 0), (uint8_t)brightness, 0});
    } else if (any_error) {
        // Red pulsating
        const uint32_t period_ms = 1024;
        const uint8_t min_brightness = 0;
        const uint8_t max_brightness = 255;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{(uint8_t)brightness, 0, 0});
    } else {
        // Slow blue pulsating
        const uint32_t period_ms = 4096;
        const uint8_t min_brightness = 64;
        const uint8_t max_brightness = 180;
        uint32_t brightness = std::abs((int32_t)(t % period_ms) - (int32_t)(period_ms / 2)) * (max_brightness - min_brightness) / (period_ms / 2) + min_brightness;
        brightness = (brightness * brightness) >> 8; // eye response very roughly sqrt
        status_led.set_color(rgb_t{0, 0, (uint8_t)brightness});
    }
#endif
}

static bool config_read_all() {
    bool success = board_read_config() &&
           config_manager.read(&odrv.config_) &&
           config_manager.read(&odrv.can_.config_);
    for (size_t i = 0; (i < AXIS_COUNT) && success; ++i) {
        success = config_manager.read(&encoders[i].config_) &&
                  config_manager.read(&axes[i].sensorless_estimator_.config_) &&
                  config_manager.read(&axes[i].controller_.config_) &&
                  config_manager.read(&axes[i].trap_traj_.config_) &&
                  config_manager.read(&axes[i].min_endstop_.config_) &&
                  config_manager.read(&axes[i].max_endstop_.config_) &&
                  config_manager.read(&axes[i].mechanical_brake_.config_) &&
                  config_manager.read(&motors[i].config_) &&
                  config_manager.read(&motors[i].fet_thermistor_.config_) &&
                  config_manager.read(&motors[i].motor_thermistor_.config_) &&
                  config_manager.read(&axes[i].config_);
    }
    return success;
}

static bool config_write_all() {
    bool success = board_write_config() &&
           config_manager.write(&odrv.config_) &&
           config_manager.write(&odrv.can_.config_);
    for (size_t i = 0; (i < AXIS_COUNT) && success; ++i) {
        success = config_manager.write(&encoders[i].config_) &&
                  config_manager.write(&axes[i].sensorless_estimator_.config_) &&
                  config_manager.write(&axes[i].controller_.config_) &&
                  config_manager.write(&axes[i].trap_traj_.config_) &&
                  config_manager.write(&axes[i].min_endstop_.config_) &&
                  config_manager.write(&axes[i].max_endstop_.config_) &&
                  config_manager.write(&axes[i].mechanical_brake_.config_) &&
                  config_manager.write(&motors[i].config_) &&
                  config_manager.write(&motors[i].fet_thermistor_.config_) &&
                  config_manager.write(&motors[i].motor_thermistor_.config_) &&
                  config_manager.write(&axes[i].config_);
    }
    return success;
}

static void config_clear_all() {
    odrv.config_ = {};
    odrv.can_.config_ = {};
    for (size_t i = 0; i < AXIS_COUNT; ++i) {
        encoders[i].config_ = {};
        axes[i].sensorless_estimator_.config_ = {};
        axes[i].controller_.config_ = {};
        axes[i].controller_.config_.load_encoder_axis = i;
        axes[i].trap_traj_.config_ = {};
        axes[i].min_endstop_.config_ = {};
        axes[i].max_endstop_.config_ = {};
        axes[i].mechanical_brake_.config_ = {};
        motors[i].config_ = {};
        motors[i].fet_thermistor_.config_ = {};
        motors[i].motor_thermistor_.config_ = {};
        axes[i].clear_config();
    }
}

{'fraction_non_alphanumeric': 0.131576635924462, 'fraction_numerical': 0.015634606938954763, 'mean_word_length': 2.95209996528983, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4202558', 'n_tokens_mistral': 4027, 'n_tokens_neox': 3684, 'n_words': 629}