Rod Coleman / I2CTextLCD
Committer:
RodColeman
Date:
Tue Aug 23 11:29:30 2011 +0000
Revision:
2:24c878e63f10
Parent:
1:e60cbc407d73
Child:
3:4b9faffb3f98
fixed address undef at start

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