495 lines
20 KiB
C++
495 lines
20 KiB
C++
#include "hwdata.h"
|
|
#include "esp_err.h"
|
|
#include "esp_log.h"
|
|
#include "bottom_half.h"
|
|
#include "char_lcd.h"
|
|
#include "../helper.h"
|
|
#include "nvs.h"
|
|
|
|
static const char* TAG = "hwdata";
|
|
|
|
HWData::HWData()
|
|
: compat_mode(true)
|
|
{}
|
|
|
|
HWData::HWData(HWData1 data, bool compat_mode)
|
|
: compat_mode(compat_mode),
|
|
inner(data)
|
|
{}
|
|
|
|
esp_err_t HWData::save(nvs_handle_t handle, bool force) {
|
|
if (compat_mode && !force) {
|
|
ESP_LOGW(TAG, "Not saving due to being in compatability mode.");
|
|
return ESP_OK;
|
|
}
|
|
return inner.save(handle);
|
|
}
|
|
|
|
HWData HWData::load(nvs_handle_t handle) {
|
|
esp_err_t err;
|
|
|
|
uint16_t stored_version = 0;
|
|
err = nvs_get_u16(handle, "version", &stored_version);
|
|
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
|
ESP_LOGE(TAG, "No NVS data found! using defaults");
|
|
return HWData();
|
|
} else if (err != ESP_OK) {
|
|
ESP_ERROR_CHECK_WITHOUT_ABORT(err);
|
|
ESP_LOGE(TAG, "Other esp error! using defaults");
|
|
return HWData();
|
|
}
|
|
|
|
HWData1 data;
|
|
switch (stored_version) {
|
|
case 0:
|
|
ESP_LOGE(TAG, "HWData version was 0! using defaults");
|
|
return HWData();
|
|
case 1:
|
|
data.load(handle);
|
|
return HWData(data, false);
|
|
default:
|
|
ESP_LOGW(TAG, "Max currently supported version is %d, but saved version is %d. Loading version %d anyway!", CURRENT_HWDATA_VERSION, stored_version, CURRENT_HWDATA_VERSION);
|
|
data.load(handle);
|
|
return HWData(data, true);
|
|
}
|
|
}
|
|
|
|
HWData1::HWData1() {}
|
|
|
|
esp_err_t HWData1::save(nvs_handle_t handle) const {
|
|
ESP_ERROR_CHECK(nvs_set_u16(handle, "version", 1));
|
|
|
|
// Serial number
|
|
ESP_ERROR_CHECK(nvs_set_str(handle, "serial_num", serial_num.c_str()));
|
|
|
|
// Revisions
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_ctrl_maj", rev_ctrl_maj));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_ctrl_min", rev_ctrl_min));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_exp_maj", rev_exp_maj));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_exp_min", rev_exp_min));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_ft_maj", rev_ft_maj));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_ft_min", rev_ft_min));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_fb_maj", rev_fb_maj));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "rev_fb_min", rev_fb_min));
|
|
|
|
// Enums
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "sseg_color_t", static_cast<uint8_t>(sseg_color_t)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "sseg_color_b", static_cast<uint8_t>(sseg_color_b)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "lcd_color", static_cast<uint8_t>(lcd_color)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "button_type", static_cast<uint8_t>(button_type)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "tft_type", static_cast<uint8_t>(tft_type)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "bat_type", static_cast<uint8_t>(bat_type)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "shape1", static_cast<uint8_t>(shape1)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "shape2", static_cast<uint8_t>(shape2)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "shape3", static_cast<uint8_t>(shape3)));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "shape4", static_cast<uint8_t>(shape4)));
|
|
|
|
// Other fields
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "switch_pos", switch_pos));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_speaker", has_speaker));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_mic", has_mic));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_ir", has_ir));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_rfid", has_rfid));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_fp", has_fp));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_fp_hall", has_fp_hall));
|
|
ESP_ERROR_CHECK(nvs_set_u8(handle, "has_close_hall", has_close_hall));
|
|
|
|
// Battery capacity
|
|
ESP_ERROR_CHECK(nvs_set_u16(handle, "bat_cap", bat_cap));
|
|
|
|
return nvs_commit(handle);
|
|
}
|
|
|
|
void HWData1::load(nvs_handle_t handle) {
|
|
char buf[128];
|
|
size_t required_size = sizeof(buf);
|
|
esp_err_t err = nvs_get_str(handle, "serial_num", buf, &required_size);
|
|
serial_num = (err == ESP_OK) ? std::string(buf) : "";
|
|
|
|
nvs_get_u8(handle, "rev_ctrl_maj", &rev_ctrl_maj);
|
|
nvs_get_u8(handle, "rev_ctrl_min", &rev_ctrl_min);
|
|
nvs_get_u8(handle, "rev_exp_maj", &rev_exp_maj);
|
|
nvs_get_u8(handle, "rev_exp_min", &rev_exp_min);
|
|
nvs_get_u8(handle, "rev_ft_maj", &rev_ft_maj);
|
|
nvs_get_u8(handle, "rev_ft_min", &rev_ft_min);
|
|
nvs_get_u8(handle, "rev_fb_maj", &rev_fb_maj);
|
|
nvs_get_u8(handle, "rev_fb_min", &rev_fb_min);
|
|
|
|
uint8_t tmp;
|
|
if (nvs_get_u8(handle, "sseg_color_t", &tmp) == ESP_OK) sseg_color_t = static_cast<SSegColor>(tmp);
|
|
if (nvs_get_u8(handle, "sseg_color_b", &tmp) == ESP_OK) sseg_color_b = static_cast<SSegColor>(tmp);
|
|
if (nvs_get_u8(handle, "lcd_color", &tmp) == ESP_OK) lcd_color = static_cast<LCDColor>(tmp);
|
|
if (nvs_get_u8(handle, "button_type", &tmp) == ESP_OK) button_type = static_cast<ButtonType>(tmp);
|
|
if (nvs_get_u8(handle, "tft_type", &tmp) == ESP_OK) tft_type = static_cast<TFTType>(tmp);
|
|
if (nvs_get_u8(handle, "bat_type", &tmp) == ESP_OK) bat_type = static_cast<BatType>(tmp);
|
|
nvs_get_u16(handle, "bat_cap", &bat_cap);
|
|
|
|
if (nvs_get_u8(handle, "shape1", &tmp) == ESP_OK) shape1 = static_cast<ShapeType>(tmp);
|
|
if (nvs_get_u8(handle, "shape2", &tmp) == ESP_OK) shape2 = static_cast<ShapeType>(tmp);
|
|
if (nvs_get_u8(handle, "shape3", &tmp) == ESP_OK) shape3 = static_cast<ShapeType>(tmp);
|
|
if (nvs_get_u8(handle, "shape4", &tmp) == ESP_OK) shape4 = static_cast<ShapeType>(tmp);
|
|
|
|
nvs_get_u8(handle, "switch_pos", &switch_pos);
|
|
nvs_get_u8(handle, "has_speaker", &tmp); has_speaker = tmp;
|
|
nvs_get_u8(handle, "has_mic", &tmp); has_mic = tmp;
|
|
nvs_get_u8(handle, "has_ir", &tmp); has_ir = tmp;
|
|
nvs_get_u8(handle, "has_rfid", &tmp); has_rfid = tmp;
|
|
nvs_get_u8(handle, "has_fp", &tmp); has_fp = tmp;
|
|
nvs_get_u8(handle, "has_fp_hall", &tmp); has_fp_hall = tmp;
|
|
nvs_get_u8(handle, "has_close_hall", &tmp); has_close_hall = tmp;
|
|
}
|
|
|
|
static void handle_uint8(KeypadKey key, uint8_t& val) {
|
|
char key_c = char_of_keypad_key(key);
|
|
bool is_digit = std::isdigit(static_cast<unsigned char>(key_c));
|
|
uint8_t digit = is_digit ? static_cast<uint8_t>(key_c - '0') : 0;
|
|
|
|
if (key == KeypadKey::star) {
|
|
val = 0;
|
|
} else if (is_digit) {
|
|
uint16_t new_digit = ((uint16_t) val) * 10 + (uint16_t) digit;
|
|
if (new_digit < 255) val = new_digit;
|
|
}
|
|
}
|
|
static void handle_uint16(KeypadKey key, uint16_t& val) {
|
|
char key_c = char_of_keypad_key(key);
|
|
bool is_digit = std::isdigit(static_cast<unsigned char>(key_c));
|
|
uint8_t digit = is_digit ? static_cast<uint8_t>(key_c - '0') : 0;
|
|
|
|
if (key == KeypadKey::star) {
|
|
val = 0;
|
|
} else if (is_digit) {
|
|
uint32_t new_digit = ((uint32_t) val) * 10 + (uint32_t) digit;
|
|
if (new_digit < 65535) val = new_digit;
|
|
}
|
|
}
|
|
|
|
static void handle_enum(ButtonKey key, uint8_t& val, uint8_t n_items) {
|
|
if (key == ButtonKey::b1) {
|
|
// dec
|
|
val = (val + n_items - 1) % n_items;
|
|
} else if (key == ButtonKey::b2) {
|
|
// inc
|
|
val = (val + 1) % n_items;
|
|
}
|
|
}
|
|
|
|
void hardware_config() {
|
|
clean_bomb();
|
|
uint8_t current_item = 0;
|
|
const uint8_t n_items = 28;
|
|
|
|
HWData1& hwdata = get_hw_data().inner;
|
|
|
|
ButtonKey btn;
|
|
KeypadKey key;
|
|
bool dirty = true;
|
|
while (true) {
|
|
if (dirty) {
|
|
// display
|
|
char name[21];
|
|
char value[21];
|
|
|
|
switch (current_item) {
|
|
case 0: // serial_num
|
|
snprintf(name, sizeof(name), "%-20s", "serial_num");
|
|
snprintf(value, sizeof(value), "%s", hwdata.serial_num.c_str());
|
|
break;
|
|
|
|
case 1: // rev_ctrl_maj
|
|
snprintf(name, sizeof(name), "%-20s", "rev_ctrl_maj");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_ctrl_maj);
|
|
break;
|
|
|
|
case 2: // rev_ctrl_min
|
|
snprintf(name, sizeof(name), "%-20s", "rev_ctrl_min");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_ctrl_min);
|
|
break;
|
|
|
|
case 3: // rev_exp_maj
|
|
snprintf(name, sizeof(name), "%-20s", "rev_exp_maj");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_exp_maj);
|
|
break;
|
|
|
|
case 4: // rev_exp_min
|
|
snprintf(name, sizeof(name), "%-20s", "rev_exp_min");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_exp_min);
|
|
break;
|
|
|
|
case 5: // rev_ft_maj
|
|
snprintf(name, sizeof(name), "%-20s", "rev_ft_maj");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_ft_maj);
|
|
break;
|
|
|
|
case 6: // rev_ft_min
|
|
snprintf(name, sizeof(name), "%-20s", "rev_ft_min");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_ft_min);
|
|
break;
|
|
|
|
case 7: // rev_fb_maj
|
|
snprintf(name, sizeof(name), "%-20s", "rev_fb_maj");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_fb_maj);
|
|
break;
|
|
|
|
case 8: // rev_fb_min
|
|
snprintf(name, sizeof(name), "%-20s", "rev_fb_min");
|
|
snprintf(value, sizeof(value), "%d", hwdata.rev_fb_min);
|
|
break;
|
|
|
|
case 9: // sseg_color_t
|
|
snprintf(name, sizeof(name), "%-20s", "sseg_color_t");
|
|
snprintf(value, sizeof(value), "%s", SSEG_COLOR_NAMES[static_cast<uint8_t>(hwdata.sseg_color_t)]);
|
|
break;
|
|
|
|
case 10: // sseg_color_b
|
|
snprintf(name, sizeof(name), "%-20s", "sseg_color_b");
|
|
snprintf(value, sizeof(value), "%s", SSEG_COLOR_NAMES[static_cast<uint8_t>(hwdata.sseg_color_b)]);
|
|
break;
|
|
|
|
case 11: // lcd_color
|
|
snprintf(name, sizeof(name), "%-20s", "lcd_color");
|
|
snprintf(value, sizeof(value), "%s", LCD_COLOR_NAMES[static_cast<uint8_t>(hwdata.lcd_color)]);
|
|
break;
|
|
|
|
case 12: // switch_pos
|
|
snprintf(name, sizeof(name), "%-20s", "switch_pos");
|
|
snprintf(value, sizeof(value), "%d", hwdata.switch_pos);
|
|
break;
|
|
|
|
case 13: // button_type
|
|
snprintf(name, sizeof(name), "%-20s", "button_type");
|
|
snprintf(value, sizeof(value), "%s", BUTTON_TYPE_NAMES[static_cast<uint8_t>(hwdata.button_type)]);
|
|
break;
|
|
|
|
case 14: // tft_type
|
|
snprintf(name, sizeof(name), "%-20s", "tft_type");
|
|
snprintf(value, sizeof(value), "%s", TFT_TYPE_NAMES[static_cast<uint8_t>(hwdata.tft_type)]);
|
|
break;
|
|
|
|
case 15: // bat_type
|
|
snprintf(name, sizeof(name), "%-20s", "bat_type");
|
|
snprintf(value, sizeof(value), "%s", BAT_TYPE_NAMES[static_cast<uint8_t>(hwdata.bat_type)]);
|
|
break;
|
|
|
|
case 16: // bat_cap
|
|
snprintf(name, sizeof(name), "%-20s", "bat_cap");
|
|
snprintf(value, sizeof(value), "%d", hwdata.bat_cap);
|
|
break;
|
|
|
|
case 17: // shape1
|
|
snprintf(name, sizeof(name), "%-20s", "shape1");
|
|
snprintf(value, sizeof(value), "%s", SHAPE_TYPE_NAMES[static_cast<uint8_t>(hwdata.shape1)]);
|
|
break;
|
|
|
|
case 18: // shape2
|
|
snprintf(name, sizeof(name), "%-20s", "shape2");
|
|
snprintf(value, sizeof(value), "%s", SHAPE_TYPE_NAMES[static_cast<uint8_t>(hwdata.shape2)]);
|
|
break;
|
|
|
|
case 19: // shape3
|
|
snprintf(name, sizeof(name), "%-20s", "shape3");
|
|
snprintf(value, sizeof(value), "%s", SHAPE_TYPE_NAMES[static_cast<uint8_t>(hwdata.shape3)]);
|
|
break;
|
|
|
|
case 20: // shape4
|
|
snprintf(name, sizeof(name), "%-20s", "shape4");
|
|
snprintf(value, sizeof(value), "%s", SHAPE_TYPE_NAMES[static_cast<uint8_t>(hwdata.shape4)]);
|
|
break;
|
|
|
|
case 21: // has_speaker
|
|
snprintf(name, sizeof(name), "%-20s", "has_speaker");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_speaker ? "true" : "false");
|
|
break;
|
|
|
|
case 22: // has_mic
|
|
snprintf(name, sizeof(name), "%-20s", "has_mic");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_mic ? "true" : "false");
|
|
break;
|
|
|
|
case 23: // has_ir
|
|
snprintf(name, sizeof(name), "%-20s", "has_ir");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_ir ? "true" : "false");
|
|
break;
|
|
|
|
case 24: // has_rfid
|
|
snprintf(name, sizeof(name), "%-20s", "has_rfid");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_rfid ? "true" : "false");
|
|
break;
|
|
|
|
case 25: // has_fp
|
|
snprintf(name, sizeof(name), "%-20s", "has_fp");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_fp ? "true" : "false");
|
|
break;
|
|
|
|
case 26: // has_fp_hall
|
|
snprintf(name, sizeof(name), "%-20s", "has_fp_hall");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_fp_hall ? "true" : "false");
|
|
break;
|
|
|
|
case 27: // has_close_hall
|
|
snprintf(name, sizeof(name), "%-20s", "has_close_hall");
|
|
snprintf(value, sizeof(value), "%s", hwdata.has_close_hall ? "true" : "false");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
lcd_print(1, 0, name);
|
|
lcd_print(2, 0, value);
|
|
|
|
dirty = false;
|
|
}
|
|
|
|
if (get_button_pressed(&btn)) {
|
|
dirty = true;
|
|
switch (btn) {
|
|
case ButtonKey::b3: // dec
|
|
current_item = (current_item + n_items - 1) % n_items;
|
|
break;
|
|
case ButtonKey::b4: // inc
|
|
current_item = (current_item + 1) % n_items;
|
|
break;
|
|
default:
|
|
switch (current_item) {
|
|
case 9: // sseg_color_t
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.sseg_color_t), SSEG_COLOR_COUNT);
|
|
break;
|
|
|
|
case 10: // sseg_color_b
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.sseg_color_b), SSEG_COLOR_COUNT);
|
|
break;
|
|
|
|
case 11: // lcd_color
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.lcd_color), LCD_COLOR_COUNT);
|
|
break;
|
|
|
|
case 13: // button_type
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.button_type), BUTTON_TYPE_COUNT);
|
|
break;
|
|
|
|
case 14: // tft_type
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.tft_type), TFT_TYPE_COUNT);
|
|
break;
|
|
|
|
case 15: // bat_type
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.bat_type), BAT_TYPE_COUNT);
|
|
break;
|
|
|
|
case 17: // shape1
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.shape1), SHAPE_TYPE_COUNT);
|
|
break;
|
|
case 18: // shape2
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.shape2), SHAPE_TYPE_COUNT);
|
|
break;
|
|
case 19: // shape3
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.shape3), SHAPE_TYPE_COUNT);
|
|
break;
|
|
case 20: // shape4
|
|
handle_enum(btn, reinterpret_cast<uint8_t&>(hwdata.shape4), SHAPE_TYPE_COUNT);
|
|
break;
|
|
|
|
case 21: // has_speaker
|
|
hwdata.has_speaker = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 22: // has_mic
|
|
hwdata.has_mic = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 23: // has_ir
|
|
hwdata.has_ir = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 24: // has_rfid
|
|
hwdata.has_rfid = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 25: // has_fp
|
|
hwdata.has_fp = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 26: // has_fp_hall
|
|
hwdata.has_fp_hall = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
case 27: // has_close_hall
|
|
hwdata.has_close_hall = btn == ButtonKey::button_green;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (get_keypad_pressed(&key)) {
|
|
dirty = true;
|
|
if (key == KeypadKey::pound) {
|
|
// TODO: ask the user to save
|
|
return; // done
|
|
}
|
|
|
|
char key_c = char_of_keypad_key(key);
|
|
bool is_digit = std::isdigit(static_cast<unsigned char>(key_c));
|
|
uint8_t digit = is_digit ? static_cast<uint8_t>(key_c - '0') : 0;
|
|
|
|
// update the current value
|
|
switch (current_item) {
|
|
case 0: // serial_num
|
|
if (key == KeypadKey::star) {
|
|
hwdata.serial_num.clear();
|
|
} else {
|
|
hwdata.serial_num.push_back(char_of_keypad_key(key));
|
|
}
|
|
break;
|
|
|
|
case 1: // rev_ctrl_maj
|
|
handle_uint8(key, hwdata.rev_ctrl_maj);
|
|
break;
|
|
|
|
case 2: // rev_ctrl_min
|
|
handle_uint8(key, hwdata.rev_ctrl_min);
|
|
break;
|
|
|
|
case 3: // rev_exp_maj
|
|
handle_uint8(key, hwdata.rev_exp_maj);
|
|
break;
|
|
|
|
case 4: // rev_exp_min
|
|
handle_uint8(key, hwdata.rev_exp_min);
|
|
break;
|
|
|
|
case 5: // rev_ft_maj
|
|
handle_uint8(key, hwdata.rev_ft_maj);
|
|
break;
|
|
|
|
case 6: // rev_ft_min
|
|
handle_uint8(key, hwdata.rev_ft_min);
|
|
break;
|
|
|
|
case 7: // rev_fb_maj
|
|
handle_uint8(key, hwdata.rev_fb_maj);
|
|
break;
|
|
|
|
case 8: // rev_fb_min
|
|
handle_uint8(key, hwdata.rev_fb_min);
|
|
break;
|
|
|
|
case 12: // switch_pos
|
|
if (digit == 2 || digit == 3) hwdata.switch_pos = digit;
|
|
break;
|
|
|
|
case 16: // bat_cap
|
|
handle_uint16(key, hwdata.bat_cap);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
}
|