142 lines
2.7 KiB
C
142 lines
2.7 KiB
C
|
#include "config.h"
|
||
|
|
||
|
#include <avr/io.h>
|
||
|
#include <util/delay.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
#define LCD_DATA_PORT PORTB
|
||
|
#define LCD_DATA_DDR DDRB
|
||
|
#define LCD_RS_PIN PB1
|
||
|
#define LCD_EN_PIN PB2
|
||
|
#define LCD_DB4 PB3
|
||
|
#define LCD_DB5 PB4
|
||
|
#define LCD_DB6 PB5
|
||
|
#define LCD_DB7 PB6
|
||
|
|
||
|
// Delay constants from the datasheet. These are mostly in nanoseconds
|
||
|
#define LAG 10
|
||
|
#define TW 300
|
||
|
#define TSU1 100
|
||
|
|
||
|
void lcd_4bit_init() {
|
||
|
LCD_DATA_DDR = 0xFF;
|
||
|
LCD_DATA_PORT = (1 << LCD_DB5);
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_RS_PIN);
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_DB5);
|
||
|
_delay_us(1);
|
||
|
}
|
||
|
|
||
|
void lcd_send(bool rs, uint8_t data) {
|
||
|
LCD_DATA_DDR = 0xFF;
|
||
|
LCD_DATA_PORT = 0x00;
|
||
|
|
||
|
LCD_DATA_PORT |= (data >> 4) << 3;
|
||
|
_delay_us(1);
|
||
|
|
||
|
// If rs (actual text data), set RS pin high
|
||
|
if(rs == true) LCD_DATA_PORT |= (1 << LCD_RS_PIN);
|
||
|
|
||
|
// Pulse enable
|
||
|
_delay_ms(2);
|
||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||
|
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||
|
|
||
|
//_delay_us(1);
|
||
|
|
||
|
// Clear data pins
|
||
|
LCD_DATA_PORT &= ~(0x0F << 3);
|
||
|
|
||
|
// Mask the lower bits and shift accordingly
|
||
|
LCD_DATA_PORT |= (data & 0x0F) << 3;
|
||
|
_delay_us(1);
|
||
|
|
||
|
// Pulse enable
|
||
|
LCD_DATA_PORT |= (1 << LCD_EN_PIN);
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_EN_PIN);
|
||
|
_delay_us(1);
|
||
|
LCD_DATA_PORT &= ~(0x0F << 3);
|
||
|
|
||
|
LCD_DATA_PORT &= ~(1 << LCD_RS_PIN); // RS Low
|
||
|
}
|
||
|
|
||
|
void lcd_init() {
|
||
|
_delay_ms(100);
|
||
|
lcd_4bit_init();
|
||
|
|
||
|
//lcd_send(1, 0b01111000);
|
||
|
lcd_send(0, 0x01); // Clear screen
|
||
|
lcd_send(0, 0x02); // Return home
|
||
|
lcd_send(0, 0b00001100); // Display on, no cursor
|
||
|
lcd_send(0, 0b00101000);
|
||
|
}
|
||
|
|
||
|
void lcd_clear() {
|
||
|
lcd_send(0, 0x01);
|
||
|
}
|
||
|
|
||
|
void test_leds() {
|
||
|
DDRB |= 0xFF;
|
||
|
PORTB = (1 << LCD_DB4);
|
||
|
_delay_us(1);
|
||
|
PORTB = (1 << LCD_DB5);
|
||
|
_delay_us(1);
|
||
|
PORTB = (1 << LCD_DB6);
|
||
|
_delay_us(1);
|
||
|
PORTB = (1 << LCD_DB7);
|
||
|
_delay_us(1);
|
||
|
|
||
|
PORTB = (1 << LCD_EN_PIN);
|
||
|
_delay_us(1);
|
||
|
PORTB = (1 << LCD_RS_PIN);
|
||
|
_delay_us(1);
|
||
|
PORTB = 0x00;
|
||
|
}
|
||
|
|
||
|
void lcd_set_cursor(uint8_t row, uint8_t col) {
|
||
|
uint8_t position = 0x80;
|
||
|
|
||
|
if (row == 1) position += 0x40;
|
||
|
|
||
|
position += col;
|
||
|
lcd_send(0, position);
|
||
|
}
|
||
|
|
||
|
// Takes a string and splits it over two lines if needed. Max length is 32 characters.
|
||
|
void lcd_write_string(const char* string) {
|
||
|
uint8_t i = 0;
|
||
|
while(string[i]) {
|
||
|
if(i == 16) {
|
||
|
lcd_set_cursor(1, 0);
|
||
|
while(string[i] == ' ') i++; // Skip leading spaces on the new line
|
||
|
}
|
||
|
lcd_send(1, string[i]);
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Takes two separate strings and prints them on their corresponding row
|
||
|
void lcd_write_strings(const char* top, const char* bottom) {
|
||
|
uint8_t i = 0;
|
||
|
|
||
|
while (top[i]) {
|
||
|
lcd_send(1, top[i]);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
i = 0;
|
||
|
lcd_set_cursor(1, 0);
|
||
|
while(bottom[i]) {
|
||
|
lcd_send(1, bottom[i]);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
}
|