1 //*****************************************************************************
3 // osram96x16.c - Driver for the OSRAM 96x16 graphical OLED display.
5 // Copyright (c) 2006 Luminary Micro, Inc. All rights reserved.
7 // Software License Agreement
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10 // exclusively on LMI's Stellaris Family of microcontroller products.
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.
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.
24 // This is part of revision 816 of the Stellaris Driver Library.
26 //*****************************************************************************
28 //*****************************************************************************
30 //! \addtogroup ev_lm3s811_api
33 //*****************************************************************************
36 #include "hw_memmap.h"
37 #include "hw_sysctl.h"
39 #include "src/debug.h"
42 #include "src/sysctl.h"
43 #include "osram96x16.h"
45 extern void I2CMasterInitExpClk(unsigned long ulBase, unsigned long ulI2CClk, tBoolean bFast);
46 //*****************************************************************************
48 // The I2C slave address of the SSD0303 controller on the OLED display.
50 //*****************************************************************************
51 #define SSD0303_ADDR 0x3d
53 //*****************************************************************************
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.
60 //*****************************************************************************
61 static const unsigned char g_pucFont[95][5] =
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 }, // ~
160 //*****************************************************************************
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.
166 //*****************************************************************************
167 static const unsigned char g_pucOSRAMInit[] =
170 // Turn off the panel
175 // Set lower column address
180 // Set higher column address
185 // Set contrast control register
187 0x04, 0x80, 0x81, 0x80, 0x2b,
190 // Set segment re-map
195 // Set display start line
200 // Set display offset
202 0x04, 0x80, 0xd3, 0x80, 0x00,
205 // Set multiplex ratio
207 0x04, 0x80, 0xa8, 0x80, 0x0f,
210 // Set the display to normal mode
215 // Non-inverted display
220 // Set the page address
225 // Set COM output scan direction
230 // Set display clock divide ratio/oscillator frequency
232 0x04, 0x80, 0xd5, 0x80, 0x72,
237 0x04, 0x80, 0xd8, 0x80, 0x00,
240 // Set pre-charge period
242 0x04, 0x80, 0xd9, 0x80, 0x22,
245 // Set COM pins hardware configuration
247 0x04, 0x80, 0xda, 0x80, 0x12,
250 // Set VCOM deslect level
252 0x04, 0x80, 0xdb, 0x80, 0x0f,
257 0x04, 0x80, 0xad, 0x80, 0x8b,
265 //*****************************************************************************
267 // The inter-byte delay required by the SSD0303 OLED controller.
269 //*****************************************************************************
270 static unsigned long g_ulDelay;
272 //*****************************************************************************
276 //! Provide a small delay.
278 //! \param ulCount is the number of delay loop iterations to perform.
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.
287 //*****************************************************************************
290 OSRAMDelay(unsigned long ulCount)
292 __asm(" subs r0, #1\n"
298 static void __attribute__((naked))
299 OSRAMDelay(unsigned long ulCount)
301 __asm(" subs r0, #1\n"
306 #if defined(rvmdk) || defined(__ARMCC_VERSION)
308 OSRAMDelay(unsigned long ulCount)
316 //*****************************************************************************
320 //! Start a transfer to the SSD0303 controller.
322 //! \param ucChar is the first byte to be written to the controller.
324 //! This function will start a transfer to the SSD0303 controller via the I2C
327 //! The data is written in a polled fashion; this function will not return
328 //! until the byte has been written to the controller.
332 //*****************************************************************************
334 OSRAMWriteFirst(unsigned char ucChar)
337 // Set the slave address.
339 I2CMasterSlaveAddrSet(I2C_MASTER_BASE, SSD0303_ADDR, false);
342 // Write the first byte to the controller.
344 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
347 // Start the transfer.
349 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
352 //*****************************************************************************
356 //! Write a byte to the SSD0303 controller.
358 //! \param ucChar is the byte to be transmitted to the controller.
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().
364 //! The data is written in a polled faashion; this function will not return
365 //! until the byte has been written to the controller.
369 //*****************************************************************************
371 OSRAMWriteByte(unsigned char ucChar)
374 // Wait until the current byte has been transferred.
376 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
381 // Provide the required inter-byte delay.
383 OSRAMDelay(g_ulDelay);
386 // Write the next byte to the controller.
388 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
391 // Continue the transfer.
393 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
396 //*****************************************************************************
400 //! Write a sequence of bytes to the SSD0303 controller.
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().
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.
411 //*****************************************************************************
413 OSRAMWriteArray(const unsigned char *pucBuffer, unsigned long ulCount)
416 // Loop while there are more bytes left to be transferred.
421 // Wait until the current byte has been transferred.
423 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
428 // Provide the required inter-byte delay.
430 OSRAMDelay(g_ulDelay);
433 // Write the next byte to the controller.
435 I2CMasterDataPut(I2C_MASTER_BASE, *pucBuffer++);
439 // Continue the transfer.
441 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
445 //*****************************************************************************
449 //! Finish a transfer to the SSD0303 controller.
451 //! \param ucChar is the final byte to be written to the controller.
453 //! This function will finish a transfer to the SSD0303 controller via the I2C
454 //! bus. This must only be called after calling OSRAMWriteFirst().
456 //! The data is written in a polled fashion; this function will not return
457 //! until the byte has been written to the controller.
461 //*****************************************************************************
463 OSRAMWriteFinal(unsigned char ucChar)
466 // Wait until the current byte has been transferred.
468 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
473 // Provide the required inter-byte delay.
475 OSRAMDelay(g_ulDelay);
478 // Write the final byte to the controller.
480 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
483 // Finish the transfer.
485 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
488 // Wait until the final byte has been transferred.
490 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
495 // Provide the required inter-byte delay.
497 OSRAMDelay(g_ulDelay);
500 //*****************************************************************************
502 //! Clears the OLED display.
504 //! This function will clear the display. All pixels in the display will be
509 //*****************************************************************************
513 static const unsigned char pucRow1[] =
515 0xb0, 0x80, 0x04, 0x80, 0x12, 0x40
517 static const unsigned char pucRow2[] =
519 0xb1, 0x80, 0x04, 0x80, 0x12, 0x40
524 // Move the display cursor to the first column of the first row.
526 OSRAMWriteFirst(0x80);
527 OSRAMWriteArray(pucRow1, sizeof(pucRow1));
530 // Fill this row with zeros.
532 for(ulIdx = 0; ulIdx < 95; ulIdx++)
534 OSRAMWriteByte(0x00);
536 OSRAMWriteFinal(0x00);
539 // Move the display cursor to the first column of the second row.
541 OSRAMWriteFirst(0x80);
542 OSRAMWriteArray(pucRow2, sizeof(pucRow2));
545 // Fill this row with zeros.
547 for(ulIdx = 0; ulIdx < 95; ulIdx++)
549 OSRAMWriteByte(0x00);
551 OSRAMWriteFinal(0x00);
554 //*****************************************************************************
556 //! Displays a string on the OLED display.
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
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
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.
578 //*****************************************************************************
580 OSRAMStringDraw(const char *pcStr, unsigned long ulX, unsigned long ulY)
583 // Check the arguments.
589 // Move the display cursor to the requested position on the display.
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);
600 // Loop while there are more characters in the string.
605 // See if there is enough space on the display for this entire
611 // Write the contents of this character to the display.
613 OSRAMWriteArray(g_pucFont[*pcStr - ' '], 5);
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
620 if((ulX == 90) || (pcStr[1] == 0))
623 // Write the final column of the display.
625 OSRAMWriteFinal(0x00);
628 // The string has been displayed.
634 // Write the inter-character padding column.
636 OSRAMWriteByte(0x00);
641 // Write the portion of the character that will fit onto the
644 OSRAMWriteArray(g_pucFont[*pcStr - ' '], 95 - ulX);
645 OSRAMWriteFinal(g_pucFont[*pcStr - ' '][95 - ulX]);
648 // The string has been displayed.
654 // Advance to the next character.
659 // Increment the X coordinate by the six columns that were just
666 //*****************************************************************************
668 //! Displays an image on the OLED display.
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
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).
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
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.
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):
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 //! +-------+ +-------+ +-------+ +-------+
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 //! +-------+ +-------+ +-------+ +-------+
722 //*****************************************************************************
724 OSRAMImageDraw(const unsigned char *pucImage, unsigned long ulX,
725 unsigned long ulY, unsigned long ulWidth,
726 unsigned long ulHeight)
729 // Check the arguments.
733 ASSERT((ulX + ulWidth) <= 96);
734 ASSERT((ulY + ulHeight) <= 2);
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
744 // Loop while there are more rows to display.
749 // Write the starting address within this row.
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);
760 // Write this row of image data.
762 OSRAMWriteArray(pucImage, ulWidth - 1);
763 OSRAMWriteFinal(pucImage[ulWidth - 1]);
766 // Advance to the next row of the image.
773 //*****************************************************************************
775 //! Initialize the OLED display.
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.
780 //! This function initializes the I2C interface to the OLED display and
781 //! configures the SSD0303 controller on the panel.
785 //*****************************************************************************
787 OSRAMInit(tBoolean bFast)
792 // Enable the I2C and GPIO port B blocks as they are needed by this driver.
794 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C);
795 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
798 // Configure the I2C SCL and SDA pins for I2C operation.
800 GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
803 // Initialize the I2C master.
805 I2CMasterInitExpClk(I2C_MASTER_BASE, SysCtlClockGet(), bFast);
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.
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:
821 // To then scale this to the actual I2C rate (since it won't always be
822 // precisely 100 kHz):
825 // C * ---------- * -------
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.
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):
839 // C * ---------- * f(CPU)
840 // 50,000,000 ------------
843 // Inverting the dividend in the last term:
845 // f(CPU) 100,000 * 2 * 10 * TPR
846 // C * ---------- * ----------------------
849 // The f(CPU) now cancels out.
851 // 100,000 * 2 * 10 * TPR
852 // C * ----------------------
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:
861 // C * --- = 1700 * --- = 340 * ---
864 // Note that the constant C is actually a bit larger than it needs to be in
865 // order to provide some safety margin.
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.
870 g_ulDelay = (640 * (HWREG(I2C_MASTER_BASE + I2C_MASTER_O_TPR) + 1)) / 5;
873 // Initialize the SSD0303 controller. Loop through the initialization
874 // sequence doing a single I2C transfer for each command.
876 for(ulIdx = 0; ulIdx < sizeof(g_pucOSRAMInit);
877 ulIdx += g_pucOSRAMInit[ulIdx] + 1)
880 // Send this command.
882 OSRAMWriteFirst(g_pucOSRAMInit[ulIdx + 1]);
883 OSRAMWriteArray(g_pucOSRAMInit + ulIdx + 2, g_pucOSRAMInit[ulIdx] - 2);
884 OSRAMWriteFinal(g_pucOSRAMInit[ulIdx + g_pucOSRAMInit[ulIdx]]);
888 // Now, switch to the actual value of C.
890 g_ulDelay = (340 * (HWREG(I2C_MASTER_BASE + I2C_MASTER_O_TPR) + 1)) / 5;
893 // Clear the frame buffer.
898 //*****************************************************************************
900 //! Turns on the OLED display.
902 //! This function will turn on the OLED display, causing it to display the
903 //! contents of its internal frame buffer.
907 //*****************************************************************************
912 // Turn on the DC-DC converter and the display.
914 OSRAMWriteFirst(0x80);
915 OSRAMWriteByte(0xad);
916 OSRAMWriteByte(0x80);
917 OSRAMWriteByte(0x8b);
918 OSRAMWriteByte(0x80);
919 OSRAMWriteFinal(0xaf);
922 //*****************************************************************************
924 //! Turns off the OLED display.
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
933 //*****************************************************************************
935 OSRAMDisplayOff(void)
938 // Turn off the DC-DC converter and the display.
940 OSRAMWriteFirst(0x80);
941 OSRAMWriteByte(0xad);
942 OSRAMWriteByte(0x80);
943 OSRAMWriteByte(0x8a);
944 OSRAMWriteByte(0x80);
945 OSRAMWriteFinal(0xae);
948 //*****************************************************************************
950 // Close the Doxygen group.
953 //*****************************************************************************