Olivier Smeesters / ExtTextLCD

Dependents:   DtmfKit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TextLCD.cpp Source File

TextLCD.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 "ext_text_lcd/TextLCD.h"
00024 #include "mbed.h"
00025 
00026 namespace ext_text_lcd {
00027 
00028 namespace {
00029     int makeLcdAddress(const TextLCD::LCDType &type, int column, int row) {
00030         return column + row * 0x40;
00031     }
00032     
00033     int makeLcdAddress40(const TextLCD::LCDType &type, int column, int row) {
00034         return column + row * 40;
00035     }
00036     
00037     int makeLcdAddress4Rows(const TextLCD::LCDType &type, int column, int row) {
00038         return column + (row % 2) * 0x40 + (row / 2) * 20;
00039     }
00040 }
00041 
00042 const TextLCD::LCDType TextLCD::LCD16x2(16, 2, makeLcdAddress);
00043 const TextLCD::LCDType TextLCD::LCD16x2B(16, 2, makeLcdAddress40);
00044 const TextLCD::LCDType TextLCD::LCD20x2(20, 2, makeLcdAddress);
00045 const TextLCD::LCDType TextLCD::LCD20x4(20, 4, makeLcdAddress4Rows);
00046 
00047 TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5,
00048                  PinName d6, PinName d7, const LCDType &type) : 
00049     _rs(rs), _e(e), _output(new BusOutput(d4, d5, d6, d7)),
00050     _type(type)
00051 {
00052     init();
00053 }
00054 
00055 TextLCD::TextLCD(PinName rs, PinName e, PortName dport, std::size_t dlsb, 
00056                  const LCDType &type) :
00057     _rs(rs), _e(e), _output(new PortOutput(dport, dlsb)),
00058     _type(type)
00059 {
00060     init();
00061 }
00062 
00063 void TextLCD::init() {
00064     _e  = 1;
00065     _rs = 0;            // command mode
00066 
00067     wait(0.015);        // Wait 15ms to ensure powered up
00068 
00069     // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
00070     for (int i=0; i<3; i++) {
00071         writeByte(0x3);
00072         wait(0.00164);  // this command takes 1.64ms, so wait for it
00073     }
00074     writeByte(0x2);     // 4-bit mode
00075     wait(0.000040f);    // most instructions take 40us
00076 
00077     writeCommand(0x28); // Function set 001 BW N F - -
00078     writeCommand(0x0C);
00079     writeCommand(0x6);  // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes
00080     cls();
00081 }
00082 
00083 void TextLCD::cls() {
00084     writeCommand(0x01); // cls, and set cursor to 0
00085     wait(0.00164f);     // This command takes 1.64 ms
00086     locate(0, 0);
00087 }
00088 
00089 void TextLCD::locate(int column, int row) {
00090     _column = column;
00091     _row = row;
00092     
00093     int a = address(column, row);
00094     writeCommand(0x80 | a);
00095 }
00096 
00097 int TextLCD::_putc(int value) {
00098     int column = _column;
00099     int row = _row;
00100     if (value == '\n') {
00101         column = 0;
00102         row = _row+1;
00103     } else {
00104         writeData(value);
00105         column++;
00106         if (column < columns()) {
00107             return value;
00108         }
00109         
00110         column = 0;
00111         row++;
00112     }
00113     if (row >= rows()) {
00114         row = 0;
00115     }
00116     locate(column, row);
00117     return value;
00118 }
00119 
00120 int TextLCD::_getc() {
00121     return -1;
00122 }
00123 
00124 void TextLCD::writeByte(int value) {
00125     _output->writeNibble(value >> 4);
00126     wait(0.000040f); // most instructions take 40us
00127     _e = 0;
00128     wait(0.000040f);
00129     _e = 1;
00130     _output->writeNibble(value);
00131     wait(0.000040f);
00132     _e = 0;
00133     wait(0.000040f);  // most instructions take 40us
00134     _e = 1;
00135 }
00136 
00137 void TextLCD::writeCommand(int command) {
00138     _rs = 0;
00139     writeByte(command);
00140 }
00141 
00142 void TextLCD::writeData(int data) {
00143     _rs = 1;
00144     writeByte(data);
00145 }
00146 
00147 void TextLCD::setDisplayControl(DisplayControl d, CursorDisplayControl c, CursorStyle b)
00148 {
00149     writeCommand(0x08 | d | c | b);
00150 }
00151 
00152 void TextLCD::writeToCGMem(unsigned addr, const char *buffer, std::size_t size)
00153 {
00154     writeCommand(0x40 | (addr & 0x3f));
00155     while (size > 0) {
00156         writeData(*buffer);
00157         size--;
00158         buffer++;
00159     }
00160     
00161     locate(_column, _row);
00162 }
00163 
00164 void TextLCD::BusOutput::writeNibble(int value) {
00165     _bus = value; 
00166 }
00167 
00168 void TextLCD::PortOutput::writeNibble(int value) {
00169     _port = value << _shift;
00170 }
00171 
00172 } // ext_text_lcd namespace