From fe25cca198cc468ae12d9cbf320c0d273c630016 Mon Sep 17 00:00:00 2001
From: Stanley Huang <stanleyhuangyc@gmail.com>
Date: Mon, 24 Feb 2014 01:47:57 +0800
Subject: Update OBD logger

---
 obdlogger/MicroLCD.cpp  |   3 +
 obdlogger/MicroLCD.h    |  21 ++-
 obdlogger/README.txt    |   4 +-
 obdlogger/SH1106.cpp    | 399 ++++++++++++++++++++++++++++++++++++++++++++++++
 obdlogger/SH1106.h      |   1 +
 obdlogger/config.h      |   5 +-
 obdlogger/obdlogger.cbp |   2 +-
 7 files changed, 429 insertions(+), 6 deletions(-)
 create mode 100644 obdlogger/SH1106.cpp
 create mode 100644 obdlogger/SH1106.h

(limited to 'obdlogger')

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" />
-- 
cgit v1.2.3