library for driving character LCD in 4-bit mode (HD44780, ST7066U & compatible) supports 16x2, 20x2, 20x4 & 40x2 uses R/W pin for timing rather than delays

Dependents:   Ultrasonic

Committer:
wertyfrog
Date:
Wed Jul 11 22:21:07 2012 +0000
Revision:
1:ca430b27054d
Parent:
0:173f8aaea8cc
1st public

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wertyfrog 0:173f8aaea8cc 1 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
wertyfrog 1:ca430b27054d 2 * Modified for 40x2 panels by wertyfrog (note: this version uses R/W pin for timing)
wertyfrog 0:173f8aaea8cc 3 * Copyright (c) 2007-2010, sford, http://mbed.org
wertyfrog 0:173f8aaea8cc 4 *
wertyfrog 0:173f8aaea8cc 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
wertyfrog 0:173f8aaea8cc 6 * of this software and associated documentation files (the "Software"), to deal
wertyfrog 0:173f8aaea8cc 7 * in the Software without restriction, including without limitation the rights
wertyfrog 0:173f8aaea8cc 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
wertyfrog 0:173f8aaea8cc 9 * copies of the Software, and to permit persons to whom the Software is
wertyfrog 0:173f8aaea8cc 10 * furnished to do so, subject to the following conditions:
wertyfrog 0:173f8aaea8cc 11 *
wertyfrog 0:173f8aaea8cc 12 * The above copyright notice and this permission notice shall be included in
wertyfrog 0:173f8aaea8cc 13 * all copies or substantial portions of the Software.
wertyfrog 0:173f8aaea8cc 14 *
wertyfrog 0:173f8aaea8cc 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
wertyfrog 0:173f8aaea8cc 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
wertyfrog 0:173f8aaea8cc 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
wertyfrog 0:173f8aaea8cc 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
wertyfrog 0:173f8aaea8cc 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wertyfrog 0:173f8aaea8cc 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
wertyfrog 0:173f8aaea8cc 21 * THE SOFTWARE.
wertyfrog 0:173f8aaea8cc 22 */
wertyfrog 0:173f8aaea8cc 23
wertyfrog 0:173f8aaea8cc 24 #include "LCD40x2.h"
wertyfrog 0:173f8aaea8cc 25 #include "mbed.h"
wertyfrog 0:173f8aaea8cc 26
wertyfrog 0:173f8aaea8cc 27 TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1,
wertyfrog 0:173f8aaea8cc 28 PinName d2, PinName d3, LCDType type) : _rs(rs), _rw(rw),
wertyfrog 0:173f8aaea8cc 29 _e(e), _d(d0, d1, d2, d3), _type(type) {
wertyfrog 0:173f8aaea8cc 30 _rs = 0; // command mode
wertyfrog 0:173f8aaea8cc 31 _rw = 0;
wertyfrog 0:173f8aaea8cc 32 _e = 0;
wertyfrog 0:173f8aaea8cc 33 _d.output(); // data out
wertyfrog 0:173f8aaea8cc 34
wertyfrog 0:173f8aaea8cc 35 wait(0.05); // Wait 50ms to ensure powered up
wertyfrog 0:173f8aaea8cc 36
wertyfrog 0:173f8aaea8cc 37 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
wertyfrog 0:173f8aaea8cc 38 for (int i=0; i<3; i++) {
wertyfrog 0:173f8aaea8cc 39 _e = 1;
wertyfrog 0:173f8aaea8cc 40 __nop();
wertyfrog 0:173f8aaea8cc 41 _d = 0x3;
wertyfrog 0:173f8aaea8cc 42 __nop();
wertyfrog 0:173f8aaea8cc 43 _e = 0;
wertyfrog 0:173f8aaea8cc 44 wait(0.004f); // 4ms
wertyfrog 0:173f8aaea8cc 45 }
wertyfrog 0:173f8aaea8cc 46 _e = 1;
wertyfrog 0:173f8aaea8cc 47 __nop();
wertyfrog 0:173f8aaea8cc 48 _d = 0x2; // 4 Bit mode
wertyfrog 0:173f8aaea8cc 49 __nop();
wertyfrog 0:173f8aaea8cc 50 _e = 0;
wertyfrog 0:173f8aaea8cc 51
wertyfrog 0:173f8aaea8cc 52 writeCommand(0x28); // Function set 4 Bit, 2Line, 5*7
wertyfrog 0:173f8aaea8cc 53 writeCommand(0x08); // Display off
wertyfrog 0:173f8aaea8cc 54 writeCommand(0x01); // clear Display
wertyfrog 0:173f8aaea8cc 55 writeCommand(0x04); // cursor right, Display is not shifted
wertyfrog 0:173f8aaea8cc 56 writeCommand(0x0C); // Display on , Cursor off
wertyfrog 0:173f8aaea8cc 57 }
wertyfrog 0:173f8aaea8cc 58
wertyfrog 0:173f8aaea8cc 59 void TextLCD::character(int column, int row, int c) {
wertyfrog 0:173f8aaea8cc 60 int a = address(column, row);
wertyfrog 0:173f8aaea8cc 61 writeCommand(a);
wertyfrog 0:173f8aaea8cc 62 writeData(c);
wertyfrog 0:173f8aaea8cc 63 }
wertyfrog 0:173f8aaea8cc 64
wertyfrog 0:173f8aaea8cc 65 void TextLCD::cls() {
wertyfrog 0:173f8aaea8cc 66 writeCommand(0x01); // cls, and set cursor to 0
wertyfrog 0:173f8aaea8cc 67 locate(0, 0);
wertyfrog 0:173f8aaea8cc 68 }
wertyfrog 0:173f8aaea8cc 69
wertyfrog 0:173f8aaea8cc 70 void TextLCD::locate(int column, int row) {
wertyfrog 0:173f8aaea8cc 71 _column = column;
wertyfrog 0:173f8aaea8cc 72 _row = row;
wertyfrog 0:173f8aaea8cc 73 }
wertyfrog 0:173f8aaea8cc 74
wertyfrog 0:173f8aaea8cc 75
wertyfrog 0:173f8aaea8cc 76
wertyfrog 0:173f8aaea8cc 77 int TextLCD::_putc(int value) {
wertyfrog 0:173f8aaea8cc 78 if (value == '\n') {
wertyfrog 0:173f8aaea8cc 79 _column = 0;
wertyfrog 0:173f8aaea8cc 80 _row++;
wertyfrog 0:173f8aaea8cc 81 if (_row >= rows()) {
wertyfrog 0:173f8aaea8cc 82 _row = 0;
wertyfrog 0:173f8aaea8cc 83 }
wertyfrog 0:173f8aaea8cc 84 } else {
wertyfrog 0:173f8aaea8cc 85 character(_column, _row, value);
wertyfrog 0:173f8aaea8cc 86 _column++;
wertyfrog 0:173f8aaea8cc 87 if (_column >= columns()) {
wertyfrog 0:173f8aaea8cc 88 _column = 0;
wertyfrog 0:173f8aaea8cc 89 _row++;
wertyfrog 0:173f8aaea8cc 90 if (_row >= rows()) {
wertyfrog 0:173f8aaea8cc 91 _row = 0;
wertyfrog 0:173f8aaea8cc 92 }
wertyfrog 0:173f8aaea8cc 93 }
wertyfrog 0:173f8aaea8cc 94 }
wertyfrog 0:173f8aaea8cc 95 return value;
wertyfrog 0:173f8aaea8cc 96 }
wertyfrog 0:173f8aaea8cc 97
wertyfrog 0:173f8aaea8cc 98 int TextLCD::_getc() {
wertyfrog 0:173f8aaea8cc 99 int a = address(_column, _row);
wertyfrog 0:173f8aaea8cc 100 writeCommand(a);
wertyfrog 0:173f8aaea8cc 101 return (readData());
wertyfrog 0:173f8aaea8cc 102 }
wertyfrog 0:173f8aaea8cc 103
wertyfrog 0:173f8aaea8cc 104 void TextLCD::writeByte(int value) {
wertyfrog 0:173f8aaea8cc 105 _e = 1;
wertyfrog 0:173f8aaea8cc 106 __nop();
wertyfrog 0:173f8aaea8cc 107 _d = value >> 4;
wertyfrog 0:173f8aaea8cc 108 __nop();
wertyfrog 0:173f8aaea8cc 109 _e = 0;
wertyfrog 0:173f8aaea8cc 110 __nop();
wertyfrog 0:173f8aaea8cc 111 _e = 1;
wertyfrog 0:173f8aaea8cc 112 __nop();
wertyfrog 0:173f8aaea8cc 113 _d = value >> 0;
wertyfrog 0:173f8aaea8cc 114 __nop();
wertyfrog 0:173f8aaea8cc 115 _e = 0;
wertyfrog 0:173f8aaea8cc 116 }
wertyfrog 0:173f8aaea8cc 117
wertyfrog 0:173f8aaea8cc 118 void TextLCD::writeCommand(int command) {
wertyfrog 0:173f8aaea8cc 119 waitBusy(); // check if display is ready
wertyfrog 0:173f8aaea8cc 120 _rs = 0;
wertyfrog 0:173f8aaea8cc 121 writeByte(command);
wertyfrog 0:173f8aaea8cc 122 }
wertyfrog 0:173f8aaea8cc 123
wertyfrog 0:173f8aaea8cc 124 int TextLCD::readData(){
wertyfrog 0:173f8aaea8cc 125 int input;
wertyfrog 0:173f8aaea8cc 126 waitBusy();
wertyfrog 0:173f8aaea8cc 127 _rw = 1;
wertyfrog 0:173f8aaea8cc 128 _rs = 1;
wertyfrog 0:173f8aaea8cc 129 __nop();
wertyfrog 0:173f8aaea8cc 130 _d.input(); // switch Data port to input
wertyfrog 0:173f8aaea8cc 131 _e = 1;
wertyfrog 0:173f8aaea8cc 132 __nop();
wertyfrog 0:173f8aaea8cc 133 input = _d.read() << 4; // high nibble
wertyfrog 0:173f8aaea8cc 134 _e = 0;
wertyfrog 0:173f8aaea8cc 135 __nop();
wertyfrog 0:173f8aaea8cc 136 _e = 1;
wertyfrog 0:173f8aaea8cc 137 __nop();
wertyfrog 0:173f8aaea8cc 138 input = input | _d.read(); // low nibble
wertyfrog 0:173f8aaea8cc 139 _e = 0;
wertyfrog 0:173f8aaea8cc 140 return (input);
wertyfrog 0:173f8aaea8cc 141 }
wertyfrog 0:173f8aaea8cc 142
wertyfrog 0:173f8aaea8cc 143 void TextLCD::waitBusy(){
wertyfrog 0:173f8aaea8cc 144 int input;
wertyfrog 0:173f8aaea8cc 145 _rw = 1;
wertyfrog 0:173f8aaea8cc 146 _rs = 0;
wertyfrog 0:173f8aaea8cc 147 __nop();
wertyfrog 0:173f8aaea8cc 148 _d.input(); // switch Data port to input
wertyfrog 0:173f8aaea8cc 149 do{
wertyfrog 0:173f8aaea8cc 150 _e = 1;
wertyfrog 0:173f8aaea8cc 151 __nop();
wertyfrog 0:173f8aaea8cc 152 input = _d.read();
wertyfrog 0:173f8aaea8cc 153 _e = 0;
wertyfrog 0:173f8aaea8cc 154 __nop();
wertyfrog 0:173f8aaea8cc 155 _e = 1;
wertyfrog 0:173f8aaea8cc 156 __nop();
wertyfrog 0:173f8aaea8cc 157 _e = 0;
wertyfrog 0:173f8aaea8cc 158 }while((0x8 & input) == 0x8); // wait until display is ready
wertyfrog 0:173f8aaea8cc 159 _rw = 0;
wertyfrog 0:173f8aaea8cc 160 _d.output(); // switch port back to output
wertyfrog 0:173f8aaea8cc 161 }
wertyfrog 0:173f8aaea8cc 162
wertyfrog 0:173f8aaea8cc 163 void TextLCD::writeData(int data) {
wertyfrog 0:173f8aaea8cc 164 waitBusy();
wertyfrog 0:173f8aaea8cc 165 _rs = 1;
wertyfrog 0:173f8aaea8cc 166 writeByte(data);
wertyfrog 0:173f8aaea8cc 167 }
wertyfrog 0:173f8aaea8cc 168
wertyfrog 0:173f8aaea8cc 169
wertyfrog 0:173f8aaea8cc 170 // set user defined char
wertyfrog 0:173f8aaea8cc 171 void TextLCD::writeCGRAM(int address, int pattern[8]){
wertyfrog 0:173f8aaea8cc 172 int i;
wertyfrog 0:173f8aaea8cc 173 address = address & 0x07; //max 8 char
wertyfrog 0:173f8aaea8cc 174 for(i=0;i<8;i++){
wertyfrog 0:173f8aaea8cc 175 waitBusy(); // check if display is ready
wertyfrog 0:173f8aaea8cc 176 _rs = 0;
wertyfrog 0:173f8aaea8cc 177 writeByte(0x40 + address * 8 + i);
wertyfrog 0:173f8aaea8cc 178 writeData(pattern[i]);
wertyfrog 0:173f8aaea8cc 179 }
wertyfrog 0:173f8aaea8cc 180 }
wertyfrog 0:173f8aaea8cc 181
wertyfrog 0:173f8aaea8cc 182
wertyfrog 0:173f8aaea8cc 183 int TextLCD::address(int column, int row) {
wertyfrog 0:173f8aaea8cc 184 switch (_type) {
wertyfrog 0:173f8aaea8cc 185 case LCD20x4:
wertyfrog 0:173f8aaea8cc 186 switch (row) {
wertyfrog 0:173f8aaea8cc 187 case 0:
wertyfrog 0:173f8aaea8cc 188 return 0x80 + column;
wertyfrog 0:173f8aaea8cc 189 case 1:
wertyfrog 0:173f8aaea8cc 190 return 0xc0 + column;
wertyfrog 0:173f8aaea8cc 191 case 2:
wertyfrog 0:173f8aaea8cc 192 return 0x94 + column;
wertyfrog 0:173f8aaea8cc 193 case 3:
wertyfrog 0:173f8aaea8cc 194 return 0xd4 + column;
wertyfrog 0:173f8aaea8cc 195 }
wertyfrog 0:173f8aaea8cc 196 case LCD16x2B:
wertyfrog 0:173f8aaea8cc 197 return 0x80 + (row * 40) + column;
wertyfrog 0:173f8aaea8cc 198 case LCD16x2:
wertyfrog 0:173f8aaea8cc 199 case LCD20x2:
wertyfrog 0:173f8aaea8cc 200 case LCD40x2:
wertyfrog 0:173f8aaea8cc 201 default:
wertyfrog 0:173f8aaea8cc 202 return 0x80 + (row * 0x40) + column;
wertyfrog 0:173f8aaea8cc 203 }
wertyfrog 0:173f8aaea8cc 204 }
wertyfrog 0:173f8aaea8cc 205
wertyfrog 0:173f8aaea8cc 206 int TextLCD::columns() {
wertyfrog 0:173f8aaea8cc 207 switch (_type) {
wertyfrog 0:173f8aaea8cc 208 case LCD40x2:
wertyfrog 0:173f8aaea8cc 209 return 40;
wertyfrog 0:173f8aaea8cc 210 case LCD20x4:
wertyfrog 0:173f8aaea8cc 211 case LCD20x2:
wertyfrog 0:173f8aaea8cc 212 return 20;
wertyfrog 0:173f8aaea8cc 213 case LCD16x2:
wertyfrog 0:173f8aaea8cc 214 case LCD16x2B:
wertyfrog 0:173f8aaea8cc 215 default:
wertyfrog 0:173f8aaea8cc 216 return 16;
wertyfrog 0:173f8aaea8cc 217 }
wertyfrog 0:173f8aaea8cc 218 }
wertyfrog 0:173f8aaea8cc 219
wertyfrog 0:173f8aaea8cc 220 int TextLCD::rows() {
wertyfrog 0:173f8aaea8cc 221 switch (_type) {
wertyfrog 0:173f8aaea8cc 222 case LCD20x4:
wertyfrog 0:173f8aaea8cc 223 return 4;
wertyfrog 0:173f8aaea8cc 224 case LCD16x2:
wertyfrog 0:173f8aaea8cc 225 case LCD16x2B:
wertyfrog 0:173f8aaea8cc 226 case LCD20x2:
wertyfrog 0:173f8aaea8cc 227 case LCD40x2:
wertyfrog 0:173f8aaea8cc 228 default:
wertyfrog 0:173f8aaea8cc 229 return 2;
wertyfrog 0:173f8aaea8cc 230 }
wertyfrog 0:173f8aaea8cc 231 }