1 //*****************************************************************************
\r
3 // osram96x16.c - Driver for the OSRAM 96x16 graphical OLED display.
\r
5 // Copyright (c) 2006 Luminary Micro, Inc. All rights reserved.
\r
7 // Software License Agreement
\r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
\r
10 // exclusively on LMI's Stellaris Family of microcontroller products.
\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
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
24 // This is part of revision 816 of the Stellaris Driver Library.
\r
26 //*****************************************************************************
\r
28 //*****************************************************************************
\r
30 //! \addtogroup ev_lm3s811_api
\r
33 //*****************************************************************************
\r
36 #include "hw_memmap.h"
\r
37 #include "hw_sysctl.h"
\r
38 #include "hw_types.h"
\r
39 #include "src/debug.h"
\r
40 #include "src/gpio.h"
\r
41 #include "src/i2c.h"
\r
42 #include "src/sysctl.h"
\r
43 #include "osram96x16.h"
\r
45 //*****************************************************************************
\r
47 // The I2C slave address of the SSD0303 controller on the OLED display.
\r
49 //*****************************************************************************
\r
50 #define SSD0303_ADDR 0x3d
\r
52 //*****************************************************************************
\r
54 // A 5x7 font (in a 6x8 cell, where the sixth column is omitted from this
\r
55 // table) for displaying text on the OLED display. The data is organized as
\r
56 // bytes from the left column to the right column, with each byte containing
\r
57 // the top row in the LSB and the bottom row in the MSB.
\r
59 //*****************************************************************************
\r
60 static const unsigned char g_pucFont[95][5] =
\r
62 { 0x00, 0x00, 0x00, 0x00, 0x00 }, // " "
\r
63 { 0x00, 0x00, 0x4f, 0x00, 0x00 }, // !
\r
64 { 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
\r
65 { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
\r
66 { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
\r
67 { 0x23, 0x13, 0x08, 0x64, 0x62 }, // %
\r
68 { 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
\r
69 { 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
\r
70 { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
\r
71 { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
\r
72 { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // *
\r
73 { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // +
\r
74 { 0x00, 0x50, 0x30, 0x00, 0x00 }, // ,
\r
75 { 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
\r
76 { 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
\r
77 { 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
\r
78 { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 0
\r
79 { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 1
\r
80 { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
\r
81 { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 3
\r
82 { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 4
\r
83 { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
\r
84 { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 6
\r
85 { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
\r
86 { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
\r
87 { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 9
\r
88 { 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
\r
89 { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
\r
90 { 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
\r
91 { 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
\r
92 { 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
\r
93 { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
\r
94 { 0x32, 0x49, 0x79, 0x41, 0x3e }, // @
\r
95 { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // A
\r
96 { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // B
\r
97 { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // C
\r
98 { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // D
\r
99 { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // E
\r
100 { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // F
\r
101 { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // G
\r
102 { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // H
\r
103 { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // I
\r
104 { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // J
\r
105 { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // K
\r
106 { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // L
\r
107 { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // M
\r
108 { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // N
\r
109 { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // O
\r
110 { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // P
\r
111 { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // Q
\r
112 { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // R
\r
113 { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
\r
114 { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // T
\r
115 { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // U
\r
116 { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // V
\r
117 { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // W
\r
118 { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
\r
119 { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
\r
120 { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
\r
121 { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // [
\r
122 { 0x02, 0x04, 0x08, 0x10, 0x20 }, // "\"
\r
123 { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // ]
\r
124 { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
\r
125 { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
\r
126 { 0x00, 0x01, 0x02, 0x04, 0x00 }, // `
\r
127 { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
\r
128 { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // b
\r
129 { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
\r
130 { 0x38, 0x44, 0x44, 0x48, 0x7f }, // d
\r
131 { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
\r
132 { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // f
\r
133 { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // g
\r
134 { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // h
\r
135 { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // i
\r
136 { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // j
\r
137 { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // k
\r
138 { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // l
\r
139 { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // m
\r
140 { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // n
\r
141 { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
\r
142 { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // p
\r
143 { 0x08, 0x14, 0x14, 0x18, 0x7c }, // q
\r
144 { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // r
\r
145 { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
\r
146 { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // t
\r
147 { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // u
\r
148 { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // v
\r
149 { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // w
\r
150 { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
\r
151 { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // y
\r
152 { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // z
\r
153 { 0x00, 0x08, 0x36, 0x41, 0x00 }, // {
\r
154 { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // |
\r
155 { 0x00, 0x41, 0x36, 0x08, 0x00 }, // }
\r
156 { 0x02, 0x01, 0x02, 0x04, 0x02 }, // ~
\r
159 //*****************************************************************************
\r
161 // The sequence of commands used to initialize the SSD0303 controller.
\r
163 //*****************************************************************************
\r
164 static const unsigned char g_pucOSRAMInit[] =
\r
167 // Turn off the panel
\r
172 // Set lower column address
\r
177 // Set higher column address
\r
182 // Set contrast control register
\r
184 0x80, 0x81, 0x80, 0x2b,
\r
187 // Set segment re-map
\r
192 // Set display start line
\r
197 // Set display offset
\r
199 0x80, 0xd3, 0x80, 0x00,
\r
202 // Set multiplex ratio
\r
204 0x80, 0xa8, 0x80, 0x0f,
\r
207 // Set the display to normal mode
\r
212 // Non-inverted display
\r
217 // Set the page address
\r
222 // Set COM output scan direction
\r
227 // Set display clock divide ratio/oscillator frequency
\r
229 0x80, 0xd5, 0x80, 0x72,
\r
232 // Enable mono mode
\r
234 0x80, 0xd8, 0x80, 0x00,
\r
237 // Set pre-charge period
\r
239 0x80, 0xd9, 0x80, 0x22,
\r
242 // Set COM pins hardware configuration
\r
244 0x80, 0xda, 0x80, 0x12,
\r
247 // Set VCOM deslect level
\r
249 0x80, 0xdb, 0x80, 0x0f,
\r
254 0x80, 0xad, 0x80, 0x8b,
\r
257 // Turn on the panel
\r
262 //*****************************************************************************
\r
264 // The inter-byte delay required by the SSD0303 OLED controller.
\r
266 //*****************************************************************************
\r
267 static unsigned long g_ulDelay;
\r
269 //*****************************************************************************
\r
273 //! Provide a small delay.
\r
275 //! \param ulCount is the number of delay loop iterations to perform.
\r
277 //! Since the SSD0303 controller needs a delay between bytes written to it over
\r
278 //! the I2C bus, this function provides a means of generating that delay. It
\r
279 //! is written in assembly to keep the delay consistent across tool chains,
\r
280 //! avoiding the need to tune the delay based on the tool chain in use.
\r
284 //*****************************************************************************
\r
287 OSRAMDelay(unsigned long ulCount)
\r
289 __asm(" subs r0, #1\n"
\r
290 " bne OSRAMDelay\n"
\r
295 static void __attribute__((naked))
\r
296 OSRAMDelay(unsigned long ulCount)
\r
298 __asm(" subs r0, #1\n"
\r
299 " bne OSRAMDelay\n"
\r
303 #if defined(rvmdk) || defined(__ARMCC_VERSION)
\r
305 OSRAMDelay(unsigned long ulCount)
\r
313 //*****************************************************************************
\r
317 //! Start a transfer to the SSD0303 controller.
\r
319 //! \param ucChar is the first byte to be written to the controller.
\r
321 //! This function will start a transfer to the SSD0303 controller via the I2C
\r
324 //! The data is written in a polled fashion; this function will not return
\r
325 //! until the byte has been written to the controller.
\r
329 //*****************************************************************************
\r
331 OSRAMWriteFirst(unsigned char ucChar)
\r
334 // Set the slave address.
\r
336 I2CMasterSlaveAddrSet(I2C_MASTER_BASE, SSD0303_ADDR, false);
\r
339 // Write the first byte to the controller.
\r
341 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
\r
344 // Start the transfer.
\r
346 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
\r
349 //*****************************************************************************
\r
353 //! Write a byte to the SSD0303 controller.
\r
355 //! \param ucChar is the byte to be transmitted to the controller.
\r
357 //! This function continues a transfer to the SSD0303 controller by writing
\r
358 //! another byte over the I2C bus. This must only be called after calling
\r
359 //! OSRAMWriteFirst(), but before calling OSRAMWriteFinal().
\r
361 //! The data is written in a polled faashion; this function will not return
\r
362 //! until the byte has been written to the controller.
\r
366 //*****************************************************************************
\r
368 OSRAMWriteByte(unsigned char ucChar)
\r
371 // Wait until the current byte has been transferred.
\r
373 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
\r
378 // Provide the required inter-byte delay.
\r
380 OSRAMDelay(g_ulDelay);
\r
383 // Write the next byte to the controller.
\r
385 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
\r
388 // Continue the transfer.
\r
390 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
\r
393 //*****************************************************************************
\r
397 //! Write a sequence of bytes to the SSD0303 controller.
\r
399 //! This function continues a transfer to the SSD0303 controller by writing a
\r
400 //! sequence of bytes over the I2C bus. This must only be called after calling
\r
401 //! OSRAMWriteFirst(), but before calling OSRAMWriteFinal().
\r
403 //! The data is written in a polled fashion; this function will not return
\r
404 //! until the entire byte sequence has been written to the controller.
\r
408 //*****************************************************************************
\r
410 OSRAMWriteArray(const unsigned char *pucBuffer, unsigned long ulCount)
\r
413 // Loop while there are more bytes left to be transferred.
\r
415 while(ulCount != 0)
\r
418 // Wait until the current byte has been transferred.
\r
420 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
\r
425 // Provide the required inter-byte delay.
\r
427 OSRAMDelay(g_ulDelay);
\r
430 // Write the next byte to the controller.
\r
432 I2CMasterDataPut(I2C_MASTER_BASE, *pucBuffer++);
\r
436 // Continue the transfer.
\r
438 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
\r
442 //*****************************************************************************
\r
446 //! Finish a transfer to the SSD0303 controller.
\r
448 //! \param ucChar is the final byte to be written to the controller.
\r
450 //! This function will finish a transfer to the SSD0303 controller via the I2C
\r
451 //! bus. This must only be called after calling OSRAMWriteFirst().
\r
453 //! The data is written in a polled fashion; this function will not return
\r
454 //! until the byte has been written to the controller.
\r
458 //*****************************************************************************
\r
460 OSRAMWriteFinal(unsigned char ucChar)
\r
463 // Wait until the current byte has been transferred.
\r
465 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
\r
470 // Provide the required inter-byte delay.
\r
472 OSRAMDelay(g_ulDelay);
\r
475 // Write the final byte to the controller.
\r
477 I2CMasterDataPut(I2C_MASTER_BASE, ucChar);
\r
480 // Finish the transfer.
\r
482 I2CMasterControl(I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
\r
485 // Wait until the final byte has been transferred.
\r
487 while(I2CMasterIntStatus(I2C_MASTER_BASE, false) == 0)
\r
492 // Provide the required inter-byte delay.
\r
494 OSRAMDelay(g_ulDelay);
\r
497 //*****************************************************************************
\r
499 //! Clears the OLED display.
\r
501 //! This function will clear the display. All pixels in the display will be
\r
504 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
505 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
510 //*****************************************************************************
\r
514 static const unsigned char pucRow1[] =
\r
516 0xb0, 0x80, 0x04, 0x80, 0x12, 0x40
\r
518 static const unsigned char pucRow2[] =
\r
520 0xb1, 0x80, 0x04, 0x80, 0x12, 0x40
\r
522 unsigned long ulIdx;
\r
525 // Move the display cursor to the first column of the first row.
\r
527 OSRAMWriteFirst(0x80);
\r
528 OSRAMWriteArray(pucRow1, sizeof(pucRow1));
\r
531 // Fill this row with zeros.
\r
533 for(ulIdx = 0; ulIdx < 95; ulIdx++)
\r
535 OSRAMWriteByte(0x00);
\r
537 OSRAMWriteFinal(0x00);
\r
540 // Move the display cursor to the first column of the second row.
\r
542 OSRAMWriteFirst(0x80);
\r
543 OSRAMWriteArray(pucRow2, sizeof(pucRow2));
\r
546 // Fill this row with zeros.
\r
548 for(ulIdx = 0; ulIdx < 95; ulIdx++)
\r
550 OSRAMWriteByte(0x00);
\r
552 OSRAMWriteFinal(0x00);
\r
555 //*****************************************************************************
\r
557 //! Displays a string on the OLED display.
\r
559 //! \param pcStr is a pointer to the string to display.
\r
560 //! \param ulX is the horizontal position to display the string, specified in
\r
561 //! columns from the left edge of the display.
\r
562 //! \param ulY is the vertical position to display the string, specified in
\r
563 //! eight scan line blocks from the top of the display (i.e. only 0 and 1 are
\r
566 //! This function will draw a string on the display. Only the ASCII characters
\r
567 //! between 32 (space) and 126 (tilde) are supported; other characters will
\r
568 //! result in random data being draw on the display (based on whatever appears
\r
569 //! before/after the font in memory). The font is mono-spaced, so characters
\r
570 //! such as "i" and "l" have more white space around them than characters such
\r
573 //! If the drawing of the string reaches the right edge of the display, no more
\r
574 //! characters will be drawn. Therefore, special care is not required to avoid
\r
575 //! supplying a string that is "too long" to display.
\r
577 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
578 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
583 //*****************************************************************************
\r
585 OSRAMStringDraw(const char *pcStr, unsigned long ulX, unsigned long ulY)
\r
588 // Check the arguments.
\r
594 // Move the display cursor to the requested position on the display.
\r
596 OSRAMWriteFirst(0x80);
\r
597 OSRAMWriteByte((ulY == 0) ? 0xb0 : 0xb1);
\r
598 OSRAMWriteByte(0x80);
\r
599 OSRAMWriteByte((ulX + 36) & 0x0f);
\r
600 OSRAMWriteByte(0x80);
\r
601 OSRAMWriteByte(0x10 | (((ulX + 36) >> 4) & 0x0f));
\r
602 OSRAMWriteByte(0x40);
\r
605 // Loop while there are more characters in the string.
\r
610 // See if there is enough space on the display for this entire
\r
616 // Write the contents of this character to the display.
\r
618 OSRAMWriteArray(g_pucFont[*pcStr - ' '], 5);
\r
621 // See if this is the last character to display (either because the
\r
622 // right edge has been reached or because there are no more
\r
625 if((ulX == 90) || (pcStr[1] == 0))
\r
628 // Write the final column of the display.
\r
630 OSRAMWriteFinal(0x00);
\r
633 // The string has been displayed.
\r
639 // Write the inter-character padding column.
\r
641 OSRAMWriteByte(0x00);
\r
646 // Write the portion of the character that will fit onto the
\r
649 OSRAMWriteArray(g_pucFont[*pcStr - ' '], 95 - ulX);
\r
650 OSRAMWriteFinal(g_pucFont[*pcStr - ' '][95 - ulX]);
\r
653 // The string has been displayed.
\r
659 // Advance to the next character.
\r
664 // Increment the X coordinate by the six columns that were just
\r
671 //*****************************************************************************
\r
673 //! Displays an image on the OLED display.
\r
675 //! \param pucImage is a pointer to the image data.
\r
676 //! \param ulX is the horizontal position to display this image, specified in
\r
677 //! columns from the left edge of the display.
\r
678 //! \param ulY is the vertical position to display this image, specified in
\r
679 //! eight scan line blocks from the top of the display (i.e. only 0 and 1 are
\r
681 //! \param ulWidth is the width of the image, specified in columns.
\r
682 //! \param ulHeight is the height of the image, specified in eight row blocks
\r
683 //! (i.e. only 1 and 2 are valid).
\r
685 //! This function will display a bitmap graphic on the display. The image to
\r
686 //! be displayed must be a multiple of eight scan lines high (i.e. one row) and
\r
687 //! will be drawn at a vertical position that is a multiple of eight scan lines
\r
688 //! (i.e. scan line zero or scan line eight, corresponding to row zero or row
\r
691 //! The image data is organized with the first row of image data appearing left
\r
692 //! to right, followed immediately by the second row of image data. Each byte
\r
693 //! contains the data for the eight scan lines of the column, with the top scan
\r
694 //! line being in the least significant bit of the byte and the bottom scan
\r
695 //! line being in the most significat bit of the byte.
\r
697 //! For example, an image four columns wide and sixteen scan lines tall would
\r
698 //! be arranged as follows (showing how the eight bytes of the image would
\r
699 //! appear on the display):
\r
702 //! +-------+ +-------+ +-------+ +-------+
\r
703 //! | | 0 | | | 0 | | | 0 | | | 0 |
\r
704 //! | B | 1 | | B | 1 | | B | 1 | | B | 1 |
\r
705 //! | y | 2 | | y | 2 | | y | 2 | | y | 2 |
\r
706 //! | t | 3 | | t | 3 | | t | 3 | | t | 3 |
\r
707 //! | e | 4 | | e | 4 | | e | 4 | | e | 4 |
\r
708 //! | | 5 | | | 5 | | | 5 | | | 5 |
\r
709 //! | 0 | 6 | | 1 | 6 | | 2 | 6 | | 3 | 6 |
\r
710 //! | | 7 | | | 7 | | | 7 | | | 7 |
\r
711 //! +-------+ +-------+ +-------+ +-------+
\r
713 //! +-------+ +-------+ +-------+ +-------+
\r
714 //! | | 0 | | | 0 | | | 0 | | | 0 |
\r
715 //! | B | 1 | | B | 1 | | B | 1 | | B | 1 |
\r
716 //! | y | 2 | | y | 2 | | y | 2 | | y | 2 |
\r
717 //! | t | 3 | | t | 3 | | t | 3 | | t | 3 |
\r
718 //! | e | 4 | | e | 4 | | e | 4 | | e | 4 |
\r
719 //! | | 5 | | | 5 | | | 5 | | | 5 |
\r
720 //! | 4 | 6 | | 5 | 6 | | 6 | 6 | | 7 | 6 |
\r
721 //! | | 7 | | | 7 | | | 7 | | | 7 |
\r
722 //! +-------+ +-------+ +-------+ +-------+
\r
725 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
726 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
731 //*****************************************************************************
\r
733 OSRAMImageDraw(const unsigned char *pucImage, unsigned long ulX,
\r
734 unsigned long ulY, unsigned long ulWidth,
\r
735 unsigned long ulHeight)
\r
738 // Check the arguments.
\r
742 ASSERT((ulX + ulWidth) <= 96);
\r
743 ASSERT((ulY + ulHeight) <= 2);
\r
746 // The first 36 columns of the LCD buffer are not displayed, so increment
\r
747 // the X coorddinate by 36 to account for the non-displayed frame buffer
\r
753 // Loop while there are more rows to display.
\r
758 // Write the starting address within this row.
\r
760 OSRAMWriteFirst(0x80);
\r
761 OSRAMWriteByte((ulY == 0) ? 0xb0 : 0xb1);
\r
762 OSRAMWriteByte(0x80);
\r
763 OSRAMWriteByte(ulX & 0x0f);
\r
764 OSRAMWriteByte(0x80);
\r
765 OSRAMWriteByte(0x10 | ((ulX >> 4) & 0x0f));
\r
766 OSRAMWriteByte(0x40);
\r
769 // Write this row of image data.
\r
771 OSRAMWriteArray(pucImage, ulWidth - 1);
\r
772 OSRAMWriteFinal(pucImage[ulWidth - 1]);
\r
775 // Advance to the next row of the image.
\r
777 pucImage += ulWidth;
\r
782 //*****************************************************************************
\r
784 //! Initialize the OLED display.
\r
786 //! \param bFast is a boolean that is \e true if the I2C interface should be
\r
787 //! run at 400 kbps and \e false if it should be run at 100 kbps.
\r
789 //! This function initializes the I2C interface to the OLED display and
\r
790 //! configures the SSD0303 controller on the panel.
\r
792 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
793 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
798 //*****************************************************************************
\r
800 OSRAMInit(tBoolean bFast)
\r
803 // Enable the I2C and GPIO port B blocks as they are needed by this driver.
\r
805 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C);
\r
806 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
\r
809 // Configure the I2C SCL and SDA pins for I2C operation.
\r
811 GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
\r
814 // Initialize the I2C master.
\r
816 I2CMasterInit(I2C_MASTER_BASE, bFast);
\r
819 // Compute the inter-byte delay for the SSD0303 controller. This delay is
\r
820 // dependent upon the I2C bus clock rate; the slower the clock the longer
\r
821 // the delay required.
\r
823 // The derivation of this formula is based on a measured delay of
\r
824 // OSRAMDelay(1640) for a 100 kHz I2C bus with the CPU running at 50 MHz
\r
825 // (referred to as C). To scale this to the delay for a different CPU
\r
826 // speed (since this is just a CPU-based delay loop) is:
\r
832 // To then scale this to the actual I2C rate (since it won't always be
\r
833 // precisely 100 kHz):
\r
836 // C * ---------- * -------
\r
837 // 50,000,000 f(I2C)
\r
839 // This equation will give the inter-byte delay required for any
\r
840 // configuration of the I2C master. But, as arranged it is impossible to
\r
841 // directly compute in 32-bit arithmetic (without loosing a lot of
\r
842 // accuracy). So, the equation is simplified.
\r
844 // Since f(I2C) is generated by dividing down from f(CPU), replace it with
\r
845 // the equivalent (where TPR is the value programmed into the Master Timer
\r
846 // Period Register of the I2C master, with the 1 added back):
\r
850 // C * ---------- * f(CPU)
\r
851 // 50,000,000 ------------
\r
854 // Inverting the dividend in the last term:
\r
856 // f(CPU) 100,000 * 2 * 10 * TPR
\r
857 // C * ---------- * ----------------------
\r
858 // 50,000,000 f(CPU)
\r
860 // The f(CPU) now cancels out.
\r
862 // 100,000 * 2 * 10 * TPR
\r
863 // C * ----------------------
\r
866 // Since there are no clock frequencies left in the equation, this equation
\r
867 // also works for 400 kHz bus operation as well, since the 100,000 in the
\r
868 // numerator becomes 400,000 but C is 1/4, which cancel out each other.
\r
869 // Reducing the constants gives:
\r
872 // C * --- = 1640 * --- = 328 * ---
\r
875 // Note that the constant C is actually a bit larger than it needs to be in
\r
876 // order to provide some safety margin.
\r
878 g_ulDelay = (328 * (HWREG(I2C_MASTER_BASE + I2C_MASTER_O_TPR) + 1)) / 5;
\r
881 // Initialize the SSD0303 controller.
\r
883 OSRAMWriteFirst(g_pucOSRAMInit[0]);
\r
884 OSRAMWriteArray(g_pucOSRAMInit + 1, sizeof(g_pucOSRAMInit) - 2);
\r
885 OSRAMWriteFinal(g_pucOSRAMInit[sizeof(g_pucOSRAMInit) - 1]);
\r
888 // Clear the frame buffer.
\r
893 //*****************************************************************************
\r
895 //! Turns on the OLED display.
\r
897 //! This function will turn on the OLED display, causing it to display the
\r
898 //! contents of its internal frame buffer.
\r
900 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
901 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
906 //*****************************************************************************
\r
908 OSRAMDisplayOn(void)
\r
911 // Turn on the DC-DC converter and the display.
\r
913 OSRAMWriteFirst(0x80);
\r
914 OSRAMWriteByte(0xad);
\r
915 OSRAMWriteByte(0x80);
\r
916 OSRAMWriteByte(0x8b);
\r
917 OSRAMWriteByte(0x80);
\r
918 OSRAMWriteFinal(0xaf);
\r
921 //*****************************************************************************
\r
923 //! Turns off the OLED display.
\r
925 //! This function will turn off the OLED display. This will stop the scanning
\r
926 //! of the panel and turn off the on-chip DC-DC converter, preventing damage to
\r
927 //! the panel due to burn-in (it has similar characters to a CRT in this
\r
930 //! This function is contained in <tt>osram96x16.c</tt>, with
\r
931 //! <tt>osram96x16.h</tt> containing the API definition for use by
\r
936 //*****************************************************************************
\r
938 OSRAMDisplayOff(void)
\r
941 // Turn off the DC-DC converter and the display.
\r
943 OSRAMWriteFirst(0x80);
\r
944 OSRAMWriteByte(0xad);
\r
945 OSRAMWriteByte(0x80);
\r
946 OSRAMWriteByte(0x8a);
\r
947 OSRAMWriteByte(0x80);
\r
948 OSRAMWriteFinal(0xae);
\r
951 //*****************************************************************************
\r
953 // Close the Doxygen group.
\r
956 //*****************************************************************************
\r