]> begriffs open source - cmsis-freertos/blob - Demo/CORTEX_LM3S811_KEIL/LuminaryCode/osram96x16.c
there was an extra ')'... caused build to fail
[cmsis-freertos] / Demo / CORTEX_LM3S811_KEIL / LuminaryCode / osram96x16.c
1 //*****************************************************************************
2 //
3 // osram96x16.c - Driver for the OSRAM 96x16 graphical OLED display.
4 //
5 // Copyright (c) 2006 Luminary Micro, Inc.  All rights reserved.
6 //
7 // Software License Agreement
8 //
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10 // exclusively on LMI's Stellaris Family of microcontroller products.
11 //
12 // The software is owned by LMI and/or its suppliers, and is protected under
13 // applicable copyright laws.  All rights are reserved.  Any use in violation
14 // of the foregoing restrictions may subject the user to criminal sanctions
15 // under applicable laws, as well as to civil liability for the breach of the
16 // terms and conditions of this license.
17 //
18 // THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
23 //
24 // This is part of revision 816 of the Stellaris Driver Library.
25 //
26 //*****************************************************************************
27
28 //*****************************************************************************
29 //
30 //! \addtogroup ev_lm3s811_api
31 //! @{
32 //
33 //*****************************************************************************
34
35 #include "hw_i2c.h"
36 #include "hw_memmap.h"
37 #include "hw_sysctl.h"
38 #include "hw_types.h"
39 #include "src/debug.h"
40 #include "src/gpio.h"
41 #include "src/i2c.h"
42 #include "src/sysctl.h"
43 #include "osram96x16.h"
44
45 extern void I2CMasterInitExpClk(unsigned long ulBase, unsigned long ulI2CClk,  tBoolean bFast);
46 //*****************************************************************************
47 //
48 // The I2C slave address of the SSD0303 controller on the OLED display.
49 //
50 //*****************************************************************************
51 #define SSD0303_ADDR            0x3d
52
53 //*****************************************************************************
54 //
55 // A 5x7 font (in a 6x8 cell, where the sixth column is omitted from this
56 // table) for displaying text on the OLED display.  The data is organized as
57 // bytes from the left column to the right column, with each byte containing
58 // the top row in the LSB and the bottom row in the MSB.
59 //
60 //*****************************************************************************
61 static const unsigned char g_pucFont[95][5] =
62 {
63     { 0x00, 0x00, 0x00, 0x00, 0x00 }, // " "
64     { 0x00, 0x00, 0x4f, 0x00, 0x00 }, // !
65     { 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
66     { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
67     { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
68     { 0x23, 0x13, 0x08, 0x64, 0x62 }, // %
69     { 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
70     { 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
71     { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
72     { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
73     { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // *
74     { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // +
75     { 0x00, 0x50, 0x30, 0x00, 0x00 }, // ,
76     { 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
77     { 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
78     { 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
79     { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 0
80     { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 1
81     { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
82     { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 3
83     { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 4
84     { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
85     { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 6
86     { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
87     { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
88     { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 9
89     { 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
90     { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
91     { 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
92     { 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
93     { 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
94     { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
95     { 0x32, 0x49, 0x79, 0x41, 0x3e }, // @
96     { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // A
97     { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // B
98     { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // C
99     { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // D
100     { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // E
101     { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // F
102     { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // G
103     { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // H
104     { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // I
105     { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // J
106     { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // K
107     { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // L
108     { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // M
109     { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // N
110     { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // O
111     { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // P
112     { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // Q
113     { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // R
114     { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
115     { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // T
116     { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // U
117     { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // V
118     { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // W
119     { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
120     { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
121     { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
122     { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // [
123     { 0x02, 0x04, 0x08, 0x10, 0x20 }, // "\"
124     { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // ]
125     { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
126     { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
127     { 0x00, 0x01, 0x02, 0x04, 0x00 }, // `
128     { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
129     { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // b
130     { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
131     { 0x38, 0x44, 0x44, 0x48, 0x7f }, // d
132     { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
133     { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // f
134     { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // g
135     { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // h
136     { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // i
137     { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // j
138     { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // k
139     { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // l
140     { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // m
141     { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // n
142     { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
143     { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // p
144     { 0x08, 0x14, 0x14, 0x18, 0x7c }, // q
145     { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // r
146     { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
147     { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // t
148     { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // u
149     { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // v
150     { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // w
151     { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
152     { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // y
153     { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // z
154     { 0x00, 0x08, 0x36, 0x41, 0x00 }, // {
155     { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // |
156     { 0x00, 0x41, 0x36, 0x08, 0x00 }, // }
157     { 0x02, 0x01, 0x02, 0x04, 0x02 }, // ~
158 };
159
160 //*****************************************************************************
161 //
162 // The sequence of commands used to initialize the SSD0303 controller.  Each
163 // command is described as follows:  there is a byte specifying the number of
164 // bytes in the I2C transfer, followed by that many bytes of command data.
165 //
166 //*****************************************************************************
167 static const unsigned char g_pucOSRAMInit[] =
168 {
169     //
170     // Turn off the panel
171     //
172     0x02, 0x80, 0xae,
173
174     //
175     // Set lower column address
176     //
177     0x02, 0x80, 0x04,
178
179     //
180     // Set higher column address
181     //
182     0x02, 0x80, 0x12,
183
184     //
185     // Set contrast control register
186     //
187     0x04, 0x80, 0x81, 0x80, 0x2b,
188
189     //
190     // Set segment re-map
191     //
192     0x02, 0x80, 0xa1,
193
194     //
195     // Set display start line
196     //
197     0x02, 0x80, 0x40,
198
199     //
200     // Set display offset
201     //
202     0x04, 0x80, 0xd3, 0x80, 0x00,
203
204     //
205     // Set multiplex ratio
206     //
207     0x04, 0x80, 0xa8, 0x80, 0x0f,
208
209     //
210     // Set the display to normal mode
211     //
212     0x02, 0x80, 0xa4,
213
214     //
215     // Non-inverted display
216     //
217     0x02, 0x80, 0xa6,
218
219     //
220     // Set the page address
221     //
222     0x02, 0x80, 0xb0,
223
224     //
225     // Set COM output scan direction
226     //
227     0x02, 0x80, 0xc8,
228
229     //
230     // Set display clock divide ratio/oscillator frequency
231     //
232     0x04, 0x80, 0xd5, 0x80, 0x72,
233
234     //
235     // Enable mono mode
236     //
237     0x04, 0x80, 0xd8, 0x80, 0x00,
238
239     //
240     // Set pre-charge period
241     //
242     0x04, 0x80, 0xd9, 0x80, 0x22,
243
244     //
245     // Set COM pins hardware configuration
246     //
247     0x04, 0x80, 0xda, 0x80, 0x12,
248
249     //
250     // Set VCOM deslect level
251     //
252     0x04, 0x80, 0xdb, 0x80, 0x0f,
253
254     //
255     // Set DC-DC on
256     //
257     0x04, 0x80, 0xad, 0x80, 0x8b,
258
259     //
260     // Turn on the panel
261     //
262     0x02, 0x80, 0xaf,
263 };
264
265 //*****************************************************************************
266 //
267 // The inter-byte delay required by the SSD0303 OLED controller.
268 //
269 //*****************************************************************************
270 static unsigned long g_ulDelay;
271
272 //*****************************************************************************
273 //
274 //! \internal
275 //!
276 //! Provide a small delay.
277 //!
278 //! \param ulCount is the number of delay loop iterations to perform.
279 //!
280 //! Since the SSD0303 controller needs a delay between bytes written to it over
281 //! the I2C bus, this function provides a means of generating that delay.  It
282 //! is written in assembly to keep the delay consistent across tool chains,
283 //! avoiding the need to tune the delay based on the tool chain in use.
284 //!
285 //! \return None.
286 //
287 //*****************************************************************************
288 #if defined(ewarm)
289 static void
290 OSRAMDelay(unsigned long ulCount)
291 {
292     __asm("    subs    r0, #1\n"
293           "    bne     OSRAMDelay\n"
294           "    bx      lr");
295 }
296 #endif
297 #if defined(gcc)
298 static void __attribute__((naked))
299 OSRAMDelay(unsigned long ulCount)
300 {
301     __asm("    subs    r0, #1\n"
302           "    bne     OSRAMDelay\n"
303           "    bx      lr");
304 }
305 #endif
306 #if defined(rvmdk) || defined(__ARMCC_VERSION)
307 __asm void
308 OSRAMDelay(unsigned long ulCount)
309 {
310     subs    r0, #1;
311     bne     OSRAMDelay;
312     bx      lr;
313 }
314 #endif
315
316 //*****************************************************************************
317 //
318 //! \internal
319 //!
320 //! Start a transfer to the SSD0303 controller.
321 //!
322 //! \param ucChar is the first byte to be written to the controller.
323 //!
324 //! This function will start a transfer to the SSD0303 controller via the I2C
325 //! bus.
326 //!
327 //! The data is written in a polled fashion; this function will not return
328 //! until the byte has been written to the controller.
329 //!
330 //! \return None.
331 //
332 //*****************************************************************************
333 static void
334 OSRAMWriteFirst(unsigned char ucChar)
335 {
336     //
337     // Set the slave address.
338     //
339     I2CMasterSlaveAddrSet(I2C_MASTER_BASE, SSD0303_ADDR, false);
340
341     //
342     // Write the first byte to the controller.
343     //
344     I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
345
346     //
347     // Start the transfer.
348     //
349     I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
350 }
351
352 //*****************************************************************************
353 //
354 //! \internal
355 //!
356 //! Write a byte to the SSD0303 controller.
357 //!
358 //! \param ucChar is the byte to be transmitted to the controller.
359 //!
360 //! This function continues a transfer to the SSD0303 controller by writing
361 //! another byte over the I2C bus.  This must only be called after calling
362 //! OSRAMWriteFirst(), but before calling OSRAMWriteFinal().
363 //!
364 //! The data is written in a polled faashion; this function will not return
365 //! until the byte has been written to the controller.
366 //!
367 //! \return None.
368 //
369 //*****************************************************************************
370 static void
371 OSRAMWriteByte(unsigned char ucChar)
372 {
373     //
374     // Wait until the current byte has been transferred.
375     //
376     while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
377     {
378     }
379
380     //
381     // Provide the required inter-byte delay.
382     //
383     OSRAMDelay(g_ulDelay);
384
385     //
386     // Write the next byte to the controller.
387     //
388     I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
389
390     //
391     // Continue the transfer.
392     //
393     I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
394 }
395
396 //*****************************************************************************
397 //
398 //! \internal
399 //!
400 //! Write a sequence of bytes to the SSD0303 controller.
401 //!
402 //! This function continues a transfer to the SSD0303 controller by writing a
403 //! sequence of bytes over the I2C bus.  This must only be called after calling
404 //! OSRAMWriteFirst(), but before calling OSRAMWriteFinal().
405 //!
406 //! The data is written in a polled fashion; this function will not return
407 //! until the entire byte sequence has been written to the controller.
408 //!
409 //! \return None.
410 //
411 //*****************************************************************************
412 static void
413 OSRAMWriteArray(const unsigned char *pucBuffer, unsigned long ulCount)
414 {
415     //
416     // Loop while there are more bytes left to be transferred.
417     //
418     while(ulCount != 0)
419     {
420         //
421         // Wait until the current byte has been transferred.
422         //
423         while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
424         {
425         }
426
427         //
428         // Provide the required inter-byte delay.
429         //
430         OSRAMDelay(g_ulDelay);
431
432         //
433         // Write the next byte to the controller.
434         //
435         I2CMasterDataPut(I2C_MASTER_BASE, *pucBuffer++);
436         ulCount--;
437
438         //
439         // Continue the transfer.
440         //
441         I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
442     }
443 }
444
445 //*****************************************************************************
446 //
447 //! \internal
448 //!
449 //! Finish a transfer to the SSD0303 controller.
450 //!
451 //! \param ucChar is the final byte to be written to the controller.
452 //!
453 //! This function will finish a transfer to the SSD0303 controller via the I2C
454 //! bus.  This must only be called after calling OSRAMWriteFirst().
455 //!
456 //! The data is written in a polled fashion; this function will not return
457 //! until the byte has been written to the controller.
458 //!
459 //! \return None.
460 //
461 //*****************************************************************************
462 static void
463 OSRAMWriteFinal(unsigned char ucChar)
464 {
465     //
466     // Wait until the current byte has been transferred.
467     //
468     while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
469     {
470     }
471
472     //
473     // Provide the required inter-byte delay.
474     //
475     OSRAMDelay(g_ulDelay);
476
477     //
478     // Write the final byte to the controller.
479     //
480     I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
481
482     //
483     // Finish the transfer.
484     //
485     I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
486
487     //
488     // Wait until the final byte has been transferred.
489     //
490     while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
491     {
492     }
493
494     //
495     // Provide the required inter-byte delay.
496     //
497     OSRAMDelay(g_ulDelay);
498 }
499
500 //*****************************************************************************
501 //
502 //! Clears the OLED display.
503 //!
504 //! This function will clear the display.  All pixels in the display will be
505 //! turned off.
506 //!
507 //! \return None.
508 //
509 //*****************************************************************************
510 void
511 OSRAMClear(void)
512 {
513     static const unsigned char pucRow1[] =
514     {
515         0xb0, 0x80, 0x04, 0x80, 0x12, 0x40
516     };
517     static const unsigned char pucRow2[] =
518     {
519         0xb1, 0x80, 0x04, 0x80, 0x12, 0x40
520     };
521     unsigned long ulIdx;
522
523     //
524     // Move the display cursor to the first column of the first row.
525     //
526     OSRAMWriteFirst(0x80);
527     OSRAMWriteArray(pucRow1, sizeof(pucRow1));
528
529     //
530     // Fill this row with zeros.
531     //
532     for(ulIdx = 0; ulIdx < 95; ulIdx++)
533     {
534         OSRAMWriteByte(0x00);
535     }
536     OSRAMWriteFinal(0x00);
537
538     //
539     // Move the display cursor to the first column of the second row.
540     //
541     OSRAMWriteFirst(0x80);
542     OSRAMWriteArray(pucRow2, sizeof(pucRow2));
543
544     //
545     // Fill this row with zeros.
546     //
547     for(ulIdx = 0; ulIdx < 95; ulIdx++)
548     {
549         OSRAMWriteByte(0x00);
550     }
551     OSRAMWriteFinal(0x00);
552 }
553
554 //*****************************************************************************
555 //
556 //! Displays a string on the OLED display.
557 //!
558 //! \param pcStr is a pointer to the string to display.
559 //! \param ulX is the horizontal position to display the string, specified in
560 //! columns from the left edge of the display.
561 //! \param ulY is the vertical position to display the string, specified in
562 //! eight scan line blocks from the top of the display (i.e. only 0 and 1 are
563 //! valid).
564 //!
565 //! This function will draw a string on the display.  Only the ASCII characters
566 //! between 32 (space) and 126 (tilde) are supported; other characters will
567 //! result in random data being draw on the display (based on whatever appears
568 //! before/after the font in memory).  The font is mono-spaced, so characters
569 //! such as "i" and "l" have more white space around them than characters such
570 //! as "m" or "w".
571 //!
572 //! If the drawing of the string reaches the right edge of the display, no more
573 //! characters will be drawn.  Therefore, special care is not required to avoid
574 //! supplying a string that is "too long" to display.
575 //!
576 //! \return None.
577 //
578 //*****************************************************************************
579 void
580 OSRAMStringDraw(const char *pcStr, unsigned long ulX, unsigned long ulY)
581 {
582     //
583     // Check the arguments.
584     //
585     ASSERT(ulX < 96);
586     ASSERT(ulY < 2);
587
588     //
589     // Move the display cursor to the requested position on the display.
590     //
591     OSRAMWriteFirst(0x80);
592     OSRAMWriteByte((ulY == 0) ? 0xb0 : 0xb1);
593     OSRAMWriteByte(0x80);
594     OSRAMWriteByte((ulX + 36) & 0x0f);
595     OSRAMWriteByte(0x80);
596     OSRAMWriteByte(0x10 | (((ulX + 36) >> 4) & 0x0f));
597     OSRAMWriteByte(0x40);
598
599     //
600     // Loop while there are more characters in the string.
601     //
602     while(*pcStr != 0)
603     {
604         //
605         // See if there is enough space on the display for this entire
606         // character.
607         //
608         if(ulX <= 90)
609         {
610             //
611             // Write the contents of this character to the display.
612             //
613             OSRAMWriteArray(g_pucFont[*pcStr - ' '], 5);
614
615             //
616             // See if this is the last character to display (either because the
617             // right edge has been reached or because there are no more
618             // characters).
619             //
620             if((ulX == 90) || (pcStr[1] == 0))
621             {
622                 //
623                 // Write the final column of the display.
624                 //
625                 OSRAMWriteFinal(0x00);
626
627                 //
628                 // The string has been displayed.
629                 //
630                 return;
631             }
632
633             //
634             // Write the inter-character padding column.
635             //
636             OSRAMWriteByte(0x00);
637         }
638         else
639         {
640             //
641             // Write the portion of the character that will fit onto the
642             // display.
643             //
644             OSRAMWriteArray(g_pucFont[*pcStr - ' '], 95 - ulX);
645             OSRAMWriteFinal(g_pucFont[*pcStr - ' '][95 - ulX]);
646
647             //
648             // The string has been displayed.
649             //
650             return;
651         }
652
653         //
654         // Advance to the next character.
655         //
656         pcStr++;
657
658         //
659         // Increment the X coordinate by the six columns that were just
660         // written.
661         //
662         ulX += 6;
663     }
664 }
665
666 //*****************************************************************************
667 //
668 //! Displays an image on the OLED display.
669 //!
670 //! \param pucImage is a pointer to the image data.
671 //! \param ulX is the horizontal position to display this image, specified in
672 //! columns from the left edge of the display.
673 //! \param ulY is the vertical position to display this image, specified in
674 //! eight scan line blocks from the top of the display (i.e. only 0 and 1 are
675 //! valid).
676 //! \param ulWidth is the width of the image, specified in columns.
677 //! \param ulHeight is the height of the image, specified in eight row blocks
678 //! (i.e. only 1 and 2 are valid).
679 //!
680 //! This function will display a bitmap graphic on the display.  The image to
681 //! be displayed must be a multiple of eight scan lines high (i.e. one row) and
682 //! will be drawn at a vertical position that is a multiple of eight scan lines
683 //! (i.e. scan line zero or scan line eight, corresponding to row zero or row
684 //! one).
685 //!
686 //! The image data is organized with the first row of image data appearing left
687 //! to right, followed immediately by the second row of image data.  Each byte
688 //! contains the data for the eight scan lines of the column, with the top scan
689 //! line being in the least significant bit of the byte and the bottom scan
690 //! line being in the most significant bit of the byte.
691 //!
692 //! For example, an image four columns wide and sixteen scan lines tall would
693 //! be arranged as follows (showing how the eight bytes of the image would
694 //! appear on the display):
695 //!
696 //! \verbatim
697 //!     +-------+  +-------+  +-------+  +-------+
698 //!     |   | 0 |  |   | 0 |  |   | 0 |  |   | 0 |
699 //!     | B | 1 |  | B | 1 |  | B | 1 |  | B | 1 |
700 //!     | y | 2 |  | y | 2 |  | y | 2 |  | y | 2 |
701 //!     | t | 3 |  | t | 3 |  | t | 3 |  | t | 3 |
702 //!     | e | 4 |  | e | 4 |  | e | 4 |  | e | 4 |
703 //!     |   | 5 |  |   | 5 |  |   | 5 |  |   | 5 |
704 //!     | 0 | 6 |  | 1 | 6 |  | 2 | 6 |  | 3 | 6 |
705 //!     |   | 7 |  |   | 7 |  |   | 7 |  |   | 7 |
706 //!     +-------+  +-------+  +-------+  +-------+
707 //!
708 //!     +-------+  +-------+  +-------+  +-------+
709 //!     |   | 0 |  |   | 0 |  |   | 0 |  |   | 0 |
710 //!     | B | 1 |  | B | 1 |  | B | 1 |  | B | 1 |
711 //!     | y | 2 |  | y | 2 |  | y | 2 |  | y | 2 |
712 //!     | t | 3 |  | t | 3 |  | t | 3 |  | t | 3 |
713 //!     | e | 4 |  | e | 4 |  | e | 4 |  | e | 4 |
714 //!     |   | 5 |  |   | 5 |  |   | 5 |  |   | 5 |
715 //!     | 4 | 6 |  | 5 | 6 |  | 6 | 6 |  | 7 | 6 |
716 //!     |   | 7 |  |   | 7 |  |   | 7 |  |   | 7 |
717 //!     +-------+  +-------+  +-------+  +-------+
718 //! \endverbatim
719 //!
720 //! \return None.
721 //
722 //*****************************************************************************
723 void
724 OSRAMImageDraw(const unsigned char *pucImage, unsigned long ulX,
725                unsigned long ulY, unsigned long ulWidth,
726                unsigned long ulHeight)
727 {
728     //
729     // Check the arguments.
730     //
731     ASSERT(ulX < 96);
732     ASSERT(ulY < 2);
733     ASSERT((ulX + ulWidth) <= 96);
734     ASSERT((ulY + ulHeight) <= 2);
735
736     //
737     // The first 36 columns of the LCD buffer are not displayed, so increment
738     // the X coorddinate by 36 to account for the non-displayed frame buffer
739     // memory.
740     //
741     ulX += 36;
742
743     //
744     // Loop while there are more rows to display.
745     //
746     while(ulHeight--)
747     {
748         //
749         // Write the starting address within this row.
750         //
751         OSRAMWriteFirst(0x80);
752         OSRAMWriteByte((ulY == 0) ? 0xb0 : 0xb1);
753         OSRAMWriteByte(0x80);
754         OSRAMWriteByte(ulX & 0x0f);
755         OSRAMWriteByte(0x80);
756         OSRAMWriteByte(0x10 | ((ulX >> 4) & 0x0f));
757         OSRAMWriteByte(0x40);
758
759         //
760         // Write this row of image data.
761         //
762         OSRAMWriteArray(pucImage, ulWidth - 1);
763         OSRAMWriteFinal(pucImage[ulWidth - 1]);
764
765         //
766         // Advance to the next row of the image.
767         //
768         pucImage += ulWidth;
769         ulY++;
770     }
771 }
772
773 //*****************************************************************************
774 //
775 //! Initialize the OLED display.
776 //!
777 //! \param bFast is a boolean that is \e true if the I2C interface should be
778 //! run at 400 kbps and \e false if it should be run at 100 kbps.
779 //!
780 //! This function initializes the I2C interface to the OLED display and
781 //! configures the SSD0303 controller on the panel.
782 //!
783 //! \return None.
784 //
785 //*****************************************************************************
786 void
787 OSRAMInit(tBoolean bFast)
788 {
789     unsigned long ulIdx;
790
791     //
792     // Enable the I2C and GPIO port B blocks as they are needed by this driver.
793     //
794     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C);
795     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
796
797     //
798     // Configure the I2C SCL and SDA pins for I2C operation.
799     //
800     GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
801
802     //
803     // Initialize the I2C master.
804     //
805     I2CMasterInitExpClk(I2C_MASTER_BASE, SysCtlClockGet(), bFast);
806
807     //
808     // Compute the inter-byte delay for the SSD0303 controller.  This delay is
809     // dependent upon the I2C bus clock rate; the slower the clock the longer
810     // the delay required.
811     //
812     // The derivation of this formula is based on a measured delay of
813     // OSRAMDelay(1700) for a 100 kHz I2C bus with the CPU running at 50 MHz
814     // (referred to as C).  To scale this to the delay for a different CPU
815     // speed (since this is just a CPU-based delay loop) is:
816     //
817     //           f(CPU)
818     //     C * ----------
819     //         50,000,000
820     //
821     // To then scale this to the actual I2C rate (since it won't always be
822     // precisely 100 kHz):
823     //
824     //           f(CPU)     100,000
825     //     C * ---------- * -------
826     //         50,000,000    f(I2C)
827     //
828     // This equation will give the inter-byte delay required for any
829     // configuration of the I2C master.  But, as arranged it is impossible to
830     // directly compute in 32-bit arithmetic (without loosing a lot of
831     // accuracy).  So, the equation is simplified.
832     //
833     // Since f(I2C) is generated by dividing down from f(CPU), replace it with
834     // the equivalent (where TPR is the value programmed into the Master Timer
835     // Period Register of the I2C master, with the 1 added back):
836     //
837     //                        100,000
838     //           f(CPU)       -------
839     //     C * ---------- *    f(CPU)
840     //         50,000,000   ------------
841     //                      2 * 10 * TPR
842     //
843     // Inverting the dividend in the last term:
844     //
845     //           f(CPU)     100,000 * 2 * 10 * TPR
846     //     C * ---------- * ----------------------
847     //         50,000,000          f(CPU)
848     //
849     // The f(CPU) now cancels out.
850     //
851     //         100,000 * 2 * 10 * TPR
852     //     C * ----------------------
853     //               50,000,000
854     //
855     // Since there are no clock frequencies left in the equation, this equation
856     // also works for 400 kHz bus operation as well, since the 100,000 in the
857     // numerator becomes 400,000 but C is 1/4, which cancel out each other.
858     // Reducing the constants gives:
859     //
860     //         TPR              TPR             TPR
861     //     C * ---   =   1700 * ---   =   340 * ---
862     //         25               25               5
863     //
864     // Note that the constant C is actually a bit larger than it needs to be in
865     // order to provide some safety margin.
866     //
867     // When the panel is being initialized, the value of C actually needs to be
868     // a bit longer (3200 instead of 1700).  So, set the larger value for now.
869     //
870     g_ulDelay = (640 * (HWREG(I2C_MASTER_BASE + I2C_MASTER_O_TPR) + 1)) / 5;
871
872     //
873     // Initialize the SSD0303 controller.  Loop through the initialization
874     // sequence doing a single I2C transfer for each command.
875     //
876     for(ulIdx = 0; ulIdx < sizeof(g_pucOSRAMInit);
877         ulIdx += g_pucOSRAMInit[ulIdx] + 1)
878     {
879         //
880         // Send this command.
881         //
882         OSRAMWriteFirst(g_pucOSRAMInit[ulIdx + 1]);
883         OSRAMWriteArray(g_pucOSRAMInit + ulIdx + 2, g_pucOSRAMInit[ulIdx] - 2);
884         OSRAMWriteFinal(g_pucOSRAMInit[ulIdx + g_pucOSRAMInit[ulIdx]]);
885     }
886
887     //
888     // Now, switch to the actual value of C.
889     //
890     g_ulDelay = (340 * (HWREG(I2C_MASTER_BASE + I2C_MASTER_O_TPR) + 1)) / 5;
891
892     //
893     // Clear the frame buffer.
894     //
895     OSRAMClear();
896 }
897
898 //*****************************************************************************
899 //
900 //! Turns on the OLED display.
901 //!
902 //! This function will turn on the OLED display, causing it to display the
903 //! contents of its internal frame buffer.
904 //!
905 //! \return None.
906 //
907 //*****************************************************************************
908 void
909 OSRAMDisplayOn(void)
910 {
911     //
912     // Turn on the DC-DC converter and the display.
913     //
914     OSRAMWriteFirst(0x80);
915     OSRAMWriteByte(0xad);
916     OSRAMWriteByte(0x80);
917     OSRAMWriteByte(0x8b);
918     OSRAMWriteByte(0x80);
919     OSRAMWriteFinal(0xaf);
920 }
921
922 //*****************************************************************************
923 //
924 //! Turns off the OLED display.
925 //!
926 //! This function will turn off the OLED display.  This will stop the scanning
927 //! of the panel and turn off the on-chip DC-DC converter, preventing damage to
928 //! the panel due to burn-in (it has similar characters to a CRT in this
929 //! respect).
930 //!
931 //! \return None.
932 //
933 //*****************************************************************************
934 void
935 OSRAMDisplayOff(void)
936 {
937     //
938     // Turn off the DC-DC converter and the display.
939     //
940     OSRAMWriteFirst(0x80);
941     OSRAMWriteByte(0xad);
942     OSRAMWriteByte(0x80);
943     OSRAMWriteByte(0x8a);
944     OSRAMWriteByte(0x80);
945     OSRAMWriteFinal(0xae);
946 }
947
948 //*****************************************************************************
949 //
950 // Close the Doxygen group.
951 //! @}
952 //
953 //*****************************************************************************