diff --git a/stm-firmware/include/reflow-controller/ui/lcd.h b/stm-firmware/include/reflow-controller/ui/lcd.h index bf14743..be13de4 100644 --- a/stm-firmware/include/reflow-controller/ui/lcd.h +++ b/stm-firmware/include/reflow-controller/ui/lcd.h @@ -21,4 +21,14 @@ #ifndef __LCD_H__ #define __LCD_H__ +#define LCD_DPORT (GPIOD) +#define LCD_RCC_MASK RCC_AHB1ENR_GPIODEN +#define LCD_DATA_BIT_OFFSET (8) +#define LCD_RS (6) +#define LCD_E (7) + +#define LCD_DATA_MASK (0xFU << LCD_DATA_BIT_OFFSET) +#define LCD_RS_MASK (1U << LCD_RS) +#define LCD_E_MASK (1U << LCD_E) + #endif /* __LCD_H__ */ diff --git a/stm-firmware/ui/lcd.c b/stm-firmware/ui/lcd.c index 9fefa6d..41abfc9 100644 --- a/stm-firmware/ui/lcd.c +++ b/stm-firmware/ui/lcd.c @@ -18,4 +18,222 @@ * If not, see . */ +#include #include +#include +#include + +static void lcd_port_clear(void) +{ + LCD_DPORT->ODR &= ~(LCD_E_MASK); + LCD_DPORT->ODR &= ~(LCD_DATA_MASK | LCD_RS_MASK | LCD_E_MASK); +} + +static void lcd_enable(void) +{ + LCD_DPORT->ODR |= LCD_E_MASK; + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + LCD_DPORT->ODR &= ~LCD_E_MASK; + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); + __ASM("nop"); +} + +static void lcd_out(uint8_t data) +{ + LCD_DPORT->ODR &= ~(LCD_DATA_MASK); + LCD_DPORT->ODR |= (data << LCD_DATA_BIT_OFFSET) & LCD_DATA_MASK; +} + +static void lcd_data(uint8_t data) +{ + lcd_port_clear(); + LCD_DPORT->ODR |= LCD_RS_MASK; + lcd_out((data>>4) & 0xFU); + lcd_enable(); + lcd_out(data & 0xFU); + lcd_enable(); + systick_wait_ms(1); +} + +static void lcd_command(uint8_t data) +{ + lcd_port_clear(); + lcd_out((data>>4) & 0xFU); + lcd_enable(); + lcd_out(data & 0xFU); + lcd_enable(); + systick_wait_ms(1); +} + +#define LCD_DDADR_LINE1 0x00 +#define LCD_DDADR_LINE2 0x40 +#define LCD_DDADR_LINE3 0x10 +#define LCD_DDADR_LINE4 0x50 + +// Clear Display -------------- 0b00000001 +#define LCD_CLEAR_DISPLAY 0x01 + +// Cursor Home ---------------- 0b0000001x +#define LCD_CURSOR_HOME 0x02 + +// Set Entry Mode ------------- 0b000001xx +#define LCD_SET_ENTRY 0x04 + +#define LCD_ENTRY_DECREASE 0x00 +#define LCD_ENTRY_INCREASE 0x02 +#define LCD_ENTRY_NOSHIFT 0x00 +#define LCD_ENTRY_SHIFT 0x01 + +// Set Display ---------------- 0b00001xxx +#define LCD_SET_DISPLAY 0x08 + +#define LCD_DISPLAY_OFF 0x00 +#define LCD_DISPLAY_ON 0x04 +#define LCD_CURSOR_OFF 0x00 +#define LCD_CURSOR_ON 0x02 +#define LCD_BLINKING_OFF 0x00 +#define LCD_BLINKING_ON 0x01 + +// Set Shift ------------------ 0b0001xxxx +#define LCD_SET_SHIFT 0x10 + +#define LCD_CURSOR_MOVE 0x00 +#define LCD_DISPLAY_SHIFT 0x08 +#define LCD_SHIFT_LEFT 0x00 +#define LCD_SHIFT_RIGHT 0x04 + +// Set Function --------------- 0b001xxxxx +#define LCD_SET_FUNCTION 0x20 + +#define LCD_FUNCTION_4BIT 0x00 +#define LCD_FUNCTION_8BIT 0x10 +#define LCD_FUNCTION_1LINE 0x00 +#define LCD_FUNCTION_2LINE 0x08 +#define LCD_FUNCTION_5X7 0x00 +#define LCD_FUNCTION_5X10 0x04 + +#define LCD_SOFT_RESET 0x30 + +// Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM) +#define LCD_SET_CGADR 0x40 + +#define LCD_GC_CHAR0 0 +#define LCD_GC_CHAR1 1 +#define LCD_GC_CHAR2 2 +#define LCD_GC_CHAR3 3 +#define LCD_GC_CHAR4 4 +#define LCD_GC_CHAR5 5 +#define LCD_GC_CHAR6 6 +#define LCD_GC_CHAR7 7 + +// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM) +#define LCD_SET_DDADR 0x80 + +void lcd_clear(void) +{ + lcd_command(LCD_CLEAR_DISPLAY); + systick_wait_ms(3); +} + +void lcd_home( void ) +{ + lcd_command(LCD_CURSOR_HOME); + systick_wait_ms(3); +} + +void lcd_setcursor( uint8_t x, uint8_t y ) +{ + uint8_t data; + + switch (y) { + case 0: + /* First line */ + data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x; + break; + + case 1: + /* Second Line */ + data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x; + break; + + case 2: + /* Third line */ + data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x; + break; + + case 3: + /* Fourth line */ + data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x; + break; + + default: + return; // für den Fall einer falschen Zeile + } + + lcd_command(data); +} + +void lcd_string(const char *data) +{ + while (*data != '\0') + lcd_data((uint8_t)*data++); +} + +void lcd_init(void) +{ + int i; + + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK)); + lcd_port_clear(); + + systick_wait_ms(100); + LCD_DPORT->ODR |= (0x3 << LCD_DATA_BIT_OFFSET); + + for (i = 0; i < 3; i++) { + lcd_enable(); + systick_wait_ms(5); + } + + // Set 4 Bit mode + lcd_port_clear(); + LCD_DPORT->ODR |= (0x2<AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK)); +}