1 /* 2 * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com 3 * MAX3421E USB host controller support 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the authors nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 //this code is heavily borrowed from official Arduino source v.0017 31 // link to original http://code.google.com/p/arduino/source/browse/trunk/hardware/libraries/LiquidCrystal/LiquidCrystal.cpp 32 #include "Max_LCD.h" 33 #include "Max3421e.h" 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <inttypes.h> 38 #include "Arduino.h" 39 40 // When the display powers up, it is configured as follows: 41 // 42 // 1. Display clear 43 // 2. Function set: 44 // DL = 1; 8-bit interface data 45 // N = 0; 1-line display 46 // F = 0; 5x8 dot character font 47 // 3. Display on/off control: 48 // D = 0; Display off 49 // C = 0; Cursor off 50 // B = 0; Blinking off 51 // 4. Entry mode set: 52 // I/D = 1; Increment by 1 53 // S = 0; No shift 54 // 55 // Note, however, that resetting the Arduino doesn't reset the LCD, so we 56 // can't assume that it's in that state when a sketch starts 57 58 // pin definition and set/clear 59 60 #define RS 0x04 // RS pin 61 #define E 0x08 // E pin 62 63 #define SET_RS lcdPins |= RS 64 #define CLR_RS lcdPins &= ~RS 65 #define SET_E lcdPins |= E 66 #define CLR_E lcdPins &= ~E 67 68 #define SENDlcdPins() MAX3421E::gpioWr( lcdPins ) 69 70 #define LCD_sendcmd(a) { CLR_RS; \ 71 sendbyte(a); \ 72 } 73 74 #define LCD_sendchar(a) { SET_RS; \ 75 sendbyte(a); \ 76 } 77 78 static byte lcdPins; //copy of LCD pins 79 80 Max_LCD::Max_LCD() 81 { 82 lcdPins = 0; 83 } 84 85 86 void Max_LCD::init() 87 { 88 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 89 90 // MAX3421E::gpioWr(0x55); 91 92 begin(16, 1); 93 } 94 95 void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { 96 if (lines > 1) { 97 _displayfunction |= LCD_2LINE; 98 } 99 _numlines = lines; 100 _currline = 0; 101 102 // for some 1 line displays you can select a 10 pixel high font 103 if ((dotsize != 0) && (lines == 1)) { 104 _displayfunction |= LCD_5x10DOTS; 105 } 106 107 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 108 // according to datasheet, we need at least 40ms after power rises above 2.7V 109 // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 110 delayMicroseconds(50000); 111 lcdPins = 0x30; 112 SET_E; 113 SENDlcdPins(); 114 CLR_E; 115 SENDlcdPins(); 116 delayMicroseconds(10000); // wait min 4.1ms 117 //second try 118 SET_E; 119 SENDlcdPins(); 120 CLR_E; 121 SENDlcdPins(); 122 delayMicroseconds(10000); // wait min 4.1ms 123 // third go! 124 SET_E; 125 SENDlcdPins(); 126 CLR_E; 127 SENDlcdPins(); 128 delayMicroseconds(10000); 129 // finally, set to 4-bit interface 130 lcdPins = 0x20; 131 //SET_RS; 132 SET_E; 133 SENDlcdPins(); 134 //CLR_RS; 135 CLR_E; 136 SENDlcdPins(); 137 delayMicroseconds(10000); 138 // finally, set # lines, font size, etc. 139 command(LCD_FUNCTIONSET | _displayfunction); 140 141 // turn the display on with no cursor or blinking default 142 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 143 display(); 144 145 // clear it off 146 clear(); 147 148 // Initialize to default text direction (for romance languages) 149 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 150 // set the entry mode 151 command(LCD_ENTRYMODESET | _displaymode); 152 } 153 154 /********** high level commands, for the user! */ 155 void Max_LCD::clear() 156 { 157 command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 158 delayMicroseconds(2000); // this command takes a long time! 159 } 160 161 void Max_LCD::home() 162 { 163 command(LCD_RETURNHOME); // set cursor position to zero 164 delayMicroseconds(2000); // this command takes a long time! 165 } 166 167 void Max_LCD::setCursor(uint8_t col, uint8_t row) 168 { 169 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 170 if ( row > _numlines ) { 171 row = _numlines-1; // we count rows starting w/0 172 } 173 174 command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 175 } 176 177 // Turn the display on/off (quickly) 178 void Max_LCD::noDisplay() { 179 _displaycontrol &= ~LCD_DISPLAYON; 180 command(LCD_DISPLAYCONTROL | _displaycontrol); 181 } 182 void Max_LCD::display() { 183 _displaycontrol |= LCD_DISPLAYON; 184 command(LCD_DISPLAYCONTROL | _displaycontrol); 185 } 186 187 // Turns the underline cursor on/off 188 void Max_LCD::noCursor() { 189 _displaycontrol &= ~LCD_CURSORON; 190 command(LCD_DISPLAYCONTROL | _displaycontrol); 191 } 192 void Max_LCD::cursor() { 193 _displaycontrol |= LCD_CURSORON; 194 command(LCD_DISPLAYCONTROL | _displaycontrol); 195 } 196 197 198 // Turn on and off the blinking cursor 199 void Max_LCD::noBlink() { 200 _displaycontrol &= ~LCD_BLINKON; 201 command(LCD_DISPLAYCONTROL | _displaycontrol); 202 } 203 void Max_LCD::blink() { 204 _displaycontrol |= LCD_BLINKON; 205 command(LCD_DISPLAYCONTROL | _displaycontrol); 206 } 207 208 // These commands scroll the display without changing the RAM 209 void Max_LCD::scrollDisplayLeft(void) { 210 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 211 } 212 void Max_LCD::scrollDisplayRight(void) { 213 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 214 } 215 216 // This is for text that flows Left to Right 217 void Max_LCD::leftToRight(void) { 218 _displaymode |= LCD_ENTRYLEFT; 219 command(LCD_ENTRYMODESET | _displaymode); 220 } 221 222 // This is for text that flows Right to Left 223 void Max_LCD::rightToLeft(void) { 224 _displaymode &= ~LCD_ENTRYLEFT; 225 command(LCD_ENTRYMODESET | _displaymode); 226 } 227 228 // This will 'right justify' text from the cursor 229 void Max_LCD::autoscroll(void) { 230 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 231 command(LCD_ENTRYMODESET | _displaymode); 232 } 233 234 // This will 'left justify' text from the cursor 235 void Max_LCD::noAutoscroll(void) { 236 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 237 command(LCD_ENTRYMODESET | _displaymode); 238 } 239 240 // Allows us to fill the first 8 CGRAM locations 241 // with custom characters 242 void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { 243 location &= 0x7; // we only have 8 locations 0-7 244 command(LCD_SETCGRAMADDR | (location << 3)); 245 for (int i=0; i<8; i++) { 246 write(charmap[i]); 247 } 248 } 249 250 /*********** mid level commands, for sending data/cmds */ 251 252 inline void Max_LCD::command(uint8_t value) { 253 LCD_sendcmd(value); 254 delayMicroseconds(100); 255 } 256 257 inline size_t Max_LCD::write(uint8_t value) { 258 LCD_sendchar(value); 259 } 260 261 void Max_LCD::sendbyte( uint8_t val ) 262 { 263 lcdPins &= 0x0f; //prepare place for the upper nibble 264 lcdPins |= ( val & 0xf0 ); //copy upper nibble to LCD variable 265 SET_E; //send 266 SENDlcdPins(); 267 delayMicroseconds(2); 268 CLR_E; 269 delayMicroseconds(2); 270 SENDlcdPins(); 271 lcdPins &= 0x0f; //prepare place for the lower nibble 272 lcdPins |= ( val << 4 ) & 0xf0; //copy lower nibble to LCD variable 273 SET_E; //send 274 SENDlcdPins(); 275 CLR_E; 276 SENDlcdPins(); 277 delayMicroseconds(100); 278 } 279