Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
I2CTextLCD.cpp@9:16c12a5da0ac, 2013-10-15 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |