diff --git a/docs/contributors.txt b/docs/contributors.txt index 654e1540..d429e7d2 100644 --- a/docs/contributors.txt +++ b/docs/contributors.txt @@ -1,27 +1,27 @@ -This file is a complete history of persons who contributed to the GLCD Library. - -At this point we want to thank all of these people for their work. - - -NickName RealName Contribution -======== ======== ============ - -Mobyfab Fabien Poussin SSD1289 driver - -inmarket Andrew Hannam GDISP (restructorizing the entire library) - VMT - ASYNC and MULTITHREAD implementation - -Badger Thomas Saunders console implementation - FSMC for STM32F1 and F4 - lld orientation fixed for S6F1121 and SSD1289 - -Abhishek Abhishek Kumar S6D1121 GPIO - font rendering - touchpad noise filtering & optimizations - -benwilliam - lcdDrawEllipse() - fastMath - -dxli Dongxu Li lcdDrawEllipse() filled option - +This file is a complete history of persons who contributed to the GLCD Library. + +At this point we want to thank all of these people for their work. + + +NickName RealName Contribution +======== ======== ============ + +Mobyfab Fabien Poussin SSD1963 driver + +inmarket Andrew Hannam GDISP (restructorizing the entire library) + VMT + ASYNC and MULTITHREAD implementation + +Badger Thomas Saunders console implementation + FSMC for STM32F1 and F4 + lld orientation fixed for S6F1121 and SSD1289 + +Abhishek Abhishek Kumar S6D1121 GPIO + font rendering + touchpad noise filtering & optimizations + +benwilliam - lcdDrawEllipse() + fastMath + +dxli Dongxu Li lcdDrawEllipse() filled option + diff --git a/docs/releases.txt b/docs/releases.txt index 47073038..7f939e05 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -1,9 +1,11 @@ -***************************************************************************** -*** Releases *** -***************************************************************************** - -*** 0.1.0 *** -FIX: removed gdisp and touchpad prefix of driver directories -UPDATE: added SSD1289 driver (by Mobyfab) - - +***************************************************************************** +*** Releases *** +***************************************************************************** + +*** 0.1.0 *** +FIX: removed gdisp and touchpad prefix of driver directories +UPDATE: added SSD1963 driver (by Mobyfab) +UPDATE: fixed Validation, VMT driver, console and BitBlit +UPDATE: added clipping support + + diff --git a/drivers/gdisp/Nokia6610/gdisp_lld.c b/drivers/gdisp/Nokia6610/gdisp_lld.c index 5ebe2177..b1740609 100644 --- a/drivers/gdisp/Nokia6610/gdisp_lld.c +++ b/drivers/gdisp/Nokia6610/gdisp_lld.c @@ -60,8 +60,6 @@ /* Driver local functions. */ /*===========================================================================*/ -#include "gdisp_fonts.h" - #if defined(BOARD_OLIMEX_SAM7_EX256) #include "gdisp_lld_board_olimexsam7ex256.h" #else @@ -69,16 +67,13 @@ #include "gdisp_lld_board.h" #endif -#define gdisp_lld_write_command(cmd) GDISP_LLD(write_spi)((cmd) & ~0x0100) -#define gdisp_lld_write_data(data) GDISP_LLD(write_spi)((data) | 0x0100) - static __inline void gdisp_lld_setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) { - gdisp_lld_write_command(CASET); // Column address set - gdisp_lld_write_data(x); - gdisp_lld_write_data(x+cx-1); - gdisp_lld_write_command(PASET); // Page address set - gdisp_lld_write_data(y); - gdisp_lld_write_data(y+cy-1); + GDISP_LLD(write_cmd)(CASET); // Column address set + GDISP_LLD(write_data)(x); + GDISP_LLD(write_data)(x+cx-1); + GDISP_LLD(write_cmd)(PASET); // Page address set + GDISP_LLD(write_data)(y); + GDISP_LLD(write_data)(y+cy-1); } /*===========================================================================*/ @@ -112,141 +107,141 @@ bool_t GDISP_LLD(init)(void) { #if defined(LCD_USE_GE8) #if 1 - gdisp_lld_write_command(DISCTL); // Display control - gdisp_lld_write_data(0x00); // P1: 0x00 = 2 divisions, switching period=8 (default) - gdisp_lld_write_data(0x20); // P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32) - gdisp_lld_write_data(0x00); // P3: 0x00 = no inversely highlighted lines - gdisp_lld_write_command(COMSCN); // COM scan - gdisp_lld_write_data(1); // P1: 0x01 = Scan 1->80, 160<-81 - gdisp_lld_write_command(OSCON); // Internal oscilator ON - gdisp_lld_write_command(SLPOUT); // Sleep out - gdisp_lld_write_command(PWRCTR); // Power control - gdisp_lld_write_data(0x0f); // reference voltage regulator on, circuit voltage follower on, BOOST ON + GDISP_LLD(write_cmd)(DISCTL); // Display control + GDISP_LLD(write_data)(0x00); // P1: 0x00 = 2 divisions, switching period=8 (default) + GDISP_LLD(write_data)(0x20); // P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32) + GDISP_LLD(write_data)(0x00); // P3: 0x00 = no inversely highlighted lines + GDISP_LLD(write_cmd)(COMSCN); // COM scan + GDISP_LLD(write_data)(1); // P1: 0x01 = Scan 1->80, 160<-81 + GDISP_LLD(write_cmd)(OSCON); // Internal oscilator ON + GDISP_LLD(write_cmd)(SLPOUT); // Sleep out + GDISP_LLD(write_cmd)(PWRCTR); // Power control + GDISP_LLD(write_data)(0x0f); // reference voltage regulator on, circuit voltage follower on, BOOST ON // Interesting - all the code seems to say this should be done. But my display doesn't want it! - //gdisp_lld_write_command(DISINV); // Inverse display - gdisp_lld_write_command(DATCTL); // Data control - gdisp_lld_write_data(0x01); // P1: 0x01 = page address inverted, column address normal, address scan in column direction - gdisp_lld_write_data(0x00); // P2: 0x00 = RGB sequence (default value) - gdisp_lld_write_data(0x02); // P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A) - gdisp_lld_write_command(VOLCTR); // Voltage control (contrast setting) - gdisp_lld_write_data(32); // P1 = 32 volume value (experiment with this value to get the best contrast) - gdisp_lld_write_data(3); // P2 = 3 resistance ratio (only value that works) + //GDISP_LLD(write_cmd)(DISINV); // Inverse display + GDISP_LLD(write_cmd)(DATCTL); // Data control + GDISP_LLD(write_data)(0x48/*0x01*/); // P1: 0x01 = page address inverted, column address normal, address scan in column direction + GDISP_LLD(write_data)(0x00); // P2: 0x00 = RGB sequence (default value) + GDISP_LLD(write_data)(0x02); // P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A) + GDISP_LLD(write_cmd)(VOLCTR); // Voltage control (contrast setting) + GDISP_LLD(write_data)(32); // P1 = 32 volume value (experiment with this value to get the best contrast) + GDISP_LLD(write_data)(3); // P2 = 3 resistance ratio (only value that works) chThdSleepMilliseconds(100); // allow power supply to stabilize - gdisp_lld_write_command(DISON); // Turn on the display + GDISP_LLD(write_cmd)(DISON); // Turn on the display #else // Alternative - gdisp_lld_write_command(DISCTL); // Display control - gdisp_lld_write_data(0x00); // default - gdisp_lld_write_data(0x20); // (32 + 1) * 4 = 132 lines (of which 130 are visible) - gdisp_lld_write_data(0x0a); // default - gdisp_lld_write_command(COMSCN); // COM scan - gdisp_lld_write_data(0x00); // Scan 1-80 - gdisp_lld_write_command(OSCON); // Internal oscilator ON + GDISP_LLD(write_cmd)(DISCTL); // Display control + GDISP_LLD(write_data)(0x00); // default + GDISP_LLD(write_data)(0x20); // (32 + 1) * 4 = 132 lines (of which 130 are visible) + GDISP_LLD(write_data)(0x0a); // default + GDISP_LLD(write_cmd)(COMSCN); // COM scan + GDISP_LLD(write_data)(0x00); // Scan 1-80 + GDISP_LLD(write_cmd)(OSCON); // Internal oscilator ON chThdSleepMilliseconds(100); // wait aproximetly 100ms - gdisp_lld_write_command(SLPOUT); // Sleep out - gdisp_lld_write_command(VOLCTR); // Voltage control - gdisp_lld_write_data(0x1F); // middle value of V1 - gdisp_lld_write_data(0x03); // middle value of resistance value - gdisp_lld_write_command(TMPGRD); // Temperature gradient - gdisp_lld_write_data(0x00); // default - gdisp_lld_write_command(PWRCTR); // Power control - gdisp_lld_write_data(0x0f); // referance voltage regulator on, circuit voltage follower on, BOOST ON - gdisp_lld_write_command(DISNOR); // Normal display - gdisp_lld_write_command(DISINV); // Inverse display - gdisp_lld_write_command(PTLOUT); // Partial area off - // gdisp_lld_write_command(ASCSET); // Scroll area set - // gdisp_lld_write_data(0); - // gdisp_lld_write_data(0); - // gdisp_lld_write_data(40); - // gdisp_lld_write_data(3); - // gdisp_lld_write_command(SCSTART); // Vertical scrool address start - // gdisp_lld_write_data(0); - gdisp_lld_write_command(DATCTL); // Data control - gdisp_lld_write_data(0x00); // all inversions off, column direction - gdisp_lld_write_data(0x03); // RGB sequence - gdisp_lld_write_data(0x02); // Grayscale -> 16 - gdisp_lld_write_command(PASET); // Page Address set - gdisp_lld_write_data(0); - gdisp_lld_write_data(131); - gdisp_lld_write_command(CASET); // Page Column set - gdisp_lld_write_data(0); - gdisp_lld_write_data(131); - gdisp_lld_write_command(DISON); // Turn on the display + GDISP_LLD(write_cmd)(SLPOUT); // Sleep out + GDISP_LLD(write_cmd)(VOLCTR); // Voltage control + GDISP_LLD(write_data)(0x1F); // middle value of V1 + GDISP_LLD(write_data)(0x03); // middle value of resistance value + GDISP_LLD(write_cmd)(TMPGRD); // Temperature gradient + GDISP_LLD(write_data)(0x00); // default + GDISP_LLD(write_cmd)(PWRCTR); // Power control + GDISP_LLD(write_data)(0x0f); // referance voltage regulator on, circuit voltage follower on, BOOST ON + GDISP_LLD(write_cmd)(DISNOR); // Normal display + GDISP_LLD(write_cmd)(DISINV); // Inverse display + GDISP_LLD(write_cmd)(PTLOUT); // Partial area off + // GDISP_LLD(write_cmd)(ASCSET); // Scroll area set + // GDISP_LLD(write_data)(0); + // GDISP_LLD(write_data)(0); + // GDISP_LLD(write_data)(40); + // GDISP_LLD(write_data)(3); + // GDISP_LLD(write_cmd)(SCSTART); // Vertical scrool address start + // GDISP_LLD(write_data)(0); + GDISP_LLD(write_cmd)(DATCTL); // Data control + GDISP_LLD(write_data)(0x00); // all inversions off, column direction + GDISP_LLD(write_data)(0x03); // RGB sequence + GDISP_LLD(write_data)(0x02); // Grayscale -> 16 + GDISP_LLD(write_cmd)(PASET); // Page Address set + GDISP_LLD(write_data)(0); + GDISP_LLD(write_data)(131); + GDISP_LLD(write_cmd)(CASET); // Page Column set + GDISP_LLD(write_data)(0); + GDISP_LLD(write_data)(131); + GDISP_LLD(write_cmd)(DISON); // Turn on the display #endif #elif defined(LCD_USE_GE12) #if 1 - gdisp_lld_write_command(SLEEPOUT); // Sleep out - gdisp_lld_write_command(INVON); // Inversion on: seems to be required for this controller - gdisp_lld_write_command(COLMOD); // Color Interface Pixel Format - gdisp_lld_write_data(0x03); // 0x03 = 12 bits-per-pixel - gdisp_lld_write_command(MADCTL); // Memory access controler - gdisp_lld_write_data(0xC8); // 0xC0 = mirror x and y, reverse rgb - gdisp_lld_write_command(SETCON); // Write contrast - gdisp_lld_write_data(0x30); // contrast - experiental value + GDISP_LLD(write_cmd)(SLEEPOUT); // Sleep out + GDISP_LLD(write_cmd)(INVON); // Inversion on: seems to be required for this controller + GDISP_LLD(write_cmd)(COLMOD); // Color Interface Pixel Format + GDISP_LLD(write_data)(0x03); // 0x03 = 12 bits-per-pixel + GDISP_LLD(write_cmd)(MADCTL); // Memory access controler + GDISP_LLD(write_data)(0xC8); // 0xC0 = mirror x and y, reverse rgb + GDISP_LLD(write_cmd)(SETCON); // Write contrast + GDISP_LLD(write_data)(0x30); // contrast - experiental value chThdSleepMilliseconds(20); - gdisp_lld_write_command(DISPON); // Display On + GDISP_LLD(write_cmd)(DISPON); // Display On #else // Alternative // Hardware reset commented out - gdisp_lld_write_command(SOFTRST); // Software Reset + GDISP_LLD(write_cmd)(SOFTRST); // Software Reset chThdSleepMilliseconds(20); - gdisp_lld_write_command(INITESC); // Initial escape + GDISP_LLD(write_cmd)(INITESC); // Initial escape chThdSleepMilliseconds(20); - gdisp_lld_write_command(REFSET); // Refresh set - gdisp_lld_write_data(0); - gdisp_lld_write_command(DISPCTRL); // Set Display control - gdisp_lld_write_data(128); // Set the lenght of one selection term - gdisp_lld_write_data(128); // Set N inversion -> no N inversion - gdisp_lld_write_data(134); // Set frame frequence and bias rate -> 2 devision of frequency and 1/8 bias, 1/67 duty, 96x67 size - gdisp_lld_write_data(84); // Set duty parameter - gdisp_lld_write_data(69); // Set duty parameter - gdisp_lld_write_data(82); // Set duty parameter - gdisp_lld_write_data(67); // Set duty parameter - gdisp_lld_write_command(GRAYSCALE0); // Grey scale 0 position set - 15 parameters - gdisp_lld_write_data(1); // GCP1 - gray lavel to be output when the RAM data is "0001" - gdisp_lld_write_data(2); // GCP2 - gray lavel to be output when the RAM data is "0010" - gdisp_lld_write_data(4); // GCP3 - gray lavel to be output when the RAM data is "0011" - gdisp_lld_write_data(8); // GCP4 - gray lavel to be output when the RAM data is "0100" - gdisp_lld_write_data(16); // GCP5 - gray lavel to be output when the RAM data is "0101" - gdisp_lld_write_data(30); // GCP6 - gray lavel to be output when the RAM data is "0110" - gdisp_lld_write_data(40); // GCP7 - gray lavel to be output when the RAM data is "0111" - gdisp_lld_write_data(50); // GCP8 - gray lavel to be output when the RAM data is "1000" - gdisp_lld_write_data(60); // GCP9 - gray lavel to be output when the RAM data is "1001" - gdisp_lld_write_data(70); // GCP10 - gray lavel to be output when the RAM data is "1010" - gdisp_lld_write_data(80); // GCP11 - gray lavel to be output when the RAM data is "1011" - gdisp_lld_write_data(90); // GCP12 - gray lavel to be output when the RAM data is "1100" - gdisp_lld_write_data(100); // GCP13 - gray lavel to be output when the RAM data is "1101" - gdisp_lld_write_data(110); // GCP14 - gray lavel to be output when the RAM data is "1110" - gdisp_lld_write_data(127); // GCP15 - gray lavel to be output when the RAM data is "1111" - gdisp_lld_write_command(GAMMA); // Gamma curve set - select gray scale - GRAYSCALE 0 or GREYSCALE 1 - gdisp_lld_write_data(1); // Select grey scale 0 - gdisp_lld_write_command(COMMONDRV); // Command driver output - gdisp_lld_write_data(0); // Set COM1-COM41 side come first, normal mod - gdisp_lld_write_command(NORMALMODE); // Set Normal mode (my) - // gdisp_lld_write_command(INVERSIONOFF); // Inversion off - gdisp_lld_write_command(COLADDRSET); // Column address set - gdisp_lld_write_data(0); - gdisp_lld_write_data(131); - gdisp_lld_write_command(PAGEADDRSET); // Page address set - gdisp_lld_write_data(0); - gdisp_lld_write_data(131); - gdisp_lld_write_command(ACCESSCTRL); // Memory access controler - gdisp_lld_write_data(0x40); // horizontal - //gdisp_lld_write_data(0x20); // vertical - gdisp_lld_write_command(PWRCTRL); // Power control - gdisp_lld_write_data(4); // Internal resistance, V1OUT -> high power mode, oscilator devision rate - gdisp_lld_write_command(SLEEPOUT); // Sleep out - gdisp_lld_write_command(VOLTCTRL); // Voltage control - voltage control and write contrast define LCD electronic volume - //gdisp_lld_write_data(0x7f); // full voltage control - //gdisp_lld_write_data(0x03); // must be "1" - gdisp_lld_write_command(CONTRAST); // Write contrast - gdisp_lld_write_data(0x3b); // contrast + GDISP_LLD(write_cmd)(REFSET); // Refresh set + GDISP_LLD(write_data)(0); + GDISP_LLD(write_cmd)(DISPCTRL); // Set Display control + GDISP_LLD(write_data)(128); // Set the lenght of one selection term + GDISP_LLD(write_data)(128); // Set N inversion -> no N inversion + GDISP_LLD(write_data)(134); // Set frame frequence and bias rate -> 2 devision of frequency and 1/8 bias, 1/67 duty, 96x67 size + GDISP_LLD(write_data)(84); // Set duty parameter + GDISP_LLD(write_data)(69); // Set duty parameter + GDISP_LLD(write_data)(82); // Set duty parameter + GDISP_LLD(write_data)(67); // Set duty parameter + GDISP_LLD(write_cmd)(GRAYSCALE0); // Grey scale 0 position set - 15 parameters + GDISP_LLD(write_data)(1); // GCP1 - gray lavel to be output when the RAM data is "0001" + GDISP_LLD(write_data)(2); // GCP2 - gray lavel to be output when the RAM data is "0010" + GDISP_LLD(write_data)(4); // GCP3 - gray lavel to be output when the RAM data is "0011" + GDISP_LLD(write_data)(8); // GCP4 - gray lavel to be output when the RAM data is "0100" + GDISP_LLD(write_data)(16); // GCP5 - gray lavel to be output when the RAM data is "0101" + GDISP_LLD(write_data)(30); // GCP6 - gray lavel to be output when the RAM data is "0110" + GDISP_LLD(write_data)(40); // GCP7 - gray lavel to be output when the RAM data is "0111" + GDISP_LLD(write_data)(50); // GCP8 - gray lavel to be output when the RAM data is "1000" + GDISP_LLD(write_data)(60); // GCP9 - gray lavel to be output when the RAM data is "1001" + GDISP_LLD(write_data)(70); // GCP10 - gray lavel to be output when the RAM data is "1010" + GDISP_LLD(write_data)(80); // GCP11 - gray lavel to be output when the RAM data is "1011" + GDISP_LLD(write_data)(90); // GCP12 - gray lavel to be output when the RAM data is "1100" + GDISP_LLD(write_data)(100); // GCP13 - gray lavel to be output when the RAM data is "1101" + GDISP_LLD(write_data)(110); // GCP14 - gray lavel to be output when the RAM data is "1110" + GDISP_LLD(write_data)(127); // GCP15 - gray lavel to be output when the RAM data is "1111" + GDISP_LLD(write_cmd)(GAMMA); // Gamma curve set - select gray scale - GRAYSCALE 0 or GREYSCALE 1 + GDISP_LLD(write_data)(1); // Select grey scale 0 + GDISP_LLD(write_cmd)(COMMONDRV); // Command driver output + GDISP_LLD(write_data)(0); // Set COM1-COM41 side come first, normal mod + GDISP_LLD(write_cmd)(NORMALMODE); // Set Normal mode (my) + // GDISP_LLD(write_cmd)(INVERSIONOFF); // Inversion off + GDISP_LLD(write_cmd)(COLADDRSET); // Column address set + GDISP_LLD(write_data)(0); + GDISP_LLD(write_data)(131); + GDISP_LLD(write_cmd)(PAGEADDRSET); // Page address set + GDISP_LLD(write_data)(0); + GDISP_LLD(write_data)(131); + GDISP_LLD(write_cmd)(ACCESSCTRL); // Memory access controler + GDISP_LLD(write_data)(0x40); // horizontal + //GDISP_LLD(write_data)(0x20); // vertical + GDISP_LLD(write_cmd)(PWRCTRL); // Power control + GDISP_LLD(write_data)(4); // Internal resistance, V1OUT -> high power mode, oscilator devision rate + GDISP_LLD(write_cmd)(SLEEPOUT); // Sleep out + GDISP_LLD(write_cmd)(VOLTCTRL); // Voltage control - voltage control and write contrast define LCD electronic volume + //GDISP_LLD(write_data)(0x7f); // full voltage control + //GDISP_LLD(write_data)(0x03); // must be "1" + GDISP_LLD(write_cmd)(CONTRAST); // Write contrast + GDISP_LLD(write_data)(0x3b); // contrast chThdSleepMilliseconds(20); - gdisp_lld_write_command(TEMPGRADIENT); // Temperature gradient - for(i=0; i<14; i++) gdisp_lld_write_data(0); - gdisp_lld_write_command(BOOSTVON); // Booster voltage ON - gdisp_lld_write_command(DISPLAYON); // Finally - Display On + GDISP_LLD(write_cmd)(TEMPGRADIENT); // Temperature gradient + for(i=0; i<14; i++) GDISP_LLD(write_data)(0); + GDISP_LLD(write_cmd)(BOOSTVON); // Booster voltage ON + GDISP_LLD(write_cmd)(DISPLAYON); // Finally - Display On #endif #endif @@ -260,6 +255,12 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOn; GDISP.Backlight = 100; GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif return TRUE; } @@ -273,70 +274,21 @@ bool_t GDISP_LLD(init)(void) { * @notapi */ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; #endif gdisp_lld_setviewport(x, y, 1, 1); - gdisp_lld_write_command(RAMWR); - gdisp_lld_write_data((color >> 4) & 0xFF); - gdisp_lld_write_data((color << 4) & 0xF0); - gdisp_lld_write_command(NOP); + GDISP_LLD(write_cmd)(RAMWR); + GDISP_LLD(write_data)((color >> 4) & 0xFF); + GDISP_LLD(write_data)((color << 4) & 0xF0); + GDISP_LLD(write_cmd)(NOP); } /* ---- Optional Routines ---- */ -/* - All the below routines are optional. - Defining them will increase speed but everything - will work if they are not defined. - If you are not using a routine - turn it off using - the appropriate GDISP_HARDWARE_XXXX macro. - Don't bother coding for obvious similar routines if - there is no performance penalty as the emulation software - makes a good job of using similar routines. - eg. If fillarea() is defined there is little - point in defining clear() unless the - performance bonus is significant. - For good performance it is suggested to implement - fillarea() and blitarea(). -*/ - -#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) - /** - * @brief Clear the display. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] color The color of the pixel - * - * @notapi - */ - void GDISP_LLD(clear(color_t color) { - /* NOT IMPLEMENTED */ - /* Nothing to be gained by implementing this - * as fillarea is just as fast. - */ - } -#endif - -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif #if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) /** * @brief Fill an area with a color. - * @note Optional - The high level driver can emulate using software. * * @param[in] x, y The start filled area * @param[in] cx, cy The width and height to be filled @@ -357,11 +309,11 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { // This extra pixel is ignored by the controller. gdisp_lld_setviewport(x, y, cx, cy); - gdisp_lld_write_command(RAMWR); + GDISP_LLD(write_cmd)(RAMWR); for(i=0; i < tuples; i++) { - gdisp_lld_write_data((color >> 4) & 0xFF); - gdisp_lld_write_data(((color << 4) & 0xF0)|((color >> 8) & 0x0F)); - gdisp_lld_write_data(color & 0xFF); + GDISP_LLD(write_data)((color >> 4) & 0xFF); + GDISP_LLD(write_data)(((color << 4) & 0xF0)|((color >> 8) & 0x0F)); + GDISP_LLD(write_data)(color & 0xFF); } } #endif @@ -369,175 +321,125 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { #if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) /** * @brief Fill an area with a bitmap. - * @note Optional - The high level driver can emulate using software. * * @param[in] x, y The start filled area * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. * @param[in] buffer The pixels to use to fill the area. * * @notapi */ - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { - unsigned i, area, tuples; - #ifndef GDISP_PACKED_PIXELS - color_t c1, c2; + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + coord_t endx, endy, lg; + color_t c1, c2; + #if GDISP_PACKED_PIXELS + coord_t pos; + const uint8_t *p; #endif - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) return; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; } + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif - area = cx*cy; + /* What are our end points */ + endx = srcx + cx; + endy = y + cy; gdisp_lld_setviewport(x, y, cx, cy); - gdisp_lld_write_command(RAMWR); + GDISP_LLD(write_cmd)(RAMWR); - #ifdef GDISP_PACKED_PIXELS - // 3 bytes per 2 pixels + an extra 2 bytes if the total size is odd. - // Note we can't just over-estimate this and let the controller handle the extra pixel - // as that might over-run our source buffer (very bad in some circumstances). - tuples = (area/2)*3+(area & 0x01)*2; - for(i=0; i < tuples; i++) - gdisp_lld_write_data(*buffer++); - if (area & 0x01) - gdisp_lld_write_command(NOP); - #else + #if !GDISP_PACKED_PIXELS // Although this controller uses packed pixels we support unpacked pixel // formats in this blit by packing the data as we feed it to the controller. - tuples = area/2; - for(i=0; i < tuples; i++) { + lg = srccx - cx; + buffer += srcy * srccx + srcx; + x = srcx; + while (1) { + /* Get a pixel */ c1 = *buffer++; + if (++x >= endx) { + if (++y >= endy) { + /* Odd pixel at end */ + GDISP_LLD(write_data)((c1 >> 4) & 0xFF); + GDISP_LLD(write_data)((c1 << 4) & 0xF0); + GDISP_LLD(write_cmd)(NOP); + break; + } + x = srcx; + buffer += lg; + } + /* Get the next pixel */ c2 = *buffer++; - gdisp_lld_write_data((c1 >> 4) & 0xFF); - gdisp_lld_write_data(((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)); - gdisp_lld_write_data(c2 & 0xFF); + GDISP_LLD(write_data)((c1 >> 4) & 0xFF); + GDISP_LLD(write_data)(((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)); + GDISP_LLD(write_data)(c2 & 0xFF); + if (++x >= endx) { + if (++y >= endy) + break; + x = srcx; + buffer += lg; + } } - if (area & 0x01) { - c1 = *buffer++; - gdisp_lld_write_data((c1 >> 4) & 0xFF); - gdisp_lld_write_data((c1 << 4) & 0xF0); - gdisp_lld_write_command(NOP); + + #else + + // Although this controller uses packed pixels, we may have to feed it into + // the controller with different packing to the source bitmap + #if !GDISP_PACKED_LINES + srccx = (srccx + 1) & ~1; + #endif + pos = srcy*srccx; + lg = (srccx - cx)/2*3; + p = ((const uint8_t *)buffer) + ((pos+srcx)/2 * 3); + + x = srcx; + while (1) { + /* Get a pixel */ + switch((pos+x)&1) { + case 0: c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break; + case 1: c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break; + } + if (++x >= endx) { + if (++y >= endy) { + /* Odd pixel at end */ + GDISP_LLD(write_data)((c1 >> 4) & 0xFF); + GDISP_LLD(write_data)((c1 << 4) & 0xF0); + GDISP_LLD(write_cmd)(NOP); + break; + } + x = srcx; + p += lg; + pos += srccx; + } + /* Get the next pixel */ + switch((pos+x)&1) { + case 0: c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4); break; + case 1: c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]); break; + } + GDISP_LLD(write_data)((c1 >> 4) & 0xFF); + GDISP_LLD(write_data)(((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)); + GDISP_LLD(write_data)(c2 & 0xFF); + if (++x >= endx) { + if (++y >= endy) + break; + x = srcx; + p += lg; + pos += srccx; + } } #endif } #endif -/* Circular Drawing Functions */ -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLES) || defined(__DOXYGEN__) - /** - * @brief Draw a circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSES) || defined(__DOXYGEN__) - /** - * @brief Draw an ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - #include "gdisp_fonts.h" -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a transparent background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * - * @notapi - */ - void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXTFILLS) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a filled background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * @param[in] bgcolor The background color - * - * @notapi - */ - void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__) +#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) /** * @brief Get the color of a particular pixel. - * @note Optional. * @note If x,y is off the screen, the result is undefined. * * @param[in] x, y The start of the text @@ -546,13 +448,15 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { */ color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { /* NOT IMPLEMENTED */ + /* Some board hardware might support this in the future. + * The Olimex board doesn't. + */ } #endif -#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__) +#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) /** * @brief Scroll vertically a section of the screen. - * @note Optional. * @note If x,y + cx,cy is off the screen, the result is undefined. * @note If lines is >= cy, it is equivelent to a area fill with bgcolor. * @@ -565,6 +469,9 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { */ void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { /* NOT IMPLEMENTED */ + /* The hardware seems capable of doing this. + * It is just really complex so we leave it out for now. + */ } #endif @@ -590,6 +497,13 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { */ void GDISP_LLD(control)(int what, void *value) { /* NOT IMPLEMENTED YET */ + /* The hardware is capable of supporting... + * GDISP_CONTROL_POWER + * GDISP_CONTROL_ORIENTATION + * GDISP_CONTROL_BACKLIGHT (at least on the Olimex board) + * GDISP_CONTROL_CONTRAST + * We don't currently implement any of it. + */ switch(what) { case GDISP_CONTROL_POWER: if (GDISP.Powermode == (gdisp_powermode_t)value) @@ -602,7 +516,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { /* Code here */ /* You may need this --- if (GDISP.Powermode != powerSleep) - GDISP_LLD(init(); + GDISP_LLD(init)(); */ break; case powerSleep: @@ -642,6 +556,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { default: return; } + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width; + GDISP.clipy1 = GDISP.Height; + #endif GDISP.Orientation = (gdisp_orientation_t)value; return; /* @@ -652,37 +572,5 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if (GDISP_NEED_QUERY && GDISP_HARDWARE_QUERY) || defined(__DOXYGEN__) -/** - * @brief Query a driver value. - * @detail Typecase the result to the type you want. - * @note GDISP_QUERY_WIDTH - (coord_t) Gets the width of the screen - * GDISP_QUERY_HEIGHT - (coord_t) Gets the height of the screen - * GDISP_QUERY_POWER - (gdisp_powermode_t) Get the current powermode - * GDISP_QUERY_ORIENTATION - (gdisp_orientation_t) Get the current screen orientation - * GDISP_QUERY_BACKLIGHT - (coord_t) Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - (coord_t) Get the contrast (0 to 100). - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to Query - * - * @notapi - */ -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - case GDISP_QUERY_LLD+0: - /* Code here */ - default: return (void *)-1; - } -} -#endif - #endif /* HAL_USE_GDISP */ /** @} */ diff --git a/drivers/gdisp/Nokia6610/gdisp_lld_board_example.h b/drivers/gdisp/Nokia6610/gdisp_lld_board_example.h index 0e2b806e..12b136da 100644 --- a/drivers/gdisp/Nokia6610/gdisp_lld_board_example.h +++ b/drivers/gdisp/Nokia6610/gdisp_lld_board_example.h @@ -41,6 +41,7 @@ */ static __inline void GDISP_LLD(init_board)(void) { /* Code here */ +#error "gdispNokia6610: You must supply a definition for init_board for your board" } /** @@ -52,30 +53,31 @@ static __inline void GDISP_LLD(init_board)(void) { */ static __inline void GDISP_LLD(setpin_reset)(bool_t state) { /* Code here */ +#error "gdispNokia6610: You must supply a definition for setpin_reset for your board" } /** - * @brief Set or clear the lcd back-light pin. + * @brief Send an 8 bit command to the lcd. + * + * @param[in] data The command to send * - * @param[in] state TRUE = lcd back-light on, FALSE = lcd back-light off - * * @notapi */ -static __inline void GDISP_LLD(setpin_backlight)(bool_t state) { +static __inline void GDISP_LLD(write_cmd)(uint16_t data) { /* Code here */ +#error "gdispNokia6610: You must supply a definition for write_cmd for your board" } /** - * @brief Send a 9 bit command/data to the lcd. - * @note The chip select may need to be asserted/de-asserted - * around the actual spi write + * @brief Send an 8 bit data to the lcd. * * @param[in] data The data to send * * @notapi */ -static __inline void GDISP_LLD(write_spi)(uint16_t data) { +static __inline void GDISP_LLD(write_data)(uint16_t data) { /* Code here */ +#error "gdispNokia6610: You must supply a definition for write_data for your board" } #if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__) @@ -88,8 +90,9 @@ static __inline void GDISP_LLD(write_spi)(uint16_t data) { * * @notapi */ -static __inline uint16_t GDISP_LLD(read_spi)(void) { +static __inline uint16_t GDISP_LLD(read_data)(void) { /* Code here */ +#error "gdispNokia6610: You must supply a definition for read_data for your board" } #endif diff --git a/drivers/gdisp/Nokia6610/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610/gdisp_lld_board_olimexsam7ex256.h index b5b4b1d5..d42dc6d4 100644 --- a/drivers/gdisp/Nokia6610/gdisp_lld_board_olimexsam7ex256.h +++ b/drivers/gdisp/Nokia6610/gdisp_lld_board_olimexsam7ex256.h @@ -168,17 +168,31 @@ static __inline void GDISP_LLD(setpin_backlight)(bool_t state) { } /** - * @brief Send a 9 bit command/data to the lcd. + * @brief Send an 8 bit command to the lcd. + * + * @param[in] data The command to send + * + * @notapi + */ +static __inline void GDISP_LLD(write_cmd)(uint16_t data) { + // wait for the previous transfer to complete + while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); + // send the command + pSPI->SPI_TDR = data & 0xFF; +} + +/** + * @brief Send an 8 bit data to the lcd. * * @param[in] data The data to send * * @notapi */ -static __inline void GDISP_LLD(write_spi)(uint16_t data) { +static __inline void GDISP_LLD(write_data)(uint16_t data) { // wait for the previous transfer to complete while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // send the data - pSPI->SPI_TDR = data; + pSPI->SPI_TDR = data | 0x0100; } #if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__) @@ -189,7 +203,7 @@ static __inline void GDISP_LLD(write_spi)(uint16_t data) { * * @notapi */ -static __inline uint16_t GDISP_LLD(read_spi)(void) { +static __inline uint16_t GDISP_LLD(read_data)(void) { #error "gdispNokia6610: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board" return 0; } diff --git a/drivers/gdisp/Nokia6610/gdisp_lld_config.h b/drivers/gdisp/Nokia6610/gdisp_lld_config.h index 9e2d1258..7d458447 100644 --- a/drivers/gdisp/Nokia6610/gdisp_lld_config.h +++ b/drivers/gdisp/Nokia6610/gdisp_lld_config.h @@ -38,25 +38,18 @@ #define GDISP_DRIVER_NAME "Nokia6610" #define GDISP_LLD(x) gdisp_lld_##x##_Nokia6610 -#define GDISP_HARDWARE_LINES FALSE -#define GDISP_HARDWARE_CLEARS FALSE #define GDISP_HARDWARE_FILLS TRUE #define GDISP_HARDWARE_BITFILLS TRUE -#define GDISP_HARDWARE_CIRCLES FALSE -#define GDISP_HARDWARE_CIRCLEFILLS FALSE -#define GDISP_HARDWARE_ELLIPSES FALSE -#define GDISP_HARDWARE_ELLIPSEFILLS FALSE -#define GDISP_HARDWARE_TEXT FALSE -#define GDISP_HARDWARE_TEXTFILLS FALSE -#define GDISP_HARDWARE_SCROLL FALSE -#define GDISP_HARDWARE_PIXELREAD FALSE #define GDISP_HARDWARE_CONTROL FALSE #define GDISP_HARDWARE_QUERY FALSE -#define GDISP_SOFTWARE_TEXTFILLDRAW TRUE +#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB444 +/* This driver supports both packed and unpacked pixel formats and line formats. + * By default we leave these as FALSE. + */ #define GDISP_PACKED_PIXELS FALSE #define GDISP_PACKED_LINES FALSE diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c index 5811a6ed..f6e8166a 100644 --- a/drivers/gdisp/S6D1121/gdisp_lld.c +++ b/drivers/gdisp/S6D1121/gdisp_lld.c @@ -35,22 +35,6 @@ /* Include the emulation code for things we don't support */ #include "gdisp_emulation.c" -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - #include "s6d1121_lld.c.h" /*===========================================================================*/ @@ -200,6 +184,12 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOn; GDISP.Backlight = 100; GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif return TRUE; } @@ -213,29 +203,14 @@ bool_t GDISP_LLD(init)(void) { * @notapi */ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; #endif lld_lcdSetCursor(x, y); lld_lcdWriteReg(0x0022, color); } /* ---- Optional Routines ---- */ -/* - All the below routines are optional. - Defining them will increase speed but everything - will work if they are not defined. - If you are not using a routine - turn it off using - the appropriate GDISP_HARDWARE_XXXX macro. - Don't bother coding for obvious similar routines if - there is no performance penalty as the emulation software - makes a good job of using similar routines. - eg. If fillarea() is defined there is little - point in defining clear() unless the - performance bonus is significant. - For good performance it is suggested to implement - fillarea() and blitarea(). -*/ #if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) /** @@ -259,25 +234,6 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - #if GDISP_NEED_VALIDATION - /* Need to clip to screen */ - #endif - /* Code here */ - } -#endif - #if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) /** * @brief Fill an area with a color. @@ -290,14 +246,16 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; - #endif - unsigned i, area; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; + #endif + area = cx*cy; lld_lcdSetViewPort(x, y, cx, cy); lld_lcdWriteStreamStart(); @@ -315,157 +273,40 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * * @param[in] x, y The start filled area * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. * @param[in] buffer The pixels to use to fill the area. * * @notapi */ - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { - unsigned i, area; + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + coord_t endx, endy; + unsigned lg; - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) return; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; } + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif - area = cx*cy; lld_lcdSetViewPort(x, y, cx, cy); lld_lcdWriteStreamStart(); - for(i = 0; i < area; i++) - lld_lcdWriteData(*buffer++); + + endx = srcx + cx; + endy = y + cy; + lg = srccx - cx; + buffer += srcx + srcy * srccx; + for(; y < endy; y++, buffer += lg) + for(x=srcx; x < endx; x++) + lld_lcdWriteData(*buffer++); lld_lcdWriteStreamStop(); lld_lcdResetViewPort(); } #endif -/* Circular Drawing Functions */ -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLES) || defined(__DOXYGEN__) - /** - * @brief Draw a circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSES) || defined(__DOXYGEN__) - /** - * @brief Draw an ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - #include "gdisp_fonts.h" -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a transparent background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * - * @notapi - */ - void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXTFILLS) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a filled background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * @param[in] bgcolor The background color - * - * @notapi - */ - void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - #if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__) /** * @brief Get the color of a particular pixel. @@ -483,8 +324,8 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { */ color_t color; - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return 0; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; #endif lld_lcdSetCursor(x, y); @@ -521,15 +362,15 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { coord_t row0, row1; unsigned i, gap, abslines; - abslines = lines < 0 ? -lines : lines; - - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; #endif - if (!abslines) return; + abslines = lines < 0 ? -lines : lines; if (abslines >= cy) { abslines = cy; gap = 0; @@ -642,6 +483,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { default: return; } + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width; + GDISP.clipy1 = GDISP.Height; + #endif GDISP.Orientation = (gdisp_orientation_t)value; return; /* @@ -652,37 +499,5 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if (GDISP_NEED_QUERY && GDISP_HARDWARE_QUERY) || defined(__DOXYGEN__) -/** - * @brief Query a driver value. - * @detail Typecase the result to the type you want. - * @note GDISP_QUERY_WIDTH - (coord_t) Gets the width of the screen - * GDISP_QUERY_HEIGHT - (coord_t) Gets the height of the screen - * GDISP_QUERY_POWER - (gdisp_powermode_t) Get the current powermode - * GDISP_QUERY_ORIENTATION - (gdisp_orientation_t) Get the current screen orientation - * GDISP_QUERY_BACKLIGHT - (coord_t) Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - (coord_t) Get the contrast (0 to 100). - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to Query - * - * @notapi - */ -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - case GDISP_QUERY_LLD+0: - /* Code here */ - default: return (void *)-1; - } -} -#endif - #endif /* HAL_USE_GDISP */ /** @} */ diff --git a/drivers/gdisp/S6D1121/gdisp_lld_config.h b/drivers/gdisp/S6D1121/gdisp_lld_config.h index ee3fdeee..65849c40 100644 --- a/drivers/gdisp/S6D1121/gdisp_lld_config.h +++ b/drivers/gdisp/S6D1121/gdisp_lld_config.h @@ -35,30 +35,17 @@ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "S6d1121" -#define GDISP_LLD(x) gdisp_lld_##x##_S6d1121 +#define GDISP_DRIVER_NAME "S6D1121" +#define GDISP_LLD(x) gdisp_lld_##x##_S6D1121 -#define GDISP_HARDWARE_LINES FALSE #define GDISP_HARDWARE_CLEARS TRUE #define GDISP_HARDWARE_FILLS TRUE #define GDISP_HARDWARE_BITFILLS TRUE -#define GDISP_HARDWARE_CIRCLES FALSE -#define GDISP_HARDWARE_CIRCLEFILLS FALSE -#define GDISP_HARDWARE_ELLIPSES FALSE -#define GDISP_HARDWARE_ELLIPSEFILLS FALSE -#define GDISP_HARDWARE_TEXT FALSE -#define GDISP_HARDWARE_TEXTFILLS FALSE #define GDISP_HARDWARE_SCROLL TRUE #define GDISP_HARDWARE_PIXELREAD FALSE #define GDISP_HARDWARE_CONTROL TRUE -#define GDISP_HARDWARE_QUERY FALSE - -#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE -#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 -#define GDISP_PACKED_PIXELS FALSE -#define GDISP_PACKED_LINES FALSE #endif /* HAL_USE_GDISP */ diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c index 5f017b37..21e0abf0 100644 --- a/drivers/gdisp/SSD1289/gdisp_lld.c +++ b/drivers/gdisp/SSD1289/gdisp_lld.c @@ -35,22 +35,6 @@ /* Include the emulation code for things we don't support */ #include "gdisp_emulation.c" -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - #include "ssd1289_lld.c.h" /*===========================================================================*/ @@ -141,6 +125,12 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOn; GDISP.Backlight = 100; GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif return TRUE; } @@ -154,8 +144,8 @@ bool_t GDISP_LLD(init)(void) { * @notapi */ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; #endif lld_lcdSetCursor(x, y); lld_lcdWriteReg(0x0022, color); @@ -200,22 +190,6 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - #if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) /** * @brief Fill an area with a color. @@ -228,10 +202,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif unsigned i, area; @@ -253,139 +229,40 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * * @param[in] x, y The start filled area * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. * @param[in] buffer The pixels to use to fill the area. * * @notapi */ - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { - unsigned i, area; + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + coord_t endx, endy; + unsigned lg; - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) return; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; } + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif - area = cx*cy; lld_lcdSetViewPort(x, y, cx, cy); lld_lcdWriteStreamStart(); - for(i = 0; i < area; i++) - lld_lcdWriteData(*buffer++); + + endx = srcx + cx; + endy = y + cy; + lg = srccx - cx; + buffer += srcx + srcy * srccx; + for(; y < endy; y++, buffer += lg) + for(x=srcx; x < endx; x++) + lld_lcdWriteData(*buffer++); lld_lcdWriteStreamStop(); lld_lcdResetViewPort(); } #endif -/* Circular Drawing Functions */ -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLES) || defined(__DOXYGEN__) - /** - * @brief Draw a circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSES) || defined(__DOXYGEN__) - /** - * @brief Draw an ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - #include "gdisp_fonts.h" -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a transparent background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * - * @notapi - */ - void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - /* NOT IMPLEMENTED */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXTFILLS) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a filled background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * @param[in] bgcolor The background color - * - * @notapi - */ - void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - /* NOT IMPLEMENTED */ - } -#endif - #if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__) /** * @brief Get the color of a particular pixel. @@ -399,8 +276,8 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { color_t color; - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return 0; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; #endif lld_lcdSetCursor(x, y); @@ -434,15 +311,16 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { coord_t row0, row1; unsigned i, gap, abslines; - abslines = lines < 0 ? -lines : lines; - - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; #endif - if (!abslines) return; + abslines = lines < 0 ? -lines : lines; + if (abslines >= cy) { abslines = cy; gap = 0; @@ -560,6 +438,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { default: return; } + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width; + GDISP.clipy1 = GDISP.Height; + #endif GDISP.Orientation = (gdisp_orientation_t)value; return; /* @@ -570,37 +454,5 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if (GDISP_NEED_QUERY && GDISP_HARDWARE_QUERY) || defined(__DOXYGEN__) -/** - * @brief Query a driver value. - * @detail Typecase the result to the type you want. - * @note GDISP_QUERY_WIDTH - (coord_t) Gets the width of the screen - * GDISP_QUERY_HEIGHT - (coord_t) Gets the height of the screen - * GDISP_QUERY_POWER - (gdisp_powermode_t) Get the current powermode - * GDISP_QUERY_ORIENTATION - (gdisp_orientation_t) Get the current screen orientation - * GDISP_QUERY_BACKLIGHT - (coord_t) Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - (coord_t) Get the contrast (0 to 100). - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to Query - * - * @notapi - */ -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - case GDISP_QUERY_LLD+0: - /* Code here */ - default: return (void *)-1; - } -} -#endif - #endif /* HAL_USE_GDISP */ /** @} */ diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h index 123ce875..7311c7ba 100644 --- a/drivers/gdisp/SSD1289/gdisp_lld_config.h +++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h @@ -38,27 +38,14 @@ #define GDISP_DRIVER_NAME "SSD1289" #define GDISP_LLD(x) gdisp_lld_##x##_SSD1289 -#define GDISP_HARDWARE_LINES FALSE #define GDISP_HARDWARE_CLEARS TRUE #define GDISP_HARDWARE_FILLS TRUE #define GDISP_HARDWARE_BITFILLS TRUE -#define GDISP_HARDWARE_CIRCLES FALSE -#define GDISP_HARDWARE_CIRCLEFILLS FALSE -#define GDISP_HARDWARE_ELLIPSES FALSE -#define GDISP_HARDWARE_ELLIPSEFILLS FALSE -#define GDISP_HARDWARE_TEXT FALSE -#define GDISP_HARDWARE_TEXTFILLS FALSE #define GDISP_HARDWARE_SCROLL TRUE #define GDISP_HARDWARE_PIXELREAD TRUE #define GDISP_HARDWARE_CONTROL TRUE -#define GDISP_HARDWARE_QUERY FALSE - -#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE -#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 -#define GDISP_PACKED_PIXELS FALSE -#define GDISP_PACKED_LINES FALSE #endif /* HAL_USE_GDISP */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c index 2d8bacce..63d5f6b2 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld.c +++ b/drivers/gdisp/SSD1963/gdisp_lld.c @@ -1,771 +1,565 @@ -/* - ChibiOS-LCD-Driver - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS-LCD-Driver. - - ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS-LCD-Driver is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file SSD1963/gdisp_lld.c - * @brief GDISP Graphics Driver subsystem low level driver source. - * - * @addtogroup GDISP - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gdisp.h" - -#if HAL_USE_GDISP || defined(__DOXYGEN__) - -/* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if GDISP_NEED_TEXT - #include "gdisp_fonts.h" -#endif - -/* All the board specific code should go in these include file so the driver - * can be ported to another board just by creating a suitable file. - */ -#if defined(BOARD_YOURBOARDNAME) - #include "gdisp_lld_board_yourboardname.h" -#else - /* Include the user supplied board definitions */ - #include "gdisp_lld_board.h" -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -#include "ssd1963.h" - - -#if defined(LCD_USE_FSMC) -__inline void GDISP_LLD(writeindex)(uint8_t cmd) { - LCD_REG = cmd; -} - -__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) { - LCD_REG = lcdReg; - LCD_RAM = lcdRegValue; -} - -__inline void GDISP_LLD(writedata)(uint16_t data) { - LCD_RAM = data; -} - -__inline uint16_t GDISP_LLD(readdata)(void) { - return (LCD_RAM); -} - -__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) { - LCD_REG = lcdReg; - return (LCD_RAM); -} - -__inline void GDISP_LLD(writestreamstart)(void) { - GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START); -} - -__inline void GDISP_LLD(readstreamstart)(void) { - GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START); -} - -__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) { - uint16_t i; - for(i = 0; i < size; i++) - LCD_RAM = buffer[i]; -} - -__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) { - uint16_t i; - - for(i = 0; i < size; i++) { - buffer[i] = LCD_RAM; - } -} - -#elif defined(LCD_USE_GPIO) - -__inline void GDISP_LLD(writeindex)(uint8_t cmd) { - Set_CS; Set_RS; Set_WR; Clr_RD; - palWritePort(LCD_DATA_PORT, cmd); - Clr_CS; -} - -__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) { - Set_CS; Set_RS; Set_WR; Clr_RD; - palWritePort(LCD_DATA_PORT, lcdReg); - Clr_RS; - palWritePort(LCD_DATA_PORT, lcdRegValue); - Clr_CS; -} -__inline void GDISP_LLD(writedata)(uint16_t data) { - Set_CS; Clr_RS; Set_WR; Clr_RD; - palWritePort(LCD_DATA_PORT, data); - Clr_CS; -} - -__inline uint16_t GDISP_LLD(readdata)(void) { - Set_CS; Clr_RS; Clr_WR; Set_RD; - uint16_t data = palReadPort(LCD_DATA_PORT); - Clr_CS; - return data; -} - -__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) { - Set_CS; Set_RS; Clr_WR; Set_RD; - palWritePort(LCD_DATA_PORT, lcdReg); - Clr_RS; - uint16_t data = palReadPort(LCD_DATA_PORT); - Clr_CS; - return data; -} - -__inline void GDISP_LLD(writestreamstart)(void) { - GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START); -} - -__inline void GDISP_LLD(readstreamstart)(void) { - GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START); -} - -__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) { - uint16_t i; - Set_CS; Clr_RS; Set_WR; Clr_RD; - for(i = 0; i < size; i++) { - Set_WR; - palWritePort(LCD_DATA_PORT, buffer[i]); - Clr_WR; - } - Clr_CS; -} - -__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) { - uint16_t i; - Set_CS; Clr_RS; Clr_WR; Set_RD; - for(i = 0; i < size; i++) { - Set_RD; - buffer[i] = palReadPort(LCD_DATA_PORT); - Clr_RD; - } -} -#endif - -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. -*/ - -/** - * @brief Low level GDISP driver initialisation. - * @return TRUE if successful, FALSE on error. - * - * @notapi - */ -bool_t GDISP_LLD(init)(void) { - /* Initialise your display */ - - /* Initialise the GDISP structure to match */ - GDISP.Width = SCREEN_WIDTH; - GDISP.Height = SCREEN_HEIGHT; - GDISP.Orientation = landscape; - GDISP.Powermode = powerOn; - GDISP.Backlight = 100; - GDISP.Contrast = 50; - -#if defined(LCD_USE_FSMC) - - #if defined(STM32F1XX) || defined(STM32F3XX) - /* FSMC setup for F1/F3 */ - rccEnableAHB(RCC_AHBENR_FSMCEN, 0); - - #elif defined(STM32F4XX) || defined(STM32F2XX) - /* STM32F2-F4 FSMC init */ - rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0); - #else - #error "FSMC not implemented for this device" - #endif - - /* set pins to FSMC mode */ - IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) | - (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0}; - - IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | - (1 << 13) | (1 << 14) | (1 << 15), 0}; - - palSetBusMode(&busD, PAL_MODE_ALTERNATE(12)); - palSetBusMode(&busE, PAL_MODE_ALTERNATE(12)); - - const unsigned char FSMC_Bank = 0; - /* FSMC timing */ - FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \ - | (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \ - | (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ; - - /* Bank1 NOR/SRAM control register configuration - * This is actually not needed as already set by default after reset */ - FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; - - #elif defined(LCD_USE_GPIO) - IOBus busCMD = {LCD_CMD_PORT, (1 << LCD_CS) | (1 << LCD_RS) | (1 << LCD_WR) | (1 << LCD_RD), 0}; - IOBus busDATA = {LCD_CMD_PORT, 0xFFFFF, 0}; - palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL); - palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL); - - #else - #error "Please define LCD_USE_FSMC or LCD_USE_GPIO" -#endif - GDISP_LLD(writeindex)(SSD1963_SOFT_RESET); - chThdSleepMicroseconds(100); - - /* Driver PLL config */ - GDISP_LLD(writeindex)(SSD1963_SET_PLL_MN); - GDISP_LLD(writedata)(35); // PLLclk = REFclk (10Mhz) * 36 (360Mhz) - GDISP_LLD(writedata)(2); // SYSclk = PLLclk / 3 (120MHz) - GDISP_LLD(writedata)(4); // Apply calculation bit, else it is ignored - - GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Enable PLL - GDISP_LLD(writedata)(0x01); - chThdSleepMicroseconds(200); - - GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Use PLL - GDISP_LLD(writedata)(0x03); - chThdSleepMicroseconds(200); - - GDISP_LLD(writeindex)(SSD1963_SOFT_RESET); - chThdSleepMicroseconds(100); - - /* Screen size */ - GDISP_LLD(writeindex)(SSD1963_SET_LCD_MODE); -// GDISP_LLD(writedata)(0x0000); - GDISP_LLD(writedata)(0b00011000); - GDISP_LLD(writedata)(0x0000); - GDISP_LLD(writedata)(mHIGH((SCREEN_WIDTH+1))); - GDISP_LLD(writedata)((SCREEN_WIDTH+1)); - GDISP_LLD(writedata)(mHIGH((SCREEN_HEIGHT+1))); - GDISP_LLD(writedata)((SCREEN_HEIGHT+1)); - GDISP_LLD(writedata)(0x0000); - - GDISP_LLD(writeindex)(SSD1963_SET_PIXEL_DATA_INTERFACE); - GDISP_LLD(writedata)(SSD1963_PDI_16BIT565); - - /* LCD Clock specs */ - GDISP_LLD(writeindex)(SSD1963_SET_LSHIFT_FREQ); - GDISP_LLD(writedata)((LCD_FPR >> 16) & 0xFF); - GDISP_LLD(writedata)((LCD_FPR >> 8) & 0xFF); - GDISP_LLD(writedata)(LCD_FPR & 0xFF); - - GDISP_LLD(writeindex)(SSD1963_SET_HORI_PERIOD); - GDISP_LLD(writedata)(mHIGH(SCREEN_HSYNC_PERIOD)); - GDISP_LLD(writedata)(mLOW(SCREEN_HSYNC_PERIOD)); - GDISP_LLD(writedata)(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); - GDISP_LLD(writedata)(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); - GDISP_LLD(writedata)(SCREEN_HSYNC_PULSE); - GDISP_LLD(writedata)(0x00); - GDISP_LLD(writedata)(0x00); - GDISP_LLD(writedata)(0x00); - - GDISP_LLD(writeindex)(SSD1963_SET_VERT_PERIOD); - GDISP_LLD(writedata)(mHIGH(SCREEN_VSYNC_PERIOD)); - GDISP_LLD(writedata)(mLOW(SCREEN_VSYNC_PERIOD)); - GDISP_LLD(writedata)(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); - GDISP_LLD(writedata)(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); - GDISP_LLD(writedata)(SCREEN_VSYNC_PULSE); - GDISP_LLD(writedata)(0x00); - GDISP_LLD(writedata)(0x00); - - /* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel */ - GDISP_LLD(writeindex)(SSD1963_SET_TEAR_ON); - GDISP_LLD(writedata)(0x0000); - - /* Turn on */ - GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON); -#if defined(LCD_USE_FSMC) - /* FSMC delay reduced as the controller now runs at full speed */ - FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ; - FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; -#endif - - return TRUE; -} - -void GDISP_LLD(setwindow)(coord_t x0, coord_t y0, coord_t x1, coord_t y1) { - #if GDISP_NEED_VALIDATION - if (x0 >= GDISP.Width || y0 >= GDISP.Height) return; - else if (x1 >= GDISP.Width || y1 >= GDISP.Height) return; - #endif - GDISP_LLD(writeindex)(SSD1963_SET_PAGE_ADDRESS); - GDISP_LLD(writedata)((y0 >> 8) & 0xFF); - GDISP_LLD(writedata)((y0 >> 0) & 0xFF); - GDISP_LLD(writedata)((y1 >> 8) & 0xFF); - GDISP_LLD(writedata)((y1 >> 0) & 0xFF); - GDISP_LLD(writeindex)(SSD1963_SET_COLUMN_ADDRESS); - GDISP_LLD(writedata)((x0 >> 8) & 0xFF); - GDISP_LLD(writedata)((x0 >> 0) & 0xFF); - GDISP_LLD(writedata)((x1 >> 8) & 0xFF); - GDISP_LLD(writedata)((x1 >> 0) & 0xFF); -} - -/** - * @brief Draws a pixel on the display. - * - * @param[in] x X location of the pixel - * @param[in] y Y location of the pixel - * @param[in] color The color of the pixel - * - * @notapi - */ -void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return; - #endif - - GDISP_LLD(setwindow)(x, y, x, y); - GDISP_LLD(writestreamstart)(); - GDISP_LLD(writedata)(color); -} - -/* ---- Optional Routines ---- */ -/* - All the below routines are optional. - Defining them will increase speed but everything - will work if they are not defined. - If you are not using a routine - turn it off using - the appropriate GDISP_HARDWARE_XXXX macro. - Don't bother coding for obvious similar routines if - there is no performance penalty as the emulation software - makes a good job of using similar routines. - eg. If fillarea() is defined there is little - point in defining clear() unless the - performance bonus is significant. - For good performance it is suggested to implement - fillarea() and blitarea(). -*/ - -#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) - /** - * @brief Clear the display. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] color The color of the pixel - * - * @notapi - */ - void GDISP_LLD(clear)(color_t color) { - GDISP_LLD(fillarea)(0, 0, GDISP.Width-1, GDISP.Height-1, color); - } -#endif - -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - #if GDISP_NEED_VALIDATION - /* Need to clip to screen */ - #endif - /* Code here */ - } -#endif - -#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) - /** - * @brief Fill an area with a color. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The start filled area - * @param[in] cx, cy The width and height to be filled - * @param[in] color The color of the fill - * - * @notapi - */ - void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; - #endif - - uint32_t index = 0, area; - area = (cx+1)*(cy+1); - - GDISP_LLD(setwindow)(x, y, x+cx, y+cy); - GDISP_LLD(writestreamstart)(); - - for(index = 0; index <= area; index++) - GDISP_LLD(writedata)(color); - - } -#endif - -#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) - /** - * @brief Fill an area with a bitmap. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The start filled area - * @param[in] cx, cy The width and height to be filled - * @param[in] buffer The pixels to use to fill the area. - * - * @notapi - */ - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) return; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; - #endif - /* Code here */ - } -#endif - -/* Circular Drawing Functions */ -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLES) || defined(__DOXYGEN__) - /** - * @brief Draw a circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSES) || defined(__DOXYGEN__) - /** - * @brief Draw an ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a transparent background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * - * @notapi - */ - void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXTFILLS) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a filled background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * @param[in] bgcolor The background color - * - * @notapi - */ - void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - #if GDISP_NEED_VALIDATION - /* Code here */ - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__) - /** - * @brief Get the color of a particular pixel. - * @note Optional. - * @note If x,y is off the screen, the result is undefined. - * @return The color of the specified pixel. - * - * @param[in] x, y The start of the text - * - * @notapi - */ - color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return 0; - #endif - /* Code here */ - } -#endif - -#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__) - /** - * @brief Scroll vertically a section of the screen. - * @note Optional. - * @note If x,y + cx,cy is off the screen, the result is undefined. - * @note If lines is >= cy, it is equivelent to a area fill with bgcolor. - * - * @param[in] x, y The start of the area to be scrolled - * @param[in] cx, cy The size of the area to be scrolled - * @param[in] lines The number of lines to scroll (Can be positive or negative) - * @param[in] bgcolor The color to fill the newly exposed area. - * - * @notapi - */ - void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; - #endif - /* Code here */ - - /* - uint16_t size = x1 - x0 ; - - lld_lcdWriteIndex(SSD1963_SET_SCROLL_AREA); - lld_lcdWriteData((x0 >> 8) & 0xFF); - lld_lcdWriteData((x0 >> 0) & 0xFF); - lld_lcdWriteData((size >> 8) & 0xFF); - lld_lcdWriteData((size >> 0) & 0xFF); - lld_lcdWriteData(((lcd_height-x1) >> 8) & 0xFF); - lld_lcdWriteData(((lcd_height-x1) >> 0) & 0xFF); - - lld_lcdWriteIndex(SSD1963_SET_SCROLL_START); - lld_lcdWriteData((lines >> 8) & 0xFF); - lld_lcdWriteData((lines >> 0) & 0xFF); - */ - } - -#endif - -#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) - /** - * @brief Driver Control - * @detail Unsupported control codes are ignored. - * @note The value parameter should always be typecast to (void *). - * @note There are some predefined and some specific to the low level driver. - * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t - * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t - * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver - * that only supports off/on anything other - * than zero is on. - * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. - * GDISP_CONTROL_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to do. - * @param[in] value The value to use (always cast to a void *). - * - * @notapi - */ - void GDISP_LLD(control)(unsigned what, void *value) { - switch(what) { - case GDISP_CONTROL_POWER: - if (GDISP.Powermode == (gdisp_powermode_t)value) - return; - switch((gdisp_powermode_t)value) { - case powerOff: - GDISP_LLD(writeindex)(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode - chThdSleepMicroseconds(5000); - GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF); - GDISP_LLD(writeindex)(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode - break; - case powerOn: - GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); // 2x Dummy reads to wake up from deep sleep - GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); - if (GDISP.Powermode != powerSleep) - GDISP_LLD(init)(); - GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON); - - break; - case powerSleep: - GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF); - GDISP_LLD(writeindex)(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode - chThdSleepMicroseconds(5000); - break; - default: - return; - } - GDISP.Powermode = (gdisp_powermode_t)value; - return; - case GDISP_CONTROL_ORIENTATION: - if (GDISP.Orientation == (gdisp_orientation_t)value) - return; - switch((gdisp_orientation_t)value) { - case portrait: - /* Code here */ - GDISP.Height = SCREEN_HEIGHT; - GDISP.Width = SCREEN_WIDTH; - break; - case landscape: - /* Code here */ - GDISP.Height = SCREEN_WIDTH; - GDISP.Width = SCREEN_HEIGHT; - break; - case portraitInv: - /* Code here */ - GDISP.Height = SCREEN_HEIGHT; - GDISP.Width = SCREEN_WIDTH; - break; - case landscapeInv: - /* Code here */ - GDISP.Height = SCREEN_WIDTH; - GDISP.Width = SCREEN_HEIGHT; - break; - default: - return; - } - GDISP.Orientation = (gdisp_orientation_t)value; - return; -/* - case GDISP_CONTROL_BACKLIGHT: - case GDISP_CONTROL_CONTRAST: -*/ - } - } -#endif - -#if (GDISP_NEED_QUERY && GDISP_HARDWARE_QUERY) || defined(__DOXYGEN__) -/** - * @brief Query a driver value. - * @detail Typecase the result to the type you want. - * @note GDISP_QUERY_WIDTH - (coord_t) Gets the width of the screen - * GDISP_QUERY_HEIGHT - (coord_t) Gets the height of the screen - * GDISP_QUERY_POWER - (gdisp_powermode_t) Get the current powermode - * GDISP_QUERY_ORIENTATION - (gdisp_orientation_t) Get the current screen orientation - * GDISP_QUERY_BACKLIGHT - (coord_t) Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - (coord_t) Get the contrast (0 to 100). - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to Query - * - * @notapi - */ -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - case GDISP_QUERY_LLD+0: - /* Code here */ - default: return (void *)-1; - } -} -#endif - -#endif /* HAL_USE_GDISP */ -/** @} */ +/* + ChibiOS-LCD-Driver - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS-LCD-Driver. + + ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS-LCD-Driver is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SSD1963/gdisp_lld.c + * @brief GDISP Graphics Driver subsystem low level driver source. + * + * @addtogroup GDISP + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gdisp.h" + +#if HAL_USE_GDISP || defined(__DOXYGEN__) + +/* Include the emulation code for things we don't support */ +#include "gdisp_emulation.c" + +/* All the board specific code should go in these include file so the driver + * can be ported to another board just by creating a suitable file. + */ +//#if defined(BOARD_YOURBOARDNAME) +// #include "gdisp_lld_board_yourboardname.h" +//#else +// /* Include the user supplied board definitions */ +// #include "gdisp_lld_board.h" +//#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +#include "ssd1963.h" + + +#if defined(LCD_USE_FSMC) +__inline void GDISP_LLD(writeindex)(uint8_t cmd) { + LCD_REG = cmd; +} + +__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) { + LCD_REG = lcdReg; + LCD_RAM = lcdRegValue; +} + +__inline void GDISP_LLD(writedata)(uint16_t data) { + LCD_RAM = data; +} + +__inline uint16_t GDISP_LLD(readdata)(void) { + return (LCD_RAM); +} + +__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) { + LCD_REG = lcdReg; + return (LCD_RAM); +} + +__inline void GDISP_LLD(writestreamstart)(void) { + GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START); +} + +__inline void GDISP_LLD(readstreamstart)(void) { + GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START); +} + +__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) { + uint16_t i; + for(i = 0; i < size; i++) + LCD_RAM = buffer[i]; +} + +__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) { + uint16_t i; + + for(i = 0; i < size; i++) { + buffer[i] = LCD_RAM; + } +} + +#elif defined(LCD_USE_GPIO) + +__inline void GDISP_LLD(writeindex)(uint8_t cmd) { + Set_CS; Set_RS; Set_WR; Clr_RD; + palWritePort(LCD_DATA_PORT, cmd); + Clr_CS; +} + +__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) { + Set_CS; Set_RS; Set_WR; Clr_RD; + palWritePort(LCD_DATA_PORT, lcdReg); + Clr_RS; + palWritePort(LCD_DATA_PORT, lcdRegValue); + Clr_CS; +} +__inline void GDISP_LLD(writedata)(uint16_t data) { + Set_CS; Clr_RS; Set_WR; Clr_RD; + palWritePort(LCD_DATA_PORT, data); + Clr_CS; +} + +__inline uint16_t GDISP_LLD(readdata)(void) { + Set_CS; Clr_RS; Clr_WR; Set_RD; + uint16_t data = palReadPort(LCD_DATA_PORT); + Clr_CS; + return data; +} + +__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) { + Set_CS; Set_RS; Clr_WR; Set_RD; + palWritePort(LCD_DATA_PORT, lcdReg); + Clr_RS; + uint16_t data = palReadPort(LCD_DATA_PORT); + Clr_CS; + return data; +} + +__inline void GDISP_LLD(writestreamstart)(void) { + GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START); +} + +__inline void GDISP_LLD(readstreamstart)(void) { + GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START); +} + +__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) { + uint16_t i; + Set_CS; Clr_RS; Set_WR; Clr_RD; + for(i = 0; i < size; i++) { + Set_WR; + palWritePort(LCD_DATA_PORT, buffer[i]); + Clr_WR; + } + Clr_CS; +} + +__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) { + uint16_t i; + Set_CS; Clr_RS; Clr_WR; Set_RD; + for(i = 0; i < size; i++) { + Set_RD; + buffer[i] = palReadPort(LCD_DATA_PORT); + Clr_RD; + } +} +#endif + +/* ---- Required Routines ---- */ +/* + The following 2 routines are required. + All other routines are optional. +*/ + +/** + * @brief Low level GDISP driver initialisation. + * @return TRUE if successful, FALSE on error. + * + * @notapi + */ +bool_t GDISP_LLD(init)(void) { + /* Initialise the display */ + +#if defined(LCD_USE_FSMC) + + #if defined(STM32F1XX) || defined(STM32F3XX) + /* FSMC setup for F1/F3 */ + rccEnableAHB(RCC_AHBENR_FSMCEN, 0); + + #elif defined(STM32F4XX) || defined(STM32F2XX) + /* STM32F2-F4 FSMC init */ + rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0); + #else + #error "FSMC not implemented for this device" + #endif + + /* set pins to FSMC mode */ + IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) | + (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0}; + + IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | + (1 << 13) | (1 << 14) | (1 << 15), 0}; + + palSetBusMode(&busD, PAL_MODE_ALTERNATE(12)); + palSetBusMode(&busE, PAL_MODE_ALTERNATE(12)); + + const unsigned char FSMC_Bank = 0; + /* FSMC timing */ + FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \ + | (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \ + | (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ; + + /* Bank1 NOR/SRAM control register configuration + * This is actually not needed as already set by default after reset */ + FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; + + #elif defined(LCD_USE_GPIO) + IOBus busCMD = {LCD_CMD_PORT, (1 << LCD_CS) | (1 << LCD_RS) | (1 << LCD_WR) | (1 << LCD_RD), 0}; + IOBus busDATA = {LCD_CMD_PORT, 0xFFFFF, 0}; + palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL); + palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL); + + #else + #error "Please define LCD_USE_FSMC or LCD_USE_GPIO" +#endif + GDISP_LLD(writeindex)(SSD1963_SOFT_RESET); + chThdSleepMicroseconds(100); + + /* Driver PLL config */ + GDISP_LLD(writeindex)(SSD1963_SET_PLL_MN); + GDISP_LLD(writedata)(35); // PLLclk = REFclk (10Mhz) * 36 (360Mhz) + GDISP_LLD(writedata)(2); // SYSclk = PLLclk / 3 (120MHz) + GDISP_LLD(writedata)(4); // Apply calculation bit, else it is ignored + + GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Enable PLL + GDISP_LLD(writedata)(0x01); + chThdSleepMicroseconds(200); + + GDISP_LLD(writeindex)(SSD1963_SET_PLL); // Use PLL + GDISP_LLD(writedata)(0x03); + chThdSleepMicroseconds(200); + + GDISP_LLD(writeindex)(SSD1963_SOFT_RESET); + chThdSleepMicroseconds(100); + + /* Screen size */ + GDISP_LLD(writeindex)(SSD1963_SET_LCD_MODE); +// GDISP_LLD(writedata)(0x0000); + GDISP_LLD(writedata)(0b00011000); + GDISP_LLD(writedata)(0x0000); + GDISP_LLD(writedata)(mHIGH((SCREEN_WIDTH+1))); + GDISP_LLD(writedata)((SCREEN_WIDTH+1)); + GDISP_LLD(writedata)(mHIGH((SCREEN_HEIGHT+1))); + GDISP_LLD(writedata)((SCREEN_HEIGHT+1)); + GDISP_LLD(writedata)(0x0000); + + GDISP_LLD(writeindex)(SSD1963_SET_PIXEL_DATA_INTERFACE); + GDISP_LLD(writedata)(SSD1963_PDI_16BIT565); + + /* LCD Clock specs */ + GDISP_LLD(writeindex)(SSD1963_SET_LSHIFT_FREQ); + GDISP_LLD(writedata)((LCD_FPR >> 16) & 0xFF); + GDISP_LLD(writedata)((LCD_FPR >> 8) & 0xFF); + GDISP_LLD(writedata)(LCD_FPR & 0xFF); + + GDISP_LLD(writeindex)(SSD1963_SET_HORI_PERIOD); + GDISP_LLD(writedata)(mHIGH(SCREEN_HSYNC_PERIOD)); + GDISP_LLD(writedata)(mLOW(SCREEN_HSYNC_PERIOD)); + GDISP_LLD(writedata)(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); + GDISP_LLD(writedata)(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); + GDISP_LLD(writedata)(SCREEN_HSYNC_PULSE); + GDISP_LLD(writedata)(0x00); + GDISP_LLD(writedata)(0x00); + GDISP_LLD(writedata)(0x00); + + GDISP_LLD(writeindex)(SSD1963_SET_VERT_PERIOD); + GDISP_LLD(writedata)(mHIGH(SCREEN_VSYNC_PERIOD)); + GDISP_LLD(writedata)(mLOW(SCREEN_VSYNC_PERIOD)); + GDISP_LLD(writedata)(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); + GDISP_LLD(writedata)(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); + GDISP_LLD(writedata)(SCREEN_VSYNC_PULSE); + GDISP_LLD(writedata)(0x00); + GDISP_LLD(writedata)(0x00); + + /* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel */ + GDISP_LLD(writeindex)(SSD1963_SET_TEAR_ON); + GDISP_LLD(writedata)(0x0000); + + /* Turn on */ + GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON); +#if defined(LCD_USE_FSMC) + /* FSMC delay reduced as the controller now runs at full speed */ + FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ; + FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; +#endif + + /* Initialise the GDISP structure to match */ + GDISP.Width = SCREEN_WIDTH; + GDISP.Height = SCREEN_HEIGHT; + GDISP.Orientation = landscape; + GDISP.Powermode = powerOn; + GDISP.Backlight = 100; + GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif + + return TRUE; +} + +void GDISP_LLD(setwindow)(coord_t x0, coord_t y0, coord_t x1, coord_t y1) { + /* We don't need to validate here as the LLD routines will validate first. + * + * #if GDISP_NEED_VALIDATION + * if (x0 >= GDISP.Width || y0 >= GDISP.Height || x0 < 0 || y0 < 0) return; + * else if (x1 >= GDISP.Width || y1 >= GDISP.Height || y1 < 0 || y2 < 0) return; + * #endif + */ + GDISP_LLD(writeindex)(SSD1963_SET_PAGE_ADDRESS); + GDISP_LLD(writedata)((y0 >> 8) & 0xFF); + GDISP_LLD(writedata)((y0 >> 0) & 0xFF); + GDISP_LLD(writedata)((y1 >> 8) & 0xFF); + GDISP_LLD(writedata)((y1 >> 0) & 0xFF); + GDISP_LLD(writeindex)(SSD1963_SET_COLUMN_ADDRESS); + GDISP_LLD(writedata)((x0 >> 8) & 0xFF); + GDISP_LLD(writedata)((x0 >> 0) & 0xFF); + GDISP_LLD(writedata)((x1 >> 8) & 0xFF); + GDISP_LLD(writedata)((x1 >> 0) & 0xFF); +} + +/** + * @brief Draws a pixel on the display. + * + * @param[in] x X location of the pixel + * @param[in] y Y location of the pixel + * @param[in] color The color of the pixel + * + * @notapi + */ +void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + #endif + + GDISP_LLD(setwindow)(x, y, x, y); + GDISP_LLD(writestreamstart)(); + GDISP_LLD(writedata)(color); +} + +/* ---- Optional Routines ---- */ + +#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) + /** + * @brief Fill an area with a color. + * @note Optional - The high level driver can emulate using software. + * + * @param[in] x, y The start filled area + * @param[in] cx, cy The width and height to be filled + * @param[in] color The color of the fill + * + * @notapi + */ + void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; + #endif + + uint32_t index = 0, area; + area = cx*cy; + + GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1); + GDISP_LLD(writestreamstart)(); + + for(index = 0; index < area; index++) + GDISP_LLD(writedata)(color); + } +#endif + +#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) + /** + * @brief Fill an area with a bitmap. + * @note Optional - The high level driver can emulate using software. + * + * @param[in] x, y The start filled area + * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. + * @param[in] buffer The pixels to use to fill the area. + * + * @notapi + */ + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + coord_t endx, endy; + unsigned lg; + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; } + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; + #endif + + GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1); + GDISP_LLD(writestreamstart)(); + + endx = srcx + cx; + endy = y + cy; + lg = srccx - cx; + buffer += srcx + srcy * srccx; + for(; y < endy; y++, buffer += lg) + for(x=srcx; x < endx; x++) + GDISP_LLD(writedata)(*buffer++); + } +#endif + +#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__) + /** + * @brief Scroll vertically a section of the screen. + * @note Optional. + * @note If x,y + cx,cy is off the screen, the result is undefined. + * @note If lines is >= cy, it is equivelent to a area fill with bgcolor. + * + * @param[in] x, y The start of the area to be scrolled + * @param[in] cx, cy The size of the area to be scrolled + * @param[in] lines The number of lines to scroll (Can be positive or negative) + * @param[in] bgcolor The color to fill the newly exposed area. + * + * @notapi + */ + void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; + #endif + /* NOT IMPLEMENTED YET */ + + /* + uint16_t size = x1 - x0 ; + + lld_lcdWriteIndex(SSD1963_SET_SCROLL_AREA); + lld_lcdWriteData((x0 >> 8) & 0xFF); + lld_lcdWriteData((x0 >> 0) & 0xFF); + lld_lcdWriteData((size >> 8) & 0xFF); + lld_lcdWriteData((size >> 0) & 0xFF); + lld_lcdWriteData(((lcd_height-x1) >> 8) & 0xFF); + lld_lcdWriteData(((lcd_height-x1) >> 0) & 0xFF); + + lld_lcdWriteIndex(SSD1963_SET_SCROLL_START); + lld_lcdWriteData((lines >> 8) & 0xFF); + lld_lcdWriteData((lines >> 0) & 0xFF); + */ + } + +#endif + +#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) + /** + * @brief Driver Control + * @detail Unsupported control codes are ignored. + * @note The value parameter should always be typecast to (void *). + * @note There are some predefined and some specific to the low level driver. + * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t + * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t + * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver + * that only supports off/on anything other + * than zero is on. + * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. + * GDISP_CONTROL_LLD - Low level driver control constants start at + * this value. + * + * @param[in] what What to do. + * @param[in] value The value to use (always cast to a void *). + * + * @notapi + */ + void GDISP_LLD(control)(unsigned what, void *value) { + /* NOT IMPLEMENTED YET */ + switch(what) { + case GDISP_CONTROL_POWER: + if (GDISP.Powermode == (gdisp_powermode_t)value) + return; + switch((gdisp_powermode_t)value) { + case powerOff: + GDISP_LLD(writeindex)(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode + chThdSleepMicroseconds(5000); + GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF); + GDISP_LLD(writeindex)(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode + break; + case powerOn: + GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); // 2x Dummy reads to wake up from deep sleep + GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); + if (GDISP.Powermode != powerSleep) + GDISP_LLD(init)(); + GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON); + + break; + case powerSleep: + GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF); + GDISP_LLD(writeindex)(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode + chThdSleepMicroseconds(5000); + break; + default: + return; + } + GDISP.Powermode = (gdisp_powermode_t)value; + return; + case GDISP_CONTROL_ORIENTATION: + if (GDISP.Orientation == (gdisp_orientation_t)value) + return; + switch((gdisp_orientation_t)value) { + case portrait: + /* Code here */ + GDISP.Height = SCREEN_HEIGHT; + GDISP.Width = SCREEN_WIDTH; + break; + case landscape: + /* Code here */ + GDISP.Height = SCREEN_WIDTH; + GDISP.Width = SCREEN_HEIGHT; + break; + case portraitInv: + /* Code here */ + GDISP.Height = SCREEN_HEIGHT; + GDISP.Width = SCREEN_WIDTH; + break; + case landscapeInv: + /* Code here */ + GDISP.Height = SCREEN_WIDTH; + GDISP.Width = SCREEN_HEIGHT; + break; + default: + return; + } + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width; + GDISP.clipy1 = GDISP.Height; + #endif + GDISP.Orientation = (gdisp_orientation_t)value; + return; +/* + case GDISP_CONTROL_BACKLIGHT: + case GDISP_CONTROL_CONTRAST: +*/ + } + } +#endif + +#endif /* HAL_USE_GDISP */ +/** @} */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld_config.h b/drivers/gdisp/SSD1963/gdisp_lld_config.h index 85dd7282..fc8d8489 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld_config.h +++ b/drivers/gdisp/SSD1963/gdisp_lld_config.h @@ -1,66 +1,52 @@ -/* - ChibiOS-LCD-Driver Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS-LCD-Driver. - - ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS-LCD-Driver is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file SSD1963/gdisp_lld_config.h - * @brief GDISP Graphic Driver subsystem low level driver header. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_CONFIG_H -#define _GDISP_LLD_CONFIG_H - -#if HAL_USE_GDISP || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver hardware support. */ -/*===========================================================================*/ - -#define GDISP_DRIVER_NAME "SSD1963" -#define GDISP_LLD(x) gdisp_lld_##x##_SSD1963 - -#define GDISP_HARDWARE_LINES FALSE -#define GDISP_HARDWARE_CLEARS TRUE -#define GDISP_HARDWARE_FILLS TRUE -#define GDISP_HARDWARE_BITFILLS FALSE -#define GDISP_HARDWARE_CIRCLES FALSE -#define GDISP_HARDWARE_CIRCLEFILLS FALSE -#define GDISP_HARDWARE_ELLIPSES FALSE -#define GDISP_HARDWARE_ELLIPSEFILLS FALSE -#define GDISP_HARDWARE_TEXT FALSE -#define GDISP_HARDWARE_TEXTFILLS FALSE -#define GDISP_HARDWARE_SCROLL FALSE -#define GDISP_HARDWARE_PIXELREAD FALSE -#define GDISP_HARDWARE_CONTROL FALSE -#define GDISP_HARDWARE_QUERY FALSE - -#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE -#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE - -#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 -#define GDISP_PACKED_PIXELS FALSE -#define GDISP_PACKED_LINES FALSE - -#endif /* HAL_USE_GDISP */ - -#endif /* _GDISP_LLD_CONFIG_H */ -/** @} */ +/* + ChibiOS-LCD-Driver Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS-LCD-Driver. + + ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS-LCD-Driver is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SSD1963/gdisp_lld_config.h + * @brief GDISP Graphic Driver subsystem low level driver header. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_CONFIG_H +#define _GDISP_LLD_CONFIG_H + +#if HAL_USE_GDISP || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver hardware support. */ +/*===========================================================================*/ + +#define GDISP_DRIVER_NAME "SSD1963" +#define GDISP_LLD(x) gdisp_lld_##x##_SSD1963 + +#define GDISP_HARDWARE_FILLS TRUE +#define GDISP_HARDWARE_BITFILLS TRUE +/* Maybe someday soon */ +#define GDISP_HARDWARE_SCROLL FALSE +#define GDISP_HARDWARE_CONTROL FALSE + +#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 + +#endif /* HAL_USE_GDISP */ + +#endif /* _GDISP_LLD_CONFIG_H */ +/** @} */ diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c index fd8410fb..1999d4ec 100644 --- a/drivers/gdisp/TestStub/gdisp_lld.c +++ b/drivers/gdisp/TestStub/gdisp_lld.c @@ -35,30 +35,6 @@ /* Include the emulation code for things we don't support */ #include "gdisp_emulation.c" -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - /* ---- Required Routines ---- */ /* The following 2 routines are required. @@ -78,6 +54,12 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOff; GDISP.Backlight = 100; GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif return TRUE; } @@ -94,179 +76,6 @@ void GDISP_LLD(drawpixel)(coord_t UNUSED(x), coord_t UNUSED(y), color_t UNUSED(c } /* ---- Optional Routines ---- */ -/* - All the below routines are optional. - Defining them will increase speed but everything - will work if they are not defined. - If you are not using a routine - turn it off using - the appropriate GDISP_HARDWARE_XXXX macro. - Don't bother coding for obvious similar routines if - there is no performance penalty as the emulation software - makes a good job of using similar routines. - eg. If fillarea() is defined there is little - point in defining clear() unless the - performance bonus is significant. - For good performance it is suggested to implement - fillarea() and blitarea(). -*/ - -#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__) - /** - * @brief Clear the display. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] color The color of the pixel - * - * @notapi - */ - void GDISP_LLD(clear)(color_t UNUSED(color)) { - } -#endif - -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t UNUSED(x0), coord_t UNUSED(y0), coord_t UNUSED(x1), coord_t UNUSED(y1), color_t UNUSED(color)) { - } -#endif - -#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) - /** - * @brief Fill an area with a color. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The start filled area - * @param[in] cx, cy The width and height to be filled - * @param[in] color The color of the fill - * - * @notapi - */ - void GDISP_LLD(fillarea)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(cx), coord_t UNUSED(cy), color_t UNUSED(color)) { - } -#endif - -#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) - /** - * @brief Fill an area with a bitmap. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The start filled area - * @param[in] cx, cy The width and height to be filled - * @param[in] buffer The pixels to use to fill the area. - * - * @notapi - */ - void GDISP_LLD(blitarea)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(cx), coord_t UNUSED(cy), const pixel_t *UNUSED(buffer)) { - } -#endif - -/* Circular Drawing Functions */ -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLES) || defined(__DOXYGEN__) - /** - * @brief Draw a circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(drawcircle)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(radius), color_t UNUSED(color)) { - } -#endif - -#if (GDISP_NEED_CIRCLE && GDISP_HARDWARE_CIRCLEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled circle. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the circle is over the edges of the screen. - * - * @param[in] x, y The centre of the circle - * @param[in] radius The radius of the circle - * @param[in] color The color of the circle - * - * @notapi - */ - void GDISP_LLD(fillcircle)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(radius), color_t UNUSED(color)) { - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSES) || defined(__DOXYGEN__) - /** - * @brief Draw an ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(drawellipse)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(a), coord_t UNUSED(b), color_t UNUSED(color)) { - } -#endif - -#if (GDISP_NEED_ELLIPSE && GDISP_HARDWARE_ELLIPSEFILLS) || defined(__DOXYGEN__) - /** - * @brief Create a filled ellipse. - * @note Optional - The high level driver can emulate using software. - * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave - * correctly if the ellipse is over the edges of the screen. - * - * @param[in] x, y The centre of the ellipse - * @param[in] a, b The dimensions of the ellipse - * @param[in] color The color of the ellipse - * - * @notapi - */ - void GDISP_LLD(fillellipse)(coord_t UNUSED(x), coord_t UNUSED(y), coord_t UNUSED(a), coord_t UNUSED(b), color_t UNUSED(color)) { - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a transparent background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * - * @notapi - */ - void GDISP_LLD(drawchar)(coord_t UNUSED(x), coord_t UNUSED(y), char UNUSED(c), font_t UNUSED(font), color_t UNUSED(color)) { - } -#endif - -#if (GDISP_NEED_TEXT && GDISP_HARDWARE_TEXTFILLS) || defined(__DOXYGEN__) - /** - * @brief Draw a character using a filled background. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x, y The top-left corner of the text - * @param[in] c The character to print - * @param[in] color The color of the character - * @param[in] bgcolor The background color - * - * @notapi - */ - void GDISP_LLD(fillchar)(coord_t UNUSED(x), coord_t UNUSED(y), char UNUSED(c), font_t UNUSED(font), color_t UNUSED(color), color_t UNUSED(bgcolor)) { - } -#endif #if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__) /** @@ -301,61 +110,5 @@ void GDISP_LLD(drawpixel)(coord_t UNUSED(x), coord_t UNUSED(y), color_t UNUSED(c } #endif -#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) - /** - * @brief Driver Control - * @detail Unsupported control codes are ignored. - * @note The value parameter should always be typecast to (void *). - * @note There are some predefined and some specific to the low level driver. - * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t - * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t - * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver - * that only supports off/on anything other - * than zero is on. - * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. - * GDISP_CONTROL_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to do. - * @param[in] value The value to use (always cast to a void *). - * - * @notapi - */ - void GDISP_LLD(control)(unsigned UNUSED(what), void *UNUSED(value)) { - } -#endif - -#if (GDISP_NEED_QUERY && GDISP_HARDWARE_QUERY) || defined(__DOXYGEN__) -/** - * @brief Query a driver value. - * @detail Typecase the result to the type you want. - * @note GDISP_QUERY_WIDTH - (coord_t) Gets the width of the screen - * GDISP_QUERY_HEIGHT - (coord_t) Gets the height of the screen - * GDISP_QUERY_POWER - (gdisp_powermode_t) Get the current powermode - * GDISP_QUERY_ORIENTATION - (gdisp_orientation_t) Get the current screen orientation - * GDISP_QUERY_BACKLIGHT - (coord_t) Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - (coord_t) Get the contrast (0 to 100). - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to Query - * - * @notapi - */ -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - case GDISP_QUERY_LLD+0: - /* Code here */ - default: return (void *)-1; - } -} -#endif - #endif /* HAL_USE_GDISP */ /** @} */ diff --git a/drivers/gdisp/TestStub/gdisp_lld_config.h b/drivers/gdisp/TestStub/gdisp_lld_config.h index d66e050f..b570ef39 100644 --- a/drivers/gdisp/TestStub/gdisp_lld_config.h +++ b/drivers/gdisp/TestStub/gdisp_lld_config.h @@ -38,23 +38,8 @@ #define GDISP_DRIVER_NAME "TestStub" #define GDISP_LLD(x) gdisp_lld_##x##_TestStub -#define GDISP_HARDWARE_LINES FALSE -#define GDISP_HARDWARE_CLEARS FALSE -#define GDISP_HARDWARE_FILLS FALSE -#define GDISP_HARDWARE_BITFILLS FALSE -#define GDISP_HARDWARE_CIRCLES FALSE -#define GDISP_HARDWARE_CIRCLEFILLS FALSE -#define GDISP_HARDWARE_ELLIPSES FALSE -#define GDISP_HARDWARE_ELLIPSEFILLS FALSE -#define GDISP_HARDWARE_TEXT FALSE -#define GDISP_HARDWARE_TEXTFILLS FALSE #define GDISP_HARDWARE_SCROLL GDISP_NEED_SCROLL #define GDISP_HARDWARE_PIXELREAD GDISP_NEED_PIXELREAD -#define GDISP_HARDWARE_CONTROL FALSE -#define GDISP_HARDWARE_QUERY FALSE - -#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE -#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 #define GDISP_PACKED_PIXELS FALSE diff --git a/drivers/gdisp/VMT/gdisp_lld.c b/drivers/gdisp/VMT/gdisp_lld.c index 1528f470..3e149640 100644 --- a/drivers/gdisp/VMT/gdisp_lld.c +++ b/drivers/gdisp/VMT/gdisp_lld.c @@ -49,8 +49,11 @@ bool_t GDISP_LLD1(init)(void); void GDISP_LLD1(clear)(color_t color); void GDISP_LLD1(drawpixel)(coord_t x, coord_t y, color_t color); void GDISP_LLD1(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); -void GDISP_LLD1(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer); +void GDISP_LLD1(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer); void GDISP_LLD1(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); +#if GDISP_NEED_CLIP + void GDISP_LLD1(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); +#endif #if GDISP_NEED_CIRCLE void GDISP_LLD1(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color); void GDISP_LLD1(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color); @@ -59,6 +62,10 @@ void GDISP_LLD1(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_ void GDISP_LLD1(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); void GDISP_LLD1(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); #endif +#if GDISP_NEED_ARC + void GDISP_LLD1(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + void GDISP_LLD1(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); +#endif #if GDISP_NEED_TEXT void GDISP_LLD1(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color); void GDISP_LLD1(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor); @@ -80,8 +87,11 @@ bool_t GDISP_LLD2(init)(void); void GDISP_LLD2(clear)(color_t color); void GDISP_LLD2(drawpixel)(coord_t x, coord_t y, color_t color); void GDISP_LLD2(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); -void GDISP_LLD2(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer); +void GDISP_LLD2(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer); void GDISP_LLD2(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); +#if GDISP_NEED_CLIP + void GDISP_LLD2(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); +#endif #if GDISP_NEED_CIRCLE void GDISP_LLD2(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color); void GDISP_LLD2(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color); @@ -90,6 +100,10 @@ void GDISP_LLD2(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_ void GDISP_LLD2(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); void GDISP_LLD2(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); #endif +#if GDISP_NEED_ARC + void GDISP_LLD2(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + void GDISP_LLD2(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); +#endif #if GDISP_NEED_TEXT void GDISP_LLD2(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color); void GDISP_LLD2(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor); @@ -115,7 +129,7 @@ void GDISP_LLD2(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_ void GDISP_LLD_VMT(clear)(color_t color); void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color); void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); -void GDISP_LLD_VMT(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer); +void GDISP_LLD_VMT(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer); void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); #if GDISP_NEED_CIRCLE @@ -152,6 +166,10 @@ void GDISP_LLD_VMT(control)(unsigned what, void *value); #if GDISP_NEED_QUERY void *GDISP_LLD_VMT(query)(unsigned what); #endif +/* Clipping Functions */ +#if GDISP_NEED_CLIP +void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); +#endif /*===========================================================================*/ @@ -179,7 +197,7 @@ bool_t gdisp_lld_init_VMT(void) { gdisp_lld_clear_VMT = GDISP_VMT_NAME1(gdisp_lld_clear_); gdisp_lld_drawpixel_VMT = GDISP_VMT_NAME1(gdisp_lld_drawpixel_); gdisp_lld_fillarea_VMT = GDISP_VMT_NAME1(gdisp_lld_fillarea_); - gdisp_lld_blitarea_VMT = GDISP_VMT_NAME1(gdisp_lld_blitarea_); + gdisp_lld_blitareaex_VMT = GDISP_VMT_NAME1(gdisp_lld_blitareaex_); gdisp_lld_drawline_VMT = GDISP_VMT_NAME1(gdisp_lld_drawline_); #if GDISP_NEED_CIRCLE gdisp_lld_drawcircle_VMT = GDISP_VMT_NAME1(gdisp_lld_drawcircle_); @@ -189,6 +207,10 @@ bool_t gdisp_lld_init_VMT(void) { gdisp_lld_drawellipse_VMT = GDISP_VMT_NAME1(gdisp_lld_drawellipse_); gdisp_lld_fillellipse_VMT = GDISP_VMT_NAME1(gdisp_lld_fillellipse_); #endif + #if GDISP_NEED_ARC + gdisp_lld_drawarc_VMT = GDISP_VMT_NAME1(gdisp_lld_drawarc_); + gdisp_lld_fillarc_VMT = GDISP_VMT_NAME1(gdisp_lld_fillarc_); + #endif #if GDISP_NEED_TEXT gdisp_lld_drawchar_VMT = GDISP_VMT_NAME1(gdisp_lld_drawchar_); gdisp_lld_fillchar_VMT = GDISP_VMT_NAME1(gdisp_lld_fillchar_); @@ -205,6 +227,9 @@ bool_t gdisp_lld_init_VMT(void) { #if GDISP_NEED_QUERY gdisp_lld_query_VMT = GDISP_VMT_NAME1(gdisp_lld_query_); #endif + #if GDISP_NEED_CLIP + gdisp_lld_setclip_VMT = GDISP_VMT_NAME1(gdisp_lld_setclip_); + #endif return TRUE; } @@ -213,7 +238,7 @@ bool_t gdisp_lld_init_VMT(void) { gdisp_lld_clear_VMT = GDISP_VMT_NAME2(gdisp_lld_clear_); gdisp_lld_drawpixel_VMT = GDISP_VMT_NAME2(gdisp_lld_drawpixel_); gdisp_lld_fillarea_VMT = GDISP_VMT_NAME2(gdisp_lld_fillarea_); - gdisp_lld_blitarea_VMT = GDISP_VMT_NAME2(gdisp_lld_blitarea_); + gdisp_lld_blitareaex_VMT = GDISP_VMT_NAME2(gdisp_lld_blitareaex_); gdisp_lld_drawline_VMT = GDISP_VMT_NAME2(gdisp_lld_drawline_); #if GDISP_NEED_CIRCLE gdisp_lld_drawcircle_VMT = GDISP_VMT_NAME2(gdisp_lld_drawcircle_); @@ -223,6 +248,10 @@ bool_t gdisp_lld_init_VMT(void) { gdisp_lld_drawellipse_VMT = GDISP_VMT_NAME2(gdisp_lld_drawellipse_); gdisp_lld_fillellipse_VMT = GDISP_VMT_NAME2(gdisp_lld_fillellipse_); #endif + #if GDISP_NEED_ARC + gdisp_lld_drawarc_VMT = GDISP_VMT_NAME2(gdisp_lld_drawarc_); + gdisp_lld_fillarc_VMT = GDISP_VMT_NAME2(gdisp_lld_fillarc_); + #endif #if GDISP_NEED_TEXT gdisp_lld_drawchar_VMT = GDISP_VMT_NAME2(gdisp_lld_drawchar_); gdisp_lld_fillchar_VMT = GDISP_VMT_NAME2(gdisp_lld_fillchar_); @@ -239,6 +268,9 @@ bool_t gdisp_lld_init_VMT(void) { #if GDISP_NEED_QUERY gdisp_lld_query_VMT = GDISP_VMT_NAME2(gdisp_lld_query_); #endif + #if GDISP_NEED_CLIP + gdisp_lld_setclip_VMT = GDISP_VMT_NAME2(gdisp_lld_setclip_); + #endif return TRUE; } diff --git a/drivers/gdisp/VMT/gdisp_lld_config.h b/drivers/gdisp/VMT/gdisp_lld_config.h index 6c6f7c80..6eedc23e 100644 --- a/drivers/gdisp/VMT/gdisp_lld_config.h +++ b/drivers/gdisp/VMT/gdisp_lld_config.h @@ -47,12 +47,15 @@ #define GDISP_HARDWARE_CIRCLEFILLS TRUE #define GDISP_HARDWARE_ELLIPSES TRUE #define GDISP_HARDWARE_ELLIPSEFILLS TRUE +#define GDISP_HARDWARE_ARCS TRUE +#define GDISP_HARDWARE_ARCFILLS TRUE #define GDISP_HARDWARE_TEXT TRUE #define GDISP_HARDWARE_TEXTFILLS TRUE #define GDISP_HARDWARE_SCROLL TRUE #define GDISP_HARDWARE_PIXELREAD TRUE #define GDISP_HARDWARE_CONTROL TRUE #define GDISP_HARDWARE_QUERY TRUE +#define GDISP_HARDWARE_CLIP TRUE #define GDISP_SOFTWARE_TEXTFILLDRAW FALSE #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE diff --git a/drivers/gdisp/VMT/gdisp_lld_driver1.c b/drivers/gdisp/VMT/gdisp_lld_driver1.c index f088623e..c15878b1 100644 --- a/drivers/gdisp/VMT/gdisp_lld_driver1.c +++ b/drivers/gdisp/VMT/gdisp_lld_driver1.c @@ -31,8 +31,8 @@ #if HAL_USE_GDISP || defined(__DOXYGEN__) -#define CONFIGFILE() <../GDISP_VMT_NAME1(gdisp)/gdisp_lld_config.h> -#define DRIVERFILE() <../GDISP_VMT_NAME1(gdisp)/gdisp_lld.c> +#define CONFIGFILE() <../GDISP_VMT_NAME1()/gdisp_lld_config.h> +#define DRIVERFILE() <../GDISP_VMT_NAME1()/gdisp_lld.c> /* We don't need these in our VMT referenced driver */ #undef GDISP_NEED_MSGAPI diff --git a/drivers/gdisp/VMT/gdisp_lld_driver2.c b/drivers/gdisp/VMT/gdisp_lld_driver2.c index 325a53e6..4c64ea70 100644 --- a/drivers/gdisp/VMT/gdisp_lld_driver2.c +++ b/drivers/gdisp/VMT/gdisp_lld_driver2.c @@ -31,8 +31,8 @@ #if HAL_USE_GDISP || defined(__DOXYGEN__) -#define CONFIGFILE() <../GDISP_VMT_NAME2(gdisp)/gdisp_lld_config.h> -#define DRIVERFILE() <../GDISP_VMT_NAME2(gdisp)/gdisp_lld.c> +#define CONFIGFILE() <../GDISP_VMT_NAME2()/gdisp_lld_config.h> +#define DRIVERFILE() <../GDISP_VMT_NAME2()/gdisp_lld.c> /* We don't need these in our VMT referenced driver */ #undef GDISP_NEED_MSGAPI diff --git a/include/console.h b/include/console.h index edd8498e..7a2f25e9 100644 --- a/include/console.h +++ b/include/console.h @@ -1,87 +1,53 @@ -/* - ChibiOS/RT - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS-LCD-Driver. - - ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS-LCD-Driver is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef CONSOLE_H -#define CONSOLE_H - -#include "ch.h" -#include "hal.h" - -#include "gdisp.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 */ - coord_t x0,y0; - /* current cursor position, in pixels */ - coord_t cx,cy; - /* console size in pixels */ - coord_t sx,sy; - /* foreground and background colour */ - pixel_t bkcolor, color; - /* font size in pixels */ - uint8_t fy; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -msg_t lcdConsoleInit(GLCDConsole *console, coord_t x0, coord_t y0, coord_t width, coord_t height, font_t font, pixel_t bkcolor, pixel_t color); -msg_t lcdConsolePut(GLCDConsole *console, char c); -msg_t lcdConsoleWrite(GLCDConsole *console, char *bp, size_t n); - -#ifdef __cplusplus -} -#endif - -#endif /* CONSOLE_H */ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS-LCD-Driver. + + ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS-LCD-Driver is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#ifdef HAL_USE_GDISP + +#ifndef GDISP_NEED_CONSOLE + #define GDISP_NEED_CONSOLE FALSE +#endif + +#if GDISP_NEED_CONSOLE + +#include "gdisp.h" + +/** + * @brief Structure representing a GConsole driver. + */ +typedef struct GConsole GConsole; + +#ifdef __cplusplus +extern "C" { +#endif + +msg_t lcdConsoleInit(GConsole *console, coord_t x0, coord_t y0, coord_t width, coord_t height, font_t font, pixel_t bkcolor, pixel_t color); +msg_t lcdConsolePut(GConsole *console, char c); +msg_t lcdConsoleWrite(GConsole *console, const uint8_t *bp, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* GDISP_NEED_CONSOLE */ +#endif /* HAL_USE_GDISP */ +#endif /* CONSOLE_H */ diff --git a/include/gdisp.h b/include/gdisp.h index 9e856aa9..ce864682 100644 --- a/include/gdisp.h +++ b/include/gdisp.h @@ -163,7 +163,12 @@ extern "C" { void gdispDrawPixel(coord_t x, coord_t y, color_t color); void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); - void gdispBlitArea(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer); + void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer); + + /* Clipping Functions */ + #if GDISP_NEED_CLIP + void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy); + #endif /* Circle Functions */ #if GDISP_NEED_CIRCLE @@ -177,6 +182,12 @@ extern "C" { void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); #endif + /* Arc Functions */ + #if GDISP_NEED_ARC + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + #endif + /* Basic Text Rendering Functions */ #if GDISP_NEED_TEXT void gdispDrawChar(coord_t x, coord_t y, char c, font_t font, color_t color); @@ -212,9 +223,12 @@ extern "C" { #define gdispDrawPixel(x, y, color) GDISP_LLD(drawpixel)(x, y, color) #define gdispDrawLine(x0, y0, x1, y1, color) GDISP_LLD(drawline)(x0, y0, x1, y1, color) #define gdispFillArea(x, y, cx, cy, color) GDISP_LLD(fillarea)(x, y, cx, cy, color) - #define gdispBlitArea(x, y, cx, cy, buffer) GDISP_LLD(blitarea)(x, y, cx, cy, buffer) + #define gdispBlitAreaEx(x, y, cx, cy, sx, sy, scx, buf) GDISP_LLD(blitareaex)(x, y, cx, cy, sx, sy, scx, buf) + #define gdispSetClip(x, y, cx, cy) GDISP_LLD(setclip)(x, y, cx, cy) #define gdispDrawCircle(x, y, radius, color) GDISP_LLD(drawcircle)(x, y, radius, color) #define gdispFillCircle(x, y, radius, color) GDISP_LLD(fillcircle)(x, y, radius, color) + #define gdispDrawArc(x, y, radius, sangle, eangle, color) GDISP_LLD(drawarc)(x, y, radius, sangle, eangle, color) + #define gdispFillArc(x, y, radius, sangle, eangle, color) GDISP_LLD(fillarc)(x, y, radius, sangle, eangle, color) #define gdispDrawEllipse(x, y, a, b, color) GDISP_LLD(drawellipse)(x, y, a, b, color) #define gdispFillEllipse(x, y, a, b, color) GDISP_LLD(fillellipse)(x, y, a, b, color) #define gdispDrawChar(x, y, c, font, color) GDISP_LLD(drawchar)(x, y, c, font, color) @@ -226,9 +240,11 @@ extern "C" { #endif +/* Now obsolete functions */ +#define gdispBlitArea(x, y, cx, cy, buffer) gdispBlitAreaEx(x, y, cx, cy, 0, 0, cx, buffer) + +/* Extra drawing functions */ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); -void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color); -void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color); /* Extra Text Functions */ #if GDISP_NEED_TEXT @@ -258,6 +274,10 @@ void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t #define gdispGetBacklight() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_BACKLIGHT)) #define gdispGetContrast() ((coord_t)(unsigned)gdispQuery(GDISP_QUERY_CONTRAST)) +/* More interesting macro's */ +#define gdispUnsetClip() gdispSetClip(0,0,gdispGetWidth(),gdispGetHeight()) + + #ifdef __cplusplus } #endif diff --git a/include/gdisp_emulation.c b/include/gdisp_emulation.c index cb3773a7..fc82e1b5 100644 --- a/include/gdisp_emulation.c +++ b/include/gdisp_emulation.c @@ -50,6 +50,10 @@ gdisp_powermode_t Powermode; coord_t Backlight; coord_t Contrast; + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + coord_t clipx0, clipy0; + coord_t clipx1, clipy1; /* not inclusive */ + #endif } GDISP; #endif @@ -159,33 +163,52 @@ #endif #if !GDISP_HARDWARE_BITFILLS - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { coord_t x0, x1, y1; x0 = x; x1 = x + cx; y1 = y + cy; - for(; y < y1; y++) - for(x = x0; x < x1; x++) + buffer += srcy*srccx+srcx; + srccx -= cx; + for(; y < y1; y++, buffer += srccx) + for(x=x0; x < x1; x++) GDISP_LLD(drawpixel)(x, y, *buffer++); } #endif +#if GDISP_NEED_CLIP && !GDISP_HARDWARE_CLIP + void GDISP_LLD(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy) { + #if GDISP_NEED_VALIDATION + if (x >= GDISP.Width || y >= GDISP.Height || cx < 0 || cy < 0) + return; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x+cx > GDISP.Width) cx = GDISP.Width - x; + if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #endif + GDISP.clipx0 = x; + GDISP.clipy0 = y; + GDISP.clipx1 = x+cx; + GDISP.clipy1 = y+cy; + } +#endif + #if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLES void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - int16_t a, b, P; + coord_t a, b, P; a = 0; b = radius; P = 1 - radius; do { - GDISP_LLD(drawpixel)(a+x, b+y, color); - GDISP_LLD(drawpixel)(b+x, a+y, color); - GDISP_LLD(drawpixel)(x-a, b+y, color); - GDISP_LLD(drawpixel)(x-b, a+y, color); - GDISP_LLD(drawpixel)(b+x, y-a, color); - GDISP_LLD(drawpixel)(a+x, y-b, color); + GDISP_LLD(drawpixel)(x+a, y+b, color); + GDISP_LLD(drawpixel)(x+b, y+a, color); + GDISP_LLD(drawpixel)(x-a, y+b, color); + GDISP_LLD(drawpixel)(x-b, y+a, color); + GDISP_LLD(drawpixel)(x+b, y-a, color); + GDISP_LLD(drawpixel)(x+a, y-b, color); GDISP_LLD(drawpixel)(x-a, y-b, color); GDISP_LLD(drawpixel)(x-b, y-a, color); if (P < 0) @@ -198,7 +221,7 @@ #if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLEFILLS void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - int16_t a, b, P; + coord_t a, b, P; a = 0; b = radius; @@ -275,6 +298,115 @@ } #endif +#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCS + + #include + + /* + * @brief Internal helper function for gdispDrawArc() + * + * @note DO NOT USE DIRECTLY! + * + * @param[in] x, y The middle point of the arc + * @param[in] start The start angle of the arc + * @param[in] end The end angle of the arc + * @param[in] radius The radius of the arc + * @param[in] color The color in which the arc will be drawn + * + * @notapi + */ + static void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { + if (start >= 0 && start <= 180) { + float x_maxI = x + radius*cos(start*M_PI/180); + float x_minI; + + if (end > 180) + x_minI = x - radius; + else + x_minI = x + radius*cos(end*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxI && x-a >= x_minI) + GDISP_LLD(drawpixel)(x-a, y+b, color); + if(x+a <= x_maxI && x+a >= x_minI) + GDISP_LLD(drawpixel)(x+a, y+b, color); + if(x-b <= x_maxI && x-b >= x_minI) + GDISP_LLD(drawpixel)(x-b, y+a, color); + if(x+b <= x_maxI && x+b >= x_minI) + GDISP_LLD(drawpixel)(x+b, y+a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while(a <= b); + } + + if (end > 180 && end <= 360) { + float x_maxII = x+radius*cos(end*M_PI/180); + float x_minII; + + if(start <= 180) + x_minII = x - radius; + else + x_minII = x+radius*cos(start*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxII && x-a >= x_minII) + GDISP_LLD(drawpixel)(x-a, y-b, color); + if(x+a <= x_maxII && x+a >= x_minII) + GDISP_LLD(drawpixel)(x+a, y-b, color); + if(x-b <= x_maxII && x-b >= x_minII) + GDISP_LLD(drawpixel)(x-b, y-a, color); + if(x+b <= x_maxII && x+b >= x_minII) + GDISP_LLD(drawpixel)(x+b, y-a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while (a <= b); + } + } + + void GDISP_LLD(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + if(endangle < startangle) { + _draw_arc(x, y, startangle, 360, radius, color); + _draw_arc(x, y, 0, endangle, radius, color); + } else { + _draw_arc(x, y, startangle, endangle, radius, color); + } + } +#endif + +#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCFILLS + void GDISP_LLD(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + (void)x; + (void)y; + (void)radius; + (void)startangle; + (void)endangle; + (void)color; +#warning "GDISP: FillArc Emulation Not Implemented Yet" + } +#endif + #if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT #include "gdisp_fonts.h" #endif @@ -352,7 +484,7 @@ #if GDISP_NEED_VALIDATION /* Check our buffer is big enough */ - if (height > sizeof(buf)/sizeof(buf[0])) return; + if ((unsigned)height > sizeof(buf)/sizeof(buf[0])) return; #endif ptr = _getCharData(font, c); @@ -374,7 +506,7 @@ } for(xs=0; xs < xscale; xs++) - GDISP_LLD(blitarea)(x+i+xs, y, 1, height, buf); + GDISP_LLD(blitareaex)(x+i+xs, y, 1, height, 0, 0, 1, buf); } } @@ -418,7 +550,7 @@ } /* [Patch by Badger] Write all in one stroke */ - GDISP_LLD(blitarea)(x, y, width, height, buf); + GDISP_LLD(blitareaex)(x, y, width, height, 0, 0, width, buf); } /* Method 4: Draw pixel by pixel */ @@ -492,11 +624,16 @@ void *GDISP_LLD(query)(unsigned what) { GDISP_LLD(fillarea)(msg->fillarea.x, msg->fillarea.y, msg->fillarea.cx, msg->fillarea.cy, msg->fillarea.color); break; case GDISP_LLD_MSG_BLITAREA: - GDISP_LLD(blitarea)(msg->blitarea.x, msg->blitarea.y, msg->blitarea.cx, msg->blitarea.cy, msg->blitarea.buffer); + GDISP_LLD(blitareaex)(msg->blitarea.x, msg->blitarea.y, msg->blitarea.cx, msg->blitarea.cy, msg->blitarea.srcx, msg->blitarea.srcy, msg->blitarea.srccx, msg->blitarea.buffer); break; case GDISP_LLD_MSG_DRAWLINE: GDISP_LLD(drawline)(msg->drawline.x0, msg->drawline.y0, msg->drawline.x1, msg->drawline.y1, msg->drawline.color); break; + #if GDISP_NEED_CLIP + case GDISP_LLD_MSG_SETCLIP: + GDISP_LLD(setclip)(msg->setclip.x, msg->setclip.y, msg->setclip.cx, msg->setclip.cy); + break; + #endif #if GDISP_NEED_CIRCLE case GDISP_LLD_MSG_DRAWCIRCLE: GDISP_LLD(drawcircle)(msg->drawcircle.x, msg->drawcircle.y, msg->drawcircle.radius, msg->drawcircle.color); @@ -513,6 +650,14 @@ void *GDISP_LLD(query)(unsigned what) { GDISP_LLD(fillellipse)(msg->fillellipse.x, msg->fillellipse.y, msg->fillellipse.a, msg->fillellipse.b, msg->fillellipse.color); break; #endif + #if GDISP_NEED_ARC + case GDISP_LLD_MSG_DRAWARC: + GDISP_LLD(drawcircle)(msg->drawarc.x, msg->drawarc.y, msg->drawarc.radius, msg->drawarc.startangle, msg->drawarc.endangle, msg->drawarc.color); + break; + case GDISP_LLD_MSG_FILLARC: + GDISP_LLD(fillcircle)(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color); + break; + #endif #if GDISP_NEED_TEXT case GDISP_LLD_MSG_DRAWCHAR: GDISP_LLD(drawchar)(msg->drawchar.x, msg->drawchar.y, msg->drawchar.c, msg->drawchar.font, msg->drawchar.color); diff --git a/include/gdisp_lld.h b/include/gdisp_lld.h index 91485455..3e265b47 100644 --- a/include/gdisp_lld.h +++ b/include/gdisp_lld.h @@ -69,6 +69,14 @@ #define GDISP_NEED_ELLIPSE TRUE #endif + /** + * @brief Are arc functions needed. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_ARC + #define GDISP_NEED_ARC FALSE + #endif + /** * @brief Are text functions needed. * @details Defaults to TRUE @@ -93,6 +101,14 @@ #define GDISP_NEED_PIXELREAD FALSE #endif + /** + * @brief Are clipping functions needed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_CLIP + #define GDISP_NEED_CLIP FALSE + #endif + /** * @brief Control some aspect of the drivers operation. * @details Defaults to FALSE @@ -253,6 +269,22 @@ #define GDISP_HARDWARE_ELLIPSEFILLS FALSE #endif + /** + * @brief Hardware accelerated arc's. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ARCS + #define GDISP_HARDWARE_ARCS FALSE + #endif + + /** + * @brief Hardware accelerated filled arcs. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ARCFILLS + #define GDISP_HARDWARE_ARCFILLS FALSE + #endif + /** * @brief Hardware accelerated text drawing. * @details If set to @p FALSE software emulation is used. @@ -300,6 +332,14 @@ #ifndef GDISP_HARDWARE_QUERY #define GDISP_HARDWARE_QUERY FALSE #endif + + /** + * @brief The driver supports a clipping in hardware. + * @details If set to @p FALSE there is no support for non-standard queries. + */ + #ifndef GDISP_HARDWARE_CLIP + #define GDISP_HARDWARE_CLIP FALSE + #endif /** @} */ /** @@ -543,7 +583,7 @@ extern "C" { extern void GDISP_LLD_VMT(clear)(color_t color); extern void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color); extern void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); - extern void GDISP_LLD_VMT(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer); + extern void GDISP_LLD_VMT(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer); extern void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); /* Circular Drawing Functions */ @@ -557,6 +597,12 @@ extern "C" { extern void GDISP_LLD_VMT(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); #endif + /* Arc Drawing Functions */ + #if GDISP_NEED_ARC + extern void GDISP_LLD_VMT(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + extern void GDISP_LLD_VMT(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + #endif + /* Text Rendering Functions */ #if GDISP_NEED_TEXT extern void GDISP_LLD_VMT(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color); @@ -583,6 +629,11 @@ extern "C" { extern void *GDISP_LLD_VMT(query)(unsigned what); #endif + /* Clipping Functions */ + #if GDISP_NEED_CLIP + extern void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); + #endif + /* Messaging API */ #if GDISP_NEED_MSGAPI #include "gdisp_lld_msgs.h" diff --git a/include/gdisp_lld_msgs.h b/include/gdisp_lld_msgs.h index 28a6707e..ff9d4084 100644 --- a/include/gdisp_lld_msgs.h +++ b/include/gdisp_lld_msgs.h @@ -39,6 +39,9 @@ typedef enum gdisp_msgaction { GDISP_LLD_MSG_FILLAREA, GDISP_LLD_MSG_BLITAREA, GDISP_LLD_MSG_DRAWLINE, + #if GDISP_NEED_CLIP + GDISP_LLD_MSG_SETCLIP, + #endif #if GDISP_NEED_CIRCLE GDISP_LLD_MSG_DRAWCIRCLE, GDISP_LLD_MSG_FILLCIRCLE, @@ -47,6 +50,10 @@ typedef enum gdisp_msgaction { GDISP_LLD_MSG_DRAWELLIPSE, GDISP_LLD_MSG_FILLELLIPSE, #endif + #if GDISP_NEED_ARC + GDISP_LLD_MSG_DRAWARC, + GDISP_LLD_MSG_FILLARC, + #endif #if GDISP_NEED_TEXT GDISP_LLD_MSG_DRAWCHAR, GDISP_LLD_MSG_FILLCHAR, @@ -89,8 +96,15 @@ typedef union gdisp_lld_msg { gdisp_msgaction_t action; // GDISP_LLD_MSG_BLITAREA coord_t x, y; coord_t cx, cy; + coord_t srcx, srcy; + coord_t srccx; const pixel_t *buffer; } blitarea; + struct gdisp_lld_msg_setclip { + gdisp_msgaction_t action; // GDISP_LLD_MSG_SETCLIP + coord_t x, y; + coord_t cx, cy; + } setclip; struct gdisp_lld_msg_drawline { gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWLINE coord_t x0, y0; @@ -121,6 +135,20 @@ typedef union gdisp_lld_msg { coord_t a, b; color_t color; } fillellipse; + struct gdisp_lld_msg_drawarc { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWARC + coord_t x, y; + coord_t radius; + coord_t startangle, endangle; + color_t color; + } drawcircle; + struct gdisp_lld_msg_fillarc { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLARC + coord_t x, y; + coord_t radius; + coord_t startangle, endangle; + color_t color; + } fillcircle; struct gdisp_lld_msg_drawchar { gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCHAR coord_t x, y; diff --git a/src/console.c b/src/console.c index 7805ff2e..560f827e 100644 --- a/src/console.c +++ b/src/console.c @@ -1,180 +1,219 @@ -/* - ChibiOS/RT - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS-LCD-Driver. - - ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS-LCD-Driver is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "ch.h" -#include "hal.h" - -#include "gdisp.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 uint16_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, coord_t x0, coord_t y0, coord_t width, coord_t height, font_t font, pixel_t bkcolor, pixel_t color) { - const uint8_t* ptr; - uint16_t chi; - uint16_t x,y; - - console->vmt = &vmt; - /* read font, get height */ - console->fy = gdispGetFontMetric(font, fontHeight); - - /* calculate the size of the console as an integer multiple of characters height*/ - 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; - - gdispFillArea(x0, y0, x0 + width, y0 + height, console->bkcolor); - return RDY_OK; -} - -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) - gdispFillArea(console->x0 + console->cx, console->y0 + console->cy, - console->sx - console->cx, console->fy, - 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 = gdispGetCharWidth(c, console->font) + gdispGetFontMetric(console->font, fontCharPadding); - if((console->cx + width) >= console->sx) { - /* clear the text at the end of the line */ - if (console->cy <= console->sy) - gdispFillArea(console->x0 + console->cx, console->y0 + console->cy, - console->sx - (console->cx + width), console->fy, - console->bkcolor); - console->cx = 0; - console->cy += console->fy; - } - - if((console->cy > console->sy)) { -#if GDISP_NEED_SCROLL - /* scroll the console */ - gdispVerticalScroll(console->x0, console->y0, console->sx, - console->sy + console->fy, console->fy, console->bkcolor); - /* reset the cursor to the start of the line */ - console->cx = 0; - console->cy = console->sy; -#else - /* clear the console */ - gdispFillArea(console->x0, console->y0, - console->sx, console->sy + console->fy, - console->bkcolor); - /* reset the cursor to the top of the console */ - console->cx = 0; - console->cy = 0; -#endif - } - - gdispDrawChar(console->x0 + console->cx, console->y0 + console->cy, c, - console->font, console->color); - - /* update cursor */ - console->cx += width; - } - return RDY_OK; -} - -msg_t lcdConsoleWrite(GLCDConsole *console, char *bp, size_t n) { - size_t i; - for(i = 0; i < n; i++) - lcdConsolePut(console, bp[i]); - - return RDY_OK; -} +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS-LCD-Driver. + + ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS-LCD-Driver is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if GDISP_NEED_CONSOLE + +#include "ch.h" +#include "hal.h" + +#include "console.h" + +/** + * @extends BaseAsynchronousChannelVMT + * + * @brief @p GConsole virtual methods table. + */ +struct GConsoleVMT { + _base_asynchronous_channel_methods +}; + +/** + * @extends BaseAsynchronousChannel + * + * @brief GConsole class. + * @details This class extends @p BaseAsynchronousChannel by adding physical + * I/O queues. + */ +struct GConsole { + /** @brief Virtual Methods Table.*/ + const struct GConsoleVMT *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 */ + coord_t x0,y0; + /* current cursor position, in pixels */ + coord_t cx,cy; + /* console size in pixels */ + coord_t sx,sy; + /* foreground and background colour */ + color_t bkcolor, color; + /* font size in pixels */ + uint8_t fy; + /* font inter-character padding in pixels */ + uint8_t fp; +}; + +/* + * Interface implementation. The interface is write only + */ +static size_t writes(void *ip, const uint8_t *bp, size_t n) { + return lcdConsoleWrite((GConsole *)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) { + (void)ip; + + return RDY_OK; +} + +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((GConsole *)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((GConsole *)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 ioflags_t getflags(void *ip) { + _ch_get_and_clear_flags_impl(ip); +} + +static const struct GConsoleVMT vmt = { + writes, reads, put, get, + putt, gett, writet, readt, + getflags +}; + + +msg_t lcdConsoleInit(GConsole *console, coord_t x0, coord_t y0, coord_t width, coord_t height, font_t font, pixel_t bkcolor, pixel_t color) { + console->vmt = &vmt; + /* read font, get height & padding */ + console->fy = gdispGetFontMetric(font, fontHeight); + console->fp = gdispGetFontMetric(font, fontCharPadding); + + /* calculate the size of the console as an integer multiple of characters height*/ + 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; + + gdispFillArea(x0, y0, x0 + width, y0 + height, console->bkcolor); + return RDY_OK; +} + +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) + gdispFillArea(console->x0 + console->cx, console->y0 + console->cy, + console->sx - console->cx, console->fy, + 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 = gdispGetCharWidth(c, console->font) + console->fp; + if((console->cx + width) >= console->sx) { + /* clear the text at the end of the line */ + if (console->cy <= console->sy) + gdispFillArea(console->x0 + console->cx, console->y0 + console->cy, + console->sx - (console->cx + width), console->fy, + console->bkcolor); + console->cx = 0; + console->cy += console->fy; + } + + if((console->cy > console->sy)) { +#if GDISP_NEED_SCROLL + /* scroll the console */ + gdispVerticalScroll(console->x0, console->y0, console->sx, + console->sy + console->fy, console->fy, console->bkcolor); + /* reset the cursor to the start of the line */ + console->cx = 0; + console->cy = console->sy; +#else + /* clear the console */ + gdispFillArea(console->x0, console->y0, + console->sx, console->sy + console->fy, + console->bkcolor); + /* reset the cursor to the top of the console */ + console->cx = 0; + console->cy = 0; +#endif + } + + gdispDrawChar(console->x0 + console->cx, console->y0 + console->cy, c, + console->font, console->color); + + /* update cursor */ + console->cx += width; + } + return RDY_OK; +} + +msg_t lcdConsoleWrite(GLCDConsole *console, const uint8_t *bp, size_t n) { + size_t i; + for(i = 0; i < n; i++) + lcdConsolePut(console, bp[i]); + + return RDY_OK; +} + +#endif /* GDISP_NEED_CONSOLE */ diff --git a/src/gdisp.c b/src/gdisp.c index c3b83214..41ae8778 100644 --- a/src/gdisp.c +++ b/src/gdisp.c @@ -28,7 +28,6 @@ #include "ch.h" #include "hal.h" #include "gdisp.h" -#include #ifndef _GDISP_C #define _GDISP_C @@ -329,29 +328,58 @@ * or at least retained until this call has finished the blit. You can * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE. * - * @param[in] x0,y0 The start position + * @param[in] x,y The start position * @param[in] cx,cy The size of the filled area * @param[in] buffer The bitmap in the driver's pixel format. * * @api */ - void gdispBlitArea(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { + void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { chMtxLock(&gdispMutex); - GDISP_LLD(blitarea)(x, y, cx, cy, buffer); + GDISP_LLD(blitareaex)(x, y, cx, cy, srcx, srcy, srccx, buffer); chMtxUnlock(); } #elif GDISP_NEED_ASYNC - void gdispBlitArea(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { + void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_BLITAREA); p->blitarea.x = x; p->blitarea.y = y; p->blitarea.cx = cx; p->blitarea.cy = cy; + p->blitarea.srcx = srcx; + p->blitarea.srcy = srcy; + p->blitarea.srccx = srccx; p->blitarea.buffer = buffer; chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE); } #endif +#if (GDISP_NEED_CLIP && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__) + /** + * @brief Clip all drawing to the defined area. + * @pre The GDISP unit must be in powerOn or powerSleep mode. + * + * @param[in] x,y The start position + * @param[in] cx,cy The size of the clip area + * + * @api + */ + void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { + chMtxLock(&gdispMutex); + GDISP_LLD(setclip)(x, y, cx, cy); + chMtxUnlock(); + } +#elif GDISP_NEED_CLIP && GDISP_NEED_ASYNC + void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { + gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_SETCLIP); + p->setclip.x = x; + p->setclip.y = y; + p->setclip.cx = cx; + p->setclip.cy = cy; + chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE); + } +#endif + #if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__) /** * @brief Draw a circle. @@ -462,6 +490,66 @@ } #endif +#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__) + /** + * @brief Draw an arc. + * @pre The GDISP unit must be in powerOn or powerSleep mode. + * + * @param[in] x,y The center of the arc circle + * @param[in] radius The radius of the arc circle + * @param[in] startangle, endangle The start and end angle in degrees (0 to 359) + * @param[in] color The color to use + * + * @api + */ + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + chMtxLock(&gdispMutex); + GDISP_LLD(drawarc)(x, y, radius, startangle, endangle, color); + chMtxUnlock(); + } +#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC); + p->drawarc.x = x; + p->drawarc.y = y; + p->drawarc.radius = radius; + p->drawarc.startangle = startangle; + p->drawarc.endangle = endangle; + p->drawarc.color = color; + chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE); + } +#endif + +#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__) + /** + * @brief Draw a filled arc. + * @pre The GDISP unit must be in powerOn or powerSleep mode. + * + * @param[in] x,y The center of the arc circle + * @param[in] radius The radius of the arc circle + * @param[in] startangle, endangle The start and end angle in degrees (0 to 359) + * @param[in] color The color to use + * + * @api + */ + void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + chMtxLock(&gdispMutex); + GDISP_LLD(fillarc)(x, y, radius, startangle, endangle, color); + chMtxUnlock(); + } +#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC + void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC); + p->fillarc.x = x; + p->fillarc.y = y; + p->fillarc.radius = radius; + p->fillarc.startangle = startangle; + p->fillarc.endangle = endangle; + p->fillarc.color = color; + chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE); + } +#endif + #if (GDISP_NEED_TEXT && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__) /** * @brief Draw a text character. @@ -659,131 +747,6 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } } -/* - * @brief Internal helper function for gdispDrawArc() - * - * @note DO NOT USE DIRECTLY! - * - * @param[in] x, y The middle point of the arc - * @param[in] start The start angle of the arc - * @param[in] end The end angle of the arc - * @param[in] radius The radius of the arc - * @param[in] color The color in which the arc will be drawn - * - * @notapi - */ -void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { - if (start >= 0 && start <= 180) { - float x_maxI = x + radius*cos(start*M_PI/180); - float x_minI; - - if (end > 180) - x_minI = x - radius; - else - x_minI = x + radius*cos(end*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxI && x-a >= x_minI) - gdispDrawPixel(x-a, y+b, color); - if(x+a <= x_maxI && x+a >= x_minI) - gdispDrawPixel(x+a, y+b, color); - if(x-b <= x_maxI && x-b >= x_minI) - gdispDrawPixel(x-b, y+a, color); - if(x+b <= x_maxI && x+b >= x_minI) - gdispDrawPixel(x+b, y+a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while(a <= b); - } - - if (end > 180 && end <= 360) { - float x_maxII = x+radius*cos(end*M_PI/180); - float x_minII; - - if(start <= 180) - x_minII = x - radius; - else - x_minII = x+radius*cos(start*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxII && x-a >= x_minII) - gdispDrawPixel(x-a, y-b, color); - if(x+a <= x_maxII && x+a >= x_minII) - gdispDrawPixel(x+a, y-b, color); - if(x-b <= x_maxII && x-b >= x_minII) - gdispDrawPixel(x-b, y-a, color); - if(x+b <= x_maxII && x+b >= x_minII) - gdispDrawPixel(x+b, y-a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while (a <= b); - } -} - -/* - * @brief Draw an arc. - * @pre The GDISP must be in powerOn or powerSleep mode. - * - * @param[in] x0,y0 The center point - * @param[in] radius The radius of the arc - * @param[in] start The start angle (0 to 360) - * @param[in] end The end angle (0 to 360) - * @param[in] color The color of the arc - * - * @api - */ -void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { - if(end < start) { - _draw_arc(x, y, start, 360, radius, color); - _draw_arc(x, y, 0, end, radius, color); - } else { - _draw_arc(x, y, start, end, radius, color); - } -} - -/* - * @brief Draw a filled arc. - * @pre The GDISP must be in powerOn or powerSleep mode. - * - * @param[in] x0,y0 The center point of the filled arc - * @param[in] radius The radius of the filled arc - * @param[in] start The start angle (0 to 360) - * @param[in] end The end angle (0 to 360) - * @param[in] color The color of the filled arc - * - * @api - */ -void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { - /* ToDo */ - (void)x; - (void)y; - (void)radius; - (void)start; - (void)end; - (void)color; -} #if GDISP_NEED_TEXT || defined(__DOXYGEN__) /** diff --git a/templates/gdispXXXXX/gdisp_lld.c b/templates/gdispXXXXX/gdisp_lld.c index 81e96894..26052e98 100644 --- a/templates/gdispXXXXX/gdisp_lld.c +++ b/templates/gdispXXXXX/gdisp_lld.c @@ -35,23 +35,7 @@ /* Include the emulation code for things we don't support */ #include "gdisp_emulation.c" -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if GDISP_NEED_TEXT +#if GDISP_NEED_TEXT && GDISP_HARDWARE_TEXT #include "gdisp_fonts.h" #endif @@ -95,6 +79,12 @@ bool_t GDISP_LLD(init)(void) { GDISP.Powermode = powerOn; GDISP.Backlight = 100; GDISP.Contrast = 50; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width-1; + GDISP.clipy1 = GDISP.Height-1; + #endif return TRUE; } @@ -108,8 +98,8 @@ bool_t GDISP_LLD(init)(void) { * @notapi */ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; #endif /* Code here */ } @@ -157,8 +147,8 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - #if GDISP_NEED_VALIDATION - /* Need to clip to screen */ + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + /* Code here */ #endif /* Code here */ } @@ -176,10 +166,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif /* Code here */ } @@ -192,15 +184,20 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * * @param[in] x, y The start filled area * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. * @param[in] buffer The pixels to use to fill the area. * * @notapi */ - void GDISP_LLD(blitarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, const pixel_t *buffer) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) return; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + void GDISP_LLD(blitareaex)(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; } + if (srcx+cx > srccx) cx = srccx - srcx; + if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy -= GDISP.clipy1 - y; #endif /* Code here */ } @@ -221,7 +218,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -242,7 +239,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -263,7 +260,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -284,7 +281,52 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + /* Code here */ + #endif + /* Code here */ + } +#endif + +/* Arc Drawing Functions */ +#if (GDISP_NEED_ARC && GDISP_HARDWARE_ARCS) || defined(__DOXYGEN__) + /** + * @brief Draw an arc. + * @note Optional - The high level driver can emulate using software. + * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave + * correctly if the circle is over the edges of the screen. + * + * @param[in] x, y The centre of the arc circle + * @param[in] radius The radius of the arc circle + * @param[in] startangle, endangle The start and end angles for the arc (0..359) + * @param[in] color The color of the circle + * + * @notapi + */ + void GDISP_LLD(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + /* Code here */ + #endif + /* Code here */ + } +#endif + +#if (GDISP_NEED_ARC && GDISP_HARDWARE_ARCFILLS) || defined(__DOXYGEN__) + /** + * @brief Create a filled arc. + * @note Optional - The high level driver can emulate using software. + * @note If GDISP_NEED_CLIPPING is defined this routine MUST behave + * correctly if the circle is over the edges of the screen. + * + * @param[in] x, y The centre of the arc circle + * @param[in] radius The radius of the arc circle + * @param[in] startangle, endangle The start and end angles for the arc (0..359) + * @param[in] color The color of the circle + * + * @notapi + */ + void GDISP_LLD(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -303,7 +345,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -323,7 +365,7 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - #if GDISP_NEED_VALIDATION + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP /* Code here */ #endif /* Code here */ @@ -342,8 +384,8 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height) return 0; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; #endif /* Code here */ } @@ -364,10 +406,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { * @notapi */ void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - #if GDISP_NEED_VALIDATION - if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } + if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } + if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + if (x+cx > GDISP.clipx1) cx -= GDISP.clipx1 - x; + if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; #endif /* Code here */ } @@ -444,6 +488,12 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { default: return; } + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + GDISP.clipx0 = 0; + GDISP.clipy0 = 0; + GDISP.clipx1 = GDISP.Width; + GDISP.clipy1 = GDISP.Height; + #endif GDISP.Orientation = (gdisp_orientation_t)value; return; /* @@ -486,5 +536,23 @@ void *GDISP_LLD(query)(unsigned what) { } #endif +#if GDISP_NEED_CLIP && GDISP_HARDWARE_CLIP + void GDISP_LLD(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy) { + #if GDISP_NEED_VALIDATION + if (x >= GDISP.Width || y >= GDISP.Height || cx < 0 || cy < 0) + return; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x+cx > GDISP.Width) cx = GDISP.Width - x; + if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #endif + GDISP.clipx0 = x; + GDISP.clipy0 = y; + GDISP.clipx1 = x+cx; + GDISP.clipy1 = y+cy; + /* Code here to set hardware clipping */ + } +#endif + #endif /* HAL_USE_GDISP */ /** @} */ diff --git a/templates/gdispXXXXX/gdisp_lld_config.h b/templates/gdispXXXXX/gdisp_lld_config.h index 81a6826f..191c4c3e 100644 --- a/templates/gdispXXXXX/gdisp_lld_config.h +++ b/templates/gdispXXXXX/gdisp_lld_config.h @@ -46,12 +46,15 @@ #define GDISP_HARDWARE_CIRCLEFILLS FALSE #define GDISP_HARDWARE_ELLIPSES FALSE #define GDISP_HARDWARE_ELLIPSEFILLS FALSE +#define GDISP_HARDWARE_ARCS FALSE +#define GDISP_HARDWARE_ARCFILLS FALSE #define GDISP_HARDWARE_TEXT FALSE #define GDISP_HARDWARE_TEXTFILLS FALSE #define GDISP_HARDWARE_SCROLL FALSE #define GDISP_HARDWARE_PIXELREAD FALSE #define GDISP_HARDWARE_CONTROL FALSE #define GDISP_HARDWARE_QUERY FALSE +#define GDISP_HARDWARE_CLIP FALSE #define GDISP_SOFTWARE_TEXTFILLDRAW FALSE #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE