#include "libCharLCD/lcdInterface.h"
/// \brief Initialise : call after ChibiOS is running .
void lcdInterface_t::init()
{
}
void lcdInterface_t::setLineMode(ioline_t line, unsigned mode)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = line.pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(line.gpio, &GPIO_InitStruct);
}
void lcdInterface_t::polledDelay(unsigned microsec)
{
uint16_t tval = __HAL_TIM_GET_COUNTER(LCD_DELAY_CNT);
// need to determine timer is "after"
while ((__HAL_TIM_GET_COUNTER(LCD_DELAY_CNT) - tval) < microsec)
{
};
};
void lcdInterface_t::writeData4(uint8_t data_)
{
// set write bit to low = write
HAL_GPIO_WritePin(m_wrBit.gpio, m_wrBit.pin, GPIO_PIN_RESET);
for (int i = 0; i < 4; i++)
setLineMode(m_dBits[i], GPIO_MODE_OUTPUT_PP);
for (int i = 0; i < 4; i++)
HAL_GPIO_WritePin(m_dBits[i].gpio, m_dBits[i].pin, (data_ & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
polledDelay(2);
// pulse enable line high
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_SET);
polledDelay(2);
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_RESET);
}
void lcdInterface_t::writeData8(uint8_t data_)
{
writeData4((data_ & 0xF0) >> 4);
writeData4(data_ & 0x0F);
}
uint8_t lcdInterface_t::readData4()
{
// clear write bit to high = read
HAL_GPIO_WritePin(m_wrBit.gpio, m_wrBit.pin, GPIO_PIN_SET);
for (int i = 0; i < 4; i++)
setLineMode(m_dBits[i], GPIO_MODE_INPUT);
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_SET);
polledDelay(2);
uint8_t dat = 0;
for (int i = 0; i < 4; i++)
{
if (HAL_GPIO_ReadPin(m_dBits[i].gpio, m_dBits[i].pin) == GPIO_PIN_SET)
dat |= 1 << i;
}
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_RESET);
return dat;
}
uint8_t lcdInterface_t::readData8()
{
uint8_t dat = readData4() << 4;
dat |= readData4();
return dat;
}
/// \brief Return the X size of this display
uint8_t lcdInterface_t::displayXsize() const
{
switch (m_lcdType)
{
case LCD_8X1:
case LCD_8X2:
return 8;
case LCD_10X1:
case LCD_10X2:
return 10;
case LCD_16X1:
case LCD_16X2:
return 16;
case LCD_20X1:
case LCD_20X2:
return 20;
case LCD_40X1:
case LCD_40X2:
return 40;
}
return 0;
}
/// \brief Return the Y size (1 or 2) of this display
uint8_t lcdInterface_t::displayYsize() const
{
switch (m_lcdType)
{
case LCD_8X1:
case LCD_10X1:
case LCD_16X1:
case LCD_20X1:
case LCD_40X1:
return 1;
case LCD_8X2:
case LCD_10X2:
case LCD_16X2:
case LCD_20X2:
case LCD_40X2:
return 2;
}
return 0;
}
void lcdInterface_t::writeData(uint8_t data_)
{
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_SET);
writeData8(data_);
pollBusy();
}
void lcdInterface_t::writeCtrl(uint8_t data_)
{
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_RESET);
writeData8(data_);
}
void lcdInterface_t::writeCtrl4(uint8_t data_)
{
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_RESET);
writeData4(data_ >> 4);
}
void lcdInterface_t::pollBusy()
{
// read from the status bit
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_RESET);
// limit to a certain number of loops
int tries = 1000;
while (--tries)
{
if ((readData8() & 0x80) == 0)
return;
}
m_timeouts++;
// fall out as it failed .
}
void lcdInterface_t::writeCtrlWait(uint8_t data_)
{
writeCtrl(data_);
pollBusy();
}
uint8_t lcdInterface_t::readData()
{
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_SET);
return readData8();
}
uint8_t lcdInterface_t::readCtrl()
{
HAL_GPIO_WritePin(m_rsBit.gpio, m_rsBit.pin, GPIO_PIN_RESET);
return readData8();
}
void lcdInterface_t::pulseE()
{
// pulse enable line high
polledDelay(2);
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_SET);
polledDelay(2);
HAL_GPIO_WritePin(m_eBit.gpio, m_eBit.pin, GPIO_PIN_RESET);
}