This is a part of the Kinetiszer project.
Diff: lcd.c
- Revision:
- 0:cb80470434eb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcd.c Tue Oct 28 12:19:42 2014 +0000 @@ -0,0 +1,271 @@ +/** +* @file +* Implementation of a portable LCD driver. +* +* You have to provide two functions to interface this driver +* to the actual hardware: +* +* void lcd_4bit_write_port(uint8_t value); +* +* uint8_t lcd_4bit_read_port(void); +* +* void lcd_backlight(uint8_t on); +* +* Author: Clemens Valens +* License: GNU General Public License +* +* History +* 2011.04.11 ver 1.00 Preliminary version, first release +*/ + +#include "lcd.h" +#include "systick.h" +#include "string.h" + + +const uint8_t custom_characters[8][8] = +{ + /*{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f }, + { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }*/ + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04 }, + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04 }, + { 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04 }, + { 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04 }, +// { 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x04, 0x04, 0x04, 0x0e, 0x0e, 0x1f, 0x1f, 0x04 }, + { 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x1f, 0x1f, 0x0e, 0x0e, 0x04, 0x04, 0x04, 0x04 } +}; + +typedef uint8_t I2C_ID_T; +#define I2C0 (0) + +// State machine handler for I2C0 and I2C1. +static void i2c_state_handling(I2C_ID_T id) +{ + /*if (Chip_I2C_IsMasterActive(id)) + { + Chip_I2C_MasterStateHandler(id); + } + else + { + Chip_I2C_SlaveStateHandler(id); + }*/ +} + + +void I2C_IRQHandler(void) +{ + i2c_state_handling(I2C0); +} + + +void st7032i_write_byte(uint8_t cmd_or_data, uint8_t value) +{ + // buffer must be static because the I2C engine does not copy the data, + // but uses a pointer to buffer. + //static uint8_t buffer[2]; + //buffer[0] = cmd_or_data; + //buffer[1] = value; + //Chip_I2C_MasterSend(I2C0,LCD_I2C_ADDRESS,buffer,2); +} + + +void st7032i_write_data(uint8_t value) +{ + // Bit 6 (the RS bit) must be set (1) in order to write the Data Register (DR). + // With bit 7 cleared (the Co bit) only one control byte can be sent. + st7032i_write_byte(0x40,value); +} + + +void st7032i_write_command(uint8_t cmd, uint8_t value) +{ + // Bit 6 (the RS bit) must be cleared (0) in order to write the Instruction Register (IR). + // With bit 7 cleared (the Co bit) only one control byte can be sent. + st7032i_write_byte(0x00,cmd|value); +} + + +uint8_t lcd_putc(char ch) +{ + st7032i_write_data(ch); + return 1; +} + + +uint8_t lcd_puts(char *p_str) +{ + uint8_t result = 0; + + while (*p_str!=0) + { + st7032i_write_data(*p_str++); + result += 1; + } + + return result; +} + + +void lcd_clear(void) +{ + st7032i_write_command(ST7032_CMD_CLEAR,0); + SysTick_Delay(2); +} + + +void lcd_cursor(uint8_t line, uint8_t column) +{ + st7032i_write_command(ST7032_CMD_DDRAM_ADDRESS,(line==0?0:0x40)+column); + lcd_display_cursor_blink(1,0,0); +} + + +void lcd_display_cursor_blink(uint8_t display, uint8_t cursor, uint8_t blink) +{ + uint8_t cmd = 0; + if (display!=0) cmd |= ST7032_DISPLAY_ON; + // Beware of auto-increment. If you don't see the cursor, maybe it fell off the screen? + if (cursor!=0) cmd |= ST7032_CURSOR_ON; + if (blink!=0) cmd |= ST7032_BLINK_ON; + st7032i_write_command(ST7032_CMD_ON_OFF,cmd); +} + + +void lcd_clear_to_eol(int line, int column) +{ + uint8_t i; + lcd_cursor(line,column); + for (i=column; i<BOARD_LCD_CHARS_PER_LINE; i++) + { + lcd_putc(' '); + } + lcd_cursor(line,column); +} + + +void lcd_contrast(uint8_t contrast) +{ + // Set contrast low bits. + st7032i_write_command(ST7032_CMD_CONTRAST_LO,contrast&ST7032_CONTRAST_LO_MASK); + // Set contrast high bits. + // When LCD is powered from 3V the booster must be on. + st7032i_write_command(ST7032_CMD_POWER_ICON_CONTRAST,ST7032_BOOSTER_ON|((contrast>>4)&ST7032_CONTRAST_HI_MASK)); +} + + +void lcd_font(uint8_t font) +{ + st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED|(font&ST7032_FUNC_HEIGHT_DOUBLE)); +} + + +void lcd_set_custom_character(uint8_t index, const uint8_t *p_data) +{ + int i; + // Up to 8 custom characters may be defined. + // Select function table 0. + st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_NORMAL); + // Set CGRAM address. + st7032i_write_command(ST7032_CMD_CGRAM_ADDRESS,(8*index)&0x3f); + // 8 bytes per character. + for (i=0; i<7; i++) + { + st7032i_write_data(p_data[i]&0x1f); + } +} + + +void lcd_bar_graph(uint8_t position, uint8_t value, uint8_t value_max) +{ + //st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF); + uint16_t v = value; + v = 14*v/value_max; // map [1,255] to 14 possibilities, 0 is possibility 15. + lcd_cursor(1,position); + if (v<=6) + { + if (value==0) + { + v = 5; //'0'; + } + else + { + v += 1; + if (v==5) v = 0x11; + else if (v==7) v = 'T'; + } + lcd_putc(v); + lcd_cursor(0,position); + lcd_putc(0); + } + else + { + lcd_putc(0); + lcd_cursor(0,position); + v -= 6; + if (v==5) v = 0x11; + else if (v==7) v = 'T'; + else if (v>7) v = 7; //'M'; + lcd_putc(v); + } +} + + +void lcd_init(void) +{ + int i; + + Board_LCD_SetBacklight(true); + // Liberate LCD. + SysTick_Delay(10); + Board_LCD_ResetDeassert(); + SysTick_Delay(ST7032_RESET_RECOVERY_TIME); + + // Setup I2C port. +// Chip_SYSCTL_DeassertPeriphReset(RESET_I2C0); +// Chip_I2C_Init(I2C0); +// Chip_I2C_SetClockRate(I2C0,400000); // ST7032 can handle 400 kHz. +// Chip_I2C_SetMasterEventHandler(I2C0,Chip_I2C_EventHandler); + // Enable I2C interrupts. +// NVIC_EnableIRQ(I2C0_IRQn); + // Low interrupt priority. +// NVIC_SetPriority(I2C0_IRQn,7); + + // Initialize LCD module. + // Set custom characters. + for (i=0; i<8; i++) + { + lcd_set_custom_character(i,(const uint8_t *)&custom_characters[i]); + } + // Set our default config and enable extended functions. + st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED); + // Set internal oscillator. + st7032i_write_command(ST7032_CMD_BIAS_OSC,ST7032_BIAS_020|4); + // Set contrast. 4 is a good value for 3V displays. + lcd_contrast(4); + // Follower on, amplifier max. (Why? From the Midas datasheet) + st7032i_write_command(ST7032_CMD_FOLLOWER,ST7032_FOLLOWER_ON|7); + // A 200 ms delay is recommended for the power to stabilize. + SysTick_Delay(200); + // Display on. + //st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF); + lcd_display_cursor_blink(1,0,0); + // Clear display. + lcd_clear(); + + // Check custom characters. + /*lcd_display_cursor_blink(1,1,0); + for (i=0; i<8; i++) + { + lcd_putc((char)i); + } + SysTick_Delay(5000);*/ +}