Oliver Broad / Mbed 2 deprecated LCD_nonblocking_demo

Dependencies:   mbed

Fork of LCD_nonblocking_demo by Oliver Broad

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LCD_nonblocking.cpp Source File

LCD_nonblocking.cpp

00001 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
00002  * Copyright (c) 2007-2010, sford, http://mbed.org
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022 
00023 #include "LCD_nonblocking.h"
00024 #include "mbed.h"
00025 
00026 
00027 
00028 
00029 
00030 TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5,
00031                  PinName d6, PinName d7, LCDType type) : busy(0),_rs(rs),
00032     _e(e), _d(d4, d5, d6, d7),
00033     _type(type) , _column(0),_row(0),
00034     _head(0), _tail(0) {}
00035 void TextLCD::init()
00036 {
00037 
00038     busy=1;
00039     _rs = 1;
00040     _d  = 0;
00041     wait_us(1);
00042     _e  = 0;
00043     _rs = 0;            // command mode
00044     timer.attach_us(this,&TextLCD::init2,15000);
00045 }
00046 void TextLCD::init2()
00047 {
00048     _rs = 0;
00049     _d = 0x3;
00050     _e = 1;
00051     wait_us(1);
00052     _e = 0;
00053     timer.attach_us(this,&TextLCD::init2b,4100);
00054 }
00055 void TextLCD::init2b()
00056 {
00057 
00058     _d = 0x3;
00059     _e = 1;
00060     wait_us(1);
00061     _e = 0;
00062     timer.attach_us(this,&TextLCD::init3,4100);
00063 }
00064 void TextLCD::init3()
00065 {
00066     _d = 0x3;
00067     _e = 1;
00068     wait_us(1);
00069     _e = 0;
00070     timer.attach_us(this,&TextLCD::init4,1000);
00071 }
00072 void TextLCD::init4()
00073 {
00074     _d = 0x2;
00075     _e = 1;
00076     wait_us(1);
00077     _e = 0;
00078     timer.attach_us(this,&TextLCD::init5,60);
00079 }
00080 void TextLCD::init5()
00081 {
00082 
00083     writeByte(0x28); // Function set 001 BW N F - -
00084     timer.attach_us(this,&TextLCD::init6,60);
00085 }
00086 void TextLCD::init6()
00087 {
00088     writeByte(0x0C);
00089     timer.attach_us(this,&TextLCD::init7,60);
00090 }
00091 void TextLCD::init7()
00092 {
00093     writeByte(0x6);  // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
00094     timer.attach_us(this,&TextLCD::init8,60);
00095 }
00096 void TextLCD::init8()
00097 {
00098     writeByte(0x01); // cls, and set cursor to 0
00099     // This command takes 1.64 ms
00100     locate(0, 0);
00101     timer.attach_us(this,&TextLCD::locate_cb,1640);
00102 }
00103 /*
00104 void TextLCD::character(int column, int row, int c)
00105 {
00106     int a = address(column, row);
00107     writeCommand(a);
00108     writeData(c);
00109 }
00110 */
00111 void TextLCD::cls()
00112 {
00113     busy=1;
00114     writeByte(0x01); // cls, and set cursor to 0
00115     // This command takes 1.64 ms
00116     locate(0, 0);
00117     timer.attach_us(this,&TextLCD::locate_cb,1640);
00118 }
00119 
00120 void TextLCD::locate(int column, int row)
00121 {
00122     _column = column;
00123     _row = row;
00124 }
00125 /* this is the general buffered-write callback for writing text to the display
00126  * it normally chains to itself unless a newline occurs in which case it chains to
00127  * locate_cb
00128  * or the buffer runs out in which case it clears busy and does not chain
00129  */
00130 
00131 void TextLCD::callback()
00132 {
00133     if (_tail<_head) {
00134         int value=_queue[_tail++];
00135         if (value == '\n') {
00136             _column = 0;
00137             _row++;
00138             if (_row >= rows()) {
00139                 _row = 0;
00140             }
00141             locate_cb(); // newline isn't printed so go straight to "locate" code
00142         } else {
00143             _rs = 1; // data mode
00144             writeByte(value);
00145             _column++;
00146             if (_column >= columns()) { //if we've reached the end of line then chain to "locate"
00147                                         //otherwise go back to callback
00148                 _column = 0;
00149                 _row++;
00150                 if (_row >= rows()) {
00151                     _row = 0;
00152                 }
00153                 timer.attach_us(this,&TextLCD::locate_cb,60);
00154             } else {
00155                 timer.attach_us(this,&TextLCD::callback,60);
00156             }
00157 
00158         }
00159 
00160     } else {  //if we've run out of text then clear flag
00161         _head=_tail=0;
00162         busy=0;
00163     }
00164 }
00165 
00166 void TextLCD::locate_cb()
00167 {
00168     int a = address(_column, _row);
00169     _rs=0;
00170     writeByte(a);
00171     timer.attach_us(this,&TextLCD::callback,60);
00172 }
00173 
00174 
00175 int TextLCD::_putc(int value)
00176 {
00177     if (_head<40) {
00178         _queue[_head++]=value;
00179     };
00180     if (busy==0) {
00181         busy=1;
00182         locate_cb(); // set cursor position before text
00183         /*
00184         int a = address(_column, _row);
00185         _rs=0;
00186         writeByte(a);
00187         timer.attach_us(this,&TextLCD::callback,60);
00188         */
00189     };
00190     return value;
00191 }
00192 
00193 /*{
00194     if (value == '\n') {
00195         _column = 0;
00196         _row++;
00197         if (_row >= rows()) {
00198             _row = 0;
00199         }
00200     } else {
00201         character(_column, _row, value);
00202         _column++;
00203         if (_column >= columns()) {
00204             _column = 0;
00205             _row++;
00206             if (_row >= rows()) {
00207                 _row = 0;
00208             }
00209         }
00210     }
00211     return value;
00212 }
00213 */
00214 int TextLCD::_getc()
00215 {
00216     return -1;
00217 }
00218 
00219 void TextLCD::writeByte(int value)
00220 {
00221     _d = value >> 4;
00222     _e = 1;
00223     wait_us(1);
00224     _e = 0;
00225     _d = value >> 0;
00226     wait_us(2);
00227     _e = 1;
00228     wait_us(1);  // most instructions take 40us
00229     _e = 0;
00230 }
00231 
00232 void TextLCD::writeCommand(int command)
00233 {
00234     _rs = 0;  //command mode
00235     wait_us(50); // most instructions take 40us
00236     writeByte(command);
00237 }
00238 
00239 void TextLCD::writeData(int data)
00240 {
00241     _rs = 1; // data mode
00242     wait_us(50); // most instructions take 40us
00243     writeByte(data);
00244 }
00245 
00246 int TextLCD::address(int column, int row)
00247 {
00248     switch (_type) {
00249         case LCD20x4:
00250             switch (row) {
00251                 case 0:
00252                     return 0x80 + column;
00253                 case 1:
00254                     return 0xc0 + column;
00255                 case 2:
00256                     return 0x94 + column;
00257                 case 3:
00258                     return 0xd4 + column;
00259             }
00260         case LCD16x2B:
00261             return 0x80 + (row * 40) + column;
00262         case LCD16x2:
00263         case LCD20x2:
00264         default:
00265             return 0x80 + (row * 0x40) + column;
00266     }
00267 }
00268 
00269 int TextLCD::columns()
00270 {
00271     switch (_type) {
00272         case LCD20x4:
00273         case LCD20x2:
00274             return 20;
00275         case LCD16x2:
00276         case LCD16x2B:
00277         default:
00278             return 16;
00279     }
00280 }
00281 
00282 int TextLCD::rows()
00283 {
00284     switch (_type) {
00285         case LCD20x4:
00286             return 4;
00287         case LCD16x2:
00288         case LCD16x2B:
00289         case LCD20x2:
00290         default:
00291             return 2;
00292     }
00293 }