displaying on SSD1306, 128x64 pixels OLED
OLED.cpp
- Committer:
- bvirk
- Date:
- 2020-02-24
- Revision:
- 8:5972683a7190
- Parent:
- 6:c69f08f464b5
- Child:
- 10:8bf77efd1579
File content as of revision 8:5972683a7190:
#include "MicroBit.h" #include "MicroBitI2C.h" #include "OLED.h" #include "cppNorm.h" /** * ssd1306 compatible device of 128x64 pixels OLED display. * Init() must be called after construction. * Works for some untraced circumstances not in fibers */ OLED::OLED() : i2c(I2C_SDA0,I2C_SCL0) ,charX(0) ,charY(0) ,displayWidth(128) ,displayHeight(64 / 8) ,screenSize(0) ,pendingNewline(false) {} void OLED::command(uint8_t cmd) { char buf[2]; buf[0] = '\0'; buf[1] = cmd; i2c.write(chipAdress,buf,2); } /** * Initialisere display and clears it. A buffer representing charaters are * filled with space characters */ void OLED::init() { init(128, 64); } void OLED::init(uint8_t width, uint8_t height) { command(SSD1306_DISPLAYOFF); command(SSD1306_SETDISPLAYCLOCKDIV); command(0x80); // the suggested ratio 0x80 command(SSD1306_SETMULTIPLEX); command(0x3F); command(SSD1306_SETDISPLAYOFFSET); command(0x0); // no offset command(SSD1306_SETSTARTLINE | 0x0); // line #0 command(SSD1306_CHARGEPUMP); command(0x14); command(SSD1306_MEMORYMODE); command(0x00); // 0x0 act like ks0108 command(SSD1306_SEGREMAP | 0x1); command(SSD1306_COMSCANDEC); command(SSD1306_SETCOMPINS); command(0x12); command(SSD1306_SETCONTRAST); command(0xCF); command(SSD1306_SETPRECHARGE); command(0xF1); command(SSD1306_SETVCOMDETECT); command(0x40); command(SSD1306_DISPLAYALLON_RESUME); command(SSD1306_NORMALDISPLAY); command(SSD1306_DISPLAYON); displayWidth = width; displayHeight = height / 8; screenSize = displayWidth * displayHeight; charX = xOffset; charY = yOffset; loadStarted = false; loadPercent = 0; clear(); } /** * clears the display */ void OLED::clear() { loadStarted = false; loadPercent = 0; command(SSD1306_SETCOLUMNADRESS); command(0x00); command(displayWidth - 1); command(SSD1306_SETPAGEADRESS); command(0x00); command(displayHeight - 1); char data[17]; data[0] = 0x40; for (int8_t i = 1; i < 17; i++) data[i] = 0x00; for (int16_t i = 0; i < screenSize; i += 16) { i2c.write(chipAdress, data, 17,false); } charX = xOffset; charY = yOffset; setTextArea(32,true); } /** * Put a char on display. A value in range [0x00,0xFF] i permitted - * 0,0xff and 0x20 are bitpatterns with all null pixels (like space) * * @param x horizontal pixelwise position, range [0,displayWidth - 6] * @param y vertical position, range [0,7] */ void OLED::drawChar(uint8_t x, uint8_t y, uint8_t chr ) { command(SSD1306_SETCOLUMNADRESS); command(x); command(x + 5); command(SSD1306_SETPAGEADRESS); command(y); command(y + 1); textArea[x/6][y]=chr; char line[2]; line[0] = 0x40; for (int8_t i = 0; i < 6; i++) { if (i == 5) line[1] = 0x00; else line[1] = font[chr][i]; i2c.write(chipAdress, line, 2, false); } } void OLED::setTextArea(uint8_t chr, bool setLine8=false) { for (int8_t line = 0; line <= 8; line++) if (line < 8 || setLine8) for (int8_t xPos = 0; xPos < 22; xPos++) textArea[xPos][line]=chr; } /** * Scroll display one line up. An empty line will arise at bottom. */ void OLED::scroll() { for (int8_t line = 1; line <= 8; line++) for (int8_t xPos = 0; xPos < 22; xPos++) drawChar(6*xPos,line-1,textArea[xPos][line]); } /** * Makes a newline by incrementing charY and assigning xOffset to charX * if charY becomes 8 the display screen is scrolled one line and charY * is decremented to 7. pendingNewline=false is done at last. */ /** * Makes a newline by incrementing charY and assigning xOffset to charX * if charY becomes 8 the display screen is scrolled one line and charY * is decremented to 7. pendingNewline=false is done at last. */ void OLED::newLine() { charY++; charX = xOffset; if (charY == 8) { charY = 7; scroll(); } pendingNewline=false; } /** * Writes a string at charX, charY position. Afterwards are * charX, charY set to the new starting point for writting * \n and \r is processed - \n includes \r functionality * * @param str to be displayed at (charX, charY). */ void OLED::puts(string str) { for (uint16_t i = 0; i < str.length(); i++) { if (str.charAt(i) == '\r') charX = xOffset; else if (str.charAt(i) == '\n') { if (pendingNewline) newLine(); pendingNewline=true; } else { if (pendingNewline || charX > displayWidth - 6) newLine(); drawChar(charX, charY, (uint8_t)str.charAt(i)); charX += 6; } } } /** * printf - the old clasic but don't use \n or \r in format string * \n and \r is processed - \n includes \r functionality * This function is the main reason to that OLED not works in fibers. */ uint8_t OLED::printf(const char * fmt, ...) { va_list args; va_start(args, fmt); uint8_t len = min(vsnprintf(printf_text, printf_textSize, fmt, args), printf_textSize); va_end(args); printf_text[len] = '\0'; puts(printf_text); return len; }