#include //! How far can the LCD state be pushed //! \ingroup lcd #define LCD_STATE_DEPTH 3 #define LCD_REG_COMMAND 0 //! LCD State //! \ingroup lcd struct _lcd_state_t { uint8_t x; //!< The X position of the cursor uint8_t y; //!< The Y position of the cursor uint8_t flags; //!< The state flags (backlight, blink) float contrast; //!< The contrast level }; typedef struct _lcd_state_t lcd_state_t; typedef struct _lcd_dvr_t lcd_dvr_t; /*! \struct lcd_dvr_t lcd.h This structure defines the geometry and hardware specific operations of the LCD. \ingroup lcd */ struct _lcd_dvr_t { /*! Initialize the LCD hardware. This includes setup data direction, and bring the LCD into a state where lcd_in() and lcd_out driver calls will work. Also do any contrast and backlight initialization. \param dvr Pointer to "this" driver. \return 0 if successful initializtion. non-zero on error. */ int8_t (*init)(lcd_dvr_t *); /*! Read a byte from the LCD. Select data or command register. \param reg LCD_DATA or LCD_COMMAND \return The data read */ uint8_t (*in)(uint8_t reg); /*! Write a byte to the LCD. Select data or command register \param reg LCD_DATA or LCD_COMMAND */ void (*out)(uint8_t reg, uint8_t dat); /*! Do what is necessary to set the state of the backlight to on \param on The new state of the backlight (LCD_BACKLIGHT_ON or LCD_BACKLIGHT_OFF) */ void (*backlight)(uint8_t on); /*! The LCD contrast is internally represented as a float. The hardware needs to do its best interpolation of the contrast value when setting the contrast. \param c The new contrast */ void (*contrast)(float c); /*! Set by the caller. These values are used to calculate offsets when placing text. */ uint8_t rows; uint8_t cols; /*! The state of the LCD. */ lcd_state_t state[LCD_STATE_DEPTH]; uint8_t state_idx; uint8_t check; }; static inline uint8_t lcd_busy(lcd_dvr_t *lcd) { return lcd->check && (lcd->in(LCD_REG_COMMAND) & 0x80); } static inline void lcd_command(lcd_dvr_t *lcd, uint8_t c) { while (lcd_busy(lcd)) /* do nothing */ ; lcd->out(LCD_REG_COMMAND, c); } void lcd_set_cgram_ptr(lcd_dvr_t *lcd, uint8_t idx) { lcd_command(lcd, 0x40 + idx * 8); }