Rod Coleman / I2CTextLCD
Committer:
RodColeman
Date:
Tue Oct 15 10:44:20 2013 +0000
Revision:
9:16c12a5da0ac
Parent:
8:4816fdd57607
Init changes as proved at Dawson

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RodColeman 0:9d621b44ea24 1 /* mbed I2CTextLCD Library
RodColeman 0:9d621b44ea24 2 * Copyright (c) 2007-2009 sford
RodColeman 0:9d621b44ea24 3 * Copyright (c) 2010 Wim De Roeve changed to work with I2C PCF8575
RodColeman 0:9d621b44ea24 4 * Released under the MIT License: http://mbed.org/license/mit
RodColeman 0:9d621b44ea24 5 */
RodColeman 0:9d621b44ea24 6
RodColeman 0:9d621b44ea24 7 #include "I2CTextLCD.h"
RodColeman 0:9d621b44ea24 8 #include "mbed.h"
RodColeman 0:9d621b44ea24 9 #include "error.h"
RodColeman 0:9d621b44ea24 10
RodColeman 0:9d621b44ea24 11 using namespace mbed;
RodColeman 0:9d621b44ea24 12
RodColeman 0:9d621b44ea24 13 I2CTextLCD::I2CTextLCD(PinName sda, PinName scl, int i2cAddress , int columns, int rows,
RodColeman 0:9d621b44ea24 14 bool backlight) : _i2c(sda, scl) {
RodColeman 0:9d621b44ea24 15
RodColeman 0:9d621b44ea24 16 _i2cAddress = i2cAddress;
RodColeman 0:9d621b44ea24 17 _columns = columns;
RodColeman 0:9d621b44ea24 18 _rows = rows;
RodColeman 0:9d621b44ea24 19 _backlight=backlight;
RodColeman 8:4816fdd57607 20 _i2c.frequency(70000); // RC:2011-12-1 put this back in
RodColeman 9:16c12a5da0ac 21
RodColeman 9:16c12a5da0ac 22 // Winstar 20x4 WH2004-NYG- needs 40ms after VDD> 4,5V
RodColeman 7:dd2dcba75885 23 //RC:2011-11-23: Newhaven 20x4 OLED data sheet method
RodColeman 9:16c12a5da0ac 24 wait(0.055);
RodColeman 9:16c12a5da0ac 25 init8574A(); // I2C chip PCF85774A init - E high - E falls with 0x2 on the D-nibble (set 4-bit mode command)
RodColeman 9:16c12a5da0ac 26 writeCommand(0x2); // 4-bit mode
RodColeman 6:bc76b6a20bfb 27 wait(0.05);
RodColeman 9:16c12a5da0ac 28 writeCommand(0x2); // 4-bit mode
RodColeman 6:bc76b6a20bfb 29 wait(0.05);
RodColeman 9:16c12a5da0ac 30 writeCommand(0x2A); // 2012-6-22 RC: Russian font Table. was 0x28. display OFF, "Function Set". Newhaven say 0x08, but this loses 2 rows!
RodColeman 7:dd2dcba75885 31 wait(0.05);
RodColeman 9:16c12a5da0ac 32 writeCommand(0x1); // display clear
RodColeman 6:bc76b6a20bfb 33 wait(0.05);
RodColeman 9:16c12a5da0ac 34 writeCommand(0x6); // entry mode set
RodColeman 7:dd2dcba75885 35 wait(0.05);
RodColeman 9:16c12a5da0ac 36 writeCommand(0x2); // 4-bit mode
RodColeman 7:dd2dcba75885 37 wait(0.05);
RodColeman 3:4b9faffb3f98 38 writeCommand(0x0C); // ON-OFF ctrl: turns display ON, no cursor. Use 0x0E for cursor ON.
RodColeman 9:16c12a5da0ac 39 /* 0x28 also works for Winstar WEH002004ALPP5N00000 OLED display. 0x29= westEuro fon table, 0x2A = UK/Russian*/
RodColeman 9:16c12a5da0ac 40 wait(0.015); // Wait 15ms to ensure powered up
RodColeman 0:9d621b44ea24 41 }
RodColeman 0:9d621b44ea24 42
RodColeman 0:9d621b44ea24 43 int I2CTextLCD::_putc(int value) {
RodColeman 0:9d621b44ea24 44 if (value == '\n') {
RodColeman 0:9d621b44ea24 45 newline();
RodColeman 9:16c12a5da0ac 46 }
RodColeman 9:16c12a5da0ac 47 else {
RodColeman 0:9d621b44ea24 48 writeData(value);
RodColeman 0:9d621b44ea24 49 }
RodColeman 0:9d621b44ea24 50 return value;
RodColeman 0:9d621b44ea24 51 }
RodColeman 0:9d621b44ea24 52
RodColeman 0:9d621b44ea24 53 int I2CTextLCD::_getc() {
RodColeman 0:9d621b44ea24 54 return 0;
RodColeman 0:9d621b44ea24 55 }
RodColeman 0:9d621b44ea24 56
RodColeman 0:9d621b44ea24 57 /* void I2CTextLCD::backlight(bool status) {
RodColeman 0:9d621b44ea24 58 _backlight=status;
RodColeman 0:9d621b44ea24 59 if (_backlight)
RodColeman 0:9d621b44ea24 60 writeI2CByte(BACKLIGHT_ON | E1_ON);
RodColeman 0:9d621b44ea24 61 else
RodColeman 0:9d621b44ea24 62 writeI2CByte(E1_ON);
RodColeman 0:9d621b44ea24 63 }
RodColeman 0:9d621b44ea24 64 */
RodColeman 0:9d621b44ea24 65
RodColeman 0:9d621b44ea24 66 void I2CTextLCD::newline() {
RodColeman 0:9d621b44ea24 67 _column = 0;
RodColeman 0:9d621b44ea24 68 _row++;
RodColeman 0:9d621b44ea24 69 if (_row >= _rows) {
RodColeman 0:9d621b44ea24 70 _row = 0;
RodColeman 0:9d621b44ea24 71 }
RodColeman 0:9d621b44ea24 72 locate(_column, _row);
RodColeman 0:9d621b44ea24 73 }
RodColeman 0:9d621b44ea24 74
RodColeman 0:9d621b44ea24 75 void I2CTextLCD::locate(int column, int row) {
RodColeman 0:9d621b44ea24 76 if (column < 0 || column >= _columns || row < 0 || row >= _rows) {
RodColeman 0:9d621b44ea24 77 error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
RodColeman 0:9d621b44ea24 78 return;
RodColeman 0:9d621b44ea24 79 }
RodColeman 0:9d621b44ea24 80 _row = row;
RodColeman 0:9d621b44ea24 81 _column = column;
RodColeman 2:24c878e63f10 82 int address = 0x80;
RodColeman 4:d3b7c4237e9d 83 if (row==0){
RodColeman 0:9d621b44ea24 84 address = 0x80+_column;
RodColeman 0:9d621b44ea24 85 }
RodColeman 4:d3b7c4237e9d 86 else if (row==1){
RodColeman 0:9d621b44ea24 87 address= 0xc0+_column;
RodColeman 0:9d621b44ea24 88 }
RodColeman 4:d3b7c4237e9d 89 else if (row==2){
RodColeman 0:9d621b44ea24 90 address=0x94+_column;
RodColeman 0:9d621b44ea24 91 }
RodColeman 4:d3b7c4237e9d 92 else if(row==3){
RodColeman 0:9d621b44ea24 93 address=0xd4+_column;
RodColeman 0:9d621b44ea24 94 }
RodColeman 0:9d621b44ea24 95 /*
RodColeman 0:9d621b44ea24 96 int address = 0x80 + (_row * 40) + _column; // memory starts at 0x00, and is 40 chars long per row
RodColeman 0:9d621b44ea24 97 Set bit 7 also, to signify ADDRESS SET mode.
RodColeman 0:9d621b44ea24 98 // pc_LCD.traceOut("locate %dx%d\r\n", column, row);
RodColeman 0:9d621b44ea24 99 */
RodColeman 0:9d621b44ea24 100 writeCommand(address); // must set bit 7 to indicate address SET command
RodColeman 0:9d621b44ea24 101 wait(0.004); // takes 1.5ms on Winstar LCD 20x4
RodColeman 0:9d621b44ea24 102 }
RodColeman 0:9d621b44ea24 103
RodColeman 0:9d621b44ea24 104 void I2CTextLCD::cls() {
RodColeman 0:9d621b44ea24 105 writeCommand(0x01); // Clear Display
RodColeman 4:d3b7c4237e9d 106 wait(0.01f); // This command takes 1.64 ms (LCD), 6.2ms for Winstar OLED
RodColeman 0:9d621b44ea24 107 locate(0, 0);
RodColeman 0:9d621b44ea24 108 }
RodColeman 0:9d621b44ea24 109
RodColeman 0:9d621b44ea24 110 void I2CTextLCD::reset() {
RodColeman 0:9d621b44ea24 111 cls();
RodColeman 0:9d621b44ea24 112 }
RodColeman 9:16c12a5da0ac 113 void I2CTextLCD::init8574A(void) { // This puts the first command on the bus with E high
RodColeman 9:16c12a5da0ac 114 // to prevent E going LOW at init with undef data lines, WS0010 does not like.
RodColeman 9:16c12a5da0ac 115 char cmd[2];
RodColeman 9:16c12a5da0ac 116 cmd[0]=(0x2)<<2; // lower nibble
RodColeman 9:16c12a5da0ac 117 cmd[0]=cmd[0] & 0x3c; // 3C = 0011 1100
RodColeman 9:16c12a5da0ac 118 //RS = 0 for commands - and for init (only), we start with E high
RodColeman 0:9d621b44ea24 119 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 120 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 121 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
RodColeman 0:9d621b44ea24 122 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 123 wait_us(1);
RodColeman 9:16c12a5da0ac 124 }
RodColeman 9:16c12a5da0ac 125 void I2CTextLCD::writeByte(int c, bool rs) { // This is the actual I2C transfer of the display data:
RodColeman 9:16c12a5da0ac 126 char cmd[2];
RodColeman 9:16c12a5da0ac 127 cmd[0]=c>>2; // upper nibble
RodColeman 9:16c12a5da0ac 128 cmd[0]=cmd[0] & 0x3c; // mask out bits other than 5:2 for data (RS and E are enabled separately, below:)
RodColeman 9:16c12a5da0ac 129 cmd[1]=c<<2; // lower nibble
RodColeman 9:16c12a5da0ac 130 cmd[1]=cmd[1] & 0x3c; // 3C = 0011 1100
RodColeman 9:16c12a5da0ac 131 if (rs) {
RodColeman 9:16c12a5da0ac 132 cmd[0]=cmd[0] | 0x01; // RS selects display DATA or a COMMAND. It's on bit 0:
RodColeman 9:16c12a5da0ac 133 cmd[1]=cmd[1] | 0x01;
RodColeman 9:16c12a5da0ac 134 }
RodColeman 0:9d621b44ea24 135 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 136 _i2c.write( _i2cAddress, cmd,1);
RodColeman 9:16c12a5da0ac 137 //wait_us(1); ** delays between nibbles not needed. At 70kHz, the time for the I2C command writes is 114us per byte
RodColeman 9:16c12a5da0ac 138 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0. Data latched on fall of E (tS(d) = 40ns; tH(d) = 20ns)
RodColeman 9:16c12a5da0ac 139 _i2c.write( _i2cAddress, cmd,1);
RodColeman 9:16c12a5da0ac 140 cmd[0]=cmd[1]; // prepare lower nibble
RodColeman 9:16c12a5da0ac 141 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 9:16c12a5da0ac 142 _i2c.write( _i2cAddress, cmd,1);
RodColeman 9:16c12a5da0ac 143 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0. this preserves E low beween cycles.
RodColeman 0:9d621b44ea24 144 _i2c.write( _i2cAddress, cmd,1);
RodColeman 9:16c12a5da0ac 145 // ****** RECOVERY TIME:
RodColeman 9:16c12a5da0ac 146 wait_us(300); // specified max. recovery time for all operations, except cls(), is 600us
RodColeman 0:9d621b44ea24 147 }
RodColeman 0:9d621b44ea24 148
RodColeman 0:9d621b44ea24 149 void I2CTextLCD::writeCommand(int command) {
RodColeman 0:9d621b44ea24 150 // RS = 0;
RodColeman 0:9d621b44ea24 151 writeByte(command,false);
RodColeman 0:9d621b44ea24 152 }
RodColeman 0:9d621b44ea24 153
RodColeman 0:9d621b44ea24 154 void I2CTextLCD::writeData(int data) {
RodColeman 0:9d621b44ea24 155 //RS = 1
RodColeman 0:9d621b44ea24 156 writeByte(data,true);
RodColeman 0:9d621b44ea24 157
RodColeman 0:9d621b44ea24 158 _column++;
RodColeman 0:9d621b44ea24 159 if (_column >= _columns) {
RodColeman 0:9d621b44ea24 160 newline();
RodColeman 0:9d621b44ea24 161 }
RodColeman 9:16c12a5da0ac 162 }