1 /* 2 OrangutanLCD.h - Library for using the LCD on the Orangutan LV, SV, SVP, X2, or 3pi robot. 3 */ 4 5 /* 6 * Copyright (c) 2008-2012 Pololu Corporation. For more information, see 7 * 8 * http://www.pololu.com 9 * http://forum.pololu.com 10 * http://www.pololu.com/docs/0J18 11 * 12 * You may freely modify and share this code, as long as you keep this 13 * notice intact (including the two links above). Licensed under the 14 * Creative Commons BY-SA 3.0 license: 15 * 16 * http://creativecommons.org/licenses/by-sa/3.0/ 17 * 18 * Disclaimer: To the extent permitted by law, Pololu provides this work 19 * without any warranty. It might be defective, in which case you agree 20 * to be responsible for all resulting costs and damages. 21 * 22 * This library incorporates some code originally written by Tom Benedict 23 * as part of Orangutan-Lib and released into the public domain. 24 */ 25 26 #ifndef OrangutanLCD_h 27 #define OrangutanLCD_h 28 29 #include <avr/pgmspace.h> 30 #include <avr/io.h> 31 #include "../OrangutanResources/include/OrangutanModel.h" 32 33 34 #define LCD_LEFT 0 35 #define LCD_RIGHT 1 36 #define CURSOR_SOLID 0 37 #define CURSOR_BLINKING 1 38 39 40 #ifdef _ORANGUTAN_SVP 41 42 #define LCD_DB4 PORTC2 // PC2 43 #define LCD_DB5 PORTC3 // PC3 44 #define LCD_DB6 PORTC4 // PC4 45 #define LCD_DB7 PORTC5 // PC5 46 47 #define LCD_RS_DDR DDRB 48 #define LCD_RS_PORT PORTB 49 #define LCD_E_DDR DDRB 50 #define LCD_E_PORT PORTB 51 #define LCD_RW_DDR DDRB 52 #define LCD_RW_PORT PORTB 53 54 #define LCD_RS PORTB0 55 #define LCD_RW PORTB1 56 #define LCD_E PORTB2 57 58 #define LCD_BF_DDR DDRC 59 #define LCD_BF_PIN PINC 60 #define LCD_BF_PORT PORTC 61 #define LCD_BF_MASK (1 << LCD_DB7) 62 63 // Since we're only using four data lines, and since the pins they're 64 // wired up to don't start with 0, we need to shift them into 65 // position in order to load their values into the LCD. 66 // 67 // PortC: 7 6 5 4 3 2 1 0 68 // LCD Data: 3 2 1 0 69 // 70 // Pass your 4-bit LCD data value to the LCD_PORTC_DATA macro to get 71 // the appropriate PORTC value. You can use the macro as follows: 72 // 73 // PORTC &= ~LCD_PORTC_MASK; 74 // PORTC |= LCD_PORTC_DATA(lcdData); 75 76 #define LCD_PORTC_MASK ((1 << LCD_DB4) | (1 << LCD_DB5) | (1 << LCD_DB6) | (1 << LCD_DB7)) 77 #define LCD_PORTC_DATA(data) ((data & 0x0F) << LCD_DB4) 78 79 80 #elif defined(_ORANGUTAN_X2) 81 82 #define LCD_RS_DDR DDRB 83 #define LCD_RS_PORT PORTB 84 #define LCD_E_DDR DDRB 85 #define LCD_E_PORT PORTB 86 #define LCD_RW_DDR DDRB 87 #define LCD_RW_PORT PORTB 88 89 #define LCD_RS PORTB0 90 #define LCD_RW PORTB1 91 #define LCD_E PORTB3 92 93 #define LCD_BF_DDR DDRC 94 #define LCD_BF_PIN PINC 95 #define LCD_BF_PORT PORTC 96 #define LCD_BF_MASK (1 << PORTC7) 97 98 99 #else 100 101 // On the Orangutan LV-168 and 3pi robot, the LCD control lines are split between 102 // ports B and D: 103 104 #define LCD_DB4 PORTB1 // PB1 105 #define LCD_DB5 PORTB4 // PB4 106 #define LCD_DB6 PORTB5 // PB5 107 #define LCD_DB7 PORTD7 // PD7 108 109 #define LCD_RS_DDR DDRD 110 #define LCD_RS_PORT PORTD 111 #define LCD_E_DDR DDRD 112 #define LCD_E_PORT PORTD 113 #define LCD_RW_DDR DDRB 114 #define LCD_RW_PORT PORTB 115 116 #define LCD_RW PORTB0 117 #define LCD_RS PORTD2 118 #define LCD_E PORTD4 119 120 #define LCD_BF_DDR DDRD 121 #define LCD_BF_PIN PIND 122 #define LCD_BF_PORT PORTD 123 #define LCD_BF_MASK (1 << LCD_DB7) 124 125 // Since we're only using four data lines, and since the pins they're 126 // wired up to don't start with 0, we need to shift them into 127 // position in order to load their values into the LCD. Port B uses 128 // bits 1, 4, and 5. We need to make our data line up like this: 129 // 130 // PortB: 7 6 5 4 3 2 1 0 131 // LCD Data: 2 1 0 132 // 133 // PortD: 7 6 5 4 3 2 1 0 134 // LCD Data: 3 135 // 136 // Pass your 4-bit LCD data value to the LCD_PORTB_DATA and LCD_PORTD_DATA 137 // macros to get the respective PORTB and PORTD values. You can use them 138 // as follows: 139 // 140 // PORTB &= ~LCD_PORTB_MASK; 141 // PORTB |= LCD_PORTB_DATA(lcdData); 142 // PORTD &= ~LCD_PORTD_MASK; 143 // PORTD |= LCD_PORTD_DATA(lcdData); 144 145 #define LCD_PORTB_MASK ((1 << LCD_DB4) | (1 << LCD_DB5) | (1 << LCD_DB6)) 146 #define LCD_PORTD_MASK (1 << LCD_DB7) 147 #define LCD_PORTB_DATA(data) (((data & 0x01) <<1 ) | ((data & 0x06) << 3)) 148 #define LCD_PORTD_DATA(data) ((data & 0x08) << 4) 149 150 151 #endif 152 153 // Commands 154 155 #define LCD_CLEAR 0x01 156 #define LCD_SHOW_BLINK 0x0F 157 #define LCD_SHOW_SOLID 0x0E 158 #define LCD_HIDE 0x0C 159 #define LCD_CURSOR_L 0x10 160 #define LCD_CURSOR_R 0x14 161 #define LCD_SHIFT_L 0x18 162 #define LCD_SHIFT_R 0x1C 163 164 #ifdef __cplusplus 165 166 class OrangutanLCD 167 { 168 public: 169 170 // constructor 171 OrangutanLCD(); 172 173 // Send either data or a command 174 // If we are using a 4-bit interface, only the low nibble is 175 // sent when numSends == 1; otherwise, first the high nibble is sent 176 // and then the low nibble is sent. 177 // If we are using an 8-bit interface, numSends has no effect: the data is 178 // sent via a single 8-bit transfer. 179 static void send(unsigned char data, unsigned char rs, unsigned char numSends); 180 send_cmd(unsigned char cmd)181 static inline void send_cmd(unsigned char cmd) 182 { 183 send(cmd, 0, 2); 184 } 185 send_4bit_cmd(unsigned char cmd)186 static inline void send_4bit_cmd(unsigned char cmd) 187 { 188 send(cmd, 0, 1); 189 } 190 send_data(unsigned char data)191 static inline void send_data(unsigned char data) 192 { 193 send(data, 1, 2); 194 } 195 196 // clears the LCD screen and returns the cursor to position (0, 0) 197 static void clear(); 198 199 // prints an ASCII character at the current LCD cursor position 200 static void print(char character); print(unsigned char character)201 static inline void print(unsigned char character) 202 { 203 print((char)character); 204 }; 205 206 // sends a string to the LCD. You can send a string 207 // longer than 8 characters, but only eight characters show up. 208 // The string is printed from wherever the cursor is, and will 209 // not span lines. (This lets you concatenate print statements.) 210 static void print(const char *str); 211 212 // Sends a PROGMEM string to the LCD. 213 static void printFromProgramSpace(const char *str); 214 215 #ifndef LIB_ORANGUTAN 216 static void printIn(const char *str); // for compatibility with other libs 217 #endif 218 219 // prints signed and unsigned integer values at the current cursor 220 // position and will not span lines. 221 static void print(unsigned long value); 222 static void print(long value); print(unsigned int value)223 static inline void print(unsigned int value) 224 { 225 print((unsigned long)value); 226 }; print(int value)227 static inline void print(int value) 228 { 229 print((long)value); 230 }; 231 232 // prints a two-byte value (word) in hex at your current 233 // cursor location. 234 static void printHex(unsigned int word); 235 236 // prints a one-byte value in hex at your current location 237 static void printHex(unsigned char byte); 238 239 // lcd_binary prints a byte in binary starting at your current cursor location. 240 static void printBinary(unsigned char byte); 241 242 // Go to an (X,Y) location on the LCD. The top line is Y=0, the 243 // leftmost character is X=0. 244 static void gotoXY(unsigned char x, unsigned char y); 245 246 // Shows the cursor as either a BLINKING or SOLID block 247 // cursorType should be either CURSOR_BLINKING or CURSOR_SOLID 248 static void showCursor(unsigned char cursorType); 249 250 // Hide the cursor 251 static void hideCursor(); 252 253 // shifts the cursor LEFT or RIGHT the given number of positions. 254 // direction should be either LCD_LEFT or LCD_RIGHT 255 static void moveCursor(unsigned char direction, unsigned char num); 256 257 // shifts the display LEFT or RIGHT the given number of 258 // positions, delaying for delay_time milliseconds between each shift. 259 // This is what you'd use for a scrolling display. 260 // direction should be either LCD_LEFT or LCD_RIGHT 261 static void scroll(unsigned char direction, unsigned char num, 262 unsigned int delay_time); 263 264 // Loads a custom character into the character memory of the LCD. 265 // The parameter 'number' is a character value between 0 and 7, 266 // which represents the character that will be customized. That is 267 // The pointer 'picture_p' is a pointer to an 8 byte array in 268 // program space containing the picture data. This kind of array 269 // may be defined as follows: 270 // 271 // #include <avr/pgmspace.h> 272 // const char pi[] PROGMEM = { 0b11100, .... } 273 // 274 // The first byte represets row one, which has, in this example, 275 // three black pixels on the left, followed by two clear 276 // pixels. Subsequent values specify the pixels for the remaining 277 // rows of the 5x8 character. 278 // 279 // After loading all desired custom characters, clear() should be 280 // called to reset the LCD. 281 static void loadCustomCharacter(const char *picture_p, unsigned char number); 282 283 // Initializes the LCD library for printf support. After this, 284 // printf will start sending characters to the LCD. 285 static void initPrintf(); // uses default width and height for device 286 static void initPrintf(unsigned char lcdWidth, unsigned char lcdHeight); 287 288 289 private: 290 init()291 static inline void init() 292 { 293 static unsigned char initialized = 0; 294 295 if (!initialized) 296 { 297 initialized = 1; 298 init2(); 299 } 300 } 301 302 // initializes the LCD hardware; this function MUST be called before 303 // the LCD can be used. It is called if needed by the inline 304 // member function init(), which is called if needed by send(). 305 static void init2(); 306 307 // Wait for the busy flag to clear on a 4-bit interface 308 // This is necessarily more complicated than the 8-bit interface 309 // because E must be strobed twice to get the full eight bits 310 // back from the LCD, even though we're only interested in one 311 // of them. 312 static void busyWait(); 313 314 // Send data via the 4- or 8-bit interface. This assumes the busy flag 315 // is clear, that our DDRs are all set, etc. Basically all it does is 316 // line up the bits and send them out the appropriate I/O lines while 317 // strobing the E control line. 318 static void sendData(unsigned char data); 319 320 // prints a hex nibble (half of a hex byte) at 321 // your current cursor location. 322 static void printHexNibble(unsigned char nibble); 323 }; 324 325 extern "C" { 326 #endif // __cplusplus 327 328 void lcd_init_printf(void); 329 void lcd_init_printf_with_dimensions(unsigned char width, unsigned char height); 330 void clear(void); 331 void print(const char *str); 332 void print_from_program_space(const char *str); 333 void print_character(char c); 334 void print_long(long value); 335 void print_unsigned_long(unsigned long value); 336 void print_binary(unsigned char value); 337 void print_hex(unsigned int value); 338 void print_hex_byte(unsigned char value); 339 void lcd_goto_xy(unsigned char col, unsigned char row); 340 void lcd_show_cursor(unsigned char cursorType); 341 void lcd_hide_cursor(void); 342 void lcd_move_cursor(unsigned char direction, unsigned char num); 343 void lcd_scroll(unsigned char direction, unsigned char num, 344 unsigned int delay_time); 345 void lcd_load_custom_character(const char *picture, unsigned char number); 346 347 #ifdef __cplusplus 348 } 349 #endif 350 351 #endif 352 353 354 // Local Variables: ** 355 // mode: C++ ** 356 // c-basic-offset: 4 ** 357 // tab-width: 4 ** 358 // indent-tabs-mode: t ** 359 // end: ** 360