LCD module Switch Science SKU#1405, which driver IC is ST7032i.

Revision:
0:92bfc61fb13b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/st7032i.cpp	Sat Jul 01 16:01:37 2017 +0000
@@ -0,0 +1,148 @@
+#include "st7032i.h"
+
+#define SLAVE_ADDR  0x3e
+
+#define MAX_VAL_CONTRAST  63
+
+#define CONTINUE     0x80
+#define INSTRUCTION  0x00
+#define NOT_CONTINUE 0x00
+#define DATA         0x40
+
+#define MAX_VAL_COLUMN    8
+#define MAX_VAL_ROW       2
+
+St7032i::St7032i(I2C *obj){
+    i2c = obj;
+}
+
+St7032i::Status St7032i::init(){
+    // Initialization command sequence. Check the data sheet.
+    const char initSequence[] = {
+            0x38,    // Function set
+            0x39,    // Function set
+            0x14,    // Internal OSC frequency
+            0x70,    // Contrast set
+            0x56,    // Power/ICON/Contrast control
+            0x6c,    // Follower control
+            0x38,    // Function set
+            0x0c,    // Display ON/OFF control
+            0x01     // Clear Display
+        };
+        
+    // wait time after a command sent. Check the data sheet.
+    const int t_wait_us[] = { 
+            27, 27, 27, 27, 27, 200000, 27, 27, 1080  // micro-seconds
+        };
+
+    /* Somehow this workaround was needed on my test environment (BLENano) to 
+     * make the module work correctly. Maybe the following issue is related to
+     * this problem.
+     * https://strawberry-linux.com/pub/i2c_lcd-an004.pdf
+     */
+    {
+        i2c->start();    // start condition
+        wait_us(100);
+        i2c->stop();     // stop condition
+        wait_us(100);
+    }
+
+    // number of commands
+    int n_cmd = sizeof(initSequence)/sizeof(char);    
+
+    // Execute the initialization sequence.
+    for(int i=0; i < n_cmd; i++){
+        char data[2] = {(INSTRUCTION | NOT_CONTINUE), initSequence[i]};
+        if(i2c->write((SLAVE_ADDR << 1), data, 2) != 0){
+            return ERROR_I2C_NO_ACK;
+        }
+        wait_us(t_wait_us[i]);
+    }
+    
+    return SUCCESS;    
+}
+
+St7032i::Status St7032i::setContrast(uint8_t val){
+    const int t_wait_us = 27;   // wait time in micro-seconds
+    
+    // sanity check
+    if(MAX_VAL_CONTRAST < val){
+        return INPUT_OUT_OF_RANGE;
+    }
+    
+    char high = (0x54 | ((val & 0x30) >> 4));
+    char low = (0x70 | (val & 0x0F));
+
+    char sequence[] = {0x39, high, low, 0x38};    
+    
+    // Execute the command sequence
+    int n = sizeof(sequence)/sizeof(char);
+    for(int i=0; i < n; i++){
+        char data[2] = {(INSTRUCTION | NOT_CONTINUE), sequence[i]};
+        if(i2c->write((SLAVE_ADDR << 1), data, 2) != 0){
+            return ERROR_I2C_NO_ACK;
+        }
+        wait_us(t_wait_us);
+    }
+    
+    return SUCCESS;
+}
+
+St7032i::Status St7032i::setCursorPosition(uint8_t col, uint8_t row){
+    // sanity check
+    if( col > MAX_VAL_COLUMN || row > MAX_VAL_ROW){
+        return INPUT_OUT_OF_RANGE;
+    }
+    
+    char ddramAddr = (0x80 | (((row & 0x01) << 6) | (col & 0x0f)));
+    
+    char data[2] = {0x00, ddramAddr};
+    if(i2c->write((SLAVE_ADDR << 1), data, 2) != 0){
+        return ERROR_I2C_NO_ACK;
+    }
+    
+    return SUCCESS;
+}
+
+St7032i::Status St7032i::putc(char c){
+    char data[2] = {(NOT_CONTINUE | DATA), c};
+    if(i2c->write((SLAVE_ADDR << 1), data, 2) != 0){
+        return ERROR_I2C_NO_ACK;
+    }
+    return SUCCESS;
+}
+
+
+St7032i::Status St7032i::clear(bool wait){
+    const int TIME_WAIT = 1080; // in micro-seconds
+    char data[2] = {(NOT_CONTINUE | INSTRUCTION), 0x01};
+    if(i2c->write((SLAVE_ADDR << 1), data, 2) != 0){
+        return ERROR_I2C_NO_ACK;
+    }
+    if(wait){
+        wait_us(TIME_WAIT);
+    }
+    return SUCCESS;
+}
+
+St7032i::Status St7032i::puts(const char *str, bool wrap){
+    Status st;
+    if((st=setCursorPosition(0,0)) != SUCCESS){
+        return st;
+    }
+    for(int i=0; i < MAX_VAL_ROW; i++){
+        for(int j=0; j < MAX_VAL_COLUMN; j++){
+            char c = str[i*MAX_VAL_COLUMN+j];
+            if(c == '\0'){
+                return SUCCESS;
+            }
+            putc(c);
+        }
+        if(wrap){
+            if((st=setCursorPosition(0,1)) != SUCCESS){
+                return st;
+            }
+        }
+    }          
+    return SUCCESS;
+}