Add mutexes for I2C access in multiple drivers and update cursor handling in char_lcd and wires. Adjust task stack sizes for better resource management.
This commit is contained in:
parent
da781c23f1
commit
dcd4f5bb62
@ -729,7 +729,9 @@ uint16_t BQ27441::i2cWriteBytes(uint8_t subAddress, uint8_t * src, uint8_t count
|
|||||||
w_buff[i+1] = src[i];
|
w_buff[i+1] = src[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
|
||||||
esp_err_t ret = i2c_master_write_to_device(BQ72441_I2C_NUM, _deviceAddress, src, count+1, timeout);
|
esp_err_t ret = i2c_master_write_to_device(BQ72441_I2C_NUM, _deviceAddress, src, count+1, timeout);
|
||||||
|
xSemaphoreGive(main_i2c_mutex);
|
||||||
|
|
||||||
return ret == ESP_OK;
|
return ret == ESP_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,6 +76,7 @@ void init_bottom_half() {
|
|||||||
|
|
||||||
static uint8_t receive_delta(void) {
|
static uint8_t receive_delta(void) {
|
||||||
uint8_t reg = 1;
|
uint8_t reg = 1;
|
||||||
|
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
|
||||||
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS));
|
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS));
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
||||||
if (result != ESP_OK) {
|
if (result != ESP_OK) {
|
||||||
@ -85,10 +86,11 @@ static uint8_t receive_delta(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void receive_keypad(void) {
|
static void receive_keypad(void) {
|
||||||
// TODO: use mutex
|
|
||||||
// TODO: change the bottom half polling scheme from a state-based protocol to an event based protocol
|
// TODO: change the bottom half polling scheme from a state-based protocol to an event based protocol
|
||||||
uint8_t reg = 2;
|
uint8_t reg = 2;
|
||||||
|
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
|
||||||
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS));
|
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS));
|
||||||
|
xSemaphoreGive(main_i2c_mutex);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
||||||
if (result != ESP_OK) {
|
if (result != ESP_OK) {
|
||||||
return;
|
return;
|
||||||
@ -117,7 +119,9 @@ static void receive_keypad(void) {
|
|||||||
|
|
||||||
static void receive_button_switch(void) {
|
static void receive_button_switch(void) {
|
||||||
uint8_t reg = 3;
|
uint8_t reg = 3;
|
||||||
|
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
|
||||||
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS));
|
esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS));
|
||||||
|
xSemaphoreGive(main_i2c_mutex);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
ESP_ERROR_CHECK_WITHOUT_ABORT(result);
|
||||||
if (result != ESP_OK) {
|
if (result != ESP_OK) {
|
||||||
return;
|
return;
|
||||||
@ -188,7 +192,9 @@ static void receive_button_switch(void) {
|
|||||||
static void receive_touch(void) {
|
static void receive_touch(void) {
|
||||||
uint8_t reg = 4;
|
uint8_t reg = 4;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(main_i2c_mutex);
|
||||||
bool new_touch_state = buf[0] != 0;
|
bool new_touch_state = buf[0] != 0;
|
||||||
|
|
||||||
bool just_pressed = new_touch_state & !touch_state;
|
bool just_pressed = new_touch_state & !touch_state;
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
i2c_lcd_pcf8574_handle_t lcd;
|
i2c_lcd_pcf8574_handle_t lcd;
|
||||||
SemaphoreHandle_t lcd_mutex;
|
SemaphoreHandle_t lcd_mutex;
|
||||||
|
|
||||||
|
static volatile bool cursor_visible = false;
|
||||||
|
static volatile uint8_t cursor_resting_row = 0;
|
||||||
|
static volatile uint8_t cursor_resting_col = 0;
|
||||||
|
|
||||||
static volatile bool header_enabled = false;
|
static volatile bool header_enabled = false;
|
||||||
|
|
||||||
static const char *TAG = "char_lcd";
|
static const char *TAG = "char_lcd";
|
||||||
@ -147,6 +151,8 @@ void lcd_set_cursor_vis(bool cursor, bool no_lock) {
|
|||||||
}
|
}
|
||||||
if (!no_lock) xSemaphoreGive(lcd_mutex);
|
if (!no_lock) xSemaphoreGive(lcd_mutex);
|
||||||
|
|
||||||
|
cursor_visible = cursor;
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
event_occured("LCD_CURSOR_VIS", cursor ? "true" : "false");
|
event_occured("LCD_CURSOR_VIS", cursor ? "true" : "false");
|
||||||
}
|
}
|
||||||
@ -249,6 +255,11 @@ void lcd_print(uint8_t row, uint8_t col, const char* str, bool no_lock) {
|
|||||||
if (!no_lock) xSemaphoreTake(lcd_mutex, portMAX_DELAY);
|
if (!no_lock) xSemaphoreTake(lcd_mutex, portMAX_DELAY);
|
||||||
lcd_set_cursor(&lcd, col, row);
|
lcd_set_cursor(&lcd, col, row);
|
||||||
lcd_print(&lcd, str);
|
lcd_print(&lcd, str);
|
||||||
|
|
||||||
|
if (cursor_visible) {
|
||||||
|
lcd_set_cursor(&lcd, cursor_resting_col, cursor_resting_row);
|
||||||
|
}
|
||||||
|
|
||||||
if (!no_lock) xSemaphoreGive(lcd_mutex);
|
if (!no_lock) xSemaphoreGive(lcd_mutex);
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
@ -310,4 +321,18 @@ bool lcd_lock(uint32_t ticks_to_wait) {
|
|||||||
|
|
||||||
void lcd_unlock() {
|
void lcd_unlock() {
|
||||||
xSemaphoreGive(lcd_mutex);
|
xSemaphoreGive(lcd_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_set_cursor_resting_position(uint8_t row, uint8_t col) {
|
||||||
|
cursor_resting_row = row;
|
||||||
|
cursor_resting_col = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_get_cursor_resting_position(uint8_t* row, uint8_t* col) {
|
||||||
|
if (row) *row = cursor_resting_row;
|
||||||
|
if (col) *col = cursor_resting_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lcd_is_cursor_visible() {
|
||||||
|
return cursor_visible;
|
||||||
}
|
}
|
||||||
@ -79,4 +79,18 @@ bool lcd_lock(uint32_t ticks_to_wait);
|
|||||||
/// @brief Unlocks the LCD to give away the mutex access to it.
|
/// @brief Unlocks the LCD to give away the mutex access to it.
|
||||||
void lcd_unlock();
|
void lcd_unlock();
|
||||||
|
|
||||||
|
/// @brief Set the resting position for the cursor
|
||||||
|
/// @param row the row where the cursor should rest
|
||||||
|
/// @param col the column where the cursor should rest
|
||||||
|
void lcd_set_cursor_resting_position(uint8_t row, uint8_t col);
|
||||||
|
|
||||||
|
/// @brief Get the current resting position of the cursor
|
||||||
|
/// @param row pointer to store the resting row
|
||||||
|
/// @param col pointer to store the resting column
|
||||||
|
void lcd_get_cursor_resting_position(uint8_t* row, uint8_t* col);
|
||||||
|
|
||||||
|
/// @brief Check if the cursor is currently visible
|
||||||
|
/// @return true if cursor is visible, false otherwise
|
||||||
|
bool lcd_is_cursor_visible();
|
||||||
|
|
||||||
#endif /* CHAR_LCD_H */
|
#endif /* CHAR_LCD_H */
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
#include "hwdata.h"
|
#include "hwdata.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "bottom_half.h"
|
||||||
|
#include "char_lcd.h"
|
||||||
|
#include "../helper.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
|
||||||
static const char* TAG = "hwdata";
|
static const char* TAG = "hwdata";
|
||||||
|
|
||||||
@ -120,10 +124,10 @@ void HWData1::load(nvs_handle_t handle) {
|
|||||||
if (nvs_get_u8(handle, "bat_type", &tmp) == ESP_OK) bat_type = static_cast<BatType>(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);
|
nvs_get_u16(handle, "bat_cap", &bat_cap);
|
||||||
|
|
||||||
if (nvs_get_u8(handle, "shape1", &tmp) == ESP_OK) shape1 = static_cast<Shape>(tmp);
|
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<Shape>(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<Shape>(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<Shape>(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, "switch_pos", &switch_pos);
|
||||||
nvs_get_u8(handle, "has_speaker", &tmp); has_speaker = tmp;
|
nvs_get_u8(handle, "has_speaker", &tmp); has_speaker = tmp;
|
||||||
@ -135,4 +139,356 @@ void HWData1::load(nvs_handle_t handle) {
|
|||||||
nvs_get_u8(handle, "has_close_hall", &tmp); has_close_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,19 @@
|
|||||||
#define CURRENT_HWDATA_VERSION 1
|
#define CURRENT_HWDATA_VERSION 1
|
||||||
#define CURRENT_HWDATA_STRUCT HWData1
|
#define CURRENT_HWDATA_STRUCT HWData1
|
||||||
|
|
||||||
|
#define SSEG_COLOR_COUNT 10
|
||||||
|
static constexpr const char* SSEG_COLOR_NAMES[SSEG_COLOR_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"NONE",
|
||||||
|
"OTHER",
|
||||||
|
"RED",
|
||||||
|
"ORANGE",
|
||||||
|
"YELLOW",
|
||||||
|
"GREEN",
|
||||||
|
"BLUE",
|
||||||
|
"PURPLE",
|
||||||
|
"WHITE"
|
||||||
|
};
|
||||||
enum class SSegColor : uint8_t {
|
enum class SSegColor : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
NONE = 1,
|
NONE = 1,
|
||||||
@ -23,6 +36,17 @@ enum class SSegColor : uint8_t {
|
|||||||
WHITE = 9,
|
WHITE = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LCD_COLOR_COUNT 8
|
||||||
|
static constexpr const char* LCD_COLOR_NAMES[LCD_COLOR_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"NONE",
|
||||||
|
"OTHER",
|
||||||
|
"BLACK_GREEN",
|
||||||
|
"WHITE_BLUE",
|
||||||
|
"BLACK_SKY",
|
||||||
|
"BLACK_WHITE",
|
||||||
|
"WHITE_BLACK"
|
||||||
|
};
|
||||||
enum class LCDColor : uint8_t {
|
enum class LCDColor : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
NONE = 1,
|
NONE = 1,
|
||||||
@ -34,6 +58,15 @@ enum class LCDColor : uint8_t {
|
|||||||
WHITE_BLACK = 7,
|
WHITE_BLACK = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BUTTON_TYPE_COUNT 6
|
||||||
|
static constexpr const char* BUTTON_TYPE_NAMES[BUTTON_TYPE_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"NONE",
|
||||||
|
"OTHER",
|
||||||
|
"WHITE",
|
||||||
|
"BROWN",
|
||||||
|
"RED"
|
||||||
|
};
|
||||||
enum class ButtonType : uint8_t {
|
enum class ButtonType : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
NONE = 1,
|
NONE = 1,
|
||||||
@ -43,6 +76,14 @@ enum class ButtonType : uint8_t {
|
|||||||
RED = 5,
|
RED = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TFT_TYPE_COUNT 5
|
||||||
|
static constexpr const char* TFT_TYPE_NAMES[TFT_TYPE_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"NONE",
|
||||||
|
"OTHER",
|
||||||
|
"EAST_RISING",
|
||||||
|
"SHENZHEN"
|
||||||
|
};
|
||||||
enum class TFTType : uint8_t {
|
enum class TFTType : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
NONE = 1,
|
NONE = 1,
|
||||||
@ -51,6 +92,14 @@ enum class TFTType : uint8_t {
|
|||||||
SHENZHEN = 4,
|
SHENZHEN = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BAT_TYPE_COUNT 5
|
||||||
|
static constexpr const char* BAT_TYPE_NAMES[BAT_TYPE_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"NONE",
|
||||||
|
"OTHER",
|
||||||
|
"BAT_18650",
|
||||||
|
"LIPO"
|
||||||
|
};
|
||||||
enum class BatType : uint8_t {
|
enum class BatType : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
NONE = 1,
|
NONE = 1,
|
||||||
@ -59,7 +108,21 @@ enum class BatType : uint8_t {
|
|||||||
LIPO = 4,
|
LIPO = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Shape : uint8_t {
|
#define SHAPE_TYPE_COUNT 11
|
||||||
|
static constexpr const char* SHAPE_TYPE_NAMES[SHAPE_TYPE_COUNT] = {
|
||||||
|
"UNKNOWN",
|
||||||
|
"OTHER",
|
||||||
|
"CIRCLE",
|
||||||
|
"SQUARE",
|
||||||
|
"TRIANGLE",
|
||||||
|
"X",
|
||||||
|
"STAR",
|
||||||
|
"SPADE",
|
||||||
|
"DIAMOND",
|
||||||
|
"CLUB",
|
||||||
|
"HEART"
|
||||||
|
};
|
||||||
|
enum class ShapeType : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
OTHER = 1,
|
OTHER = 1,
|
||||||
CIRCLE = 2,
|
CIRCLE = 2,
|
||||||
@ -74,6 +137,7 @@ enum class Shape : uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Version 1 of HWData, kept constant for migrations
|
/// @brief Version 1 of HWData, kept constant for migrations
|
||||||
struct HWData1 {
|
struct HWData1 {
|
||||||
std::string serial_num;
|
std::string serial_num;
|
||||||
@ -95,10 +159,10 @@ struct HWData1 {
|
|||||||
BatType bat_type;
|
BatType bat_type;
|
||||||
uint16_t bat_cap;
|
uint16_t bat_cap;
|
||||||
|
|
||||||
Shape shape1;
|
ShapeType shape1;
|
||||||
Shape shape2;
|
ShapeType shape2;
|
||||||
Shape shape3;
|
ShapeType shape3;
|
||||||
Shape shape4;
|
ShapeType shape4;
|
||||||
|
|
||||||
bool has_speaker;
|
bool has_speaker;
|
||||||
bool has_mic;
|
bool has_mic;
|
||||||
@ -130,4 +194,6 @@ struct HWData {
|
|||||||
static HWData load(nvs_handle_t handle);
|
static HWData load(nvs_handle_t handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void hardware_config();
|
||||||
|
|
||||||
#endif /* HWDATA_H */
|
#endif /* HWDATA_H */
|
||||||
|
|||||||
@ -76,3 +76,25 @@ void lcd_print_header_bat() {
|
|||||||
|
|
||||||
lcd_print(0, 16, buf);
|
lcd_print(0, 16, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// memory version
|
||||||
|
// void lcd_print_header_bat() {
|
||||||
|
// if (!lcd_header_enabled()) return;
|
||||||
|
// if (lcd_starcode_displaying_result()) return;
|
||||||
|
|
||||||
|
// // Show memory usage percentage instead of battery percentage
|
||||||
|
// char buf[6];
|
||||||
|
// size_t free_heap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||||
|
// size_t total_heap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
|
||||||
|
// uint8_t mem_percent = 0;
|
||||||
|
// if (total_heap > 0) {
|
||||||
|
// mem_percent = (uint8_t)(100 - ((free_heap * 100) / total_heap));
|
||||||
|
// }
|
||||||
|
// if (mem_percent >= 100) {
|
||||||
|
// snprintf(buf, sizeof(buf), " 100");
|
||||||
|
// } else {
|
||||||
|
// snprintf(buf, sizeof(buf), " %2d%%", mem_percent);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// lcd_print(0, 16, buf);
|
||||||
|
// }
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "drivers/bottom_half.h"
|
#include "drivers/bottom_half.h"
|
||||||
#include "char_lcd.h"
|
#include "char_lcd.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
static const char* TAG = "star_code";
|
static const char* TAG = "star_code";
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ volatile bool handling_new_starcodes = false;
|
|||||||
static volatile bool system_initialized = false;
|
static volatile bool system_initialized = false;
|
||||||
|
|
||||||
// TODO: use the semaphore, convert to RWLock?
|
// TODO: use the semaphore, convert to RWLock?
|
||||||
static volatile SemaphoreHandle_t star_codes_sem;
|
static volatile SemaphoreHandle_t star_codes_mutex;
|
||||||
static std::vector<StarCodeEntry> star_codes;
|
static std::vector<StarCodeEntry> star_codes;
|
||||||
|
|
||||||
static const char EMPTY_STAR_CODE_HEADER[] = " ";
|
static const char EMPTY_STAR_CODE_HEADER[] = " ";
|
||||||
@ -29,23 +30,40 @@ static uint16_t starcode_waiting_on_release;
|
|||||||
static char current[STARCODE_MAX_LEN + 1];
|
static char current[STARCODE_MAX_LEN + 1];
|
||||||
static size_t current_idx;
|
static size_t current_idx;
|
||||||
|
|
||||||
|
// Task handle for the starcode callback task
|
||||||
|
static TaskHandle_t starcode_callback_task_handle = nullptr;
|
||||||
|
|
||||||
|
static void starcode_callback_task(void* arg) {
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Wait for notification from starcode_trigger_cb
|
||||||
|
uint32_t notification_value;
|
||||||
|
if (xTaskNotifyWait(0, ULONG_MAX, ¬ification_value, portMAX_DELAY) == pdTRUE) {
|
||||||
|
// Process the starcode callback
|
||||||
|
delaying_for_starcode = false;
|
||||||
|
lcd_print_header();
|
||||||
|
|
||||||
|
if (current_starcode != nullptr) {
|
||||||
|
if (current_starcode->triggered_sem != nullptr)
|
||||||
|
xSemaphoreGive(current_starcode->triggered_sem);
|
||||||
|
if (current_starcode->callback != nullptr)
|
||||||
|
(current_starcode->callback)();
|
||||||
|
|
||||||
|
current_starcode = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void starcode_trigger_cb(void* arg) {
|
static void starcode_trigger_cb(void* arg) {
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
delaying_for_starcode = false;
|
if (starcode_callback_task_handle != nullptr) {
|
||||||
|
xTaskNotify(starcode_callback_task_handle, 1, eSetBits);
|
||||||
if (current_starcode != nullptr) {
|
|
||||||
if (current_starcode->triggered_sem != nullptr)
|
|
||||||
xSemaphoreGive(current_starcode->triggered_sem);
|
|
||||||
if (current_starcode->callback != nullptr)
|
|
||||||
(current_starcode->callback)();
|
|
||||||
|
|
||||||
current_starcode = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename star code everywhere to starcode
|
|
||||||
lcd_print_header();
|
|
||||||
}
|
}
|
||||||
|
// TODO: rename star code everywhere to starcode
|
||||||
|
|
||||||
|
|
||||||
void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) {
|
void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) {
|
||||||
@ -91,8 +109,9 @@ void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init_star_code_system() {
|
void init_star_code_system() {
|
||||||
star_codes_sem = xSemaphoreCreateBinary();
|
star_codes_mutex = xSemaphoreCreateMutex();
|
||||||
xSemaphoreGive(star_codes_sem);
|
|
||||||
|
xTaskCreate(starcode_callback_task, "starcode_cb", 4096, NULL, 3, &starcode_callback_task_handle);
|
||||||
|
|
||||||
const esp_timer_create_args_t timer_args = {
|
const esp_timer_create_args_t timer_args = {
|
||||||
.callback = &starcode_trigger_cb,
|
.callback = &starcode_trigger_cb,
|
||||||
|
|||||||
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
extern uint32_t current_step;
|
extern uint32_t current_step;
|
||||||
|
|
||||||
|
/// The mutex for accessing `I2C_NUM_1` (wires I2C bus).
|
||||||
|
SemaphoreHandle_t wires_i2c_mutex;
|
||||||
|
|
||||||
uint32_t total_strikes;
|
uint32_t total_strikes;
|
||||||
uint32_t step_strikes[N_STEPS] = {0};
|
uint32_t step_strikes[N_STEPS] = {0};
|
||||||
uint32_t step_finish_times[N_STEPS] = {0};
|
uint32_t step_finish_times[N_STEPS] = {0};
|
||||||
@ -41,6 +44,10 @@ void init_wires(void) {
|
|||||||
ESP_ERROR_CHECK(i2c_param_config(WIRES_I2C_NUM, &wires_conf));
|
ESP_ERROR_CHECK(i2c_param_config(WIRES_I2C_NUM, &wires_conf));
|
||||||
ESP_ERROR_CHECK(i2c_driver_install(WIRES_I2C_NUM, wires_conf.mode, 0, 0, 0));
|
ESP_ERROR_CHECK(i2c_driver_install(WIRES_I2C_NUM, wires_conf.mode, 0, 0, 0));
|
||||||
|
|
||||||
|
// Create mutex for wires I2C bus
|
||||||
|
wires_i2c_mutex = xSemaphoreCreateMutex();
|
||||||
|
assert(wires_i2c_mutex != NULL);
|
||||||
|
|
||||||
gpio_config_t int_pin_conf = {};
|
gpio_config_t int_pin_conf = {};
|
||||||
// delta_pin_conf.intr_type = GPIO_INTR_LOW_LEVEL;
|
// delta_pin_conf.intr_type = GPIO_INTR_LOW_LEVEL;
|
||||||
int_pin_conf.mode = GPIO_MODE_INPUT;
|
int_pin_conf.mode = GPIO_MODE_INPUT;
|
||||||
@ -92,38 +99,48 @@ void strike(const char* reason) {
|
|||||||
step_strikes[current_step - 1] += 1;
|
step_strikes[current_step - 1] += 1;
|
||||||
}
|
}
|
||||||
uint8_t reg = 6;
|
uint8_t reg = 6;
|
||||||
|
xSemaphoreTake(wires_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(wires_i2c_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_leds(uint8_t led_states) {
|
void set_leds(uint8_t led_states) {
|
||||||
buf[0] = 5; // register 5
|
buf[0] = 5; // register 5
|
||||||
buf[1] = led_states;
|
buf[1] = led_states;
|
||||||
|
xSemaphoreTake(wires_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, buf, 2, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, buf, 2, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(wires_i2c_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t receive_delta(void) {
|
static uint8_t receive_delta(void) {
|
||||||
uint8_t reg = 1;
|
uint8_t reg = 1;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
xSemaphoreTake(wires_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(wires_i2c_mutex);
|
||||||
return buf[0];
|
return buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void receive_wires(void) {
|
static void receive_wires(void) {
|
||||||
uint8_t reg = 2;
|
uint8_t reg = 2;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
xSemaphoreTake(wires_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(wires_i2c_mutex);
|
||||||
uint8_t new_wires = buf[0];
|
uint8_t new_wires = buf[0];
|
||||||
|
|
||||||
uint8_t just_cut = ~new_wires & wires_state;
|
uint8_t just_cut = ~new_wires & wires_state;
|
||||||
wires_cut |= just_cut;
|
wires_cut |= just_cut;
|
||||||
|
|
||||||
wires_state = new_wires;
|
wires_state = new_wires;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void receive_button(void) {
|
static void receive_button(void) {
|
||||||
uint8_t reg = 3;
|
uint8_t reg = 3;
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
xSemaphoreTake(wires_i2c_mutex, portMAX_DELAY);
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)));
|
||||||
|
xSemaphoreGive(wires_i2c_mutex);
|
||||||
bool new_button = buf[0] != 0;
|
bool new_button = buf[0] != 0;
|
||||||
|
|
||||||
bool just_pressed = new_button & !button_state;
|
bool just_pressed = new_button & !button_state;
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#include <driver/i2c.h>
|
#include <driver/i2c.h>
|
||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
#include "drivers/char_lcd.h"
|
#include "drivers/char_lcd.h"
|
||||||
#include "drivers/game_timer.h"
|
#include "drivers/game_timer.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@ -16,6 +18,9 @@
|
|||||||
#define WIRES_I2C_NUM I2C_NUM_1
|
#define WIRES_I2C_NUM I2C_NUM_1
|
||||||
#define WIRES_I2C_ADDR 125
|
#define WIRES_I2C_ADDR 125
|
||||||
|
|
||||||
|
/// The mutex for accessing `I2C_NUM_1` (wires I2C bus).
|
||||||
|
extern SemaphoreHandle_t wires_i2c_mutex;
|
||||||
|
|
||||||
#define DELTA_BIT_WIRES 0
|
#define DELTA_BIT_WIRES 0
|
||||||
#define DELTA_BIT_BUTTON 1
|
#define DELTA_BIT_BUTTON 1
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,8 @@ void print_wires(WireColor* wires, int editing_idx) {
|
|||||||
}
|
}
|
||||||
lcd_print(3, 1, string_buf);
|
lcd_print(3, 1, string_buf);
|
||||||
|
|
||||||
// TODO: find a way to indicate without a cursor.
|
lcd_set_cursor_vis(true);
|
||||||
// lcd_set_cursor_pos(editing_idx+1, 1);
|
lcd_set_cursor_resting_position(1, editing_idx+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_wires(void) {
|
void setup_wires(void) {
|
||||||
|
|||||||
@ -34,9 +34,6 @@ static void battery_stats() {
|
|||||||
vTaskDelete(xHandle);
|
vTaskDelete(xHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void hardware_config() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove. This is temperary
|
// TODO: remove. This is temperary
|
||||||
static void replay_last() {
|
static void replay_last() {
|
||||||
@ -224,8 +221,8 @@ static void _update_display(uint8_t* digits, uint8_t cursor_pos) {
|
|||||||
lcd_print(1, 1, str_buf);
|
lcd_print(1, 1, str_buf);
|
||||||
cursor_pos = MAX(0, MIN(4, cursor_pos));
|
cursor_pos = MAX(0, MIN(4, cursor_pos));
|
||||||
int mapped_cursor_pos = CURSOR_POS_MAP[cursor_pos];
|
int mapped_cursor_pos = CURSOR_POS_MAP[cursor_pos];
|
||||||
// TODO: find some way to indicate without a cursor.
|
|
||||||
// lcd_set_cursor_pos(mapped_cursor_pos, 1);
|
lcd_set_cursor_resting_position(1, mapped_cursor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_game_time() {
|
static void set_game_time() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user