diff --git a/LCD_OLED.h b/LCD_OLED.h index efa2bc7..a635fb4 100644 --- a/LCD_OLED.h +++ b/LCD_OLED.h @@ -1,5 +1,5 @@ /* - * © 2020, Chris Harlow. All rights reserved. + * © 2020, Chris Harlow, 2021, Neil McKechnie. All rights reserved. * * This file is part of CommandStation-EX * @@ -18,40 +18,46 @@ */ // OLED Implementation of LCDDisplay class -// Note: this file is optionally included by LCD_Implenentation.h -// It is NOT a .cpp file to prevent it being compiled and demanding libraraies even when not needed. +// Note: this file is optionally included by LCD_Implementation.h +// It is NOT a .cpp file to prevent it being compiled and demanding libraries even when not needed. -#include -Adafruit_SSD1306 LCDDriver(OLED_DRIVER); +#include "SSD1306/SSD1306Ascii.h" +#include "SSD1306/SSD1306AsciiWire.h" +SSD1306AsciiWire LCDDriver; // DEVICE SPECIFIC LCDDisplay Implementation for OLED -LCDDisplay::LCDDisplay() { - if(LCDDriver.begin(SSD1306_SWITCHCAPVCC, 0x3C) || LCDDriver.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { - DIAG(F("\nOLED display found")); - delay(2000); // painful Adafruit splash pants! - lcdDisplay=this; - LCDDriver.setTextSize(1); // Normal 1:1 pixel scale - LCDDriver.setTextColor(SSD1306_WHITE); // Draw white text - interfake(OLED_DRIVER,0); - clear(); - return; + LCDDisplay::LCDDisplay() { + // Scan for device on 0x3c and 0x3d. + for (byte address=0x3c; address<=0x3d; address++) { + Wire.beginTransmission(address); + byte error = Wire.endTransmission(); + if (!error) { + // Device found + DIAG(F("\nOLED display found at 0x%x"), address); + interfake(OLED_DRIVER,0); + LCDDriver.begin(lcdRows==32 ? &Adafruit128x32 : &Adafruit128x64, address); + lcdDisplay=this; + LCDDriver.setFont(System5x7); // Normal 1:1 pixel scale + clear(); + return; } - DIAG(F("\nOLED display not found\n")); } + DIAG(F("\nOLED display not found\n")); + } void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; lcdRows=p2/8; (void)p3;} - void LCDDisplay::clearNative() {LCDDriver.clearDisplay();} + void LCDDisplay::clearNative() {LCDDriver.clear();} void LCDDisplay::setRowNative(byte row) { // Positions text write to start of row 1..n and clears previous text - int y=8*row; - LCDDriver.fillRect(0, y, LCDDriver.width(), 8, SSD1306_BLACK); + int y=row; LCDDriver.setCursor(0, y); - } + LCDDriver.clearToEOL(); + } - void LCDDisplay::writeNative(char * b){ LCDDriver.print(b); } + void LCDDisplay::writeNative(char * b){ LCDDriver.write(b); } - void LCDDisplay::displayNative() { LCDDriver.display(); } + void LCDDisplay::displayNative() { } diff --git a/SSD1306/SSD1306Ascii.cpp b/SSD1306/SSD1306Ascii.cpp new file mode 100644 index 0000000..70b6a63 --- /dev/null +++ b/SSD1306/SSD1306Ascii.cpp @@ -0,0 +1,383 @@ +/* Arduino SSD1306Ascii Library + * Copyright (C) 2015 by William Greiman + * + * This file is part of the Arduino SSD1306Ascii Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Arduino SSD1306Ascii Library. If not, see + * . + */ +#include "SSD1306Ascii.h" +//------------------------------------------------------------------------------ +uint8_t SSD1306Ascii::charWidth(uint8_t c) const { + if (!m_font) { + return 0; + } + uint8_t first = readFontByte(m_font + FONT_FIRST_CHAR); + uint8_t count = readFontByte(m_font + FONT_CHAR_COUNT); + if (c < first || c >= (first + count)) { + return 0; + } + if (fontSize() > 1) { + // Proportional font. + return m_magFactor*readFontByte(m_font + FONT_WIDTH_TABLE + c - first); + } + // Fixed width font. + return m_magFactor*readFontByte(m_font + FONT_WIDTH); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::clear() { +#if INCLUDE_SCROLLING + m_pageOffset = 0; + setStartLine(0); +#endif // INCLUDE_SCROLLING + clear(0, displayWidth() - 1, 0 , displayRows() - 1); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::clear(uint8_t c0, uint8_t c1, uint8_t r0, uint8_t r1) { + // Cancel skip character pixels. + m_skip = 0; + + // Insure only rows on display will be cleared. + if (r1 >= displayRows()) r1 = displayRows() - 1; + + for (uint8_t r = r0; r <= r1; r++) { + setCursor(c0, r); + for (uint8_t c = c0; c <= c1; c++) { + // Insure clear() writes zero. result is (m_invertMask^m_invertMask). + ssd1306WriteRamBuf(m_invertMask); + } + } + setCursor(c0, r0); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::clearToEOL() { + clear(m_col, displayWidth() -1, m_row, m_row + fontRows() - 1); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::clearField(uint8_t col, uint8_t row, uint8_t n) { + clear(col, col + fieldWidth(n) - 1, row, row + fontRows() - 1); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::displayRemap(bool mode) { + ssd1306WriteCmd(mode ? SSD1306_SEGREMAP : SSD1306_SEGREMAP | 1); + ssd1306WriteCmd(mode ? SSD1306_COMSCANINC : SSD1306_COMSCANDEC); +} +//------------------------------------------------------------------------------ +size_t SSD1306Ascii::fieldWidth(uint8_t n) { + return n*(fontWidth() + letterSpacing()); +} +//------------------------------------------------------------------------------ +uint8_t SSD1306Ascii::fontCharCount() const { + return m_font ? readFontByte(m_font + FONT_CHAR_COUNT) : 0; +} +//------------------------------------------------------------------------------ +char SSD1306Ascii::fontFirstChar() const { + return m_font ? readFontByte(m_font + FONT_FIRST_CHAR) : 0; +} +//------------------------------------------------------------------------------ +uint8_t SSD1306Ascii::fontHeight() const { + return m_font ? m_magFactor*readFontByte(m_font + FONT_HEIGHT) : 0; +} +//------------------------------------------------------------------------------ +uint8_t SSD1306Ascii::fontRows() const { + return m_font ? m_magFactor*((readFontByte(m_font + FONT_HEIGHT) + 7)/8) : 0; +} +//------------------------------------------------------------------------------ +uint16_t SSD1306Ascii::fontSize() const { + return (readFontByte(m_font) << 8) | readFontByte(m_font + 1); +} +//------------------------------------------------------------------------------ +uint8_t SSD1306Ascii::fontWidth() const { + return m_font ? m_magFactor*readFontByte(m_font + FONT_WIDTH) : 0; +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::init(const DevType* dev) { + m_col = 0; + m_row = 0; +#ifdef __AVR__ + const uint8_t* table = (const uint8_t*)pgm_read_word(&dev->initcmds); +#else // __AVR__ + const uint8_t* table = dev->initcmds; +#endif // __AVR + uint8_t size = readFontByte(&dev->initSize); + m_displayWidth = readFontByte(&dev->lcdWidth); + m_displayHeight = readFontByte(&dev->lcdHeight); + m_colOffset = readFontByte(&dev->colOffset); + for (uint8_t i = 0; i < size; i++) { + ssd1306WriteCmd(readFontByte(table + i)); + } + clear(); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::invertDisplay(bool invert) { + ssd1306WriteCmd(invert ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setCol(uint8_t col) { + if (col < m_displayWidth) { + m_col = col; + col += m_colOffset; + ssd1306WriteCmd(SSD1306_SETLOWCOLUMN | (col & 0XF)); + ssd1306WriteCmd(SSD1306_SETHIGHCOLUMN | (col >> 4)); + } +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setContrast(uint8_t value) { + ssd1306WriteCmd(SSD1306_SETCONTRAST); + ssd1306WriteCmd(value); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setCursor(uint8_t col, uint8_t row) { + setCol(col); + setRow(row); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setFont(const uint8_t* font) { + m_font = font; + if (font && fontSize() == 1) { + m_letterSpacing = 0; + } else { + m_letterSpacing = 1; + } +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setRow(uint8_t row) { + if (row < displayRows()) { + m_row = row; +#if INCLUDE_SCROLLING + ssd1306WriteCmd(SSD1306_SETSTARTPAGE | ((m_row + m_pageOffset) & 7)); +#else // INCLUDE_SCROLLING + ssd1306WriteCmd(SSD1306_SETSTARTPAGE | m_row); +#endif // INCLUDE_SCROLLING + } +} +#if INCLUDE_SCROLLING +//------------------------------------------------------------------------------ +void SSD1306Ascii::setPageOffset(uint8_t page) { + m_pageOffset = page & 7; + setRow(m_row); +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::setStartLine(uint8_t line) { + m_startLine = line & 0X3F; + ssd1306WriteCmd(SSD1306_SETSTARTLINE | m_startLine); +} +#endif // INCLUDE_SCROLLING +//------------------------------------------------------------------------------ +void SSD1306Ascii::ssd1306WriteRam(uint8_t c) { + if (m_col < m_displayWidth) { + writeDisplay(c^m_invertMask, SSD1306_MODE_RAM); + m_col++; + } +} +//------------------------------------------------------------------------------ +void SSD1306Ascii::ssd1306WriteRamBuf(uint8_t c) { + if (m_skip) { + m_skip--; + } else if (m_col < m_displayWidth) { + writeDisplay(c^m_invertMask, SSD1306_MODE_RAM_BUF); + m_col++; + } +} +//------------------------------------------------------------------------------ +GLCDFONTDECL(scaledNibble) = { + 0X00, 0X03, 0X0C, 0X0F, + 0X30, 0X33, 0X3C, 0X3F, + 0XC0, 0XC3, 0XCC, 0XCF, + 0XF0, 0XF3, 0XFC, 0XFF +}; +//------------------------------------------------------------------------------ +size_t SSD1306Ascii::strWidth(const char* str) const { + size_t sw = 0; + while (*str) { + uint8_t cw = charWidth(*str++); + if (cw == 0) { + return 0; + } + sw += cw + letterSpacing(); + } + return sw; +} +// //------------------------------------------------------------------------------ +// void SSD1306Ascii::tickerInit(TickerState* state, const uint8_t* font, +// uint8_t row, bool mag2X, uint8_t bgnCol, uint8_t endCol) { +// state->font = font; +// state->row = row; +// state->mag2X = mag2X; +// state->bgnCol = bgnCol; +// state->endCol = endCol < m_displayWidth ? endCol : m_displayWidth - 1; +// state->nQueue = 0; +// } +// //------------------------------------------------------------------------------ +// bool SSD1306Ascii::tickerText(TickerState* state, const char* text) { +// if (!text) { +// state->nQueue = 0; +// return true; +// } +// if (state->nQueue >= TICKER_QUEUE_DIM) { +// return false; +// } +// if (state->nQueue == 0) { +// state->init = true; +// } +// state->queue[state->nQueue++] = text; +// return true; +// } +// //------------------------------------------------------------------------------ +// int8_t SSD1306Ascii::tickerTick(TickerState* state) { +// if (!state->font) { +// return -1; +// } +// if (!state->nQueue) { +// return 0; +// } +// setFont(state->font); +// m_magFactor = state->mag2X ? 2 : 1; +// if (state->init) { +// clear(state->bgnCol, state->endCol, state->row, state->row + fontRows() -1); +// state->col = state->endCol; +// state->skip = 0; +// state->init = false; +// } +// // Adjust display width to truncate pixels after endCol. Find better way? +// uint8_t save = m_displayWidth; +// m_displayWidth = state->endCol + 1; + +// // Skip pixels before bgnCol. +// skipColumns(state->skip); +// setCursor(state->col, state->row); +// for (uint8_t i = 0; i < state->nQueue; i++) { +// const char* str = state->queue[i]; +// while (*str && m_col <= state->endCol) { +// write(*str++); +// } +// if (m_col > state->endCol) { +// break; +// } +// } +// if (m_col <= state->endCol) { +// clear(m_col, m_col, state->row, state->row + fontRows() - 1); +// } +// // Restore display width. +// m_displayWidth = save; + +// if (state->nQueue == 1 && *state->queue[0] == 0) { +// state->nQueue = 0; +// return 0; +// } +// if (state->col > state->bgnCol) { +// state->col--; +// } else { +// state->skip++; +// if (state->skip >= charSpacing(*state->queue[0])) { +// state->skip = 0; +// state->queue[0]++; +// if (*state->queue[0] == 0 && state->nQueue > 1) { +// state->nQueue--; +// for (uint8_t i = 0; i < state->nQueue; i++) { +// state->queue[i] = state->queue[i + 1]; +// } +// } +// } +// } +// return state->nQueue; +// } +//------------------------------------------------------------------------------ +size_t SSD1306Ascii::write(uint8_t ch) { + if (!m_font) { + return 0; + } + uint8_t w = readFontByte(m_font + FONT_WIDTH); + uint8_t h = readFontByte(m_font + FONT_HEIGHT); + uint8_t nr = (h + 7)/8; + uint8_t first = readFontByte(m_font + FONT_FIRST_CHAR); + uint8_t count = readFontByte(m_font + FONT_CHAR_COUNT); + const uint8_t* base = m_font + FONT_WIDTH_TABLE; + + if (ch < first || ch >= (first + count)) { + if (ch == '\r') { + setCol(0); + return 1; + } + if (ch == '\n') { + setCol(0); + uint8_t fr = m_magFactor*nr; +#if INCLUDE_SCROLLING + uint8_t dr = displayRows(); + uint8_t tmpRow = m_row + fr; + int8_t delta = tmpRow + fr - dr; + if (m_scrollMode == SCROLL_MODE_OFF || delta <= 0) { + setRow(tmpRow); + } else { + m_pageOffset = (m_pageOffset + delta) & 7; + m_row = dr - fr; + // Cursor will be positioned by clearToEOL. + clearToEOL(); + if (m_scrollMode == SCROLL_MODE_AUTO) { + setStartLine(8*m_pageOffset); + } + } +#else // INCLUDE_SCROLLING + setRow(m_row + fr); +#endif // INCLUDE_SCROLLING + return 1; + } + return 0; + } + ch -= first; + uint8_t s = letterSpacing(); + uint8_t thieleShift = 0; + if (fontSize() < 2) { + // Fixed width font. + base += nr*w*ch; + } else { + if (h & 7) { + thieleShift = 8 - (h & 7); + } + uint16_t index = 0; + for (uint8_t i = 0; i < ch; i++) { + index += readFontByte(base + i); + } + w = readFontByte(base + ch); + base += nr*index + count; + } + uint8_t scol = m_col; + uint8_t srow = m_row; + uint8_t skip = m_skip; + for (uint8_t r = 0; r < nr; r++) { + for (uint8_t m = 0; m < m_magFactor; m++) { + skipColumns(skip); + if (r || m) { + setCursor(scol, m_row + 1); + } + for (uint8_t c = 0; c < w; c++) { + uint8_t b = readFontByte(base + c + r*w); + if (thieleShift && (r + 1) == nr) { + b >>= thieleShift; + } + if (m_magFactor == 2) { + b = m ? b >> 4 : b & 0XF; + b = readFontByte(scaledNibble + b); + ssd1306WriteRamBuf(b); + } + ssd1306WriteRamBuf(b); + } + for (uint8_t i = 0; i < s; i++) { + ssd1306WriteRamBuf(0); + } + } + } + setRow(srow); + return 1; +} diff --git a/SSD1306/SSD1306Ascii.h b/SSD1306/SSD1306Ascii.h new file mode 100644 index 0000000..9bf22b9 --- /dev/null +++ b/SSD1306/SSD1306Ascii.h @@ -0,0 +1,477 @@ +/* Arduino SSD1306Ascii Library + * Copyright (C) 2015 by William Greiman + * + * This file is part of the Arduino SSD1306Ascii Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Arduino SSD1306Ascii Library. If not, see + * . + */ +/** + * @file SSD1306Ascii.h + * @brief Base class for ssd1306 displays. + */ +#ifndef SSD1306Ascii_h +#define SSD1306Ascii_h +#include "Arduino.h" +#include "SSD1306init.h" +#include "fonts/allFonts.h" +//------------------------------------------------------------------------------ +/** SSD1306Ascii version */ +#define SDD1306_ASCII_VERSION 1.3.0 +//------------------------------------------------------------------------------ +// Configuration options. +/** Set Scrolling mode for newline. + * + * If INCLUDE_SCROLLING is defined to be zero, newline will not scroll + * the display and code for scrolling will not be included. This option + * will save some code space and three bytes of RAM. + * + * If INCLUDE_SCROLLING is nonzero, the scroll feature will included. + */ +#define INCLUDE_SCROLLING 1 + +/** Initial scroll mode, SCROLL_MODE_OFF, + SCROLL_MODE_AUTO, or SCROLL_MODE_APP. */ +#define INITIAL_SCROLL_MODE SCROLL_MODE_OFF + +/** Dimension of TickerState pointer queue */ +#define TICKER_QUEUE_DIM 6 + +/** Use larger faster I2C code. */ +#define OPTIMIZE_I2C 1 + +/** If MULTIPLE_I2C_PORTS is nonzero, + define a constructor with port selection. */ +#ifdef __AVR__ +// Save memory on AVR. Set nonzero to use alternate I2C or software I2c on AVR. +#define MULTIPLE_I2C_PORTS 0 +#else // __AVR__ +#define MULTIPLE_I2C_PORTS 1 +#endif // __AVR__ + +/** AvrI2c uses 400 kHz fast mode if AVRI2C_FASTMODE is nonzero else 100 kHz. */ +#define AVRI2C_FASTMODE 1 +//------------------------------------------------------------------------------ +// Values for setScrolMode(uint8_t mode) +/** Newline will not scroll the display or RAM window. */ +#define SCROLL_MODE_OFF 0 +/** Newline will scroll both the display and RAM windows. */ +#define SCROLL_MODE_AUTO 1 +/** Newline scrolls the RAM window. The app scrolls the display window. */ +#define SCROLL_MODE_APP 2 +//------------------------------------------------------------------------------ +// Values for writeDisplay() mode parameter. +/** Write to Command register. */ +#define SSD1306_MODE_CMD 0 +/** Write one byte to display RAM. */ +#define SSD1306_MODE_RAM 1 +/** Write to display RAM with possible buffering. */ +#define SSD1306_MODE_RAM_BUF 2 +//------------------------------------------------------------------------------ +/** + * @brief Reset the display controller. + * + * @param[in] rst Reset pin number. + */ +inline void oledReset(uint8_t rst) { + pinMode(rst, OUTPUT); + digitalWrite(rst, LOW); + delay(10); + digitalWrite(rst, HIGH); + delay(10); +} +//------------------------------------------------------------------------------ +/** + * @struct TickerState + * @brief ticker status + */ +struct TickerState { + const char* queue[TICKER_QUEUE_DIM]; ///< Queue of text pointers. + uint8_t nQueue = 0; ///< Count of pointers in queue. + const uint8_t* font = nullptr; ///< Font for ticker. + bool mag2X; ///< Use mag2X if true. + uint8_t row; ///< Row for ticker + uint8_t bgnCol; ///< Begin column of ticker. + uint8_t endCol; ///< End column of ticker. + bool init; ///< clear and initialize display area if true. + uint8_t col; ///< Column for start of displayed text. + uint8_t skip; ///< Number of pixels to skip in first character. + /// @return Count of free queue slots. + uint8_t queueFree() {return TICKER_QUEUE_DIM - nQueue;} + /// @return Count of used queue slots. + uint8_t queueUsed() {return nQueue;} +}; +//------------------------------------------------------------------------------ +/** + * @class SSD1306Ascii + * @brief SSD1306 base class + */ +class SSD1306Ascii : public Print { + public: + using Print::write; + SSD1306Ascii() {} +#if INCLUDE_SCROLLING +//------------------------------------------------------------------------------ + /** + * @return the RAM page for top of the RAM window. + */ + uint8_t pageOffset() const {return m_pageOffset;} + /** + * @return the display line for pageOffset. + */ + uint8_t pageOffsetLine() const {return 8*m_pageOffset;} + /** + * @brief Scroll the Display window. + * + * @param[in] lines Number of lines to scroll the window. + */ + void scrollDisplay(int8_t lines) {setStartLine(m_startLine + lines);} + /** + * @brief Scroll the RAM window. + * + * @param[in] rows Number of rows to scroll the window. + */ + void scrollMemory(int8_t rows) {setPageOffset(m_pageOffset + rows);} + /** + * @return true if the first display line is equal to the + * start of the RAM window. + */ + bool scrollIsSynced() const {return startLine() == pageOffsetLine();} + /** + * @brief Set page offset. + * + * @param[in] page the RAM page for start of the RAM window + */ + void setPageOffset(uint8_t page); + /** + * @brief Enable or disable scroll mode. Deprecated use setScrollMode(). + * + * @param[in] enable true enable scroll on newline false disable scroll. + */ + void setScroll(bool enable) __attribute__((deprecated("use setScrollMode"))) { + setScrollMode(enable ? SCROLL_MODE_AUTO : SCROLL_MODE_OFF); + } + /** + * @brief Set scroll mode. + * + * @param[in] mode One of the following. + * + * SCROLL_MODE_OFF - newline will not scroll the display or RAM window. + * + * SCROLL_MODE_AUTO - newline will scroll both the display and RAM windows. + * + * SCROLL_MODE_APP - newline scrolls the RAM window. + * The app scrolls the display window. + */ + void setScrollMode(uint8_t mode) {m_scrollMode = mode;} + /** + * @brief Set the display start line register. + * + * @param[in] line RAM line to be mapped to first display line. + */ + void setStartLine(uint8_t line); + /** + * @return the display startline. + */ + uint8_t startLine() const {return m_startLine;} +#endif // INCLUDE_SCROLLING + //---------------------------------------------------------------------------- + /** + * @brief Determine the spacing of a character. Spacing is width + space. + * + * @param[in] c Character code. + * @return Spacing of the character in pixels. + */ + uint8_t charSpacing(uint8_t c) {return charWidth(c) + letterSpacing();} + /** + * @brief Determine the width of a character. + * + * @param[in] c Character code. + * @return Width of the character in pixels. + */ + uint8_t charWidth(uint8_t c) const; + /** + * @brief Clear the display and set the cursor to (0, 0). + */ + void clear(); + /** + * @brief Clear a region of the display. + * + * @param[in] c0 Starting column. + * @param[in] c1 Ending column. + * @param[in] r0 Starting row; + * @param[in] r1 Ending row; + * @note The final cursor position will be (c0, r0). + */ + void clear(uint8_t c0, uint8_t c1, uint8_t r0, uint8_t r1); + /** + * @brief Clear a field of n fieldWidth() characters. + * + * @param[in] col Field start column. + * + * @param[in] row Field start row. + * + * @param[in] n Number of characters in the field. + * + */ + void clearField(uint8_t col, uint8_t row, uint8_t n); + /** + * @brief Clear the display to the end of the current line. + * @note The number of rows cleared will be determined by the height + * of the current font. + * @note The cursor will be returned to the original position. + */ + void clearToEOL(); + /** + * @return The current column in pixels. + */ + uint8_t col() const {return m_col;} + /** + * @return The display hight in pixels. + */ + uint8_t displayHeight() const {return m_displayHeight;} + /** + * @brief Set display to normal or 180 degree remap mode. + * + * @param[in] mode true for normal mode, false for remap mode. + * + * @note Adafruit and many ebay displays use remap mode. + * Use normal mode to rotate these displays 180 degrees. + */ + void displayRemap(bool mode); + /** + * @return The display height in rows with eight pixels to a row. + */ + uint8_t displayRows() const {return m_displayHeight/8;} + /** + * @return The display width in pixels. + */ + uint8_t displayWidth() const {return m_displayWidth;} + /** + * @brief Width of a field in pixels. + * + * @param[in] n Number of characters in the field. + * + * @return Width of the field. + */ + size_t fieldWidth(uint8_t n); + /** + * @return The current font pointer. + */ + const uint8_t* font() const {return m_font;} + /** + * @return The count of characters in a font. + */ + uint8_t fontCharCount() const; + /** + * @return The first character in a font. + */ + char fontFirstChar() const; + /** + * @return The current font height in pixels. + */ + uint8_t fontHeight() const; + /** + * @return The number of eight pixel rows required to display a character + * in the current font. + */ + uint8_t fontRows() const; + /** + * @return The maximum width of characters in the current font. + */ + uint8_t fontWidth() const; + /** + * @brief Set the cursor position to (0, 0). + */ + void home() {setCursor(0, 0);} + /** + * @brief Initialize the display controller. + * + * @param[in] dev A display initialization structure. + */ + void init(const DevType* dev); + /** + * @brief Set pixel mode for for entire display. + * + * @param[in] invert Inverted display if true or normal display if false. + */ + void invertDisplay(bool invert); + /** + * @return invert mode. + */ + bool invertMode() const {return !!m_invertMask;} + /** + * @brief Set invert mode for write/print. + * + * @param[in] mode Invert pixels if true and use normal mode if false. + */ + void setInvertMode(bool mode) {m_invertMask = mode ? 0XFF : 0;} + /** + * @return letter-spacing in pixels with magnification factor. + */ + uint8_t letterSpacing() const {return m_magFactor*m_letterSpacing;} + /** + * @return The character magnification factor. + */ + uint8_t magFactor() const {return m_magFactor;} + /** + * @return the current row number with eight pixels to a row. + */ + uint8_t row() const {return m_row;} + /** + * @brief Set the character magnification factor to one. + */ + void set1X() {m_magFactor = 1;} + /** + * @brief Set the character magnification factor to two. + */ + void set2X() {m_magFactor = 2;} + /** + * @brief Set the current column number. + * + * @param[in] col The desired column number in pixels. + */ + void setCol(uint8_t col); + /** + * @brief Set the display contrast. + * + * @param[in] value The contrast level in th range 0 to 255. + */ + void setContrast(uint8_t value); + /** + * @brief Set the cursor position. + * + * @param[in] col The column number in pixels. + * @param[in] row the row number in eight pixel rows. + */ + void setCursor(uint8_t col, uint8_t row); + /** + * @brief Set the current font. + * + * @param[in] font Pointer to a font table. + */ + void setFont(const uint8_t* font); + /** + * @brief Set letter-spacing. setFont() will restore default letter-spacing. + * + * @param[in] pixels letter-spacing in pixels before magnification. + */ + void setLetterSpacing(uint8_t pixels) {m_letterSpacing = pixels;} + /** + * @brief Set the current row number. + * + * @param[in] row the row number in eight pixel rows. + */ + void setRow(uint8_t row); + /** + * @brief Write a command byte to the display controller. + * + * @param[in] c The command byte. + * @note The byte will immediately be sent to the controller. + */ + void ssd1306WriteCmd(uint8_t c) {writeDisplay(c, SSD1306_MODE_CMD);} + /** + * @brief Write a byte to RAM in the display controller. + * + * @param[in] c The data byte. + * @note The byte will immediately be sent to the controller. + */ + void ssd1306WriteRam(uint8_t c); + /** + * @brief Write a byte to RAM in the display controller. + * + * @param[in] c The data byte. + * @note The byte may be buffered until a call to ssd1306WriteCmd + * or ssd1306WriteRam. + */ + void ssd1306WriteRamBuf(uint8_t c); + /** + * @brief Skip leading pixels writing characters to display display RAM. + * + * @param[in] n Number of pixels to skip. + */ + void skipColumns(uint8_t n) {m_skip = n;} + /** + * @brief Character width. + * + * @param[in] str The pointer to string. + * @return the width of the string in pixels. + */ + size_t strWidth(const char* str) const; + // /** + // * @brief Initialize TickerState struct and clear ticker field. + // * + // * @param[in,out] state Ticker state. + // * @param[in] font to be displayed. + // * @param[in] row Row for ticker. + // * @param[in] mag2X set magFactor to two if true. + // * @param[in] bgnCol First column of ticker. Default is zero. + // * @param[in] endCol Last column of ticker. Default is last column of display. + // */ + // void tickerInit(TickerState* state, const uint8_t* font, uint8_t row, + // bool mag2X = false, uint8_t bgnCol = 0, uint8_t endCol = 255); + // /** + // * @brief Add text pointer to display queue. + // * + // * @param[in,out] state Ticker state. + // * @param[in] str Pointer to String object. Clear queue if nullptr. + // * @return false if queue is full else true. + // */ + // bool tickerText(TickerState* state, const String &str) { + // return tickerText(state, str ? str.c_str() : nullptr); + // } + // /** + // * @brief Add text pointer to display queue. + // * + // * @param[in,out] state Ticker state. + // * @param[in] text Pointer to C string. Clear queue if nullptr. + // * @return false if queue is full else true. + // */ + // bool tickerText(TickerState* state, const char* text); + // /** + // * @brief Advance ticker by one pixel. + // * + // * @param[in,out] state Ticker state. + // * + // * @return Number of entries in text pointer queue. + // */ + // int8_t tickerTick(TickerState* state); + /** + * @brief Display a character. + * + * @param[in] c The character to display. + * @return one for success else zero. + */ + size_t write(uint8_t c); + + protected: + uint16_t fontSize() const; + virtual void writeDisplay(uint8_t b, uint8_t mode) = 0; + uint8_t m_col; // Cursor column. + uint8_t m_row; // Cursor RAM row. + uint8_t m_displayWidth; // Display width. + uint8_t m_displayHeight; // Display height. + uint8_t m_colOffset; // Column offset RAM to SEG. + uint8_t m_letterSpacing; // Letter-spacing in pixels. +#if INCLUDE_SCROLLING + uint8_t m_startLine; // Top line of display + uint8_t m_pageOffset; // Top page of RAM window. + uint8_t m_scrollMode = INITIAL_SCROLL_MODE; // Scroll mode for newline. +#endif // INCLUDE_SCROLLING + uint8_t m_skip = 0; + const uint8_t* m_font = nullptr; // Current font. + uint8_t m_invertMask = 0; // font invert mask + uint8_t m_magFactor = 1; // Magnification factor. +}; +#endif // SSD1306Ascii_h diff --git a/SSD1306/SSD1306AsciiWire.h b/SSD1306/SSD1306AsciiWire.h new file mode 100644 index 0000000..cdc287b --- /dev/null +++ b/SSD1306/SSD1306AsciiWire.h @@ -0,0 +1,111 @@ +/* Arduino SSD1306Ascii Library + * Copyright (C) 2015 by William Greiman + * + * This file is part of the Arduino SSD1306Ascii Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Arduino SSD1306Ascii Library. If not, see + * . + */ +/** + * @file SSD1306AsciiWire.h + * @brief Class for I2C displays using Wire. + */ +#ifndef SSD1306AsciiWire_h +#define SSD1306AsciiWire_h +#include +#include "SSD1306Ascii.h" +/** + * @class SSD1306AsciiWire + * @brief Class for I2C displays using Wire. + */ +class SSD1306AsciiWire : public SSD1306Ascii { + public: +#if MULTIPLE_I2C_PORTS + /** + * @brief Initialize object on specific I2C bus. + * + * @param[in] bus The I2C bus to be used. + */ + explicit SSD1306AsciiWire(decltype(Wire) &bus = Wire) : m_oledWire(bus) {} +#else // MULTIPLE_I2C_PORTS +#define m_oledWire Wire +#endif // MULTIPLE_I2C_PORTS + /** + * @brief Initialize the display controller. + * + * @param[in] dev A device initialization structure. + * @param[in] i2cAddr The I2C address of the display controller. + */ + void begin(const DevType* dev, uint8_t i2cAddr) { +#if OPTIMIZE_I2C + m_nData = 0; +#endif // OPTIMIZE_I2C + m_i2cAddr = i2cAddr; + init(dev); + } + /** + * @brief Initialize the display controller. + * + * @param[in] dev A device initialization structure. + * @param[in] i2cAddr The I2C address of the display controller. + * @param[in] rst The display controller reset pin. + */ + void begin(const DevType* dev, uint8_t i2cAddr, uint8_t rst) { + oledReset(rst); + begin(dev, i2cAddr); + } + /** + * @brief Set the I2C clock rate to 400 kHz. + * Deprecated use Wire.setClock(400000L) + */ + void set400kHz() __attribute__((deprecated("use Wire.setClock(400000L)"))) { + m_oledWire.setClock(400000L); + } + + protected: + void writeDisplay(uint8_t b, uint8_t mode) { +#if OPTIMIZE_I2C + if (m_nData > 16 || (m_nData && mode == SSD1306_MODE_CMD)) { + m_oledWire.endTransmission(); + m_nData = 0; + } + if (m_nData == 0) { + m_oledWire.beginTransmission(m_i2cAddr); + m_oledWire.write(mode == SSD1306_MODE_CMD ? 0X00 : 0X40); + } + m_oledWire.write(b); + if (mode == SSD1306_MODE_RAM_BUF) { + m_nData++; + } else { + m_oledWire.endTransmission(); + m_nData = 0; + } +#else // OPTIMIZE_I2C + m_oledWire.beginTransmission(m_i2cAddr); + m_oledWire.write(mode == SSD1306_MODE_CMD ? 0X00: 0X40); + m_oledWire.write(b); + m_oledWire.endTransmission(); +#endif // OPTIMIZE_I2C + } + + protected: +#if MULTIPLE_I2C_PORTS + decltype(Wire)& m_oledWire; +#endif // MULTIPLE_I2C_PORTS + uint8_t m_i2cAddr; +#if OPTIMIZE_I2C + uint8_t m_nData; +#endif // OPTIMIZE_I2C +}; +#endif // SSD1306AsciiWire_h diff --git a/SSD1306/SSD1306init.h b/SSD1306/SSD1306init.h new file mode 100644 index 0000000..90614fd --- /dev/null +++ b/SSD1306/SSD1306init.h @@ -0,0 +1,266 @@ +/* Arduino SSD1306Ascii Library + * Copyright (C) 2015 by William Greiman + * + * This file is part of the Arduino SSD1306Ascii Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Arduino SSD1306Ascii Library. If not, see + * . + */ +/** + * @file SSD1306init.h + * @brief Display controller initialization commands. + */ +#ifndef SSD1306init_h +#define SSD1306init_h +//------------------------------------------------------------------------------ +#ifndef __AVR__ +/** Handle AVR flash addressing. */ +#define MEM_TYPE +#else // __AVR__ +#define MEM_TYPE __attribute__ ((progmem)) +#endif // __AVR__ +//------------------------------------------------------------------------------ +/** Set Lower Column Start Address for Page Addressing Mode. */ +#define SSD1306_SETLOWCOLUMN 0x00 +/** Set Higher Column Start Address for Page Addressing Mode. */ +#define SSD1306_SETHIGHCOLUMN 0x10 +/** Set Memory Addressing Mode. */ +#define SSD1306_MEMORYMODE 0x20 +/** Set display RAM display start line register from 0 - 63. */ +#define SSD1306_SETSTARTLINE 0x40 +/** Set Display Contrast to one of 256 steps. */ +#define SSD1306_SETCONTRAST 0x81 +/** Enable or disable charge pump. Follow with 0X14 enable, 0X10 disable. */ +#define SSD1306_CHARGEPUMP 0x8D +/** Set Segment Re-map between data column and the segment driver. */ +#define SSD1306_SEGREMAP 0xA0 +/** Resume display from GRAM content. */ +#define SSD1306_DISPLAYALLON_RESUME 0xA4 +/** Force display on regardless of GRAM content. */ +#define SSD1306_DISPLAYALLON 0xA5 +/** Set Normal Display. */ +#define SSD1306_NORMALDISPLAY 0xA6 +/** Set Inverse Display. */ +#define SSD1306_INVERTDISPLAY 0xA7 +/** Set Multiplex Ratio from 16 to 63. */ +#define SSD1306_SETMULTIPLEX 0xA8 +/** Set Display off. */ +#define SSD1306_DISPLAYOFF 0xAE +/** Set Display on. */ +#define SSD1306_DISPLAYON 0xAF +/**Set GDDRAM Page Start Address. */ +#define SSD1306_SETSTARTPAGE 0XB0 +/** Set COM output scan direction normal. */ +#define SSD1306_COMSCANINC 0xC0 +/** Set COM output scan direction reversed. */ +#define SSD1306_COMSCANDEC 0xC8 +/** Set Display Offset. */ +#define SSD1306_SETDISPLAYOFFSET 0xD3 +/** Sets COM signals pin configuration to match the OLED panel layout. */ +#define SSD1306_SETCOMPINS 0xDA +/** This command adjusts the VCOMH regulator output. */ +#define SSD1306_SETVCOMDETECT 0xDB +/** Set Display Clock Divide Ratio/ Oscillator Frequency. */ +#define SSD1306_SETDISPLAYCLOCKDIV 0xD5 +/** Set Pre-charge Period */ +#define SSD1306_SETPRECHARGE 0xD9 +/** Deactivate scroll */ +#define SSD1306_DEACTIVATE_SCROLL 0x2E +/** No Operation Command. */ +#define SSD1306_NOP 0XE3 +//------------------------------------------------------------------------------ +/** Set Pump voltage value: (30H~33H) 6.4, 7.4, 8.0 (POR), 9.0. */ +#define SH1106_SET_PUMP_VOLTAGE 0X30 +/** First byte of set charge pump mode */ +#define SH1106_SET_PUMP_MODE 0XAD +/** Second byte charge pump on. */ +#define SH1106_PUMP_ON 0X8B +/** Second byte charge pump off. */ +#define SH1106_PUMP_OFF 0X8A +//------------------------------------------------------------------------------ +/** + * @struct DevType + * @brief Device initialization structure. + */ +struct DevType { + /** + * Pointer to initialization command bytes. + */ + const uint8_t* initcmds; + /** + * Number of initialization bytes. + */ + const uint8_t initSize; + /** + * Width of the diaplay in pixels. + */ + const uint8_t lcdWidth; + /** + * Height of the display in pixels. + */ + const uint8_t lcdHeight; + /** + * Column offset RAM to display. Used to pick start column of SH1106. + */ + const uint8_t colOffset; +}; +//------------------------------------------------------------------------------ +/** Initialization commands for a 64x48 Micro OLED display (by r7) */ +static const uint8_t MEM_TYPE MicroOLED64x48init[] = { + // Init sequence for 64x48 Micro OLED module + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 + SSD1306_SETMULTIPLEX, 0x2F, // + SSD1306_SETDISPLAYOFFSET, 0x0, // no offset + SSD1306_SETSTARTLINE | 0x0, // line #0 + SSD1306_CHARGEPUMP, 0x14, // internal vcc + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYALLON_RESUME, + SSD1306_SEGREMAP | 0x1, // column 127 mapped to SEG0 + SSD1306_COMSCANDEC, // column scan direction reversed + SSD1306_SETCOMPINS, 0x12, // 0x12 if height > 32 else 0x02 + SSD1306_SETCONTRAST, 0x7F, // contrast level 127 + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) + SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level + SSD1306_DISPLAYON +}; +/** Initialize a 64x48 Micro OLED display. */ +static const DevType MEM_TYPE MicroOLED64x48 = { + MicroOLED64x48init, + sizeof(MicroOLED64x48init), + 64, + 48, + 32 +}; +//------------------------------------------------------------------------------ +// this section is based on +// https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_ssd1306_96x16.c +/** Initialization commands for a 96x16 SSD1306 oled display. */ +static const uint8_t MEM_TYPE SSD1306_96x16init[] = { + // Init sequence for Generic 96x16 OLED module + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // clock divide ratio and osc frequency + SSD1306_SETMULTIPLEX, 0x0F, // multiplex ratio + SSD1306_SETDISPLAYOFFSET, 0x0, // display offset zero + SSD1306_SETSTARTLINE | 0x0, // set display start line to 0 + SSD1306_CHARGEPUMP, 0x14, // charge pump setting enable + SSD1306_MEMORYMODE, 0x00, // page addressing mode + SSD1306_SEGREMAP | 0xA1, // segment remap + SSD1306_COMSCANDEC, // scan dir reverse + SSD1306_SETCOMPINS, 0x02, // com pin HW config + SSD1306_SETCONTRAST, 0xAF, // set contrast level 0xaf + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period 0x0f1 + SSD1306_SETVCOMDETECT, 0x20, // vcomh deselect level + SSD1306_DEACTIVATE_SCROLL, // Deactivate scroll + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; +/** Initialize a 96x16 SSD1306 oled display. */ +static const DevType MEM_TYPE SSD1306_96x16 = { + SSD1306_96x16init, + sizeof(SSD1306_96x16init), + 96, + 16, + 0 +}; +//------------------------------------------------------------------------------ +// this section is based on https://github.com/adafruit/Adafruit_SSD1306 +/** Initialization commands for a 128x32 SSD1306 oled display. */ +static const uint8_t MEM_TYPE Adafruit128x32init[] = { + // Init sequence for Adafruit 128x32 OLED module + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 + SSD1306_SETMULTIPLEX, 0x1F, // ratio 32 + SSD1306_SETDISPLAYOFFSET, 0x0, // no offset + SSD1306_SETSTARTLINE | 0x0, // line #0 + SSD1306_CHARGEPUMP, 0x14, // internal vcc + SSD1306_MEMORYMODE, 0x02, // page mode + SSD1306_SEGREMAP | 0x1, // column 127 mapped to SEG0 + SSD1306_COMSCANDEC, // column scan direction reversed + SSD1306_SETCOMPINS, 0x02, // sequential COM pins, disable remap + SSD1306_SETCONTRAST, 0x7F, // contrast level 127 + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) + SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; +/** Initialize a 128x32 SSD1306 oled display. */ +static const DevType MEM_TYPE Adafruit128x32 = { + Adafruit128x32init, + sizeof(Adafruit128x32init), + 128, + 32, + 0 +}; +//------------------------------------------------------------------------------ +// This section is based on https://github.com/adafruit/Adafruit_SSD1306 +/** Initialization commands for a 128x64 SSD1306 oled display. */ +static const uint8_t MEM_TYPE Adafruit128x64init[] = { + // Init sequence for Adafruit 128x64 OLED module + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80 + SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 + SSD1306_SETDISPLAYOFFSET, 0x0, // no offset + SSD1306_SETSTARTLINE | 0x0, // line #0 + SSD1306_CHARGEPUMP, 0x14, // internal vcc + SSD1306_MEMORYMODE, 0x02, // page mode + SSD1306_SEGREMAP | 0x1, // column 127 mapped to SEG0 + SSD1306_COMSCANDEC, // column scan direction reversed + SSD1306_SETCOMPINS, 0x12, // alt COM pins, disable remap + SSD1306_SETCONTRAST, 0x7F, // contrast level 127 + SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15) + SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; +/** Initialize a 128x64 oled display. */ +static const DevType MEM_TYPE Adafruit128x64 = { + Adafruit128x64init, + sizeof(Adafruit128x64init), + 128, + 64, + 0 +}; +//------------------------------------------------------------------------------ +// This section is based on https://github.com/stanleyhuangyc/MultiLCD +/** Initialization commands for a 128x64 SH1106 oled display. */ +static const uint8_t MEM_TYPE SH1106_128x64init[] = { + SSD1306_DISPLAYOFF, + SSD1306_SETSTARTPAGE | 0X0, // set page address + SSD1306_SETCONTRAST, 0x80, // 128 + SSD1306_SEGREMAP | 0X1, // set segment remap + SSD1306_NORMALDISPLAY, // normal / reverse + SSD1306_SETMULTIPLEX, 0x3F, // ratio 64 + SH1106_SET_PUMP_MODE, SH1106_PUMP_ON, // set charge pump enable + SH1106_SET_PUMP_VOLTAGE | 0X2, // 8.0 volts + SSD1306_COMSCANDEC, // Com scan direction + SSD1306_SETDISPLAYOFFSET, 0X00, // set display offset + SSD1306_SETDISPLAYCLOCKDIV, 0X80, // set osc division + SSD1306_SETPRECHARGE, 0X1F, // set pre-charge period + SSD1306_SETCOMPINS, 0X12, // set COM pins + SSD1306_SETVCOMDETECT, 0x40, // set vcomh + SSD1306_DISPLAYON +}; +/** Initialize a 128x64 oled SH1106 display. */ +static const DevType MEM_TYPE SH1106_128x64 = { + SH1106_128x64init, + sizeof(SH1106_128x64init), + 128, + 64, + 2 // SH1106 is a 132x64 controller. Use middle 128 columns. +}; +#endif // SSD1306init_h diff --git a/SSD1306/fonts/System5x7.h b/SSD1306/fonts/System5x7.h new file mode 100644 index 0000000..bb14510 --- /dev/null +++ b/SSD1306/fonts/System5x7.h @@ -0,0 +1,148 @@ +/* + * + * System5x7 + * + * + * File Name : System5x7.h + * Date : 28 Oct 2008 + * Font size in bytes : 470 + * Font width : 5 + * Font height : 7 + * Font first char : 32 + * Font last char : 127 + * Font used chars : 94 + * + * The font data are defined as + * + * struct _FONT_ { + * uint16_t font_Size_in_Bytes_over_all_included_Size_it_self; + * uint8_t font_Width_in_Pixel_for_fixed_drawing; + * uint8_t font_Height_in_Pixel_for_all_characters; + * unit8_t font_First_Char; + * uint8_t font_Char_Count; + * + * uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1]; + * // for each character the separate width in pixels, + * // characters < 128 have an implicit virtual right empty row + * + * uint8_t font_data[]; + * // bit field of all characters + */ + +#ifndef SYSTEM5x7_H +#define SYSTEM5x7_H + +#define SYSTEM5x7_WIDTH 5 +#define SYSTEM5x7_HEIGHT 7 + +GLCDFONTDECL(System5x7) = { + 0x0, 0x0, // size of zero indicates fixed width font, + 0x05, // width + 0x07, // height + 0x20, // first char + 0x61, // char count + + // Fixed width; char width table not used !!!! + + // font data + 0x00, 0x00, 0x00, 0x00, 0x00,// (space) + 0x00, 0x00, 0x5F, 0x00, 0x00,// ! + 0x00, 0x07, 0x00, 0x07, 0x00,// " + 0x14, 0x7F, 0x14, 0x7F, 0x14,// # + 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $ + 0x23, 0x13, 0x08, 0x64, 0x62,// % + 0x36, 0x49, 0x55, 0x22, 0x50,// & + 0x00, 0x05, 0x03, 0x00, 0x00,// ' + 0x00, 0x1C, 0x22, 0x41, 0x00,// ( + 0x00, 0x41, 0x22, 0x1C, 0x00,// ) + 0x08, 0x2A, 0x1C, 0x2A, 0x08,// * + 0x08, 0x08, 0x3E, 0x08, 0x08,// + + 0x00, 0x50, 0x30, 0x00, 0x00,// , + 0x08, 0x08, 0x08, 0x08, 0x08,// - + 0x00, 0x60, 0x60, 0x00, 0x00,// . + 0x20, 0x10, 0x08, 0x04, 0x02,// / + 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 + 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 + 0x42, 0x61, 0x51, 0x49, 0x46,// 2 + 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 + 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 + 0x27, 0x45, 0x45, 0x45, 0x39,// 5 + 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 + 0x01, 0x71, 0x09, 0x05, 0x03,// 7 + 0x36, 0x49, 0x49, 0x49, 0x36,// 8 + 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 + 0x00, 0x36, 0x36, 0x00, 0x00,// : + 0x00, 0x56, 0x36, 0x00, 0x00,// ; + 0x00, 0x08, 0x14, 0x22, 0x41,// < + 0x14, 0x14, 0x14, 0x14, 0x14,// = + 0x41, 0x22, 0x14, 0x08, 0x00,// > + 0x02, 0x01, 0x51, 0x09, 0x06,// ? + 0x32, 0x49, 0x79, 0x41, 0x3E,// @ + 0x7E, 0x11, 0x11, 0x11, 0x7E,// A + 0x7F, 0x49, 0x49, 0x49, 0x36,// B + 0x3E, 0x41, 0x41, 0x41, 0x22,// C + 0x7F, 0x41, 0x41, 0x22, 0x1C,// D + 0x7F, 0x49, 0x49, 0x49, 0x41,// E + 0x7F, 0x09, 0x09, 0x01, 0x01,// F + 0x3E, 0x41, 0x41, 0x51, 0x32,// G + 0x7F, 0x08, 0x08, 0x08, 0x7F,// H + 0x00, 0x41, 0x7F, 0x41, 0x00,// I + 0x20, 0x40, 0x41, 0x3F, 0x01,// J + 0x7F, 0x08, 0x14, 0x22, 0x41,// K + 0x7F, 0x40, 0x40, 0x40, 0x40,// L + 0x7F, 0x02, 0x04, 0x02, 0x7F,// M + 0x7F, 0x04, 0x08, 0x10, 0x7F,// N + 0x3E, 0x41, 0x41, 0x41, 0x3E,// O + 0x7F, 0x09, 0x09, 0x09, 0x06,// P + 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q + 0x7F, 0x09, 0x19, 0x29, 0x46,// R + 0x46, 0x49, 0x49, 0x49, 0x31,// S + 0x01, 0x01, 0x7F, 0x01, 0x01,// T + 0x3F, 0x40, 0x40, 0x40, 0x3F,// U + 0x1F, 0x20, 0x40, 0x20, 0x1F,// V + 0x7F, 0x20, 0x18, 0x20, 0x7F,// W + 0x63, 0x14, 0x08, 0x14, 0x63,// X + 0x03, 0x04, 0x78, 0x04, 0x03,// Y + 0x61, 0x51, 0x49, 0x45, 0x43,// Z + 0x00, 0x00, 0x7F, 0x41, 0x41,// [ + 0x02, 0x04, 0x08, 0x10, 0x20,// "\" + 0x41, 0x41, 0x7F, 0x00, 0x00,// ] + 0x04, 0x02, 0x01, 0x02, 0x04,// ^ + 0x40, 0x40, 0x40, 0x40, 0x40,// _ + 0x00, 0x01, 0x02, 0x04, 0x00,// ` + 0x20, 0x54, 0x54, 0x54, 0x78,// a + 0x7F, 0x48, 0x44, 0x44, 0x38,// b + 0x38, 0x44, 0x44, 0x44, 0x20,// c + 0x38, 0x44, 0x44, 0x48, 0x7F,// d + 0x38, 0x54, 0x54, 0x54, 0x18,// e + 0x08, 0x7E, 0x09, 0x01, 0x02,// f + 0x08, 0x14, 0x54, 0x54, 0x3C,// g + 0x7F, 0x08, 0x04, 0x04, 0x78,// h + 0x00, 0x44, 0x7D, 0x40, 0x00,// i + 0x20, 0x40, 0x44, 0x3D, 0x00,// j + 0x00, 0x7F, 0x10, 0x28, 0x44,// k + 0x00, 0x41, 0x7F, 0x40, 0x00,// l + 0x7C, 0x04, 0x18, 0x04, 0x78,// m + 0x7C, 0x08, 0x04, 0x04, 0x78,// n + 0x38, 0x44, 0x44, 0x44, 0x38,// o + 0x7C, 0x14, 0x14, 0x14, 0x08,// p + 0x08, 0x14, 0x14, 0x18, 0x7C,// q + 0x7C, 0x08, 0x04, 0x04, 0x08,// r + 0x48, 0x54, 0x54, 0x54, 0x20,// s + 0x04, 0x3F, 0x44, 0x40, 0x20,// t + 0x3C, 0x40, 0x40, 0x20, 0x7C,// u + 0x1C, 0x20, 0x40, 0x20, 0x1C,// v + 0x3C, 0x40, 0x30, 0x40, 0x3C,// w + 0x44, 0x28, 0x10, 0x28, 0x44,// x + 0x0C, 0x50, 0x50, 0x50, 0x3C,// y + 0x44, 0x64, 0x54, 0x4C, 0x44,// z + 0x00, 0x08, 0x36, 0x41, 0x00,// { + 0x00, 0x00, 0x7F, 0x00, 0x00,// | + 0x00, 0x41, 0x36, 0x08, 0x00,// } + 0x08, 0x08, 0x2A, 0x1C, 0x08,// -> + 0x08, 0x1C, 0x2A, 0x08, 0x08, // <- + 0x00, 0x06, 0x09, 0x09, 0x06 // degree symbol + +}; + +#endif diff --git a/SSD1306/fonts/allFonts.h b/SSD1306/fonts/allFonts.h new file mode 100644 index 0000000..a63a647 --- /dev/null +++ b/SSD1306/fonts/allFonts.h @@ -0,0 +1,119 @@ +/* + * allFonts.h font header for GLCD library + * The fonts listed below will be available in a sketch if this file is included + * + * If you create your own fonts you can add the header to this file + * + * Note that the build environment only holds a font in Flash if its selected + * so there is no penalty to including a font file here if its not used + */ +/** + * @file allFonts.h + * @brief Font definitions. + */ +#ifndef _allFonts_h_ +#define _allFonts_h_ + +#ifdef __AVR__ +#include +/** declare a font for AVR. */ +#define GLCDFONTDECL(_n) static const uint8_t __attribute__ ((progmem))_n[] +#define readFontByte(addr) pgm_read_byte(addr) +#else // __AVR__ +/** declare a font. */ +#define GLCDFONTDECL(_n) static const uint8_t _n[] +/** Fake read from flash. */ +#define readFontByte(addr) (*(const unsigned char *)(addr)) +#endif // __AVR__ +//------------------------------------------------------------------------------ +// Font Indices +/** No longer used Big Endian length field. Now indicates font type. + * + * 00 00 (fixed width font with 1 padding pixel on right and below) + * + * 00 01 (fixed width font with no padding pixels) + */ +#define FONT_LENGTH 0 +/** Maximum character width. */ +#define FONT_WIDTH 2 +/** Font hight in pixels */ +#define FONT_HEIGHT 3 +/** Ascii value of first character */ +#define FONT_FIRST_CHAR 4 +/** count of characters in font. */ +#define FONT_CHAR_COUNT 5 +/** Offset to width table. */ +#define FONT_WIDTH_TABLE 6 +// +// FONT_LENGTH is a 16 bit Big Endian length field. +// Unfortunately, FontCreator2 screwed up the value it put in the field +// so it is pretty much meaningless. However it still is used to indicate +// some special things. +// 00 00 (fixed width font with 1 padding pixel on right and below) +// 00 01 (fixed width font with no padding pixels) +// FONT_WIDTH it the max character width. +// any other value means variable width font in FontCreator2 (thiele) +// format with pixel padding + +// #include "Adafruit5x7.h" // Font from Adafruit GFX library +// #include "font5x7.h" +// #include "lcd5x7.h" +// #include "Stang5x7.h" +// #include "X11fixed7x14.h" +// #include "X11fixed7x14B.h" +// #include "ZevvPeep8x16.h" + +#include "System5x7.h" // system font (fixed width) +// #include "SystemFont5x7.h" // backward compability System5x7 header +// #include "Iain5x7.h" // similar to system5x7 but proportional +// #include "Arial14.h" // proportional font +// #include "Arial_bold_14.h" // Bold proportional font +// #include "Corsiva_12.h" +// #include "Verdana_digits_24.h" // large proportional font contains [0-9] and : + +// #include "Callibri10.h" +// #include "Callibri11.h" +// #include "Callibri11_bold.h" +// #include "Callibri11_italic.h" +// #include "Callibri14.h" +// #include "Callibri15.h" +// #include "Cooper19.h" +// #include "Cooper21.h" +// #include "Cooper26.h" +// #include "TimesNewRoman13.h" +// #include "TimesNewRoman13_italic.h" +// #include "TimesNewRoman16.h" +// #include "TimesNewRoman16_bold.h" +// #include "TimesNewRoman16_italic.h" +// #include "Verdana12.h" +// #include "Verdana12_bold.h" +// #include "Verdana12_italic.h" +// #include "Roosewood22.h" +// #include "Roosewood26.h" + +// #include "fixednums7x15.h" // fixed width font - + , - . / [0-9] and : +// #include "fixednums8x16.h" // fixed width font - + , - . / [0-9] and : +// #include "fixednums15x31.h" // fixed width font - + , - . / [0-9] and : + +// #include "CalBlk36.h" +// #include "CalLite24.h" +// #include "lcdnums12x16.h" // font that looks like LCD digits +// #include "lcdnums14x24.h" // font that looks like LCD digits +// #include "fixed_bold10x15.h" +// #include "Wendy3x5.h" +// #include "newbasic3x5.h" + +/* + * These fonts require no-pad rendering code + */ +// #include "font8x8.h" // fixed wider font but similar to system5x7 font +// #include "cp437font8x8.h" // fixed Font from 80's IBM PC + +/* + * These fonts require UTF8 encoding support + */ + +// #include "utf8font10x16.h" // UTF8 font up to U+00FF + // http://www.fileformat.info/info/charset/UTF-8/list.htm + +#endif diff --git a/platformio.ini b/platformio.ini index 468a3b3..9df32e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ [platformio] default_envs = mega2560 - uno + ;uno src_dir = . [env] @@ -37,9 +37,6 @@ lib_deps = arduino-libraries/Ethernet SPI marcoschwartz/LiquidCrystal_I2C - Adafruit/Adafruit_BusIO - Adafruit/Adafruit_SSD1306 - Adafruit/Adafruit-GFX-Library monitor_speed = 115200 monitor_flags = --echo