#include "libCharLCD/lcd.h"
namespace
{
unsigned const LCD_BUSY_FLAG = 0x80;
unsigned const LCD_INIT_SEQ = 0x30; // initialise
unsigned const LCD_DISP_CLEAR = 0x01;
unsigned const LCD_DISP_OFF = 0x08;
unsigned const LCD_DISP_ON = 0x0C;
unsigned const LCD_CURSOR_ON = 0x0E;
unsigned const LCD_CURSOR_OFF = 0x0C;
unsigned const LCD_CURSOR_BLINK = 0x0F;
unsigned const LCD_RETURN_HOME = 0x02;
unsigned const LCD_ENTRY_MODE = 0x06;
unsigned const LCD_4BIT_MODE = 0x20;
unsigned const LCD_8BIT_MODE = 0x30;
unsigned const LCD_1_ROWS = 0x00;
unsigned const LCD_2_ROWS = 0x08;
unsigned const LCD_FONT_5x8 = 0x00;
unsigned const LCD_FONT_5x10 = 0x04;
unsigned const LCD_POSITION = 0x80;
unsigned const LCD_CG = 0x40;
unsigned const LCD_SHIFT = 0x10;
unsigned const LCD_CURSOR = 0x00;
unsigned const LCD_DISPLAY = 0x08;
unsigned const LCD_LEFT = 0x00;
unsigned const LCD_RIGHT = 0x04;
unsigned const LCD_ROW1_START = 0x00;
unsigned const LCD_ROW2_START = 0x40;
} // namespace
// initialise the display
void lcd_t::init()
{
// initialise low level code now ChibiOS is running
m_lcd.init();
m_lcd.writeCtrl4(LCD_INIT_SEQ);
HAL_Delay(5); // > 4.1ms
m_lcd.writeCtrl4(LCD_INIT_SEQ);
HAL_Delay(5);
m_lcd.writeCtrlWait(LCD_4BIT_MODE | LCD_2_ROWS | LCD_FONT_5x8);
HAL_Delay(5);
m_lcd.writeCtrlWait(LCD_4BIT_MODE | LCD_2_ROWS | LCD_FONT_5x8);
m_lcd.writeCtrlWait(LCD_DISP_OFF);
m_lcd.writeCtrlWait(LCD_DISP_CLEAR);
m_lcd.writeCtrlWait(LCD_ENTRY_MODE);
}
/// \brief clear the display
void lcd_t::clear()
{
m_lcd.writeCtrlWait(LCD_DISP_CLEAR);
}
void lcd_t::enable(bool ena_)
{
m_lcd.writeCtrlWait(ena_ ? LCD_DISP_ON : LCD_DISP_OFF);
}
void lcd_t::gotoxy(uint8_t x_, uint8_t y_)
{
if (y_ >= displayYsize())
return;
if (x_ >= displayXsize())
return;
uint8_t row = (y_ == 1) ? LCD_ROW2_START : LCD_ROW1_START;
// x_ is already constrained
m_lcd.writeCtrlWait(LCD_POSITION | row | x_);
}
void lcd_t::printString(char *str_, uint8_t count_)
{
printString(const_cast<char const *>(str_),count_);
}
void lcd_t::printString(char const *str_, uint8_t count_)
{
// if passed a null terminated string and a count less than display X size
if (count_ > displayXsize())
{
count_ = displayXsize();
while (*str_ && count_--)
m_lcd.writeData(*str_++);
return;
}
else
{
while (count_--)
m_lcd.writeData(*str_++);
}
}
uint8_t lcd_t::format_num(char *buff, uint8_t digits, uint8_t dp_pos, int val)
{
digits++;
uint8_t pos = digits;
uint8_t dp_loc = pos - dp_pos;
uint8_t sign = 0;
if (val < 0)
{
sign = 1;
val = -val;
}
buff[pos] = 0;
while (pos)
{
if (pos == dp_loc)
{
buff[--pos] = '.';
}
else
{
buff[--pos] = val % 10 + '0';
val /= 10;
if (val == 0 && pos < dp_loc)
break;
}
}
if (sign)
{
buff[--pos] = '-';
}
return digits;
}
void lcd_t::font_digits(uint8_t digits, uint8_t dp_pos, int val)
{
char buff[10] = " ";
format_num(buff, digits, dp_pos, val);
printString(buff);
}
void lcd_t::defineChar(uint8_t code, uint8_t* rows)
{
defineChar(code, const_cast<uint8_t const *>(rows));
}
void lcd_t::defineChar(uint8_t code, uint8_t const * rows)
{
uint8_t addr = (code & 0x7)* 8;
m_lcd.writeCtrlWait(LCD_CG | (addr &0x3F) );
for (int i = 0; i < 8; i++)
m_lcd.writeData(rows[i] & 0x1f);
}