diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h new file mode 100644 index 00000000..0d675833 --- /dev/null +++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h @@ -0,0 +1,102 @@ +/* + * 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://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/RA8875/gdisp_lld_board_marlin.h + * @brief GDISP Graphic Driver subsystem board interface for the RA8875 display. + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +// For a multiple display configuration we would put all this in a structure and then +// set g->priv to that structure. +#define GDISP_RAM (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */ +#define GDISP_REG (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */ +#define FSMC_BANK 4 + + +static inline void init_board(GDisplay *g, unsigned display) { + + // As we are not using multiple displays we set g->priv to NULL as we don't use it. + g->priv = 0; + + if (display == 0) { + + /** + * Set up for Display 0 + */ + + /* set pins to FSMC mode */ + IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (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}; + + IOBus busG = {GPIOG, (1 << 10), 0}; + + palSetBusMode(&busD, PAL_MODE_ALTERNATE(12)); + palSetBusMode(&busE, PAL_MODE_ALTERNATE(12)); + palSetBusMode(&busG, PAL_MODE_ALTERNATE(12)); + + /* 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; + } +} + +static inline void post_init_board(GDisplay *g) { + (void) g; + + /* FSMC delay reduced as the controller now runs at full speed */ + FSMC_Bank1->BTCR[2+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ; + FSMC_Bank1->BTCR[2] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; +} + +static inline void release_bus(GDisplay *g) { + (void) g; +} + +static inline void write_index(GDisplay *g, uint16_t index) { + (void) g; + GDISP_REG = index; +} + +static inline void write_data(GDisplay *g, uint16_t data) { + (void) g; + GDISP_RAM = data; +} + +static inline void setreadmode(GDisplay *g) { + (void) g; +} + +static inline void setwritemode(GDisplay *g) { + (void) g; +} + +static inline uint16_t read_data(GDisplay *g) { + (void) g; + return GDISP_RAM; +} + +#endif /* _GDISP_LLD_BOARD_H */ diff --git a/drivers/gdisp/RA8875/board_RA8875_template.h b/drivers/gdisp/RA8875/board_RA8875_template.h new file mode 100644 index 00000000..f60067f2 --- /dev/null +++ b/drivers/gdisp/RA8875/board_RA8875_template.h @@ -0,0 +1,140 @@ +/* + * 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://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/SSD1963/gdisp_lld_board_template.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +/** + * @brief Initialise the board for the display. + * + * @param[in] g The GDisplay structure + * @param[in] display The display number on this controller (0..n) + * + * @note Set the g->priv member to whatever is appropriate. For multiple + * displays this might be a pointer to the appropriate register set. + * + * @notapi + */ +static inline void init_board(GDisplay *g, unsigned display) { +} + +/** + * @brief After the initialisation. + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void post_init_board(GDisplay *g) { +} + +/** + * @brief Set or clear the lcd reset pin. + * + * @param[in] g The GDisplay structure + * @param[in] state TRUE = lcd in reset, FALSE = normal operation + * + * @notapi + */ +static inline void setpin_reset(GDisplay *g, bool_t state) { + +} + +/** + * @brief Take exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void acquire_bus(GDisplay *g) { + +} + +/** + * @brief Release exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void release_bus(GDisplay *g) { + +} + +/** + * @brief Send data to the index register. + * + * @param[in] g The GDisplay structure + * @param[in] index The index register to set + * + * @notapi + */ +static inline void write_index(GDisplay *g, uint16_t index) { + +} + +/** + * @brief Send data to the lcd. + * + * @param[in] g The GDisplay structure + * @param[in] data The data to send + * + * @notapi + */ +static inline void write_data(GDisplay *g, uint16_t data) { + +} + +/** + * @brief Set the bus in read mode + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void setreadmode(GDisplay *g) { + +} + +/** + * @brief Set the bus back into write mode + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void setwritemode(GDisplay *g) { + +} + +/** + * @brief Read data from the lcd. + * @return The data from the lcd + * + * @param[in] g The GDisplay structure + * + * @note The chip select may need to be asserted/de-asserted + * around the actual spi read + * + * @notapi + */ +static inline uint16_t read_data(GDisplay *g) { + +} + +#endif /* _GDISP_LLD_BOARD_H */ +/** @} */ + diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c index 397c933a..b8072f51 100644 --- a/drivers/gdisp/RA8875/gdisp_lld.c +++ b/drivers/gdisp/RA8875/gdisp_lld.c @@ -8,22 +8,98 @@ /** * @file drivers/gdisp/RA8875/gdisp_lld.c * @brief GDISP Graphics Driver subsystem low level driver source. - * - * @addtogroup GDISP - * @{ */ #include "gfx.h" #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ -/* Include the emulation code for things we don't support */ -#include "gdisp/lld/emulation.c" +#define GDISP_DRIVER_VMT GDISPVMT_RA8875 +#include "../drivers/gdisp/RA8875/gdisp_lld_config.h" +#include "gdisp/lld/gdisp_lld.h" -#include "ra8875.h" +/* include the users board interface */ +#include "board_ra8875.h" -/* include the board abstraction */ -#include "gdisp_lld_board.h" +/* include our hardware definitions */ +#include "../drivers/gdisp/RA8875/ra8875.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#ifndef GDISP_SCREEN_HEIGHT + #define GDISP_SCREEN_HEIGHT 272 +#endif +#ifndef GDISP_SCREEN_WIDTH + #define GDISP_SCREEN_WIDTH 480 +#endif +#ifndef GDISP_INITIAL_CONTRAST + #define GDISP_INITIAL_CONTRAST 50 +#endif +#ifndef GDISP_INITIAL_BACKLIGHT + #define GDISP_INITIAL_BACKLIGHT 74 +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +// Some common routines and macros +#define dummy_read(g) { volatile uint16_t dummy; dummy = read_data(g); (void) dummy; } +#define write_reg8(g, reg, data) { write_index(g, reg); write_data(g, data); } +#define write_reg16(g, reg, data) { write_index(g, reg); write_data(g, data); write_index(g, reg+1); write_data(g, (data)>>8); } +#define write_reg8x2(g, reg, d1, d2) { write_index(g, reg); write_data(g, d1); write_data(g, d2); } + +static inline void set_cursor(GDisplay *g) { + write_reg16(g, 0x46, g->p.x); + write_reg16(g, 0x48, g->p.y); + write_index(g, RA8875_WRITE_MEMORY_START); +} + +static inline void set_viewport(GDisplay* g) { + write_reg16(g, 0x30, g->p.x); //HSAW0 & HSAW1 + write_reg16(g, 0x34, g->p.x+g->p.cx-1); //HEAW0 & HEAW1 + write_reg16(g, 0x32, g->p.y); //VSAW0 & VSAW1 + write_reg16(g, 0x36, g->p.y+g->p.cy-1); //VEAW0 & VEAW1 +} + +// On this controller the back-light is controlled by the controllers internal PWM +// which is why it is in this file rather than the board file. +static inline void set_backlight(GDisplay* g, uint8_t percent) { + uint8_t temp; + + //Work in progress: the RA8875 has a built-in PWM, its output can + //be used by a Dynamic Background Control or by a host (user) + + // Enable PWM1 + write_index(g, 0x8a); //MCLR + setreadmode(g); + temp = read_data(g); + setwritemode(g); + temp |= 1<<7 ; + write_data(g, temp); + + // PWM1 function select + write_index(g, 0x8a); //MCLR + setreadmode(g); + temp = read_data(g); + setwritemode(g); + temp &= ~(1<<4); + write_data(g, temp); + + // PWM1 Clock ratio + write_index(g, 0x8a); //MCLR + setreadmode(g); + temp = read_data(g); + setwritemode(g); + temp &= 0xf0; + temp |= 0x0b & 0x0f; + write_data(g, temp); + + // PWM1 Write duty cycle + write_reg8(g, 0x8b, 54+percent); // PTNO: Also change percent to range from 0x00 to 0xFF +} /*===========================================================================*/ /* Driver interrupt handlers. */ @@ -33,417 +109,175 @@ /* Driver exported functions. */ /*===========================================================================*/ +LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) { + /* Initialise your display */ + init_board(g, display); -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. -*/ + // Hardware reset + setpin_reset(g, TRUE); + gfxSleepMilliseconds(20); + setpin_reset(g, FALSE); + gfxSleepMilliseconds(20); -/** - * @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(); + // Get the bus for the following initialisation commands + acquire_bus(g); - /* soft reset */ - write_index(0x01); - write_data(0x01); - write_data(0x00); - gfxSleepMilliseconds(1); + // Soft reset + write_reg8x2(g, 0x01, 0x01, 0x00); gfxSleepMilliseconds(1); - /* Driver PLL config 480x272*/ - write_index(0x88); - write_data(0x08); - gfxSleepMilliseconds(1); - write_index(0x89); - write_data(0x02); - gfxSleepMilliseconds(1); + // PLL config + write_reg8(g, 0x88, 0x08); gfxSleepMilliseconds(1); + write_reg8(g, 0x89, 0x02); gfxSleepMilliseconds(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_reg8(g, 0x10, 0x0F); //SYSR bit[4:3]=00 256 color bit[2:1]= 00 8bit MPU interface + // 0x0F = 16bit MCU interface and 65k color display - write_index(0x04); //set PCLK invers - write_data(0x82); - gfxSleepMilliseconds(1); + write_reg8(g, 0x04, 0x82); gfxSleepMilliseconds(1); //set PCLK inverse - //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 + // Horizontal set + write_reg8(g, 0x14, GDISP_SCREEN_WIDTH/8-1); //HDWR: Horizontal Display Width Setting Bit[6:0] - pixels = (HDWR + 1)*8 + write_reg8(g, 0x15, 0x00); //Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) - HNDFT = [3:0] + write_reg8(g, 0x16, 0x01); //HNDR: Horizontal Non-Display Period Bit[4:0] - pixels = (HNDR + 1)*8 + write_reg8(g, 0x17, 0x00); //HSTR: HSYNC Start Position[4:0] - Position(PCLK) = (HSTR + 1)*8 + write_reg8(g, 0x18, 0x05); //HPWR: HSYNC Polarity, The period width of HSYNC. Width [4:0] 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) + // Vertical set + write_reg16(g, 0x19, GDISP_SCREEN_HEIGHT-1); //VDHR0,1: Vertical Display Height = VDHR + 1 + write_reg16(g, 0x1b, 0x0002); //VNDR0,1: Vertical Non-Display Period Bit = (VSTR + 1) + write_reg16(g, 0x1d, 0x0007); //VSTR0,1: VSYNC Start Position = (VSTR + 1) + write_reg8(g, 0x1f, 0x09); //VPWR: VSYNC Polarity, VSYNC Pulse Width[6:0] - 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] + // Active window set + write_reg16(g, 0x30, 0); //HSAW0 & HSAW1 + write_reg16(g, 0x34, GDISP_SCREEN_WIDTH-1); //HEAW0 & HEAW1 + write_reg16(g, 0x32, 0); //VSAW0 & VSAW1 + write_reg16(g, 0x36, GDISP_SCREEN_HEIGHT-1); //VEAW0 & VEAW1 // Display ON - write_index(0x01); //PWRR - write_data(0x80); + write_reg8(g, 0x01, 0x80); //PWRR // GPO0 DISP high - write_index(0x13); //GPO - write_data(0x01); + write_reg8(g, 0x13, 0x01); //GPO - set_backlight(0x80); //set to 90% brightness + // Set initial back-light + set_backlight(g, GDISP_INITIAL_BACKLIGHT); - post_init_board(); + // Change timings for faster access + post_init_board(g); - /* 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 + // Release the bus + release_bus(g); + /* Initialise the GDISP structure */ + g->g.Width = GDISP_SCREEN_WIDTH; + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Orientation = GDISP_ROTATE_0; + g->g.Powermode = powerOn; + g->g.Backlight = GDISP_INITIAL_BACKLIGHT; + g->g.Contrast = GDISP_INITIAL_CONTRAST; 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 +#if GDISP_HARDWARE_STREAM_WRITE + LLDSPEC void gdisp_lld_write_start(GDisplay *g) { + acquire_bus(g); + set_viewport(g); + } + LLDSPEC void gdisp_lld_write_color(GDisplay *g) { + write_data(g, g->p.color); + } + LLDSPEC void gdisp_lld_write_stop(GDisplay *g) { + release_bus(g); + } + LLDSPEC void gdisp_lld_write_pos(GDisplay *g) { + set_cursor(g); } #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) { +#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL + LLDSPEC void gdisp_lld_control(GDisplay *g) { + switch(g->p.x) { + #if 0 case GDISP_CONTROL_POWER: - if (GDISP.Powermode == (gdisp_powermode_t)value) + if (g->g.Powermode == (powermode_t)g->p.ptr) + return; + switch((powermode_t)g->p.ptr) { + case powerOff: + acquire_bus(g); + // TODO + release_bus(g); + break; + case powerOn: + acquire_bus(g); + // TODO + release_bus(g); + break; + case powerSleep: + acquire_bus(g); + // TODO + release_bus(g); + break; + default: return; - switch((gdisp_powermode_t)value) { - case powerOff: - /* ToDo */ - break; - case powerOn: - /* ToDo */ - break; - case powerSleep: - /* ToDo */ - break; - default: - return; } - GDISP.Powermode = (gdisp_powermode_t)value; + g->g.Powermode = (powermode_t)g->p.ptr; return; + #endif + + #if 0 case GDISP_CONTROL_ORIENTATION: - if (GDISP.Orientation == (gdisp_orientation_t)value) + if (g->g.Orientation == (orientation_t)g->p.ptr) + return; + switch((orientation_t)g->p.ptr) { + case GDISP_ROTATE_0: + acquire_bus(g); + // TODO + release_bus(g); + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Width = GDISP_SCREEN_WIDTH; + break; + case GDISP_ROTATE_90: + acquire_bus(g); + // TODO + release_bus(g); + g->g.Height = GDISP_SCREEN_WIDTH; + g->g.Width = GDISP_SCREEN_HEIGHT; + break; + case GDISP_ROTATE_180: + acquire_bus(g); + // TODO + release_bus(g); + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Width = GDISP_SCREEN_WIDTH; + break; + case GDISP_ROTATE_270: + acquire_bus(g); + // TODO + release_bus(g); + g->g.Height = GDISP_SCREEN_WIDTH; + g->g.Width = GDISP_SCREEN_HEIGHT; + break; + default: 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; + g->g.Orientation = (orientation_t)value; return; - case GDISP_CONTROL_BACKLIGHT: - set_backlight((uint8_t )value); - //gdisp_lld_bg_dimmer(54 + ((uint8_t)value) << 1);//turn 0..100% in 54..255 - return; -/* - case GDISP_CONTROL_CONTRAST: -*/ + #endif + + case GDISP_CONTROL_BACKLIGHT: + if ((unsigned)g->p.ptr > 100) + g->p.ptr = (void *)100; + acquire_bus(g); + set_backlight(g, (unsigned)g->p.ptr); + release_bus(g); + g->g.Backlight = (unsigned)g->p.ptr; + return; + + //case GDISP_CONTROL_CONTRAST: + default: + return; } } #endif #endif /* GFX_USE_GDISP */ -/** @} */ - diff --git a/drivers/gdisp/RA8875/gdisp_lld.mk b/drivers/gdisp/RA8875/gdisp_lld.mk index 471b7e83..7ac03624 100644 --- a/drivers/gdisp/RA8875/gdisp_lld.mk +++ b/drivers/gdisp/RA8875/gdisp_lld.mk @@ -1,6 +1,2 @@ -# List the required driver. -GFXSRC += $(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld.c - -# Required include directories GFXINC += $(GFXLIB)/drivers/gdisp/RA8875 - +GFXSRC += $(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld.c diff --git a/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h b/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h deleted file mode 100644 index 072ba32e..00000000 --- a/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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://ugfx.org/license.html - */ - -/** - * @file drivers/gdisp/RA8875/gdisp_lld_board_marlin.h - * @brief GDISP Graphic Driver subsystem board interface for the RA8875 display. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/* Using FSMC A16 as RS */ -#define GDISP_RAM (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */ -#define GDISP_REG (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */ - -/** - * @brief Send data to the index register. - * - * @param[in] index The index register to set - * - * @notapi - */ -static inline void write_index(uint16_t index) { - GDISP_REG = index; -} - -/** - * @brief Send data to the lcd. - * - * @param[in] data The data to send - * - * @notapi - */ -static inline void write_data(uint16_t data) { - GDISP_RAM = data; -} - -/** - * @brief Read data from the lcd. - * - * @return The data from the lcd - * @note The chip select may need to be asserted/de-asserted - * around the actual spi read - * - * @notapi - */ -static inline uint16_t read_data(void) { - return GDISP_RAM; -} - -/** - * @brief Initialise the board for the display. - * @notes Performs the following functions: - * 1. initialise the io port used by your display - * 2. initialise the reset pin (initial state not-in-reset) - * 3. initialise the chip select pin (initial state not-active) - * 4. initialise the backlight pin (initial state back-light off) - * - * @notapi - */ -static inline void init_board(void) { - const unsigned char FSMC_Bank = 4; - - #if defined(STM32F1XX) || defined(STM32F3XX) - /* FSMC setup for F1/F3 */ - rccEnableAHB(RCC_AHBENR_FSMCEN, 0); - - #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM) - #error "DMA not implemented for F1/F3 Devices" - #endif - #elif defined(STM32F4XX) || defined(STM32F2XX) - /* STM32F2-F4 FSMC init */ - rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0); - - #if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM) - if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) chSysHalt(); - dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM); - dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M); - #endif - #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 << 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}; - - IOBus busG = {GPIOG, (1 << 10), 0}; - - palSetBusMode(&busD, PAL_MODE_ALTERNATE(12)); - palSetBusMode(&busE, PAL_MODE_ALTERNATE(12)); - palSetBusMode(&busG, PAL_MODE_ALTERNATE(12)); - - /* 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; -} - -static inline void post_init_board(void) { - const unsigned char FSMC_Bank = 2; - /* 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; -} - -/** - * @brief Set or clear the lcd reset pin. - * - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * - * @notapi - */ -static inline void setpin_reset(bool_t state) { - (void) state; - /* Nothing to do here */ -} - -/** - * @brief Set the lcd back-light level. - * - * @param[in] percent 0 to 100% - * - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - - //duty_cycle is 00..FF - //Work in progress: the RA8875 has a built-in PWM, its output can - //be used by a Dynamic Background Control or by a host (user) - - uint8_t temp, temp1; - // Enable PWM1 - write_index(0x8a);//MCLR - temp = read_data(); - temp |= 1<<7 ; - write_data(temp); - - // PWM1 function select - write_index(0x8a);//MCLR - temp = read_data(); - temp &= ~(1<<4); - write_data(temp); - - // PWM1 Clock ratio - temp1= 0x0b&0x0f; - write_index(0x8a);//MCLR - temp = read_data(); - temp &= 0xf0; - temp |= temp1 ; - write_data(temp); - - // Write duty cycle - write_index(0x8b);//PTNO - write_data(percent); - // PWM1 duty cycle -} - -/** - * @brief Take exclusive control of the bus - * - * @notapi - */ -static inline void acquire_bus(void) { - /* Nothing to do here */ -} - -/** - * @brief Release exclusive control of the bus - * - * @notapi - */ -static inline void release_bus(void) { - /* Nothing to do here */ -} - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/RA8875/gdisp_lld_board_template.h b/drivers/gdisp/RA8875/gdisp_lld_board_template.h deleted file mode 100644 index a11c11ab..00000000 --- a/drivers/gdisp/RA8875/gdisp_lld_board_template.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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://ugfx.org/license.html - */ - -/** - * @file drivers/gdisp/SSD1963/gdisp_lld_board_template.h - * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/** - * @brief Send data to the index register. - * - * @param[in] index The index register to set - * - * @notapi - */ -static inline void write_index(uint16_t index) { - -} - -/** - * @brief Send data to the lcd. - * - * @param[in] data The data to send - * - * @notapi - */ -static inline void write_data(uint16_t data) { - -} - -/** - * @brief Initialise the board for the display. - * - * @notapi - */ -static inline void init_board(void) { - -} - -static inline void post_init_board(void) { - -} - -/** - * @brief Set or clear the lcd reset pin. - * - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * - * @notapi - */ -static inline void setpin_reset(bool_t state) { - -} - -/** - * @brief Set the lcd back-light level. - * - * @param[in] percent 0 to 100% - * - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - -} - -/** - * @brief Take exclusive control of the bus - * - * @notapi - */ -static inline void acquire_bus(void) { - -} - -/** - * @brief Release exclusive control of the bus - * - * @notapi - */ -static inline void release_bus(void) { - -} - -__inline void write_stream(uint16_t *buffer, uint16_t size) { - -} - -__inline void read_stream(uint16_t *buffer, size_t size) { - -} - -#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__) -/** - * @brief Read data from the lcd. - * - * @return The data from the lcd - * @note The chip select may need to be asserted/de-asserted - * around the actual spi read - * - * @notapi - */ -static inline uint16_t read_data(void) { - -} -#endif - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/RA8875/gdisp_lld_config.h b/drivers/gdisp/RA8875/gdisp_lld_config.h index f49c3e03..ae290245 100644 --- a/drivers/gdisp/RA8875/gdisp_lld_config.h +++ b/drivers/gdisp/RA8875/gdisp_lld_config.h @@ -22,14 +22,9 @@ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "RA8875" - -#define GDISP_HARDWARE_FILLS TRUE -#define GDISP_HARDWARE_BITFILL TRUE -#define GDISP_HARDWARE_READPIXEL TRUE - -/* Maybe someday soon */ -#define GDISP_HARDWARE_SCROLL FALSE +#define GDISP_HARDWARE_STREAM_WRITE TRUE +#define GDISP_HARDWARE_STREAM_READ TRUE +#define GDISP_HARDWARE_STREAM_POS TRUE #define GDISP_HARDWARE_CONTROL TRUE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565