Rod Coleman / I2CTextLCD
Committer:
RodColeman
Date:
Wed Nov 23 08:17:39 2011 +0000
Revision:
6:bc76b6a20bfb
Parent:
5:4a4cea387d8e
Child:
7:dd2dcba75885
Increased all timings between initialisation commands to 50ms or more.
0,5s for PSU stabilisation

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 /*
RodColeman 0:9d621b44ea24 14 * useful info found at http://www.a-netz.de/lcd.en.php
RodColeman 0:9d621b44ea24 15 *
RodColeman 0:9d621b44ea24 16 *
RodColeman 0:9d621b44ea24 17 * Initialisation
RodColeman 0:9d621b44ea24 18 * ==============
RodColeman 0:9d621b44ea24 19 *
RodColeman 0:9d621b44ea24 20 * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state
RodColeman 0:9d621b44ea24 21 *
RodColeman 0:9d621b44ea24 22 * - wait approximately 15 ms so the display is ready to execute commands
RodColeman 0:9d621b44ea24 23 * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now).
RodColeman 0:9d621b44ea24 24 * - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command.
RodColeman 0:9d621b44ea24 25 * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now.
RodColeman 0:9d621b44ea24 26 * - Execute the "clear display" command
RodColeman 0:9d621b44ea24 27 *
RodColeman 0:9d621b44ea24 28 * Timing
RodColeman 0:9d621b44ea24 29 * ======
RodColeman 0:9d621b44ea24 30 *
RodColeman 0:9d621b44ea24 31 * Nearly all commands transmitted to the display need 40us for execution.
RodColeman 0:9d621b44ea24 32 * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position"
RodColeman 0:9d621b44ea24 33 * These commands need 1.64ms for execution. These timings are valid for all displays working with an
RodColeman 0:9d621b44ea24 34 * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you
RodColeman 0:9d621b44ea24 35 * can use the busy flag to test if the display is ready to accept the next command.
RodColeman 0:9d621b44ea24 36 *
RodColeman 0:9d621b44ea24 37 */
RodColeman 0:9d621b44ea24 38
RodColeman 0:9d621b44ea24 39 I2CTextLCD::I2CTextLCD(PinName sda, PinName scl, int i2cAddress , int columns, int rows,
RodColeman 0:9d621b44ea24 40 bool backlight) : _i2c(sda, scl) {
RodColeman 0:9d621b44ea24 41
RodColeman 0:9d621b44ea24 42 _i2cAddress = i2cAddress;
RodColeman 0:9d621b44ea24 43 _columns = columns;
RodColeman 0:9d621b44ea24 44 _rows = rows;
RodColeman 0:9d621b44ea24 45 _backlight=backlight;
RodColeman 1:e60cbc407d73 46 //_i2c.frequency(70000);
RodColeman 2:24c878e63f10 47 // Winstar 20x4 WH2004-NYG- needs 40ms after VDD> 4,5V
RodColeman 6:bc76b6a20bfb 48 wait(0.5);
RodColeman 2:24c878e63f10 49 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
RodColeman 4:d3b7c4237e9d 50 for (int i=0; i<3; i++) {
RodColeman 5:4a4cea387d8e 51 // writeCommand(0x3); //send 3 times mode
RodColeman 4:d3b7c4237e9d 52 wait(0.00164); // this command takes 1.64ms, so wait for it
RodColeman 4:d3b7c4237e9d 53 }
RodColeman 0:9d621b44ea24 54 writeCommand(0x2); // 4-bit mode
RodColeman 6:bc76b6a20bfb 55 wait(0.05);
RodColeman 5:4a4cea387d8e 56 // writeCommand(0x2); // 4-bit mode
RodColeman 0:9d621b44ea24 57
RodColeman 0:9d621b44ea24 58 writeCommand(0x28); // Function set 001 BW N F - -
RodColeman 6:bc76b6a20bfb 59 wait(0.05);
RodColeman 5:4a4cea387d8e 60 // writeCommand(0x28); // Function set 001 BW N F
RodColeman 6:bc76b6a20bfb 61 wait(0.05);
RodColeman 3:4b9faffb3f98 62 writeCommand(0x0C); // ON-OFF ctrl: turns display ON, no cursor. Use 0x0E for cursor ON.
RodColeman 0:9d621b44ea24 63 /* 0x28 also works for Winstar WEH002004ALPP5N00000 OLED display. 0x29= westEuro fon table, 0x2A = UK/Russian
RodColeman 0:9d621b44ea24 64 */
RodColeman 0:9d621b44ea24 65 // Added RC 2011-8-11
RodColeman 6:bc76b6a20bfb 66 writeCommand(0x05); // clear display RAM all to 00
RodColeman 5:4a4cea387d8e 67 wait(0.05); // 6.2ms specified for OLED display to recover from RAM clear
RodColeman 0:9d621b44ea24 68
RodColeman 3:4b9faffb3f98 69 writeCommand(0x06); // Entry mode Set. Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
RodColeman 6:bc76b6a20bfb 70 wait(0.05);
RodColeman 5:4a4cea387d8e 71 writeCommand(0x14); // OLED display shift disable etc
RodColeman 6:bc76b6a20bfb 72 wait(0.05);
RodColeman 5:4a4cea387d8e 73 writeCommand(0x17); // disable graphic mode, power ON
RodColeman 5:4a4cea387d8e 74 //cls();
RodColeman 6:bc76b6a20bfb 75 wait(0.05);
RodColeman 5:4a4cea387d8e 76 writeCommand (0x01); //clear entire display.
RodColeman 5:4a4cea387d8e 77 wait(0.07);
RodColeman 0:9d621b44ea24 78
RodColeman 0:9d621b44ea24 79
RodColeman 0:9d621b44ea24 80 }
RodColeman 0:9d621b44ea24 81
RodColeman 0:9d621b44ea24 82 int I2CTextLCD::_putc(int value) {
RodColeman 0:9d621b44ea24 83 if (value == '\n') {
RodColeman 0:9d621b44ea24 84 newline();
RodColeman 0:9d621b44ea24 85 } else {
RodColeman 0:9d621b44ea24 86 writeData(value);
RodColeman 0:9d621b44ea24 87 }
RodColeman 0:9d621b44ea24 88 return value;
RodColeman 0:9d621b44ea24 89 }
RodColeman 0:9d621b44ea24 90
RodColeman 0:9d621b44ea24 91 int I2CTextLCD::_getc() {
RodColeman 0:9d621b44ea24 92 return 0;
RodColeman 0:9d621b44ea24 93 }
RodColeman 0:9d621b44ea24 94
RodColeman 0:9d621b44ea24 95 /* void I2CTextLCD::backlight(bool status) {
RodColeman 0:9d621b44ea24 96 _backlight=status;
RodColeman 0:9d621b44ea24 97 if (_backlight)
RodColeman 0:9d621b44ea24 98 writeI2CByte(BACKLIGHT_ON | E1_ON);
RodColeman 0:9d621b44ea24 99 else
RodColeman 0:9d621b44ea24 100 writeI2CByte(E1_ON);
RodColeman 0:9d621b44ea24 101 }
RodColeman 0:9d621b44ea24 102 */
RodColeman 0:9d621b44ea24 103
RodColeman 0:9d621b44ea24 104 void I2CTextLCD::newline() {
RodColeman 0:9d621b44ea24 105 _column = 0;
RodColeman 0:9d621b44ea24 106 _row++;
RodColeman 0:9d621b44ea24 107 if (_row >= _rows) {
RodColeman 0:9d621b44ea24 108 _row = 0;
RodColeman 0:9d621b44ea24 109 }
RodColeman 0:9d621b44ea24 110 locate(_column, _row);
RodColeman 0:9d621b44ea24 111 }
RodColeman 0:9d621b44ea24 112
RodColeman 0:9d621b44ea24 113 void I2CTextLCD::locate(int column, int row) {
RodColeman 0:9d621b44ea24 114 if (column < 0 || column >= _columns || row < 0 || row >= _rows) {
RodColeman 0:9d621b44ea24 115 error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
RodColeman 0:9d621b44ea24 116 return;
RodColeman 0:9d621b44ea24 117 }
RodColeman 0:9d621b44ea24 118 _row = row;
RodColeman 0:9d621b44ea24 119 _column = column;
RodColeman 2:24c878e63f10 120 int address = 0x80;
RodColeman 4:d3b7c4237e9d 121 if (row==0){
RodColeman 0:9d621b44ea24 122 address = 0x80+_column;
RodColeman 0:9d621b44ea24 123 }
RodColeman 4:d3b7c4237e9d 124 else if (row==1){
RodColeman 0:9d621b44ea24 125 address= 0xc0+_column;
RodColeman 0:9d621b44ea24 126 }
RodColeman 4:d3b7c4237e9d 127 else if (row==2){
RodColeman 0:9d621b44ea24 128 address=0x94+_column;
RodColeman 0:9d621b44ea24 129 }
RodColeman 4:d3b7c4237e9d 130 else if(row==3){
RodColeman 0:9d621b44ea24 131 address=0xd4+_column;
RodColeman 0:9d621b44ea24 132 }
RodColeman 0:9d621b44ea24 133 /*
RodColeman 0:9d621b44ea24 134 int address = 0x80 + (_row * 40) + _column; // memory starts at 0x00, and is 40 chars long per row
RodColeman 0:9d621b44ea24 135 Set bit 7 also, to signify ADDRESS SET mode.
RodColeman 0:9d621b44ea24 136 // pc_LCD.traceOut("locate %dx%d\r\n", column, row);
RodColeman 0:9d621b44ea24 137 */
RodColeman 0:9d621b44ea24 138 writeCommand(address); // must set bit 7 to indicate address SET command
RodColeman 0:9d621b44ea24 139 wait(0.004); // takes 1.5ms on Winstar LCD 20x4
RodColeman 0:9d621b44ea24 140 }
RodColeman 0:9d621b44ea24 141
RodColeman 0:9d621b44ea24 142 void I2CTextLCD::cls() {
RodColeman 0:9d621b44ea24 143 writeCommand(0x01); // Clear Display
RodColeman 4:d3b7c4237e9d 144 wait(0.01f); // This command takes 1.64 ms (LCD), 6.2ms for Winstar OLED
RodColeman 0:9d621b44ea24 145 locate(0, 0);
RodColeman 0:9d621b44ea24 146 }
RodColeman 0:9d621b44ea24 147
RodColeman 0:9d621b44ea24 148 void I2CTextLCD::reset() {
RodColeman 0:9d621b44ea24 149 cls();
RodColeman 0:9d621b44ea24 150 }
RodColeman 0:9d621b44ea24 151
RodColeman 2:24c878e63f10 152 void I2CTextLCD::writeByte(int c, bool rs) { // This is the actual I2C transfer of the display data:
RodColeman 2:24c878e63f10 153 char cmd[2]; //led = 1;
RodColeman 0:9d621b44ea24 154 cmd[0]=c>>2; // upper nibble
RodColeman 2:24c878e63f10 155 cmd[0]=cmd[0] & 0x3c; // mask out bits other than 5:2 for data (RS and E are enabled separately, below:)
RodColeman 0:9d621b44ea24 156 cmd[1]=c<<2; // lower nibble
RodColeman 0:9d621b44ea24 157 cmd[1]=cmd[1] & 0x3c;
RodColeman 0:9d621b44ea24 158 if (rs) {
RodColeman 2:24c878e63f10 159 cmd[0]=cmd[0] | 0x01; // RS selects display DATA or a COMMAND. It's on bit 0:
RodColeman 0:9d621b44ea24 160 cmd[1]=cmd[1] | 0x01;
RodColeman 0:9d621b44ea24 161 }
RodColeman 2:24c878e63f10 162 _i2c.write( _i2cAddress,cmd,1); // E=0, write upper nibble. E's on bit 1!
RodColeman 0:9d621b44ea24 163 wait_us(1);
RodColeman 0:9d621b44ea24 164 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 165 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 166 wait_us(1);
RodColeman 0:9d621b44ea24 167 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
RodColeman 0:9d621b44ea24 168 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 169 wait_us(1);
RodColeman 0:9d621b44ea24 170 cmd[0]=cmd[1]; //E=0, write lower nibble
RodColeman 0:9d621b44ea24 171 wait_us(1);
RodColeman 0:9d621b44ea24 172 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 173 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 174 wait_us(1);
RodColeman 0:9d621b44ea24 175 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
RodColeman 0:9d621b44ea24 176 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 177 _i2c.write ( _i2cAddress,cmd,1);
RodColeman 0:9d621b44ea24 178 // led = 0;
RodColeman 0:9d621b44ea24 179 wait_us(1);
RodColeman 0:9d621b44ea24 180 }
RodColeman 2:24c878e63f10 181 // This is the original authors method:
RodColeman 0:9d621b44ea24 182 //void I2CTextLCD::writeByte(int data, bool rs) {
RodColeman 0:9d621b44ea24 183
RodColeman 0:9d621b44ea24 184
RodColeman 0:9d621b44ea24 185 /*
RodColeman 0:9d621b44ea24 186 writeNibble(data >> 4 , rs);
RodColeman 0:9d621b44ea24 187 writeNibble(data >> 0 , rs);
RodColeman 0:9d621b44ea24 188 RC 2011-8-11. change to d4..d7 - PCF8574 ports P2 .. P5
RodColeman 0:9d621b44ea24 189 */
RodColeman 0:9d621b44ea24 190 //data = data>>2;
RodColeman 0:9d621b44ea24 191 //data = data & 0x3c;
RodColeman 0:9d621b44ea24 192 //writeNibble(data , rs);
RodColeman 0:9d621b44ea24 193 //data = data<<2;
RodColeman 0:9d621b44ea24 194 //data = data & 0x3c;
RodColeman 0:9d621b44ea24 195 //writeNibble(data , rs);
RodColeman 0:9d621b44ea24 196
RodColeman 0:9d621b44ea24 197 void I2CTextLCD::writeCommand(int command) {
RodColeman 0:9d621b44ea24 198 // RS = 0;
RodColeman 0:9d621b44ea24 199 writeByte(command,false);
RodColeman 0:9d621b44ea24 200 }
RodColeman 0:9d621b44ea24 201
RodColeman 0:9d621b44ea24 202 void I2CTextLCD::writeData(int data) {
RodColeman 0:9d621b44ea24 203 //RS = 1
RodColeman 0:9d621b44ea24 204 writeByte(data,true);
RodColeman 0:9d621b44ea24 205
RodColeman 0:9d621b44ea24 206 _column++;
RodColeman 0:9d621b44ea24 207 if (_column >= _columns) {
RodColeman 0:9d621b44ea24 208 newline();
RodColeman 0:9d621b44ea24 209 }
RodColeman 0:9d621b44ea24 210 }
RodColeman 0:9d621b44ea24 211
RodColeman 0:9d621b44ea24 212 /* void I2CTextLCD::writeI2CByte(int data) {
RodColeman 0:9d621b44ea24 213 char cmd[2];
RodColeman 0:9d621b44ea24 214 cmd[0] = (data & 0xFF);
RodColeman 0:9d621b44ea24 215 cmd[1] = (data >> 8);
RodColeman 0:9d621b44ea24 216 _i2c.write(_i2cAddress, cmd, 2);
RodColeman 0:9d621b44ea24 217 */
RodColeman 0:9d621b44ea24 218
RodColeman 0:9d621b44ea24 219
RodColeman 0:9d621b44ea24 220
RodColeman 0:9d621b44ea24 221
RodColeman 0:9d621b44ea24 222
RodColeman 0:9d621b44ea24 223