Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2CTextLCD.cpp Source File

I2CTextLCD.cpp

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