Oled display settings for personal project
Diff: SSD1308.cpp
- Revision:
- 2:16c84a134393
- Parent:
- 1:b7e8f5139026
- Child:
- 4:df92b0c0cb92
--- a/SSD1308.cpp Sat Jul 21 12:49:33 2012 +0000 +++ b/SSD1308.cpp Mon Jul 23 20:03:18 2012 +0000 @@ -55,7 +55,6 @@ *@param uint8_t deviceAddress slaveaddress */ SSD1308::SSD1308(I2C &i2c, uint8_t deviceAddress) : _i2c(i2c) { -// m_devAddr = deviceAddress; _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write _readOpcode = deviceAddress | 0x01; // low order bit = 1 for read @@ -223,7 +222,7 @@ #endif -/** @brief write a progressbar to the display, Max Width is 52 pixels +/** @brief write a progressbar to the display, Width is (PRG_MAX_SCALE + 2) pixels * @param uint8_t page begin page (0..MAX_PAGE) * @param uint8_t col begin column (0..MAX_COL) * @param int percentage value (0..100) @@ -232,6 +231,7 @@ #define PRG_LEFT_EDGE 0xFF #define PRG_RIGHT_EDGE 0xFF #define PRG_ACTIVE 0xFF +//#define PRG_ACTIVE 0xBD #define PRG_NOT_ACTIVE 0x81 #if(0) @@ -239,10 +239,10 @@ void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) { uint8_t scale_value; - if (percentage < 0) { + if (percentage <= 0) { scale_value = 0; - } else if (percentage > 100) { - scale_value = PRG_MAX_SCALE; + } else if (percentage >= 100) { + scale_value = PRG_MAX_SCALE - 1; } else { scale_value = (percentage * PRG_MAX_SCALE) / 100; @@ -257,8 +257,10 @@ for (uint8_t col = 0; col < scale_value; col++) { _sendData(PRG_ACTIVE); } - - for (uint8_t col = scale_value; col < PRG_MAX_SCALE; col++) { + + _sendData(PRG_ACTIVE); + + for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) { _sendData(PRG_NOT_ACTIVE); } @@ -275,10 +277,10 @@ void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage) { uint8_t scale_value; - if (percentage < 0) { + if (percentage <= 0) { scale_value = 0; - } else if (percentage > 100) { - scale_value = PRG_MAX_SCALE; + } else if (percentage >= 100) { + scale_value = PRG_MAX_SCALE - 1 ; } else { scale_value = (percentage * PRG_MAX_SCALE) / 100; @@ -298,7 +300,9 @@ _i2c.write(PRG_ACTIVE); // Write Data } - for (uint8_t col = scale_value; col < PRG_MAX_SCALE; col++) { + _i2c.write(PRG_ACTIVE); // Write Data + + for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) { _i2c.write(PRG_NOT_ACTIVE); // Write Data } @@ -310,8 +314,53 @@ } #endif +/** @brief write a level meter to the display, Width is (PRG_MAX_SCALE + 2) pixels + * @param uint8_t page begin page (0..MAX_PAGE) + * @param uint8_t col begin column (0..MAX_COL) + * @param int percentage value (0..100) +*/ +//Optimised version +// Save lots of I2C S,P, address and datacommands: +// Send S, address, DATA_MODE, data, data, data,...., P +// +void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage) { + uint8_t scale_value; + + if (percentage <= 0) { + scale_value = 0; + } else if (percentage >= 100) { + scale_value = PRG_MAX_SCALE - 1; + } + else { + scale_value = (percentage * PRG_MAX_SCALE) / 100; + } + + //setDisplayOff(); + setPageAddress(page, page); + setColumnAddress(col, MAX_COL); + _i2c.start(); + _i2c.write(_writeOpcode); + _i2c.write(DATA_MODE); + _i2c.write(PRG_LEFT_EDGE); // Write Data + + for (uint8_t col = 0; col < scale_value; col++) { + _i2c.write(PRG_NOT_ACTIVE); // Write Data + } + + _i2c.write(PRG_ACTIVE); // Write Data at active meterlevel + + for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) { + _i2c.write(PRG_NOT_ACTIVE); // Write Data + } + + _i2c.write(PRG_RIGHT_EDGE); // Write Data + + _i2c.stop(); + + //setDisplayOn(); +} /** @brief Write single character to the display using the 8x8 fontable * @brief Start at current cursor location @@ -334,14 +383,16 @@ /** @brief Write a string to the display using the 8x8 font - * @brief Start at selected cursor location + * @brief Start at selected cursor location, text will wrap around until it is done * @param uint8_t row row number (0...ROWS/FONT_HEIGHT) * @param uint8_t col column number (0...COLUMNS/FONT_WIDTH) * @param uint16_t len number of chars in text * @param const char * text pointer to text */ -void SSD1308::writeString(uint8_t row, uint8_t col, uint16_t len, const char * text) { +void SSD1308::writeString(uint8_t row, uint8_t col, const char * text) { uint16_t index = 0; + uint16_t len = strlen(text); + setPageAddress(row, MAX_PAGE); const uint8_t col_addr = FONT8x8_WIDTH*col; setColumnAddress(col_addr, MAX_COL); @@ -449,6 +500,68 @@ } +/** @brief Write command that has five parameters +*/ +void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, + uint8_t param3, uint8_t param4, + uint8_t param5) { + +// Note continuationbit is set, so COMMAND_MODE must be +// repeated before each databyte that serves as parameter! + + _i2c.start(); + _i2c.write(_writeOpcode); + + _i2c.write(COMMAND_MODE); + _i2c.write(command); // Write Command + _i2c.write(COMMAND_MODE); + _i2c.write(param1); // Write Param1 + _i2c.write(COMMAND_MODE); + _i2c.write(param2); // Write Param2 + _i2c.write(COMMAND_MODE); + _i2c.write(param3); // Write Param3 + _i2c.write(COMMAND_MODE); + _i2c.write(param4); // Write Param4 + _i2c.write(COMMAND_MODE); + _i2c.write(param5); // Write Param5 + + _i2c.stop(); + +} + + +/** @brief Write command that has six parameters +*/ +void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2, + uint8_t param3, uint8_t param4, + uint8_t param5, uint8_t param6) { + +// Note continuationbit is set, so COMMAND_MODE must be +// repeated before each databyte that serves as parameter! + + _i2c.start(); + _i2c.write(_writeOpcode); + + _i2c.write(COMMAND_MODE); + _i2c.write(command); // Write Command + _i2c.write(COMMAND_MODE); + _i2c.write(param1); // Write Param1 + _i2c.write(COMMAND_MODE); + _i2c.write(param2); // Write Param2 + _i2c.write(COMMAND_MODE); + _i2c.write(param3); // Write Param3 + _i2c.write(COMMAND_MODE); + _i2c.write(param4); // Write Param4 + _i2c.write(COMMAND_MODE); + _i2c.write(param5); // Write Param5 + _i2c.write(COMMAND_MODE); + _i2c.write(param6); // Write Param6 + + _i2c.stop(); + +} + + #if(0) /** @brief Write command that has multiple parameters */ @@ -504,19 +617,30 @@ } - +/** @brief Set Horizontal Addressing Mode (cursor incr left-to-right, top-to-bottom) + * + */ void SSD1308::setHorizontalAddressingMode(){ setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE); } +/** @brief Set Vertical Addressing Mode (cursor incr top-to-bottom, left-to-right) + * + */ void SSD1308::setVerticalAddressingMode() { setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE); } +/** @brief Set Page Addressing Mode (cursor incr left-to-right) + * + */ void SSD1308::setPageAddressingMode(){ setMemoryAddressingMode(PAGE_ADDRESSING_MODE); } +/** @brief Set Addressing Mode + * @param uint8_t mode + */ void SSD1308::setMemoryAddressingMode(uint8_t mode){ _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode); @@ -540,6 +664,44 @@ _sendCommand(SET_COLUMN_ADDRESS, start, end); } +/** + * @brief Set Display StartLine, takes one byte, 0x00-0x3F + * @param uint8_t line startline (valid range 0..MAX_ROWS) + */ +void SSD1308::setDisplayStartLine(uint8_t line) { + + line = line & MAX_ROW; + + _sendCommand(SET_DISPLAY_START_LINE | line); +} + + +/** + * @brief Set Column Start (for Page Addressing Mode only) + * @param uint8_t column column start (valid range 0..MAX_COL) + */ +void SSD1308::setColumnStartForPageAddressingMode(uint8_t column) { + + column = column & MAX_COL; + + _sendCommand(SET_LOWER_COLUMN | ( column & 0x0F)); // lower nibble + _sendCommand(SET_HIGHER_COLUMN | ((column>>4) & 0x0F)); // higher nibble +} + + +/** + * @brief Set Page Start (for Page Addressing Mode only) + * @param uint8_t page page start (valid range PAGE0 - PAGE7) + */ +void SSD1308::setPageStartForPageAddressingMode(uint8_t page) { + + page = page & MAX_PAGE; + + _sendCommand(SET_PAGE_START_ADDRESS | page); + +} + + /** @brief Set Contrast * @param uint8_t contrast (valid range 0x00 (lowest) - 0xFF (highest)) */ @@ -651,31 +813,135 @@ } +/** @brief Shows All Pixels On + */ +void SSD1308::setEntireDisplayOn(){ + _sendCommand(SET_ENTIRE_DISPLAY_ON); +} + +/** @brief Shows Pixels as RAM content + */ +void SSD1308::setEntireDisplayRAM(){ + _sendCommand(SET_DISPLAY_GDDRAM); +} + +/** @brief Shows Pixels On or as RAM content + * @param bool on (true is All on, false is RAM content) + */ +void SSD1308::setEntireDisplay(bool on){ + if (on) { + setEntireDisplayOn(); // All Pixels on + } + else { + setEntireDisplayRAM(); // Pixels are RAM content + } +} + + +/** @brief Horizontal scroll by one column per interval + * @param bool left select Left/Right scroll + * @param uint8_t start_page begin page (0..MAX_PAGE) + * @param uint8_t end_page end page (start_page..MAX_PAGE) + * @param uint8_t interval scroll interval in frames (see codes above) + */ +void SSD1308::setContinuousHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, uint8_t interval) { + if (left) { + _sendCommand(SET_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Left + } + else { + _sendCommand(SET_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Right + } + +} + + +/** @brief Horizontal and Vertical scroll by one column per interval + * @param bool left select Left/Right scroll + * @param uint8_t start_page begin page (0..MAX_PAGE) + * @param uint8_t end_page end page (start_page..MAX_PAGE) + * @param uint8_t offset vert offset (0x01..0x63) + * @param uint8_t interval scroll interval in frames (see codes above) + */ +void SSD1308::setContinuousVerticalAndHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, + uint8_t offset, uint8_t interval) { + if (left) { + _sendCommand(SET_VERT_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Left + } + else { + _sendCommand(SET_VERT_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Right + } + +} + +/** @brief Set Vertical scroll area + * @param uint8_t topRowsFixed fixed rows (0..MAX_ROW) + * @param uint8_t scrollRowsoffset scroll rows (topRowsFixed..ROWS) + */ +void SSD1308::setVerticalScrollArea(uint8_t topRowsFixed, uint8_t scrollRows) { + + if ((topRowsFixed + scrollRows) > ROWS) { + scrollRows = ROWS - topRowsFixed; + }; + + _sendCommand(SET_VERTICAL_SCROLL_AREA, topRowsFixed, scrollRows); +} + +/** @brief Activate or Deactivate Horizontal and Vertical scroll + * @brief Note: after deactivating scrolling, the RAM data needs to be rewritten + * @param bool on activate scroll + */ +void SSD1308::setDisplayScroll(bool on) { + if (on) { + _sendCommand(SET_ACTIVATE_SCROLL); // Scroll on + } + else { + _sendCommand(SET_DEACTIVATE_SCROLL); // Scroll off + } +} + + + /** @brief Low level Init * @brief Init the configuration registers in accordance with the datasheet */ void SSD1308::_init() { -//not complete yet - _sendCommand(SET_DISPLAY_POWER_OFF); + _sendCommand(SET_DISPLAY_POWER_OFF); // 0xAE // column address 0 is mapped to SEG0 (Reset) - // row address 0 is mapped to COMM0 (Reset) - _sendCommand(SET_SEGMENT_REMAP_0); - _sendCommand(SET_COMMON_REMAP_0); + // row address 0 is mapped to COM0 (Reset) + _sendCommand(SET_SEGMENT_REMAP_0); // 0xA0 (Reset) + _sendCommand(SET_COMMON_REMAP_0); // 0xC0 (Reset) + + setDisplayStartLine(0); // 0x40 (Reset) - _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); + _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); // 0xDA, 0x12 (Reset) - setHorizontalAddressingMode(); // (Non-Reset) - - setExternalIref(); // (Reset) + // Pagemode or Horizontal mode +// setPageAddressingMode(); // 0x20, 0x02 (Reset) +// setColumnStartForPageAddressingMode(0); // 0x00, 0x10 (Reset = Column 0) +// setPageStartForPageAddressingMode(PAGE_0);// 0xBO (Reset = Page 0) + setHorizontalAddressingMode(); // 0x20, 0x00 (Non-Reset) + setColumnAddress(0, MAX_COL); // 0x21, 0x00, 0x37 (Reset) + setPageAddress(0, MAX_PAGE); // 0x22, 0x00, 0x07 (Reset) - _sendCommand(SET_CONTRAST, 0x7F); // (Reset) + setExternalIref(); // 0xAD, 0x10 (Reset) + + _sendCommand(SET_DISPLAY_CLOCK, 0x70); // 0xD5, 0x70 (Reset = 0x80) + _sendCommand(SET_PRECHARGE_TIME, 0x21); // 0xD9, 0x21 (Reset = 0x22) + _sendCommand(SET_VCOMH_DESELECT_LEVEL, 0x30); // 0xDB, 0x30 (Reset = 0x20) + _sendCommand(SET_MULTIPLEX_RATIO, 0x3F); // 0xA8, 0x3F (Reset) + _sendCommand(SET_DISPLAY_OFFSET, 0x00); // 0xD3, 0x00 (Reset) + + _sendCommand(SET_CONTRAST, 0x7F); // 0x81, 0x7F (Reset) - _sendCommand(SET_NORMAL_DISPLAY); + _sendCommand(SET_NORMAL_DISPLAY); // 0xA6 (Reset) + + setEntireDisplayRAM(); // 0xA4 (Reset) + setDisplayScroll(false); clearDisplay(); - _sendCommand(SET_DISPLAY_POWER_ON); + _sendCommand(SET_DISPLAY_POWER_ON); // 0xAF }