char lcd
This commit is contained in:
@@ -0,0 +1,317 @@
|
||||
#include "blk_box_drivers/char_lcd.hpp"
|
||||
|
||||
#include "lcd2004.hpp"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
// mutex is for all these vars
|
||||
SemaphoreHandle_t lcd_mutex;
|
||||
|
||||
LCD2004I2C lcd;
|
||||
|
||||
static CursorMode cursor_resting_mode = CursorMode::Hide;
|
||||
static CursorMode cursor_print_mode = CursorMode::Hide;
|
||||
static uint8_t resting_cursor_row = 0;
|
||||
static uint8_t resting_cursor_col = 0;
|
||||
|
||||
static bool is_header_enabled = false;
|
||||
|
||||
static const char *TAG = "char_lcd";
|
||||
static const char* EMPTY_ROW = " ";
|
||||
|
||||
// TODO: move this to power.cpp
|
||||
// static void monitor_battery_task(void* _arg) {
|
||||
// (void) _arg;
|
||||
|
||||
// while (true) {
|
||||
// vTaskDelay(pdMS_TO_TICKS(1'000));
|
||||
// lcd_print_header_bat();
|
||||
// }
|
||||
// }
|
||||
|
||||
// static bool replay_handler(const char* event, char* arg) {
|
||||
// if (strcmp(event, "LCD_CLEAR") == 0) {
|
||||
// lcd_clear();
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_SET_DISPLAY") == 0) {
|
||||
// lcd_set_display(strcmp(arg, "true") == 0);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_CURSOR_VIS") == 0) {
|
||||
// lcd_set_cursor_vis(strcmp(arg, "true") == 0);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_CURSOR_BLINK") == 0) {
|
||||
// lcd_set_cursor_blink(strcmp(arg, "true") == 0);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_SCROLL_DISPLAY_LEFT") == 0) {
|
||||
// lcd_scroll_display_left();
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_SCROLL_DISPLAY_RIGHT") == 0) {
|
||||
// lcd_scroll_display_right();
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_LEFT_TO_RIGHT") == 0) {
|
||||
// lcd_left_to_right();
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_RIGHT_TO_LEFT") == 0) {
|
||||
// lcd_right_to_left();
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_AUTOSCROLL") == 0) {
|
||||
// lcd_set_autoscroll(strcmp(arg, "true") == 0);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_BACKLIGHT") == 0) {
|
||||
// lcd_set_backlight(strcmp(arg, "true") == 0);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_CREATE_CHAR") == 0) {
|
||||
// char* location_str = strtok(arg, ",");
|
||||
// uint8_t location = atoi(location_str);
|
||||
|
||||
// uint8_t charmap[8];
|
||||
// for (int i = 0; i < 8; i++) {
|
||||
// char* str = strtok(NULL, ",");
|
||||
// charmap[i] = atoi(str);
|
||||
// }
|
||||
|
||||
// lcd_create_char(location, charmap);
|
||||
// }
|
||||
// else if (strcmp(event, "LCD_PRINT") == 0) {
|
||||
// char* str = strtok(arg, ",");
|
||||
// uint8_t row = atoi(str);
|
||||
// str = strtok(NULL, ",");
|
||||
// uint8_t col = atoi(str);
|
||||
// // get remaining part of string.
|
||||
// str = strtok(NULL, "");
|
||||
|
||||
// // TODO: handle \r and \n
|
||||
// lcd_print(row, col, str);
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
void init_lcd() {
|
||||
ESP_LOGI(TAG, "Initializing LCD...");
|
||||
|
||||
lcd_mutex = xSemaphoreCreateRecursiveMutex();
|
||||
assert(lcd_mutex != NULL);
|
||||
|
||||
lcd = LCD2004I2C();
|
||||
lcd.init(LCD_ADDR);
|
||||
|
||||
// register_replay_fn(replay_handler);
|
||||
|
||||
// xTaskCreate(monitor_battery_task, "bat_monitor", 1024*2, nullptr, 0, nullptr);
|
||||
|
||||
ESP_LOGI(TAG, "LCD initialized!");
|
||||
}
|
||||
|
||||
void LCDController::clear() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
|
||||
if (!is_header_enabled) {
|
||||
lcd.clear();
|
||||
|
||||
// if (is_state_tracking()) {
|
||||
// event_occured("LCD_CLEAR", NULL);
|
||||
// }
|
||||
} else {
|
||||
print(1, 0, EMPTY_ROW);
|
||||
print(2, 0, EMPTY_ROW);
|
||||
print(3, 0, EMPTY_ROW);
|
||||
}
|
||||
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
bool LCDController::get_backlight() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
bool backlight = lcd.get_backlight();
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
return backlight;
|
||||
}
|
||||
|
||||
void LCDController::set_backlight(bool backlight) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
lcd.set_backlight(backlight);
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
|
||||
// if (is_state_tracking()) {
|
||||
// sprintf(buf, "%d", backlight);
|
||||
// event_occured("LCD_BACKLIGHT", backlight ? "true" : "false");
|
||||
// }
|
||||
}
|
||||
|
||||
void LCDController::set_display_show(bool show_display) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
lcd.show_hide(show_display);
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
bool LCDController::get_display_show() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
bool show_display = lcd.get_show_hide();
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
return show_display;
|
||||
}
|
||||
|
||||
/// Changes the cursor display mode to the given mode.
|
||||
static void change_cursor_display(CursorMode cursor_display_mode) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
lcd.show_blink_cursor(
|
||||
cursor_display_mode != CursorMode::Hide,
|
||||
cursor_display_mode == CursorMode::Blink
|
||||
);
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
/// Moves the position of the resting cursor.
|
||||
///
|
||||
/// If the resting cursor mode is `Hide`, then this position has no effect on the display, but is still stored
|
||||
/// for when it is put into resting cursor mode.
|
||||
void LCDController::set_resting_cursor_pos(uint8_t row, uint8_t col) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
|
||||
// update pos if we're not hiding the resting cursor
|
||||
if (
|
||||
(resting_cursor_row != row || resting_cursor_col != col) &&
|
||||
cursor_resting_mode != CursorMode::Hide
|
||||
) {
|
||||
lcd.move_cursor(row, col);
|
||||
}
|
||||
|
||||
resting_cursor_row = row;
|
||||
resting_cursor_col = col;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
/// Gets the position of the resting cursor.
|
||||
///
|
||||
/// This will return the value of the resting cursor position even if the resting cursor mode is `Hide`
|
||||
/// even though the values are not meaningful during that time.
|
||||
void LCDController::get_cursor_resting_position(uint8_t* row, uint8_t* col) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
if (row) *row = resting_cursor_row;
|
||||
if (col) *col = resting_cursor_col;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
/// This puts the display in and out of resting cursor mode.
|
||||
///
|
||||
/// If the resting mode is not `Hide`, then the cursor will be displayed in the resting position when not printing.
|
||||
///
|
||||
/// The cursor mode will change to the "cursor print mode"
|
||||
/// during prints, then return to it's resting location and
|
||||
/// switch back to the "cursor resting mode".
|
||||
void LCDController::set_resting_cursor_mode(CursorMode new_mode) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
if (cursor_resting_mode != new_mode) {
|
||||
cursor_resting_mode = new_mode;
|
||||
change_cursor_display(cursor_resting_mode);
|
||||
if (cursor_resting_mode != CursorMode::Hide) {
|
||||
lcd.move_cursor(resting_cursor_row, resting_cursor_col);
|
||||
}
|
||||
}
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
/// Gets the display mode of the cursor when it is resting.
|
||||
CursorMode LCDController::get_resting_cursor_mode() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
CursorMode mode = cursor_resting_mode;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
return mode;
|
||||
}
|
||||
|
||||
/// Sets the display mode of the cursor during printing.
|
||||
void LCDController::set_cursor_print_mode(CursorMode new_mode) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
cursor_print_mode = new_mode;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
/// Gets the display mode of the cursor during printing.
|
||||
CursorMode LCDController::get_cursor_print_mode() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
CursorMode mode = cursor_print_mode;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
return mode;
|
||||
}
|
||||
|
||||
void LCDController::create_custom_char(uint8_t location, const uint8_t charmap[]) {
|
||||
if (location == 8) location = 0;
|
||||
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
lcd.create_custom_char(location, charmap);
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
|
||||
// if (is_state_tracking()) {
|
||||
// snprintf(buf, sizeof(buf),
|
||||
// "%d,%d,%d,%d,%d,%d,%d,%d,%d", location,
|
||||
// charmap[0], charmap[1], charmap[2], charmap[3], charmap[4], charmap[5], charmap[6], charmap[7]
|
||||
// );
|
||||
// event_occured("LCD_CREATE_CHAR", buf);
|
||||
// }
|
||||
}
|
||||
|
||||
/// Prints a string to the given row and column.
|
||||
///
|
||||
/// Do not print across lines, as that leads to goofy behavior.
|
||||
void LCDController::print(uint8_t row, uint8_t col, const char* str) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
lcd.move_cursor(row, col);
|
||||
change_cursor_display(cursor_print_mode);
|
||||
lcd.write_str(str);
|
||||
|
||||
if (cursor_resting_mode != CursorMode::Hide) {
|
||||
lcd.move_cursor(resting_cursor_row, resting_cursor_col);
|
||||
}
|
||||
if (cursor_resting_mode != cursor_print_mode) {
|
||||
change_cursor_display(cursor_resting_mode);
|
||||
}
|
||||
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
|
||||
// if (is_state_tracking()) {
|
||||
// // TODO: handle \r and \n and others
|
||||
// snprintf(buf, sizeof(buf), "%d,%d,%s", row, col, str);
|
||||
// event_occured("LCD_PRINT", buf);
|
||||
// }
|
||||
}
|
||||
|
||||
void LCDController::set_lcd_header_enabled(bool enable) {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
bool old_header_enabled = is_header_enabled;
|
||||
is_header_enabled = enable;
|
||||
|
||||
// print the header in response to enabling/disabling it
|
||||
if (enable && !old_header_enabled) {
|
||||
print_header();
|
||||
} else if (!enable && old_header_enabled) {
|
||||
print(0, 0, EMPTY_ROW);
|
||||
}
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
bool LCDController::header_enabled() {
|
||||
xSemaphoreTakeRecursive(lcd_mutex, portMAX_DELAY);
|
||||
bool enabled = is_header_enabled;
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool LCDController::lock(uint32_t ticks_to_wait) {
|
||||
return xSemaphoreTakeRecursive(lcd_mutex, ticks_to_wait);
|
||||
}
|
||||
|
||||
void LCDController::unlock() {
|
||||
xSemaphoreGiveRecursive(lcd_mutex);
|
||||
}
|
||||
|
||||
void LCDController::print_header() {
|
||||
// TODO:
|
||||
// lcd_print_header_star_code();
|
||||
// lcd_print_header_step();
|
||||
// lcd_print_header_bat();
|
||||
}
|
||||
Reference in New Issue
Block a user