Make LCD code working. Add FSM for LCD in order to write it in mainloop
This commit is contained in:
parent
e237776810
commit
df82f14206
@ -31,4 +31,14 @@
|
||||
#define LCD_RS_MASK (1U << LCD_RS)
|
||||
#define LCD_E_MASK (1U << LCD_E)
|
||||
|
||||
enum lcd_fsm_ret {LCD_FSM_NOP, LCD_FSM_CALL_AGAIN, LCD_FSM_WAIT_CALL};
|
||||
|
||||
void lcd_init(void);
|
||||
|
||||
void lcd_string(const char *data);
|
||||
|
||||
void lcd_home(void);
|
||||
|
||||
enum lcd_fsm_ret lcd_fsm_write_buffer(const char (*display_buffer)[21]);
|
||||
|
||||
#endif /* __LCD_H__ */
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include <reflow-controller/ui/lcd.h>
|
||||
#include <reflow-controller/systick.h>
|
||||
#include <stm-periph/clock-enable-manager.h>
|
||||
#include <stm-periph/stm32-gpio-macros.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
static void lcd_port_clear(void)
|
||||
{
|
||||
@ -42,9 +45,9 @@ static void lcd_enable(void)
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
//systick_wait_ms(10);
|
||||
LCD_DPORT->ODR &= ~LCD_E_MASK;
|
||||
__ASM("nop");
|
||||
//systick_wait_ms(10);
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
@ -141,6 +144,8 @@ static void lcd_command(uint8_t data)
|
||||
// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
|
||||
#define LCD_SET_DDADR 0x80
|
||||
|
||||
static char shadow_display[4][21];
|
||||
|
||||
void lcd_clear(void)
|
||||
{
|
||||
lcd_command(LCD_CLEAR_DISPLAY);
|
||||
@ -153,7 +158,7 @@ void lcd_home(void)
|
||||
systick_wait_ms(3);
|
||||
}
|
||||
|
||||
void lcd_setcursor(uint8_t x, uint8_t y)
|
||||
static uint8_t lcd_get_set_cursor_cmd(uint8_t x, uint8_t y)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
@ -179,9 +184,19 @@ void lcd_setcursor(uint8_t x, uint8_t y)
|
||||
break;
|
||||
|
||||
default:
|
||||
return; // für den Fall einer falschen Zeile
|
||||
/* In case of wrong line, assume first line */
|
||||
data = LCD_SET_DDADR + LCD_DDADR_LINE1;
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void lcd_setcursor(uint8_t x, uint8_t y)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
data = lcd_get_set_cursor_cmd(x, y);
|
||||
lcd_command(data);
|
||||
}
|
||||
|
||||
@ -191,13 +206,38 @@ void lcd_string(const char *data)
|
||||
lcd_data((uint8_t)*data++);
|
||||
}
|
||||
|
||||
static void lcd_port_init()
|
||||
{
|
||||
LCD_DPORT->MODER &= MODER_DELETE(LCD_E) & MODER_DELETE(LCD_RS) & MODER_DELETE(LCD_DATA_BIT_OFFSET) &
|
||||
MODER_DELETE(LCD_DATA_BIT_OFFSET + 1) & MODER_DELETE(LCD_DATA_BIT_OFFSET + 2) &
|
||||
MODER_DELETE(LCD_DATA_BIT_OFFSET + 3);
|
||||
|
||||
LCD_DPORT->MODER |= OUTPUT(LCD_E) | OUTPUT(LCD_RS) | OUTPUT(LCD_DATA_BIT_OFFSET) |
|
||||
OUTPUT(LCD_DATA_BIT_OFFSET + 1) | OUTPUT(LCD_DATA_BIT_OFFSET + 2) |
|
||||
OUTPUT(LCD_DATA_BIT_OFFSET + 3);
|
||||
}
|
||||
|
||||
static void lcd_clear_shadow_buff()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 21; j++) {
|
||||
shadow_display[i][j] = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK));
|
||||
lcd_port_init();
|
||||
lcd_port_clear();
|
||||
|
||||
lcd_clear_shadow_buff();
|
||||
|
||||
systick_wait_ms(100);
|
||||
LCD_DPORT->ODR |= (0x3 << LCD_DATA_BIT_OFFSET);
|
||||
|
||||
@ -237,3 +277,173 @@ void lcd_deinit()
|
||||
lcd_port_clear();
|
||||
rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK));
|
||||
}
|
||||
|
||||
static uint8_t compare_input_to_shadow(const char (*display_buffer)[21])
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
int i, row;
|
||||
|
||||
for (row = 0; row < 4; row++) {
|
||||
for (i = 0; i < 20; i++) {
|
||||
if (display_buffer[row][i] != shadow_display[row][i]) {
|
||||
ret |= (1U<<row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lcd_fsm_enable(bool en)
|
||||
{
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
|
||||
if (en)
|
||||
LCD_DPORT->ODR |= LCD_E_MASK;
|
||||
else
|
||||
LCD_DPORT->ODR &= ~LCD_E_MASK;
|
||||
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
__ASM("nop");
|
||||
}
|
||||
|
||||
static void lcd_fsm_write_command(bool high, uint8_t cmd)
|
||||
{
|
||||
lcd_port_clear();
|
||||
|
||||
if (high)
|
||||
lcd_out((cmd >> 4) & 0x0F);
|
||||
else
|
||||
lcd_out((cmd) & 0x0F);
|
||||
}
|
||||
|
||||
static void lcd_fsm_write_data(bool high, uint8_t data)
|
||||
{
|
||||
LCD_DPORT->ODR |= (1<<LCD_RS);
|
||||
if (high)
|
||||
lcd_out((data >> 4) & 0x0F);
|
||||
else
|
||||
lcd_out((data) & 0x0F);
|
||||
}
|
||||
|
||||
enum lcd_fsm_ret lcd_fsm_write_buffer(const char (*display_buffer)[21])
|
||||
{
|
||||
static bool idle = true;
|
||||
static uint8_t rows_to_handle = 0;
|
||||
static uint32_t state_cnt;
|
||||
static uint8_t row_cnt = 0;
|
||||
static uint32_t char_cnt;
|
||||
static uint32_t line_len;
|
||||
static uint64_t timestamp = 0ULL;
|
||||
enum lcd_fsm_ret ret;
|
||||
|
||||
ret = LCD_FSM_NOP;
|
||||
|
||||
if (idle) {
|
||||
rows_to_handle = compare_input_to_shadow(display_buffer);
|
||||
memcpy(shadow_display, display_buffer, sizeof(shadow_display));
|
||||
shadow_display[0][20] = 0;
|
||||
shadow_display[1][20] = 0;
|
||||
shadow_display[2][20] = 0;
|
||||
shadow_display[3][20] = 0;
|
||||
state_cnt = 0;
|
||||
row_cnt = 0;
|
||||
idle = false;
|
||||
}
|
||||
|
||||
if (rows_to_handle == 0) {
|
||||
idle = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((rows_to_handle & (1<<row_cnt))) {
|
||||
switch (state_cnt) {
|
||||
case 0:
|
||||
lcd_fsm_write_command(true, lcd_get_set_cursor_cmd(0, row_cnt));
|
||||
line_len = strlen(&shadow_display[row_cnt][0]);
|
||||
char_cnt = 0;
|
||||
lcd_fsm_enable(true);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 1:
|
||||
lcd_fsm_enable(false);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 2:
|
||||
lcd_fsm_write_command(false, lcd_get_set_cursor_cmd(0, row_cnt));
|
||||
lcd_fsm_enable(true);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 3:
|
||||
lcd_fsm_enable(false);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
timestamp = systick_get_global_tick();
|
||||
state_cnt++;
|
||||
break;
|
||||
case 4:
|
||||
if (!systick_ticks_have_passed(timestamp, 5)) {
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
} else {
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
lcd_fsm_write_data(true, (char_cnt >= line_len) ? ' ' : shadow_display[row_cnt][char_cnt]);
|
||||
lcd_fsm_enable(true);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 6:
|
||||
lcd_fsm_enable(false);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 7:
|
||||
lcd_fsm_write_data(false, (char_cnt >= line_len) ? ' ' : shadow_display[row_cnt][char_cnt]);
|
||||
lcd_fsm_enable(true);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
state_cnt++;
|
||||
break;
|
||||
case 8:
|
||||
lcd_fsm_enable(false);
|
||||
ret = LCD_FSM_WAIT_CALL;
|
||||
char_cnt++;
|
||||
if (char_cnt < 20) {
|
||||
state_cnt = 5;
|
||||
} else {
|
||||
state_cnt = 0;
|
||||
rows_to_handle &= (uint8_t)~(1U<<row_cnt);
|
||||
if (row_cnt < 3) {
|
||||
row_cnt++;
|
||||
} else {
|
||||
idle = true;
|
||||
row_cnt = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = LCD_FSM_NOP;
|
||||
idle = true;
|
||||
rows_to_handle = 0U;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (row_cnt < 3) {
|
||||
row_cnt++;
|
||||
ret = LCD_FSM_CALL_AGAIN;
|
||||
} else {
|
||||
row_cnt = 0;
|
||||
ret = LCD_FSM_NOP;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user