/* * Copyright (c) 2022-2023 Jamie McCrae * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public API for auxiliary (textual/non-graphical) display drivers */ #ifndef ZEPHYR_INCLUDE_DRIVERS_AUXDISPLAY_H_ #define ZEPHYR_INCLUDE_DRIVERS_AUXDISPLAY_H_ /** * @brief Auxiliary (Text) Display Interface * @defgroup auxdisplay_interface Text Display Interface * @ingroup io_interfaces * @{ */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** @brief Used for minimum and maximum brightness/backlight values if not supported */ #define AUXDISPLAY_LIGHT_NOT_SUPPORTED 0 /** @brief Used to describe the mode of an auxiliary (text) display */ typedef uint32_t auxdisplay_mode_t; /** @brief Used for moving the cursor or display position */ enum auxdisplay_position { /** Moves to specified X,Y position */ AUXDISPLAY_POSITION_ABSOLUTE = 0, /** Shifts current position by +/- X,Y position, does not take display direction into * consideration */ AUXDISPLAY_POSITION_RELATIVE, /** Shifts current position by +/- X,Y position, takes display direction into * consideration */ AUXDISPLAY_POSITION_RELATIVE_DIRECTION, AUXDISPLAY_POSITION_COUNT, }; /** @brief Used for setting character append position */ enum auxdisplay_direction { /** Each character will be placed to the right of existing characters */ AUXDISPLAY_DIRECTION_RIGHT = 0, /** Each character will be placed to the left of existing characters */ AUXDISPLAY_DIRECTION_LEFT, AUXDISPLAY_DIRECTION_COUNT, }; /** @brief Light levels for brightness and/or backlight. If not supported by a * display/driver, both minimum and maximum will be AUXDISPLAY_LIGHT_NOT_SUPPORTED. */ struct auxdisplay_light { /** Minimum light level supported */ uint8_t minimum; /** Maximum light level supported */ uint8_t maximum; }; /** @brief Structure holding display capabilities. */ struct auxdisplay_capabilities { /** Number of character columns */ uint16_t columns; /** Number of character rows */ uint16_t rows; /** Display-specific data (e.g. 4-bit or 8-bit mode for HD44780-based displays) */ auxdisplay_mode_t mode; /** Brightness details for display (if supported) */ struct auxdisplay_light brightness; /** Backlight details for display (if supported) */ struct auxdisplay_light backlight; /** Number of custom characters supported by display (0 if unsupported) */ uint8_t custom_characters; /** Width (in pixels) of a custom character, supplied custom characters should match. */ uint8_t custom_character_width; /** Height (in pixels) of a custom character, supplied custom characters should match. */ uint8_t custom_character_height; }; /** @brief Structure for a custom command. This may be extended by specific drivers. */ struct auxdisplay_custom_data { /** Raw command data to be sent */ uint8_t *data; /** Length of supplied data */ uint16_t len; /** Display-driver specific options for command */ uint32_t options; }; /** @brief Structure for a custom character. */ struct auxdisplay_character { /** Custom character index on the display */ uint8_t index; /** Custom character pixel data, a character must be valid for a display consisting * of a uint8 array of size character width by character height, values should be * 0x00 for pixel off or 0xff for pixel on, if a display supports shades then values * between 0x00 and 0xff may be used (display driver dependent). */ uint8_t *data; /** Will be updated with custom character index to use in the display write function to * disaplay this custom character */ uint8_t character_code; }; /** * @cond INTERNAL_HIDDEN * * For internal use only, skip these in public documentation. */ /** * @typedef auxdisplay_display_on_t * @brief Callback API to turn display on * See auxdisplay_display_on() for argument description */ typedef int (*auxdisplay_display_on_t)(const struct device *dev); /** * @typedef auxdisplay_display_off_t * @brief Callback API to turn display off * See auxdisplay_display_off() for argument description */ typedef int (*auxdisplay_display_off_t)(const struct device *dev); /** * @typedef auxdisplay_cursor_set_enabled_t * @brief Callback API to turn display cursor visibility on or off * See auxdisplay_cursor_set_enabled() for argument description */ typedef int (*auxdisplay_cursor_set_enabled_t)(const struct device *dev, bool enabled); /** * @typedef auxdisplay_position_blinking_set_enabled_t * @brief Callback API to turn the current position blinking on or off * See auxdisplay_position_blinking_set_enabled() for argument description */ typedef int (*auxdisplay_position_blinking_set_enabled_t)(const struct device *dev, bool enabled); /** * @typedef auxdisplay_cursor_shift_set_t * @brief Callback API to set how the cursor shifts after a character is written * See auxdisplay_cursor_shift_set() for argument description */ typedef int (*auxdisplay_cursor_shift_set_t)(const struct device *dev, uint8_t direction, bool display_shift); /** * @typedef auxdisplay_cursor_position_set_t * @brief Callback API to set the cursor position * See auxdisplay_cursor_position_set() for argument description */ typedef int (*auxdisplay_cursor_position_set_t)(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y); /** * @typedef auxdisplay_cursor_position_get_t * @brief Callback API to get the cursor position * See auxdisplay_cursor_position_get() for argument description */ typedef int (*auxdisplay_cursor_position_get_t)(const struct device *dev, int16_t *x, int16_t *y); /** * @typedef auxdisplay_display_position_set_t * @brief Callback API to set the current position of the display * See auxdisplay_display_position_set() for argument description */ typedef int (*auxdisplay_display_position_set_t)(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y); /** * @typedef auxdisplay_display_position_get_t * @brief Callback API to get the current position of the display * See auxdisplay_display_position_get() for argument description */ typedef int (*auxdisplay_display_position_get_t)(const struct device *dev, int16_t *x, int16_t *y); /** * @typedef auxdisplay_capabilities_get_t * @brief Callback API to get details on the display * See auxdisplay_capabilities_get() for argument description */ typedef int (*auxdisplay_capabilities_get_t)(const struct device *dev, struct auxdisplay_capabilities *capabilities); /** * @typedef auxdisplay_clear_t * @brief Callback API to clear the contents of the display * See auxdisplay_clear() for argument description */ typedef int (*auxdisplay_clear_t)(const struct device *dev); /** * @typedef auxdisplay_brightness_get_t * @brief Callback API to get the current and minimum/maximum supported * brightness settings of the display * See auxdisplay_brightness_get_api() for argument description */ typedef int (*auxdisplay_brightness_get_t)(const struct device *dev, uint8_t *brightness); /** * @typedef auxdisplay_brightness_set_t * @brief Callback API to set the brightness of the display * See auxdisplay_brightness_set_api() for argument description */ typedef int (*auxdisplay_brightness_set_t)(const struct device *dev, uint8_t brightness); /** * @typedef auxdisplay_backlight_get_t * @brief Callback API to get the current and minimum/maximum supported * backlight settings of the display * See auxdisplay_backlight_set() for argument description */ typedef int (*auxdisplay_backlight_get_t)(const struct device *dev, uint8_t *backlight); /** * @typedef auxdisplay_backlight_set_t * @brief Callback API to set the backlight status * See auxdisplay_backlight_set() for argument description */ typedef int (*auxdisplay_backlight_set_t)(const struct device *dev, uint8_t backlight); /** * @typedef auxdisplay_is_busy_t * @brief Callback API to check if the display is busy with an operation * See auxdisplay_is_busy() for argument description */ typedef int (*auxdisplay_is_busy_t)(const struct device *dev); /** * @typedef auxdisplay_custom_character_set_t * @brief Callback API to set a customer character on the display for usage * See auxdisplay_custom_character_set() for argument description */ typedef int (*auxdisplay_custom_character_set_t)(const struct device *dev, struct auxdisplay_character *character); /** * @typedef auxdisplay_write_t * @brief Callback API to write text to the display * See auxdisplay_write() for argument description */ typedef int (*auxdisplay_write_t)(const struct device *dev, const uint8_t *data, uint16_t len); /** * @typedef auxdisplay_custom_command_t * @brief Callback API to send a custom command to the display * See auxdisplay_custom_command() for argument description */ typedef int (*auxdisplay_custom_command_t)(const struct device *dev, struct auxdisplay_custom_data *command); struct auxdisplay_driver_api { auxdisplay_display_on_t display_on; auxdisplay_display_off_t display_off; auxdisplay_cursor_set_enabled_t cursor_set_enabled; auxdisplay_position_blinking_set_enabled_t position_blinking_set_enabled; auxdisplay_cursor_shift_set_t cursor_shift_set; auxdisplay_cursor_position_set_t cursor_position_set; auxdisplay_cursor_position_get_t cursor_position_get; auxdisplay_display_position_set_t display_position_set; auxdisplay_display_position_get_t display_position_get; auxdisplay_capabilities_get_t capabilities_get; auxdisplay_clear_t clear; auxdisplay_brightness_get_t brightness_get; auxdisplay_brightness_set_t brightness_set; auxdisplay_backlight_get_t backlight_get; auxdisplay_backlight_set_t backlight_set; auxdisplay_is_busy_t is_busy; auxdisplay_custom_character_set_t custom_character_set; auxdisplay_write_t write; auxdisplay_custom_command_t custom_command; }; /** * @endcond */ /** * @brief Turn display on. * * @param dev Auxiliary display device instance * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_display_on(const struct device *dev); static inline int z_impl_auxdisplay_display_on(const struct device *dev) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->display_on) { return -ENOSYS; } return api->display_on(dev); } /** * @brief Turn display off. * * @param dev Auxiliary display device instance * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_display_off(const struct device *dev); static inline int z_impl_auxdisplay_display_off(const struct device *dev) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->display_off) { return -ENOSYS; } return api->display_off(dev); } /** * @brief Set cursor enabled status on an auxiliary display * * @param dev Auxiliary display device instance * @param enabled True to enable cursor, false to disable * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_cursor_set_enabled(const struct device *dev, bool enabled); static inline int z_impl_auxdisplay_cursor_set_enabled(const struct device *dev, bool enabled) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->cursor_set_enabled) { return -ENOSYS; } return api->cursor_set_enabled(dev, enabled); } /** * @brief Set cursor blinking status on an auxiliary display * * @param dev Auxiliary display device instance * @param enabled Set to true to enable blinking position, false to disable * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_position_blinking_set_enabled(const struct device *dev, bool enabled); static inline int z_impl_auxdisplay_position_blinking_set_enabled(const struct device *dev, bool enabled) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->position_blinking_set_enabled) { return -ENOSYS; } return api->position_blinking_set_enabled(dev, enabled); } /** * @brief Set cursor shift after character write and display shift * * @param dev Auxiliary display device instance * @param direction Sets the direction of the display when characters are written * @param display_shift If true, will shift the display when characters are written * (which makes it look like the display is moving, not the cursor) * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_cursor_shift_set(const struct device *dev, uint8_t direction, bool display_shift); static inline int z_impl_auxdisplay_cursor_shift_set(const struct device *dev, uint8_t direction, bool display_shift) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->cursor_shift_set) { return -ENOSYS; } if (direction >= AUXDISPLAY_DIRECTION_COUNT) { return -EINVAL; } return api->cursor_shift_set(dev, direction, display_shift); } /** * @brief Set cursor (and write position) on an auxiliary display * * @param dev Auxiliary display device instance * @param type Type of move, absolute or offset * @param x Exact or offset X position * @param y Exact or offset Y position * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_cursor_position_set(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y); static inline int z_impl_auxdisplay_cursor_position_set(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->cursor_position_set) { return -ENOSYS; } else if (type >= AUXDISPLAY_POSITION_COUNT) { return -EINVAL; } else if (type == AUXDISPLAY_POSITION_ABSOLUTE && (x < 0 || y < 0)) { return -EINVAL; } return api->cursor_position_set(dev, type, x, y); } /** * @brief Get current cursor on an auxiliary display * * @param dev Auxiliary display device instance * @param x Will be updated with the exact X position * @param y Will be updated with the exact Y position * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y); static inline int z_impl_auxdisplay_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->cursor_position_get) { return -ENOSYS; } return api->cursor_position_get(dev, x, y); } /** * @brief Set display position on an auxiliary display * * @param dev Auxiliary display device instance * @param type Type of move, absolute or offset * @param x Exact or offset X position * @param y Exact or offset Y position * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_display_position_set(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y); static inline int z_impl_auxdisplay_display_position_set(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->display_position_set) { return -ENOSYS; } else if (type >= AUXDISPLAY_POSITION_COUNT) { return -EINVAL; } else if (type == AUXDISPLAY_POSITION_ABSOLUTE && (x < 0 || y < 0)) { return -EINVAL; } return api->display_position_set(dev, type, x, y); } /** * @brief Get current display position on an auxiliary display * * @param dev Auxiliary display device instance * @param x Will be updated with the exact X position * @param y Will be updated with the exact Y position * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_display_position_get(const struct device *dev, int16_t *x, int16_t *y); static inline int z_impl_auxdisplay_display_position_get(const struct device *dev, int16_t *x, int16_t *y) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->display_position_get) { return -ENOSYS; } return api->display_position_get(dev, x, y); } /** * @brief Fetch capabilities (and details) of auxiliary display * * @param dev Auxiliary display device instance * @param capabilities Will be updated with the details of the auxiliary display * * @retval 0 on success. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_capabilities_get(const struct device *dev, struct auxdisplay_capabilities *capabilities); static inline int z_impl_auxdisplay_capabilities_get(const struct device *dev, struct auxdisplay_capabilities *capabilities) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; return api->capabilities_get(dev, capabilities); } /** * @brief Clear display of auxiliary display and return to home position (note that * this does not reset the display configuration, e.g. custom characters and * display mode will persist). * * @param dev Auxiliary display device instance * * @retval 0 on success. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_clear(const struct device *dev); static inline int z_impl_auxdisplay_clear(const struct device *dev) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; return api->clear(dev); } /** * @brief Get the current brightness level of an auxiliary display * * @param dev Auxiliary display device instance * @param brightness Will be updated with the current brightness * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_brightness_get(const struct device *dev, uint8_t *brightness); static inline int z_impl_auxdisplay_brightness_get(const struct device *dev, uint8_t *brightness) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->brightness_get) { return -ENOSYS; } return api->brightness_get(dev, brightness); } /** * @brief Update the brightness level of an auxiliary display * * @param dev Auxiliary display device instance * @param brightness The brightness level to set * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_brightness_set(const struct device *dev, uint8_t brightness); static inline int z_impl_auxdisplay_brightness_set(const struct device *dev, uint8_t brightness) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->brightness_set) { return -ENOSYS; } return api->brightness_set(dev, brightness); } /** * @brief Get the backlight level details of an auxiliary display * * @param dev Auxiliary display device instance * @param backlight Will be updated with the current backlight level * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_backlight_get(const struct device *dev, uint8_t *backlight); static inline int z_impl_auxdisplay_backlight_get(const struct device *dev, uint8_t *backlight) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->backlight_get) { return -ENOSYS; } return api->backlight_get(dev, backlight); } /** * @brief Update the backlight level of an auxiliary display * * @param dev Auxiliary display device instance * @param backlight The backlight level to set * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_backlight_set(const struct device *dev, uint8_t backlight); static inline int z_impl_auxdisplay_backlight_set(const struct device *dev, uint8_t backlight) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->backlight_set) { return -ENOSYS; } return api->backlight_set(dev, backlight); } /** * @brief Check if an auxiliary display driver is busy * * @param dev Auxiliary display device instance * * @retval 1 on success and display busy. * @retval 0 on success and display not busy. * @retval -ENOSYS if not supported/implemented. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_is_busy(const struct device *dev); static inline int z_impl_auxdisplay_is_busy(const struct device *dev) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->is_busy) { return -ENOSYS; } return api->is_busy(dev); } /** * @brief Sets a custom character in the display, the custom character struct * must contain the pixel data for the custom character to add and valid * custom character index, if successful then the character_code variable * in the struct will be set to the character code that can be used with * the auxdisplay_write() function to show it. * * A character must be valid for a display consisting of a uint8 array of * size character width by character height, values should be 0x00 for * pixel off or 0xff for pixel on, if a display supports shades then * values between 0x00 and 0xff may be used (display driver dependent). * * @param dev Auxiliary display device instance * @param character Pointer to custom character structure * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_custom_character_set(const struct device *dev, struct auxdisplay_character *character); static inline int z_impl_auxdisplay_custom_character_set(const struct device *dev, struct auxdisplay_character *character) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->custom_character_set) { return -ENOSYS; } return api->custom_character_set(dev, character); } /** * @brief Write data to auxiliary display screen at current position * * @param dev Auxiliary display device instance * @param data Text data to write * @param len Length of text data to write * * @retval 0 on success. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_write(const struct device *dev, const uint8_t *data, uint16_t len); static inline int z_impl_auxdisplay_write(const struct device *dev, const uint8_t *data, uint16_t len) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; return api->write(dev, data, len); } /** * @brief Send a custom command to the display (if supported by driver) * * @param dev Auxiliary display device instance * @param data Custom command structure (this may be extended by specific drivers) * * @retval 0 on success. * @retval -ENOSYS if not supported/implemented. * @retval -EINVAL if provided argument is invalid. * @retval -errno Negative errno code on other failure. */ __syscall int auxdisplay_custom_command(const struct device *dev, struct auxdisplay_custom_data *data); static inline int z_impl_auxdisplay_custom_command(const struct device *dev, struct auxdisplay_custom_data *data) { struct auxdisplay_driver_api *api = (struct auxdisplay_driver_api *)dev->api; if (!api->custom_command) { return -ENOSYS; } return api->custom_command(dev, data); } #ifdef __cplusplus } #endif /** * @} */ #include #endif /* ZEPHYR_INCLUDE_DRIVERS_AUXDISPLAY_H_ */