reflow-oven-control-sw/stm-firmware/ui/lcd.c

240 lines
5.4 KiB
C
Raw Normal View History

/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
2020-02-23 21:22:38 +01:00
#include <stm32/stm32f4xx.h>
#include <reflow-controller/ui/lcd.h>
2020-02-23 21:22:38 +01:00
#include <reflow-controller/systick.h>
#include <stm-periph/clock-enable-manager.h>
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<<LCD_DATA_BIT_OFFSET);
lcd_enable();
systick_wait_ms(2);
/* 4 Bit mode 2 lines */
lcd_command( LCD_SET_FUNCTION |
LCD_FUNCTION_4BIT |
LCD_FUNCTION_2LINE |
LCD_FUNCTION_5X7 );
/* Display on without cursor */
lcd_command( LCD_SET_DISPLAY |
LCD_DISPLAY_ON |
LCD_CURSOR_OFF |
LCD_BLINKING_OFF);
/* Cursor increment, no scroll */
lcd_command( LCD_SET_ENTRY |
LCD_ENTRY_INCREASE |
LCD_ENTRY_NOSHIFT );
lcd_clear();
}
void lcd_deinit()
{
lcd_port_clear();
rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LCD_RCC_MASK));
}