BeRTOS
lcd_hx8347.c
Go to the documentation of this file.
00001 
00041 /* ----------------------------------------------------------------------------
00042  *         ATMEL Microcontroller Software Support
00043  * ----------------------------------------------------------------------------
00044  * Copyright (c) 2010, Atmel Corporation
00045  *
00046  * All rights reserved.
00047  *
00048  * Redistribution and use in source and binary forms, with or without
00049  * modification, are permitted provided that the following conditions are met:
00050  *
00051  * - Redistributions of source code must retain the above copyright notice,
00052  * this list of conditions and the disclaimer below.
00053  *
00054  * Atmel's name may not be used to endorse or promote products derived from
00055  * this software without specific prior written permission.
00056  *
00057  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00058  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00059  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00060  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00061  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00062  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00063  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00064  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00065  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00066  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00067  * ----------------------------------------------------------------------------
00068  */
00069 
00070 #include "lcd_hx8347.h"
00071 
00072 #include "hw/hw_hx8347.h"
00073 #include <cfg/debug.h>
00074 #include <drv/timer.h>
00075 
00076 // Himax HX8347 chip id
00077 #define HX8347_ID_HIMAX  0x47
00078 
00079 
00080 static uint16_t lcd_row[LCD_WIDTH];
00081 
00082 
00083 struct lcd_hx8347_reg
00084 {
00085     uint8_t cmd;    // Register index, if 0xFF wait for value ms
00086     uint8_t data;   // Register value
00087 };
00088 
00089 static const struct lcd_hx8347_reg init_seq[] =
00090 {
00091     // Start internal OSC
00092     { 0x19, 0x49 },   // OSCADJ=10 0000, OSD_EN=1 //60Hz
00093     { 0x93, 0x0C },   // RADJ=1100
00094 
00095     // Power on flow
00096     { 0x44, 0x4D },   // VCM=100 1101
00097     { 0x45, 0x11 },   // VDV=1 0001
00098     { 0x20, 0x40 },   // BT=0100
00099     { 0x1D, 0x07 },   // VC1=111
00100     { 0x1E, 0x00 },   // VC3=000
00101     { 0x1F, 0x04 },   // VRH=0100
00102 
00103     { 0x1C, 0x04 },   // AP=100
00104     { 0x1B, 0x10 },   // GASENB=0, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
00105     { 0xFF, 50   },   // 50 ms delay
00106 
00107     { 0x43, 0x80 },   // Set VCOMG=1
00108     { 0xFF, 50   },   // 50 ms delay
00109 
00110 #if 0
00111     // Gamma for CMO 2.8
00112     { 0x46, 0x95 },
00113     { 0x47, 0x51 },
00114     { 0x48, 0x00 },
00115     { 0x49, 0x36 },
00116     { 0x4A, 0x11 },
00117     { 0x4B, 0x66 },
00118     { 0x4C, 0x14 },
00119     { 0x4D, 0x77 },
00120     { 0x4E, 0x13 },
00121     { 0x4F, 0x4C },
00122     { 0x50, 0x46 },
00123     { 0x51, 0x46 },
00124 #endif
00125 
00126     // 240x320 window setting
00127     { 0x02, 0x00 },   // Column address start2
00128     { 0x03, 0x00 },   // Column address start1
00129     { 0x04, 0x00 },   // Column address end2
00130     { 0x05, 0xEF },   // Column address end1
00131     { 0x06, 0x00 },   // Row address start2
00132     { 0x07, 0x00 },   // Row address start1
00133     { 0x08, 0x01 },   // Row address end2
00134     { 0x09, 0x3F },   // Row address end1
00135 
00136     // Display Setting
00137     { 0x01, 0x06 },   // IDMON=0, INVON=1, NORON=1, PTLON=0
00138 //  { 0x16, 0xC8 },   // MY=1, MX=1, MV=0, BGR=1
00139     { 0x16, 0x68 },   // MY=0, MX=1, MV=1, RGB XY exchange X mirror
00140     { 0x23, 0x95 },   // N_DC=1001 0101
00141     { 0x24, 0x95 },   // P_DC=1001 0101
00142     { 0x25, 0xFF },   // I_DC=1111 1111
00143     { 0x27, 0x06 },   // N_BP=0000 0110
00144     { 0x28, 0x06 },   // N_FP=0000 0110
00145     { 0x29, 0x06 },   // P_BP=0000 0110
00146     { 0x2A, 0x06 },   // P_FP=0000 0110
00147     { 0x2C, 0x06 },   // I_BP=0000 0110
00148     { 0x2D, 0x06 },   // I_FP=0000 0110
00149     { 0x3A, 0x01 },   // N_RTN=0000, N_NW=001
00150     { 0x3B, 0x01 },   // P_RTN=0000, P_NW=001
00151     { 0x3C, 0xF0 },   // I_RTN=1111, I_NW=000
00152     { 0x3D, 0x00 },   // DIV=00
00153     { 0x3E, 0x38 },   // SON=38h
00154     { 0x40, 0x0F },   // GDON=0Fh
00155     { 0x41, 0xF0 },   // GDOF=F0h
00156 };
00157 
00158 /*
00159  * Write to an LCD register.
00160  */
00161 static void regWrite(uint8_t reg, uint16_t val)
00162 {
00163     hx8347_cmd(reg);
00164     hx8347_write(val);
00165 }
00166 
00167 /*
00168  * Read data from a LCD register.
00169  */
00170 static uint16_t regRead(uint8_t reg)
00171 {
00172     hx8347_cmd(reg);
00173     return hx8347_read();
00174 }
00175 
00176 /*
00177  * Write data in a buffer to the LCD controller.
00178  */
00179 static void bufferWrite(const uint16_t *buf, uint16_t size)
00180 {
00181     uint16_t i;
00182     for (i = 0 ; i < size; ++i)
00183         hx8347_write(buf[i]);
00184 }
00185 
00186 static void lcd_setCursor(uint16_t x, uint16_t y)
00187 {
00188     regWrite(0x02, x >> 8);
00189     regWrite(0x03, x & 0xff);
00190     regWrite(0x06, y >> 8);
00191     regWrite(0x07, y & 0xff);
00192 }
00193 
00194 static void lcd_setWindow(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
00195 {
00196     ASSERT(x + width <= LCD_WIDTH);
00197     ASSERT(y + height <= LCD_HEIGHT);
00198     ASSERT(width > 0);
00199     ASSERT(height > 0);
00200 
00201     // Window right and bottom limits are inclusive
00202     width--;
00203     height--;
00204 
00205     lcd_setCursor(x, y);
00206 
00207     regWrite(0x04, (x + width) >> 8);
00208     regWrite(0x05, (x + width) & 0xff);
00209     regWrite(0x08, (y + height) >> 8);
00210     regWrite(0x09, (y + height) & 0xff);
00211 }
00212 
00213 /*
00214  * Refresh a bitmap on screen
00215  */
00216 void lcd_hx8347_blitBitmap(const Bitmap *bm)
00217 {
00218     uint8_t mask;
00219     int i, l, r;
00220 
00221     lcd_setWindow(0, 0, bm->width, bm->height);
00222     hx8347_cmd(0x22);
00223 
00224     for (l = 0; l < bm->height / 8; l++)
00225     {
00226         for (mask = 1; mask; mask <<= 1)
00227         {
00228             for (i = 0; i < bm->width; i++)
00229             {
00230                 if (bm->raster[l * bm->width + i] & mask)
00231                     lcd_row[i] = 0x0000;
00232                 else
00233                     lcd_row[i] = 0xFFFF;
00234             }
00235             bufferWrite(lcd_row, bm->width);
00236         }
00237     }
00238 
00239     for (r = 0, mask = 1; r < bm->height % 8; r++, mask <<= 1)
00240     {
00241         for (i = 0; i < bm->width; i++)
00242         {
00243             if (bm->raster[l * bm->width + i] & mask)
00244                 lcd_row[i] = 0x0000;
00245             else
00246                 lcd_row[i] = 0xFFFF;
00247         }
00248         bufferWrite(lcd_row, bm->width);
00249     }
00250 }
00251 
00252 /*
00253  * Blit a 24 bit color raw raster directly on screen
00254  */
00255 void lcd_hx8347_blitBitmap24(int x, int y, int width, int height, const char *bmp)
00256 {
00257     int l, r;
00258 
00259     lcd_setWindow(x, y, width, height);
00260     hx8347_cmd(0x22);
00261 
00262     for (l = 0; l < height; l++)
00263     {
00264         for (r = 0; r < width; r++)
00265         {
00266             lcd_row[r] =
00267                 (((uint16_t)bmp[0] << 8) & 0xF800) |
00268                 (((uint16_t)bmp[1] << 3) & 0x07E0) |
00269                 (((uint16_t)bmp[2] >> 3) & 0x001F);
00270             bmp += 3;
00271         }
00272         bufferWrite(lcd_row, width);
00273     }
00274 }
00275 
00279 void lcd_hx8347_off(void)
00280 {
00281     regWrite(0x90, 0);  // SAP=0000 0000
00282     regWrite(0x26, 0);  // GON=0, DTE=0, D=00
00283 }
00284 
00288 void lcd_hx8347_on(void)
00289 {
00290     regWrite(0x90, 0x7F);  // SAP=0111 1111
00291     regWrite(0x26, 0x04);  // GON=0, DTE=0, D=01
00292     timer_delay(100);
00293     regWrite(0x26, 0x24);  // GON=1, DTE=0, D=01
00294     regWrite(0x26, 0x2C);  // GON=1, DTE=0, D=11
00295     timer_delay(100);
00296     regWrite(0x26, 0x3C);  // GON=1, DTE=1, D=11
00297 }
00298 
00302 void lcd_hx8347_init(void)
00303 {
00304     unsigned i;
00305     uint16_t chip_id;
00306 
00307     hx8347_busInit();
00308     lcd_hx8347_off();
00309 
00310     // Check chip id
00311     if ((chip_id = regRead(0x67)) != HX8347_ID_HIMAX)
00312     {
00313         kprintf("HX8347 chip id read error or wrong id (0x%x), skipping initialization.\n", chip_id);
00314         return;
00315     }
00316 
00317     for (i = 0; i < countof(init_seq); i++)
00318     {
00319         if (init_seq[i].cmd != 0xFF)
00320             regWrite(init_seq[i].cmd, init_seq[i].data);
00321         else
00322             timer_delay(init_seq[i].data);
00323     }
00324 
00325     lcd_hx8347_on();
00326 }