displaying on SSD1306, 128x64 pixels OLED

Dependencies:   microbit

Committer:
bvirk
Date:
Mon Feb 24 18:31:22 2020 +0000
Revision:
8:5972683a7190
Parent:
6:c69f08f464b5
Child:
10:8bf77efd1579
class header doc copied to cpp files

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bvirk 3:f36427797fd7 1
bvirk 3:f36427797fd7 2 #include "MicroBit.h"
bvirk 3:f36427797fd7 3 #include "MicroBitI2C.h"
bvirk 3:f36427797fd7 4
bvirk 3:f36427797fd7 5 #include "OLED.h"
bvirk 4:19da6ea94042 6 #include "cppNorm.h"
bvirk 4:19da6ea94042 7
bvirk 4:19da6ea94042 8 /**
bvirk 8:5972683a7190 9 * ssd1306 compatible device of 128x64 pixels OLED display.
bvirk 8:5972683a7190 10 * Init() must be called after construction.
bvirk 8:5972683a7190 11 * Works for some untraced circumstances not in fibers
bvirk 8:5972683a7190 12 */
bvirk 3:f36427797fd7 13 OLED::OLED() :
bvirk 3:f36427797fd7 14 i2c(I2C_SDA0,I2C_SCL0)
bvirk 3:f36427797fd7 15 ,charX(0)
bvirk 3:f36427797fd7 16 ,charY(0)
bvirk 3:f36427797fd7 17 ,displayWidth(128)
bvirk 3:f36427797fd7 18 ,displayHeight(64 / 8)
bvirk 4:19da6ea94042 19 ,screenSize(0)
bvirk 4:19da6ea94042 20 ,pendingNewline(false)
bvirk 4:19da6ea94042 21 {}
bvirk 3:f36427797fd7 22
bvirk 3:f36427797fd7 23 void OLED::command(uint8_t cmd) {
bvirk 3:f36427797fd7 24 char buf[2];
bvirk 3:f36427797fd7 25 buf[0] = '\0';
bvirk 3:f36427797fd7 26 buf[1] = cmd;
bvirk 3:f36427797fd7 27 i2c.write(chipAdress,buf,2);
bvirk 3:f36427797fd7 28 }
bvirk 8:5972683a7190 29
bvirk 8:5972683a7190 30 /**
bvirk 8:5972683a7190 31 * Initialisere display and clears it. A buffer representing charaters are
bvirk 8:5972683a7190 32 * filled with space characters
bvirk 8:5972683a7190 33 */
bvirk 4:19da6ea94042 34 void OLED::init() {
bvirk 4:19da6ea94042 35 init(128, 64);
bvirk 4:19da6ea94042 36 }
bvirk 4:19da6ea94042 37
bvirk 3:f36427797fd7 38
bvirk 3:f36427797fd7 39 void OLED::init(uint8_t width, uint8_t height) {
bvirk 3:f36427797fd7 40 command(SSD1306_DISPLAYOFF);
bvirk 3:f36427797fd7 41 command(SSD1306_SETDISPLAYCLOCKDIV);
bvirk 3:f36427797fd7 42 command(0x80); // the suggested ratio 0x80
bvirk 3:f36427797fd7 43 command(SSD1306_SETMULTIPLEX);
bvirk 3:f36427797fd7 44 command(0x3F);
bvirk 3:f36427797fd7 45 command(SSD1306_SETDISPLAYOFFSET);
bvirk 3:f36427797fd7 46 command(0x0); // no offset
bvirk 3:f36427797fd7 47 command(SSD1306_SETSTARTLINE | 0x0); // line #0
bvirk 3:f36427797fd7 48 command(SSD1306_CHARGEPUMP);
bvirk 3:f36427797fd7 49 command(0x14);
bvirk 3:f36427797fd7 50 command(SSD1306_MEMORYMODE);
bvirk 3:f36427797fd7 51 command(0x00); // 0x0 act like ks0108
bvirk 3:f36427797fd7 52 command(SSD1306_SEGREMAP | 0x1);
bvirk 3:f36427797fd7 53 command(SSD1306_COMSCANDEC);
bvirk 3:f36427797fd7 54 command(SSD1306_SETCOMPINS);
bvirk 3:f36427797fd7 55 command(0x12);
bvirk 3:f36427797fd7 56 command(SSD1306_SETCONTRAST);
bvirk 3:f36427797fd7 57 command(0xCF);
bvirk 3:f36427797fd7 58 command(SSD1306_SETPRECHARGE);
bvirk 3:f36427797fd7 59 command(0xF1);
bvirk 3:f36427797fd7 60 command(SSD1306_SETVCOMDETECT);
bvirk 3:f36427797fd7 61 command(0x40);
bvirk 3:f36427797fd7 62 command(SSD1306_DISPLAYALLON_RESUME);
bvirk 3:f36427797fd7 63 command(SSD1306_NORMALDISPLAY);
bvirk 3:f36427797fd7 64 command(SSD1306_DISPLAYON);
bvirk 3:f36427797fd7 65 displayWidth = width;
bvirk 3:f36427797fd7 66 displayHeight = height / 8;
bvirk 3:f36427797fd7 67 screenSize = displayWidth * displayHeight;
bvirk 3:f36427797fd7 68 charX = xOffset;
bvirk 3:f36427797fd7 69 charY = yOffset;
bvirk 3:f36427797fd7 70 loadStarted = false;
bvirk 3:f36427797fd7 71 loadPercent = 0;
bvirk 3:f36427797fd7 72 clear();
bvirk 3:f36427797fd7 73 }
bvirk 3:f36427797fd7 74
bvirk 8:5972683a7190 75 /**
bvirk 8:5972683a7190 76 * clears the display
bvirk 8:5972683a7190 77 */
bvirk 3:f36427797fd7 78 void OLED::clear() {
bvirk 3:f36427797fd7 79 loadStarted = false;
bvirk 3:f36427797fd7 80 loadPercent = 0;
bvirk 3:f36427797fd7 81 command(SSD1306_SETCOLUMNADRESS);
bvirk 3:f36427797fd7 82 command(0x00);
bvirk 3:f36427797fd7 83 command(displayWidth - 1);
bvirk 3:f36427797fd7 84 command(SSD1306_SETPAGEADRESS);
bvirk 3:f36427797fd7 85 command(0x00);
bvirk 3:f36427797fd7 86 command(displayHeight - 1);
bvirk 3:f36427797fd7 87 char data[17];
bvirk 8:5972683a7190 88 data[0] = 0x40;
bvirk 3:f36427797fd7 89 for (int8_t i = 1; i < 17; i++)
bvirk 3:f36427797fd7 90 data[i] = 0x00;
bvirk 3:f36427797fd7 91 for (int16_t i = 0; i < screenSize; i += 16) {
bvirk 3:f36427797fd7 92 i2c.write(chipAdress, data, 17,false);
bvirk 3:f36427797fd7 93 }
bvirk 3:f36427797fd7 94 charX = xOffset;
bvirk 3:f36427797fd7 95 charY = yOffset;
bvirk 4:19da6ea94042 96 setTextArea(32,true);
bvirk 3:f36427797fd7 97 }
bvirk 3:f36427797fd7 98
bvirk 8:5972683a7190 99 /**
bvirk 8:5972683a7190 100 * Put a char on display. A value in range [0x00,0xFF] i permitted -
bvirk 8:5972683a7190 101 * 0,0xff and 0x20 are bitpatterns with all null pixels (like space)
bvirk 8:5972683a7190 102 *
bvirk 8:5972683a7190 103 * @param x horizontal pixelwise position, range [0,displayWidth - 6]
bvirk 8:5972683a7190 104 * @param y vertical position, range [0,7]
bvirk 8:5972683a7190 105 */
bvirk 3:f36427797fd7 106 void OLED::drawChar(uint8_t x, uint8_t y, uint8_t chr ) {
bvirk 3:f36427797fd7 107 command(SSD1306_SETCOLUMNADRESS);
bvirk 3:f36427797fd7 108 command(x);
bvirk 3:f36427797fd7 109 command(x + 5);
bvirk 3:f36427797fd7 110 command(SSD1306_SETPAGEADRESS);
bvirk 3:f36427797fd7 111 command(y);
bvirk 3:f36427797fd7 112 command(y + 1);
bvirk 4:19da6ea94042 113 textArea[x/6][y]=chr;
bvirk 3:f36427797fd7 114 char line[2];
bvirk 3:f36427797fd7 115 line[0] = 0x40;
bvirk 3:f36427797fd7 116 for (int8_t i = 0; i < 6; i++) {
bvirk 3:f36427797fd7 117 if (i == 5)
bvirk 3:f36427797fd7 118 line[1] = 0x00;
bvirk 3:f36427797fd7 119 else
bvirk 3:f36427797fd7 120 line[1] = font[chr][i];
bvirk 3:f36427797fd7 121 i2c.write(chipAdress, line, 2, false);
bvirk 3:f36427797fd7 122 }
bvirk 3:f36427797fd7 123 }
bvirk 3:f36427797fd7 124
bvirk 4:19da6ea94042 125
bvirk 4:19da6ea94042 126 void OLED::setTextArea(uint8_t chr, bool setLine8=false) {
bvirk 4:19da6ea94042 127 for (int8_t line = 0; line <= 8; line++)
bvirk 4:19da6ea94042 128 if (line < 8 || setLine8)
bvirk 4:19da6ea94042 129 for (int8_t xPos = 0; xPos < 22; xPos++)
bvirk 4:19da6ea94042 130 textArea[xPos][line]=chr;
bvirk 4:19da6ea94042 131 }
bvirk 4:19da6ea94042 132
bvirk 8:5972683a7190 133 /**
bvirk 8:5972683a7190 134 * Scroll display one line up. An empty line will arise at bottom.
bvirk 8:5972683a7190 135 */
bvirk 4:19da6ea94042 136 void OLED::scroll() {
bvirk 4:19da6ea94042 137 for (int8_t line = 1; line <= 8; line++)
bvirk 4:19da6ea94042 138 for (int8_t xPos = 0; xPos < 22; xPos++)
bvirk 4:19da6ea94042 139 drawChar(6*xPos,line-1,textArea[xPos][line]);
bvirk 4:19da6ea94042 140 }
bvirk 4:19da6ea94042 141
bvirk 8:5972683a7190 142 /**
bvirk 8:5972683a7190 143 * Makes a newline by incrementing charY and assigning xOffset to charX
bvirk 8:5972683a7190 144 * if charY becomes 8 the display screen is scrolled one line and charY
bvirk 8:5972683a7190 145 * is decremented to 7. pendingNewline=false is done at last.
bvirk 8:5972683a7190 146 */
bvirk 8:5972683a7190 147 /**
bvirk 8:5972683a7190 148 * Makes a newline by incrementing charY and assigning xOffset to charX
bvirk 8:5972683a7190 149 * if charY becomes 8 the display screen is scrolled one line and charY
bvirk 8:5972683a7190 150 * is decremented to 7. pendingNewline=false is done at last.
bvirk 8:5972683a7190 151 */
bvirk 4:19da6ea94042 152 void OLED::newLine() {
bvirk 4:19da6ea94042 153 charY++;
bvirk 4:19da6ea94042 154 charX = xOffset;
bvirk 4:19da6ea94042 155 if (charY == 8) {
bvirk 4:19da6ea94042 156 charY = 7;
bvirk 4:19da6ea94042 157 scroll();
bvirk 4:19da6ea94042 158 }
bvirk 4:19da6ea94042 159 pendingNewline=false;
bvirk 4:19da6ea94042 160 }
bvirk 4:19da6ea94042 161
bvirk 8:5972683a7190 162 /**
bvirk 8:5972683a7190 163 * Writes a string at charX, charY position. Afterwards are
bvirk 8:5972683a7190 164 * charX, charY set to the new starting point for writting
bvirk 8:5972683a7190 165 * \n and \r is processed - \n includes \r functionality
bvirk 8:5972683a7190 166 *
bvirk 8:5972683a7190 167 * @param str to be displayed at (charX, charY).
bvirk 8:5972683a7190 168 */
bvirk 6:c69f08f464b5 169 void OLED::puts(string str) {
bvirk 3:f36427797fd7 170 for (uint16_t i = 0; i < str.length(); i++) {
bvirk 6:c69f08f464b5 171 if (str.charAt(i) == '\r')
bvirk 4:19da6ea94042 172 charX = xOffset;
bvirk 6:c69f08f464b5 173 else if (str.charAt(i) == '\n') {
bvirk 6:c69f08f464b5 174 if (pendingNewline)
bvirk 6:c69f08f464b5 175 newLine();
bvirk 6:c69f08f464b5 176 pendingNewline=true;
bvirk 6:c69f08f464b5 177 } else {
bvirk 6:c69f08f464b5 178 if (pendingNewline || charX > displayWidth - 6)
bvirk 6:c69f08f464b5 179 newLine();
bvirk 6:c69f08f464b5 180 drawChar(charX, charY, (uint8_t)str.charAt(i));
bvirk 6:c69f08f464b5 181 charX += 6;
bvirk 3:f36427797fd7 182 }
bvirk 3:f36427797fd7 183 }
bvirk 3:f36427797fd7 184 }
bvirk 4:19da6ea94042 185
bvirk 8:5972683a7190 186 /**
bvirk 8:5972683a7190 187 * printf - the old clasic but don't use \n or \r in format string
bvirk 8:5972683a7190 188 * \n and \r is processed - \n includes \r functionality
bvirk 8:5972683a7190 189 * This function is the main reason to that OLED not works in fibers.
bvirk 8:5972683a7190 190 */
bvirk 6:c69f08f464b5 191 uint8_t OLED::printf(const char * fmt, ...) {
bvirk 6:c69f08f464b5 192 va_list args;
bvirk 6:c69f08f464b5 193 va_start(args, fmt);
bvirk 6:c69f08f464b5 194 uint8_t len = min(vsnprintf(printf_text, printf_textSize, fmt, args), printf_textSize);
bvirk 6:c69f08f464b5 195 va_end(args);
bvirk 6:c69f08f464b5 196 printf_text[len] = '\0';
bvirk 6:c69f08f464b5 197 puts(printf_text);
bvirk 6:c69f08f464b5 198 return len;
bvirk 4:19da6ea94042 199 }