X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=drv%2Flcd_text.c;fp=drv%2Flcd_text.c;h=0000000000000000000000000000000000000000;hb=791e167e053bdd9250d34a9a5ccae6ccde4d6679;hp=8e519280fa570055b25f2b6a93bbb076535bfe20;hpb=faf2f6bfd5933ff75e6cc01e3d48f9277f731d8f;p=bertos.git diff --git a/drv/lcd_text.c b/drv/lcd_text.c deleted file mode 100644 index 8e519280..00000000 --- a/drv/lcd_text.c +++ /dev/null @@ -1,499 +0,0 @@ -/** - * \file - * - * - * \brief Generic text LCD driver (impl.). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/09/20 20:02:43 marco - *#* Replaced ISLISTEMPTY with LIST_EMPTY - *#* - *#* Revision 1.3 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.2 2006/02/24 00:27:14 bernie - *#* Use new naming convention for list macros. - *#* - *#* Revision 1.1 2005/11/04 18:00:42 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.11 2005/06/14 14:43:43 bernie - *#* Add DevLib headers. - *#* - *#* Revision 1.10 2005/06/06 17:41:57 batt - *#* Add lcd_layerSet function. - *#* - *#* Revision 1.9 2005/06/01 16:40:07 batt - *#* Remove debug string. - *#* - *#* Revision 1.8 2005/06/01 16:38:04 batt - *#* Adapt to changes in mware/list.h. - *#* - *#* Revision 1.7 2005/06/01 10:45:22 batt - *#* lcd_setAddr(): Bugfix boundary condition; Misc cleanup. - *#* - *#* Revision 1.6 2005/06/01 10:36:23 batt - *#* Layer: Rename member variables and Doxygenize. - *#* - *#* Revision 1.5 2005/05/27 11:05:58 batt - *#* Do not write on lcd if layer is hidden. - *#*/ - -#include "lcd_text.h" -#include "lcd_hd44.h" -#include // timer_delay() -#include // _formatted_write() -#include // LIST_EMPTY() -#include // BV() -#include - -#include // strlen() - - -/** Maximum number of layers. */ -#define LCD_LAYERS 6 - -#if CONFIG_KERNEL - /** Semaphore to arbitrate access to the display. */ - static struct Semaphore lcd_semaphore; - #define LOCK_LCD sem_obtain(&lcd_semaphore) - #define UNLOCK_LCD sem_release(&lcd_semaphore) -#else /* !CONFIG_KERNEL */ - #define LOCK_LCD do {} while (0) - #define UNLOCK_LCD do {} while (0) -#endif /* !CONFIG_KERNEL */ - -DECLARE_LIST_TYPE(Layer); - -Layer *lcd_DefLayer; -static Layer lcd_LayersPool[LCD_LAYERS]; -static LIST_TYPE(Layer) lcd_Layers; -static LIST_TYPE(Layer) lcd_FreeLayers; - -/** - * Current cursor status. - * - * One of LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK or LCD_CMD_CURSOR_LINE. - */ -static uint8_t lcd_CursorStatus; - -/** Current cursor position, encoded as a Cursor position and status. */ -static lcdpos_t lcd_CursorAddr; - - -void lcd_setAddr(Layer *layer, lcdpos_t addr) -{ - /* Sanity check: wrap around to display limits */ - while (addr >= LCD_ROWS * LCD_COLS) - addr -= LCD_ROWS * LCD_COLS; - - layer->addr = addr; -} - -#if CONFIG_KERNEL - -void lcd_lock(void) -{ - LOCK_LCD; -} - - -void lcd_unlock(void) -{ - UNLOCK_LCD; -} - -#endif /* CONFIG_KERNEL */ - - -/** - * Write one character to the display at the current - * cursor prosition, then move the cursor right. The - * cursor is wrapped to the next line when it moves - * beyond the end of the current line. - * - * \note Does _NOT_ lock the display semaphore. - */ -static void lcd_putCharUnlocked(char c, Layer *layer) -{ - Layer *l2; - lcdpos_t addr = layer->addr; - - /* Store character in layer buffer */ - layer->buf[addr] = c; - - /* Move to next character */ - if (++layer->addr >= LCD_COLS * LCD_ROWS) - layer->addr = 0; - - /* Do not write on LCD if layer is hidden. */ - if (layer->pri == LAYER_HIDDEN) - return; - - /* - * Check if this location is obscured by - * other layers above us. - */ - for (l2 = layer->pred; l2->pred; l2 = l2->pred) - { - if (l2->buf[addr]) - { - /* DB(kprintf("layer %04x obs %04x at %d\n", l2, layer, addr);) */ - return; - } - } - - /* Write character */ - if (c) - lcd_putc(addr, c); - else - /* FIXME: should look for layers beneath! */ - lcd_putc(addr, ' '); -} - - -void lcd_putChar(char c, Layer *layer) -{ - LOCK_LCD; - lcd_putCharUnlocked(c, layer); - UNLOCK_LCD; -} - -void lcd_layerSet(Layer *layer, char c) -{ - int i; - - LOCK_LCD; - lcd_setAddr(layer, 0); - for (i = 0; i < LCD_COLS * LCD_ROWS; i++) - lcd_putCharUnlocked(c, layer); - UNLOCK_LCD; -} - - -void lcd_clear(Layer *layer) -{ - lcd_layerSet(layer, 0); -} - - -void lcd_clearLine(Layer *layer, int y) -{ - int i; - - LOCK_LCD; - lcd_setAddr(layer, LCD_POS(0, y)); - for (i = 0; i < LCD_COLS; i++) - lcd_putCharUnlocked(0, layer); - UNLOCK_LCD; -} - - -void lcd_moveCursor(lcdpos_t addr) -{ - LOCK_LCD; - lcd_moveTo(addr); - UNLOCK_LCD; -} - - -char lcd_setCursor(char mode) -{ - static const char cursor_cmd[3] = - { - LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK, LCD_CMD_CURSOR_LINE - }; - char oldmode = lcd_CursorStatus; - - LOCK_LCD; - lcd_CursorStatus = mode; - lcd_setReg(cursor_cmd[(int)mode]); - if (mode) - lcd_moveCursor(lcd_CursorAddr); - UNLOCK_LCD; - - return oldmode; -} - - -int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap) -{ - int len; - - LOCK_LCD; - - /* - * Se il cursore era acceso, spegnilo durante - * l'output per evitare che salti alla posizione - * in cui si scrive. - */ - if (lcd_CursorStatus) - lcd_setReg(LCD_CMD_CURSOR_OFF); - - /* Spostamento del cursore */ - lcd_setAddr(layer, addr); - - if (mode & LCD_CENTER) - { - int pad; - - /* - * NOTE: calculating the string lenght BEFORE it gets - * printf()-formatted. Real lenght may differ. - */ - pad = (LCD_COLS - strlen(format)) / 2; - while (pad--) - lcd_putCharUnlocked(' ', layer); - } - - len = _formatted_write(format, (void (*)(char, void *))lcd_putCharUnlocked, layer, ap); - - if (mode & (LCD_FILL | LCD_CENTER)) - while (layer->addr % LCD_COLS) - lcd_putCharUnlocked(' ', layer); - - /* - * Riaccendi il cursore e riportalo alla - * vecchia posizione - */ - if (lcd_CursorStatus) - lcd_setCursor(lcd_CursorStatus); - - UNLOCK_LCD; - - return len; -} - - -int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...) -{ - int len; - va_list ap; - - va_start(ap, format); - len = lcd_vprintf(layer, addr, mode, format, ap); - va_end(ap); - - return len; -} - - -/** - * Internal function to move a layer between two positions. - * - * \note The layer must be *already* enqueued in some list. - * \note The display must be already locked! - */ -static void lcd_enqueueLayer(Layer *layer, char pri) -{ - Layer *l2; - - /* Remove layer from whatever list it was in before */ - REMOVE(layer); - - layer->pri = pri; - - /* - * Search for the first layer whose priority - * is less or equal to the layer we are adding. - */ - FOREACH_NODE(l2, &lcd_Layers) - if (l2->pri <= pri) - break; - - /* Enqueue layer */ - INSERT_BEFORE(layer, l2); -} - -Layer *lcd_newLayer(char pri) -{ - Layer *layer; - - LOCK_LCD; - - if (LIST_EMPTY(&lcd_FreeLayers)) - { - UNLOCK_LCD; - //ASSERT(false); - return NULL; - } - - layer = (Layer *)LIST_HEAD(&lcd_FreeLayers); - layer->addr = 0; - memset(layer->buf, 0, LCD_ROWS * LCD_COLS); - - lcd_enqueueLayer(layer, pri); - - UNLOCK_LCD; - return layer; -} - -/** - * Redraw the display (internal). - * - * \note The display must be already locked. - */ -static void lcd_refresh(void) -{ - lcdpos_t addr; - Layer *l; - - for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) - { - FOREACH_NODE(l, &lcd_Layers) - { - //kprintf("%d %x %p\n", addr, l->buf[0], l); - if (l->pri == LAYER_HIDDEN) - break; - - if (l->buf[addr]) - { - /* Refresh location */ - lcd_putc(addr, l->buf[addr]); - goto done; - } - } - - /* Draw background */ - lcd_putc(addr, ' '); - done: - ; - } -} - -/** - * Rearrange layer depth and refresh display accordingly. - * - * \note Setting a priority of LAYER_HIDDEN makes the layer invisible. - */ -void lcd_setLayerDepth(Layer *layer, char pri) -{ - if (pri != layer->pri) - { - LOCK_LCD; - lcd_enqueueLayer(layer, pri); - /* Vile but simple */ - lcd_refresh(); - UNLOCK_LCD; - } -} - -void lcd_deleteLayer(Layer *layer) -{ - LOCK_LCD; - -/* We use lcd_refresh() instead. Much simpler than this mess, but slower. */ -#if 0 - Layer *l2; - lcdpos_t addr; - - /* Repair damage on underlaying layers */ - for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) - { - /* If location was covered by us */ - if (layer->buf[addr]) - { - /* ...and it wasn't covered by others above us... */ - for (l2 = layer->pred; l2->pred; l2 = l2->pred) - if (l2->buf[addr]) - /* can't just break here! */ - goto not_visible; - - /* ...scan underlaying layers to repair damage */ - for (l2 = layer->succ; l2->succ; l2 = l2->succ) - if (l2->buf[addr]) - { - /* Refresh character */ - lcd_putc(addr, l2->buf[addr]); - - /* No need to search on deeper layers */ - break; - } - - not_visible: - ; - } - } -#endif - - // Remove layer from lcd_Layers list. - REMOVE(layer); - - /* Put layer back into free list */ - ADDHEAD(&lcd_FreeLayers, layer); - - lcd_refresh(); - - UNLOCK_LCD; -} - - -static void lcd_setDefLayer(Layer *layer) -{ - lcd_DefLayer = layer; -} - -#include -void lcd_init(void) -{ - int i; - - LIST_INIT(&lcd_Layers); - LIST_INIT(&lcd_FreeLayers); - for (i = 0; i < LCD_LAYERS; ++i) - ADDHEAD(&lcd_FreeLayers, &lcd_LayersPool[i]); - - lcd_setDefLayer(lcd_newLayer(0)); - - lcd_hw_init(); - - lcd_setCursor(0); -} - -#if CONFIG_TEST -void lcd_test(void) -{ - int i; - - for (i = 0; i < LCD_ROWS * LCD_COLS; ++i) - { - lcd_putCharUnlocked('0' + (i % 10), lcd_DefLayer); - timer_delay(100); - } -} -#endif /* CONFIG_TEST */ -