diff options
Diffstat (limited to 'glcd.c')
-rw-r--r-- | glcd.c | 278 |
1 files changed, 99 insertions, 179 deletions
@@ -3,89 +3,15 @@ #include <stdlib.h> #include <math.h> -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/* - * Interface implementation. The interface is write only - */ - -static size_t writes(void *ip, const uint8_t *bp, size_t n) { - (void)ip; - return lcdWriteString(bp, n); -} - -static size_t reads(void *ip, uint8_t *bp, size_t n) { - (void)ip; - (void)bp; - (void)n; - return 0; -} - -static msg_t put(void *ip, uint8_t b) { - (void)ip; - return lcdDrawChar((char)b); -} - -static msg_t get(void *ip) { - (void)ip; - return RDY_OK; -} - -static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - (void)ip; - (void)timeout; - /* TODO: handle timeout */ - return lcdDrawChar((char)b); -} - -static msg_t gett(void *ip, systime_t timeout) { - (void)ip; - (void)timeout; - return RDY_OK; -} - -static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { - (void)ip; - (void)time; - return lcdWriteString(bp, n); -} - -static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { - (void)ip; - (void)bp; - (void)n; - (void)time; - return 0; -} - -static chnflags_t getflags(void *ip) { - _chn_get_and_clear_flags_impl(ip); -} - -static const struct GLCDDriverVMT vmt = { - writes, reads, put, get, - putt, gett, writet, readt, - getflags -}; - uint16_t lcd_width, lcd_height; -uint16_t bgcolor = White, fgcolor = Black; -uint16_t cx = 0, cy = 0; -static uint8_t tpText = 0; -const uint8_t* font; void lcdInit(GLCDDriver *glcdp) { - glcdp->vmt = &vmt; lld_lcdInit(); lcd_width = lcdGetWidth(); lcd_height = lcdGetHeight(); lcdSetOrientation(portrait); - lcdSetFontTransparency(transparent); - lcdSetFont(font_MediumBold); } uint16_t lcdGetHeight(void) { @@ -120,6 +46,14 @@ void lcdFillArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t co lld_lcdFillArea(x0, y0, x1, y1, color); } +void lcdWriteArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t *buffer, size_t n) { + lld_lcdSetWindow(x0, y0, x1, y1); + + lld_lcdWriteStreamStart(); + lld_lcdWriteStream(buffer, n); + lld_lcdWriteStreamStop(); +} + void lcdClear(uint16_t color) { lld_lcdClear(color); } @@ -193,135 +127,118 @@ void lcdDrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t co } } -void lcdSetFont(const uint8_t *newFont) { - font = newFont; -} - -void lcdSetFontTransparency(uint8_t transparency) { - tpText = transparency; -} - -msg_t lcdDrawChar(char c) { +int lcdDrawChar(uint16_t cx, uint16_t cy, char c, font_t font, uint16_t color, uint16_t bkcolor, bool_t tpText) { + /* Working pointer */ const uint8_t* ptr; - uint8_t fontHeight = lcdGetCurFontHeight(); - uint8_t sps = font[FONT_TABLE_PAD_AFTER_CHAR_IDX]; - uint16_t chi; - uint16_t x,y; - - // No support for nongraphic characters, so just ignore them + uint8_t x, y; + + /* Variables to store character details */ + uint8_t charWidth; + uint8_t charHeight = lcdGetFontHeight(font); + uint8_t padAfterChar = font[FONT_TABLE_PAD_AFTER_CHAR_IDX]; + + /* Local var to hold offset in font table */ + uint16_t charStartOffset; + + /* Working buffer for fast non-transparent text rendering [patch by Badger] */ + static uint16_t buf[20*16]; + + /* No support for nongraphic characters, so just ignore them */ if(c < 0x20 || c > 0x7F) { - if(c == '\n') - lcdLineBreak(); return RDY_OK; } - chi = *(uint16_t*)(&font[FONT_TABLE_CHAR_LOOKUP_IDX + (c-0x20)*2]); - - ptr = font + chi; - - uint8_t fontWidth = *(ptr++); - - if(cx + fontWidth > lcdGetWidth()) - lcdLineBreak(); - - for(x = 0; x < fontWidth; x++) { - chi = *(uint16_t*)ptr; - for(y = 0; y < fontHeight; y++) { - if(chi & 0x01) - lcdDrawPixel(cx+x, cy+y, fgcolor); - else if(!tpText) - lcdDrawPixel(cx+x, cy+y, bgcolor); - - chi >>= 1; + /* Read the offset of the character data in the font table from the lookup table */ + charStartOffset = *(uint16_t*)(&font[FONT_TABLE_CHAR_LOOKUP_IDX + (c - 0x20) * 2]); + + /* After we're done, position the pointer at the offset. + * The first byte that is immediately read will be the font width + * After that, actual 16-bit font data follows, first column down */ + ptr = font + charStartOffset; + charWidth = *(ptr++); + + /* Loop through the data and display. The font data is LSB first, down the column */ + for(x = 0; x < charWidth; x++) { + /* Get the font bitmap data for the column */ + uint16_t charData = *(uint16_t*)ptr; + + for(y = 0; y < charHeight; y++) { + /* Draw the LSB on the screen accordingly. */ + if(!tpText) { + /* Store data into working buffer (patch by Badger), + * Then write it all onto the LCD in one stroke */ + buf[y*charWidth + x] = (charData & 0x01) ? color : bkcolor; + } else { + /* Just draw the needed pixels onto the LCD */ + if (charData & 0x01) + lcdDrawPixel(cx+x, cy+y, color); + } + + /* Shift the data down by one bit */ + charData >>= 1; } + + /* Increment pointer by 2 bytes to the next column */ ptr += 2; } - cx += fontWidth; - if(sps != 0) { - if(!tpText) - lcdFillArea(cx, cy, cx+sps, cy+fontHeight, bgcolor); - cx += sps; - } - - /* TODO: proper return codes */ - return RDY_OK; -} - -size_t lcdWriteString(const char *str, size_t n) { - size_t l = 0; - for(l = 0; l < n; l++) { - if(lcdDrawChar(*str++) != RDY_OK) - break; + if(!tpText) { + /* [Patch by Badger] Write all in one stroke */ + lcdWriteArea(cx, cy, cx+charWidth, cy+charHeight, buf, charWidth*charHeight); + + /* Do padding after character, if needed for solid text rendering + * TODO: To be optimised */ + if (padAfterChar != 0) { + lcdFillArea(cx+charWidth, cy+charHeight, cx+charWidth+padAfterChar, cy+charHeight, bkcolor); + } } - return l; + /* Return the width of the character, we need it so that lcdDrawString may work + * We don't have a static address counter */ + return charWidth + padAfterChar; } -size_t lcdPutString(const char *str) { - size_t l = 0; - while(*str) { - if(lcdDrawChar(*str++) != RDY_OK) - break; - - l++; +/* WARNING: No boundary checks! Unpredictable behaviour if text exceeds boundary */ +void lcdDrawString(uint16_t x, uint16_t y, const char *str, font_t font, uint16_t color, uint16_t bkcolor, bool_t tpText) { + uint16_t cx=x, cy=y; + + while (*str) { + cx += lcdDrawChar(cx, cy, *str++, font, color, bkcolor, tpText); } - - return l; -} - -void lcdMoveCursor(uint16_t x, uint16_t y, uint16_t color, uint16_t bkcolor) { - cx = x; - cy = y; - bgcolor = bkcolor; - fgcolor = color; -} - -void lcdDrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bkcolor) { - uint16_t _bg = bgcolor, _fg = fgcolor; - cx = x; - cy = y; - bgcolor = bkcolor; - fgcolor = color; - lcdPutString(str); - bgcolor = _bg; - fgcolor = _fg; } -uint16_t lcdMeasureChar(char c) { - const uint8_t *ptr; - - // First get spaces after each character, usually 0 but can change - uint8_t sps = font[FONT_TABLE_PAD_AFTER_CHAR_IDX]; +uint16_t lcdMeasureChar(char c, font_t font) { + /* Variables to store character details */ + uint8_t charWidth; + uint8_t padAfterChar = font[FONT_TABLE_PAD_AFTER_CHAR_IDX]; + + /* Local var to hold offset in font table */ + uint16_t charStartOffset; - uint16_t chi; - - if(c < 0x20 || c > 0x7F) + /* No support for nongraphic characters, so just ignore them */ + if(c < 0x20 || c > 0x7F) { return 0; + } - chi = *(uint16_t*)(&font[FONT_TABLE_CHAR_LOOKUP_IDX + (c-0x20)*2]); - - ptr = font + chi; - - uint8_t fontWidth = *(ptr++); + /* Read the offset of the character data in the font table from the lookup table */ + charStartOffset = *(uint16_t*)(&font[FONT_TABLE_CHAR_LOOKUP_IDX + (c - 0x20) * 2]); - return fontWidth + sps; + /* Retrurn the byte at the offset, that's our charWidth */ + charWidth = *(font + charStartOffset); + + return charWidth+padAfterChar; } -uint16_t lcdMeasureString(const char *str) { +uint16_t lcdMeasureString(const char *str, font_t font) { uint16_t result = 0; - while (*str)result += lcdMeasureChar(*str++); + /* Measure each char width, add it, return the result */ + while (*str) + result += lcdMeasureChar(*str++, font); return result; } -void lcdLineBreak() { - // x=0 seems too much on the edge. So I keep it at 3 - cx = 3; - cy += lcdGetCurFontHeight(); -} - uint16_t lcdBGR2RGB(uint16_t color) { uint16_t r, g, b, rgb; @@ -360,15 +277,15 @@ void lcdDrawRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t fil } } -void lcdDrawRectString(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, const char *str, uint16_t fontColor, uint16_t bkColor) { +void lcdDrawRectString(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, const char* str, font_t font, uint16_t fontColor, uint16_t bkColor) { uint16_t off_left, off_up; - off_left = ((x1-x0)-lcdMeasureString(str))/2; + off_left = ((x1-x0)-lcdMeasureString(str, font))/2; off_up = ((y1-y0) - lcdGetCurFontHeight()) / 2; lcdDrawRect(x0, y0, x1, y1, 1, bkColor); - - lcdDrawString(x0+off_left, y0+off_up, str, fontColor, bkColor); + /* Abhishek: default to solid text for this? */ + lcdDrawString(x0+off_left, y0+off_up, str, font, fontColor, bkColor, solid); } void lcdDrawCircle(uint16_t x, uint16_t y, uint16_t radius, uint8_t filled, uint16_t color) { @@ -401,3 +318,6 @@ void lcdDrawCircle(uint16_t x, uint16_t y, uint16_t radius, uint8_t filled, uint } while(a <= b); } +void lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines) { + lld_lcdVerticalScroll(x0,y0,x1,y1,lines); +} |