Files
2026-10-10 09:22:34 +03:00

229 lines
9.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file zh_160x_i2c.h
*
* @brief Driver for 16x2 and 16x4 LCD displays via I2C PCF8574 expander.
*
* Provides a high-level API for controlling HD44780-compatible LCD modules
* connected through a PCF8574 I/O expander. Supports text output, cursor
* control, and progress bar display.
*
* Key features:
* - 4-bit interface mode for efficient data transfer
* - Support for 16x2 and 16x4 LCD configurations
* - Text, integer, and floating-point number printing
* - Custom progress bar rendering
* - Cursor visibility and blink control
*
* @note All display operations require an initialized handle obtained through zh_160x_init().
* @note The text position counter of the HD44780 controller is shared by all rows,
* so row addresses are remapped internally.
*/
#pragma once
#include "zh_pcf8574.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Opaque handle for LCD 160x I2C display.
*
* Internal structure containing the PCF8574 expander handle and
* current LCD size configuration.
*/
typedef struct _zh_160x_i2c_handle_t zh_160x_i2c_handle_t;
/**
* @brief Supported LCD display sizes.
*/
typedef enum
{
ZH_LCD_16X2, /*!< LCD size 16x2 */
ZH_LCD_16X4, /*!< LCD size 16x4 */
ZH_LCD_NUM_MAX /*!< Number of supported LCD sizes */
} zh_160x_i2c_lcd_size_t;
/**
* @brief Initializes the LCD 160x display.
*
* Allocates and configures the LCD handle, then sends the initialization
* sequence to the LCD controller via the PCF8574 I2C expander.
* Configures 4-bit mode and sets default display parameters.
*
* @param[in] expander Pointer to the PCF8574 expander handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[out] handle Pointer to the output LCD handle pointer (must not be NULL and must point to a NULL pointer)
* @param[in] size LCD size configuration (must be < ZH_LCD_NUM_MAX)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter pointer is NULL or size is invalid
* @return ESP_ERR_INVALID_STATE if the output pointer already holds an initialized handle
* @return ESP_ERR_NO_MEM if memory allocation fails
* @return ESP_FAIL if LCD initialization sequence fails
*/
esp_err_t zh_160x_init(zh_pcf8574_handle_t **expander, zh_160x_i2c_handle_t **handle, zh_160x_i2c_lcd_size_t size);
/**
* @brief Deinitializes the LCD 160x display and frees the handle.
*
* Releases the allocated memory for the LCD handle and sets the output
* pointer to NULL to prevent use-after-free.
*
* @param[in,out] handle Pointer to the LCD handle (must not be NULL)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
*/
esp_err_t zh_160x_deinit(zh_160x_i2c_handle_t **handle);
/**
* @brief Clears the LCD screen and moves cursor to home position.
*
* Sends the LCD clear command (0x01) to erase all displayed text
* and reset the cursor to the upper-left corner (row 0, column 0).
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
* @return ESP_FAIL if sending the command fails
*/
esp_err_t zh_160x_lcd_clear(zh_160x_i2c_handle_t **handle);
/**
* @brief Sets the cursor to a specific position on the LCD.
*
* Moves the cursor to the specified row and column.
* For 16x2 displays: rows 0–1, columns 0–15.
* For 16x4 displays: rows 0–3, columns 0–15.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] row Row number (must be < 2 for 16x2 and < 4 for 16x4)
* @param[in] col Column number (must be < 16)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter pointer is NULL or coordinates are out of range
* @return ESP_FAIL if sending the command fails
*
* @note Row address mapping: row 0 = 0x00, row 1 = 0x40,
* row 2 = 0x10, row 3 = 0x50.
*/
esp_err_t zh_160x_set_cursor(zh_160x_i2c_handle_t **handle, uint8_t row, uint8_t col);
/**
* @brief Prints a string to the LCD at the current cursor position.
*
* Transmits each character of the null-terminated string to the LCD
* in 4-bit mode. The cursor advances automatically after each character.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] str Null-terminated string to display (must not be NULL)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or handle points to a NULL handle
* @return ESP_FAIL if any character transmission fails
*/
esp_err_t zh_160x_print_char(zh_160x_i2c_handle_t **handle, const char *str);
/**
* @brief Prints an integer to the LCD at the current cursor position.
*
* Converts the integer to a decimal string and displays it.
* Supports the full range of signed 32-bit values
* (maximum 10 digits plus an optional sign).
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] num Integer value to display
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
* @return ESP_FAIL if string conversion or printing fails
*/
esp_err_t zh_160x_print_int(zh_160x_i2c_handle_t **handle, int num);
/**
* @brief Prints a floating-point number to the LCD at the current cursor position.
*
* Converts the floating-point value to a decimal string with the
* specified number of decimal places and displays it. The converted
* text must fit into an internal 16-character buffer.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] num Floating-point value to display
* @param[in] precision Number of decimal places passed to snprintf (0–6 recommended)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
* @return ESP_FAIL if string conversion or printing fails
*/
esp_err_t zh_160x_print_float(zh_160x_i2c_handle_t **handle, float num, uint8_t precision);
/**
* @brief Displays a progress bar on a specific row of the LCD.
*
* Renders a 16-block progress bar where filled blocks represent the
* progress percentage and empty blocks show the remainder. Filled
* blocks are printed as byte 0xFF, which displays as a solid block
* only when DDRAM location 0xFF is configured as a custom character
* (CGRAM pattern 7 on HD44780 controllers).
* Leaves the cursor at the end of the row.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] row Row number (must be < 2 for 16x2 and < 4 for 16x4)
* @param[in] progress Progress percentage (must be <= 100)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter pointer is NULL, row is out of range, or progress exceeds 100
* @return ESP_FAIL if cursor positioning or character printing fails
*/
esp_err_t zh_160x_print_progress_bar(zh_160x_i2c_handle_t **handle, uint8_t row, uint8_t progress);
/**
* @brief Clears a specific row on the LCD.
*
* Moves the cursor to the beginning of the specified row and fills
* all 16 positions with spaces to erase existing content.
* Leaves the cursor at the start of the cleared row.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] row Row number (must be < 2 for 16x2 and < 4 for 16x4)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter pointer is NULL or row is out of range
* @return ESP_FAIL if cursor positioning or character printing fails
*/
esp_err_t zh_160x_clear_row(zh_160x_i2c_handle_t **handle, uint8_t row);
/**
* @brief Enables the cursor with optional blink mode.
*
* Turns on the cursor and optionally enables blinking.
* Command 0x0F enables cursor with blink, 0x0E enables cursor only.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
* @param[in] blink Enable cursor blink mode
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
* @return ESP_FAIL if sending the command fails
*/
esp_err_t zh_160x_on_cursor(zh_160x_i2c_handle_t **handle, bool blink);
/**
* @brief Hides the cursor and disables blinking.
*
* Sends command 0x0C to turn off both cursor and cursor blink.
*
* @param[in] handle Pointer to the LCD handle pointer (must not be NULL and must point to a non-NULL handle)
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if handle pointer is NULL or points to a NULL handle
* @return ESP_FAIL if sending the command fails
*/
esp_err_t zh_160x_off_cursor(zh_160x_i2c_handle_t **handle);
#ifdef __cplusplus
}
#endif