A simple library for SSH1106 controlled GLCDs

Dependents:   SSH1106_OLED

Committer:
Anaesthetix
Date:
Mon Dec 19 15:02:30 2016 +0000
Revision:
0:3cd0a11a2f91
Child:
1:ac9efaadd666
-

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anaesthetix 0:3cd0a11a2f91 1 /**
Anaesthetix 0:3cd0a11a2f91 2 * This is a simple library for SSH1106 controlled graphic LCD's.
Anaesthetix 0:3cd0a11a2f91 3 * Written for a cheap 1.3" OLED GLCD
Anaesthetix 0:3cd0a11a2f91 4 * See http://www.dx.com/p/open-smart-1-8-128-64-lcd-display-breakout-module-w-blue-backlit-444694
Anaesthetix 0:3cd0a11a2f91 5 *
Anaesthetix 0:3cd0a11a2f91 6 * Written by: Erik van de Coevering
Anaesthetix 0:3cd0a11a2f91 7 * With thanks to Tim Barr from whom I've reused some code
Anaesthetix 0:3cd0a11a2f91 8 * Use this code in whatever way you like, as long as it stays free of charge!
Anaesthetix 0:3cd0a11a2f91 9 */
Anaesthetix 0:3cd0a11a2f91 10
Anaesthetix 0:3cd0a11a2f91 11 #include "SSH1106.h"
Anaesthetix 0:3cd0a11a2f91 12
Anaesthetix 0:3cd0a11a2f91 13 SSH1106::SSH1106(SPI &lcd, DigitalOut &lcd_cs, DigitalOut &lcd_cd, DigitalOut &lcd_rst)
Anaesthetix 0:3cd0a11a2f91 14 {
Anaesthetix 0:3cd0a11a2f91 15 _lcd = &lcd;
Anaesthetix 0:3cd0a11a2f91 16 _lcd_cs = &lcd_cs;
Anaesthetix 0:3cd0a11a2f91 17 _lcd_cd = &lcd_cd;
Anaesthetix 0:3cd0a11a2f91 18 _lcd_rst = &lcd_rst;
Anaesthetix 0:3cd0a11a2f91 19 }
Anaesthetix 0:3cd0a11a2f91 20
Anaesthetix 0:3cd0a11a2f91 21 void SSH1106::init()
Anaesthetix 0:3cd0a11a2f91 22 {
Anaesthetix 0:3cd0a11a2f91 23 _lcd_cs->write(1);
Anaesthetix 0:3cd0a11a2f91 24 _lcd->frequency(24000000); // Abusing SPI to save some time.. Try a lower freq if this doesn't work
Anaesthetix 0:3cd0a11a2f91 25 _lcd->format(8,3);
Anaesthetix 0:3cd0a11a2f91 26 _lcd_cs->write(0); // enable SPI
Anaesthetix 0:3cd0a11a2f91 27 _lcd_cd->write(0); // COMMAND mode
Anaesthetix 0:3cd0a11a2f91 28
Anaesthetix 0:3cd0a11a2f91 29 _lcd_rst->write(0);
Anaesthetix 0:3cd0a11a2f91 30 wait_ms(100);
Anaesthetix 0:3cd0a11a2f91 31 _lcd_rst->write(1);
Anaesthetix 0:3cd0a11a2f91 32
Anaesthetix 0:3cd0a11a2f91 33 wait_ms(50);
Anaesthetix 0:3cd0a11a2f91 34
Anaesthetix 0:3cd0a11a2f91 35 _lcd->write(0xAE); // Display off
Anaesthetix 0:3cd0a11a2f91 36 _lcd->write(0x02); // Set lower column address
Anaesthetix 0:3cd0a11a2f91 37 _lcd->write(0x10); // Set higher column address
Anaesthetix 0:3cd0a11a2f91 38 _lcd->write(0x40); // Set display start line
Anaesthetix 0:3cd0a11a2f91 39 _lcd->write(0xB0); // Set page address
Anaesthetix 0:3cd0a11a2f91 40 _lcd->write(0x81); // Set contrast to
Anaesthetix 0:3cd0a11a2f91 41 _lcd->write(0x80); // 128
Anaesthetix 0:3cd0a11a2f91 42 _lcd->write(0xA1); // Segment remap
Anaesthetix 0:3cd0a11a2f91 43 _lcd->write(0xA6); // Inverse: normal (A7 = inverse)
Anaesthetix 0:3cd0a11a2f91 44 _lcd->write(0xA8); // Multiplex ratio
Anaesthetix 0:3cd0a11a2f91 45 _lcd->write(0x3F); // Duty = 1/32
Anaesthetix 0:3cd0a11a2f91 46 _lcd->write(0xAD); // Charge pump enable
Anaesthetix 0:3cd0a11a2f91 47 _lcd->write(0x8B); // External VCC
Anaesthetix 0:3cd0a11a2f91 48 _lcd->write(0x33); // VPP: 9v
Anaesthetix 0:3cd0a11a2f91 49 _lcd->write(0xC8); // Com scan direction
Anaesthetix 0:3cd0a11a2f91 50 _lcd->write(0xD3); // Display offset
Anaesthetix 0:3cd0a11a2f91 51 _lcd->write(0x00); // 0x20
Anaesthetix 0:3cd0a11a2f91 52 _lcd->write(0xD5); // Osc division
Anaesthetix 0:3cd0a11a2f91 53 _lcd->write(0x80);
Anaesthetix 0:3cd0a11a2f91 54 _lcd->write(0xD9); // Pre-charge period
Anaesthetix 0:3cd0a11a2f91 55 _lcd->write(0x1F); // 0x22
Anaesthetix 0:3cd0a11a2f91 56 _lcd->write(0xDA); // Set com pins
Anaesthetix 0:3cd0a11a2f91 57 _lcd->write(0x12);
Anaesthetix 0:3cd0a11a2f91 58 _lcd->write(0xDB); // Set vcomh
Anaesthetix 0:3cd0a11a2f91 59 _lcd->write(0x40);
Anaesthetix 0:3cd0a11a2f91 60 _lcd->write(0xAF); // Display ON
Anaesthetix 0:3cd0a11a2f91 61 _lcd_cs->write(1);
Anaesthetix 0:3cd0a11a2f91 62 _lcd_cd->write(1);
Anaesthetix 0:3cd0a11a2f91 63
Anaesthetix 0:3cd0a11a2f91 64 }
Anaesthetix 0:3cd0a11a2f91 65
Anaesthetix 0:3cd0a11a2f91 66 void SSH1106::setContrast(char contrast)
Anaesthetix 0:3cd0a11a2f91 67 {
Anaesthetix 0:3cd0a11a2f91 68 _lcd_cs->write(0); // enable SPI
Anaesthetix 0:3cd0a11a2f91 69 _lcd_cd->write(0); // command mode
Anaesthetix 0:3cd0a11a2f91 70 _lcd->write(0x81); // command to set contrast
Anaesthetix 0:3cd0a11a2f91 71 _lcd->write(contrast); // set contrast
Anaesthetix 0:3cd0a11a2f91 72 _lcd_cs->write(1);
Anaesthetix 0:3cd0a11a2f91 73 _lcd_cd->write(1);
Anaesthetix 0:3cd0a11a2f91 74 }
Anaesthetix 0:3cd0a11a2f91 75
Anaesthetix 0:3cd0a11a2f91 76 void SSH1106::setCursor(char column, char line)
Anaesthetix 0:3cd0a11a2f91 77 {
Anaesthetix 0:3cd0a11a2f91 78 int i, j;
Anaesthetix 0:3cd0a11a2f91 79 column = column+2; // column+4
Anaesthetix 0:3cd0a11a2f91 80
Anaesthetix 0:3cd0a11a2f91 81 i=(column&0xF0)>>4;
Anaesthetix 0:3cd0a11a2f91 82 j=column&0x0F;
Anaesthetix 0:3cd0a11a2f91 83 _lcd_cd->write(0);
Anaesthetix 0:3cd0a11a2f91 84 _lcd->write(0xb0+line);
Anaesthetix 0:3cd0a11a2f91 85 _lcd->write(0x10+i);
Anaesthetix 0:3cd0a11a2f91 86 _lcd->write(j);
Anaesthetix 0:3cd0a11a2f91 87 _lcd_cd->write(1);
Anaesthetix 0:3cd0a11a2f91 88 }
Anaesthetix 0:3cd0a11a2f91 89
Anaesthetix 0:3cd0a11a2f91 90 void SSH1106::clear()
Anaesthetix 0:3cd0a11a2f91 91 {
Anaesthetix 0:3cd0a11a2f91 92 _lcd_cs->write(0);
Anaesthetix 0:3cd0a11a2f91 93 _lcd_cd->write(1);
Anaesthetix 0:3cd0a11a2f91 94
Anaesthetix 0:3cd0a11a2f91 95 for(unsigned short j = 0; j < 8; j++) {
Anaesthetix 0:3cd0a11a2f91 96 SSH1106::setCursor(0, j);
Anaesthetix 0:3cd0a11a2f91 97 for(unsigned short i = 0; i < 128 ; i++) {
Anaesthetix 0:3cd0a11a2f91 98 _lcd->write(0x00);
Anaesthetix 0:3cd0a11a2f91 99 }
Anaesthetix 0:3cd0a11a2f91 100 }
Anaesthetix 0:3cd0a11a2f91 101
Anaesthetix 0:3cd0a11a2f91 102 SSH1106::setCursor(0, 0);
Anaesthetix 0:3cd0a11a2f91 103
Anaesthetix 0:3cd0a11a2f91 104 _lcd_cs->write(1);
Anaesthetix 0:3cd0a11a2f91 105 }
Anaesthetix 0:3cd0a11a2f91 106
Anaesthetix 0:3cd0a11a2f91 107 void SSH1106::writeText2d(char column, char page, const char font_address[96][8], const char *text, int size)
Anaesthetix 0:3cd0a11a2f91 108 {
Anaesthetix 0:3cd0a11a2f91 109 _lcd_cs->write(0);
Anaesthetix 0:3cd0a11a2f91 110 SSH1106::setCursor(column, page);
Anaesthetix 0:3cd0a11a2f91 111 for(int i=0; i<size; i++) {
Anaesthetix 0:3cd0a11a2f91 112 for(int a=0; a<8; a++) {
Anaesthetix 0:3cd0a11a2f91 113 _lcd->write((font_address[(text[i]-32)][a]));
Anaesthetix 0:3cd0a11a2f91 114 }
Anaesthetix 0:3cd0a11a2f91 115 }
Anaesthetix 0:3cd0a11a2f91 116 _lcd_cs->write(1);
Anaesthetix 0:3cd0a11a2f91 117 }
Anaesthetix 0:3cd0a11a2f91 118
Anaesthetix 0:3cd0a11a2f91 119 void SSH1106::writeText(char column, char page, const char *font_address, const char *text, const uint8_t size)
Anaesthetix 0:3cd0a11a2f91 120 {
Anaesthetix 0:3cd0a11a2f91 121 // Position of character data in memory array
Anaesthetix 0:3cd0a11a2f91 122 uint16_t pos_array;
Anaesthetix 0:3cd0a11a2f91 123 // temporary column, page address, and column_cnt are used
Anaesthetix 0:3cd0a11a2f91 124 // to stay inside display area
Anaesthetix 0:3cd0a11a2f91 125 uint8_t i,y, column_cnt = 0;
Anaesthetix 0:3cd0a11a2f91 126 uint8_t count = 0;
Anaesthetix 0:3cd0a11a2f91 127
Anaesthetix 0:3cd0a11a2f91 128 // font information, needed for calculation
Anaesthetix 0:3cd0a11a2f91 129 uint8_t start_code, last_code, width, page_height, bytes_p_char;
Anaesthetix 0:3cd0a11a2f91 130
Anaesthetix 0:3cd0a11a2f91 131 uint8_t *txtbuffer;
Anaesthetix 0:3cd0a11a2f91 132
Anaesthetix 0:3cd0a11a2f91 133 start_code = font_address[2]; // get first defined character
Anaesthetix 0:3cd0a11a2f91 134 last_code = font_address[3]; // get last defined character
Anaesthetix 0:3cd0a11a2f91 135 width = font_address[4]; // width in pixel of one char
Anaesthetix 0:3cd0a11a2f91 136 page_height = font_address[6]; // page count per char
Anaesthetix 0:3cd0a11a2f91 137 bytes_p_char = font_address[7]; // bytes per char
Anaesthetix 0:3cd0a11a2f91 138
Anaesthetix 0:3cd0a11a2f91 139 _lcd_cs->write(0); // Enable SPI
Anaesthetix 0:3cd0a11a2f91 140 _lcd_cd->write(1); // Data mode
Anaesthetix 0:3cd0a11a2f91 141
Anaesthetix 0:3cd0a11a2f91 142 if(page_height + page > LCDPAGES) //stay inside display area
Anaesthetix 0:3cd0a11a2f91 143 page_height = LCDPAGES - page;
Anaesthetix 0:3cd0a11a2f91 144
Anaesthetix 0:3cd0a11a2f91 145 // The string is displayed character after character. If the font has more then one page,
Anaesthetix 0:3cd0a11a2f91 146 // the top page is printed first, then the next page and so on
Anaesthetix 0:3cd0a11a2f91 147 for(y = 0; y < page_height; y++) {
Anaesthetix 0:3cd0a11a2f91 148 txtbuffer = &_lcdbuffer[page*LCDWIDTH + column];
Anaesthetix 0:3cd0a11a2f91 149 column_cnt = 0; // clear column_cnt start point
Anaesthetix 0:3cd0a11a2f91 150 i = 0;
Anaesthetix 0:3cd0a11a2f91 151 while(( i < size) && ((column_cnt + column) < LCDWIDTH)) {
Anaesthetix 0:3cd0a11a2f91 152 if(text[i] < start_code || (uint8_t)text[i] > last_code) //make sure data is valid
Anaesthetix 0:3cd0a11a2f91 153 i++;
Anaesthetix 0:3cd0a11a2f91 154 else {
Anaesthetix 0:3cd0a11a2f91 155 // calculate position of ASCII character in font array
Anaesthetix 0:3cd0a11a2f91 156 // bytes for header + (ASCII - startcode) * bytes per char)
Anaesthetix 0:3cd0a11a2f91 157 pos_array = 8 + (uint8_t)(text[i++] - start_code) * bytes_p_char;
Anaesthetix 0:3cd0a11a2f91 158
Anaesthetix 0:3cd0a11a2f91 159 // get the dot pattern for the part of the char to print
Anaesthetix 0:3cd0a11a2f91 160 pos_array += y*width;
Anaesthetix 0:3cd0a11a2f91 161
Anaesthetix 0:3cd0a11a2f91 162 // stay inside display area
Anaesthetix 0:3cd0a11a2f91 163 if((column_cnt + width + column) > LCDWIDTH)
Anaesthetix 0:3cd0a11a2f91 164 column_cnt = LCDWIDTH-width;
Anaesthetix 0:3cd0a11a2f91 165
Anaesthetix 0:3cd0a11a2f91 166 // copy character data to buffer
Anaesthetix 0:3cd0a11a2f91 167 memcpy (txtbuffer+column_cnt,font_address+pos_array,width);
Anaesthetix 0:3cd0a11a2f91 168 }
Anaesthetix 0:3cd0a11a2f91 169
Anaesthetix 0:3cd0a11a2f91 170 column_cnt += width;
Anaesthetix 0:3cd0a11a2f91 171 }
Anaesthetix 0:3cd0a11a2f91 172 SSH1106::setCursor(column,page); // set start position x and y
Anaesthetix 0:3cd0a11a2f91 173
Anaesthetix 0:3cd0a11a2f91 174 do {
Anaesthetix 0:3cd0a11a2f91 175 _lcd->write(txtbuffer[count]);
Anaesthetix 0:3cd0a11a2f91 176 count++;
Anaesthetix 0:3cd0a11a2f91 177 } while ((count <= column_cnt));
Anaesthetix 0:3cd0a11a2f91 178 }
Anaesthetix 0:3cd0a11a2f91 179
Anaesthetix 0:3cd0a11a2f91 180 _lcd_cs->write(1); // Disable SPI
Anaesthetix 0:3cd0a11a2f91 181
Anaesthetix 0:3cd0a11a2f91 182 }
Anaesthetix 0:3cd0a11a2f91 183
Anaesthetix 0:3cd0a11a2f91 184 void SSH1106::drawBitmap(const char *data)
Anaesthetix 0:3cd0a11a2f91 185 {
Anaesthetix 0:3cd0a11a2f91 186 int cnt = 0;
Anaesthetix 0:3cd0a11a2f91 187 _lcd_cs->write(0);
Anaesthetix 0:3cd0a11a2f91 188 _lcd_cd->write(1);
Anaesthetix 0:3cd0a11a2f91 189 SSH1106::setCursor(0,0);
Anaesthetix 0:3cd0a11a2f91 190 for(int row=0; row<8; row++) {
Anaesthetix 0:3cd0a11a2f91 191 SSH1106::setCursor(0, row);
Anaesthetix 0:3cd0a11a2f91 192 for(int column=0; column<128; column++) {
Anaesthetix 0:3cd0a11a2f91 193 _lcd->write(data[cnt]);
Anaesthetix 0:3cd0a11a2f91 194 cnt++;
Anaesthetix 0:3cd0a11a2f91 195 }
Anaesthetix 0:3cd0a11a2f91 196 }
Anaesthetix 0:3cd0a11a2f91 197 }