Repository: ClemensElflein/OpenMower
File: Firmware/LowLevel/src/datatypes.h (C/C++)

Code before:
struct HallConfig {
    HallMode mode : 3;  // 1 bit reserved
    bool active_low : 1;
} __attribute__((packed));
#pragma pack(pop)

#define MAX_HALL_INPUTS 10  // How much Hall-inputs we support. 4 * OM + 6 * Stock-CoverUI + 0 spare (because not yet required to make it fixed)

// LL/HL config packet, bi-directional, flexible-length, with defaults for YF-C500.
#pragma pack(push, 1)
struct ll_high_level_config {
    // ATTENTION: This is a flexible length struct. It is allowed to grow independently to HL without loosing compatibility,
    //    but never change or restructure already published member, except you really know their consequences.

    // uint8_t type; Just for illustration. Get set in wire buffer with type PACKET_ID_LL_HIGH_LEVEL_CONFIG_REQ or PACKET_ID_LL_HIGH_LEVEL_CONFIG_RSP

    ConfigOptions options = {0, 0, 0};
    uint16_t rain_threshold = 700;         // If (stock CoverUI) rain value < rain_threshold then it rains. Expected to differ between C500, SA and SC types (0xFFFF = unknown)
    float v_charge_cutoff = 30.0f;         // Protective max. charging voltage before charging get switched off (-1 = unknown)
    float i_charge_cutoff = 1.5f;          // Protective max. charging current before charging get switched off (-1 = unknown)
    float v_battery_cutoff = 29.0f;        // Protective max. battery voltage before charging get switched off (-1 = unknown)
    float v_battery_empty = 21.7f + 0.3f;  // Empty battery voltage used for % calc of capacity (-1 = unknown)
    float v_battery_full = 28.7f - 0.3f;   // Full battery voltage used for % calc of capacity (-1 = unknown)
    uint16_t lift_period = 100;            // Period (ms) for >=2 wheels to be lifted in order to count as emergency (0 = disable, 0xFFFF = unknown). This is to filter uneven ground
    uint16_t tilt_period = 2500;           // Period (ms) for a single wheel to be lifted in order to count as emergency (0 = disable, 0xFFFF = unknown). This is to filter uneven ground
    float shutdown_esc_max_pitch = 0.0f;   // Do not shutdown ESCs if absolute pitch angle is greater than this (0 = disable, 0xffff = unknown) (to be implemented)
    iso639_1 language = {'e', 'n'};        // ISO 639-1 (2-char) language code (en, de, ...)
    uint8_t volume = 80;                   // Volume (0-100%) feedback (if directly changed i.e. via CoverUI or WebApp) (0xff = do not change)
    HallConfig hall_configs[MAX_HALL_INPUTS] = {
        {HallMode::LIFT_TILT, true},  // [0] OM Hall-1 input (Lift1) = YF-C500 default
        {HallMode::LIFT_TILT, true},  // [1] OM Hall-2 input (Lift2) = YF-C500 default
        {HallMode::STOP, true},       // [2] OM Hall-3 input (Stop1) = YF-C500 default
        {HallMode::STOP, true},       // [3] OM Hall-4 input (Stop2) = YF-C500 default
        //{HallMode::LIFT_TILT, false},  // [4] CoverUI-LIFT | LIFTX (up to CoverUI FW 2.0x)
        //{HallMode::LIFT_TILT, false},  // [5] CoverUI-LIFTX (as of CoverUI FW 2.1x)
        //{HallMode::LIFT_TILT, false},  // [6] CoverUI-LBUMP | RBUMP (up to CoverUI FW 2.0x)
        //{HallMode::LIFT_TILT, false},  // [7] CoverUI-RBUMP (as of CoverUI FW 2.1x)
        //{HallMode::STOP, false},       // [8] CoverUI-Stop1
        //{HallMode::STOP, false},       // [9] CoverUI-Stop2
    };
    // INFO: Before adding a new member here: Decide if and how much hall_configs spares do we like to have

