This is a part of the Kinetiszer project.
lcd.c@1:8ae4ab73ca6a, 2014-10-28 (annotated)
- Committer:
- Clemo
- Date:
- Tue Oct 28 20:09:12 2014 +0000
- Revision:
- 1:8ae4ab73ca6a
- Parent:
- 0:cb80470434eb
First publication (untested)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Clemo | 0:cb80470434eb | 1 | /** |
Clemo | 0:cb80470434eb | 2 | * @file |
Clemo | 0:cb80470434eb | 3 | * Implementation of a portable LCD driver. |
Clemo | 0:cb80470434eb | 4 | * |
Clemo | 0:cb80470434eb | 5 | * You have to provide two functions to interface this driver |
Clemo | 0:cb80470434eb | 6 | * to the actual hardware: |
Clemo | 0:cb80470434eb | 7 | * |
Clemo | 0:cb80470434eb | 8 | * void lcd_4bit_write_port(uint8_t value); |
Clemo | 0:cb80470434eb | 9 | * |
Clemo | 0:cb80470434eb | 10 | * uint8_t lcd_4bit_read_port(void); |
Clemo | 0:cb80470434eb | 11 | * |
Clemo | 0:cb80470434eb | 12 | * void lcd_backlight(uint8_t on); |
Clemo | 0:cb80470434eb | 13 | * |
Clemo | 0:cb80470434eb | 14 | * Author: Clemens Valens |
Clemo | 0:cb80470434eb | 15 | * License: GNU General Public License |
Clemo | 0:cb80470434eb | 16 | * |
Clemo | 0:cb80470434eb | 17 | * History |
Clemo | 0:cb80470434eb | 18 | * 2011.04.11 ver 1.00 Preliminary version, first release |
Clemo | 0:cb80470434eb | 19 | */ |
Clemo | 0:cb80470434eb | 20 | |
Clemo | 0:cb80470434eb | 21 | #include "lcd.h" |
Clemo | 0:cb80470434eb | 22 | #include "systick.h" |
Clemo | 0:cb80470434eb | 23 | #include "string.h" |
Clemo | 0:cb80470434eb | 24 | |
Clemo | 0:cb80470434eb | 25 | |
Clemo | 0:cb80470434eb | 26 | const uint8_t custom_characters[8][8] = |
Clemo | 0:cb80470434eb | 27 | { |
Clemo | 0:cb80470434eb | 28 | /*{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f }, |
Clemo | 0:cb80470434eb | 29 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 30 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 31 | { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 32 | { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 33 | { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 34 | { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, |
Clemo | 0:cb80470434eb | 35 | { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }*/ |
Clemo | 0:cb80470434eb | 36 | { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 37 | { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04 }, |
Clemo | 0:cb80470434eb | 38 | { 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 39 | { 0x04, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 40 | { 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 41 | // { 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 42 | { 0x04, 0x04, 0x04, 0x0e, 0x0e, 0x1f, 0x1f, 0x04 }, |
Clemo | 0:cb80470434eb | 43 | { 0x04, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, |
Clemo | 0:cb80470434eb | 44 | { 0x1f, 0x1f, 0x0e, 0x0e, 0x04, 0x04, 0x04, 0x04 } |
Clemo | 0:cb80470434eb | 45 | }; |
Clemo | 0:cb80470434eb | 46 | |
Clemo | 0:cb80470434eb | 47 | typedef uint8_t I2C_ID_T; |
Clemo | 0:cb80470434eb | 48 | #define I2C0 (0) |
Clemo | 0:cb80470434eb | 49 | |
Clemo | 0:cb80470434eb | 50 | // State machine handler for I2C0 and I2C1. |
Clemo | 0:cb80470434eb | 51 | static void i2c_state_handling(I2C_ID_T id) |
Clemo | 0:cb80470434eb | 52 | { |
Clemo | 0:cb80470434eb | 53 | /*if (Chip_I2C_IsMasterActive(id)) |
Clemo | 0:cb80470434eb | 54 | { |
Clemo | 0:cb80470434eb | 55 | Chip_I2C_MasterStateHandler(id); |
Clemo | 0:cb80470434eb | 56 | } |
Clemo | 0:cb80470434eb | 57 | else |
Clemo | 0:cb80470434eb | 58 | { |
Clemo | 0:cb80470434eb | 59 | Chip_I2C_SlaveStateHandler(id); |
Clemo | 0:cb80470434eb | 60 | }*/ |
Clemo | 0:cb80470434eb | 61 | } |
Clemo | 0:cb80470434eb | 62 | |
Clemo | 0:cb80470434eb | 63 | |
Clemo | 0:cb80470434eb | 64 | void I2C_IRQHandler(void) |
Clemo | 0:cb80470434eb | 65 | { |
Clemo | 0:cb80470434eb | 66 | i2c_state_handling(I2C0); |
Clemo | 0:cb80470434eb | 67 | } |
Clemo | 0:cb80470434eb | 68 | |
Clemo | 0:cb80470434eb | 69 | |
Clemo | 0:cb80470434eb | 70 | void st7032i_write_byte(uint8_t cmd_or_data, uint8_t value) |
Clemo | 0:cb80470434eb | 71 | { |
Clemo | 0:cb80470434eb | 72 | // buffer must be static because the I2C engine does not copy the data, |
Clemo | 0:cb80470434eb | 73 | // but uses a pointer to buffer. |
Clemo | 0:cb80470434eb | 74 | //static uint8_t buffer[2]; |
Clemo | 0:cb80470434eb | 75 | //buffer[0] = cmd_or_data; |
Clemo | 0:cb80470434eb | 76 | //buffer[1] = value; |
Clemo | 0:cb80470434eb | 77 | //Chip_I2C_MasterSend(I2C0,LCD_I2C_ADDRESS,buffer,2); |
Clemo | 0:cb80470434eb | 78 | } |
Clemo | 0:cb80470434eb | 79 | |
Clemo | 0:cb80470434eb | 80 | |
Clemo | 0:cb80470434eb | 81 | void st7032i_write_data(uint8_t value) |
Clemo | 0:cb80470434eb | 82 | { |
Clemo | 0:cb80470434eb | 83 | // Bit 6 (the RS bit) must be set (1) in order to write the Data Register (DR). |
Clemo | 0:cb80470434eb | 84 | // With bit 7 cleared (the Co bit) only one control byte can be sent. |
Clemo | 0:cb80470434eb | 85 | st7032i_write_byte(0x40,value); |
Clemo | 0:cb80470434eb | 86 | } |
Clemo | 0:cb80470434eb | 87 | |
Clemo | 0:cb80470434eb | 88 | |
Clemo | 0:cb80470434eb | 89 | void st7032i_write_command(uint8_t cmd, uint8_t value) |
Clemo | 0:cb80470434eb | 90 | { |
Clemo | 0:cb80470434eb | 91 | // Bit 6 (the RS bit) must be cleared (0) in order to write the Instruction Register (IR). |
Clemo | 0:cb80470434eb | 92 | // With bit 7 cleared (the Co bit) only one control byte can be sent. |
Clemo | 0:cb80470434eb | 93 | st7032i_write_byte(0x00,cmd|value); |
Clemo | 0:cb80470434eb | 94 | } |
Clemo | 0:cb80470434eb | 95 | |
Clemo | 0:cb80470434eb | 96 | |
Clemo | 0:cb80470434eb | 97 | uint8_t lcd_putc(char ch) |
Clemo | 0:cb80470434eb | 98 | { |
Clemo | 0:cb80470434eb | 99 | st7032i_write_data(ch); |
Clemo | 0:cb80470434eb | 100 | return 1; |
Clemo | 0:cb80470434eb | 101 | } |
Clemo | 0:cb80470434eb | 102 | |
Clemo | 0:cb80470434eb | 103 | |
Clemo | 0:cb80470434eb | 104 | uint8_t lcd_puts(char *p_str) |
Clemo | 0:cb80470434eb | 105 | { |
Clemo | 0:cb80470434eb | 106 | uint8_t result = 0; |
Clemo | 0:cb80470434eb | 107 | |
Clemo | 0:cb80470434eb | 108 | while (*p_str!=0) |
Clemo | 0:cb80470434eb | 109 | { |
Clemo | 0:cb80470434eb | 110 | st7032i_write_data(*p_str++); |
Clemo | 0:cb80470434eb | 111 | result += 1; |
Clemo | 0:cb80470434eb | 112 | } |
Clemo | 0:cb80470434eb | 113 | |
Clemo | 0:cb80470434eb | 114 | return result; |
Clemo | 0:cb80470434eb | 115 | } |
Clemo | 0:cb80470434eb | 116 | |
Clemo | 0:cb80470434eb | 117 | |
Clemo | 0:cb80470434eb | 118 | void lcd_clear(void) |
Clemo | 0:cb80470434eb | 119 | { |
Clemo | 0:cb80470434eb | 120 | st7032i_write_command(ST7032_CMD_CLEAR,0); |
Clemo | 0:cb80470434eb | 121 | SysTick_Delay(2); |
Clemo | 0:cb80470434eb | 122 | } |
Clemo | 0:cb80470434eb | 123 | |
Clemo | 0:cb80470434eb | 124 | |
Clemo | 0:cb80470434eb | 125 | void lcd_cursor(uint8_t line, uint8_t column) |
Clemo | 0:cb80470434eb | 126 | { |
Clemo | 0:cb80470434eb | 127 | st7032i_write_command(ST7032_CMD_DDRAM_ADDRESS,(line==0?0:0x40)+column); |
Clemo | 0:cb80470434eb | 128 | lcd_display_cursor_blink(1,0,0); |
Clemo | 0:cb80470434eb | 129 | } |
Clemo | 0:cb80470434eb | 130 | |
Clemo | 0:cb80470434eb | 131 | |
Clemo | 0:cb80470434eb | 132 | void lcd_display_cursor_blink(uint8_t display, uint8_t cursor, uint8_t blink) |
Clemo | 0:cb80470434eb | 133 | { |
Clemo | 0:cb80470434eb | 134 | uint8_t cmd = 0; |
Clemo | 0:cb80470434eb | 135 | if (display!=0) cmd |= ST7032_DISPLAY_ON; |
Clemo | 0:cb80470434eb | 136 | // Beware of auto-increment. If you don't see the cursor, maybe it fell off the screen? |
Clemo | 0:cb80470434eb | 137 | if (cursor!=0) cmd |= ST7032_CURSOR_ON; |
Clemo | 0:cb80470434eb | 138 | if (blink!=0) cmd |= ST7032_BLINK_ON; |
Clemo | 0:cb80470434eb | 139 | st7032i_write_command(ST7032_CMD_ON_OFF,cmd); |
Clemo | 0:cb80470434eb | 140 | } |
Clemo | 0:cb80470434eb | 141 | |
Clemo | 0:cb80470434eb | 142 | |
Clemo | 0:cb80470434eb | 143 | void lcd_clear_to_eol(int line, int column) |
Clemo | 0:cb80470434eb | 144 | { |
Clemo | 0:cb80470434eb | 145 | uint8_t i; |
Clemo | 0:cb80470434eb | 146 | lcd_cursor(line,column); |
Clemo | 0:cb80470434eb | 147 | for (i=column; i<BOARD_LCD_CHARS_PER_LINE; i++) |
Clemo | 0:cb80470434eb | 148 | { |
Clemo | 0:cb80470434eb | 149 | lcd_putc(' '); |
Clemo | 0:cb80470434eb | 150 | } |
Clemo | 0:cb80470434eb | 151 | lcd_cursor(line,column); |
Clemo | 0:cb80470434eb | 152 | } |
Clemo | 0:cb80470434eb | 153 | |
Clemo | 0:cb80470434eb | 154 | |
Clemo | 0:cb80470434eb | 155 | void lcd_contrast(uint8_t contrast) |
Clemo | 0:cb80470434eb | 156 | { |
Clemo | 0:cb80470434eb | 157 | // Set contrast low bits. |
Clemo | 0:cb80470434eb | 158 | st7032i_write_command(ST7032_CMD_CONTRAST_LO,contrast&ST7032_CONTRAST_LO_MASK); |
Clemo | 0:cb80470434eb | 159 | // Set contrast high bits. |
Clemo | 0:cb80470434eb | 160 | // When LCD is powered from 3V the booster must be on. |
Clemo | 0:cb80470434eb | 161 | st7032i_write_command(ST7032_CMD_POWER_ICON_CONTRAST,ST7032_BOOSTER_ON|((contrast>>4)&ST7032_CONTRAST_HI_MASK)); |
Clemo | 0:cb80470434eb | 162 | } |
Clemo | 0:cb80470434eb | 163 | |
Clemo | 0:cb80470434eb | 164 | |
Clemo | 0:cb80470434eb | 165 | void lcd_font(uint8_t font) |
Clemo | 0:cb80470434eb | 166 | { |
Clemo | 0:cb80470434eb | 167 | st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED|(font&ST7032_FUNC_HEIGHT_DOUBLE)); |
Clemo | 0:cb80470434eb | 168 | } |
Clemo | 0:cb80470434eb | 169 | |
Clemo | 0:cb80470434eb | 170 | |
Clemo | 0:cb80470434eb | 171 | void lcd_set_custom_character(uint8_t index, const uint8_t *p_data) |
Clemo | 0:cb80470434eb | 172 | { |
Clemo | 0:cb80470434eb | 173 | int i; |
Clemo | 0:cb80470434eb | 174 | // Up to 8 custom characters may be defined. |
Clemo | 0:cb80470434eb | 175 | // Select function table 0. |
Clemo | 0:cb80470434eb | 176 | st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_NORMAL); |
Clemo | 0:cb80470434eb | 177 | // Set CGRAM address. |
Clemo | 0:cb80470434eb | 178 | st7032i_write_command(ST7032_CMD_CGRAM_ADDRESS,(8*index)&0x3f); |
Clemo | 0:cb80470434eb | 179 | // 8 bytes per character. |
Clemo | 0:cb80470434eb | 180 | for (i=0; i<7; i++) |
Clemo | 0:cb80470434eb | 181 | { |
Clemo | 0:cb80470434eb | 182 | st7032i_write_data(p_data[i]&0x1f); |
Clemo | 0:cb80470434eb | 183 | } |
Clemo | 0:cb80470434eb | 184 | } |
Clemo | 0:cb80470434eb | 185 | |
Clemo | 0:cb80470434eb | 186 | |
Clemo | 0:cb80470434eb | 187 | void lcd_bar_graph(uint8_t position, uint8_t value, uint8_t value_max) |
Clemo | 0:cb80470434eb | 188 | { |
Clemo | 0:cb80470434eb | 189 | //st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF); |
Clemo | 0:cb80470434eb | 190 | uint16_t v = value; |
Clemo | 0:cb80470434eb | 191 | v = 14*v/value_max; // map [1,255] to 14 possibilities, 0 is possibility 15. |
Clemo | 0:cb80470434eb | 192 | lcd_cursor(1,position); |
Clemo | 0:cb80470434eb | 193 | if (v<=6) |
Clemo | 0:cb80470434eb | 194 | { |
Clemo | 0:cb80470434eb | 195 | if (value==0) |
Clemo | 0:cb80470434eb | 196 | { |
Clemo | 0:cb80470434eb | 197 | v = 5; //'0'; |
Clemo | 0:cb80470434eb | 198 | } |
Clemo | 0:cb80470434eb | 199 | else |
Clemo | 0:cb80470434eb | 200 | { |
Clemo | 0:cb80470434eb | 201 | v += 1; |
Clemo | 0:cb80470434eb | 202 | if (v==5) v = 0x11; |
Clemo | 0:cb80470434eb | 203 | else if (v==7) v = 'T'; |
Clemo | 0:cb80470434eb | 204 | } |
Clemo | 0:cb80470434eb | 205 | lcd_putc(v); |
Clemo | 0:cb80470434eb | 206 | lcd_cursor(0,position); |
Clemo | 0:cb80470434eb | 207 | lcd_putc(0); |
Clemo | 0:cb80470434eb | 208 | } |
Clemo | 0:cb80470434eb | 209 | else |
Clemo | 0:cb80470434eb | 210 | { |
Clemo | 0:cb80470434eb | 211 | lcd_putc(0); |
Clemo | 0:cb80470434eb | 212 | lcd_cursor(0,position); |
Clemo | 0:cb80470434eb | 213 | v -= 6; |
Clemo | 0:cb80470434eb | 214 | if (v==5) v = 0x11; |
Clemo | 0:cb80470434eb | 215 | else if (v==7) v = 'T'; |
Clemo | 0:cb80470434eb | 216 | else if (v>7) v = 7; //'M'; |
Clemo | 0:cb80470434eb | 217 | lcd_putc(v); |
Clemo | 0:cb80470434eb | 218 | } |
Clemo | 0:cb80470434eb | 219 | } |
Clemo | 0:cb80470434eb | 220 | |
Clemo | 0:cb80470434eb | 221 | |
Clemo | 0:cb80470434eb | 222 | void lcd_init(void) |
Clemo | 0:cb80470434eb | 223 | { |
Clemo | 0:cb80470434eb | 224 | int i; |
Clemo | 0:cb80470434eb | 225 | |
Clemo | 0:cb80470434eb | 226 | Board_LCD_SetBacklight(true); |
Clemo | 0:cb80470434eb | 227 | // Liberate LCD. |
Clemo | 0:cb80470434eb | 228 | SysTick_Delay(10); |
Clemo | 0:cb80470434eb | 229 | Board_LCD_ResetDeassert(); |
Clemo | 0:cb80470434eb | 230 | SysTick_Delay(ST7032_RESET_RECOVERY_TIME); |
Clemo | 0:cb80470434eb | 231 | |
Clemo | 0:cb80470434eb | 232 | // Setup I2C port. |
Clemo | 0:cb80470434eb | 233 | // Chip_SYSCTL_DeassertPeriphReset(RESET_I2C0); |
Clemo | 0:cb80470434eb | 234 | // Chip_I2C_Init(I2C0); |
Clemo | 0:cb80470434eb | 235 | // Chip_I2C_SetClockRate(I2C0,400000); // ST7032 can handle 400 kHz. |
Clemo | 0:cb80470434eb | 236 | // Chip_I2C_SetMasterEventHandler(I2C0,Chip_I2C_EventHandler); |
Clemo | 0:cb80470434eb | 237 | // Enable I2C interrupts. |
Clemo | 0:cb80470434eb | 238 | // NVIC_EnableIRQ(I2C0_IRQn); |
Clemo | 0:cb80470434eb | 239 | // Low interrupt priority. |
Clemo | 0:cb80470434eb | 240 | // NVIC_SetPriority(I2C0_IRQn,7); |
Clemo | 0:cb80470434eb | 241 | |
Clemo | 0:cb80470434eb | 242 | // Initialize LCD module. |
Clemo | 0:cb80470434eb | 243 | // Set custom characters. |
Clemo | 0:cb80470434eb | 244 | for (i=0; i<8; i++) |
Clemo | 0:cb80470434eb | 245 | { |
Clemo | 0:cb80470434eb | 246 | lcd_set_custom_character(i,(const uint8_t *)&custom_characters[i]); |
Clemo | 0:cb80470434eb | 247 | } |
Clemo | 0:cb80470434eb | 248 | // Set our default config and enable extended functions. |
Clemo | 0:cb80470434eb | 249 | st7032i_write_command(ST7032_CMD_FUNCTION,ST7032_FUNC_CONFIG_EXTENDED); |
Clemo | 0:cb80470434eb | 250 | // Set internal oscillator. |
Clemo | 0:cb80470434eb | 251 | st7032i_write_command(ST7032_CMD_BIAS_OSC,ST7032_BIAS_020|4); |
Clemo | 0:cb80470434eb | 252 | // Set contrast. 4 is a good value for 3V displays. |
Clemo | 0:cb80470434eb | 253 | lcd_contrast(4); |
Clemo | 0:cb80470434eb | 254 | // Follower on, amplifier max. (Why? From the Midas datasheet) |
Clemo | 0:cb80470434eb | 255 | st7032i_write_command(ST7032_CMD_FOLLOWER,ST7032_FOLLOWER_ON|7); |
Clemo | 0:cb80470434eb | 256 | // A 200 ms delay is recommended for the power to stabilize. |
Clemo | 0:cb80470434eb | 257 | SysTick_Delay(200); |
Clemo | 0:cb80470434eb | 258 | // Display on. |
Clemo | 0:cb80470434eb | 259 | //st7032i_write_command(ST7032_CMD_ON_OFF,ST7032_DISPLAY_ON|ST7032_CURSOR_OFF|ST7032_BLINK_OFF); |
Clemo | 0:cb80470434eb | 260 | lcd_display_cursor_blink(1,0,0); |
Clemo | 0:cb80470434eb | 261 | // Clear display. |
Clemo | 0:cb80470434eb | 262 | lcd_clear(); |
Clemo | 0:cb80470434eb | 263 | |
Clemo | 0:cb80470434eb | 264 | // Check custom characters. |
Clemo | 0:cb80470434eb | 265 | /*lcd_display_cursor_blink(1,1,0); |
Clemo | 0:cb80470434eb | 266 | for (i=0; i<8; i++) |
Clemo | 0:cb80470434eb | 267 | { |
Clemo | 0:cb80470434eb | 268 | lcd_putc((char)i); |
Clemo | 0:cb80470434eb | 269 | } |
Clemo | 0:cb80470434eb | 270 | SysTick_Delay(5000);*/ |
Clemo | 0:cb80470434eb | 271 | } |