LCD module Switch Science SKU#1405, which driver IC is ST7032i.
Diff: st7032i.cpp
- 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; +}