    // uint16_t crc;  Just for illustration, that it get appended, but only within the wire buffer
} __attribute__((packed));
#pragma pack(pop)

#endif


Review comment (suggestion):
Would you use this field both as a general toggle for the shutdown and for configuring the max pitch? My intuition is to better add another boolean field before this. Or uint8 if we need different modes, but that wouldn't impact the struct size.

Code after:
    OptionState reserved_for_future_use4 : 2;
    OptionState reserved_for_future_use5 : 2;
} __attribute__((packed));
#pragma pack(pop)
static_assert(sizeof(ConfigOptions) == 2, "Changing size of ConfigOption != 2 will break packet compatibilty");

typedef char iso639_1[2]; // Two char ISO 639-1 language code

enum class HallMode : unsigned int {
    OFF = 0,
    LIFT_TILT,  // Wheel lifted and/or wheels tilted functionality
    STOP,       // Stop mower
    UNDEFINED   // This is used by foreign side to inform that it doesn't has a configuration for this sensor
};

#pragma pack(push, 1)
struct HallConfig {
    HallMode mode : 3;  // 1 bit reserved
    bool active_low : 1;
} __attribute__((packed));
#pragma pack(pop)

// For each active hall, we've a handle of it for quick and direct access
struct HallHandle {
    HallConfig config;
    std::function<bool()> get_value;
};

#define MAX_HALL_INPUTS 10  // How much Hall-inputs we support. 4 * OM + 6 * Stock-CoverUI + 0 spare (because not yet required to make it fixed)

// LL/HL config packet, bi-directional, flexible-length, with defaults for YF-C500.
#pragma pack(push, 1)
struct ll_high_level_config {
    // ATTENTION: This is a flexible length struct. It is allowed to grow independently to HL without loosing compatibility,
    //    but never change or restructure already published member, except you really know their consequences.

    // uint8_t type; Just for illustration. Get set in wire buffer with type PACKET_ID_LL_HIGH_LEVEL_CONFIG_REQ or PACKET_ID_LL_HIGH_LEVEL_CONFIG_RSP

    ConfigOptions options = {.dfp_is_5v = OptionState::OFF, .background_sounds = OptionState::OFF, .ignore_charging_current = OptionState::OFF};
    uint16_t rain_threshold = 700;         // If (stock CoverUI) rain value < rain_threshold then it rains. Expected to differ between C500, SA and SC types (0xFFFF = unknown)
    float v_charge_cutoff = 30.0f;         // Protective max. charging voltage before charging get switched off (-1 = unknown)
    float i_charge_cutoff = 1.5f;          // Protective max. charging current before charging get switched off (-1 = unknown)
    float v_battery_cutoff = 29.0f;        // Protective max. battery voltage before charging get switched off (-1 = unknown)
    float v_battery_empty = 21.7f + 0.3f;  // Empty battery voltage used for % calc of capacity (-1 = unknown)
    float v_battery_full = 28.7f - 0.3f;   // Full battery voltage used for % calc of capacity (-1 = unknown)
    uint16_t lift_period = 100;            // Period (ms) for >=2 wheels to be lifted in order to count as emergency (0 = disable, 0xFFFF = unknown). This is to filter uneven ground
    uint16_t tilt_period = 2500;           // Period (ms) for a single wheel to be lifted in order to count as emergency (0 = disable, 0xFFFF = unknown). This is to filter uneven ground
    uint8_t shutdown_esc_max_pitch = 0;    // Do not shutdown ESCs if absolute pitch angle is greater than this (0 = disable, 0xffff = unknown) (to be implemented, see PR #97)
    iso639_1 language = {'e', 'n'};        // ISO 639-1 (2-char) language code (en, de, ...)
    uint8_t volume = 80;                   // Volume (0-100%) feedback (if directly changed i.e. via CoverUI or WebApp) (0xff = do not change)
    HallConfig hall_configs[MAX_HALL_INPUTS] = {