Rod Coleman / I2CTextLCD
Committer:
RodColeman
Date:
Fri Aug 26 12:28:31 2011 +0000
Revision:
3:4b9faffb3f98
Parent:
2:24c878e63f10
Child:
4:d3b7c4237e9d
row addresses changed, for OLED

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