Lightweight proportional text library for C12832 LCD. Easy to modify, fast, robust and compact. Nice font, good for text driven menus, messages, etc. Fell free to use and modify in any projects.

Dependents:   app-board-lcd128

Documentation will be here later.

Usage sample:

Import programapp-board-lcd128

Sample usage of lightweight C12832 LCD library

Committer:
medvdv
Date:
Sat Jan 14 14:52:41 2017 +0000
Revision:
7:d73d65360196
Parent:
6:5cd32671a837
New revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
medvdv 0:6ac8f630d9a0 1 //
medvdv 0:6ac8f630d9a0 2 // MBED Application Board
medvdv 0:6ac8f630d9a0 3 // Lightweight C12832 LCD library
medvdv 0:6ac8f630d9a0 4 // 2014, Alexander Medvedev, @medvdv
medvdv 0:6ac8f630d9a0 5 //
medvdv 0:6ac8f630d9a0 6
medvdv 0:6ac8f630d9a0 7 #include "mbed.h"
medvdv 0:6ac8f630d9a0 8
medvdv 0:6ac8f630d9a0 9 #include "lcd128lib.h"
medvdv 0:6ac8f630d9a0 10 #include "lcd128font8.h"
medvdv 0:6ac8f630d9a0 11
medvdv 0:6ac8f630d9a0 12 //
medvdv 0:6ac8f630d9a0 13 // lcd128 class implementation
medvdv 0:6ac8f630d9a0 14 //
medvdv 0:6ac8f630d9a0 15
medvdv 0:6ac8f630d9a0 16 // SPI writer with command / data switch
medvdv 4:1bd241d1fad0 17
medvdv 5:ff31feb7d966 18 void lcd128::write(unsigned char data, bool cmd)
medvdv 0:6ac8f630d9a0 19 {
medvdv 6:5cd32671a837 20 a0 = cmd ? 0 : 1;
medvdv 6:5cd32671a837 21 cs = 0;
medvdv 0:6ac8f630d9a0 22 spi.write(data);
medvdv 6:5cd32671a837 23 cs = 1;
medvdv 0:6ac8f630d9a0 24 }
medvdv 0:6ac8f630d9a0 25
medvdv 4:1bd241d1fad0 26 // Constructor, SPI setup and defaults
medvdv 4:1bd241d1fad0 27
medvdv 0:6ac8f630d9a0 28 lcd128::lcd128(PinName mosi, PinName sclk, PinName p_a0, PinName p_cs, PinName p_rst):
medvdv 0:6ac8f630d9a0 29 spi(mosi, NC, sclk), rst(p_rst), cs(p_cs), a0(p_a0)
medvdv 0:6ac8f630d9a0 30 {
medvdv 0:6ac8f630d9a0 31 // Setup SPI
medvdv 0:6ac8f630d9a0 32 spi.format(8, 3);
medvdv 0:6ac8f630d9a0 33 spi.frequency(20000000);
medvdv 0:6ac8f630d9a0 34
medvdv 6:5cd32671a837 35 // Default font
medvdv 0:6ac8f630d9a0 36 font.first_code = 32;
medvdv 7:d73d65360196 37 font.glyphs_total = sizeof(font8widths) / sizeof(unsigned char);
medvdv 7:d73d65360196 38 font.widths = font8widths;
medvdv 7:d73d65360196 39 font.glyphs = font8chars;
medvdv 0:6ac8f630d9a0 40
medvdv 6:5cd32671a837 41 // Default drawing modes
medvdv 0:6ac8f630d9a0 42 invert = false;
medvdv 1:17443d6d2740 43 bold = false;
medvdv 1:17443d6d2740 44 underline = false;
medvdv 0:6ac8f630d9a0 45 }
medvdv 0:6ac8f630d9a0 46
medvdv 4:1bd241d1fad0 47 // Inverting chars on / off
medvdv 4:1bd241d1fad0 48
medvdv 0:6ac8f630d9a0 49 void lcd128::Invert(bool invert)
medvdv 0:6ac8f630d9a0 50 {
medvdv 0:6ac8f630d9a0 51 this -> invert = invert;
medvdv 0:6ac8f630d9a0 52 }
medvdv 0:6ac8f630d9a0 53
medvdv 4:1bd241d1fad0 54 // Bold mode (twice wide chars) on / off
medvdv 4:1bd241d1fad0 55
medvdv 0:6ac8f630d9a0 56 void lcd128::Bold(bool bold)
medvdv 0:6ac8f630d9a0 57 {
medvdv 0:6ac8f630d9a0 58 this -> bold = bold;
medvdv 0:6ac8f630d9a0 59 }
medvdv 0:6ac8f630d9a0 60
medvdv 4:1bd241d1fad0 61 // Underline mode on / off
medvdv 4:1bd241d1fad0 62
medvdv 1:17443d6d2740 63 void lcd128::Underline(bool underline)
medvdv 1:17443d6d2740 64 {
medvdv 1:17443d6d2740 65 this -> underline = underline;
medvdv 1:17443d6d2740 66 }
medvdv 1:17443d6d2740 67
medvdv 0:6ac8f630d9a0 68 // Reset LCD, configure defaults and contrast
medvdv 4:1bd241d1fad0 69
medvdv 0:6ac8f630d9a0 70 void lcd128::Reset()
medvdv 0:6ac8f630d9a0 71 {
medvdv 0:6ac8f630d9a0 72 a0 = 0;
medvdv 0:6ac8f630d9a0 73 cs = 1;
medvdv 0:6ac8f630d9a0 74 rst = 0;
medvdv 4:1bd241d1fad0 75
medvdv 0:6ac8f630d9a0 76 wait_us(50);
medvdv 4:1bd241d1fad0 77
medvdv 0:6ac8f630d9a0 78 rst = 1;
medvdv 0:6ac8f630d9a0 79
medvdv 0:6ac8f630d9a0 80 wait_ms(5);
medvdv 0:6ac8f630d9a0 81
medvdv 0:6ac8f630d9a0 82 write(0xae, true);
medvdv 0:6ac8f630d9a0 83 write(0xa2, true);
medvdv 0:6ac8f630d9a0 84 write(0xa0, true);
medvdv 0:6ac8f630d9a0 85 write(0xc8, true);
medvdv 0:6ac8f630d9a0 86 write(0x22, true);
medvdv 0:6ac8f630d9a0 87 write(0x2f, true);
medvdv 0:6ac8f630d9a0 88 write(0x40, true);
medvdv 0:6ac8f630d9a0 89
medvdv 0:6ac8f630d9a0 90 write(0xaf, true);
medvdv 0:6ac8f630d9a0 91 write(0x81, true);
medvdv 0:6ac8f630d9a0 92 write(0x17, true);
medvdv 0:6ac8f630d9a0 93 write(0xa6, true);
medvdv 0:6ac8f630d9a0 94
medvdv 0:6ac8f630d9a0 95 wait_ms(5);
medvdv 0:6ac8f630d9a0 96
medvdv 0:6ac8f630d9a0 97 XY();
medvdv 0:6ac8f630d9a0 98 Clear();
medvdv 0:6ac8f630d9a0 99 Update();
medvdv 0:6ac8f630d9a0 100 }
medvdv 0:6ac8f630d9a0 101
medvdv 4:1bd241d1fad0 102 // LCD power on / off
medvdv 4:1bd241d1fad0 103
medvdv 0:6ac8f630d9a0 104 void lcd128::Power(bool power)
medvdv 0:6ac8f630d9a0 105 {
medvdv 2:fdea8ffb3c4f 106 if (!power) {
medvdv 2:fdea8ffb3c4f 107 write(0xae, true);
medvdv 2:fdea8ffb3c4f 108 write(0xa5, true);
medvdv 2:fdea8ffb3c4f 109 } else {
medvdv 2:fdea8ffb3c4f 110 write(0xaf, true);
medvdv 2:fdea8ffb3c4f 111 write(0xa4, true);
medvdv 2:fdea8ffb3c4f 112 }
medvdv 0:6ac8f630d9a0 113 }
medvdv 0:6ac8f630d9a0 114
medvdv 4:1bd241d1fad0 115 // Invert LCD on / off
medvdv 4:1bd241d1fad0 116
medvdv 0:6ac8f630d9a0 117 void lcd128::InverseMode(bool invert)
medvdv 0:6ac8f630d9a0 118 {
medvdv 2:fdea8ffb3c4f 119 if (!invert)
medvdv 2:fdea8ffb3c4f 120 write(0xa6, true);
medvdv 2:fdea8ffb3c4f 121 else
medvdv 2:fdea8ffb3c4f 122 write(0xa7, true);
medvdv 0:6ac8f630d9a0 123 }
medvdv 0:6ac8f630d9a0 124
medvdv 0:6ac8f630d9a0 125 // Update buffer to LCD
medvdv 4:1bd241d1fad0 126
medvdv 0:6ac8f630d9a0 127 void lcd128::Update()
medvdv 0:6ac8f630d9a0 128 {
medvdv 5:ff31feb7d966 129 unsigned char* p = buffer;
medvdv 0:6ac8f630d9a0 130
medvdv 0:6ac8f630d9a0 131 for(int j=0; j<LCD_Y; j++) {
medvdv 0:6ac8f630d9a0 132 write(0x00, true);
medvdv 0:6ac8f630d9a0 133 write(0x10, true);
medvdv 0:6ac8f630d9a0 134 write(0xb0+j, true);
medvdv 0:6ac8f630d9a0 135 for(int i=0; i<LCD_X; i++) write(*p++, false);
medvdv 0:6ac8f630d9a0 136 }
medvdv 0:6ac8f630d9a0 137 }
medvdv 0:6ac8f630d9a0 138
medvdv 0:6ac8f630d9a0 139 // Clear all buffer or just one row
medvdv 4:1bd241d1fad0 140
medvdv 0:6ac8f630d9a0 141 void lcd128::Clear(int row)
medvdv 0:6ac8f630d9a0 142 {
medvdv 0:6ac8f630d9a0 143 if(row == -1)
medvdv 0:6ac8f630d9a0 144 memset(buffer, 0, sizeof(buffer));
medvdv 0:6ac8f630d9a0 145 else {
medvdv 6:5cd32671a837 146 if(row < 0) row = 0;
medvdv 6:5cd32671a837 147 if(row >= LCD_Y) row = LCD_Y - 1;
medvdv 6:5cd32671a837 148 memset(buffer + row*LCD_X, 0, LCD_X);
medvdv 0:6ac8f630d9a0 149 }
medvdv 6:5cd32671a837 150 }
medvdv 0:6ac8f630d9a0 151
medvdv 6:5cd32671a837 152 // Inverse all buffer or just one row
medvdv 6:5cd32671a837 153
medvdv 6:5cd32671a837 154 void lcd128::InverseRow(int row, unsigned char mask)
medvdv 6:5cd32671a837 155 {
medvdv 6:5cd32671a837 156 if(row == -1)
medvdv 6:5cd32671a837 157 for(int i=0; i < LCD_X*LCD_Y; i++) buffer[i] ^= mask;
medvdv 6:5cd32671a837 158 else {
medvdv 6:5cd32671a837 159 if(row < 0) row = 0;
medvdv 6:5cd32671a837 160 if(row >= LCD_Y) row = LCD_Y - 1;
medvdv 6:5cd32671a837 161 for(int i=LCD_X*row; i < LCD_X*(row+1); i++) buffer[i] ^= mask;
medvdv 6:5cd32671a837 162 }
medvdv 0:6ac8f630d9a0 163 }
medvdv 0:6ac8f630d9a0 164
medvdv 0:6ac8f630d9a0 165 // Change current output position
medvdv 0:6ac8f630d9a0 166 // X in pixels [0..LCD_X-1]
medvdv 0:6ac8f630d9a0 167 // Y in rows [0..LCD_Y-1]
medvdv 4:1bd241d1fad0 168
medvdv 0:6ac8f630d9a0 169 void lcd128::XY(int x, int y)
medvdv 0:6ac8f630d9a0 170 {
medvdv 0:6ac8f630d9a0 171 if (x<0) x=0;
medvdv 0:6ac8f630d9a0 172 if (x>(LCD_X-1)) x=LCD_X-1;
medvdv 0:6ac8f630d9a0 173 if (y<0) y=0;
medvdv 0:6ac8f630d9a0 174 if (y>(LCD_Y-1)) y=LCD_Y-1;
medvdv 0:6ac8f630d9a0 175
medvdv 0:6ac8f630d9a0 176 X = x;
medvdv 0:6ac8f630d9a0 177 Y = y;
medvdv 0:6ac8f630d9a0 178 }
medvdv 0:6ac8f630d9a0 179
medvdv 0:6ac8f630d9a0 180 // Write one 8bit row
medvdv 0:6ac8f630d9a0 181 // with inversion and XY update
medvdv 4:1bd241d1fad0 182
medvdv 5:ff31feb7d966 183 void lcd128::Write(unsigned char byte)
medvdv 0:6ac8f630d9a0 184 {
medvdv 1:17443d6d2740 185 if (underline) byte |= 0x80;
medvdv 5:ff31feb7d966 186 buffer[X+Y*LCD_X] = invert ? (~byte) : byte;
medvdv 0:6ac8f630d9a0 187
medvdv 0:6ac8f630d9a0 188 if (++X > (LCD_X-1)) {
medvdv 0:6ac8f630d9a0 189 X=0;
medvdv 0:6ac8f630d9a0 190 if (++Y > (LCD_Y-1)) Y=0;
medvdv 0:6ac8f630d9a0 191 }
medvdv 0:6ac8f630d9a0 192 }
medvdv 0:6ac8f630d9a0 193
medvdv 0:6ac8f630d9a0 194 // Write array of 8bit rows
medvdv 4:1bd241d1fad0 195
medvdv 5:ff31feb7d966 196 void lcd128::Write(unsigned char * data, int size)
medvdv 0:6ac8f630d9a0 197 {
medvdv 1:17443d6d2740 198 for (int i=0; i<size; i++) Write(data[i]);
medvdv 0:6ac8f630d9a0 199 }
medvdv 0:6ac8f630d9a0 200
medvdv 0:6ac8f630d9a0 201 // Write array of 8bit rows, twice each
medvdv 4:1bd241d1fad0 202
medvdv 5:ff31feb7d966 203 void lcd128::Write2(unsigned char * data, int size)
medvdv 0:6ac8f630d9a0 204 {
medvdv 1:17443d6d2740 205 for (int i=0; i<size; i++) {
medvdv 0:6ac8f630d9a0 206 Write(data[i]);
medvdv 0:6ac8f630d9a0 207 Write(data[i]);
medvdv 0:6ac8f630d9a0 208 }
medvdv 0:6ac8f630d9a0 209 }
medvdv 0:6ac8f630d9a0 210
medvdv 0:6ac8f630d9a0 211 // Write 8bit row 'count' times
medvdv 4:1bd241d1fad0 212
medvdv 5:ff31feb7d966 213 void lcd128::Write(unsigned char byte, int count)
medvdv 0:6ac8f630d9a0 214 {
medvdv 1:17443d6d2740 215 for (int i=0; i<count; i++) Write(byte);
medvdv 0:6ac8f630d9a0 216 }
medvdv 0:6ac8f630d9a0 217
medvdv 0:6ac8f630d9a0 218 // Draw one proportional font character
medvdv 0:6ac8f630d9a0 219 // Jump to next line if empty space is not enought
medvdv 4:1bd241d1fad0 220
medvdv 0:6ac8f630d9a0 221 void lcd128::Character(char chr)
medvdv 0:6ac8f630d9a0 222 {
medvdv 0:6ac8f630d9a0 223 if( chr < font.first_code ) return;
medvdv 0:6ac8f630d9a0 224 if( chr > font.first_code + font.glyphs_total - 1 ) return;
medvdv 0:6ac8f630d9a0 225
medvdv 0:6ac8f630d9a0 226 chr -= font.first_code;
medvdv 0:6ac8f630d9a0 227
medvdv 0:6ac8f630d9a0 228 int width = font.widths[chr];
medvdv 0:6ac8f630d9a0 229
medvdv 0:6ac8f630d9a0 230 if (bold) width*=2;
medvdv 0:6ac8f630d9a0 231
medvdv 0:6ac8f630d9a0 232 if ((X + width) > (LCD_X-1)) {
medvdv 0:6ac8f630d9a0 233 if (++Y > (LCD_Y-1)) Y = 0;
medvdv 0:6ac8f630d9a0 234 XY(0,Y);
medvdv 0:6ac8f630d9a0 235 }
medvdv 0:6ac8f630d9a0 236
medvdv 0:6ac8f630d9a0 237 if (bold) {
medvdv 5:ff31feb7d966 238 Write2( (unsigned char*) font.glyphs[chr], (int) font.widths[chr] );
medvdv 0:6ac8f630d9a0 239 if (X != 0) {
medvdv 0:6ac8f630d9a0 240 Write(0);
medvdv 0:6ac8f630d9a0 241 Write(0);
medvdv 0:6ac8f630d9a0 242 }
medvdv 0:6ac8f630d9a0 243 } else {
medvdv 5:ff31feb7d966 244 Write( (unsigned char*) font.glyphs[chr], (int) font.widths[chr] );
medvdv 0:6ac8f630d9a0 245 if (X != 0) Write(0);
medvdv 0:6ac8f630d9a0 246 }
medvdv 0:6ac8f630d9a0 247 }
medvdv 0:6ac8f630d9a0 248
medvdv 0:6ac8f630d9a0 249 // Calculate width of concrete character
medvdv 0:6ac8f630d9a0 250 // takes into account bold setting
medvdv 4:1bd241d1fad0 251
medvdv 0:6ac8f630d9a0 252 int lcd128::CharacterWidth(char chr)
medvdv 0:6ac8f630d9a0 253 {
medvdv 0:6ac8f630d9a0 254 if( chr < font.first_code ) return 0;
medvdv 0:6ac8f630d9a0 255 if( chr > font.first_code + font.glyphs_total - 1 ) return 0;
medvdv 0:6ac8f630d9a0 256
medvdv 0:6ac8f630d9a0 257 chr -= font.first_code;
medvdv 0:6ac8f630d9a0 258
medvdv 0:6ac8f630d9a0 259 if (bold)
medvdv 0:6ac8f630d9a0 260 return 2 * (font.widths[chr] + 1);
medvdv 0:6ac8f630d9a0 261 else
medvdv 0:6ac8f630d9a0 262 return font.widths[chr] + 1;
medvdv 0:6ac8f630d9a0 263 }
medvdv 0:6ac8f630d9a0 264
medvdv 0:6ac8f630d9a0 265 // Write string
medvdv 4:1bd241d1fad0 266
medvdv 0:6ac8f630d9a0 267 void lcd128::String(char* str)
medvdv 0:6ac8f630d9a0 268 {
medvdv 0:6ac8f630d9a0 269 while(*str) Character(*str++);
medvdv 0:6ac8f630d9a0 270 }
medvdv 0:6ac8f630d9a0 271
medvdv 0:6ac8f630d9a0 272 // Predict string width
medvdv 4:1bd241d1fad0 273
medvdv 0:6ac8f630d9a0 274 int lcd128::StringWidth(char* str)
medvdv 0:6ac8f630d9a0 275 {
medvdv 0:6ac8f630d9a0 276 int width = 0;
medvdv 0:6ac8f630d9a0 277
medvdv 0:6ac8f630d9a0 278 while(*str) width += CharacterWidth(*str++);
medvdv 0:6ac8f630d9a0 279
medvdv 0:6ac8f630d9a0 280 return width;
medvdv 0:6ac8f630d9a0 281 }
medvdv 0:6ac8f630d9a0 282
medvdv 0:6ac8f630d9a0 283 // Clear one line,
medvdv 6:5cd32671a837 284 // then write string from it's begin.
medvdv 6:5cd32671a837 285 // It can be inverted and aligned left, center and right
medvdv 4:1bd241d1fad0 286
medvdv 6:5cd32671a837 287 void lcd128::Row(int Y, char* str, bool inverse, int align)
medvdv 0:6ac8f630d9a0 288 {
medvdv 0:6ac8f630d9a0 289 Clear(Y);
medvdv 0:6ac8f630d9a0 290 XY(0, Y);
medvdv 6:5cd32671a837 291 switch(align) {
medvdv 6:5cd32671a837 292 case 1:
medvdv 6:5cd32671a837 293 XY((LCD_X/2)-StringWidth(str)/2,Y);
medvdv 6:5cd32671a837 294 break;
medvdv 6:5cd32671a837 295 case 2:
medvdv 6:5cd32671a837 296 XY(LCD_X-StringWidth(str),Y);
medvdv 6:5cd32671a837 297 break;
medvdv 6:5cd32671a837 298 case 0:
medvdv 6:5cd32671a837 299 default:
medvdv 6:5cd32671a837 300 XY(0, Y);
medvdv 6:5cd32671a837 301 break;
medvdv 6:5cd32671a837 302 }
medvdv 6:5cd32671a837 303
medvdv 0:6ac8f630d9a0 304 String(str);
medvdv 6:5cd32671a837 305 if (inverse) InverseRow(Y);
medvdv 0:6ac8f630d9a0 306 }
medvdv 1:17443d6d2740 307
medvdv 4:1bd241d1fad0 308 // Draw progress bar
medvdv 4:1bd241d1fad0 309 // fill from 0.0f to 1.0f
medvdv 4:1bd241d1fad0 310
medvdv 1:17443d6d2740 311 void lcd128::Bar(int width, float fill)
medvdv 1:17443d6d2740 312 {
medvdv 1:17443d6d2740 313 if (width < 2) return;
medvdv 1:17443d6d2740 314 if (fill < 0.0) fill = 0.0;
medvdv 1:17443d6d2740 315 if (fill > 1.0) fill = 1.0;
medvdv 1:17443d6d2740 316
medvdv 1:17443d6d2740 317 int a = (width - 2)*fill;
medvdv 1:17443d6d2740 318 int b = width - 2 - a;
medvdv 1:17443d6d2740 319
medvdv 1:17443d6d2740 320 Write(LCD_BAR_B);
medvdv 1:17443d6d2740 321 Write(LCD_BAR_F, a);
medvdv 1:17443d6d2740 322 Write(LCD_BAR_U, b);
medvdv 1:17443d6d2740 323 Write(LCD_BAR_E);
medvdv 1:17443d6d2740 324 }