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