diff options
author | Joel Bodenmann <joel@unormal.org> | 2013-06-22 03:09:45 +0200 |
---|---|---|
committer | Joel Bodenmann <joel@unormal.org> | 2013-06-22 03:09:45 +0200 |
commit | 6107cd79180603660374c626da15e70ac4f26a5e (patch) | |
tree | 298be8a4a4f9f43470dddf0f8e222d2b0914c21a /drivers/gdisp/RA8875/gdisp_lld.c | |
parent | 1f7a9166d51c94b3a729bac6dd1db38e7b2868f8 (diff) | |
download | uGFX-6107cd79180603660374c626da15e70ac4f26a5e.tar.gz uGFX-6107cd79180603660374c626da15e70ac4f26a5e.tar.bz2 uGFX-6107cd79180603660374c626da15e70ac4f26a5e.zip |
Added RA8875 GDISP driver
Diffstat (limited to 'drivers/gdisp/RA8875/gdisp_lld.c')
-rw-r--r-- | drivers/gdisp/RA8875/gdisp_lld.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c new file mode 100644 index 00000000..e04e5dba --- /dev/null +++ b/drivers/gdisp/RA8875/gdisp_lld.c @@ -0,0 +1,460 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://chibios-gfx.com/license.html + */ + +/** + * @file drivers/gdisp/RA8875/gdisp_lld.c + * @brief GDISP Graphics Driver subsystem low level driver source. + * + * @addtogroup GDISP + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gfx.h" + +#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ + +/* Include the emulation code for things we don't support */ +#include "gdisp/lld/emulation.c" + +#include "ra8875.h" + +/* include the board abstraction */ +#include "gdisp_lld_board.h" + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + + +/* ---- 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 */ + init_board(); + + /* soft reset */ + write_index(0x01); + write_data(0x01); + write_data(0x00); + chThdSleepMilliseconds(1); + + /* Driver PLL config 480x272*/ + write_index(0x88); + write_data(0x08); + chThdSleepMilliseconds(1); + write_index(0x89); + write_data(0x02); + chThdSleepMilliseconds(1); + + write_index(0x10); //SYSR bit[4:3]=00 256 color bit[2:1]= 00 8bit MPU interface + write_data(0x0F); // if 16bit MCU interface and 65k color display + + write_index(0x04); //set PCLK invers + write_data(0x82); + chThdSleepMilliseconds(1); + + //Horizontal set + write_index(0x14); //HDWR//Horizontal Display Width Setting Bit[6:0] + write_data(0x3B);//Horizontal display width(pixels) = (HDWR + 1)*8 + write_index(0x15); //Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) + write_data(0x00);//Horizontal Non-Display Period Fine Tuning(HNDFT) [3:0] + write_index(0x16); //HNDR//Horizontal Non-Display Period Bit[4:0] + write_data(0x01);//Horizontal Non-Display Period (pixels) = (HNDR + 1)*8 + write_index(0x17); //HSTR//HSYNC Start Position[4:0] + write_data(0x00);//HSYNC Start Position(PCLK) = (HSTR + 1)*8 + write_index(0x18); //HPWR//HSYNC Polarity ,The period width of HSYNC. + write_data(0x05);//HSYNC Width [4:0] HSYNC Pulse width(PCLK) = (HPWR + 1)*8 + + //Vertical set + write_index(0x19); //VDHR0 //Vertical Display Height Bit [7:0] + write_data(0x0f); //Vertical pixels = VDHR + 1 + write_index(0x1a); //VDHR1 //Vertical Display Height Bit [8] + write_data(0x01); //Vertical pixels = VDHR + 1 + write_index(0x1b); //VNDR0 //Vertical Non-Display Period Bit [7:0] + write_data(0x02); //VSYNC Start Position(PCLK) = (VSTR + 1) + write_index(0x1c); //VNDR1 //Vertical Non-Display Period Bit [8] + write_data(0x00); //Vertical Non-Display area = (VNDR + 1) + write_index(0x1d); //VSTR0 //VSYNC Start Position[7:0] + write_data(0x07);//VSYNC Start Position(PCLK) = (VSTR + 1) + write_index(0x1e); //VSTR1 //VSYNC Start Position[8] + write_data(0x00);//VSYNC Start Position(PCLK) = (VSTR + 1) + write_index(0x1f); //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0] + write_data(0x09); //VSYNC Pulse Width(PCLK) = (VPWR + 1) + + //Active window set + //setting active window X + write_index(0x30); //Horizontal Start Point 0 of Active Window (HSAW0) + write_data(0x00); //Horizontal Start Point of Active Window [7:0] + write_index(0x31); //Horizontal Start Point 1 of Active Window (HSAW1) + write_data(0x00); //Horizontal Start Point of Active Window [9:8] + write_index(0x34); //Horizontal End Point 0 of Active Window (HEAW0) + write_data(0xDF); //Horizontal End Point of Active Window [7:0] + write_index(0x35); //Horizontal End Point 1 of Active Window (HEAW1) + write_data(0x01); //Horizontal End Point of Active Window [9:8] + + //setting active window Y + write_index(0x32); //Vertical Start Point 0 of Active Window (VSAW0) + write_data(0x00); //Vertical Start Point of Active Window [7:0] + write_index(0x33); //Vertical Start Point 1 of Active Window (VSAW1) + write_data(0x00); //Vertical Start Point of Active Window [8] + write_index(0x36); //Vertical End Point of Active Window 0 (VEAW0) + write_data(0x0F); //Vertical End Point of Active Window [7:0] + write_index(0x37); //Vertical End Point of Active Window 1 (VEAW1) + write_data(0x01); //Vertical End Point of Active Window [8] + + // Display ON + write_index(0x01); //PWRR + write_data(0x80); + + // GPO0 DISP high + write_index(0x13); //GPO + write_data(0x01); + + set_backlight(0x80); //set to 90% brightness + + post_init_board(); + + /* Initialise the GDISP structure to match */ + GDISP.Width = GDISP_SCREEN_WIDTH; + GDISP.Height = GDISP_SCREEN_HEIGHT; + GDISP.Orientation = GDISP_ROTATE_0; + 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; + GDISP.clipy1 = GDISP.Height; + #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 + */ + + //setting active window X + write_index(0x30); //HSAW0 + write_data(x0); + write_index(0x31); //HSAW1 + write_data(x0>>8); + + write_index(0x34); //HEAW0 + write_data(x1); + write_index(0x35); //HEAW1 + write_data(x1>>8); + + //setting active window Y + write_index(0x32); //VSAW0 + write_data(y0); + write_index(0x33); //VSAW1 + write_data(y0>>8); + + write_index(0x36); //VEAW0 + write_data(y1); + write_index(0x37); //VEAW1 + write_data(y1>>8); + + write_index(0x46); + write_data(x0); + write_index(0x47); + write_data(x0>>8); + + write_index(0x48); + write_data(y0); + write_index(0x49); + write_data(y0>>8); +} + +/** + * @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_draw_pixel(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); + write_index(RA8875_WRITE_MEMORY_START); + write_data(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_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + uint32_t 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; + + gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1); + write_index(RA8875_WRITE_MEMORY_START); + + #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM) + uint8_t i; + dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color); + dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M); + for (i = area/65535; i; i--) { + dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535); + dmaStreamEnable(GDISP_DMA_STREAM); + dmaWaitCompletion(GDISP_DMA_STREAM); + } + dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535); + dmaStreamEnable(GDISP_DMA_STREAM); + dmaWaitCompletion(GDISP_DMA_STREAM); + #else + uint32_t index; + for(index = 0; index < area; index++) + write_data(color); + #endif //#ifdef GDISP_USE_DMA +} +#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_blit_area_ex(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 + + gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1); + write_index(RA8875_WRITE_MEMORY_START); + + buffer += srcx + srcy * srccx; + + #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM) + uint32_t area = cx*cy; + uint8_t i; + dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer); + dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M); + for (i = area/65535; i; i--) { + dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535); + dmaStreamEnable(GDISP_DMA_STREAM); + dmaWaitCompletion(GDISP_DMA_STREAM); + } + dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535); + dmaStreamEnable(GDISP_DMA_STREAM); + dmaWaitCompletion(GDISP_DMA_STREAM); + #else + coord_t endx, endy; + uint32_t lg; + endx = srcx + cx; + endy = y + cy; + lg = srccx - cx; + for(; y < endy; y++, buffer += lg) + for(x=srcx; x < endx; x++) + write_data(*buffer++); + #endif //#ifdef GDISP_USE_DMA + } +#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_vertical_scroll(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 ; + + write_index(SSD1963_SET_SCROLL_AREA); + write_data((x0 >> 8) & 0xFF); + write_data((x0 >> 0) & 0xFF); + write_data((size >> 8) & 0xFF); + write_data((size >> 0) & 0xFF); + write_data(((lcd_height-x1) >> 8) & 0xFF); + write_data(((lcd_height-x1) >> 0) & 0xFF); + + write_index(SSD1963_SET_SCROLL_START); + write_data((lines >> 8) & 0xFF); + write_data((lines >> 0) & 0xFF); + */ + } + +#endif + +#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) + /** + * @brief Driver Control + * @details 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: + write_index(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode + chThdSleepMilliseconds(5); + write_index(SSD1963_SET_DISPLAY_OFF); + write_index(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode + break; + case powerOn: + read_reg(0x0000); chThdSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep + read_reg(0x0000); chThdSleepMilliseconds(5); + if (GDISP.Powermode != powerSleep) + gdisp_lld_init(); + write_index(SSD1963_SET_DISPLAY_ON); + + break; + case powerSleep: + write_index(SSD1963_SET_DISPLAY_OFF); + write_index(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode + chThdSleepMilliseconds(5); + 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 GDISP_ROTATE_0: + /* Code here */ + GDISP.Height = GDISP_SCREEN_HEIGHT; + GDISP.Width = GDISP_SCREEN_WIDTH; + break; + case GDISP_ROTATE_90: + /* Code here */ + GDISP.Height = GDISP_SCREEN_WIDTH; + GDISP.Width = GDISP_SCREEN_HEIGHT; + break; + case GDISP_ROTATE_180: + /* Code here */ + GDISP.Height = GDISP_SCREEN_HEIGHT; + GDISP.Width = GDISP_SCREEN_WIDTH; + break; + case GDISP_ROTATE_270: + /* Code here */ + GDISP.Height = GDISP_SCREEN_WIDTH; + GDISP.Width = GDISP_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: + gdisp_lld_bg_dimmer(54 + ((uint8_t)value) << 1);//turn 0..100% in 54..255 + return; +/* + case GDISP_CONTROL_CONTRAST: +*/ + } + } +#endif + +#endif /* GFX_USE_GDISP */ +/** @} */ + |