fix mutex issue

This commit is contained in:
Mitchell Marino 2025-08-22 11:38:21 -05:00
parent 92d448020c
commit 53f58a3133
5 changed files with 22 additions and 9 deletions

View File

@ -92,11 +92,12 @@ void init_lcd() {
ESP_LOGI(TAG, "Initializing LCD..."); ESP_LOGI(TAG, "Initializing LCD...");
lcd_mutex = xSemaphoreCreateMutex(); lcd_mutex = xSemaphoreCreateMutex();
assert(lcd_mutex != NULL);
lcd_init(&lcd, LCD_ADDR, CHAR_LCD_I2C_NUM); lcd_init(&lcd, LCD_ADDR, CHAR_LCD_I2C_NUM);
lcd_begin(&lcd, LCD_COLS, LCD_ROWS); lcd_begin(&lcd, LCD_COLS, LCD_ROWS);
lcd_set_backlight(&lcd, true); lcd_set_backlight_to(&lcd, 1);
register_replay_fn(replay_handler); register_replay_fn(replay_handler);
@ -229,6 +230,8 @@ void lcd_set_backlight(bool backlight, bool no_lock) {
} }
void lcd_create_char(uint8_t location, const uint8_t charmap[], bool no_lock) { void lcd_create_char(uint8_t location, const uint8_t charmap[], bool no_lock) {
if (location == 8) location = 0;
if (!no_lock) xSemaphoreTake(lcd_mutex, portMAX_DELAY); if (!no_lock) xSemaphoreTake(lcd_mutex, portMAX_DELAY);
lcd_create_char(&lcd, location, charmap); lcd_create_char(&lcd, location, charmap);
if (!no_lock) xSemaphoreGive(lcd_mutex); if (!no_lock) xSemaphoreGive(lcd_mutex);
@ -301,3 +304,11 @@ void lcd_do_splash() {
lcd_print(5, 2, "\x03\x04\x05\x06""DEV", true); lcd_print(5, 2, "\x03\x04\x05\x06""DEV", true);
xSemaphoreGive(lcd_mutex); xSemaphoreGive(lcd_mutex);
} }
bool lcd_lock(uint32_t ticks_to_wait) {
return xSemaphoreTake(lcd_mutex, ticks_to_wait);
}
void lcd_unlock() {
xSemaphoreGive(lcd_mutex);
}

View File

@ -71,10 +71,12 @@ void lcd_do_splash();
/// @brief Locks the LCD to allow chaining multiple commands without interuptions. /// @brief Locks the LCD to allow chaining multiple commands without interuptions.
/// ///
/// Commands you call while you lock the LCD, you must call with the `no_lock` flag set to true. /// Commands you call while you lock the LCD, you must call with the `no_lock` flag set to true.
void lcd_lock(); ///
/// Do not hold this lock for an extended period of time.
/// @return `true` iff the lock was aquired.
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();
#endif /* CHAR_LCD_H */ #endif /* CHAR_LCD_H */

View File

@ -260,7 +260,7 @@ void lcd_print(i2c_lcd_pcf8574_handle_t* lcd, const char* str) {
while (*str) { while (*str) {
if (*str == '\x08') { if (*str == '\x08') {
lcd_write(lcd, '\x00'); lcd_write(lcd, '\x00');
*str++; str++;
} else { } else {
lcd_write(lcd, *str++); lcd_write(lcd, *str++);
} }
@ -305,10 +305,10 @@ static void lcd_send(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value, bool is_data)
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd); i2c_master_start(cmd);
i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, (lcd->i2c_addr << 1) | I2C_MASTER_WRITE, true);
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
lcd_write_nibble(lcd, (value >> 4 & 0x0F), is_data, cmd); lcd_write_nibble(lcd, (value >> 4 & 0x0F), is_data, cmd);
lcd_write_nibble(lcd, (value & 0x0F), is_data, cmd); lcd_write_nibble(lcd, (value & 0x0F), is_data, cmd);
i2c_master_stop(cmd); i2c_master_stop(cmd);
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
esp_err_t ret = i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); esp_err_t ret = i2c_master_cmd_begin(lcd->i2c_port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
xSemaphoreGive(main_i2c_mutex); xSemaphoreGive(main_i2c_mutex);
i2c_cmd_link_delete(cmd); i2c_cmd_link_delete(cmd);
@ -334,10 +334,8 @@ static void lcd_write_nibble(i2c_lcd_pcf8574_handle_t* lcd, uint8_t half_byte, b
if (half_byte & 0x04) data |= lcd->data_mask[2]; if (half_byte & 0x04) data |= lcd->data_mask[2];
if (half_byte & 0x08) data |= lcd->data_mask[3]; if (half_byte & 0x08) data |= lcd->data_mask[3];
xSemaphoreTake(main_i2c_mutex, portMAX_DELAY);
i2c_master_write_byte(cmd, data | lcd->enable_mask, true); i2c_master_write_byte(cmd, data | lcd->enable_mask, true);
i2c_master_write_byte(cmd, data, true); i2c_master_write_byte(cmd, data, true);
xSemaphoreGive(main_i2c_mutex);
} // lcd_write_nibble() } // lcd_write_nibble()
// Private function to change the PCF8574 pins to the given value. // Private function to change the PCF8574 pins to the given value.

View File

@ -23,7 +23,8 @@ void print_wires(WireColor* wires, int editing_idx) {
} }
lcd_print(1, 3, string_buf); lcd_print(1, 3, string_buf);
lcd_set_cursor_pos(editing_idx+1, 1); // TODO: find a way to indicate without a cursor.
// lcd_set_cursor_pos(editing_idx+1, 1);
} }
void setup_wires(void) { void setup_wires(void) {

View File

@ -214,7 +214,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];
lcd_set_cursor_pos(mapped_cursor_pos, 1); // TODO: find some way to indicate without a cursor.
// lcd_set_cursor_pos(mapped_cursor_pos, 1);
} }
static void set_game_time() { static void set_game_time() {