Demo of LCD modified to use interrupts not delays.

Dependencies:   mbed

Fork of LCD_nonblocking_demo by Oliver Broad

This is an experiment in controlling an LCD from callbacks independently of the main program loop. As it runs from callbacks it is necessary to check if the library is "busy", which is currently indicated by an integer called "busy".

Busy checking should be converted into a method so that the criteria for being "busy" can be changed without changing the API.

As this is rough I have not issued it as a library ... yet.

Also due to my inexperience using the repository manager this is currently listed as a fork of itself. Sorry.

Committer:
oliverb
Date:
Wed Nov 20 12:52:19 2013 +0000
Revision:
3:f18aa98bc9a8
Moved classes out of main

Who changed what in which revision?

UserRevisionLine numberNew contents of line
oliverb 3:f18aa98bc9a8 1 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
oliverb 3:f18aa98bc9a8 2 * Copyright (c) 2007-2010, sford, http://mbed.org
oliverb 3:f18aa98bc9a8 3 *
oliverb 3:f18aa98bc9a8 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
oliverb 3:f18aa98bc9a8 5 * of this software and associated documentation files (the "Software"), to deal
oliverb 3:f18aa98bc9a8 6 * in the Software without restriction, including without limitation the rights
oliverb 3:f18aa98bc9a8 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
oliverb 3:f18aa98bc9a8 8 * copies of the Software, and to permit persons to whom the Software is
oliverb 3:f18aa98bc9a8 9 * furnished to do so, subject to the following conditions:
oliverb 3:f18aa98bc9a8 10 *
oliverb 3:f18aa98bc9a8 11 * The above copyright notice and this permission notice shall be included in
oliverb 3:f18aa98bc9a8 12 * all copies or substantial portions of the Software.
oliverb 3:f18aa98bc9a8 13 *
oliverb 3:f18aa98bc9a8 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
oliverb 3:f18aa98bc9a8 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
oliverb 3:f18aa98bc9a8 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
oliverb 3:f18aa98bc9a8 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
oliverb 3:f18aa98bc9a8 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
oliverb 3:f18aa98bc9a8 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
oliverb 3:f18aa98bc9a8 20 * THE SOFTWARE.
oliverb 3:f18aa98bc9a8 21 */
oliverb 3:f18aa98bc9a8 22
oliverb 3:f18aa98bc9a8 23 #include "LCD_nonblocking.h"
oliverb 3:f18aa98bc9a8 24 #include "mbed.h"
oliverb 3:f18aa98bc9a8 25
oliverb 3:f18aa98bc9a8 26
oliverb 3:f18aa98bc9a8 27
oliverb 3:f18aa98bc9a8 28
oliverb 3:f18aa98bc9a8 29
oliverb 3:f18aa98bc9a8 30 TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5,
oliverb 3:f18aa98bc9a8 31 PinName d6, PinName d7, LCDType type) : busy(0),_rs(rs),
oliverb 3:f18aa98bc9a8 32 _e(e), _d(d4, d5, d6, d7),
oliverb 3:f18aa98bc9a8 33 _type(type) , _column(0),_row(0),
oliverb 3:f18aa98bc9a8 34 _head(0), _tail(0) {}
oliverb 3:f18aa98bc9a8 35 void TextLCD::init()
oliverb 3:f18aa98bc9a8 36 {
oliverb 3:f18aa98bc9a8 37
oliverb 3:f18aa98bc9a8 38 busy=1;
oliverb 3:f18aa98bc9a8 39 _rs = 1;
oliverb 3:f18aa98bc9a8 40 _d = 0;
oliverb 3:f18aa98bc9a8 41 wait_us(1);
oliverb 3:f18aa98bc9a8 42 _e = 0;
oliverb 3:f18aa98bc9a8 43 _rs = 0; // command mode
oliverb 3:f18aa98bc9a8 44 timer.attach_us(this,&TextLCD::init2,15000);
oliverb 3:f18aa98bc9a8 45 }
oliverb 3:f18aa98bc9a8 46 void TextLCD::init2()
oliverb 3:f18aa98bc9a8 47 {
oliverb 3:f18aa98bc9a8 48 _rs = 0;
oliverb 3:f18aa98bc9a8 49 _d = 0x3;
oliverb 3:f18aa98bc9a8 50 _e = 1;
oliverb 3:f18aa98bc9a8 51 wait_us(1);
oliverb 3:f18aa98bc9a8 52 _e = 0;
oliverb 3:f18aa98bc9a8 53 timer.attach_us(this,&TextLCD::init2b,4100);
oliverb 3:f18aa98bc9a8 54 }
oliverb 3:f18aa98bc9a8 55 void TextLCD::init2b()
oliverb 3:f18aa98bc9a8 56 {
oliverb 3:f18aa98bc9a8 57
oliverb 3:f18aa98bc9a8 58 _d = 0x3;
oliverb 3:f18aa98bc9a8 59 _e = 1;
oliverb 3:f18aa98bc9a8 60 wait_us(1);
oliverb 3:f18aa98bc9a8 61 _e = 0;
oliverb 3:f18aa98bc9a8 62 timer.attach_us(this,&TextLCD::init3,4100);
oliverb 3:f18aa98bc9a8 63 }
oliverb 3:f18aa98bc9a8 64 void TextLCD::init3()
oliverb 3:f18aa98bc9a8 65 {
oliverb 3:f18aa98bc9a8 66 _d = 0x3;
oliverb 3:f18aa98bc9a8 67 _e = 1;
oliverb 3:f18aa98bc9a8 68 wait_us(1);
oliverb 3:f18aa98bc9a8 69 _e = 0;
oliverb 3:f18aa98bc9a8 70 timer.attach_us(this,&TextLCD::init4,1000);
oliverb 3:f18aa98bc9a8 71 }
oliverb 3:f18aa98bc9a8 72 void TextLCD::init4()
oliverb 3:f18aa98bc9a8 73 {
oliverb 3:f18aa98bc9a8 74 _d = 0x2;
oliverb 3:f18aa98bc9a8 75 _e = 1;
oliverb 3:f18aa98bc9a8 76 wait_us(1);
oliverb 3:f18aa98bc9a8 77 _e = 0;
oliverb 3:f18aa98bc9a8 78 timer.attach_us(this,&TextLCD::init5,60);
oliverb 3:f18aa98bc9a8 79 }
oliverb 3:f18aa98bc9a8 80 void TextLCD::init5()
oliverb 3:f18aa98bc9a8 81 {
oliverb 3:f18aa98bc9a8 82
oliverb 3:f18aa98bc9a8 83 writeByte(0x28); // Function set 001 BW N F - -
oliverb 3:f18aa98bc9a8 84 timer.attach_us(this,&TextLCD::init6,60);
oliverb 3:f18aa98bc9a8 85 }
oliverb 3:f18aa98bc9a8 86 void TextLCD::init6()
oliverb 3:f18aa98bc9a8 87 {
oliverb 3:f18aa98bc9a8 88 writeByte(0x0C);
oliverb 3:f18aa98bc9a8 89 timer.attach_us(this,&TextLCD::init7,60);
oliverb 3:f18aa98bc9a8 90 }
oliverb 3:f18aa98bc9a8 91 void TextLCD::init7()
oliverb 3:f18aa98bc9a8 92 {
oliverb 3:f18aa98bc9a8 93 writeByte(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
oliverb 3:f18aa98bc9a8 94 timer.attach_us(this,&TextLCD::init8,60);
oliverb 3:f18aa98bc9a8 95 }
oliverb 3:f18aa98bc9a8 96 void TextLCD::init8()
oliverb 3:f18aa98bc9a8 97 {
oliverb 3:f18aa98bc9a8 98 writeByte(0x01); // cls, and set cursor to 0
oliverb 3:f18aa98bc9a8 99 // This command takes 1.64 ms
oliverb 3:f18aa98bc9a8 100 locate(0, 0);
oliverb 3:f18aa98bc9a8 101 timer.attach_us(this,&TextLCD::locate_cb,1640);
oliverb 3:f18aa98bc9a8 102 }
oliverb 3:f18aa98bc9a8 103 /*
oliverb 3:f18aa98bc9a8 104 void TextLCD::character(int column, int row, int c)
oliverb 3:f18aa98bc9a8 105 {
oliverb 3:f18aa98bc9a8 106 int a = address(column, row);
oliverb 3:f18aa98bc9a8 107 writeCommand(a);
oliverb 3:f18aa98bc9a8 108 writeData(c);
oliverb 3:f18aa98bc9a8 109 }
oliverb 3:f18aa98bc9a8 110 */
oliverb 3:f18aa98bc9a8 111 void TextLCD::cls()
oliverb 3:f18aa98bc9a8 112 {
oliverb 3:f18aa98bc9a8 113 busy=1;
oliverb 3:f18aa98bc9a8 114 writeByte(0x01); // cls, and set cursor to 0
oliverb 3:f18aa98bc9a8 115 // This command takes 1.64 ms
oliverb 3:f18aa98bc9a8 116 locate(0, 0);
oliverb 3:f18aa98bc9a8 117 timer.attach_us(this,&TextLCD::locate_cb,1640);
oliverb 3:f18aa98bc9a8 118 }
oliverb 3:f18aa98bc9a8 119
oliverb 3:f18aa98bc9a8 120 void TextLCD::locate(int column, int row)
oliverb 3:f18aa98bc9a8 121 {
oliverb 3:f18aa98bc9a8 122 _column = column;
oliverb 3:f18aa98bc9a8 123 _row = row;
oliverb 3:f18aa98bc9a8 124 }
oliverb 3:f18aa98bc9a8 125 /* this is the general buffered-write callback for writing text to the display
oliverb 3:f18aa98bc9a8 126 * it normally chains to itself unless a newline occurs in which case it chains to
oliverb 3:f18aa98bc9a8 127 * locate_cb
oliverb 3:f18aa98bc9a8 128 * or the buffer runs out in which case it clears busy and does not chain
oliverb 3:f18aa98bc9a8 129 */
oliverb 3:f18aa98bc9a8 130
oliverb 3:f18aa98bc9a8 131 void TextLCD::callback()
oliverb 3:f18aa98bc9a8 132 {
oliverb 3:f18aa98bc9a8 133 if (_tail<_head) {
oliverb 3:f18aa98bc9a8 134 int value=_queue[_tail++];
oliverb 3:f18aa98bc9a8 135 if (value == '\n') {
oliverb 3:f18aa98bc9a8 136 _column = 0;
oliverb 3:f18aa98bc9a8 137 _row++;
oliverb 3:f18aa98bc9a8 138 if (_row >= rows()) {
oliverb 3:f18aa98bc9a8 139 _row = 0;
oliverb 3:f18aa98bc9a8 140 }
oliverb 3:f18aa98bc9a8 141 locate_cb(); // newline isn't printed so go straight to "locate" code
oliverb 3:f18aa98bc9a8 142 } else {
oliverb 3:f18aa98bc9a8 143 _rs = 1; // data mode
oliverb 3:f18aa98bc9a8 144 writeByte(value);
oliverb 3:f18aa98bc9a8 145 _column++;
oliverb 3:f18aa98bc9a8 146 if (_column >= columns()) { //if we've reached the end of line then chain to "locate"
oliverb 3:f18aa98bc9a8 147 //otherwise go back to callback
oliverb 3:f18aa98bc9a8 148 _column = 0;
oliverb 3:f18aa98bc9a8 149 _row++;
oliverb 3:f18aa98bc9a8 150 if (_row >= rows()) {
oliverb 3:f18aa98bc9a8 151 _row = 0;
oliverb 3:f18aa98bc9a8 152 }
oliverb 3:f18aa98bc9a8 153 timer.attach_us(this,&TextLCD::locate_cb,60);
oliverb 3:f18aa98bc9a8 154 } else {
oliverb 3:f18aa98bc9a8 155 timer.attach_us(this,&TextLCD::callback,60);
oliverb 3:f18aa98bc9a8 156 }
oliverb 3:f18aa98bc9a8 157
oliverb 3:f18aa98bc9a8 158 }
oliverb 3:f18aa98bc9a8 159
oliverb 3:f18aa98bc9a8 160 } else { //if we've run out of text then clear flag
oliverb 3:f18aa98bc9a8 161 _head=_tail=0;
oliverb 3:f18aa98bc9a8 162 busy=0;
oliverb 3:f18aa98bc9a8 163 }
oliverb 3:f18aa98bc9a8 164 }
oliverb 3:f18aa98bc9a8 165
oliverb 3:f18aa98bc9a8 166 void TextLCD::locate_cb()
oliverb 3:f18aa98bc9a8 167 {
oliverb 3:f18aa98bc9a8 168 int a = address(_column, _row);
oliverb 3:f18aa98bc9a8 169 _rs=0;
oliverb 3:f18aa98bc9a8 170 writeByte(a);
oliverb 3:f18aa98bc9a8 171 timer.attach_us(this,&TextLCD::callback,60);
oliverb 3:f18aa98bc9a8 172 }
oliverb 3:f18aa98bc9a8 173
oliverb 3:f18aa98bc9a8 174
oliverb 3:f18aa98bc9a8 175 int TextLCD::_putc(int value)
oliverb 3:f18aa98bc9a8 176 {
oliverb 3:f18aa98bc9a8 177 if (_head<40) {
oliverb 3:f18aa98bc9a8 178 _queue[_head++]=value;
oliverb 3:f18aa98bc9a8 179 };
oliverb 3:f18aa98bc9a8 180 if (busy==0) {
oliverb 3:f18aa98bc9a8 181 busy=1;
oliverb 3:f18aa98bc9a8 182 locate_cb(); // set cursor position before text
oliverb 3:f18aa98bc9a8 183 /*
oliverb 3:f18aa98bc9a8 184 int a = address(_column, _row);
oliverb 3:f18aa98bc9a8 185 _rs=0;
oliverb 3:f18aa98bc9a8 186 writeByte(a);
oliverb 3:f18aa98bc9a8 187 timer.attach_us(this,&TextLCD::callback,60);
oliverb 3:f18aa98bc9a8 188 */
oliverb 3:f18aa98bc9a8 189 };
oliverb 3:f18aa98bc9a8 190 return value;
oliverb 3:f18aa98bc9a8 191 }
oliverb 3:f18aa98bc9a8 192
oliverb 3:f18aa98bc9a8 193 /*{
oliverb 3:f18aa98bc9a8 194 if (value == '\n') {
oliverb 3:f18aa98bc9a8 195 _column = 0;
oliverb 3:f18aa98bc9a8 196 _row++;
oliverb 3:f18aa98bc9a8 197 if (_row >= rows()) {
oliverb 3:f18aa98bc9a8 198 _row = 0;
oliverb 3:f18aa98bc9a8 199 }
oliverb 3:f18aa98bc9a8 200 } else {
oliverb 3:f18aa98bc9a8 201 character(_column, _row, value);
oliverb 3:f18aa98bc9a8 202 _column++;
oliverb 3:f18aa98bc9a8 203 if (_column >= columns()) {
oliverb 3:f18aa98bc9a8 204 _column = 0;
oliverb 3:f18aa98bc9a8 205 _row++;
oliverb 3:f18aa98bc9a8 206 if (_row >= rows()) {
oliverb 3:f18aa98bc9a8 207 _row = 0;
oliverb 3:f18aa98bc9a8 208 }
oliverb 3:f18aa98bc9a8 209 }
oliverb 3:f18aa98bc9a8 210 }
oliverb 3:f18aa98bc9a8 211 return value;
oliverb 3:f18aa98bc9a8 212 }
oliverb 3:f18aa98bc9a8 213 */
oliverb 3:f18aa98bc9a8 214 int TextLCD::_getc()
oliverb 3:f18aa98bc9a8 215 {
oliverb 3:f18aa98bc9a8 216 return -1;
oliverb 3:f18aa98bc9a8 217 }
oliverb 3:f18aa98bc9a8 218
oliverb 3:f18aa98bc9a8 219 void TextLCD::writeByte(int value)
oliverb 3:f18aa98bc9a8 220 {
oliverb 3:f18aa98bc9a8 221 _d = value >> 4;
oliverb 3:f18aa98bc9a8 222 _e = 1;
oliverb 3:f18aa98bc9a8 223 wait_us(1);
oliverb 3:f18aa98bc9a8 224 _e = 0;
oliverb 3:f18aa98bc9a8 225 _d = value >> 0;
oliverb 3:f18aa98bc9a8 226 wait_us(2);
oliverb 3:f18aa98bc9a8 227 _e = 1;
oliverb 3:f18aa98bc9a8 228 wait_us(1); // most instructions take 40us
oliverb 3:f18aa98bc9a8 229 _e = 0;
oliverb 3:f18aa98bc9a8 230 }
oliverb 3:f18aa98bc9a8 231
oliverb 3:f18aa98bc9a8 232 void TextLCD::writeCommand(int command)
oliverb 3:f18aa98bc9a8 233 {
oliverb 3:f18aa98bc9a8 234 _rs = 0; //command mode
oliverb 3:f18aa98bc9a8 235 wait_us(50); // most instructions take 40us
oliverb 3:f18aa98bc9a8 236 writeByte(command);
oliverb 3:f18aa98bc9a8 237 }
oliverb 3:f18aa98bc9a8 238
oliverb 3:f18aa98bc9a8 239 void TextLCD::writeData(int data)
oliverb 3:f18aa98bc9a8 240 {
oliverb 3:f18aa98bc9a8 241 _rs = 1; // data mode
oliverb 3:f18aa98bc9a8 242 wait_us(50); // most instructions take 40us
oliverb 3:f18aa98bc9a8 243 writeByte(data);
oliverb 3:f18aa98bc9a8 244 }
oliverb 3:f18aa98bc9a8 245
oliverb 3:f18aa98bc9a8 246 int TextLCD::address(int column, int row)
oliverb 3:f18aa98bc9a8 247 {
oliverb 3:f18aa98bc9a8 248 switch (_type) {
oliverb 3:f18aa98bc9a8 249 case LCD20x4:
oliverb 3:f18aa98bc9a8 250 switch (row) {
oliverb 3:f18aa98bc9a8 251 case 0:
oliverb 3:f18aa98bc9a8 252 return 0x80 + column;
oliverb 3:f18aa98bc9a8 253 case 1:
oliverb 3:f18aa98bc9a8 254 return 0xc0 + column;
oliverb 3:f18aa98bc9a8 255 case 2:
oliverb 3:f18aa98bc9a8 256 return 0x94 + column;
oliverb 3:f18aa98bc9a8 257 case 3:
oliverb 3:f18aa98bc9a8 258 return 0xd4 + column;
oliverb 3:f18aa98bc9a8 259 }
oliverb 3:f18aa98bc9a8 260 case LCD16x2B:
oliverb 3:f18aa98bc9a8 261 return 0x80 + (row * 40) + column;
oliverb 3:f18aa98bc9a8 262 case LCD16x2:
oliverb 3:f18aa98bc9a8 263 case LCD20x2:
oliverb 3:f18aa98bc9a8 264 default:
oliverb 3:f18aa98bc9a8 265 return 0x80 + (row * 0x40) + column;
oliverb 3:f18aa98bc9a8 266 }
oliverb 3:f18aa98bc9a8 267 }
oliverb 3:f18aa98bc9a8 268
oliverb 3:f18aa98bc9a8 269 int TextLCD::columns()
oliverb 3:f18aa98bc9a8 270 {
oliverb 3:f18aa98bc9a8 271 switch (_type) {
oliverb 3:f18aa98bc9a8 272 case LCD20x4:
oliverb 3:f18aa98bc9a8 273 case LCD20x2:
oliverb 3:f18aa98bc9a8 274 return 20;
oliverb 3:f18aa98bc9a8 275 case LCD16x2:
oliverb 3:f18aa98bc9a8 276 case LCD16x2B:
oliverb 3:f18aa98bc9a8 277 default:
oliverb 3:f18aa98bc9a8 278 return 16;
oliverb 3:f18aa98bc9a8 279 }
oliverb 3:f18aa98bc9a8 280 }
oliverb 3:f18aa98bc9a8 281
oliverb 3:f18aa98bc9a8 282 int TextLCD::rows()
oliverb 3:f18aa98bc9a8 283 {
oliverb 3:f18aa98bc9a8 284 switch (_type) {
oliverb 3:f18aa98bc9a8 285 case LCD20x4:
oliverb 3:f18aa98bc9a8 286 return 4;
oliverb 3:f18aa98bc9a8 287 case LCD16x2:
oliverb 3:f18aa98bc9a8 288 case LCD16x2B:
oliverb 3:f18aa98bc9a8 289 case LCD20x2:
oliverb 3:f18aa98bc9a8 290 default:
oliverb 3:f18aa98bc9a8 291 return 2;
oliverb 3:f18aa98bc9a8 292 }
oliverb 3:f18aa98bc9a8 293 }