242 lines
6.6 KiB
C++
242 lines
6.6 KiB
C++
/*
|
|
* Display.cpp
|
|
*
|
|
* Created on: Aug 12, 2023
|
|
* Author: Carst
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <stm32g0xx_ll_gpio.h>
|
|
#include "STM32G071KBT6.hpp"
|
|
#include "Display.hpp"
|
|
|
|
#define pulse_delay() for(uint32_t i = 0UL; i < 1UL; i++);
|
|
#define PIN_RS LL_GPIO_PIN_4
|
|
#define PIN_RW LL_GPIO_PIN_5
|
|
#define PIN_E LL_GPIO_PIN_6
|
|
#define PIN_BL LL_GPIO_PIN_7
|
|
|
|
namespace ElektronischeLast
|
|
{
|
|
void Display::init(void)
|
|
{
|
|
LL_GPIO_InitTypeDef init =
|
|
{
|
|
.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3 |
|
|
PIN_RS | PIN_RW | PIN_E | PIN_BL,
|
|
.Mode = LL_GPIO_MODE_OUTPUT,
|
|
.Speed = LL_GPIO_SPEED_FREQ_LOW,
|
|
.OutputType = LL_GPIO_OUTPUT_PUSHPULL,
|
|
.Pull = LL_GPIO_PULL_NO,
|
|
};
|
|
LL_GPIO_Init(GPIOB, &init);
|
|
|
|
this->set_backlight(true);
|
|
this->current_state = StateDelay;
|
|
this->next_state = StateInit01;
|
|
this->start_timer(15UL); // 15ms Startup Delay
|
|
}
|
|
|
|
void Display::run(void)
|
|
{
|
|
switch (this->current_state)
|
|
{
|
|
case StateIdle:
|
|
if(this->new_data)
|
|
{
|
|
this->new_data = false;
|
|
this->current_state = StateWriteData;
|
|
}
|
|
break;
|
|
case StateDelay:
|
|
if(this->timer_elapsed())
|
|
{
|
|
this->current_state = this->next_state;
|
|
this->run();
|
|
}
|
|
break;
|
|
case StateWaitWhileBusy:
|
|
break;
|
|
case StateInit01:
|
|
write_command_8bit_4pin(0x30u);
|
|
this->start_timer(5UL); // 5ms Delay
|
|
this->next_state = StateInit02;
|
|
break;
|
|
case StateInit02:
|
|
write_command_8bit_4pin(0x30u);
|
|
this->start_timer(1UL); // 1ms Delay
|
|
this->next_state = StateInit03;
|
|
break;
|
|
case StateInit03:
|
|
write_command_8bit_4pin(0x30u);
|
|
this->start_timer(1UL); // 1ms Delay
|
|
this->next_state = StateInit04;
|
|
break;
|
|
case StateInit04:
|
|
// 4-bit mode
|
|
write_command_8bit_4pin(0x20u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit05;
|
|
break;
|
|
case StateInit05:
|
|
// 4-bit mode, 2 lines
|
|
write_command_4bit(0x28u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit06;
|
|
break;
|
|
case StateInit06:
|
|
// Display off
|
|
write_command_4bit(0x08u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit07;
|
|
break;
|
|
case StateInit07:
|
|
// Clear Display
|
|
write_command_4bit(0x01u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit08;
|
|
break;
|
|
case StateInit08:
|
|
// increment DDRAM
|
|
write_command_4bit(0x06u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit09;
|
|
break;
|
|
case StateInit09:
|
|
// return cursor home
|
|
write_command_4bit(0x02u);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateInit10;
|
|
break;
|
|
case StateInit10:
|
|
// Display on, Cursor on, Blink on
|
|
write_command_4bit(0x0Fu);
|
|
this->start_timer(1UL);
|
|
this->next_state = StateIdle;
|
|
break;
|
|
case StateWriteData:
|
|
write_data_4bit((std::uint8_t)this->string[this->pointer++]);
|
|
if(this->string[this->pointer] == '\0')
|
|
{
|
|
this->next_state = StateIdle;
|
|
}
|
|
else
|
|
{
|
|
this->next_state = StateWriteData;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Display::set_backlight(bool on)
|
|
{
|
|
if(on)
|
|
{
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_BL);
|
|
}
|
|
else
|
|
{
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_BL);
|
|
}
|
|
}
|
|
|
|
void Display::set_cursor(Line_t line, std::uint32_t position)
|
|
{
|
|
lcd_cmd(0x80u | line | (position & 0x7F));
|
|
}
|
|
|
|
void Display::print(const char* const string)
|
|
{
|
|
strncpy(this->string, string, sizeof(this->string));
|
|
this->pointer = 0U;
|
|
this->new_data = true;
|
|
}
|
|
|
|
bool Display::timer_elapsed(void)
|
|
{
|
|
return (this->timer < systick);
|
|
}
|
|
|
|
void Display::start_timer(std::uint32_t timeout)
|
|
{
|
|
this->timer = systick + 1U + timeout; // +1 damit auch mindestens 1ms vorbei geht.
|
|
this->current_state = StateDelay;
|
|
}
|
|
|
|
void Display::write_command_8bit_4pin(std::uint32_t data)
|
|
{
|
|
// RS=low, RW=low
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_RS | PIN_RW | PIN_E);
|
|
std::uint32_t tmp = data >> 4U;
|
|
tmp |= ((~(data >> 4U) & 0xFU) << GPIO_BSRR_BR0_Pos);
|
|
LL_GPIO_SetOutputPin(GPIOB, tmp);
|
|
__NOP();
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_E);
|
|
pulse_delay();
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_E);
|
|
}
|
|
|
|
void Display::write_command_4bit(std::uint32_t command)
|
|
{
|
|
// RS=low, RW=low
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_RS | PIN_RW | PIN_E);
|
|
std::uint32_t tmp = command >> 4U;
|
|
tmp |= ((~(command >> 4U) & 0xFU) << GPIO_BSRR_BR0_Pos);
|
|
LL_GPIO_SetOutputPin(GPIOB, tmp);
|
|
__NOP();
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_E);
|
|
pulse_delay();
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_E);
|
|
tmp = command & 0x0FU;
|
|
tmp |= ((~command & 0xFU) << GPIO_BSRR_BR0_Pos);
|
|
LL_GPIO_SetOutputPin(GPIOB, tmp);
|
|
__NOP();
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_E);
|
|
pulse_delay();
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_E);
|
|
}
|
|
|
|
/// \brief write command to lcd and wait until busy is gone
|
|
/// \param[in] cmd command to transfer
|
|
void Display::lcd_cmd(uint8_t cmd)
|
|
{
|
|
write_command_4bit(cmd);
|
|
this->start_timer(1UL);
|
|
}
|
|
|
|
/// \brief write data to display
|
|
/// \param[in] data data which to write to display
|
|
void Display::lcd_data(uint8_t data)
|
|
{
|
|
write_data_4bit(data);
|
|
this->start_timer(1UL);
|
|
}
|
|
|
|
/// \brief write data to lcd in 4 bit mode
|
|
/// \details write data given by \p data to lcd.
|
|
/// First write upper nibble and in second step lower nibble
|
|
/// \param[in] data data to transfer
|
|
void Display::write_data_4bit(uint8_t data)
|
|
{
|
|
// RS=high, RW=low
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_RS | PIN_RW << GPIO_BSRR_BR0_Pos | PIN_E << GPIO_BSRR_BR0_Pos);
|
|
std::uint32_t tmp = data >> 4U;
|
|
tmp |= ((~(data >> 4U) & 0xFU) << GPIO_BSRR_BR0_Pos);
|
|
LL_GPIO_SetOutputPin(GPIOB, tmp);
|
|
__NOP();
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_E);
|
|
pulse_delay();
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_E);
|
|
tmp = data & 0x0FU;
|
|
tmp |= ((~data & 0xFU) << GPIO_BSRR_BR0_Pos);
|
|
LL_GPIO_SetOutputPin(GPIOB, tmp);
|
|
__NOP();
|
|
LL_GPIO_SetOutputPin(GPIOB, PIN_E);
|
|
pulse_delay();
|
|
LL_GPIO_ResetOutputPin(GPIOB, PIN_E);
|
|
this->start_timer(1UL);
|
|
}
|
|
}
|