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