Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TextLCD.cpp Source File

TextLCD.cpp

00001 /* draft mbed TextLCD 
00002  * (c) 2007/8, sford
00003  */
00004  
00005 #include "TextLCD.h"
00006 
00007 #include "mbed.h"
00008 
00009 using namespace mbed;
00010 
00011 /*
00012  * useful info found at http://www.a-netz.de/lcd.en.php
00013  *
00014  *
00015  * Initialisation
00016  * ==============
00017  *
00018  * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state
00019  *
00020  * - wait approximately 15 ms so the display is ready to execute commands
00021  * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now). 
00022  * - 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.
00023  * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now.
00024  * - Execute the "clear display" command
00025  *
00026  * Timing
00027  * ======
00028  *
00029  * Nearly all commands transmitted to the display need 40us for execution. 
00030  * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position" 
00031  * These commands need 1.64ms for execution. These timings are valid for all displays working with an 
00032  * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you 
00033  * can use the busy flag to test if the display is ready to accept the next command.
00034  * 
00035  * _e is kept high apart from calling clock
00036  * _rw is kept 0 (write) apart from actions that uyse it differently
00037  * _rs is set by the data/command writes
00038  */
00039 
00040 TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1,  
00041     PinName d2, PinName d3) : _rw(rw), _rs(rs),  
00042     _e(e), _d(d0, d1, d2, d3){
00043 
00044     _rows = 4;
00045     _columns = 20;
00046 
00047     _rw = 0;
00048     _e  = 1;
00049     _rs = 0; // command mode
00050 
00051     // Should theoretically wait 15ms, but most things will be powered up pre-reset
00052     // so i'll disable that for the minute. If implemented, could wait 15ms post reset
00053     // instead
00054     // wait(0.015); 
00055         
00056     // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
00057     for(int i=0; i<3; i++) {
00058         writeNibble(0x3);
00059         wait(0.00164);      // this command takes 1.64ms, so wait for it
00060     }
00061     writeNibble(0x2); // 4-bit mode
00062             
00063     writeCommand(0x28);    // Function set 001 BW N F - -  
00064     writeCommand(0x0C);
00065     writeCommand(0x6);  //  Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
00066     
00067     cls();
00068 }
00069 
00070 int TextLCD::_putc(int value) {
00071     if(value == '\n') {
00072         newline();
00073     } else {
00074         writeData(value);
00075     }
00076     return value;
00077 }
00078 
00079 int TextLCD::_getc() {
00080     return 0;
00081 }
00082 
00083 void TextLCD::newline() {
00084     _column = 0;
00085     _row++;
00086     if(_row >= _rows) {
00087         _row = 0;
00088     }
00089     locate(_column, _row); 
00090 }
00091 
00092 void TextLCD::locate(int column, int row) {
00093     if(column < 0 || column >= _columns || row < 0 || row >= _rows) {
00094         error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows);
00095         return;
00096     }
00097     
00098     _row = row;
00099       _column = column;
00100       int address=0;
00101       // row 0 : 0x0->0x13
00102       // row 1 : 0x40->0x53
00103       // row 2 : 0x14->0x27
00104       // row 3 : 0x54->0x67
00105     
00106       switch (_row) {
00107           case (0) : address = 0x00 + _column;
00108           break;
00109           case (1) : address = 0x40 + _column;
00110           break;
00111           case (2) : address = 0x14 + _column;
00112           break;
00113           case (3) : address = 0x54 + _column;
00114           break;
00115       }        
00116         
00117       address += 0x80;
00118         
00119 //      }
00120 //      else {
00121          // memory starts at 0x80, and is 40 chars long per row
00122 //          address = 0x80 + (_row * 40)  + _column; 
00123 //      }
00124       
00125       writeCommand(address);            
00126 }
00127 
00128 
00129 void TextLCD::rows(int rows) {
00130     _rows = rows;
00131 }
00132 
00133 
00134 void TextLCD::columns(int columns) {
00135     _columns = columns;
00136 }
00137 
00138 
00139 
00140 
00141 void TextLCD::cls() {
00142     writeCommand(0x01); // Clear Display
00143     wait(0.00164f);        // This command takes 1.64 ms
00144       locate(0, 0);
00145 }
00146 
00147 void TextLCD::reset() {
00148     cls();
00149 }
00150 
00151 void TextLCD::clock() {
00152     wait(0.000040f);
00153     _e = 0;
00154     wait(0.000040f);  // most instructions take 40us
00155     _e = 1;    
00156 }
00157 
00158 void TextLCD::writeNibble(int value) {
00159     _d = value;
00160     clock();
00161 }
00162 
00163 void TextLCD::writeByte(int value) {
00164     writeNibble(value >> 4);
00165     writeNibble(value >> 0);
00166 }
00167 
00168 void TextLCD::writeCommand(int command) {
00169     _rs = 0;
00170     writeByte(command);
00171 }
00172 
00173 void TextLCD::writeData(int data) {
00174     _rs = 1;
00175     writeByte(data);
00176     _column++;
00177     if(_column >= _columns) {
00178         newline();
00179     } 
00180 }