aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-10-28 11:03:39 +1000
committerinmarket <andrewh@inmarket.com.au>2013-10-28 11:03:39 +1000
commitb05a29f830008ab0e9a36d8384ed7cf4ea3fb18b (patch)
tree193e79f1d53638dad20ac86c1c2e18492311f6b6 /drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
parent9e5ed28f98e7b0b3dbd46df7a62568dbaffab92a (diff)
downloaduGFX-b05a29f830008ab0e9a36d8384ed7cf4ea3fb18b.tar.gz
uGFX-b05a29f830008ab0e9a36d8384ed7cf4ea3fb18b.tar.bz2
uGFX-b05a29f830008ab0e9a36d8384ed7cf4ea3fb18b.zip
Rename GDISP driver files to prevent problems when compiling for multiple controllers on platforms that put all generated object files into a single directory.
Diffstat (limited to 'drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c')
-rw-r--r--drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
new file mode 100644
index 00000000..b94c1a40
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
@@ -0,0 +1,285 @@
+/*
+ * 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.c
+ * @brief GDISP Graphics Driver subsystem low level driver source.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#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"
+
+#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.
+ */
+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. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+ LCD_Parameters * lcdp;
+
+ // The private area for this controller is the LCD timings
+ lcdp = (void *)&DisplayTimings[g->controllerdisplay];
+ g->priv = lcdp;
+
+ // Initialise the board interface
+ init_board(g);
+
+ // 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(g, SSD1963_SOFT_RESET);
+ gfxSleepMilliseconds(5);
+
+ /* Driver PLL config */
+ 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(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_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565);
+
+ /* LCD Clock specs */
+ 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(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(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_reg(g, SSD1963_SET_TEAR_ON, 0x00);
+
+ /* Turn on */
+ write_index(g, SSD1963_SET_DISPLAY_ON);
+
+ /* Turn on the back-light */
+ set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+ // 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;
+}
+
+#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
+
+// 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;
+ }
+ g->g.Powermode = (powermode_t)g->p.ptr;
+ return;
+
+ case GDISP_CONTROL_ORIENTATION:
+ if (g->g.Orientation == (orientation_t)g->p.ptr)
+ return;
+ 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;
+ }
+ g->g.Orientation = (orientation_t)g->p.ptr;
+ 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 */
+