diff options
-rw-r--r-- | obdlogger/MicroLCD.cpp | 3 | ||||
-rw-r--r-- | obdlogger/MicroLCD.h | 21 | ||||
-rw-r--r-- | obdlogger/README.txt | 4 | ||||
-rw-r--r-- | obdlogger/SH1106.cpp | 399 | ||||
-rw-r--r-- | obdlogger/SH1106.h | 1 | ||||
-rw-r--r-- | obdlogger/config.h | 5 | ||||
-rw-r--r-- | obdlogger/obdlogger.cbp | 2 |
7 files changed, 429 insertions, 6 deletions
diff --git a/obdlogger/MicroLCD.cpp b/obdlogger/MicroLCD.cpp index 6892099..9f3764e 100644 --- a/obdlogger/MicroLCD.cpp +++ b/obdlogger/MicroLCD.cpp @@ -292,6 +292,8 @@ void LCD_SSD1306::setCursor(byte column, byte line) size_t LCD_SSD1306::write(uint8_t c) { + uint8_t twbrbackup = TWBR; + TWBR = 18; // upgrade to 400KHz! if (c == '\n') { setCursor(0, m_row + ((m_font == FONT_SIZE_SMALL) ? 1 : 2)); return 1; @@ -383,6 +385,7 @@ size_t LCD_SSD1306::write(uint8_t c) } } #endif + TWBR = twbrbackup; return 1; } diff --git a/obdlogger/MicroLCD.h b/obdlogger/MicroLCD.h index 1206414..6e1d455 100644 --- a/obdlogger/MicroLCD.h +++ b/obdlogger/MicroLCD.h @@ -6,7 +6,7 @@ *************************************************************************/ #if !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega644P__) -#define MEMORY_SAVING +//#define MEMORY_SAVING #endif typedef enum { @@ -73,3 +73,22 @@ private: byte m_col; byte m_row; }; + +class LCD_SH1106 : public LCD_Common, public Print +{ +public: + void begin(); + void setCursor(byte column, byte line); + void draw(const PROGMEM byte* buffer, byte x, byte y, byte width, byte height); + size_t write(uint8_t c); + void clear(byte x = 0, byte y = 0, byte width = 128, byte height = 64); + void clearLine(byte line); + byte getLines() { return 21; } + byte getCols() { return 8; } +private: + void WriteCommand(unsigned char ins); + void WriteData(unsigned char dat); + void writeDigit(byte n); + byte m_col; + byte m_row; +}; diff --git a/obdlogger/README.txt b/obdlogger/README.txt index 79e7c67..217971f 100644 --- a/obdlogger/README.txt +++ b/obdlogger/README.txt @@ -2,10 +2,10 @@ This is the source code for the Arduino OBD-II data logger, which displays (on a http://obd.arduinodev.com The recorded data is stored in CSV format and the file can be illustrated into a graphic chart by a free service at: -http://obd.arduinodev.com/view.html +http://freematics.com/chart/ To compile the code with Arduino IDE, please copy all library files from the libraries directory to Arduino's libraries directory. -To open the project file (obdlogger.cbp), please download CodeBlocks Arduino Edition (http://www.arduinodev.com/codeblocks). +To open the project file (obdlogger.cbp), please download CodeBlocks Arduino Edition (http://arduinodev.com/codeblocks). The source code is distributed under GPL license. diff --git a/obdlogger/SH1106.cpp b/obdlogger/SH1106.cpp new file mode 100644 index 0000000..ee93344 --- /dev/null +++ b/obdlogger/SH1106.cpp @@ -0,0 +1,399 @@ +#include <Arduino.h> +#include <Wire.h> +#include "MicroLCD.h" + +#define I2C_ADDR 0x78 >> 1 + +void LCD_SH1106::WriteCommand(unsigned char ins) +{ + Wire.beginTransmission(I2C_ADDR);//0x78 >> 1 + Wire.write(0x00);//0x00 + Wire.write(ins); + Wire.endTransmission(); +} + +void LCD_SH1106::WriteData(unsigned char dat) +{ + Wire.beginTransmission(I2C_ADDR);//0x78 >> 1 + Wire.write(0x40);//0x40 + Wire.write(dat); + Wire.endTransmission(); +} + +void LCD_SH1106::setCursor(unsigned char x, unsigned char y) +{ + m_col = x + 2; + m_row = y; + WriteCommand(0xb0 + m_row); + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address +} + +void LCD_SH1106::clear(byte x, byte y, byte width, byte height) +{ + WriteCommand(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 + WriteCommand(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 + WriteCommand(SSD1306_SETSTARTLINE | 0x0); // line #0 + + // save I2C bitrate + uint8_t twbrbackup = TWBR; + TWBR = 18; // upgrade to 400KHz! + + height >>= 3; + width >>= 3; + y >>= 3; + for (byte i = 0; i < height; i++) { + // send a bunch of data in one xmission + WriteCommand(0xB0 + i + y);//set page address + WriteCommand((x + 2) & 0xf);//set lower column address + WriteCommand(0x10 | (x >> 4));//set higher column address + + for(byte j = 0; j < 8; j++){ + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte k = 0; k < width; k++) { + Wire.write(0); + } + Wire.endTransmission(); + } + } + + setCursor(0, 0); + TWBR = twbrbackup; +} + +size_t LCD_SH1106::write(uint8_t c) +{ + if (c == '\n') { + setCursor(0, m_row + ((m_font == FONT_SIZE_SMALL) ? 1 : 2)); + return 1; + } else if (c == '\r') { + m_col = 0; + return 1; + } + + uint8_t twbrbackup = TWBR; + TWBR = 18; // upgrade to 400KHz! +#ifndef MEMORY_SAVING + if (m_font == FONT_SIZE_SMALL) { +#endif + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + if (c > 0x20 && c < 0x7f) { + c -= 0x21; + for (byte i = 0; i < 5; i++) { + byte d = pgm_read_byte(&font5x8[c][i]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.write(0); + } else { + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 11 : 6; i > 0; i--) { + Wire.write(0); + } + } + Wire.endTransmission(); + m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 11 : 6; + if (m_col >= 128) { + m_col = 0; + m_row ++; + } +#ifndef MEMORY_SAVING + } else { + if (c > 0x20 && c < 0x7f) { + c -= 0x21; + + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = 0; i <= 14; i += 2) { + byte d = pgm_read_byte(&font8x16_terminal[c][i]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = 1; i <= 15; i += 2) { + byte d = pgm_read_byte(&font8x16_terminal[c][i]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + } else { + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 16 : 8; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 16 : 8; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + } + m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 17 : 9; + if (m_col >= 128) { + m_col = 0; + m_row += 2; + } + } +#endif + TWBR = twbrbackup; + return 1; +} + +void LCD_SH1106::writeDigit(byte n) +{ + uint8_t twbrbackup = TWBR; + TWBR = 18; // upgrade to 400KHz! + + if (m_font == FONT_SIZE_SMALL) { + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + if (n <= 9) { + n += '0' - 0x21; + for (byte i = 0; i < 5; i++) { + Wire.write(pgm_read_byte(&font5x8[n][i])); + } + Wire.write(0); + } else { + for (byte i = 0; i < 6; i++) { + Wire.write(0); + } + } + Wire.endTransmission(); + m_col += 6; + } else if (m_font == FONT_SIZE_MEDIUM) { + write(n <= 9 ? ('0' + n) : ' '); +#ifndef MEMORY_SAVING + } else if (m_font == FONT_SIZE_LARGE) { + if (n <= 9) { + byte i; + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x16[n][i]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (; i < 32; i ++) { + byte d = pgm_read_byte(&digits16x16[n][i]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + } else { + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + } + m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 30 : 16; +#endif + } else { + if (n <= 9) { + byte i; + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x24[n][i * 3]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x24[n][i * 3 + 1]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 2);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x24[n][i * 3 + 2]); + Wire.write(d); + if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + } + Wire.endTransmission(); + } else { + WriteCommand(0xB0 + m_row);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 1);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + + WriteCommand(0xB0 + m_row + 2);//set page address + WriteCommand(m_col & 0xf);//set lower column address + WriteCommand(0x10 | (m_col >> 4));//set higher column address + + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); + } + Wire.endTransmission(); + } + m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 30 : 16; + } + TWBR = twbrbackup; +} + +void LCD_SH1106::draw(const PROGMEM byte* buffer, byte x, byte y, byte width, byte height) +{ + uint8_t twbrbackup = TWBR; + TWBR = 18; // upgrade to 400KHz! + + WriteCommand(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 + WriteCommand(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 + WriteCommand(SSD1306_SETSTARTLINE | 0x0); // line #0 + + const PROGMEM byte *p = buffer; + height >>= 3; + width >>= 3; + y >>= 3; + for (byte i = 0; i < height; i++) { + // send a bunch of data in one xmission + WriteCommand(0xB0 + i + y);//set page address + WriteCommand(x & 0xf);//set lower column address + WriteCommand(0x10 | (x >> 4));//set higher column address + + for(byte j = 0; j < 8; j++){ + Wire.beginTransmission(I2C_ADDR); + Wire.write(0x40); + for (byte k = 0; k < width; k++, p++) { + Wire.write(pgm_read_byte(p)); + } + Wire.endTransmission(); + } + } + TWBR = twbrbackup; +} + +void LCD_SH1106::begin() +{ + Wire.begin(); + + WriteCommand(0xAE); /*display off*/ + + WriteCommand(0x02); /*set lower column address*/ + WriteCommand(0x10); /*set higher column address*/ + + WriteCommand(0x40); /*set display start line*/ + + WriteCommand(0xB0); /*set page address*/ + + WriteCommand(0x81); /*contract control*/ + WriteCommand(0x80); /*128*/ + + WriteCommand(0xA1); /*set segment remap*/ + + WriteCommand(0xA6); /*normal / reverse*/ + + WriteCommand(0xA8); /*multiplex ratio*/ + WriteCommand(0x3F); /*duty = 1/32*/ + + WriteCommand(0xad); /*set charge pump enable*/ + WriteCommand(0x8b); /*external VCC */ + + WriteCommand(0x30); /*0X30---0X33 set VPP 9V liangdu!!!!*/ + + WriteCommand(0xC8); /*Com scan direction*/ + + WriteCommand(0xD3); /*set display offset*/ + WriteCommand(0x00); /* 0x20 */ + + WriteCommand(0xD5); /*set osc division*/ + WriteCommand(0x80); + + WriteCommand(0xD9); /*set pre-charge period*/ + WriteCommand(0x1f); /*0x22*/ + + WriteCommand(0xDA); /*set COM pins*/ + WriteCommand(0x12); + + WriteCommand(0xdb); /*set vcomh*/ + WriteCommand(0x40); + + WriteCommand(0xAF); /*display ON*/ +} diff --git a/obdlogger/SH1106.h b/obdlogger/SH1106.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/obdlogger/SH1106.h @@ -0,0 +1 @@ + diff --git a/obdlogger/config.h b/obdlogger/config.h index 136ed80..e05b85b 100644 --- a/obdlogger/config.h +++ b/obdlogger/config.h @@ -34,13 +34,14 @@ /************************************** * Choose LCD model here **************************************/ -LCD_SSD1306 lcd; +LCD_SH1106 lcd; +//LCD_SSD1306 lcd; //LCD_Null lcd; /************************************** * Other options **************************************/ -#define USE_MPU6050 1 +#define USE_MPU6050 0 //#define OBD_MIN_INTERVAL 50 /* ms */ #define GPS_DATA_TIMEOUT 2000 /* ms */ //#define DEBUG Serial diff --git a/obdlogger/obdlogger.cbp b/obdlogger/obdlogger.cbp index e8f3685..1058588 100644 --- a/obdlogger/obdlogger.cbp +++ b/obdlogger/obdlogger.cbp @@ -584,7 +584,7 @@ </Compiler> <Unit filename="MicroLCD.cpp" /> <Unit filename="MicroLCD.h" /> - <Unit filename="SSD1306.cpp" /> + <Unit filename="SH1106.cpp" /> <Unit filename="config.h" /> <Unit filename="datalogger.h" /> <Unit filename="images.h" /> |