]> begriffs open source - cmsis-freertos/blob - Demo/CORTEX_AT91SAM3U256_IAR/AT91Lib/peripherals/lcd/lcd.c
Initial commit
[cmsis-freertos] / Demo / CORTEX_AT91SAM3U256_IAR / AT91Lib / peripherals / lcd / lcd.c
1 /* ----------------------------------------------------------------------------
2  *         ATMEL Microcontroller Software Support 
3  * ----------------------------------------------------------------------------
4  * Copyright (c) 2008, Atmel Corporation
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * - Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the disclaimer below.
13  *
14  * Atmel's name may not be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
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  * ----------------------------------------------------------------------------
28  */
29
30 #include <board.h>
31
32 #if defined (AT91C_ID_LCDC)
33
34 //------------------------------------------------------------------------------
35 //         Headers
36 //------------------------------------------------------------------------------
37
38 #include "lcd.h"
39 #include <utility/assert.h>
40 #include <utility/trace.h>
41
42
43 //------------------------------------------------------------------------------
44 //         Exported functions
45 //------------------------------------------------------------------------------
46
47 //------------------------------------------------------------------------------
48 /// Enables the LCD controller, after waiting for the specified number of
49 /// frames.
50 /// \param frames  Number of frames before the LCD is enabled.
51 //------------------------------------------------------------------------------
52 void LCD_Enable(unsigned int frames)
53 {
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");
59     }
60     AT91C_BASE_LCDC->LCDC_PWRCON = AT91C_LCDC_PWR | (frames << 1);
61 }
62
63 //------------------------------------------------------------------------------
64 /// Disables the LCD controller, after waiting for the specified number of
65 /// frames.
66 /// \param frames  Number of frames before the LCD is shut down.
67 //------------------------------------------------------------------------------
68 void LCD_Disable(unsigned int frames)
69 {
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 ) {
77     }
78     TRACE_DEBUG("LCD is in IDLE state\n\r");
79 }
80
81 //------------------------------------------------------------------------------
82 /// Enables the DMA of the LCD controller.
83 //------------------------------------------------------------------------------
84 void LCD_EnableDma(void)
85 {
86     if( (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY) == AT91C_LCDC_DMABUSY ) {
87         TRACE_DEBUG("LCD DMA BUSY E\n\r");
88     }
89     AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMAEN;
90 }
91
92 //------------------------------------------------------------------------------
93 /// Disables the DMA of the LCD controller.
94 //------------------------------------------------------------------------------
95 void LCD_DisableDma(void)
96 {
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 ) {
100     }
101     TRACE_DEBUG("LCD DMA is in IDLE state\n\r");
102 }
103
104 //------------------------------------------------------------------------------
105 /// Enables the selected LDC interrupt sources.
106 /// \param sources  Interrupt sources to enable.
107 //------------------------------------------------------------------------------
108 void LCD_EnableInterrupts(unsigned int sources)
109 {
110     AT91C_BASE_LCDC->LCDC_IER = sources;
111 }
112
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)
120 {
121     AT91C_BASE_LCDC->LCDC_LCDCON1 = ((masterClock / 2 / pixelClock) - 2) << 12;
122 }
123
124 //------------------------------------------------------------------------------
125 /// DMA reset
126 //------------------------------------------------------------------------------
127 void LCD_DMAReset(void)
128 {
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");
132     }
133     if( AT91C_LCDC_DMAEN == (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMAEN)) {
134         TRACE_ERROR("DMA Enabled, so NO DMA RESET\n\r");
135     }
136     AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMARST;
137 }
138
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)
144 {
145     unsigned int value;
146
147     ASSERT((displayType & ~AT91C_LCDC_DISTYPE) == 0,
148            "LCD_SetDisplayType: Wrong display type value.\n\r");
149
150     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
151     value &= ~AT91C_LCDC_DISTYPE;
152     value |= displayType;
153     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
154 }
155
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)
161 {
162     unsigned int value;
163
164     ASSERT((scanMode & ~AT91C_LCDC_SCANMOD) == 0,
165            "LCD_SetScanMode: Wrong scan mode value.\n\r");
166
167     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
168     value &= ~AT91C_LCDC_SCANMOD;
169     value |= scanMode;
170     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
171 }
172
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)
178 {
179     unsigned int value;
180
181     ASSERT((bitsPerPixel & ~AT91C_LCDC_PIXELSIZE) == 0,
182            "LCD_SetScanMode: Wrong bitsPerPixel value.\n\r");
183
184     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
185     value &= ~AT91C_LCDC_PIXELSIZE;
186     value |= bitsPerPixel;
187     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
188 }
189
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(
199     unsigned int lcdd,
200     unsigned int lcdvsync,
201     unsigned int lcdhsync,
202     unsigned int lcddotclk,
203     unsigned int lcdden)
204 {
205     unsigned int value;
206
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");
217
218     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
219     value &= 0xFFFFE0FF;
220     value |= lcdd | lcdvsync | lcdhsync | lcddotclk | lcdden;
221     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
222 }
223
224 //------------------------------------------------------------------------------
225 /// Sets the LCD clock mode, i.e. always active or active only during display
226 /// period.
227 /// \param clockMode  Clock mode to use.
228 //------------------------------------------------------------------------------
229 void LCD_SetClockMode(unsigned int clockMode)
230 {
231     unsigned int value;
232
233     ASSERT((clockMode & ~AT91C_LCDC_CLKMOD) == 0,
234            "LCD_SetScanMode: Wrong scan mode value.\n\r");
235
236     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
237     value &= ~AT91C_LCDC_CLKMOD;
238     value |= clockMode;
239     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
240 }
241
242 //------------------------------------------------------------------------------
243 /// Sets the format of the frame buffer memory.
244 /// \param format  Memory ordering format.
245 //------------------------------------------------------------------------------
246 void LCD_SetMemoryFormat(unsigned int format)
247 {
248     unsigned int value;
249
250     ASSERT((format & ~AT91C_LCDC_MEMOR) == 0,
251            "LCD_SetMemoryFormat: Wrong memory format value.\n\r");
252
253     value = AT91C_BASE_LCDC->LCDC_LCDCON2;
254     value &= ~AT91C_LCDC_MEMOR;
255     value |= format;
256     AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
257 }
258
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)
265 {
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");
270
271     AT91C_BASE_LCDC->LCDC_LCDFRCFG = ((width - 1) << 21) | (height - 1);
272 }
273
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(
284     unsigned int vfp,
285     unsigned int vbp,
286     unsigned int vpw,
287     unsigned int vhdly)
288 {
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");
297
298     AT91C_BASE_LCDC->LCDC_TIM1 = vfp
299                                  | (vbp << 8)
300                                  | ((vpw-1) << 16)
301                                  | ((vhdly-1) << 24);
302 }
303
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(
312     unsigned int hbp,
313     unsigned int hpw,
314     unsigned int hfp)
315 {
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");
322
323     AT91C_BASE_LCDC->LCDC_TIM2 = (hbp-1) | ((hpw-1) << 8) | ((hfp-1) << 24);
324 }
325
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)
332 {
333     void *pOldBuffer;
334     
335     pOldBuffer = (void *) AT91C_BASE_LCDC->LCDC_BA1;
336     AT91C_BASE_LCDC->LCDC_BA1 = (unsigned int) address;
337     
338     return pOldBuffer;
339 }
340
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)
346 {
347     ASSERT((frameSize & 0xFF800000) == 0,
348            "LCD_SetFrameSize: Wrong frameSize value.\n\r");
349
350     AT91C_BASE_LCDC->LCDC_FRMCFG = (frameSize& AT91C_LCDC_FRSIZE)
351                                  | (AT91C_BASE_LCDC->LCDC_FRMCFG & AT91C_LCDC_BLENGTH);
352 }
353
354 //------------------------------------------------------------------------------
355 /// Sets the DMA controller burst length.
356 /// \param burstLength  Desired burst length.
357 //------------------------------------------------------------------------------
358 void LCD_SetBurstLength(unsigned int burstLength)
359 {
360     ASSERT(((burstLength-1) & 0xFFFFFF80) == 0,
361            "LCD_SetBurstLength: Wrong burstLength value.\n\r");
362
363     AT91C_BASE_LCDC->LCDC_FRMCFG &= ~AT91C_LCDC_BLENGTH;
364     AT91C_BASE_LCDC->LCDC_FRMCFG |= (((burstLength-1) << 24) & AT91C_LCDC_BLENGTH);
365
366     AT91C_BASE_LCDC->LCDC_FIFO = (2048 - (2 * burstLength + 3)) & AT91C_LCDC_FIFOTH;
367 }
368
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)
374 {
375     ASSERT((prescaler & ~AT91C_LCDC_PS) == 0,
376            "LCD_SetContrastPrescaler: Wrong prescaler value\n\r");
377
378     AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_PS;
379     AT91C_BASE_LCDC->LCDC_CTRSTCON |= prescaler;
380 }
381
382 //------------------------------------------------------------------------------
383 /// Sets the polarity of the contrast PWM.
384 /// \param polarity  PWM polarity
385 //------------------------------------------------------------------------------
386 void LCD_SetContrastPolarity(unsigned int polarity)
387 {
388     ASSERT((polarity & ~AT91C_LCDC_POL) == 0,
389            "LCD_SetContrastPolarity: Wrong polarity value\n\r");
390
391     AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_POL;
392     AT91C_BASE_LCDC->LCDC_CTRSTCON |= polarity;
393 }
394
395 //------------------------------------------------------------------------------
396 /// Sets the threshold value of the constrast PWM.
397 /// \param value  PWM threshold value.
398 //------------------------------------------------------------------------------
399 void LCD_SetContrastValue(unsigned int value)
400 {
401     ASSERT((value & ~AT91C_LCDC_CVAL) == 0,
402            "LCD_SetContrastValue: Wrong value.\n\r");
403
404     AT91C_BASE_LCDC->LCDC_CTRSTVAL = value;
405 }
406
407 //------------------------------------------------------------------------------
408 /// Enables the contrast PWM generator.
409 //------------------------------------------------------------------------------
410 void LCD_EnableContrast(void)
411 {
412     AT91C_BASE_LCDC->LCDC_CTRSTCON |= AT91C_LCDC_ENA_PWMGEMENABLED;
413 }
414
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 //------------------------------------------------------------------------------
423 void LCD_DecodeRGB(
424     unsigned char *file,
425     unsigned char *bufferLCD,
426     unsigned int width,
427     unsigned int height,
428     unsigned char bpp)
429 {
430     unsigned int offsetLine=0, offsetLCD=0;
431     unsigned int offset=1;
432
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];
439                 offsetLine++;
440                 offsetLCD++;
441             }
442             //TRACE_DEBUG("add white\n\r");
443             while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
444                 bufferLCD[offsetLCD] = 0;
445                 //offsetLine++;
446                 offsetLCD++;
447             }
448         }
449         else {
450             //TRACE_DEBUG(">");
451             while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
452                 bufferLCD[offsetLCD] = file[offsetLine];
453                 offsetLine++;
454                 offsetLCD++;
455             }
456             //TRACE_DEBUG("r ");
457             while( offsetLine < (width*offset*(bpp/8)) ) {
458                 offsetLine++;
459             }            
460         }
461         offset++;
462     }        
463 }
464
465 #endif
466