Rod Coleman / I2CTextLCD
Committer:
RodColeman
Date:
Wed Nov 23 11:39:39 2011 +0000
Revision:
7:dd2dcba75885
Parent:
6:bc76b6a20bfb
Child:
8:4816fdd57607
more init optimising

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 7:dd2dcba75885 48 /*
RodColeman 7:dd2dcba75885 49 wait(0.5);
RodColeman 7:dd2dcba75885 50 writeCommand(0x2); // 4-bit mode
RodColeman 7:dd2dcba75885 51 wait(0.05);
RodColeman 7:dd2dcba75885 52 writeCommand(0x28); // Function set 001 BW N F - -
RodColeman 7:dd2dcba75885 53 wait(0.05);
RodColeman 7:dd2dcba75885 54 */
RodColeman 7:dd2dcba75885 55 //RC:2011-11-23: Newhaven 20x4 OLED data sheet method
RodColeman 0:9d621b44ea24 56 writeCommand(0x2); // 4-bit mode
RodColeman 6:bc76b6a20bfb 57 wait(0.05);
RodColeman 7:dd2dcba75885 58 writeCommand(0x2); // 4-bit mode
RodColeman 6:bc76b6a20bfb 59 wait(0.05);
RodColeman 7:dd2dcba75885 60 writeCommand(0x28); // display OFF, "Function Set". Newhaven say 0x08, but this loses 2 rows!
RodColeman 7:dd2dcba75885 61 wait(0.05);
RodColeman 7:dd2dcba75885 62 writeCommand(0x1); // display clear
RodColeman 6:bc76b6a20bfb 63 wait(0.05);
RodColeman 7:dd2dcba75885 64 writeCommand(0x6); // entry mode set
RodColeman 7:dd2dcba75885 65 wait(0.05);
RodColeman 7:dd2dcba75885 66 writeCommand(0x2); // 4-bit mode
RodColeman 7:dd2dcba75885 67 wait(0.05);
RodColeman 3:4b9faffb3f98 68 writeCommand(0x0C); // ON-OFF ctrl: turns display ON, no cursor. Use 0x0E for cursor ON.
RodColeman 0:9d621b44ea24 69 /* 0x28 also works for Winstar WEH002004ALPP5N00000 OLED display. 0x29= westEuro fon table, 0x2A = UK/Russian
RodColeman 0:9d621b44ea24 70 */
RodColeman 0:9d621b44ea24 71 // Added RC 2011-8-11
RodColeman 7:dd2dcba75885 72 /*
RodColeman 6:bc76b6a20bfb 73 writeCommand(0x05); // clear display RAM all to 00
RodColeman 5:4a4cea387d8e 74 wait(0.05); // 6.2ms specified for OLED display to recover from RAM clear
RodColeman 0:9d621b44ea24 75
RodColeman 3:4b9faffb3f98 76 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 77 wait(0.05);
RodColeman 5:4a4cea387d8e 78 writeCommand(0x14); // OLED display shift disable etc
RodColeman 6:bc76b6a20bfb 79 wait(0.05);
RodColeman 5:4a4cea387d8e 80 writeCommand(0x17); // disable graphic mode, power ON
RodColeman 5:4a4cea387d8e 81 //cls();
RodColeman 6:bc76b6a20bfb 82 wait(0.05);
RodColeman 5:4a4cea387d8e 83 writeCommand (0x01); //clear entire display.
RodColeman 5:4a4cea387d8e 84 wait(0.07);
RodColeman 7:dd2dcba75885 85 */
RodColeman 0:9d621b44ea24 86
RodColeman 0:9d621b44ea24 87 }
RodColeman 0:9d621b44ea24 88
RodColeman 0:9d621b44ea24 89 int I2CTextLCD::_putc(int value) {
RodColeman 0:9d621b44ea24 90 if (value == '\n') {
RodColeman 0:9d621b44ea24 91 newline();
RodColeman 0:9d621b44ea24 92 } else {
RodColeman 0:9d621b44ea24 93 writeData(value);
RodColeman 0:9d621b44ea24 94 }
RodColeman 0:9d621b44ea24 95 return value;
RodColeman 0:9d621b44ea24 96 }
RodColeman 0:9d621b44ea24 97
RodColeman 0:9d621b44ea24 98 int I2CTextLCD::_getc() {
RodColeman 0:9d621b44ea24 99 return 0;
RodColeman 0:9d621b44ea24 100 }
RodColeman 0:9d621b44ea24 101
RodColeman 0:9d621b44ea24 102 /* void I2CTextLCD::backlight(bool status) {
RodColeman 0:9d621b44ea24 103 _backlight=status;
RodColeman 0:9d621b44ea24 104 if (_backlight)
RodColeman 0:9d621b44ea24 105 writeI2CByte(BACKLIGHT_ON | E1_ON);
RodColeman 0:9d621b44ea24 106 else
RodColeman 0:9d621b44ea24 107 writeI2CByte(E1_ON);
RodColeman 0:9d621b44ea24 108 }
RodColeman 0:9d621b44ea24 109 */
RodColeman 0:9d621b44ea24 110
RodColeman 0:9d621b44ea24 111 void I2CTextLCD::newline() {
RodColeman 0:9d621b44ea24 112 _column = 0;
RodColeman 0:9d621b44ea24 113 _row++;
RodColeman 0:9d621b44ea24 114 if (_row >= _rows) {
RodColeman 0:9d621b44ea24 115 _row = 0;
RodColeman 0:9d621b44ea24 116 }
RodColeman 0:9d621b44ea24 117 locate(_column, _row);
RodColeman 0:9d621b44ea24 118 }
RodColeman 0:9d621b44ea24 119
RodColeman 0:9d621b44ea24 120 void I2CTextLCD::locate(int column, int row) {
RodColeman 0:9d621b44ea24 121 if (column < 0 || column >= _columns || row < 0 || row >= _rows) {
RodColeman 0:9d621b44ea24 122 error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
RodColeman 0:9d621b44ea24 123 return;
RodColeman 0:9d621b44ea24 124 }
RodColeman 0:9d621b44ea24 125 _row = row;
RodColeman 0:9d621b44ea24 126 _column = column;
RodColeman 2:24c878e63f10 127 int address = 0x80;
RodColeman 4:d3b7c4237e9d 128 if (row==0){
RodColeman 0:9d621b44ea24 129 address = 0x80+_column;
RodColeman 0:9d621b44ea24 130 }
RodColeman 4:d3b7c4237e9d 131 else if (row==1){
RodColeman 0:9d621b44ea24 132 address= 0xc0+_column;
RodColeman 0:9d621b44ea24 133 }
RodColeman 4:d3b7c4237e9d 134 else if (row==2){
RodColeman 0:9d621b44ea24 135 address=0x94+_column;
RodColeman 0:9d621b44ea24 136 }
RodColeman 4:d3b7c4237e9d 137 else if(row==3){
RodColeman 0:9d621b44ea24 138 address=0xd4+_column;
RodColeman 0:9d621b44ea24 139 }
RodColeman 0:9d621b44ea24 140 /*
RodColeman 0:9d621b44ea24 141 int address = 0x80 + (_row * 40) + _column; // memory starts at 0x00, and is 40 chars long per row
RodColeman 0:9d621b44ea24 142 Set bit 7 also, to signify ADDRESS SET mode.
RodColeman 0:9d621b44ea24 143 // pc_LCD.traceOut("locate %dx%d\r\n", column, row);
RodColeman 0:9d621b44ea24 144 */
RodColeman 0:9d621b44ea24 145 writeCommand(address); // must set bit 7 to indicate address SET command
RodColeman 0:9d621b44ea24 146 wait(0.004); // takes 1.5ms on Winstar LCD 20x4
RodColeman 0:9d621b44ea24 147 }
RodColeman 0:9d621b44ea24 148
RodColeman 0:9d621b44ea24 149 void I2CTextLCD::cls() {
RodColeman 0:9d621b44ea24 150 writeCommand(0x01); // Clear Display
RodColeman 4:d3b7c4237e9d 151 wait(0.01f); // This command takes 1.64 ms (LCD), 6.2ms for Winstar OLED
RodColeman 0:9d621b44ea24 152 locate(0, 0);
RodColeman 0:9d621b44ea24 153 }
RodColeman 0:9d621b44ea24 154
RodColeman 0:9d621b44ea24 155 void I2CTextLCD::reset() {
RodColeman 0:9d621b44ea24 156 cls();
RodColeman 0:9d621b44ea24 157 }
RodColeman 0:9d621b44ea24 158
RodColeman 2:24c878e63f10 159 void I2CTextLCD::writeByte(int c, bool rs) { // This is the actual I2C transfer of the display data:
RodColeman 2:24c878e63f10 160 char cmd[2]; //led = 1;
RodColeman 0:9d621b44ea24 161 cmd[0]=c>>2; // upper nibble
RodColeman 2:24c878e63f10 162 cmd[0]=cmd[0] & 0x3c; // mask out bits other than 5:2 for data (RS and E are enabled separately, below:)
RodColeman 0:9d621b44ea24 163 cmd[1]=c<<2; // lower nibble
RodColeman 0:9d621b44ea24 164 cmd[1]=cmd[1] & 0x3c;
RodColeman 0:9d621b44ea24 165 if (rs) {
RodColeman 2:24c878e63f10 166 cmd[0]=cmd[0] | 0x01; // RS selects display DATA or a COMMAND. It's on bit 0:
RodColeman 0:9d621b44ea24 167 cmd[1]=cmd[1] | 0x01;
RodColeman 0:9d621b44ea24 168 }
RodColeman 2:24c878e63f10 169 _i2c.write( _i2cAddress,cmd,1); // E=0, write upper nibble. E's on bit 1!
RodColeman 0:9d621b44ea24 170 wait_us(1);
RodColeman 0:9d621b44ea24 171 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 172 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 173 wait_us(1);
RodColeman 0:9d621b44ea24 174 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
RodColeman 0:9d621b44ea24 175 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 176 wait_us(1);
RodColeman 0:9d621b44ea24 177 cmd[0]=cmd[1]; //E=0, write lower nibble
RodColeman 0:9d621b44ea24 178 wait_us(1);
RodColeman 0:9d621b44ea24 179 cmd[0]=cmd[0]|0x02; //E=1
RodColeman 0:9d621b44ea24 180 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 181 wait_us(1);
RodColeman 0:9d621b44ea24 182 cmd[0]=cmd[0]&0x3d; //E=0, RS preserved in bit 0
RodColeman 0:9d621b44ea24 183 _i2c.write( _i2cAddress, cmd,1);
RodColeman 0:9d621b44ea24 184 _i2c.write ( _i2cAddress,cmd,1);
RodColeman 0:9d621b44ea24 185 // led = 0;
RodColeman 0:9d621b44ea24 186 wait_us(1);
RodColeman 0:9d621b44ea24 187 }
RodColeman 2:24c878e63f10 188 // This is the original authors method:
RodColeman 0:9d621b44ea24 189 //void I2CTextLCD::writeByte(int data, bool rs) {
RodColeman 0:9d621b44ea24 190
RodColeman 0:9d621b44ea24 191
RodColeman 0:9d621b44ea24 192 /*
RodColeman 0:9d621b44ea24 193 writeNibble(data >> 4 , rs);
RodColeman 0:9d621b44ea24 194 writeNibble(data >> 0 , rs);
RodColeman 0:9d621b44ea24 195 RC 2011-8-11. change to d4..d7 - PCF8574 ports P2 .. P5
RodColeman 0:9d621b44ea24 196 */
RodColeman 0:9d621b44ea24 197 //data = data>>2;
RodColeman 0:9d621b44ea24 198 //data = data & 0x3c;
RodColeman 0:9d621b44ea24 199 //writeNibble(data , rs);
RodColeman 0:9d621b44ea24 200 //data = data<<2;
RodColeman 0:9d621b44ea24 201 //data = data & 0x3c;
RodColeman 0:9d621b44ea24 202 //writeNibble(data , rs);
RodColeman 0:9d621b44ea24 203
RodColeman 0:9d621b44ea24 204 void I2CTextLCD::writeCommand(int command) {
RodColeman 0:9d621b44ea24 205 // RS = 0;
RodColeman 0:9d621b44ea24 206 writeByte(command,false);
RodColeman 0:9d621b44ea24 207 }
RodColeman 0:9d621b44ea24 208
RodColeman 0:9d621b44ea24 209 void I2CTextLCD::writeData(int data) {
RodColeman 0:9d621b44ea24 210 //RS = 1
RodColeman 0:9d621b44ea24 211 writeByte(data,true);
RodColeman 0:9d621b44ea24 212
RodColeman 0:9d621b44ea24 213 _column++;
RodColeman 0:9d621b44ea24 214 if (_column >= _columns) {
RodColeman 0:9d621b44ea24 215 newline();
RodColeman 0:9d621b44ea24 216 }
RodColeman 0:9d621b44ea24 217 }
RodColeman 0:9d621b44ea24 218
RodColeman 0:9d621b44ea24 219 /* void I2CTextLCD::writeI2CByte(int data) {
RodColeman 0:9d621b44ea24 220 char cmd[2];
RodColeman 0:9d621b44ea24 221 cmd[0] = (data & 0xFF);
RodColeman 0:9d621b44ea24 222 cmd[1] = (data >> 8);
RodColeman 0:9d621b44ea24 223 _i2c.write(_i2cAddress, cmd, 2);
RodColeman 0:9d621b44ea24 224 */
RodColeman 0:9d621b44ea24 225
RodColeman 0:9d621b44ea24 226
RodColeman 0:9d621b44ea24 227
RodColeman 0:9d621b44ea24 228
RodColeman 0:9d621b44ea24 229
RodColeman 0:9d621b44ea24 230