00001
00040 #include "lcd_text.h"
00041 #include "lcd_hd44.h"
00042
00043 #include <cfg/macros.h>
00044 #include <cfg/debug.h>
00045
00046 #include <drv/timer.h>
00047
00048 #include <mware/formatwr.h>
00049 #include <struct/list.h>
00050
00051 #include <string.h>
00052
00053
00055 #define LCD_LAYERS 6
00056
00057 #if CONFIG_KERN
00058 #include <kern/sem.h>
00060 static struct Semaphore lcd_semaphore;
00061 #define LOCK_LCD sem_obtain(&lcd_semaphore)
00062 #define UNLOCK_LCD sem_release(&lcd_semaphore)
00063 #else
00064 #define LOCK_LCD do {} while (0)
00065 #define UNLOCK_LCD do {} while (0)
00066 #endif
00067
00068 DECLARE_LIST_TYPE(Layer);
00069
00070 Layer *lcd_DefLayer;
00071 static Layer lcd_LayersPool[LCD_LAYERS];
00072 static LIST_TYPE(Layer) lcd_Layers;
00073 static LIST_TYPE(Layer) lcd_FreeLayers;
00074
00080 static uint8_t lcd_CursorStatus;
00081
00083 static lcdpos_t lcd_CursorAddr;
00084
00085
00086 void lcd_setAddr(Layer *layer, lcdpos_t addr)
00087 {
00088
00089 while (addr >= LCD_ROWS * LCD_COLS)
00090 addr -= LCD_ROWS * LCD_COLS;
00091
00092 layer->addr = addr;
00093 }
00094
00095 #if CONFIG_KERN
00096
00097 void lcd_lock(void)
00098 {
00099 LOCK_LCD;
00100 }
00101
00102
00103 void lcd_unlock(void)
00104 {
00105 UNLOCK_LCD;
00106 }
00107
00108 #endif
00109
00110
00119 static void lcd_putCharUnlocked(char c, Layer *layer)
00120 {
00121 Layer *l2;
00122 lcdpos_t addr = layer->addr;
00123
00124
00125 layer->buf[addr] = c;
00126
00127
00128 if (++layer->addr >= LCD_COLS * LCD_ROWS)
00129 layer->addr = 0;
00130
00131
00132 if (layer->pri == LAYER_HIDDEN)
00133 return;
00134
00135
00136
00137
00138
00139 for (l2 = layer->pred; l2->pred; l2 = l2->pred)
00140 {
00141 if (l2->buf[addr])
00142 {
00143
00144 return;
00145 }
00146 }
00147
00148
00149 if (c)
00150 lcd_putc(addr, c);
00151 else
00152
00153 lcd_putc(addr, ' ');
00154 }
00155
00156
00157 void lcd_putChar(char c, Layer *layer)
00158 {
00159 LOCK_LCD;
00160 lcd_putCharUnlocked(c, layer);
00161 UNLOCK_LCD;
00162 }
00163
00164 void lcd_layerSet(Layer *layer, char c)
00165 {
00166 int i;
00167
00168 LOCK_LCD;
00169 lcd_setAddr(layer, 0);
00170 for (i = 0; i < LCD_COLS * LCD_ROWS; i++)
00171 lcd_putCharUnlocked(c, layer);
00172 UNLOCK_LCD;
00173 }
00174
00175
00176 void lcd_clear(Layer *layer)
00177 {
00178 lcd_layerSet(layer, 0);
00179 }
00180
00181
00182 void lcd_clearLine(Layer *layer, int y)
00183 {
00184 int i;
00185
00186 LOCK_LCD;
00187 lcd_setAddr(layer, LCD_POS(0, y));
00188 for (i = 0; i < LCD_COLS; i++)
00189 lcd_putCharUnlocked(0, layer);
00190 UNLOCK_LCD;
00191 }
00192
00193
00194 void lcd_moveCursor(lcdpos_t addr)
00195 {
00196 LOCK_LCD;
00197 lcd_moveTo(addr);
00198 UNLOCK_LCD;
00199 }
00200
00201
00202 char lcd_setCursor(char mode)
00203 {
00204 static const char cursor_cmd[3] =
00205 {
00206 LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK, LCD_CMD_CURSOR_LINE
00207 };
00208 char oldmode = lcd_CursorStatus;
00209
00210 LOCK_LCD;
00211 lcd_CursorStatus = mode;
00212 lcd_setReg(cursor_cmd[(int)mode]);
00213 if (mode)
00214 lcd_moveCursor(lcd_CursorAddr);
00215 UNLOCK_LCD;
00216
00217 return oldmode;
00218 }
00219
00220
00221 int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap)
00222 {
00223 int len;
00224
00225 LOCK_LCD;
00226
00227
00228
00229
00230
00231
00232 if (lcd_CursorStatus)
00233 lcd_setReg(LCD_CMD_CURSOR_OFF);
00234
00235
00236 lcd_setAddr(layer, addr);
00237
00238 if (mode & LCD_CENTER)
00239 {
00240 int pad;
00241
00242
00243
00244
00245
00246 pad = (LCD_COLS - strlen(format)) / 2;
00247 while (pad--)
00248 lcd_putCharUnlocked(' ', layer);
00249 }
00250
00251 len = _formatted_write(format, (void (*)(char, void *))lcd_putCharUnlocked, layer, ap);
00252
00253 if (mode & (LCD_FILL | LCD_CENTER))
00254 while (layer->addr % LCD_COLS)
00255 lcd_putCharUnlocked(' ', layer);
00256
00257
00258
00259
00260
00261 if (lcd_CursorStatus)
00262 lcd_setCursor(lcd_CursorStatus);
00263
00264 UNLOCK_LCD;
00265
00266 return len;
00267 }
00268
00269
00270 int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...)
00271 {
00272 int len;
00273 va_list ap;
00274
00275 va_start(ap, format);
00276 len = lcd_vprintf(layer, addr, mode, format, ap);
00277 va_end(ap);
00278
00279 return len;
00280 }
00281
00282
00289 static void lcd_enqueueLayer(Layer *layer, char pri)
00290 {
00291 Layer *l2;
00292
00293
00294 REMOVE(layer);
00295
00296 layer->pri = pri;
00297
00298
00299
00300
00301
00302 FOREACH_NODE(l2, &lcd_Layers)
00303 if (l2->pri <= pri)
00304 break;
00305
00306
00307 INSERT_BEFORE(layer, l2);
00308 }
00309
00310 Layer *lcd_newLayer(char pri)
00311 {
00312 Layer *layer;
00313
00314 LOCK_LCD;
00315
00316 if (LIST_EMPTY(&lcd_FreeLayers))
00317 {
00318 UNLOCK_LCD;
00319
00320 return NULL;
00321 }
00322
00323 layer = (Layer *)LIST_HEAD(&lcd_FreeLayers);
00324 layer->addr = 0;
00325 memset(layer->buf, 0, LCD_ROWS * LCD_COLS);
00326
00327 lcd_enqueueLayer(layer, pri);
00328
00329 UNLOCK_LCD;
00330 return layer;
00331 }
00332
00338 static void lcd_refresh(void)
00339 {
00340 lcdpos_t addr;
00341 Layer *l;
00342
00343 for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr)
00344 {
00345 FOREACH_NODE(l, &lcd_Layers)
00346 {
00347
00348 if (l->pri == LAYER_HIDDEN)
00349 break;
00350
00351 if (l->buf[addr])
00352 {
00353
00354 lcd_putc(addr, l->buf[addr]);
00355 goto done;
00356 }
00357 }
00358
00359
00360 lcd_putc(addr, ' ');
00361 done:
00362 ;
00363 }
00364 }
00365
00371 void lcd_setLayerDepth(Layer *layer, char pri)
00372 {
00373 if (pri != layer->pri)
00374 {
00375 LOCK_LCD;
00376 lcd_enqueueLayer(layer, pri);
00377
00378 lcd_refresh();
00379 UNLOCK_LCD;
00380 }
00381 }
00382
00383 void lcd_deleteLayer(Layer *layer)
00384 {
00385 LOCK_LCD;
00386
00387
00388 #if 0
00389 Layer *l2;
00390 lcdpos_t addr;
00391
00392
00393 for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr)
00394 {
00395
00396 if (layer->buf[addr])
00397 {
00398
00399 for (l2 = layer->pred; l2->pred; l2 = l2->pred)
00400 if (l2->buf[addr])
00401
00402 goto not_visible;
00403
00404
00405 for (l2 = layer->succ; l2->succ; l2 = l2->succ)
00406 if (l2->buf[addr])
00407 {
00408
00409 lcd_putc(addr, l2->buf[addr]);
00410
00411
00412 break;
00413 }
00414
00415 not_visible:
00416 ;
00417 }
00418 }
00419 #endif
00420
00421
00422 REMOVE(layer);
00423
00424
00425 ADDHEAD(&lcd_FreeLayers, layer);
00426
00427 lcd_refresh();
00428
00429 UNLOCK_LCD;
00430 }
00431
00432
00433 static void lcd_setDefLayer(Layer *layer)
00434 {
00435 lcd_DefLayer = layer;
00436 }
00437
00438 #include <cfg/debug.h>
00439 void lcd_init(void)
00440 {
00441 int i;
00442
00443 LIST_INIT(&lcd_Layers);
00444 LIST_INIT(&lcd_FreeLayers);
00445 for (i = 0; i < LCD_LAYERS; ++i)
00446 ADDHEAD(&lcd_FreeLayers, &lcd_LayersPool[i]);
00447
00448 lcd_setDefLayer(lcd_newLayer(0));
00449
00450 lcd_hw_init();
00451
00452 lcd_setCursor(0);
00453 }
00454
00455