diff --git a/main/drivers/CMakeLists.txt b/main/drivers/CMakeLists.txt index 6b24231..b3eb6a9 100644 --- a/main/drivers/CMakeLists.txt +++ b/main/drivers/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES "bottom_half.cpp" "char_lcd.cpp" "game_timer.cpp" + "i2c_lcd_pcf8574.c" "leds.cpp" "power.cpp" "sd.cpp" diff --git a/main/drivers/all.cpp b/main/drivers/all.cpp new file mode 100644 index 0000000..d214208 --- /dev/null +++ b/main/drivers/all.cpp @@ -0,0 +1,36 @@ +#include "all.h" + +static void init_i2c(); + +void init_drivers() { + init_i2c(); + // init char_lcd so we can report any issues on it. + init_char_lcd(); +} + +/// @brief Initializes I2C_NUM_0. +/// +/// This is hooked up the to: +/// - The bottom half +/// - The char lcd +/// - The power board +/// - The MPU6050 +/// - The PERH port +/// - The Capacitive Touch Panel +static void init_i2c() { + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = GPIO_NUM_5, + .scl_io_num = GPIO_NUM_6, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_pullup_en = GPIO_PULLUP_DISABLE, + // .sda_pullup_en = GPIO_PULLUP_ENABLE, + // .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master = { + .clk_speed = 100*1000, + } + }; + + ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf)); + ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0)); +} \ No newline at end of file diff --git a/main/drivers/all.h b/main/drivers/all.h new file mode 100644 index 0000000..4844fe0 --- /dev/null +++ b/main/drivers/all.h @@ -0,0 +1,9 @@ +#ifndef ALL_H +#define ALL_H + +#include "char_lcd.h" +#include "sd.h" + +void init_drivers(); + +#endif /* ALL_H */ \ No newline at end of file diff --git a/main/drivers/bottom_half.cpp b/main/drivers/bottom_half.cpp index d64954f..dfa0652 100644 --- a/main/drivers/bottom_half.cpp +++ b/main/drivers/bottom_half.cpp @@ -180,19 +180,7 @@ static void receive_touch(void); // } void init_bottom_half() { - i2c_config_t conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = GPIO_NUM_5, - .scl_io_num = GPIO_NUM_6, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master = { - .clk_speed = 100000, - } - }; - - ESP_ERROR_CHECK(i2c_param_config(BOTTOM_I2C_NUM, &conf)); - ESP_ERROR_CHECK(i2c_driver_install(BOTTOM_I2C_NUM, conf.mode, 0, 0, 0)); + gpio_config_t delta_pin_conf = {}; // delta_pin_conf.intr_type = GPIO_INTR_LOW_LEVEL; diff --git a/main/drivers/char_lcd.cpp b/main/drivers/char_lcd.cpp index 7f3b0e3..3ffdbf6 100644 --- a/main/drivers/char_lcd.cpp +++ b/main/drivers/char_lcd.cpp @@ -1,9 +1,13 @@ #include "char_lcd.h" +#include "./i2c_lcd_pcf8574.h" +#include + i2c_lcd_pcf8574_handle_t lcd; static const char *TAG = "char_lcd"; +/// Initializes the 2004 Character LCD void init_char_lcd(void) { lcd_init(&lcd, LCD_ADDR, CHAR_LCD_I2C_NUM); lcd_begin(&lcd, LCD_COLS, LCD_ROWS); @@ -12,3 +16,99 @@ void init_char_lcd(void) { ESP_LOGI(TAG, "LCD initialized"); } + + +/// Clear the LCD +void lcd_clear() { + lcd_clear(&lcd); +} + +/// Move cursor to home position +void lcd_cursor_home() { + lcd_home(&lcd); +} + +/// Set cursor position +void lcd_set_cursor_pos(uint8_t col, uint8_t row) { + lcd_set_cursor(&lcd, col, row); +} + +/// Turn the display on/off +void lcd_set_display(bool display) { + if (display) { + lcd_display(&lcd); + } else { + lcd_no_display(&lcd); + } +} + +/// Turn the cursor's visibility on/off +void lcd_set_cursor_vis(bool cursor) { + if (cursor) { + lcd_cursor(&lcd); + } else { + lcd_no_cursor(&lcd); + } +} + +/// Turn blinking cursor on/off +void lcd_set_cursor_blink(bool blink) { + if (blink) { + lcd_blink(&lcd); + } else { + lcd_no_blink(&lcd); + } +} + +/// Scroll the display left +void lcd_scroll_display_left() { + lcd_scroll_display_left(&lcd); +} +/// Scroll the display right +void lcd_scroll_display_right() { + lcd_scroll_display_right(&lcd); +} + +/// Set the text to flows automatically left to right +void lcd_left_to_right() { + lcd_left_to_right(&lcd); +} +/// Set the text to flows automatically right to left +void lcd_right_to_left() { + lcd_right_to_left(&lcd); +} + +// Turn on/off autoscroll +void lcd_set_autoscroll(bool autoscroll) { + if (autoscroll) { + lcd_autoscroll(&lcd); + } else { + lcd_no_autoscroll(&lcd); + } +} + +// Set backlight brightness +void lcd_set_backlight(uint8_t brightness) { + lcd_set_backlight(&lcd, brightness); +} + +// Create a custom character +void lcd_create_char(uint8_t location, uint8_t charmap[]) { + lcd_create_char(&lcd, location, charmap); +} + +// Write a character to the LCD +void lcd_write(uint8_t value) { + lcd_write(&lcd, value); +} + +// Print a string to the LCD +void lcd_print(const char* str) { + lcd_print(&lcd, str); +} + +// Print a string to the LCD at a given pos +void lcd_print(uint8_t col, uint8_t row, const char* str) { + lcd_set_cursor_pos(col, row); + lcd_print(&lcd, str); +} \ No newline at end of file diff --git a/main/drivers/char_lcd.h b/main/drivers/char_lcd.h index f629abd..59bb74f 100644 --- a/main/drivers/char_lcd.h +++ b/main/drivers/char_lcd.h @@ -1,8 +1,7 @@ #ifndef CHAR_LCD_H #define CHAR_LCD_H -#include "./i2c_lcd_pcf8574.h" -#include +#include #define CHAR_LCD_I2C_NUM I2C_NUM_0 @@ -10,8 +9,53 @@ #define LCD_COLS 20 #define LCD_ROWS 4 -extern i2c_lcd_pcf8574_handle_t lcd; +/// Initializes the 2004 Character LCD +void init_lcd(void); -void init_char_lcd(void); +/// Clear the LCD +void lcd_clear(); + +/// Move cursor to home position +void lcd_cursor_home(); + +/// Set cursor position +void lcd_set_cursor_pos(uint8_t col, uint8_t row); + +/// Turn the display on/off +void lcd_set_display(bool display); + +/// Turn the cursor's visibility on/off +void lcd_set_cursor_vis(bool cursor); + +/// Turn blinking cursor on/off +void lcd_set_cursor_blink(bool blink); + +/// Scroll the display left +void lcd_scroll_display_left(); +/// Scroll the display right +void lcd_scroll_display_right(); + +/// Set the text to flows automatically left to right +void lcd_left_to_right(); +/// Set the text to flows automatically right to left +void lcd_right_to_left(); + +// Turn on/off autoscroll +void lcd_set_autoscroll(bool autoscroll); + +// Set backlight brightness +void lcd_set_backlight(uint8_t brightness); + +// Create a custom character +void lcd_create_char(uint8_t location, uint8_t charmap[]); + +// Write a character to the LCD +void lcd_write(uint8_t value); + +// Print a string to the LCD +void lcd_print(const char* str); + +// Print a string to the LCD at a given pos +void lcd_print(uint8_t col, uint8_t row, const char* str); #endif /* CHAR_LCD_H */ \ No newline at end of file diff --git a/main/drivers/i2c_lcd_pcf8574.c b/main/drivers/i2c_lcd_pcf8574.c index a859f1c..cfdd941 100644 --- a/main/drivers/i2c_lcd_pcf8574.c +++ b/main/drivers/i2c_lcd_pcf8574.c @@ -1,6 +1,6 @@ /// \file i2c_lcd_pcf8574.c /// \brief Liquid Crystal display driver with PCF8574 adapter for esp-idf -/// +/// /// \author Femi Olugbon, https://iamflinks.github.io /// \copyright Copyright (c) 2024 by Femi Olugbon /// @@ -13,12 +13,10 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" - #define TAG "I2C_LCD_PCF8574" #define I2C_MASTER_TIMEOUT_MS 1000 - // private functions static void lcd_send(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value, bool is_data); static void lcd_write_nibble(i2c_lcd_pcf8574_handle_t* lcd, uint8_t half_byte, bool is_data, i2c_cmd_handle_t cmd); @@ -38,7 +36,7 @@ void lcd_init(i2c_lcd_pcf8574_handle_t* lcd, uint8_t i2c_addr, i2c_port_t i2c_po lcd->data_mask[2] = 0x40; lcd->data_mask[3] = 0x80; lcd->backlight_mask = 0x08; -} // lcd_begin() +} void lcd_begin(i2c_lcd_pcf8574_handle_t* lcd, uint8_t cols, uint8_t rows) { diff --git a/main/drivers/power.cpp b/main/drivers/power.cpp index 554ff20..37aefb0 100644 --- a/main/drivers/power.cpp +++ b/main/drivers/power.cpp @@ -9,28 +9,24 @@ void bat_monitor_task(void* arg) { uint16_t voltage = lipo.voltage(); sprintf(str_buf, "%d.%03dV", voltage / 1000, voltage % 1000); - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 0); - lcd_print(&lcd, str_buf); + lcd_clear(); + lcd_print(1, 0, str_buf); int16_t current = lipo.current(current_measure::AVG); sprintf(str_buf, "%dmA", current); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, str_buf); + lcd_print(1, 1, str_buf); int16_t total_cap = lipo.capacity(capacity_measure::FULL); sprintf(str_buf, "%dmAh", total_cap); - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, str_buf); + lcd_print(1, 2, str_buf); int16_t soc = lipo.soc(soc_measure::FILTERED); sprintf(str_buf, "%d%%", soc); - lcd_set_cursor(&lcd, 1, 3); - lcd_print(&lcd, str_buf); + lcd_print(1, 3, str_buf); vTaskDelay(pdMS_TO_TICKS(250)); diff --git a/main/drivers/sd.cpp b/main/drivers/sd.cpp index fdc71b7..0033e44 100644 --- a/main/drivers/sd.cpp +++ b/main/drivers/sd.cpp @@ -5,7 +5,7 @@ sdmmc_card_t *card; static const char* mount_point = MOUNT_POINT; static const char* TAG = "sd"; -void init_sd() { +bool init_sd() { ESP_LOGI(TAG, "Initializing SD card"); esp_err_t ret; @@ -52,15 +52,16 @@ void init_sd() { ESP_LOGE(TAG, "Failed to initialize the card (%s). " "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); } - return; + return false; } ESP_LOGI(TAG, "Filesystem mounted"); // Card has been initialized, print its properties sdmmc_card_print_info(stdout, card); + return true; } void deinit_sd() { - esp_vfs_fat_sdcard_unmount(mount_point, card); + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_vfs_fat_sdcard_unmount(mount_point, card)); ESP_LOGI(TAG, "Card unmounted"); } diff --git a/main/drivers/sd.h b/main/drivers/sd.h index 35b38d5..c051159 100644 --- a/main/drivers/sd.h +++ b/main/drivers/sd.h @@ -19,7 +19,7 @@ extern sdmmc_card_t *card; #define SD_PIN_D2 GPIO_NUM_39 #define SD_PIN_D3 GPIO_NUM_38 -void init_sd(); +bool init_sd(); void deinit_sd(); #endif /* SD_H */ \ No newline at end of file diff --git a/main/drivers/wires.cpp b/main/drivers/wires.cpp index d292791..98811bf 100644 --- a/main/drivers/wires.cpp +++ b/main/drivers/wires.cpp @@ -81,8 +81,7 @@ void clear_wires_pressed_released_cut(void) { void strike(const char* reason) { ESP_LOGW("strike!", "%s", reason); - lcd_set_cursor(&lcd, 0, 3); - lcd_print(&lcd, reason); + lcd_print(0, 3, reason); time_penalty(STRIKE_TIME_PENALTY); total_strikes += 1; uint8_t reg = 6; diff --git a/main/helper.cpp b/main/helper.cpp index 23c2c0b..1f9a209 100644 --- a/main/helper.cpp +++ b/main/helper.cpp @@ -16,9 +16,9 @@ void clean_bomb(void) { set_module_sseg_raw(clear); // clear char lcd - lcd_clear(&lcd); - lcd_no_cursor(&lcd); - lcd_set_cursor(&lcd, 0, 0); + lcd_clear(); + lcd_set_cursor_vis(false); + lcd_cursor_home(); } static const int STRING_MAX_LEN = 8; @@ -47,8 +47,7 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) { StarCodeHandler sch = star_codes[i]; if (strcmp(current, sch.code) == 0) { hit = true; - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, sch.display_text); + lcd_print(1, 2, sch.display_text); vTaskDelay(pdMS_TO_TICKS(2000)); if (sch.callback != nullptr) { (sch.callback)(); @@ -61,8 +60,7 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) { } if (!hit) { - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, "Invalid Star Code"); + lcd_print(1, 2, "Invalid Star Code"); vTaskDelay(pdMS_TO_TICKS(2000)); } @@ -82,9 +80,8 @@ void do_star_codes(StarCodeHandler* star_codes, int star_codes_len) { } // ESP_LOGI(STEP0_TAG, "Pressed: %c", c); - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, current); + lcd_clear(); + lcd_print(1, 1, current); } vTaskDelay(pdMS_TO_TICKS(10)); diff --git a/main/main.cpp b/main/main.cpp index 194bbab..a392ebb 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -41,7 +41,7 @@ extern "C" void app_main(void) { init_leds(); init_wires(); init_bottom_half(); - init_char_lcd(); + init_power_board(); clean_bomb(); diff --git a/main/steps/setup_wires.cpp b/main/steps/setup_wires.cpp index 7f7d926..cbf3fa5 100644 --- a/main/steps/setup_wires.cpp +++ b/main/steps/setup_wires.cpp @@ -6,16 +6,13 @@ void print_wires(WireColor* wires, int editing_idx) { bool cut[NUM_WIRES]; solve_wires(wires, cut); - lcd_set_cursor(&lcd, 1, 1); char string_buf[NUM_WIRES+1] = {0}; wires_to_string(wires, string_buf); - lcd_print(&lcd, string_buf); + lcd_print(1, 1, string_buf); - lcd_set_cursor(&lcd, 1, 2); cut_to_string(cut, string_buf); - lcd_print(&lcd, string_buf); + lcd_print(1, 2, string_buf); - lcd_set_cursor(&lcd, 1, 3); wires_state = get_wires(); for (int i = 0; i < NUM_WIRES; i++) { if (wires_state & (1< pdMS_TO_TICKS(5000)) { strike_time = 0; - lcd_clear(&lcd); + lcd_clear(); } vTaskDelay(pdMS_TO_TICKS(10)); } diff --git a/main/steps/step3.cpp b/main/steps/step3.cpp index 6bd117b..71dcf5e 100644 --- a/main/steps/step3.cpp +++ b/main/steps/step3.cpp @@ -211,9 +211,8 @@ static bool one_second() { int lcd_string_idx = lcd_string_dist(gen); bool was_high = (tone / 3) == 1; write_leds(); - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, LCD_STRINGS[lcd_string_idx]); + lcd_clear(); + lcd_print(1, 1, LCD_STRINGS[lcd_string_idx]); int red_led_count = 0; int blue_led_count = 0; @@ -268,8 +267,7 @@ static bool three_second() { int lcd_number = lcd_number_dist(gen); char lcd_number_string[9] = {0}; sprintf(lcd_number_string, "%d", lcd_number); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, lcd_number_string); + lcd_print(1, 1, lcd_number_string); bool was_high = (tone / 3) == 1; @@ -331,8 +329,7 @@ static bool six_second() { generate_random_lcd_text(); vTaskDelay(pdMS_TO_TICKS(10)); - lcd_set_cursor(&lcd, 0, 0); - lcd_print(&lcd, random_lcd_text); + lcd_print(0, 0, random_lcd_text); int vowels = 0; for (int i = 0; i < 20; i++) { diff --git a/main/steps/step4.cpp b/main/steps/step4.cpp index 8d17fea..df3a1e5 100644 --- a/main/steps/step4.cpp +++ b/main/steps/step4.cpp @@ -657,9 +657,8 @@ static void check_line_clears(void) { static void update_score(void) { char buff[16] = {}; sprintf(buff, "%d/%d", score, target_score); - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, buff); + lcd_clear(); + lcd_print(1, 1, buff); } static void line_clear(int hi) { diff --git a/main/steps/step5.cpp b/main/steps/step5.cpp index bb4be8c..16fb261 100644 --- a/main/steps/step5.cpp +++ b/main/steps/step5.cpp @@ -217,7 +217,7 @@ void step5(void) { clean_bomb(); int solved_puzzles = 0; while (solved_puzzles < TIMES_TO_SOLVE) { - lcd_set_cursor(&lcd, 1, 1); + lcd_set_cursor_pos(1, 1); bool solved_correctly = false; int puzzle = puzzle_dist(gen); @@ -225,7 +225,7 @@ void step5(void) { switch (puzzle) { case 0: { - lcd_print(&lcd, "Clear"); + lcd_print("Clear"); set_module_time(TIME_CLEAR); start_module_timer(); @@ -258,7 +258,7 @@ void step5(void) { break; } case 1: { - lcd_print(&lcd, "Blank"); + lcd_print("Blank"); set_module_time(TIME_BLANK); start_module_timer(); @@ -375,7 +375,7 @@ void step5(void) { break; } case 3: { - lcd_print(&lcd, "Nothing"); + lcd_print("Nothing"); set_module_time(TIME_NOTHING); start_module_timer(); @@ -431,7 +431,7 @@ void step5(void) { break; } case 4: { - lcd_print(&lcd, "Blink"); + lcd_print("Blink"); set_module_time(TIME_BLINK); start_module_timer(); @@ -490,7 +490,7 @@ void step5(void) { break; } case 5: { - lcd_print(&lcd, "Ummm"); + lcd_print("Ummm"); set_module_time(TIME_UMMM); start_module_timer(); @@ -543,7 +543,7 @@ void step5(void) { break; } case 6: { - lcd_print(&lcd, "Plank"); + lcd_print("Plank"); set_module_time(TIME_PLANK); start_module_timer(); @@ -632,7 +632,7 @@ void step5(void) { break; } case 7: { - lcd_print(&lcd, "What"); + lcd_print("What"); set_module_time(TIME_WHAT); start_module_timer(); @@ -705,8 +705,7 @@ void step5(void) { } // display expression - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, display_expression.c_str()); + lcd_print(1, 2, display_expression.c_str()); // set LEDs @@ -764,13 +763,10 @@ void step5(void) { entered_string += char_of_keypad_key(key); } - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, "What"); - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, display_expression.c_str()); - lcd_set_cursor(&lcd, 1, 3); - lcd_print(&lcd, entered_string.c_str()); + lcd_clear(); + lcd_print(1, 1, "What"); + lcd_print(1, 2, display_expression.c_str()); + lcd_print(1, 3, entered_string.c_str()); } if (get_module_time() <= 0) { strike("Ran out of time!"); @@ -783,7 +779,7 @@ void step5(void) { break; } case 8: { - lcd_print(&lcd, "Plink"); + lcd_print("Plink"); set_module_time(TIME_PLINK); start_module_timer(); @@ -826,8 +822,7 @@ void step5(void) { // ESP_LOGI(TAG, "color string: %s", color_string.c_str()); - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, color_string.c_str()); + lcd_print(1, 2, color_string.c_str()); std::string entered_string; @@ -856,13 +851,10 @@ void step5(void) { break; } - lcd_clear(&lcd); - lcd_set_cursor(&lcd, 1, 1); - lcd_print(&lcd, "Plink"); - lcd_set_cursor(&lcd, 1, 2); - lcd_print(&lcd, color_string.c_str()); - lcd_set_cursor(&lcd, 1, 3); - lcd_print(&lcd, entered_string.c_str()); + lcd_clear(); + lcd_print(1, 1, "Plink"); + lcd_print(1, 2, color_string.c_str()); + lcd_print(1, 3, entered_string.c_str()); } if (get_module_time() <= 0) { strike("Ran out of time!");