diff --git a/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h b/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h new file mode 100644 index 00000000..6c7119a4 --- /dev/null +++ b/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h @@ -0,0 +1,105 @@ +/* + * 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/SSD1963/board_SSD1963_fsmc.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +static const LCD_Parameters DisplayTimings[] = { + // You need one of these array elements per display + { + 480, 272, // Panel width and height + 2, 2, 41, // Horizontal Timings (back porch, front porch, pulse) + CALC_PERIOD(480,2,2,41), // Total Horizontal Period (calculated from above line) + 2, 2, 10, // Vertical Timings (back porch, front porch, pulse) + CALC_PERIOD(272,2,2,10), // Total Vertical Period (calculated from above line) + CALC_FPR(480,272,2,2,41,2,2,10,60ULL) // FPR - the 60ULL is the frames per second. Note the ULL! + }, +}; + +// For a multiple display configuration we would put all this in a structure and then +// set g->board to that structure. + +/* Using FSMC A16 as RS */ +#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */ +#define GDISP_RAM (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */ + +static inline void init_board(GDisplay *g) { + + // As we are not using multiple displays we set g->board to NULL as we don't use it. + g->board = 0; + + switch(g->controllerdisplay) { + case 0: // Set up for Display 0 + #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)); + + /* FSMC timing */ + FSMC_Bank1->BTCR[0+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[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; + break; + } +} + +static inline void post_init_board(GDisplay *g) { + (void) g; + /* FSMC delay reduced as the controller now runs at full speed */ + FSMC_Bank1->BTCR[0+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ; + FSMC_Bank1->BTCR[0] = 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; +} + +#endif /* _GDISP_LLD_BOARD_H */ + diff --git a/drivers/gdisp/SSD1963/board_SSD1963_gpio.h b/drivers/gdisp/SSD1963/board_SSD1963_gpio.h new file mode 100644 index 00000000..0b9c0135 --- /dev/null +++ b/drivers/gdisp/SSD1963/board_SSD1963_gpio.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://chibios-gfx.com/license.html + */ + +/** + * @file drivers/gdisp/SSD1963/board_SSD1963_gpio.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +static const LCD_Parameters DisplayTimings[] = { + // You need one of these array elements per display + { + 480, 272, // Panel width and height + 2, 2, 41, // Horizontal Timings (back porch, front porch, pulse) + CALC_PERIOD(480,2,2,41), // Total Horizontal Period (calculated from above line) + 2, 2, 10, // Vertical Timings (back porch, front porch, pulse) + CALC_PERIOD(272,2,2,10), // Total Vertical Period (calculated from above line) + CALC_FPR(480,272,2,2,41,2,2,10,60ULL) // FPR - the 60ULL is the frames per second. Note the ULL! + }, +}; + +// For a multiple display configuration we would put all this in a structure and then +// set g->board to that structure. + +/** + * @brief The GPIO pin config + * + * @details This block of defines tell your driver how you wired your display + * controller to your MCU. Please change them accordingly. + */ +#define GDISP_CMD_PORT GPIOC +#define GDISP_DATA_PORT GPIOD +#define GDISP_CS 0 +#define GDISP_RS 1 +#define GDISP_WR 2 +#define GDISP_RD 3 + +#define Set_CS palSetPad(GDISP_CMD_PORT, GDISP_CS); +#define Clr_CS palClearPad(GDISP_CMD_PORT, GDISP_CS); +#define Set_RS palSetPad(GDISP_CMD_PORT, GDISP_RS); +#define Clr_RS palClearPad(GDISP_CMD_PORT, GDISP_RS); +#define Set_WR palSetPad(GDISP_CMD_PORT, GDISP_WR); +#define Clr_WR palClearPad(GDISP_CMD_PORT, GDISP_WR); +#define Set_RD palSetPad(GDISP_CMD_PORT, GDISP_RD); +#define Clr_RD palClearPad(GDISP_CMD_PORT, GDISP_RD); + +static inline void init_board(GDisplay *g) { + + // As we are not using multiple displays we set g->board to NULL as we don't use it. + g->board = 0; + + switch(g->controllerdisplay) { + case 0: // Set up for Display 0 + IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0}; + IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0}; + palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL); + palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL); + break; + } +} + +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; + Set_CS; +} + +static inline void release_bus(GDisplay *g) { + (void) g; + Clr_CS; +} + +static inline void write_index(GDisplay *g, uint16_t index) { + (void) g; + Set_RS; Clr_RD; Set_WR; + palWritePort(GDISP_DATA_PORT, index); + Clr_WR; +} + +static inline void write_data(GDisplay *g, uint16_t data) { + (void) g; + Clr_RS; Clr_RD; Set_WR; + palWritePort(GDISP_DATA_PORT, data); + Clr_WR; +} + +#endif /* _GDISP_LLD_BOARD_H */ + diff --git a/drivers/gdisp/SSD1963/board_SSD1963_template.h b/drivers/gdisp/SSD1963/board_SSD1963_template.h new file mode 100644 index 00000000..5e1999b8 --- /dev/null +++ b/drivers/gdisp/SSD1963/board_SSD1963_template.h @@ -0,0 +1,148 @@ +/* + * 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/board_SSD1963_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 LCD panel specs + * + * @note The timings need to follow the datasheet for your particular TFT/LCD screen + * (the actual screen, not the controller). + * @note Datasheets normally use a specific set of timings and acronyms, their value refers + * to the number of pixel clocks. Non-display periods refer to pulses/timings that occur + * before or after the timings that actually put pixels on the screen. Display periods + * refer to pulses/timings that directly put pixels on the screen. + * @note HDP: Horizontal Display Period, normally the width - 1
+ * HT: Horizontal Total period (display + non-display)
+ * HPS: non-display period between the start of the horizontal sync (LLINE) signal + * and the first display data
+ * LPS: horizontal sync pulse (LLINE) start location in pixel clocks
+ * HPW: Horizontal sync Pulse Width
+ * VDP: Vertical Display period, normally height - 1
+ * VT: Vertical Total period (display + non-display)
+ * VPS: non-display period in lines between the start of the frame and the first display + * data in number of lines
+ * FPS: vertical sync pulse (LFRAME) start location in lines.
+ * VPW: Vertical sync Pulse Width + * @note Here's how to convert them:
+ * SCREEN_HSYNC_FRONT_PORCH = ( HT - HPS ) - GDISP_SCREEN_WIDTH
+ * SCREEN_HSYNC_PULSE = HPW
+ * SCREEN_HSYNC_BACK_PORCH = HPS - HPW
+ * SCREEN_VSYNC_FRONT_PORCH = ( VT - VPS ) - GDISP_SCREEN_HEIGHT
+ * SCREEN_VSYNC_PULSE = VPW
+ * SCREEN_VSYNC_BACK_PORCH = VPS - LPS
+ */ + +static const LCD_Parameters DisplayTimings[] = { + // You need one of these array elements per display + { + 480, 272, // Panel width and height + 2, 2, 41, // Horizontal Timings (back porch, front porch, pulse) + CALC_PERIOD(480,2,2,41), // Total Horizontal Period (calculated from above line) + 2, 2, 10, // Vertical Timings (back porch, front porch, pulse) + CALC_PERIOD(272,2,2,10), // Total Vertical Period (calculated from above line) + CALC_FPR(480,272,2,2,41,2,2,10,60ULL) // FPR - the 60ULL is the frames per second. Note the ULL! + }, +}; + +/** + * @brief Initialise the board for the display. + * + * @param[in] g The GDisplay structure + * + * @note Set the g->board 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) { + (void) g; +} + +/** + * @brief After the initialisation. + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void post_init_board(GDisplay *g) { + (void) 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) { + (void) g; + (void) state; +} + +/** + * @brief Take exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void acquire_bus(GDisplay *g) { + (void) g; +} + +/** + * @brief Release exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void release_bus(GDisplay *g) { + (void) 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) { + (void) g; + (void) 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) { + (void) g; + (void) data; +} + +#endif /* _GDISP_LLD_BOARD_H */ +/** @} */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c index 39889731..11240568 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld.c +++ b/drivers/gdisp/SSD1963/gdisp_lld.c @@ -8,24 +8,81 @@ /** * @file drivers/gdisp/SSD1963/gdisp_lld.c * @brief GDISP Graphics Driver subsystem low level driver source. - * - * @addtogroup GDISP - * @{ */ #include "gfx.h" -#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ +#if GFX_USE_GDISP -/* Include the emulation code for things we don't support */ -#include "gdisp/lld/emulation.c" +#define GDISP_DRIVER_VMT GDISPVMT_SSD1963 +#include "../drivers/gdisp/SSD1963/gdisp_lld_config.h" +#include "gdisp/lld/gdisp_lld.h" + +#define CALC_PERIOD(w,b,f,p) (p+b+w+f) +#define CALC_FPR(w,h,hb,hf,hp,vb,vf,vp,fps) ((fps * CALC_PERIOD(w,hb,hf,hp) * CALC_PERIOD(h,vb,vf,vp) * 1048576)/100000000) + +typedef struct LCD_Parameters { + coord_t width, height; // Panel width and height + uint16_t hbporch; // Horizontal Back Porch + uint16_t hfporch; // Horizontal Front Porch + uint16_t hpulse; // Horizontal Pulse + uint16_t hperiod; // Horizontal Period (Total) + uint16_t vbporch; // Vertical Back Porch + uint16_t vfporch; // Vertical Front Porch + uint16_t vpulse; // Vertical Pulse + uint16_t vperiod; // Vertical Period (Total) + uint32_t fpr; // Calculated FPR +} LCD_Parameters; + +#include "board_SSD1963.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#ifndef GDISP_INITIAL_CONTRAST + #define GDISP_INITIAL_CONTRAST 50 +#endif +#ifndef GDISP_INITIAL_BACKLIGHT + #define GDISP_INITIAL_BACKLIGHT 90 +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ #include "ssd1963.h" -/* 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. +#define write_reg(g, reg, data) { write_index(g, reg); write_data(g, data); } +#define write_data16(g, data) { write_data(g, (data)>>8); write_data(g, (data) & 0xFF); } + +static inline void set_viewport(GDisplay* g) { + write_index(g, SSD1963_SET_PAGE_ADDRESS); + write_data16(g, g->p.y); + write_data16(g, g->p.y+g->p.cy-1); + write_index(g, SSD1963_SET_COLUMN_ADDRESS); + write_data16(g, g->p.x); + write_data16(g, g->p.x+g->p.cx-1); + write_index(g, SSD1963_WRITE_MEMORY_START); +} + +/** + * The backlight is controlled by the controller. */ -#include "gdisp_lld_board.h" +static inline void set_backlight(GDisplay *g, uint8_t percent) { + //duty_cycle is 00..FF + //Work in progress: the SSD1963 has a built-in PWM, its output can + //be used by a Dynamic Background Control or by a host (user) + //Check your LCD's hardware, the PWM connection is default left open and instead + //connected to a LED connection on the breakout board + write_index(g, SSD1963_SET_PWM_CONF); //set PWM for BackLight + write_data(g, 0x01); + write_data(g, (55+percent*2) & 0x00FF); + write_data(g, 0x01); //controlled by host (not DBC), enabled + write_data(g, 0xFF); + write_data(g, 0x60); //don't let it go too dark, avoid a useless LCD + write_data(g, 0x0F); //prescaler ??? +} /*===========================================================================*/ /* Driver interrupt handlers. */ @@ -35,393 +92,194 @@ /* Driver exported functions. */ /*===========================================================================*/ +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + LCD_Parameters * lcdp; -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. -*/ + // The private area for this controller is the LCD timings + lcdp = (void *)&DisplayTimings[g->controllerdisplay]; + g->priv = lcdp; -/** - * @brief Low level GDISP driver initialisation. - * @return TRUE if successful, FALSE on error. - * - * @notapi - */ -bool_t gdisp_lld_init(void) { - /* Initialise the display */ + // Initialise the board interface + init_board(g); - init_board(); + // Hardware reset + setpin_reset(g, TRUE); + gfxSleepMilliseconds(20); + setpin_reset(g, FALSE); + gfxSleepMilliseconds(20); + + // Get the bus for the following initialisation commands + acquire_bus(g); - write_index(SSD1963_SOFT_RESET); - gfxSleepMicroseconds(100); + write_index(g, SSD1963_SOFT_RESET); + gfxSleepMilliseconds(5); /* Driver PLL config */ - write_index(SSD1963_SET_PLL_MN); - write_data(35); // PLLclk = REFclk (10Mhz) * 36 (360Mhz) - write_data(2); // SYSclk = PLLclk / 3 (120MHz) - write_data(4); // Apply calculation bit, else it is ignored - - write_index(SSD1963_SET_PLL); // Enable PLL - write_data(0x01); - gfxSleepMicroseconds(200); - - write_index(SSD1963_SET_PLL); // Use PLL - write_data(0x03); - gfxSleepMicroseconds(200); - - write_index(SSD1963_SOFT_RESET); - gfxSleepMicroseconds(100); + write_index(g, SSD1963_SET_PLL_MN); + write_data(g, 35); // PLLclk = REFclk (10Mhz) * 36 (360Mhz) + write_data(g, 2); // SYSclk = PLLclk / 3 (120MHz) + write_data(g, 4); // Apply calculation bit, else it is ignored + write_reg(g, SSD1963_SET_PLL, 0x01); // Enable PLL + gfxSleepMilliseconds(5); + write_reg(g, SSD1963_SET_PLL, 0x03); // Use PLL + gfxSleepMilliseconds(5); + write_index(g, SSD1963_SOFT_RESET); + gfxSleepMilliseconds(5); /* Screen size */ - write_index(SSD1963_SET_GDISP_MODE); -// write_data(0x0000); - write_data(0b00011000); //Enabled dithering - write_data(0x0000); - write_data(mHIGH((GDISP_SCREEN_WIDTH+1))); - write_data((GDISP_SCREEN_WIDTH+1)); - write_data(mHIGH((GDISP_SCREEN_HEIGHT+1))); - write_data((GDISP_SCREEN_HEIGHT+1)); - write_data(0x0000); + write_index(g, SSD1963_SET_GDISP_MODE); + write_data(g, 0x18); //Enabled dithering + write_data(g, 0x00); + write_data16(g, lcdp->width-1); + write_data16(g, lcdp->height-1); + write_data(g, 0x00); // RGB - write_index(SSD1963_SET_PIXEL_DATA_INTERFACE); - write_data(SSD1963_PDI_16BIT565); + write_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565); /* LCD Clock specs */ - write_index(SSD1963_SET_LSHIFT_FREQ); - write_data((GDISP_FPR >> 16) & 0xFF); - write_data((GDISP_FPR >> 8) & 0xFF); - write_data(GDISP_FPR & 0xFF); + write_index(g, SSD1963_SET_LSHIFT_FREQ); + write_data(g, (lcdp->fpr >> 16) & 0xFF); + write_data(g, (lcdp->fpr >> 8) & 0xFF); + write_data(g, lcdp->fpr & 0xFF); - write_index(SSD1963_SET_HORI_PERIOD); - write_data(mHIGH(SCREEN_HSYNC_PERIOD)); - write_data(mLOW(SCREEN_HSYNC_PERIOD)); - write_data(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); - write_data(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH))); - write_data(SCREEN_HSYNC_PULSE); - write_data(0x00); - write_data(0x00); - write_data(0x00); + write_index(g, SSD1963_SET_HORI_PERIOD); + write_data16(g, lcdp->hperiod); + write_data16(g, lcdp->hpulse + lcdp->hbporch); + write_data(g, lcdp->hpulse); + write_data(g, 0x00); + write_data(g, 0x00); + write_data(g, 0x00); - write_index(SSD1963_SET_VERT_PERIOD); - write_data(mHIGH(SCREEN_VSYNC_PERIOD)); - write_data(mLOW(SCREEN_VSYNC_PERIOD)); - write_data(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); - write_data(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH))); - write_data(SCREEN_VSYNC_PULSE); - write_data(0x00); - write_data(0x00); + write_index(g, SSD1963_SET_VERT_PERIOD); + write_data16(g, lcdp->vperiod); + write_data16(g, lcdp->vpulse + lcdp->vbporch); + write_data(g, lcdp->vpulse); + write_data(g, 0x00); + write_data(g, 0x00); /* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) */ - write_index(SSD1963_SET_TEAR_ON); - write_data(0x0000); + write_reg(g, SSD1963_SET_TEAR_ON, 0x00); /* Turn on */ - write_index(SSD1963_SET_DISPLAY_ON); + write_index(g, SSD1963_SET_DISPLAY_ON); - set_backlight(0xE5);//set to 90% brightness - - post_init_board(); + /* Turn on the back-light */ + set_backlight(g, GDISP_INITIAL_BACKLIGHT); - /* 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 + // Finish Init + post_init_board(g); + // Release the bus + release_bus(g); + + /* Initialise the GDISP structure */ + g->g.Width = lcdp->width; + g->g.Height = lcdp->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 - */ - write_index(SSD1963_SET_PAGE_ADDRESS); - write_data((y0 >> 8) & 0xFF); - write_data((y0 >> 0) & 0xFF); - write_data((y1 >> 8) & 0xFF); - write_data((y1 >> 0) & 0xFF); - write_index(SSD1963_SET_COLUMN_ADDRESS); - write_data((x0 >> 8) & 0xFF); - write_data((x0 >> 0) & 0xFF); - write_data((x1 >> 8) & 0xFF); - write_data((x1 >> 0) & 0xFF); -} +#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); + } +#endif -/** - * @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(SSD1963_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(SSD1963_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); +// Not implemented yet. +#if 0 && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL + LLDSPEC void gdisp_lld_control(GDisplay *g) { + switch(g->p.x) { + case GDISP_CONTROL_POWER: + if (g->g.Powermode == (powermode_t)g->p.ptr) + return; + switch((powermode_t)g->p.ptr) { + case powerOff: + acquire_bus(g); + write_index(g, SSD1963_EXIT_SLEEP_MODE); // leave sleep mode + gfxSleepMilliseconds(5); + write_index(g, SSD1963_SET_DISPLAY_OFF); + write_index(g, SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode + release_bus(g); + break; + case powerOn: + acquire_bus(g); + read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep + read_reg(0x0000); gfxSleepMilliseconds(5); + write_index(g, SSD1963_SET_DISPLAY_ON); + release_bus(g); + break; + case powerSleep: + acquire_bus(g); + write_index(g, SSD1963_SET_DISPLAY_OFF); + write_index(g, SSD1963_ENTER_SLEEP_MODE); // enter sleep mode + release_bus(g); + break; + default: + return; } - 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 + g->g.Powermode = (powermode_t)g->p.ptr; + return; -#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(SSD1963_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 - gfxSleepMilliseconds(5); - write_index(SSD1963_SET_DISPLAY_OFF); - write_index(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode - break; - case powerOn: - read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep - read_reg(0x0000); gfxSleepMilliseconds(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 - gfxSleepMilliseconds(5); - break; - default: - return; - } - GDISP.Powermode = (gdisp_powermode_t)value; + case GDISP_CONTROL_ORIENTATION: + if (g->g.Orientation == (orientation_t)g->p.ptr) 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; + case GDISP_ROTATE_0: + acquire_bus(g); + /* Code here */ + release_bus(g); + g->g.Height = ((LCD_Parameters *)g->priv)->height; + g->g.Width = ((LCD_Parameters *)g->priv)->width; + break; + case GDISP_ROTATE_90: + acquire_bus(g); + /* Code here */ + release_bus(g); + g->g.Height = ((LCD_Parameters *)g->priv)->width; + g->g.Width = ((LCD_Parameters *)g->priv)->height; + break; + case GDISP_ROTATE_180: + acquire_bus(g); + /* Code here */ + release_bus(g); + g->g.Height = ((LCD_Parameters *)g->priv)->height; + g->g.Width = ((LCD_Parameters *)g->priv)->width; + break; + case GDISP_ROTATE_270: + acquire_bus(g); + /* Code here */ + release_bus(g); + g->g.Height = ((LCD_Parameters *)g->priv)->width; + g->g.Width = ((LCD_Parameters *)g->priv)->height; + break; + default: 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: -*/ + } + g->g.Orientation = (orientation_t)value; + return; + + case GDISP_CONTROL_BACKLIGHT: + if ((unsigned)g->p.ptr > 100) + g->p.ptr = (void *)100; + set_backlight(g, (unsigned)g->p.ptr); + g->g.Backlight = (unsigned)g->p.ptr; + return; + + //case GDISP_CONTROL_CONTRAST: + default: + return; } } #endif #endif /* GFX_USE_GDISP */ -/** @} */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld.mk b/drivers/gdisp/SSD1963/gdisp_lld.mk index c2ce22b6..ad406898 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld.mk +++ b/drivers/gdisp/SSD1963/gdisp_lld.mk @@ -1,6 +1,2 @@ -# List the required driver. -GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c - -# Required include directories GFXINC += $(GFXLIB)/drivers/gdisp/SSD1963 - +GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h b/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h deleted file mode 100644 index a2c296b9..00000000 --- a/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h +++ /dev/null @@ -1,177 +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://chibios-gfx.com/license.html - */ - -/** - * @file drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h - * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. - * - * @details This file demonstrates how to interface an SSD1963 based display to an - * STM32 microcontroller using ChibiOS/RT. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/* Using FSMC A16 as RS */ -#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */ -#define GDISP_RAM (*((volatile uint16_t *) 0x60020000)) /* 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 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 = 0; - - #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)) gfxExit(); - 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 << 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)); - - /* 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 = 0; - /* 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 SSD1963 has a built-in PWM, its output can - //be used by a Dynamic Background Control or by a host (user) - //Check your LCD's hardware, the PWM connection is default left open and instead - //connected to a LED connection on the breakout board - write_index(SSD1963_SET_PWM_CONF);//set PWM for BackLight - write_data(0x0001); - write_data(percent & 0x00FF); - write_data(0x0001);//controlled by host (not DBC), enabled - write_data(0x00FF); - write_data(0x0060);//don't let it go too dark, avoid a useless LCD - write_data(0x000F);//prescaler ??? -} - -/** - * @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 */ -} - -#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) { - return GDISP_RAM; -} -#endif - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h b/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h deleted file mode 100644 index 38f5b2a5..00000000 --- a/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h +++ /dev/null @@ -1,191 +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://chibios-gfx.com/license.html - */ - -/** - * @file drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h - * @brief GDISP Graphic Driver subsystem board interface for the SSD1963 display. - * - * @brief This file demonstrates how to interface an SSD1963 based display using - * a GPIO interface of an STM32 out of ChibiOS/RT. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/** - * @brief The GPIO pin config - * - * @details This block of defines tell your driver how you wired your display - * controller to your MCU. Please change them accordingly. - */ -#define GDISP_CMD_PORT GPIOC -#define GDISP_DATA_PORT GPIOD -#define GDISP_CS 0 -#define GDISP_RS 1 -#define GDISP_WR 2 -#define GDISP_RD 3 - -#define Set_CS palSetPad(GDISP_CMD_PORT, GDISP_CS); -#define Clr_CS palClearPad(GDISP_CMD_PORT, GDISP_CS); -#define Set_RS palSetPad(GDISP_CMD_PORT, GDISP_RS); -#define Clr_RS palClearPad(GDISP_CMD_PORT, GDISP_RS); -#define Set_WR palSetPad(GDISP_CMD_PORT, GDISP_WR); -#define Clr_WR palClearPad(GDISP_CMD_PORT, GDISP_WR); -#define Set_RD palSetPad(GDISP_CMD_PORT, GDISP_RD); -#define Clr_RD palClearPad(GDISP_CMD_PORT, GDISP_RD); - -/** - * @brief Send data to the index register. - * - * @param[in] index The index register to set - * - * @notapi - */ -static inline void write_index(uint16_t index) { - Set_CS; Set_RS; Set_WR; Clr_RD; - - palWritePort(GDISP_DATA_PORT, index); - - Clr_CS; -} - -/** - * @brief Send data to the lcd. - * - * @param[in] data The data to send - * - * @notapi - */ -static inline void write_data(uint16_t data) { - Set_CS; Clr_RS; Set_WR; Clr_RD; - - palWritePort(GDISP_DATA_PORT, data); - - Clr_CS; -} - -/** - * @brief Initialise the board for the display. - * - * @notapi - */ -static inline void init_board(void) { - IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0}; - IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0}; - palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL); - palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL); -} - -static inline void post_init_board(void) { - /* Nothing to do here */ -} - -/** - * @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) { - /* optional */ -} - -/** - * @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 SSD1963 has a built-in PWM, its output can - //be used by a Dynamic Background Control or by a host (user) - //Check your LCD's hardware, the PWM connection is default left open and instead - //connected to a LED connection on the breakout board - write_index(SSD1963_SET_PWM_CONF);//set PWM for BackLight - write_data(0x0001); - write_data(percent & 0x00FF); - write_data(0x0001);//controlled by host (not DBC), enabled - write_data(0x00FF); - write_data(0x0060);//don't let it go too dark, avoid a useless LCD - write_data(0x000F);//prescaler ??? -} - -/** - * @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 */ -} - -__inline void write_stream(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(GDISP_DATA_PORT, buffer[i]); - Clr_WR; - } - - Clr_CS; -} - -__inline void read_stream(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(GDISP_DATA_PORT); - Clr_RD; - } -} - -#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) { - uint16_t data; - - Set_CS; Clr_RS; Clr_WR; Set_RD; - - data = palReadPort(GDISP_DATA_PORT); - - Clr_CS; - - return data; -} -#endif - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_template.h b/drivers/gdisp/SSD1963/gdisp_lld_board_template.h deleted file mode 100644 index 44cd3712..00000000 --- a/drivers/gdisp/SSD1963/gdisp_lld_board_template.h +++ /dev/null @@ -1,115 +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. - * @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) { - -} - -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) { - -} - -#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/SSD1963/gdisp_lld_config.h b/drivers/gdisp/SSD1963/gdisp_lld_config.h index 70eec579..054d72b8 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld_config.h +++ b/drivers/gdisp/SSD1963/gdisp_lld_config.h @@ -22,14 +22,8 @@ /* 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_HARDWARE_STREAM_WRITE TRUE +//#define GDISP_HARDWARE_CONTROL TRUE // Not Yet. #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 diff --git a/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h b/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h deleted file mode 100644 index 72095495..00000000 --- a/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h +++ /dev/null @@ -1,74 +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_panel_example.h - * @brief TFT LCD panel properties. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_PANEL_H -#define _GDISP_LLD_PANEL_H - -/* LCD panel specs */ - -/* The timings need to follow the datasheet for your particular TFT/LCD screen (the actual screen, not the controller) -*** Datasheets normally use a specific set of timings and acronyms, their value refers to the number of pixel clocks -** Non-display periods refer to pulses/timings that occur before or after the timings that actually put pixels on the screen -** Display periods refer to pulses/timings that directly put pixels on the screen -HDP: Horizontal Display Period, normally the width - 1 -HT: Horizontal Total period (display + non-display) -HPS: non-display period between the start of the horizontal sync (LLINE) signal and the first display data -LPS: horizontal sync pulse (LLINE) start location in pixel clocks -HPW: Horizontal sync Pulse Width -VDP: Vertical Display period, normally height - 1 -VT: Vertical Total period (display + non-display) -VPS: non-display period in lines between the start of the frame and the first display data in number of lines -FPS: vertical sync pulse (LFRAME) start location in lines. -VPW: Vertical sync Pulse Width - -*** Here's how to convert them: -HPS = SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH -HT - HPS = GDISP_SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH -=> SCREEN_HSYNC_FRONT_PORCH = ( HT - HPS ) - GDISP_SCREEN_WIDTH - SCREEN_HSYNC_PULSE = HPW - SCREEN_HSYNC_BACK_PORCH = HPS - HPW - SCREEN_HSYNC_PERIOD = HT - -VPS = SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH -VT - VPS = GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH -=> SCREEN_VSYNC_FRONT_PORCH = ( VT - VPS ) - GDISP_SCREEN_HEIGHT - SCREEN_VSYNC_PULSE = VPW - SCREEN_VSYNC_BACK_PORCH = VPS - LPS - SCREEN_VSYNC_PERIOD = VT -*/ - -#define SCREEN_FPS 60ULL - -//The following values are for a 4.3" TFT LCD - -#define GDISP_SCREEN_WIDTH 480 -#define GDISP_SCREEN_HEIGHT 272 - -#define SCREEN_HSYNC_BACK_PORCH 2 -#define SCREEN_HSYNC_FRONT_PORCH 2 -#define SCREEN_HSYNC_PULSE 41 - -#define SCREEN_VSYNC_BACK_PORCH 2 -#define SCREEN_VSYNC_FRONT_PORCH 2 -#define SCREEN_VSYNC_PULSE 10 - -#define SCREEN_HSYNC_PERIOD (SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH + GDISP_SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH) -#define SCREEN_VSYNC_PERIOD (SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH + GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH) - -#define SCREEN_PCLK (SCREEN_HSYNC_PERIOD * SCREEN_VSYNC_PERIOD * SCREEN_FPS) -#define GDISP_FPR ((SCREEN_PCLK * 1048576)/100000000) - -#endif -/** @} */ diff --git a/drivers/gdisp/SSD1963/ssd1963.h b/drivers/gdisp/SSD1963/ssd1963.h index 46369be6..be328775 100644 --- a/drivers/gdisp/SSD1963/ssd1963.h +++ b/drivers/gdisp/SSD1963/ssd1963.h @@ -8,11 +8,6 @@ #ifndef SSD1963_H #define SSD1963_H -#include "gdisp_lld_panel.h" - -#define mHIGH(x) (x >> 8) -#define mLOW(x) (x & 0xFF) - /* SSD1963 commands */ #define SSD1963_NOP 0x0000