1 /* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2008, Atmel Corporation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
32 #if defined (AT91C_ID_LCDC)
34 //------------------------------------------------------------------------------
36 //------------------------------------------------------------------------------
39 #include <utility/assert.h>
40 #include <utility/trace.h>
43 //------------------------------------------------------------------------------
45 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
48 /// Enables the LCD controller, after waiting for the specified number of
50 /// \param frames Number of frames before the LCD is enabled.
51 //------------------------------------------------------------------------------
52 void LCD_Enable(unsigned int frames)
54 TRACE_DEBUG("LCD enable\n\r");
55 ASSERT((frames & 0xFFFFFF80) == 0,
56 "LCD_Enable: Wrong frames value.\n\r");
57 if( (AT91C_BASE_LCDC->LCDC_PWRCON & AT91C_LCDC_BUSY) == AT91C_LCDC_BUSY ) {
58 TRACE_DEBUG("LCD BUSY E\n\r");
60 AT91C_BASE_LCDC->LCDC_PWRCON = AT91C_LCDC_PWR | (frames << 1);
63 //------------------------------------------------------------------------------
64 /// Disables the LCD controller, after waiting for the specified number of
66 /// \param frames Number of frames before the LCD is shut down.
67 //------------------------------------------------------------------------------
68 void LCD_Disable(unsigned int frames)
70 TRACE_DEBUG("LCD disable\n\r");
71 ASSERT((frames & 0xFFFFFF80) == 0,
72 "LCD_Disable: Wrong frames value.\n\r");
73 // Remove AT91C_LCDC_PWR
74 AT91C_BASE_LCDC->LCDC_PWRCON = frames << 1;
75 // wait LCDC Core is in idle state
76 while( (AT91C_BASE_LCDC->LCDC_PWRCON & AT91C_LCDC_BUSY) == AT91C_LCDC_BUSY ) {
78 TRACE_DEBUG("LCD is in IDLE state\n\r");
81 //------------------------------------------------------------------------------
82 /// Enables the DMA of the LCD controller.
83 //------------------------------------------------------------------------------
84 void LCD_EnableDma(void)
86 if( (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY) == AT91C_LCDC_DMABUSY ) {
87 TRACE_DEBUG("LCD DMA BUSY E\n\r");
89 AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMAEN;
92 //------------------------------------------------------------------------------
93 /// Disables the DMA of the LCD controller.
94 //------------------------------------------------------------------------------
95 void LCD_DisableDma(void)
97 AT91C_BASE_LCDC->LCDC_DMACON = 0;
98 // wait LCDC DMA is in idle state
99 while( (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY) == AT91C_LCDC_DMABUSY ) {
101 TRACE_DEBUG("LCD DMA is in IDLE state\n\r");
104 //------------------------------------------------------------------------------
105 /// Enables the selected LDC interrupt sources.
106 /// \param sources Interrupt sources to enable.
107 //------------------------------------------------------------------------------
108 void LCD_EnableInterrupts(unsigned int sources)
110 AT91C_BASE_LCDC->LCDC_IER = sources;
113 //------------------------------------------------------------------------------
114 /// Configures the internal clock of the LCD controller given the master clock of
115 /// the system and the desired pixel clock in MHz.
116 /// \param masterClock Master clock frequency.
117 /// \param pixelClock Pixel clock frequency.
118 //------------------------------------------------------------------------------
119 void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock)
121 AT91C_BASE_LCDC->LCDC_LCDCON1 = ((masterClock / 2 / pixelClock) - 2) << 12;
124 //------------------------------------------------------------------------------
126 //------------------------------------------------------------------------------
127 void LCD_DMAReset(void)
129 // DMA Module should be reset only when disabled and in idle state
130 if( AT91C_LCDC_DMABUSY == (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY)) {
131 TRACE_ERROR("LCD BUSY so NO DMA RESET\n\r");
133 if( AT91C_LCDC_DMAEN == (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMAEN)) {
134 TRACE_ERROR("DMA Enabled, so NO DMA RESET\n\r");
136 AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMARST;
139 //------------------------------------------------------------------------------
140 /// Sets the type of display used with the LCD controller.
141 /// \param displayType Type of display used.
142 //------------------------------------------------------------------------------
143 void LCD_SetDisplayType(unsigned int displayType)
147 ASSERT((displayType & ~AT91C_LCDC_DISTYPE) == 0,
148 "LCD_SetDisplayType: Wrong display type value.\n\r");
150 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
151 value &= ~AT91C_LCDC_DISTYPE;
152 value |= displayType;
153 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
156 //------------------------------------------------------------------------------
157 /// Sets the scan mode used by the LCD (either single scan or double-scan).
158 /// \param scanMode Scan mode to use.
159 //------------------------------------------------------------------------------
160 void LCD_SetScanMode(unsigned int scanMode)
164 ASSERT((scanMode & ~AT91C_LCDC_SCANMOD) == 0,
165 "LCD_SetScanMode: Wrong scan mode value.\n\r");
167 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
168 value &= ~AT91C_LCDC_SCANMOD;
170 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
173 //------------------------------------------------------------------------------
174 /// Sets the number of bits per pixel used by the LCD display.
175 /// \param bitsPerPixel Number of bits per pixel to use.
176 //------------------------------------------------------------------------------
177 void LCD_SetBitsPerPixel(unsigned int bitsPerPixel)
181 ASSERT((bitsPerPixel & ~AT91C_LCDC_PIXELSIZE) == 0,
182 "LCD_SetScanMode: Wrong bitsPerPixel value.\n\r");
184 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
185 value &= ~AT91C_LCDC_PIXELSIZE;
186 value |= bitsPerPixel;
187 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
190 //------------------------------------------------------------------------------
191 /// Sets the LCDD, LCDVSYNC, LCDHSYNC, LCDDOTCLK and LCDDEN signal polarities.
192 /// \param lcdd LCDD signal polarity.
193 /// \param lcdvsync LCDVSYNC signal polarity.
194 /// \param lcdhsync LCDHSYNC signal polarity.
195 /// \param lcddotclk LCDDOTCLK signal polarity.
196 /// \param lcdden LCDDEN signal polarity.
197 //------------------------------------------------------------------------------
198 void LCD_SetPolarities(
200 unsigned int lcdvsync,
201 unsigned int lcdhsync,
202 unsigned int lcddotclk,
207 ASSERT((lcdd & ~AT91C_LCDC_INVVD) == 0,
208 "LCD_SetPolarities: Wrong lcdd value.\n\r");
209 ASSERT((lcdvsync & ~AT91C_LCDC_INVFRAME) == 0,
210 "LCD_SetPolarities: Wrong lcdvsync value.\n\r");
211 ASSERT((lcdhsync & ~AT91C_LCDC_INVLINE) == 0,
212 "LCD_SetPolarities: Wrong lcdhsync value.\n\r");
213 ASSERT((lcddotclk & ~AT91C_LCDC_INVCLK) == 0,
214 "LCD_SetPolarities: Wrong lcddotclk value.\n\r");
215 ASSERT((lcdden & ~AT91C_LCDC_INVDVAL) == 0,
216 "LCD_SetPolarities: Wrong lcdden value.\n\r");
218 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
220 value |= lcdd | lcdvsync | lcdhsync | lcddotclk | lcdden;
221 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
224 //------------------------------------------------------------------------------
225 /// Sets the LCD clock mode, i.e. always active or active only during display
227 /// \param clockMode Clock mode to use.
228 //------------------------------------------------------------------------------
229 void LCD_SetClockMode(unsigned int clockMode)
233 ASSERT((clockMode & ~AT91C_LCDC_CLKMOD) == 0,
234 "LCD_SetScanMode: Wrong scan mode value.\n\r");
236 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
237 value &= ~AT91C_LCDC_CLKMOD;
239 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
242 //------------------------------------------------------------------------------
243 /// Sets the format of the frame buffer memory.
244 /// \param format Memory ordering format.
245 //------------------------------------------------------------------------------
246 void LCD_SetMemoryFormat(unsigned int format)
250 ASSERT((format & ~AT91C_LCDC_MEMOR) == 0,
251 "LCD_SetMemoryFormat: Wrong memory format value.\n\r");
253 value = AT91C_BASE_LCDC->LCDC_LCDCON2;
254 value &= ~AT91C_LCDC_MEMOR;
256 AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
259 //------------------------------------------------------------------------------
260 /// Sets the size in pixel of the LCD display.
261 /// \param width Width in pixel of the LCD display.
262 /// \param height Height in pixel of the LCD display.
263 //------------------------------------------------------------------------------
264 void LCD_SetSize(unsigned int width, unsigned int height)
266 ASSERT(((width - 1) & 0xFFFFF800) == 0,
267 "LCD_SetSize: Wrong width value.\n\r");
268 ASSERT(((height - 1) & 0xFFFFF800) == 0,
269 "LCD_SetSize: Wrong height value.\n\r");
271 AT91C_BASE_LCDC->LCDC_LCDFRCFG = ((width - 1) << 21) | (height - 1);
274 //------------------------------------------------------------------------------
275 /// Sets the vertical timings of the LCD controller. Only meaningful when
276 /// using a TFT display.
277 /// \param vfp Number of idle lines at the end of a frame.
278 /// \param vbp Number of idle lines at the beginning of a frame.
279 /// \param vpw Vertical synchronization pulse width in number of lines.
280 /// \param vhdly Delay between LCDVSYNC edge and LCDHSYNC rising edge, in
281 /// LCDDOTCLK cycles.
282 //------------------------------------------------------------------------------
283 void LCD_SetVerticalTimings(
289 ASSERT((vfp & 0xFFFFFF00) == 0,
290 "LCD_SetVerticalTimings: Wrong vfp value.\n\r");
291 ASSERT((vbp & 0xFFFFFF00) == 0,
292 "LCD_SetVerticalTimings: Wrong vbp value.\n\r");
293 ASSERT(((vpw-1) & 0xFFFFFFC0) == 0,
294 "LCD_SetVerticalTimings: Wrong vpw value.\n\r");
295 ASSERT(((vhdly-1) & 0xFFFFFFF0) == 0,
296 "LCD_SetVerticalTimings: Wrong vhdly value.\n\r");
298 AT91C_BASE_LCDC->LCDC_TIM1 = vfp
304 //------------------------------------------------------------------------------
305 /// Sets the horizontal timings of the LCD controller. Meaningful for both
306 /// STN and TFT displays.
307 /// \param hbp Number of idle LCDDOTCLK cycles at the beginning of a line.
308 /// \param hpw Width of the LCDHSYNC pulse, in LCDDOTCLK cycles.
309 /// \param hfp Number of idel LCDDOTCLK cycles at the end of a line.
310 //------------------------------------------------------------------------------
311 void LCD_SetHorizontalTimings(
316 ASSERT(((hbp-1) & 0xFFFFFF00) == 0,
317 "LCD_SetHorizontalTimings: Wrong hbp value.\n\r");
318 ASSERT(((hpw-1) & 0xFFFFFFC0) == 0,
319 "LCD_SetHorizontalTimings: Wrong hpw value.\n\r");
320 ASSERT(((hfp-1) & 0xFFFFFF00) == 0,
321 "LCD_SetHorizontalTimings: Wrong hfp value.\n\r");
323 AT91C_BASE_LCDC->LCDC_TIM2 = (hbp-1) | ((hpw-1) << 8) | ((hfp-1) << 24);
326 //------------------------------------------------------------------------------
327 /// Sets the address of the frame buffer in the LCD controller DMA. When using
328 /// dual-scan mode, this is the upper frame buffer.
329 /// \param address Frame buffer address.
330 //------------------------------------------------------------------------------
331 void* LCD_SetFrameBufferAddress(void *address)
335 pOldBuffer = (void *) AT91C_BASE_LCDC->LCDC_BA1;
336 AT91C_BASE_LCDC->LCDC_BA1 = (unsigned int) address;
341 //------------------------------------------------------------------------------
342 /// Sets the size in pixels of a frame (height * width * bpp).
343 /// \param frameSize Size of frame in pixels.
344 //------------------------------------------------------------------------------
345 void LCD_SetFrameSize(unsigned int frameSize)
347 ASSERT((frameSize & 0xFF800000) == 0,
348 "LCD_SetFrameSize: Wrong frameSize value.\n\r");
350 AT91C_BASE_LCDC->LCDC_FRMCFG = (frameSize& AT91C_LCDC_FRSIZE)
351 | (AT91C_BASE_LCDC->LCDC_FRMCFG & AT91C_LCDC_BLENGTH);
354 //------------------------------------------------------------------------------
355 /// Sets the DMA controller burst length.
356 /// \param burstLength Desired burst length.
357 //------------------------------------------------------------------------------
358 void LCD_SetBurstLength(unsigned int burstLength)
360 ASSERT(((burstLength-1) & 0xFFFFFF80) == 0,
361 "LCD_SetBurstLength: Wrong burstLength value.\n\r");
363 AT91C_BASE_LCDC->LCDC_FRMCFG &= ~AT91C_LCDC_BLENGTH;
364 AT91C_BASE_LCDC->LCDC_FRMCFG |= (((burstLength-1) << 24) & AT91C_LCDC_BLENGTH);
366 AT91C_BASE_LCDC->LCDC_FIFO = (2048 - (2 * burstLength + 3)) & AT91C_LCDC_FIFOTH;
369 //------------------------------------------------------------------------------
370 /// Sets the prescaler value of the contrast control PWM.
371 /// \param prescaler Desired prescaler value.
372 //------------------------------------------------------------------------------
373 void LCD_SetContrastPrescaler(unsigned int prescaler)
375 ASSERT((prescaler & ~AT91C_LCDC_PS) == 0,
376 "LCD_SetContrastPrescaler: Wrong prescaler value\n\r");
378 AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_PS;
379 AT91C_BASE_LCDC->LCDC_CTRSTCON |= prescaler;
382 //------------------------------------------------------------------------------
383 /// Sets the polarity of the contrast PWM.
384 /// \param polarity PWM polarity
385 //------------------------------------------------------------------------------
386 void LCD_SetContrastPolarity(unsigned int polarity)
388 ASSERT((polarity & ~AT91C_LCDC_POL) == 0,
389 "LCD_SetContrastPolarity: Wrong polarity value\n\r");
391 AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_POL;
392 AT91C_BASE_LCDC->LCDC_CTRSTCON |= polarity;
395 //------------------------------------------------------------------------------
396 /// Sets the threshold value of the constrast PWM.
397 /// \param value PWM threshold value.
398 //------------------------------------------------------------------------------
399 void LCD_SetContrastValue(unsigned int value)
401 ASSERT((value & ~AT91C_LCDC_CVAL) == 0,
402 "LCD_SetContrastValue: Wrong value.\n\r");
404 AT91C_BASE_LCDC->LCDC_CTRSTVAL = value;
407 //------------------------------------------------------------------------------
408 /// Enables the contrast PWM generator.
409 //------------------------------------------------------------------------------
410 void LCD_EnableContrast(void)
412 AT91C_BASE_LCDC->LCDC_CTRSTCON |= AT91C_LCDC_ENA_PWMGEMENABLED;
415 //------------------------------------------------------------------------------
416 /// Decode the RGB file
417 /// \param file Buffer which holds the RGB file.
418 /// \param bufferLCD Buffer in which to store the decoded image adapted to LCD.
419 /// \param width Buffer width in pixels.
420 /// \param height Buffer height in pixels.
421 /// \param bpp Number of bits per pixels that the buffer stores.
422 //------------------------------------------------------------------------------
425 unsigned char *bufferLCD,
430 unsigned int offsetLine=0, offsetLCD=0;
431 unsigned int offset=1;
433 while( offset < (BOARD_LCD_HEIGHT)) {
434 //TRACE_DEBUG("LCD:%d LINE:%d off:%d\n\r", offsetLCD, offsetLine, offset);
435 if( width < BOARD_LCD_WIDTH ) {
436 //TRACE_DEBUG("width < BOARD_LCD_WIDTH\n\r");
437 while( offsetLine < (width*offset*(bpp/8)) ) {
438 bufferLCD[offsetLCD] = file[offsetLine];
442 //TRACE_DEBUG("add white\n\r");
443 while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
444 bufferLCD[offsetLCD] = 0;
451 while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
452 bufferLCD[offsetLCD] = file[offsetLine];
457 while( offsetLine < (width*offset*(bpp/8)) ) {