Merge pull request #5 from Tectu/master

Pull Tectu Changes
ugfx_release_2.6
Andrew Hannam 2012-09-06 16:00:59 -07:00
commit b8dcccb551
9 changed files with 1147 additions and 7 deletions

View File

@ -6,6 +6,8 @@ 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

View File

@ -4,4 +4,6 @@
*** 0.1.0 ***
FIX: removed gdisp and touchpad prefix of driver directories
UPDATE: added SSD1289 driver (by Mobyfab)

View File

@ -0,0 +1,771 @@
/*
ChibiOS-LCD-Driver - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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_1 | 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 */
/** @} */

View File

@ -0,0 +1,5 @@
# List the required driver.
LCDSRC += $(LCDLIB)/drivers/gdisp/SSD1963/gdisp_lld.c
# Required include directories
LCDINC += $(LCDLIB)/drivers/gdisp/SSD1963

View File

@ -0,0 +1,66 @@
/*
ChibiOS-LCD-Driver Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,53 @@
/*
ChibiOS-LCD-Driver Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file SSD1963/gdisp_lld_panel.h
* @brief TFT LCD panel properties.
*
* @addtogroup GDISP
* @{
*/
#ifndef _GDISP_LLD_PANEL_H
#define _GDISP_LLD_PANEL_H
/* LCD panel specs */
#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 272
#define SCREEN_FPS 60ULL
#define SCREEN_HSYNC_BACK_PORCH 2LL
#define SCREEN_HSYNC_FRONT_PORCH 2ULL
#define SCREEN_HSYNC_PULSE 41ULL
#define SCREEN_VSYNC_BACK_PORCH 2ULL
#define SCREEN_VSYNC_FRONT_PORCH 2ULL
#define SCREEN_VSYNC_PULSE 10ULL
#define SCREEN_HSYNC_PERIOD (SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH + SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH)
#define SCREEN_VSYNC_PERIOD (SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH + SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH)
#define SCREEN_PCLK (SCREEN_HSYNC_PERIOD * SCREEN_VSYNC_PERIOD * SCREEN_FPS)
#define LCD_FPR ((SCREEN_PCLK * 1048576)/100000000)
#endif
/** @} */

View File

@ -0,0 +1,12 @@
To use this driver:
1. Add in your halconf.h:
a) #define HAL_USE_GDISP TRUE
b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
c) One (only) of:
#define LCD_USE_GPIO (Work in progress)
#define LCD_USE_FSMC
d) Edit gdisp_lld_panel.h with your panel properties
2. To your makefile add the following lines:
include $(LCDLIB)/drivers/gdisp/SSD1963/gdisp_lld.mk

View File

