diff --git a/console.c b/console.c new file mode 100644 index 00000000..c206ef5f --- /dev/null +++ b/console.c @@ -0,0 +1,145 @@ +/* + * console.c + * + * Created on: 20 Jun 2012 + * Author: Thomas Saunders AKA "Badger" + */ + +#include "ch.h" + +#include "fonts.h" +#include "glcd.h" +#include "console.h" + +/* + * Interface implementation. The interface is write only + */ + +static size_t writes(void *ip, const uint8_t *bp, size_t n) { + return lcdConsoleWrite((GLCDConsole *)ip, 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) { + return lcdConsolePut((GLCDConsole *)ip, (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)timeout; + /* TODO: handle timeout */ + return lcdConsolePut((GLCDConsole *)ip, (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)time; + return lcdConsoleWrite((GLCDConsole *)ip, 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 GLCDConsoleVMT vmt = { + writes, reads, put, get, + putt, gett, writet, readt, + getflags +}; + + +msg_t lcdConsoleInit(GLCDConsole *console, uint16_t x0, uint16_t y0, uint16_t width, uint16_t height, + font_t font, uint16_t bkcolor, uint16_t color) { + const uint8_t* ptr; + uint16_t chi; + uint16_t x,y; + + console->vmt = &vmt; + /* read font, get height */ + console->fy = font[FONT_TABLE_HEIGHT_IDX]; + + /* calculate the size of the console as an integer multiple of characters */ + console->sx = width; + console->sy = (((int16_t)(height/console->fy))-1)*console->fy; + + console->cx = 0; + console->cy = 0; + console->x0 = x0; + console->y0 = y0; + + console->bkcolor = bkcolor; + console->color = color; + + console->font = font; +} + +msg_t lcdConsolePut(GLCDConsole *console, char c) { + uint8_t width; + + if(c == '\n') { + /* clear the text at the end of the line */ + if(console->cx < console->sx) + lcdDrawRect(console->cx, console->cy, console->sx, console->cy + console->fy, + 1, console->bkcolor); + console->cx = 0; + console->cy += console->fy; + } else if(c == '\r') { + /* TODO: work backwards through the buffer to the start of the current line */ + //console->cx = 0; + } else { + width = lcdMeasureChar(c, console->font); + if((console->cx + width) >= console->sx) { + console->cx = 0; + console->cy += console->fy; + } + + if((console->cy > console->sy)) { + + lcdVerticalScroll(console->x0, console->y0, console->x0 + console->sx, + console->y0 + console->sy + console->fy, console->fy); + /* reset the cursor */ + console->cx = 0; + console->cy = console->sy; + } + + lcdDrawChar(console->x0 + console->cx, console->y0 + console->cy, c, + console->font, console->color, console->bkcolor, solid); + + /* update cursor */ + console->cx += width; + } + +} + +msg_t lcdConsoleWrite(GLCDConsole *console, uint8_t *bp, size_t n) { + size_t i; + for(i = 0; i < n; i++) + lcdConsolePut(console, bp[i]); + + return RDY_OK; +} + + diff --git a/console.h b/console.h new file mode 100644 index 00000000..fcdef293 --- /dev/null +++ b/console.h @@ -0,0 +1,66 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include "glcd.h" + +/** + * @brief Structure representing a GLCD driver. + */ +typedef struct GLCDConsole GLCDConsole; + +/** + * @brief @p GLCDConsole specific methods. + */ +#define _glcd_driver_methods \ + _base_asynchronous_channel_methods + +/** + * @extends BaseAsynchronousChannelVMT + * + * @brief @p GLCDConsole virtual methods table. + */ +struct GLCDConsoleVMT { + _glcd_driver_methods +}; + +/** + * @extends BaseAsynchronousChannel + * + * @brief GLCD Console class. + * @details This class extends @p BaseAsynchronousChannel by adding physical + * I/O queues. + */ +struct GLCDConsole { + /** @brief Virtual Methods Table.*/ + const struct GLCDConsoleVMT *vmt; + _base_asynchronous_channel_data + /* WARNING: Do not add any data to this struct above this comment, only below */ + /* font */ + font_t font; + /* lcd area to use */ + uint16_t x0,y0; + /* current cursor position, in pixels */ + uint16_t cx,cy; + /* console size in pixels */ + uint16_t sx,sy; + /* foreground and background colour */ + uint16_t bkcolor, color; + /* font size in pixels */ + uint8_t fy; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +msg_t lcdConsoleInit(GLCDConsole *console, uint16_t x0, uint16_t y0, uint16_t width, uint16_t height, + font_t font, uint16_t bkcolor, uint16_t color); + +msg_t lcdConsolePut(GLCDConsole *console, char c); +msg_t lcdConsoleWrite(GLCDConsole *console, uint8_t *bp, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* CONSOLE_H */ diff --git a/drivers/lcd/s6d1121_lld.c b/drivers/lcd/s6d1121_lld.c index f7268126..2a591ee2 100644 --- a/drivers/lcd/s6d1121_lld.c +++ b/drivers/lcd/s6d1121_lld.c @@ -2,6 +2,8 @@ #ifdef LCD_USE_S6D1121 +static uint16_t buf[((SCREEN_HEIGHT > SCREEN_WIDTH ) ? SCREEN_HEIGHT : SCREEN_WIDTH)]; + #define LCD_RST_LOW palClearPad(LCD_RST_GPIO, LCD_RST_PIN) #define LCD_RST_HIGH palSetPad(LCD_RST_GPIO, LCD_RST_PIN) @@ -238,6 +240,18 @@ __inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) { } } +__inline void lld_lcdReadStreamStart(void) { + /* TODO */ +} + +__inline void lld_lcdReadStreamStop(void) { + /* TODO */ +} + +__inline void lld_lcdReadStream(uint16_t *buffer, size_t size) { + /* TODO */ +} + void lld_lcdFillArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) { uint32_t index = 0, area; @@ -350,5 +364,35 @@ uint16_t lld_lcdGetWidth(void) { return lcd_width; } +/* a positive lines value shifts the screen up, negative down */ +/* TODO: test this */ +void lld_lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines) { + uint16_t row0, row1; + uint16_t i; + lld_lcdSetWindow(x0, y0, x1, y1); + + for(i = 0; i < ((y1-y0) - abs(lines)); i++) { + if(lines > 0) { + row0 = y0 + i + lines; + row1 = y0 + i; + } else { + row0 = (y1 - i - 1) + lines; + row1 = (y1 - i - 1); + } + + /* read row0 into the buffer and then write at row1*/ + lld_lcdSetWindow(x0, row0, x1, row0); + lld_lcdReadStreamStart(); + lld_lcdReadStream(buf, x1-x0); + lld_lcdReadStreamStop(); + + lld_lcdSetWindow(x0, row1, x1, row1); + lld_lcdWriteStreamStart(); + lld_lcdWriteStream(buf, x1-x0); + lld_lcdWriteStreamStop(); + } +} + + #endif diff --git a/drivers/lcd/s6d1121_lld.h b/drivers/lcd/s6d1121_lld.h index edc6da33..8c4e7057 100644 --- a/drivers/lcd/s6d1121_lld.h +++ b/drivers/lcd/s6d1121_lld.h @@ -2,7 +2,6 @@ #define S6D1121_H #include "glcd.h" -#include "glcdconf.h" #ifdef LCD_USE_S6D1121 @@ -43,6 +42,7 @@ uint16_t lld_lcdGetPixelColor(uint16_t x, uint16_t y); uint16_t lld_lcdGetOrientation(void); uint16_t lld_lcdGetHeight(void); uint16_t lld_lcdGetWidth(void); +void lld_lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines); #ifdef __cplusplus } diff --git a/drivers/lcd/ssd1289_lld.c b/drivers/lcd/ssd1289_lld.c index 6b199df6..5a14d238 100644 --- a/drivers/lcd/ssd1289_lld.c +++ b/drivers/lcd/ssd1289_lld.c @@ -6,6 +6,8 @@ uint8_t orientation; uint16_t DeviceCode; extern uint16_t lcd_width, lcd_height; +static uint16_t buf[((SCREEN_HEIGHT > SCREEN_WIDTH ) ? SCREEN_HEIGHT : SCREEN_WIDTH)]; + #ifdef LCD_USE_GPIO static __inline void lld_lcdWriteIndex(uint16_t index) { @@ -63,7 +65,7 @@ static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) { } __inline void lld_lcdWriteStreamStart(void) { - Clr_CS + Clr_CS; lld_lcdWriteIndex(0x0022); } @@ -84,6 +86,25 @@ __inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) { } } +__inline void lld_lcdReadStreamStart(void) { + Clr_CS + lld_lcdWriteIndex(0x0022); +} + +__inline void lld_lcdReadStreamStop(void) { + Set_CS; +} + +__inline void lld_lcdReadStream(uint16_t *buffer, size_t size) { + uint16_t i; + /* throw away first value read */ + volatile uint16_t dummy = LCD_RAM; + + for(i = 0; i < size; i++) { + buffer[i] = LCD_RAM; + } +} + #endif #ifdef LCD_USE_SPI @@ -114,6 +135,7 @@ static __inline uint16_t lld_lcdReadData(void) { static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) { LCD_REG = lcdReg; + volatile uint16_t dummy = LCD_RAM; return (LCD_RAM); } @@ -130,6 +152,24 @@ __inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) { for(i = 0; i < size; i++) LCD_RAM = buffer[i]; } + +__inline void lld_lcdReadStreamStart(void) { + LCD_REG = 0x0022; +} + +__inline void lld_lcdReadStreamStop(void) { + +} + +__inline void lld_lcdReadStream(uint16_t *buffer, size_t size) { + uint16_t i; + /* throw away first value read */ + volatile uint16_t dummy = LCD_RAM; + + for(i = 0; i < size; i++) { + buffer[i] = LCD_RAM; + } +} #endif static __inline void lld_lcdDelay(uint16_t us) { @@ -158,13 +198,19 @@ void lld_lcdSetPowerMode(uint8_t powerMode) { } void lld_lcdSetCursor(uint16_t x, uint16_t y) { + /* Reg 0x004E is an 8 bit value + * Reg 0x004F is 9 bit + * Use a bit mask to make sure they are not set too high + */ + if(PORTRAIT) { - lld_lcdWriteReg(0x004e, x); - lld_lcdWriteReg(0x004f, y); + lld_lcdWriteReg(0x004e, x & 0x00FF); + lld_lcdWriteReg(0x004f, y & 0x01FF); } else if(LANDSCAPE) { - lld_lcdWriteReg(0x004e, y); - lld_lcdWriteReg(0x004f, x); + lld_lcdWriteReg(0x004e, y & 0x00FF); + lld_lcdWriteReg(0x004f, x & 0x01FF); } + } void lld_lcdSetOrientation(uint8_t newOrientation) { @@ -201,26 +247,35 @@ void lld_lcdSetOrientation(uint8_t newOrientation) { void lld_lcdSetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { lld_lcdSetCursor(x0, y0); + /* Reg 0x44 - Horizontal RAM address position + * Upper Byte - HEA + * Lower Byte - HSA + * 0 <= HSA <= HEA <= 0xEF + * Reg 0x45,0x46 - Vertical RAM address position + * Lower 9 bits gives 0-511 range in each value + * 0 <= Reg(0x45) <= Reg(0x46) <= 0x13F + */ + switch(lcdGetOrientation()) { case portrait: - lld_lcdWriteReg(0x44, ((x1-1) << 8) | x0); - lld_lcdWriteReg(0x45, y0); - lld_lcdWriteReg(0x46, y1-1); + lld_lcdWriteReg(0x44, (((x1-1) << 8) & 0xFF00 ) | (x0 & 0x00FF)); + lld_lcdWriteReg(0x45, y0 & 0x01FF); + lld_lcdWriteReg(0x46, (y1-1) & 0x01FF); break; case landscape: - lld_lcdWriteReg(0x44, ((y1-1) << 8) | y1); - lld_lcdWriteReg(0x45, x0); - lld_lcdWriteReg(0x46, x1-1); + lld_lcdWriteReg(0x44, (((y1-1) << 8) & 0xFF00) | (y1 & 0x00FF)); + lld_lcdWriteReg(0x45, x0 & 0x01FF); + lld_lcdWriteReg(0x46, (x1-1) & 0x01FF); break; case portraitInv: - lld_lcdWriteReg(0x44, ((x1-1) << 8) | x0); - lld_lcdWriteReg(0x45, y0); - lld_lcdWriteReg(0x46, y1-1); + lld_lcdWriteReg(0x44, (((x1-1) << 8) & 0xFF00) | (x0 & 0x00FF)); + lld_lcdWriteReg(0x45, y0 & 0x01FF); + lld_lcdWriteReg(0x46, (y1-1) & 0x01FF); break; case landscapeInv: - lld_lcdWriteReg(0x44, ((y1-1) << 8) | y1); - lld_lcdWriteReg(0x45, x0); - lld_lcdWriteReg(0x46, x1-1); + lld_lcdWriteReg(0x44, (((y1-1) << 8) & 0xFF00) | (y1 & 0x00FF)); + lld_lcdWriteReg(0x45, x0 & 0x01FF); + lld_lcdWriteReg(0x46, (x1-1) & 0x01FF); break; } } @@ -348,5 +403,33 @@ uint16_t lld_lcdGetWidth(void) { return lcd_width; } +/* a positive lines value shifts the screen up, negative down */ +void lld_lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines) { + uint16_t row0, row1; + uint16_t i; + lld_lcdSetWindow(x0, y0, x1, y1); + + for(i = 0; i < ((y1-y0) - abs(lines)); i++) { + if(lines > 0) { + row0 = y0 + i + lines; + row1 = y0 + i; + } else { + row0 = (y1 - i - 1) + lines; + row1 = (y1 - i - 1); + } + + /* read row0 into the buffer and then write at row1*/ + lld_lcdSetWindow(x0, row0, x1, row0); + lld_lcdReadStreamStart(); + lld_lcdReadStream(buf, x1-x0); + lld_lcdReadStreamStop(); + + lld_lcdSetWindow(x0, row1, x1, row1); + lld_lcdWriteStreamStart(); + lld_lcdWriteStream(buf, x1-x0); + lld_lcdWriteStreamStop(); + } +} + #endif diff --git a/drivers/lcd/ssd1289_lld.h b/drivers/lcd/ssd1289_lld.h index 5462acd6..16a9ef0d 100644 --- a/drivers/lcd/ssd1289_lld.h +++ b/drivers/lcd/ssd1289_lld.h @@ -2,7 +2,6 @@ #define SSD1289_H #include "glcd.h" -#include "glcdconf.h" #ifdef LCD_USE_SSD1289 @@ -25,6 +24,7 @@ uint16_t lld_lcdGetPixelColor(uint16_t x, uint16_t y); uint16_t lld_lcdGetOrientation(void); uint16_t lld_lcdGetHeight(void); uint16_t lld_lcdGetWidth(void); +void lld_lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines); #ifdef __cplusplus } diff --git a/drivers/touchpad/ads7843_lld.h b/drivers/touchpad/ads7843_lld.h index 388aacc8..121e6288 100644 --- a/drivers/touchpad/ads7843_lld.h +++ b/drivers/touchpad/ads7843_lld.h @@ -1,7 +1,7 @@ #ifndef ADS7843_LLD_H #define ADS7843_LLD_H -#include "glcdconf.h" +#include "glcd.h" #include "touchpad.h" #ifdef TOUCHPAD_USE_ADS7843 diff --git a/drivers/touchpad/xpt2046_lld.h b/drivers/touchpad/xpt2046_lld.h index ed7a0d09..c3a12077 100644 --- a/drivers/touchpad/xpt2046_lld.h +++ b/drivers/touchpad/xpt2046_lld.h @@ -1,7 +1,7 @@ #ifndef XPT2046_LLD_H #define XPT2046_LLD_H -#include "glcdconf.h" +#include "glcd.h" #include "touchpad.h" #ifdef TOUCHPAD_USE_XPT2046 diff --git a/glcd.c b/glcd.c index 01e166a8..2c6b3bba 100644 --- a/glcd.c +++ b/glcd.c @@ -3,89 +3,15 @@ #include #include -/*===========================================================================*/ -/* 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; + 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; - // No support for nongraphic characters, so just ignore them + /* 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]); + /* 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]); - ptr = font + chi; + /* 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++); - 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; + /* 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; + 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); + } } - /* TODO: proper return codes */ - return RDY_OK; + /* 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 lcdWriteString(const char *str, size_t n) { - size_t l = 0; - for(l = 0; l < n; l++) { - if(lcdDrawChar(*str++) != RDY_OK) - break; +/* 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; } -size_t lcdPutString(const char *str) { - size_t l = 0; - while(*str) { - if(lcdDrawChar(*str++) != RDY_OK) - break; +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; - l++; - } - - 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 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]); + /* 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]); - ptr = font + chi; - - uint8_t fontWidth = *(ptr++); - - 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); +} diff --git a/glcd.h b/glcd.h index 8108b21f..d0597a88 100644 --- a/glcd.h +++ b/glcd.h @@ -4,6 +4,11 @@ #include "ch.h" #include "hal.h" #include "fonts.h" + +#if !defined(LCD_USE_FSMC) && !defined(LCD_USE_GPIO) && !defined(LCD_USE_SPI) +#include "glcdconf.h" +#endif + #include "ssd1289_lld.h" #include "s6d1121_lld.h" @@ -30,87 +35,60 @@ enum filled {frame, filled}; enum transparency {solid, transparent}; enum powermode {powerOff, powerOn, sleepOn, sleepOff}; -// For text rendering only -extern uint16_t bgcolor, fgcolor; -extern uint16_t cx, cy; -extern const uint8_t* font; +typedef const uint8_t* font_t; // A few macros -#define lcdGotoXY(x,y) { cx=x; cy=y; } -#define lcdGetCurFontHeight() (font[FONT_TABLE_HEIGHT_IDX]) +#define lcdGetFontHeight(font) (font[FONT_TABLE_HEIGHT_IDX]) /** * @brief Structure representing a GLCD driver. */ typedef struct GLCDDriver GLCDDriver; -/** - * @brief @p GLCDDriver specific methods. - */ -#define _glcd_driver_methods \ - _base_asynchronous_channel_methods - -/** - * @extends BaseAsynchronousChannelVMT - * - * @brief @p GLCDDriver virtual methods table. - */ -struct GLCDDriverVMT { - _glcd_driver_methods -}; - -/** - * @extends BaseAsynchronousChannel - * - * @brief GLCD driver class. - * @details This class extends @p BaseAsynchronousChannel by adding physical - * I/O queues. - */ struct GLCDDriver { - /** @brief Virtual Methods Table.*/ - const struct GLCDDriverVMT *vmt; - _base_asynchronous_channel_data - /* WARNING: Do not add any data to this struct above this comment, only below */ }; #ifdef __cplusplus extern "C" { #endif - +/* Core functions */ void lcdInit(GLCDDriver *); void lcdClear(uint16_t color); void lcdSetOrientation(uint8_t newOrientation); void lcdSetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void lcdFillArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color); +void lcdWriteArea(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t *buffer, size_t n); void lcdSetPowerMode(uint8_t powerMode); +/* Drawing functions */ void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t point); void lcdDrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color); void lcdDrawRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t filled, uint16_t color); -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); void lcdDrawCircle(uint16_t x, uint16_t y, uint16_t radius, uint8_t filled, uint16_t color); -void lcdSetFontTransparency(uint8_t transparency); -void lcdSetFont(const uint8_t *newFont); -void lcdMoveCursor(uint16_t x, uint16_t y, uint16_t color, uint16_t bkcolor); -msg_t lcdDrawChar(char c); -size_t lcdWriteString(const char *str, size_t n); -size_t lcdPutString(const char *str); -void lcdDrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bkcolor); -void lcdLineBreak(void); +/* Text Rendering Functions */ +int lcdDrawChar(uint16_t cx, uint16_t cy, char c, font_t font, uint16_t color, uint16_t bkcolor, bool_t tpText); +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 lcdMeasureChar(char c); -uint16_t lcdMeasureString(const char* str); +/* Character measuring functions */ +uint16_t lcdMeasureChar(char c, font_t font); +uint16_t lcdMeasureString(const char* str, font_t font); +/* Size and orientation related */ uint16_t lcdGetHeight(void); uint16_t lcdGetWidth(void); uint16_t lcdGetOrientation(void); +/* BGR->RGB and pixel readback */ uint16_t lcdBGR2RGB(uint16_t color); uint16_t lcdGetPixelColor(uint16_t x, uint16_t y); +/* Scrolling function */ +void lcdVerticalScroll(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, int16_t lines); + #ifdef __cplusplus } #endif diff --git a/glcdconf.h b/glcdconf.h deleted file mode 100644 index b6445e93..00000000 --- a/glcdconf.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef GLCDCONF_H -#define GLCDCONF_H - -#define SCREEN_WIDTH 240 -#define SCREEN_HEIGHT 320 - -/***** LCD CONTROLLER *****/ -#define LCD_USE_SSD1289 -// #define LCD_USE_S6D1121 - - -/***** LCD INTERFACE *****/ -#define LCD_USE_GPIO -// #define LCD_USE_SPI -// #define LCD_USE_FSMC - - -/***** TOUCHPAD CONTROLLER *****/ -// #define TOUCHPAD_USE_ADS7843 -#define TOUCHPAD_USE_XPT2046 - - -#endif diff --git a/gui.c b/gui.c index 945606e7..070d9949 100644 --- a/gui.c +++ b/gui.c @@ -135,7 +135,7 @@ uint8_t guiDeleteElement(char *label) { return deleteElement(label); } -uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char *str, uint16_t fontColor, uint16_t buttonColor, uint16_t shadow, char *label, uint8_t *active, uint8_t *state) { +uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char *str, font_t font, uint16_t fontColor, uint16_t buttonColor, uint16_t shadow, char *label, uint8_t *active, uint8_t *state) { struct guiNode_t *newNode; uint16_t i; @@ -156,7 +156,7 @@ uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char * if(addElement(newNode) != 1) return 0; - lcdDrawRectString(x0, y0, x1, y1, str, fontColor, buttonColor); + lcdDrawRectString(x0, y0, x1, y1, str, font, fontColor, buttonColor); if(shadow != 0) { for(i = 0; i < shadow; i++) { diff --git a/gui.h b/gui.h index 513043aa..5b2919f7 100644 --- a/gui.h +++ b/gui.h @@ -46,6 +46,7 @@ Thread *guiInit(uint16_t interval, tprio_t priority); * * return: none */ + void guiPrintElements(BaseSequentialStream *chp); /* @@ -69,7 +70,7 @@ uint8_t guiDeleteElement(char *label); * * return: 1 if button successfully created */ -uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char *str, uint16_t fontColor, uint16_t buttonColor, uint16_t shadow, char *label, uint8_t *active, uint8_t *state); +uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char *str, font_t font, uint16_t fontColor, uint16_t buttonColor, uint16_t shadow, char *label, uint8_t *active, uint8_t *state); uint8_t guiDrawSlider(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t orientation, uint16_t frameColor, uint16_t bkColor, uint16_t valueColor, char *label, uint8_t *active, uint8_t *value); diff --git a/lcd.mk b/lcd.mk index 1c54d5e9..5ba7df1b 100644 --- a/lcd.mk +++ b/lcd.mk @@ -7,6 +7,7 @@ LCDSRC = $(LCDLIB)/glcd.c \ $(LCDLIB)/touchpad.c \ $(LCDLIB)/graph.c \ $(LCDLIB)/gui.c \ + $(LCDLIB)/console.c \ $(LCD_DRIVERS_SRC) LCDINC = $(LCDLIB) \ diff --git a/touchpad.c b/touchpad.c index 3f355ead..4829ed4a 100644 --- a/touchpad.c +++ b/touchpad.c @@ -126,8 +126,8 @@ void tpCalibrate(void) { lcdSetOrientation(portrait); lcdClear(Red); - cx=40; cy=10; - lcdDrawString(40, 10, "Touchpad Calibration", White, Red); + /* Abhishek: need to specify a font to use here, should probably make sure it exists somehow */ + lcdDrawString(40, 10, "Touchpad Calibration", font_Larger, White, Red, solid); for(i=0; i<2; i++) { tpDrawCross(cross[i][0], cross[i][1]);