From 8f45739d02f02c226452f7f62c4dc195e6e13b38 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 31 May 2015 15:48:15 +0200 Subject: o Party functional LCD code. --- LiquidCrystal.c | 197 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 68 deletions(-) (limited to 'LiquidCrystal.c') diff --git a/LiquidCrystal.c b/LiquidCrystal.c index becc07e..eed30c8 100644 --- a/LiquidCrystal.c +++ b/LiquidCrystal.c @@ -1,13 +1,14 @@ #include "LiquidCrystal.h" +#include "nrf_delay.h" +#include "nrf_error.h" #include "nrf_gpio.h" -#include "app_timer.h" /* * Arduino | LCD | nrf51 * D4 | DB4 | P0.16 * D5 | DB5 | P0.17 * D6 | DB6 | P0.18 - * D7 | DB7 | P0.10 + * D7 | DB7 | P0.19 * D8 | RS | P0.20, register select. 0=instruction (write), 0=busy (read), 1=data * D9 | EN | P0.23, clock, data is clocked in/out on falling edge * D10 | DB4 | P0.24 @@ -31,103 +32,109 @@ static struct { uint8_t pin_db7; uint8_t pin_rs; uint8_t pin_en; - - app_gpiote_user_id_t gpio_user_id; } data = { .pin_db4 = 16, .pin_db5 = 17, .pin_db6 = 18, .pin_db7 = 19, .pin_rs = 20, .pin_en = 23, }; -static uint32_t ticks_per_ms; - -static void event_handler() { -} - -static void wait_ms(uint32_t ms) { - uint32_t ticks; - - app_timer_cnt_get(&ticks); - - const uint32_t end_ticks = ticks + ms * ticks_per_ms; - - do { - app_timer_cnt_get(&ticks); - } while (ticks < end_ticks); -} - static void write_4(uint8_t value) { nrf_gpio_pin_write(data.pin_db4, value & 0x01); nrf_gpio_pin_write(data.pin_db5, value & 0x02); nrf_gpio_pin_write(data.pin_db6, value & 0x04); nrf_gpio_pin_write(data.pin_db7, value & 0x08); + nrf_delay_us(10); nrf_gpio_pin_set(data.pin_en); + nrf_delay_us(10); // 450ns is supposed to be sufficient nrf_gpio_pin_clear(data.pin_en); } -static void write_value(uint8_t value, bool is_data) { +static void write_value(uint8_t value, bool is_data, uint32_t delay) { nrf_gpio_pin_write(data.pin_rs, is_data); write_4(value >> 4); write_4(value); -} - -static void begin() { - nrf_gpio_pin_clear(data.pin_rs); - nrf_gpio_pin_clear(data.pin_en); - // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! - // according to datasheet, we need at least 40ms after power rises above 2.7V - // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50 - wait_ms(50); - - write_4(0x03); - wait_ms(5); // 4.5ms - - write_4(0x03); - wait_ms(5); // 4.5ms - - write_4(0x03); - wait_ms(5); // 4.5ms - - write_4(0x02); - - write_value(LIQUID_CRYSTAL_CMD_DISPLAY, false); - -// _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; - liquid_crystal_display(true, true, true); + nrf_delay_us(delay); } void liquid_crystal_write_char(char chr) { - write_value(chr, true); + write_value(chr, true, 50); } void liquid_crystal_write_string(char *chr) { - while (*chr != '\0') { + for (; *chr != '\0'; chr++) { liquid_crystal_write_char(*chr); } } -uint32_t liquid_crystal_display(bool display_on, bool cursor_on, bool blink) { - uint8_t value = LIQUID_CRYSTAL_CMD_DISPLAY; - - value |= display_on ? 0x04 : 0x00; - value |= cursor_on ? 0x02 : 0x00; - value |= blink ? 0x01 : 0x00; - - write_value(value, false); - - return NRF_SUCCESS; +void liquid_crystal_clear() { + // The documentation doesn't specify a value, but everything else is 37us + write_value(LIQUID_CRYSTAL_CMD_CLEAR, false, 50); } -uint32_t liquid_crystal_init(uint32_t _ticks_per_ms) { - ticks_per_ms = _ticks_per_ms; +void liquid_crystal_return_home() { + write_value(LIQUID_CRYSTAL_CMD_RETURN_HOME, false, 2000); +} - uint32_t err_code = app_gpiote_user_register(&data.gpio_user_id, 0x0000, - 0x0000, event_handler); +static struct { + union { + uint8_t value; + struct { + bool shift :1; + bool increment :1; + int :6; + } fields __attribute__((packed)); + }; +}__attribute__((packed)) entry_mode_state; + +void liquid_crystal_entry_mode_set(bool increment, bool shift) { + /* + uint8_t value = LIQUID_CRYSTAL_CMD_ENTRY_MODE_SET; + + value |= increment ? 0x02 : 0x00; + value |= shift ? 0x01 : 0x00; + + write_value(value, false); + */ + + entry_mode_state.fields.increment = increment; + entry_mode_state.fields.shift = shift; + write_value(entry_mode_state.value, false, 50); +} - if (err_code != NRF_SUCCESS) { - return err_code; - } +static struct { + union { + uint8_t value; + struct { + bool blink :1; + bool cursor_on :1; + bool display_on :1; + int :5; + } fields __attribute__((packed)); + }; +}__attribute__((packed)) display_state; + +void liquid_crystal_display(bool display_on, bool cursor_on, bool blink) { + display_state.fields.display_on = display_on; + display_state.fields.cursor_on = cursor_on; + display_state.fields.blink = blink; + + write_value(display_state.value, false, 50); +} +static struct { + union { + uint8_t value; + struct { + int :2; + bool many_dots :1; + bool two_line :1; + bool data_length :1; + int :3; + } fields __attribute__((packed)); + }; +}__attribute__((packed)) function_set_state; + +void liquid_crystal_init(bool data_length, bool two_line, bool many_dots) { nrf_gpio_cfg_output(data.pin_db4); nrf_gpio_cfg_output(data.pin_db5); nrf_gpio_cfg_output(data.pin_db6); @@ -135,7 +142,61 @@ uint32_t liquid_crystal_init(uint32_t _ticks_per_ms) { nrf_gpio_cfg_output(data.pin_rs); nrf_gpio_cfg_output(data.pin_en); - begin(data); + display_state.value = LIQUID_CRYSTAL_CMD_DISPLAY; + entry_mode_state.value = LIQUID_CRYSTAL_CMD_ENTRY_MODE_SET; + function_set_state.value = LIQUID_CRYSTAL_CMD_FUNCTION_SET; + + function_set_state.fields.data_length = data_length; + function_set_state.fields.two_line = two_line; + function_set_state.fields.many_dots = many_dots; + + for (int i = 0; i < 3; i++) { + nrf_gpio_pin_set(data.pin_en); + nrf_delay_ms(100); + nrf_gpio_pin_clear(data.pin_en); + nrf_delay_ms(100); + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50 + nrf_delay_ms(50); + + nrf_gpio_pin_clear(data.pin_rs); + nrf_gpio_pin_clear(data.pin_en); + + write_4(0x03); + nrf_delay_us(4500); + + write_4(0x03); + nrf_delay_us(4500); + + write_4(0x03); + nrf_delay_us(150); + + write_4(0x02); + + write_value(function_set_state.value, false, 50); +} + +void liquid_crystal_reset() { + liquid_crystal_clear(); + liquid_crystal_return_home(); + liquid_crystal_entry_mode_set(true, false); +} + +void liquid_crystal_set_cursor(int column, int row) { + uint8_t value = LIQUID_CRYSTAL_CMD_SET_DDRAM_ADDDRESS; + + if (row == 1) { + value += 0x40; + } else if (row == 2) { + value += 14; + } else if (row == 3) { + value += 54; + } + + value += column; - return NRF_SUCCESS; + write_value(value, false, 50); } -- cgit v1.2.3