Caddy
A 2005 Roborodentia entry with vision and path planning capability
 All Data Structures Files Functions Variables Typedefs Macros Pages
lcd_16x2.c
1 /*
2  * This file is part of Caddy.
3  *
4  * Caddy is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Caddy is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Caddy. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "lcd_16x2.h"
18 #include "timer.h"
19 #include <avr/io.h>
20 #include <stdint.h>
21 
22 // port and pins you will use for control lines
23 #define LCD_PORT PORTC
24 #define LCD_DDR DDRC
25 #define LCD_RS 2
26 #define LCD_RW 0 // not used on the Atmega32 board
27 #define LCD_E 3
28 #define LCD_POUT PORTC
29 #define LCD_PIN PINC
30 #define LCD_DELAY \
31  asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;" \
32  "nop; nop; nop; nop; nop; nop; nop; nop;" \
33  "nop; nop; nop; nop;")
34 
35 // control commands
36 #define LCD_CLR 0 // DB0: clear display
37 #define LCD_HOME 1 // DB1: return to home position
38 #define LCD_ENTRY_MODE 2 // DB2: set entry mode
39 #define LCD_ENTRY_INC 1 // DB1: increment
40 #define LCD_ENTRY_SHIFT 0 // DB2: shift
41 #define LCD_ON_CTRL 3 // DB3: turn lcd/cursor on
42 #define LCD_ON_DISPLAY 2 // DB2: turn display on
43 #define LCD_ON_CURSOR 1 // DB1: turn cursor on
44 #define LCD_ON_BLINK 0 // DB0: blinking cursor
45 #define LCD_MOVE 4 // DB4: move cursor/display
46 #define LCD_MOVE_DISP 3 // DB3: move display (0-> move cursor)
47 #define LCD_MOVE_RIGHT 2 // DB2: move right (0-> left)
48 #define LCD_FUNCTION 5 // DB5: function set
49 #define LCD_FUNCTION_8BIT 4 // DB4: set 8BIT mode (0->4BIT mode)
50 #define LCD_FUNCTION_2LINES 3 // DB3: two lines (0->one line)
51 #define LCD_FUNCTION_10DOTS 2 // DB2: 5x10 font (0->5x7 font)
52 #define LCD_CGRAM 6 // DB6: set CG RAM address
53 #define LCD_DDRAM 7 // DB7: set DD RAM address
54 
58 const uint8_t lcdLineAddr[LCD_LINES] = { 0x00, 0x40 };
59 
60 // Internal functions
61 void lcdWriteInit(uint8_t data);
62 void lcdControlWrite(uint8_t data);
63 void ourLcdControlWrite(uint8_t data);
64 void lcdDataWrite(uint8_t data);
65 void lcdSetCursor(uint8_t data);
66 void lcdWrite(uint8_t data);
67 
68 //Critical Note: you must call timerInit(); before calling lcdInit();
69 void lcdInit_(void)
70 {
71  outb(LCD_DDR, 0x0F);
72  // Turn on LCD
73  cbi(LCD_PORT, LCD_E);
74  delay(20000); //delay 15ms
75 
76  lcdWriteInit(0x30);
77  delay(4500);
78  lcdWriteInit(0x30);
79  timerPause(150);
80  lcdWriteInit(0x30);
81  timerPause(40);
82  lcdWriteInit(0x20);
83  timerPause(40);
84  lcdWriteInit(0x20);
85  timerPause(40);
86  //lcdWriteInit(0xc0);
87  lcdWriteInit(0xa0);
88  timerPause(40);
89  lcdWriteInit(0x00);
90  timerPause(40);
91  lcdWriteInit(0xF0);
92  timerPause(40);
93  lcdWriteInit(0x00);
94  timerPause(40);
95  lcdWriteInit(0x10);
96  timerPause(40);
97  lcdWriteInit(0x00);
98  timerPause(40);
99  lcdWriteInit(0x60);
100  timerPause(40);
101  lcdWriteInit(0x00);
102  timerPause(40);
103  lcdWriteInit(0xF0);
104  timerPause(40);
105 
106  ourLcdControlWrite(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY);
107 }
108 
109 // Used internally
110 void lcdWriteInit(uint8_t data)
111 {
112  cbi(LCD_PORT, LCD_RS);
113  lcdControlWrite(data);
114 }
115 
116 // Used internally
117 void lcdControlWrite(uint8_t data)
118 {
119  // write the control byte to the display controller
120  cbi(LCD_PORT, LCD_RS); // set RS to "control"
121 
122  /*
123  * Set data I/O lines to output (4bit)
124  */
125  outb(LCD_DDR, inb(LCD_DDR)|0xF0); //
126  /* Output data, high 4 bits */
127  outb(LCD_POUT, (inb(LCD_POUT)&0x0F) | (data&0xF0));
128  sbi(LCD_PORT, LCD_E);
129  delay(40);
130  cbi(LCD_PORT, LCD_E);
131  delay(40);
132 }
133 
134 void ourLcdControlWrite(uint8_t data)
135 {
136  // write the control byte to the display controller
137  //lcdBusyWait(); // wait until LCD not busy
138  delay(4500);
139  cbi(LCD_PORT, LCD_RS);
140  // set RS to "control"
141  // 4 bit write
142  sbi(LCD_PORT, LCD_E);
143  // set "E" line
144  outb(LCD_DDR, inb(LCD_DDR)|0xF0);
145  // set data I/O lines to output (4bit)
146  outb(LCD_POUT, (inb(LCD_POUT)&0x0F) | (data&0xF0));
147  // output data, high 4 bits
148  LCD_DELAY;
149  LCD_DELAY;
150  cbi(LCD_PORT, LCD_E); /* clear "E" line */
151  LCD_DELAY;
152  LCD_DELAY;
153  sbi(LCD_PORT, LCD_E); /* set "E" line */
154  outb(LCD_POUT, (inb(LCD_POUT)&0x0F) | (data<<4));
155  // output data, low 4 bits
156  LCD_DELAY;
157  LCD_DELAY;
158  cbi(LCD_PORT, LCD_E); /* clear "E" line */
159 }
160 
161 // Sets the cursor position, 0 = first character
162 void lcdSetCursor(uint8_t data)
163 {
164  cbi(LCD_PORT, LCD_RS);
165  lcdWrite(data | 0x80);
166 }
167 
168 // Prints 1 character to the LCD
169 void lcdDataWrite(uint8_t data)
170 {
171  sbi(LCD_PORT, LCD_RS);
172  // set RS to "data"
173  lcdWrite(data);
174 }
175 
176 // Used internally
177 void lcdWrite(uint8_t data)
178 {
179  // 4 bit write
180  outb(LCD_DDR, inb(LCD_DDR)|0xF0);
181  // set data I/O lines to output (4bit)
182  outb(LCD_POUT, (inb(LCD_POUT)&0x0F) | (data&0xF0));
183  // output data, high 4 bits
184  sbi(LCD_PORT, LCD_E);
185  // set "E" line
186  delay(40);
187  cbi(LCD_PORT, LCD_E);
188  // clear "E" line
189  delay(40);
190 
191  outb(LCD_POUT, (inb(LCD_POUT)&0x0F) | (data<<4));
192  // output data, low 4 bits
193  sbi(LCD_PORT, LCD_E);
194  // set "E" line
195  delay(40);
196  cbi(LCD_PORT, LCD_E);
197  // clear "E" line
198  delay(40);
199 }
200 
201 // Prints a uint8_t to the LCD as 2 hexadecimal characters
202 void lcdPrintHex_(uint8_t data, uint8_t row, uint8_t col)
203 {
204  lcdSetCursor(lcdLineAddr[row] + col);
205 
206  uint8_t temp = ((data & 0xF0) >> 4) + 0x30;
207  if (temp >= 0x3A)
208  {
209  temp += 7;
210  }
211  lcdDataWrite(temp);
212  temp = (data & 0x0F) + 0x30;
213  if (temp >= 0x3A)
214  {
215  temp += 7;
216  }
217  lcdDataWrite(temp);
218 }
219 
220 void lcdPrintDecU08_(uint8_t data, uint8_t row, uint8_t col)
221 {
222  lcdSetCursor(lcdLineAddr[row] + col);
223 
224  uint8_t ones = data % 10;
225  uint8_t tens = (data % 100) / 10;
226  uint8_t hundreds = (data % 1000) / 100;
227  if (hundreds > 0)
228  {
229  lcdDataWrite(hundreds + 0x30);
230  }
231  lcdDataWrite(tens + 0x30);
232  lcdDataWrite(ones + 0x30);
233 }
234 
235 //Prints a int8_t to the LCD with 3-4 characters (possible negative sign)
236 void lcdPrintDecS08_(int8_t data, uint8_t row, uint8_t col)
237 {
238  uint8_t ones = 0;
239  uint8_t tens = 0;
240  uint8_t hundreds = 0;
241 
242  lcdSetCursor(lcdLineAddr[row] + col);
243 
244  if (data < 0)
245  {
246  lcdDataWrite('-');
247  data *= -1;
248  }
249  ones = data % 10;
250  tens = (data % 100) / 10;
251  hundreds = (data % 1000) / 100;
252  lcdDataWrite(hundreds + 0x30);
253  lcdDataWrite(tens + 0x30);
254  lcdDataWrite(ones + 0x30);
255 }
256 
257 void lcdWriteStr_(const char *str, uint8_t row, uint8_t col)
258 {
259  // make sure we don't have a null pointer
260  if (!str)
261  {
262  return;
263  }
264 
265  lcdSetCursor(lcdLineAddr[row] + col);
266 
267  // Print each char one at a time
268  uint8_t i;
269  for (i = 0; (i < LCD_LINE_LENGTH - col) && (str[i] != '\0'); i++)
270  {
271  lcdDataWrite(str[i]);
272  }
273 }