]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3Sxxxx_Rowley/rit128x96x4.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / CORTEX_LM3Sxxxx_Rowley / rit128x96x4.c
1 //*****************************************************************************\r
2 //\r
3 // rit128x96x4.c - Driver for the RIT 128x96x4 graphical OLED display.\r
4 //\r
5 // Copyright (c) 2007 Luminary Micro, Inc.  All rights reserved.\r
6 // \r
7 // Software License Agreement\r
8 // \r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and\r
10 // exclusively on LMI's microcontroller products.\r
11 // \r
12 // The software is owned by LMI and/or its suppliers, and is protected under\r
13 // applicable copyright laws.  All rights are reserved.  Any use in violation\r
14 // of the foregoing restrictions may subject the user to criminal sanctions\r
15 // under applicable laws, as well as to civil liability for the breach of the\r
16 // terms and conditions of this license.\r
17 // \r
18 // THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED\r
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\r
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.\r
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR\r
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.\r
23 // \r
24 // This is part of revision 1504-conf of the Stellaris Peripheral Driver Library.\r
25 //\r
26 //*****************************************************************************\r
27 \r
28 //*****************************************************************************\r
29 //\r
30 //! \addtogroup ek_lm3sLM3S8962_api\r
31 //! @{\r
32 //\r
33 //*****************************************************************************\r
34 \r
35 #include "hw_ssi.h"\r
36 #include "hw_memmap.h"\r
37 #include "hw_sysctl.h"\r
38 #include "hw_types.h"\r
39 #include "debug.h"\r
40 #include "gpio.h"\r
41 #include "ssi.h"\r
42 #include "sysctl.h"\r
43 #include "rit128x96x4.h"\r
44 \r
45 //*****************************************************************************\r
46 //\r
47 // Macros that define the peripheral, port, and pin used for the OLEDDC\r
48 // panel control signal.\r
49 //\r
50 //*****************************************************************************\r
51 \r
52 unsigned long ulGPIOId = 0, ulGPIOBase = 0, ulOLEDDC_PIN = 0, ulOLEDEN_PIN = 0;\r
53 \r
54 #define LM3S8962_SYSCTL_PERIPH_GPIO_OLEDDC   SYSCTL_PERIPH_GPIOA\r
55 #define LM3S8962_GPIO_OLEDDC_BASE            GPIO_PORTA_BASE\r
56 #define LM3S8962_GPIO_OLEDDC_PIN             GPIO_PIN_6\r
57 #define LM3S8962_GPIO_OLEDEN_PIN             GPIO_PIN_7\r
58 \r
59 #define LM3S1968_SYSCTL_PERIPH_GPIO_OLEDDC   SYSCTL_PERIPH_GPIOH\r
60 #define LM3S1968_GPIO_OLEDDC_BASE            GPIO_PORTH_BASE\r
61 #define LM3S1968_GPIO_OLEDDC_PIN             GPIO_PIN_2\r
62 #define LM3S1968_GPIO_OLEDEN_PIN             GPIO_PIN_3\r
63 \r
64 \r
65 //*****************************************************************************\r
66 //\r
67 // Flag to indicate if SSI port is enabled for display usage.\r
68 //\r
69 //*****************************************************************************\r
70 static volatile tBoolean g_bSSIEnabled = false;\r
71 \r
72 //*****************************************************************************\r
73 //\r
74 // Buffer for storing sequences of command and data for the display.\r
75 //\r
76 //*****************************************************************************\r
77 static unsigned char g_pucBuffer[8];\r
78 \r
79 //*****************************************************************************\r
80 //\r
81 // Define the SSD1329 128x96x4 Remap Setting(s).  This will be used in\r
82 // several places in the code to switch between vertical and horizontal\r
83 // address incrementing.  Note that the controller support 128 rows while\r
84 // the RIT display only uses 96.\r
85 //\r
86 // The Remap Command (0xA0) takes one 8-bit parameter.  The parameter is\r
87 // defined as follows.\r
88 //\r
89 // Bit 7: Reserved\r
90 // Bit 6: Disable(0)/Enable(1) COM Split Odd Even\r
91 //        When enabled, the COM signals are split Odd on one side, even on\r
92 //        the other.  Otherwise, they are split 0-63 on one side, 64-127 on\r
93 //        the other.\r
94 // Bit 5: Reserved\r
95 // Bit 4: Disable(0)/Enable(1) COM Remap\r
96 //        When Enabled, ROW 0-127 map to COM 127-0 (i.e. reverse row order)\r
97 // Bit 3: Reserved\r
98 // Bit 2: Horizontal(0)/Vertical(1) Address Increment\r
99 //        When set, data RAM address will increment along the column rather\r
100 //        than along the row.\r
101 // Bit 1: Disable(0)/Enable(1) Nibble Remap\r
102 //        When enabled, the upper and lower nibbles in the DATA bus for access\r
103 //        to the data RAM are swapped.\r
104 // Bit 0: Disable(0)/Enable(1) Column Address Remap\r
105 //        When enabled, DATA RAM columns 0-63 are remapped to Segment Columns\r
106 //        127-0.\r
107 //\r
108 //*****************************************************************************\r
109 #define RIT_INIT_REMAP      0x52 // app note says 0x51\r
110 #define RIT_INIT_OFFSET     0x00\r
111 static const unsigned char g_pucRIT128x96x4VerticalInc[]   = { 0xA0, 0x56 };\r
112 static const unsigned char g_pucRIT128x96x4HorizontalInc[] = { 0xA0, 0x52 };\r
113 \r
114 //*****************************************************************************\r
115 //\r
116 // A 5x7 font (in a 6x8 cell, where the sixth column is omitted from this\r
117 // table) for displaying text on the OLED display.  The data is organized as\r
118 // bytes from the left column to the right column, with each byte containing\r
119 // the top row in the LSB and the bottom row in the MSB.\r
120 //\r
121 // Note:  This is the same font data that is used in the EK-LM3S811\r
122 // osram96x16x1 driver.  The single bit-per-pixel is expaned in the StringDraw\r
123 // function to the appropriate four bit-per-pixel gray scale format.\r
124 //\r
125 //*****************************************************************************\r
126 static const unsigned char g_pucFont[96][5] =\r
127 {\r
128     { 0x00, 0x00, 0x00, 0x00, 0x00 }, // " "\r
129     { 0x00, 0x00, 0x4f, 0x00, 0x00 }, // !\r
130     { 0x00, 0x07, 0x00, 0x07, 0x00 }, // "\r
131     { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #\r
132     { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $\r
133     { 0x23, 0x13, 0x08, 0x64, 0x62 }, // %\r
134     { 0x36, 0x49, 0x55, 0x22, 0x50 }, // &\r
135     { 0x00, 0x05, 0x03, 0x00, 0x00 }, // '\r
136     { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (\r
137     { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )\r
138     { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // *\r
139     { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // +\r
140     { 0x00, 0x50, 0x30, 0x00, 0x00 }, // ,\r
141     { 0x08, 0x08, 0x08, 0x08, 0x08 }, // -\r
142     { 0x00, 0x60, 0x60, 0x00, 0x00 }, // .\r
143     { 0x20, 0x10, 0x08, 0x04, 0x02 }, // /\r
144     { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 0\r
145     { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 1\r
146     { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2\r
147     { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 3\r
148     { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 4\r
149     { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5\r
150     { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 6\r
151     { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7\r
152     { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8\r
153     { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 9\r
154     { 0x00, 0x36, 0x36, 0x00, 0x00 }, // :\r
155     { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;\r
156     { 0x08, 0x14, 0x22, 0x41, 0x00 }, // <\r
157     { 0x14, 0x14, 0x14, 0x14, 0x14 }, // =\r
158     { 0x00, 0x41, 0x22, 0x14, 0x08 }, // >\r
159     { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?\r
160     { 0x32, 0x49, 0x79, 0x41, 0x3e }, // @\r
161     { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // A\r
162     { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // B\r
163     { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // C\r
164     { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // D\r
165     { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // E\r
166     { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // F\r
167     { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // G\r
168     { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // H\r
169     { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // I\r
170     { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // J\r
171     { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // K\r
172     { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // L\r
173     { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // M\r
174     { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // N\r
175     { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // O\r
176     { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // P\r
177     { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // Q\r
178     { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // R\r
179     { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S\r
180     { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // T\r
181     { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // U\r
182     { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // V\r
183     { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // W\r
184     { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X\r
185     { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y\r
186     { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z\r
187     { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // [\r
188     { 0x02, 0x04, 0x08, 0x10, 0x20 }, // "\"\r
189     { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // ]\r
190     { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^\r
191     { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _\r
192     { 0x00, 0x01, 0x02, 0x04, 0x00 }, // `\r
193     { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a\r
194     { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // b\r
195     { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c\r
196     { 0x38, 0x44, 0x44, 0x48, 0x7f }, // d\r
197     { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e\r
198     { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // f\r
199     { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // g\r
200     { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // h\r
201     { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // i\r
202     { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // j\r
203     { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // k\r
204     { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // l\r
205     { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // m\r
206     { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // n\r
207     { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o\r
208     { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // p\r
209     { 0x08, 0x14, 0x14, 0x18, 0x7c }, // q\r
210     { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // r\r
211     { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s\r
212     { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // t\r
213     { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // u\r
214     { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // v\r
215     { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // w\r
216     { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x\r
217     { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // y\r
218     { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // z\r
219     { 0x00, 0x08, 0x36, 0x41, 0x00 }, // {\r
220     { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // |\r
221     { 0x00, 0x41, 0x36, 0x08, 0x00 }, // }\r
222     { 0x02, 0x01, 0x02, 0x04, 0x02 }, // ~\r
223     { 0x02, 0x01, 0x02, 0x04, 0x02 }, // ~\r
224 };\r
225 \r
226 //*****************************************************************************\r
227 //\r
228 // The sequence of commands used to initialize the SSD1329 controller.  Each\r
229 // command is described as follows:  there is a byte specifying the number of\r
230 // bytes in the command sequence, followed by that many bytes of command data.\r
231 // Note:  This initialization sequence is derived from RIT App Note for\r
232 // the P14201.  Values used are from the RIT app note, except where noted.\r
233 //\r
234 //*****************************************************************************\r
235 static const unsigned char g_pucRIT128x96x4Init[] =\r
236 {\r
237     //\r
238     // Unlock commands\r
239     //\r
240     3, 0xFD, 0x12, 0xe3,\r
241 \r
242     //\r
243     // Display off\r
244     //\r
245     2, 0xAE, 0xe3,\r
246 \r
247     //\r
248     // Icon off\r
249     //\r
250     3, 0x94, 0, 0xe3,\r
251 \r
252     //\r
253     // Multiplex ratio\r
254     //\r
255     3, 0xA8, 95, 0xe3,\r
256 \r
257     //\r
258     // Contrast\r
259     //\r
260     3, 0x81, 0xb7, 0xe3,\r
261 \r
262     //\r
263     // Pre-charge current\r
264     //\r
265     3, 0x82, 0x3f, 0xe3,\r
266 \r
267     //\r
268     // Display Re-map\r
269     //\r
270     3, 0xA0, RIT_INIT_REMAP, 0xe3,\r
271 \r
272     //\r
273     // Display Start Line\r
274     //\r
275     3, 0xA1, 0, 0xe3,\r
276 \r
277     //\r
278     // Display Offset\r
279     //\r
280     3, 0xA2, RIT_INIT_OFFSET, 0xe3,\r
281 \r
282     //\r
283     // Display Mode Normal\r
284     //\r
285     2, 0xA4, 0xe3,\r
286 \r
287     //\r
288     // Phase Length\r
289     //\r
290     3, 0xB1, 0x11, 0xe3,\r
291 \r
292     //\r
293     // Frame frequency\r
294     //\r
295     3, 0xB2, 0x23, 0xe3,\r
296 \r
297     //\r
298     // Front Clock Divider\r
299     //\r
300     3, 0xB3, 0xe2, 0xe3,\r
301 \r
302     //\r
303     // Set gray scale table.  App note uses default command:\r
304     // 2, 0xB7, 0xe3\r
305     // This gray scale attempts some gamma correction to reduce the\r
306     // the brightness of the low levels.\r
307     //\r
308     17, 0xB8, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 19, 22, 26, 30, 0xe3,\r
309 \r
310     //\r
311     // Second pre-charge period. App note uses value 0x04.\r
312     //\r
313     3, 0xBB, 0x01, 0xe3,\r
314 \r
315     //\r
316     // Pre-charge voltage\r
317     //\r
318     3, 0xBC, 0x3f, 0xe3,\r
319 \r
320     //\r
321     // Display ON\r
322     //\r
323     2, 0xAF, 0xe3,\r
324 };\r
325 \r
326 //*****************************************************************************\r
327 //\r
328 //! \internal\r
329 //!\r
330 //! Write a sequence of command bytes to the SSD1329 controller.\r
331 //!\r
332 //! The data is written in a polled fashion; this function will not return\r
333 //! until the entire byte sequence has been written to the controller.\r
334 //!\r
335 //! \return None.\r
336 //\r
337 //*****************************************************************************\r
338 static void\r
339 RITWriteCommand(const unsigned char *pucBuffer, unsigned long ulCount)\r
340 {\r
341     unsigned long ulTemp;\r
342 \r
343     //\r
344     // Return if SSI port is not enabled for RIT display.\r
345     //\r
346     if(!g_bSSIEnabled)\r
347     {\r
348         return;\r
349     }\r
350 \r
351     //\r
352     // Clear the command/control bit to enable command mode.\r
353     //\r
354     GPIOPinWrite(ulGPIOBase, ulOLEDDC_PIN, 0); \r
355 \r
356     //\r
357     // Loop while there are more bytes left to be transferred.\r
358     //\r
359     while(ulCount != 0)\r
360     {\r
361         //\r
362         // Write the next byte to the controller.\r
363         //\r
364         SSIDataPut(SSI0_BASE, *pucBuffer++);\r
365 \r
366         //\r
367         // Dummy read to drain the fifo and time the GPIO signal.\r
368         //\r
369         SSIDataGet(SSI0_BASE, &ulTemp);\r
370 \r
371         //\r
372         // Decrement the BYTE counter.\r
373         //\r
374         ulCount--;\r
375     }\r
376 }\r
377 \r
378 //*****************************************************************************\r
379 //\r
380 //! \internal\r
381 //!\r
382 //! Write a sequence of data bytes to the SSD1329 controller.\r
383 //!\r
384 //! The data is written in a polled fashion; this function will not return\r
385 //! until the entire byte sequence has been written to the controller.\r
386 //!\r
387 //! \return None.\r
388 //\r
389 //*****************************************************************************\r
390 static void\r
391 RITWriteData(const unsigned char *pucBuffer, unsigned long ulCount)\r
392 {\r
393     unsigned long ulTemp;\r
394 \r
395     //\r
396     // Return if SSI port is not enabled for RIT display.\r
397     //\r
398     if(!g_bSSIEnabled)\r
399     {\r
400         return;\r
401     }\r
402 \r
403     //\r
404     // Set the command/control bit to enable data mode.\r
405     //\r
406     GPIOPinWrite(ulGPIOBase, ulOLEDDC_PIN, ulOLEDDC_PIN);\r
407 \r
408     //\r
409     // Loop while there are more bytes left to be transferred.\r
410     //\r
411     while(ulCount != 0)\r
412     {\r
413         //\r
414         // Write the next byte to the controller.\r
415         //\r
416         SSIDataPut(SSI0_BASE, *pucBuffer++);\r
417 \r
418         //\r
419         // Dummy read to drain the fifo and time the GPIO signal.\r
420         //\r
421         SSIDataGet(SSI0_BASE, &ulTemp);\r
422 \r
423         //\r
424         // Decrement the BYTE counter.\r
425         //\r
426         ulCount--;\r
427     }\r
428 }\r
429 \r
430 //*****************************************************************************\r
431 //\r
432 //! Clears the OLED display.\r
433 //!\r
434 //! This function will clear the display RAM.  All pixels in the display will\r
435 //! be turned off.\r
436 //!\r
437 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
438 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
439 //! applications.\r
440 //!\r
441 //! \return None.\r
442 //\r
443 //*****************************************************************************\r
444 void\r
445 RIT128x96x4Clear(void)\r
446 {\r
447     static const unsigned char pucCommand1[] = { 0x15, 0, 63 };\r
448     static const unsigned char pucCommand2[] = { 0x75, 0, 127 };\r
449     unsigned long ulRow, ulColumn;\r
450 \r
451     //\r
452     // Clear out the buffer used for sending bytes to the display.\r
453     *(unsigned long *)&g_pucBuffer[0] = 0;\r
454     *(unsigned long *)&g_pucBuffer[4] = 0;\r
455 \r
456     //\r
457     // Set the window to fill the entire display.\r
458     //\r
459     RITWriteCommand(pucCommand1, sizeof(pucCommand1));\r
460     RITWriteCommand(pucCommand2, sizeof(pucCommand2));\r
461     RITWriteCommand(g_pucRIT128x96x4HorizontalInc,\r
462                     sizeof(g_pucRIT128x96x4HorizontalInc));\r
463 \r
464     //\r
465     // Loop through the rows\r
466     //\r
467     for(ulRow = 0; ulRow < 96; ulRow++)\r
468     {\r
469         //\r
470         // Loop through the columns.  Each byte is two pixels,\r
471         // and the buffer hold 8 bytes, so 16 pixels are cleared\r
472         // at a time.\r
473         //\r
474         for(ulColumn = 0; ulColumn < 128; ulColumn += 8 * 2)\r
475         {\r
476             //\r
477             // Write 8 clearing bytes to the display, which will\r
478             // clear 16 pixels across.\r
479             //\r
480             RITWriteData(g_pucBuffer, sizeof(g_pucBuffer));\r
481         }\r
482     }\r
483 }\r
484 \r
485 //*****************************************************************************\r
486 //\r
487 //! Displays a string on the OLED display.\r
488 //!\r
489 //! \param pcStr is a pointer to the string to display.\r
490 //! \param ulX is the horizontal position to display the string, specified in\r
491 //! columns from the left edge of the display.\r
492 //! \param ulY is the vertical position to display the string, specified in\r
493 //! rows from the top edge of the display.\r
494 //! \param ucLevel is the 4-bit grey scale value to be used for displayed text.\r
495 //!\r
496 //! This function will draw a string on the display.  Only the ASCII characters\r
497 //! between 32 (space) and 126 (tilde) are supported; other characters will\r
498 //! result in random data being draw on the display (based on whatever appears\r
499 //! before/after the font in memory).  The font is mono-spaced, so characters\r
500 //! such as "i" and "l" have more white space around them than characters such\r
501 //! as "m" or "w".\r
502 //!\r
503 //! If the drawing of the string reaches the right edge of the display, no more\r
504 //! characters will be drawn.  Therefore, special care is not required to avoid\r
505 //! supplying a string that is "too long" to display.\r
506 //!\r
507 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
508 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
509 //! applications.\r
510 //!\r
511 //! \note Because the OLED display packs 2 pixels of data in a single byte, the\r
512 //! parameter \e ulX must be an even column number (e.g. 0, 2, 4, etc).\r
513 //!\r
514 //! \return None.\r
515 //\r
516 //*****************************************************************************\r
517 void\r
518 RIT128x96x4StringDraw(const char *pcStr, unsigned long ulX,\r
519                       unsigned long ulY, unsigned char ucLevel)\r
520 {\r
521     unsigned long ulIdx1, ulIdx2;\r
522     unsigned char ucTemp;\r
523 \r
524     //\r
525     // Check the arguments.\r
526     //\r
527     ASSERT(ulX < 128);\r
528     ASSERT((ulX & 1) == 0);\r
529     ASSERT(ulY < 96);\r
530     ASSERT(ucLevel < 16);\r
531 \r
532     //\r
533     // Setup a window starting at the specified column and row, ending\r
534     // at the right edge of the display and 8 rows down (single character row).\r
535     //\r
536     g_pucBuffer[0] = 0x15;\r
537     g_pucBuffer[1] = ulX / 2;\r
538     g_pucBuffer[2] = 63;\r
539     RITWriteCommand(g_pucBuffer, 3);\r
540     g_pucBuffer[0] = 0x75;\r
541     g_pucBuffer[1] = ulY;\r
542     g_pucBuffer[2] = ulY + 7;\r
543     RITWriteCommand(g_pucBuffer, 3);\r
544     RITWriteCommand(g_pucRIT128x96x4VerticalInc,\r
545                     sizeof(g_pucRIT128x96x4VerticalInc));\r
546 \r
547     //\r
548     // Loop while there are more characters in the string.\r
549     //\r
550     while(*pcStr != 0)\r
551     {\r
552         //\r
553         // Get a working copy of the current character and convert to an\r
554         // index into the character bit-map array.\r
555         //\r
556         ucTemp = *pcStr;\r
557         ucTemp &= 0x7F;\r
558         if(ucTemp < ' ')\r
559         {\r
560             ucTemp = ' ';\r
561         }\r
562         else\r
563         {\r
564             ucTemp -= ' ';\r
565         }\r
566 \r
567         //\r
568         // Build and display the character buffer.\r
569         //\r
570         for(ulIdx1 = 0; ulIdx1 < 3; ulIdx1++)\r
571         {\r
572             //\r
573             // Convert two columns of 1-bit font data into a single data\r
574             // byte column of 4-bit font data.\r
575             //\r
576             for(ulIdx2 = 0; ulIdx2 < 8; ulIdx2++)\r
577             {\r
578                 g_pucBuffer[ulIdx2] = 0;\r
579                 if(g_pucFont[ucTemp][ulIdx1*2] & (1 << ulIdx2))\r
580                 {\r
581                     g_pucBuffer[ulIdx2] = ((ucLevel << 4) & 0xf0);\r
582                 }\r
583                 if((ulIdx1 < 2) &&\r
584                     (g_pucFont[ucTemp][ulIdx1*2+1] & (1 << ulIdx2)))\r
585                 {\r
586                     g_pucBuffer[ulIdx2] |= ((ucLevel << 0) & 0x0f);\r
587                 }\r
588             }\r
589 \r
590             //\r
591             // If there is room, dump the single data byte column to the\r
592             // display.  Otherwise, bail out.\r
593             //\r
594             if(ulX < 126)\r
595             {\r
596                 RITWriteData(g_pucBuffer, 8);\r
597                 ulX += 2;\r
598             }\r
599             else\r
600             {\r
601                 return;\r
602             }\r
603         }\r
604 \r
605         //\r
606         // Advance to the next character.\r
607         //\r
608         pcStr++;\r
609     }\r
610 }\r
611 \r
612 //*****************************************************************************\r
613 //\r
614 //! Displays an image on the OLED display.\r
615 //!\r
616 //! \param pucImage is a pointer to the image data.\r
617 //! \param ulX is the horizontal position to display this image, specified in\r
618 //! columns from the left edge of the display.\r
619 //! \param ulY is the vertical position to display this image, specified in\r
620 //! rows from the top of the display.\r
621 //! \param ulWidth is the width of the image, specified in columns.\r
622 //! \param ulHeight is the height of the image, specified in rows.\r
623 //!\r
624 //! This function will display a bitmap graphic on the display.  Because of the\r
625 //! format of the display RAM, the starting column (\e ulX) and the number of\r
626 //! columns (\e ulWidth) must be an integer multiple of two.\r
627 //!\r
628 //! The image data is organized with the first row of image data appearing left\r
629 //! to right, followed immediately by the second row of image data.  Each byte\r
630 //! contains the data for two columns in the current row, with the leftmost\r
631 //! column being contained in bits 7:4 and the rightmost column being contained\r
632 //! in bits 3:0.\r
633 //!\r
634 //! For example, an image six columns wide and seven scan lines tall would\r
635 //! be arranged as follows (showing how the twenty one bytes of the image would\r
636 //! appear on the display):\r
637 //!\r
638 //! \verbatim\r
639 //!     +-------------------+-------------------+-------------------+\r
640 //!     |      Byte 0       |      Byte 1       |      Byte 2       |\r
641 //!     +---------+---------+---------+---------+---------+---------+\r
642 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
643 //!     +---------+---------+---------+---------+---------+---------+\r
644 //!     |      Byte 3       |      Byte 4       |      Byte 5       |\r
645 //!     +---------+---------+---------+---------+---------+---------+\r
646 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
647 //!     +---------+---------+---------+---------+---------+---------+\r
648 //!     |      Byte 6       |      Byte 7       |      Byte 8       |\r
649 //!     +---------+---------+---------+---------+---------+---------+\r
650 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
651 //!     +---------+---------+---------+---------+---------+---------+\r
652 //!     |      Byte 9       |      Byte 10      |      Byte 11      |\r
653 //!     +---------+---------+---------+---------+---------+---------+\r
654 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
655 //!     +---------+---------+---------+---------+---------+---------+\r
656 //!     |      Byte 12      |      Byte 13      |      Byte 14      |\r
657 //!     +---------+---------+---------+---------+---------+---------+\r
658 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
659 //!     +---------+---------+---------+---------+---------+---------+\r
660 //!     |      Byte 15      |      Byte 16      |      Byte 17      |\r
661 //!     +---------+---------+---------+---------+---------+---------+\r
662 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
663 //!     +---------+---------+---------+---------+---------+---------+\r
664 //!     |      Byte 18      |      Byte 19      |      Byte 20      |\r
665 //!     +---------+---------+---------+---------+---------+---------+\r
666 //!     | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 | 7 6 5 4 | 3 2 1 0 |\r
667 //!     +---------+---------+---------+---------+---------+---------+\r
668 //! \endverbatim\r
669 //!\r
670 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
671 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
672 //! applications.\r
673 //!\r
674 //! \return None.\r
675 //\r
676 //*****************************************************************************\r
677 void\r
678 RIT128x96x4ImageDraw(const unsigned char *pucImage, unsigned long ulX,\r
679                      unsigned long ulY, unsigned long ulWidth,\r
680                      unsigned long ulHeight)\r
681 {\r
682     //\r
683     // Check the arguments.\r
684     //\r
685     ASSERT(ulX < 128);\r
686     ASSERT((ulX & 1) == 0);\r
687     ASSERT(ulY < 96);\r
688     ASSERT((ulX + ulWidth) <= 128);\r
689     ASSERT((ulY + ulHeight) <= 96);\r
690     ASSERT((ulWidth & 1) == 0);\r
691 \r
692     //\r
693     // Setup a window starting at the specified column and row, and ending\r
694     // at the column + width and row+height.\r
695     //\r
696     g_pucBuffer[0] = 0x15;\r
697     g_pucBuffer[1] = ulX / 2;\r
698     g_pucBuffer[2] = (ulX + ulWidth - 2) / 2;\r
699     RITWriteCommand(g_pucBuffer, 3);\r
700     g_pucBuffer[0] = 0x75;\r
701     g_pucBuffer[1] = ulY;\r
702     g_pucBuffer[2] = ulY + ulHeight - 1;\r
703     RITWriteCommand(g_pucBuffer, 3);\r
704     RITWriteCommand(g_pucRIT128x96x4HorizontalInc,\r
705                     sizeof(g_pucRIT128x96x4HorizontalInc));\r
706 \r
707     //\r
708     // Loop while there are more rows to display.\r
709     //\r
710     while(ulHeight--)\r
711     {\r
712         //\r
713         // Write this row of image data.\r
714         //\r
715         RITWriteData(pucImage, (ulWidth / 2));\r
716 \r
717         //\r
718         // Advance to the next row of the image.\r
719         //\r
720         pucImage += (ulWidth / 2);\r
721     }\r
722 }\r
723 \r
724 //*****************************************************************************\r
725 //\r
726 //! Enable the SSI component of the OLED display driver.\r
727 //!\r
728 //! \param ulFrequency specifies the SSI Clock Frequency to be used.\r
729 //!\r
730 //! This function initializes the SSI interface to the OLED display.\r
731 //!\r
732 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
733 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
734 //! applications.\r
735 //!\r
736 //! \return None.\r
737 //\r
738 //*****************************************************************************\r
739 void\r
740 RIT128x96x4Enable(unsigned long ulFrequency)\r
741 {\r
742     unsigned long ulTemp;\r
743 \r
744     //\r
745     // Disable the SSI port.\r
746     //\r
747     SSIDisable(SSI0_BASE);\r
748 \r
749     //\r
750     // Configure the SSI0 port for master mode.\r
751     //\r
752     SSIConfig(SSI0_BASE, SSI_FRF_MOTO_MODE_2, SSI_MODE_MASTER, ulFrequency, 8);\r
753 \r
754     //\r
755     // (Re)Enable SSI control of the FSS pin.\r
756     //\r
757     GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_3);\r
758     GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_STRENGTH_8MA,\r
759                      GPIO_PIN_TYPE_STD_WPU);\r
760 \r
761     //\r
762     // Enable the SSI port.\r
763     //\r
764     SSIEnable(SSI0_BASE);\r
765 \r
766     //\r
767     // Drain the receive fifo.\r
768     //\r
769     while(SSIDataNonBlockingGet(SSI0_BASE, &ulTemp) != 0)\r
770     {\r
771     }\r
772 \r
773     //\r
774     // Indicate that the RIT driver can use the SSI Port.\r
775     //\r
776     g_bSSIEnabled = true;\r
777 }\r
778 \r
779 //*****************************************************************************\r
780 //\r
781 //! Enable the SSI component of the OLED display driver.\r
782 //!\r
783 //! This function initializes the SSI interface to the OLED display.\r
784 //!\r
785 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
786 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
787 //! applications.\r
788 //!\r
789 //! \return None.\r
790 //\r
791 //*****************************************************************************\r
792 void\r
793 RIT128x96x4Disable(void)\r
794 {\r
795     unsigned long ulTemp;\r
796 \r
797     //\r
798     // Indicate that the RIT driver can no longer use the SSI Port.\r
799     //\r
800     g_bSSIEnabled = false;\r
801 \r
802     //\r
803     // Drain the receive fifo.\r
804     //\r
805     while(SSIDataNonBlockingGet(SSI0_BASE, &ulTemp) != 0)\r
806     {\r
807     }\r
808 \r
809     //\r
810     // Disable the SSI port.\r
811     //\r
812     SSIDisable(SSI0_BASE);\r
813 \r
814     //\r
815     // Disable SSI control of the FSS pin.\r
816     //\r
817     GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);\r
818     GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_STRENGTH_8MA,\r
819                      GPIO_PIN_TYPE_STD_WPU);\r
820     GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3);\r
821 }\r
822 \r
823 //*****************************************************************************\r
824 //\r
825 //! Initialize the OLED display.\r
826 //!\r
827 //! \param ulFrequency specifies the SSI Clock Frequency to be used.\r
828 //!\r
829 //! This function initializes the SSI interface to the OLED display and\r
830 //! configures the SSD1329 controller on the panel.\r
831 //!\r
832 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
833 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
834 //! applications.\r
835 //!\r
836 //! \return None.\r
837 //\r
838 //*****************************************************************************\r
839 void\r
840 RIT128x96x4Init(unsigned long ulFrequency)\r
841 {\r
842     unsigned long ulIdx;\r
843 \r
844 \r
845         /* Determine which board is being used. */\r
846         if( SysCtlPeripheralPresent( SYSCTL_PERIPH_ETH ) )\r
847         {\r
848                 /* Ethernet is present, we must be using the LM3S8962 EK. */\r
849                 ulGPIOId = LM3S8962_SYSCTL_PERIPH_GPIO_OLEDDC;\r
850                 ulGPIOBase = LM3S8962_GPIO_OLEDDC_BASE;\r
851                 ulOLEDDC_PIN = GPIO_PIN_6;\r
852                 ulOLEDEN_PIN = GPIO_PIN_7;\r
853         }\r
854         else\r
855         {\r
856                 /* Ethernet is not present, we must be using the LM3S1968 EK. */\r
857                 ulGPIOId = LM3S1968_SYSCTL_PERIPH_GPIO_OLEDDC;\r
858                 ulGPIOBase = LM3S1968_GPIO_OLEDDC_BASE;\r
859                 ulOLEDDC_PIN = GPIO_PIN_2;\r
860                 ulOLEDEN_PIN = GPIO_PIN_3;\r
861         }\r
862 \r
863     //\r
864     // Enable the SSI0 and GPIO port blocks as they are needed by this driver.\r
865     //\r
866     SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);\r
867     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);\r
868     SysCtlPeripheralEnable(ulGPIOId); \r
869 \r
870     //\r
871     // Configure the SSI0CLK and SSIOTX pins for SSI operation.\r
872     //\r
873     GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_5);\r
874     GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_5,\r
875                      GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU);\r
876 \r
877     //\r
878     // Configure the GPIO port pin used as a D/Cn signal for OLED device,\r
879     // and the port pin used to enable power to the OLED panel.\r
880     //\r
881     GPIOPinTypeGPIOOutput(ulGPIOBase, ulOLEDDC_PIN | ulOLEDEN_PIN);\r
882     GPIOPadConfigSet(ulGPIOBase, ulOLEDDC_PIN | ulOLEDEN_PIN,\r
883                      GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);\r
884     GPIOPinWrite(ulGPIOBase, ulOLEDDC_PIN | ulOLEDEN_PIN,\r
885                  ulOLEDDC_PIN | ulOLEDEN_PIN);\r
886 \r
887     //\r
888     // Configure and enable the SSI0 port for master mode.\r
889     //\r
890     RIT128x96x4Enable(ulFrequency);\r
891 \r
892     //\r
893     // Clear the frame buffer.\r
894     //\r
895     RIT128x96x4Clear();\r
896 \r
897     //\r
898     // Initialize the SSD1329 controller.  Loop through the initialization\r
899     // sequence array, sending each command "string" to the controller.\r
900     //\r
901     for(ulIdx = 0; ulIdx < sizeof(g_pucRIT128x96x4Init);\r
902         ulIdx += g_pucRIT128x96x4Init[ulIdx] + 1)\r
903     {\r
904         //\r
905         // Send this command.\r
906         //\r
907         RITWriteCommand(g_pucRIT128x96x4Init + ulIdx + 1,\r
908                         g_pucRIT128x96x4Init[ulIdx] - 1);\r
909     }\r
910 }\r
911 \r
912 //*****************************************************************************\r
913 //\r
914 //! Turns on the OLED display.\r
915 //!\r
916 //! This function will turn on the OLED display, causing it to display the\r
917 //! contents of its internal frame buffer.\r
918 //!\r
919 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
920 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
921 //! applications.\r
922 //!\r
923 //! \return None.\r
924 //\r
925 //*****************************************************************************\r
926 void\r
927 RIT128x96x4DisplayOn(void)\r
928 {\r
929     unsigned long ulIdx;\r
930 \r
931     //\r
932     // Initialize the SSD1329 controller.  Loop through the initialization\r
933     // sequence array, sending each command "string" to the controller.\r
934     //\r
935     for(ulIdx = 0; ulIdx < sizeof(g_pucRIT128x96x4Init);\r
936         ulIdx += g_pucRIT128x96x4Init[ulIdx] + 1)\r
937     {\r
938         //\r
939         // Send this command.\r
940         //\r
941         RITWriteCommand(g_pucRIT128x96x4Init + ulIdx + 1,\r
942                         g_pucRIT128x96x4Init[ulIdx] - 1);\r
943     }\r
944 }\r
945 \r
946 //*****************************************************************************\r
947 //\r
948 //! Turns off the OLED display.\r
949 //!\r
950 //! This function will turn off the OLED display.  This will stop the scanning\r
951 //! of the panel and turn off the on-chip DC-DC converter, preventing damage to\r
952 //! the panel due to burn-in (it has similar characters to a CRT in this\r
953 //! respect).\r
954 //!\r
955 //! This function is contained in <tt>rit128x96x4.c</tt>, with\r
956 //! <tt>rit128x96x4.h</tt> containing the API definition for use by\r
957 //! applications.\r
958 //!\r
959 //! \return None.\r
960 //\r
961 //*****************************************************************************\r
962 void\r
963 RIT128x96x4DisplayOff(void)\r
964 {\r
965     static const unsigned char pucCommand1[] =\r
966     {\r
967         0xAE, 0xe3\r
968     };\r
969 \r
970     //\r
971     // Put the display to sleep.\r
972     //\r
973     RITWriteCommand(pucCommand1, sizeof(pucCommand1));\r
974 }\r
975 \r
976 //*****************************************************************************\r
977 //\r
978 // Close the Doxygen group.\r
979 //! @}\r
980 //\r
981 //*****************************************************************************\r