00001 /* 00002 * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com 00003 * MAX3421E USB host controller support 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the authors nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 //this code is heavily borrowed from official Arduino source v.0017 00031 // link to original http://code.google.com/p/arduino/source/browse/trunk/hardware/libraries/LiquidCrystal/LiquidCrystal.cpp 00032 #include "Max_LCD.h" 00033 #include "Max3421e.h" 00034 00035 #include <stdio.h> 00036 #include <string.h> 00037 #include <inttypes.h> 00038 #include "WProgram.h" 00039 00040 // When the display powers up, it is configured as follows: 00041 // 00042 // 1. Display clear 00043 // 2. Function set: 00044 // DL = 1; 8-bit interface data 00045 // N = 0; 1-line display 00046 // F = 0; 5x8 dot character font 00047 // 3. Display on/off control: 00048 // D = 0; Display off 00049 // C = 0; Cursor off 00050 // B = 0; Blinking off 00051 // 4. Entry mode set: 00052 // I/D = 1; Increment by 1 00053 // S = 0; No shift 00054 // 00055 // Note, however, that resetting the Arduino doesn't reset the LCD, so we 00056 // can't assume that it's in that state when a sketch starts 00057 00058 // pin definition and set/clear 00059 00060 #define RS 0x04 // RS pin 00061 #define E 0x08 // E pin 00062 00063 #define SET_RS lcdPins |= RS 00064 #define CLR_RS lcdPins &= ~RS 00065 #define SET_E lcdPins |= E 00066 #define CLR_E lcdPins &= ~E 00067 00068 #define SENDlcdPins() MAX3421E::gpioWr( lcdPins ) 00069 00070 #define LCD_sendcmd(a) { CLR_RS; \ 00071 sendbyte(a); \ 00072 } 00073 00074 #define LCD_sendchar(a) { SET_RS; \ 00075 sendbyte(a); \ 00076 } 00077 00078 static byte lcdPins; //copy of LCD pins 00079 00080 Max_LCD::Max_LCD() 00081 { 00082 lcdPins = 0; 00083 } 00084 00085 00086 void Max_LCD::init() 00087 { 00088 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 00089 00090 // MAX3421E::gpioWr(0x55); 00091 00092 begin(16, 1); 00093 } 00094 00095 void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { 00096 if (lines > 1) { 00097 _displayfunction |= LCD_2LINE; 00098 } 00099 _numlines = lines; 00100 _currline = 0; 00101 00102 // for some 1 line displays you can select a 10 pixel high font 00103 if ((dotsize != 0) && (lines == 1)) { 00104 _displayfunction |= LCD_5x10DOTS; 00105 } 00106 00107 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 00108 // according to datasheet, we need at least 40ms after power rises above 2.7V 00109 // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 00110 delayMicroseconds(50000); 00111 lcdPins = 0x30; 00112 SET_E; 00113 SENDlcdPins(); 00114 CLR_E; 00115 SENDlcdPins(); 00116 delayMicroseconds(10000); // wait min 4.1ms 00117 //second try 00118 SET_E; 00119 SENDlcdPins(); 00120 CLR_E; 00121 SENDlcdPins(); 00122 delayMicroseconds(10000); // wait min 4.1ms 00123 // third go! 00124 SET_E; 00125 SENDlcdPins(); 00126 CLR_E; 00127 SENDlcdPins(); 00128 delayMicroseconds(10000); 00129 // finally, set to 4-bit interface 00130 lcdPins = 0x20; 00131 //SET_RS; 00132 SET_E; 00133 SENDlcdPins(); 00134 //CLR_RS; 00135 CLR_E; 00136 SENDlcdPins(); 00137 delayMicroseconds(10000); 00138 // finally, set # lines, font size, etc. 00139 command(LCD_FUNCTIONSET | _displayfunction); 00140 00141 // turn the display on with no cursor or blinking default 00142 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 00143 display(); 00144 00145 // clear it off 00146 clear(); 00147 00148 // Initialize to default text direction (for romance languages) 00149 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 00150 // set the entry mode 00151 command(LCD_ENTRYMODESET | _displaymode); 00152 } 00153 00154 /********** high level commands, for the user! */ 00155 void Max_LCD::clear() 00156 { 00157 command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 00158 delayMicroseconds(2000); // this command takes a long time! 00159 } 00160 00161 void Max_LCD::home() 00162 { 00163 command(LCD_RETURNHOME); // set cursor position to zero 00164 delayMicroseconds(2000); // this command takes a long time! 00165 } 00166 00167 void Max_LCD::setCursor(uint8_t col, uint8_t row) 00168 { 00169 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 00170 if ( row > _numlines ) { 00171 row = _numlines-1; // we count rows starting w/0 00172 } 00173 00174 command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 00175 } 00176 00177 // Turn the display on/off (quickly) 00178 void Max_LCD::noDisplay() { 00179 _displaycontrol &= ~LCD_DISPLAYON; 00180 command(LCD_DISPLAYCONTROL | _displaycontrol); 00181 } 00182 void Max_LCD::display() { 00183 _displaycontrol |= LCD_DISPLAYON; 00184 command(LCD_DISPLAYCONTROL | _displaycontrol); 00185 } 00186 00187 // Turns the underline cursor on/off 00188 void Max_LCD::noCursor() { 00189 _displaycontrol &= ~LCD_CURSORON; 00190 command(LCD_DISPLAYCONTROL | _displaycontrol); 00191 } 00192 void Max_LCD::cursor() { 00193 _displaycontrol |= LCD_CURSORON; 00194 command(LCD_DISPLAYCONTROL | _displaycontrol); 00195 } 00196 00197 00198 // Turn on and off the blinking cursor 00199 void Max_LCD::noBlink() { 00200 _displaycontrol &= ~LCD_BLINKON; 00201 command(LCD_DISPLAYCONTROL | _displaycontrol); 00202 } 00203 void Max_LCD::blink() { 00204 _displaycontrol |= LCD_BLINKON; 00205 command(LCD_DISPLAYCONTROL | _displaycontrol); 00206 } 00207 00208 // These commands scroll the display without changing the RAM 00209 void Max_LCD::scrollDisplayLeft(void) { 00210 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 00211 } 00212 void Max_LCD::scrollDisplayRight(void) { 00213 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 00214 } 00215 00216 // This is for text that flows Left to Right 00217 void Max_LCD::leftToRight(void) { 00218 _displaymode |= LCD_ENTRYLEFT; 00219 command(LCD_ENTRYMODESET | _displaymode); 00220 } 00221 00222 // This is for text that flows Right to Left 00223 void Max_LCD::rightToLeft(void) { 00224 _displaymode &= ~LCD_ENTRYLEFT; 00225 command(LCD_ENTRYMODESET | _displaymode); 00226 } 00227 00228 // This will 'right justify' text from the cursor 00229 void Max_LCD::autoscroll(void) { 00230 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 00231 command(LCD_ENTRYMODESET | _displaymode); 00232 } 00233 00234 // This will 'left justify' text from the cursor 00235 void Max_LCD::noAutoscroll(void) { 00236 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 00237 command(LCD_ENTRYMODESET | _displaymode); 00238 } 00239 00240 // Allows us to fill the first 8 CGRAM locations 00241 // with custom characters 00242 void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { 00243 location &= 0x7; // we only have 8 locations 0-7 00244 command(LCD_SETCGRAMADDR | (location << 3)); 00245 for (int i=0; i<8; i++) { 00246 write(charmap[i]); 00247 } 00248 } 00249 00250 /*********** mid level commands, for sending data/cmds */ 00251 00252 inline void Max_LCD::command(uint8_t value) { 00253 LCD_sendcmd(value); 00254 delayMicroseconds(100); 00255 } 00256 00257 inline void Max_LCD::write(uint8_t value) { 00258 LCD_sendchar(value); 00259 } 00260 00261 void Max_LCD::sendbyte( uint8_t val ) 00262 { 00263 lcdPins &= 0x0f; //prepare place for the upper nibble 00264 lcdPins |= ( val & 0xf0 ); //copy upper nibble to LCD variable 00265 SET_E; //send 00266 SENDlcdPins(); 00267 delayMicroseconds(2); 00268 CLR_E; 00269 delayMicroseconds(2); 00270 SENDlcdPins(); 00271 lcdPins &= 0x0f; //prepare place for the lower nibble 00272 lcdPins |= ( val << 4 ) & 0xf0; //copy lower nibble to LCD variable 00273 SET_E; //send 00274 SENDlcdPins(); 00275 CLR_E; 00276 SENDlcdPins(); 00277 delayMicroseconds(100); 00278 }