@ -0,0 +1,141 @@
/*
ChibiOS-LCD-Driver - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file SSD1963/ssd1963.h
* @brief SSD1963 specific data.
*
* @addtogroup GDISP
* @{
*/
#ifndef SSD1963_H
#define SSD1963_H
#include "gdisp_lld_panel.h"
#if defined(LCD_USE_GPIO)
#define Set_CS palSetPad(LCD_CMD_PORT, LCD_CS);
#define Clr_CS palClearPad(LCD_CMD_PORT, LCD_CS);
#define Set_RS palSetPad(LCD_CMD_PORT, LCD_RS);
#define Clr_RS palClearPad(LCD_CMD_PORT, LCD_RS);
#define Set_WR palSetPad(LCD_CMD_PORT, LCD_WR);
#define Clr_WR palClearPad(LCD_CMD_PORT, LCD_WR);
#define Set_RD palSetPad(LCD_CMD_PORT, LCD_RD);
#define Clr_RD palClearPad(LCD_CMD_PORT, LCD_RD);
#endif
#if defined(LCD_USE_FSMC)
/* Using FSMC A16 as RS */
#define LCD_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
#define LCD_RAM (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
#endif
#define mHIGH(x) (x >> 8)
#define mLOW(x) (x & 0xFF)
/* SSD1963 commands */
#define SSD1963_NOP 0x0000
#define SSD1963_SOFT_RESET 0x0001
#define SSD1963_GET_POWER_MODE 0x000A
#define SSD1963_GET_ADDRESS_MODE 0x000B
#define SSD1963_GET_DISPLAY_MODE 0x000D
#define SSD1963_GET_TEAR_EFFECT_STATUS 0x000E
#define SSD1963_ENTER_SLEEP_MODE 0x0010
#define SSD1963_EXIT_SLEEP_MODE 0x0011
#define SSD1963_ENTER_PARTIAL_MODE 0x0012
#define SSD1963_ENTER_NORMAL_MODE 0x0013
#define SSD1963_EXIT_INVERT_MODE 0x0020
#define SSD1963_ENTER_INVERT_MODE 0x0021
#define SSD1963_SET_GAMMA_CURVE 0x0026
#define SSD1963_SET_DISPLAY_OFF 0x0028
#define SSD1963_SET_DISPLAY_ON 0x0029
#define SSD1963_SET_COLUMN_ADDRESS 0x002A
#define SSD1963_SET_PAGE_ADDRESS 0x002B
#define SSD1963_WRITE_MEMORY_START 0x002C
#define SSD1963_READ_MEMORY_START 0x002E
#define SSD1963_SET_PARTIAL_AREA 0x0030
#define SSD1963_SET_SCROLL_AREA 0x0033
#define SSD1963_SET_TEAR_OFF 0x0034
#define SSD1963_SET_TEAR_ON 0x0035
#define SSD1963_SET_ADDRESS_MODE 0x0036
#define SSD1963_SET_SCROLL_START 0x0037
#define SSD1963_EXIT_IDLE_MODE 0x0038
#define SSD1963_ENTER_IDLE_MODE 0x0039
#define SSD1963_SET_PIXEL_FORMAT 0x003A
#define SSD1963_WRITE_MEMORY_CONTINUE 0x003C
#define SSD1963_READ_MEMORY_CONTINUE 0x003E
#define SSD1963_SET_TEAR_SCANLINE 0x0044
#define SSD1963_GET_SCANLINE 0x0045
#define SSD1963_READ_DDB 0x00A1
#define SSD1963_SET_LCD_MODE 0x00B0
#define SSD1963_GET_LCD_MODE 0x00B1
#define SSD1963_SET_HORI_PERIOD 0x00B4
#define SSD1963_GET_HORI_PERIOD 0x00B5
#define SSD1963_SET_VERT_PERIOD 0x00B6
#define SSD1963_GET_VERT_PERIOD 0x00B7
#define SSD1963_SET_GPIO_CONF 0x00B8
#define SSD1963_GET_GPIO_CONF 0x00B9
#define SSD1963_SET_GPIO_VALUE 0x00BA
#define SSD1963_GET_GPIO_STATUS 0x00BB
#define SSD1963_SET_POST_PROC 0x00BC
#define SSD1963_GET_POST_PROC 0x00BD
#define SSD1963_SET_PWM_CONF 0x00BE
#define SSD1963_GET_PWM_CONF 0x00BF
#define SSD1963_GET_LCD_GEN0 0x00C0
#define SSD1963_SET_LCD_GEN0 0x00C1
#define SSD1963_GET_LCD_GEN1 0x00C2
#define SSD1963_SET_LCD_GEN1 0x00C3
#define SSD1963_GET_LCD_GEN2 0x00C4
#define SSD1963_SET_LCD_GEN2 0x00C5
#define SSD1963_GET_LCD_GEN3 0x00C6
#define SSD1963_SET_LCD_GEN3 0x00C7
#define SSD1963_SET_GPIO0_ROP 0x00C8
#define SSD1963_GET_GPIO0_ROP 0x00C9
#define SSD1963_SET_GPIO1_ROP 0x00CA
#define SSD1963_GET_GPIO1_ROP 0x00CB
#define SSD1963_SET_GPIO2_ROP 0x00CC
#define SSD1963_GET_GPIO2_ROP 0x00CD
#define SSD1963_SET_GPIO3_ROP 0x00CE
#define SSD1963_GET_GPIO3_ROP 0x00CF
#define SSD1963_SET_DBC_CONF 0x00D0
#define SSD1963_GET_DBC_CONF 0x00D1
#define SSD1963_SET_DBC_TH 0x00D4
#define SSD1963_GET_DBC_TH 0x00D5
#define SSD1963_SET_PLL 0x00E0
#define SSD1963_SET_PLL_MN 0x00E2
#define SSD1963_GET_PLL_MN 0x00E3
#define SSD1963_GET_PLL_STATUS 0x00E4
#define SSD1963_SET_DEEP_SLEEP 0x00E5
#define SSD1963_SET_LSHIFT_FREQ 0x00E6
#define SSD1963_GET_LSHIFT_FREQ 0x00E7
#define SSD1963_SET_PIXEL_DATA_INTERFACE 0x00F0
#define SSD1963_PDI_8BIT 0
#define SSD1963_PDI_12BIT 1
#define SSD1963_PDI_16BIT 2
#define SSD1963_PDI_16BIT565 3
#define SSD1963_PDI_18BIT 4
#define SSD1963_PDI_24BIT 5
#define SSD1963_PDI_9BIT 6
#define SSD1963_GET_PIXEL_DATA_INTERFACE 0x00F1
#endif
/** @} */

View File

@ -659,6 +659,89 @@ 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.
@ -672,12 +755,11 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
* @api
*/
void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
uint16_t i;
float step = 0.01;
for(i = 0; i <= (int)((abs(end-start)) / step); i++) {
gdispDrawPixel( ((float)x + (float)radius * cosf((float)start * M_PI / 180.0f) + (float)i * step * M_PI / 180.0f),
((float)y + (float)radius * sinf((float)start * M_PI / 180.0f) + (float)i * step * M_PI / 180.0f), 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);
}
}
@ -694,7 +776,13 @@ void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t
* @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__)