Skip to content

Commit 9cc16e6

Browse files
committed
Add lcd library
1 parent 885b0d4 commit 9cc16e6

File tree

3 files changed

+712
-0
lines changed

3 files changed

+712
-0
lines changed

library/lcd/lcd.c

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
/* -----------------------------------------
2+
* G.Raf^engineering
3+
* www.sunriax.at (github.com/0x007e)
4+
* -----------------------------------------
5+
* Platform: Independent
6+
* Hardware: ATTiny406/1606/...
7+
* -----------------------------------------
8+
* Version: 1.0 Release
9+
* Author: G.Raf
10+
* Description:
11+
* Function file for lcd library
12+
* -----------------------------------------
13+
*/
14+
15+
#include "lcd.h"
16+
17+
// +---------------------------------------------------------------+
18+
// | LCD initialization |
19+
// +---------------------------------------------------------------+
20+
void lcd_init(void)
21+
{
22+
// Initialize LCD command and data lines
23+
LCD_PORT_DATA.DIRSET = LCD_RS | LCD_E;
24+
LCD_PORT_CTRL.DIRSET = LCD_DB3 | LCD_DB2 | LCD_DB1 | LCD_DB0;
25+
26+
LCD_PORT_DATA.OUTCLR = LCD_RS | LCD_E;
27+
LCD_PORT_CTRL.OUTCLR = LCD_DB3 | LCD_DB2 | LCD_DB1 | LCD_DB0;
28+
29+
// Wait until LCD has started
30+
_delay_ms(LCD_STARTUP_TIME);
31+
32+
// Setup 4 bit mode & wait function time
33+
lcd_set(LCD_FUNCTION);
34+
_delay_us(LCD_FUNCTION_TIME);
35+
36+
// Setup LCD settings
37+
lcd_cmd(LCD_FUNCTION | LCD_FUNCTION_2LINE); // Setup number of display lines and character font
38+
lcd_cmd(LCD_DISPLAY | LCD_DISPLAY_ON); // | LCD_CURSOR_ON | LCD_BLINK_ON); // Setup display status, display cursor, display cursor blink
39+
lcd_cmd(LCD_ENTRY | LCD_ENTRY_INCREMENT); // Setup display cursor move direction
40+
41+
// Clears entire display
42+
lcd_clear();
43+
}
44+
45+
// +---------------------------------------------------------------+
46+
// | LCD disable function |
47+
// +---------------------------------------------------------------+
48+
void lcd_disable(void)
49+
{
50+
// Disable LCD
51+
LCD_PORT_DATA.OUTCLR = LCD_RS | LCD_E;
52+
LCD_PORT_CTRL.OUTCLR = LCD_DB3 | LCD_DB2 | LCD_DB1 | LCD_DB0;
53+
54+
LCD_PORT_DATA.DIRCLR = LCD_RS | LCD_E;
55+
LCD_PORT_CTRL.DIRCLR = LCD_DB3 | LCD_DB2 | LCD_DB1 | LCD_DB0;
56+
}
57+
58+
// +---------------------------------------------------------------+
59+
// | LCD generate clock |
60+
// +---------------------------------------------------------------+
61+
void lcd_clock(void)
62+
{
63+
LCD_PORT_CTRL.OUTSET = LCD_E; // Enable E (HIGH) @ control port
64+
_delay_us((1000000UL/(F_LCD * 2))); // Wait half of defined clock period
65+
LCD_PORT_CTRL.OUTCLR = LCD_E; // Disable E (LOW) @ control port
66+
_delay_us((1000000UL/(F_LCD * 2))); // Wait half of defined clock period
67+
}
68+
69+
// +---------------------------------------------------------------+
70+
// | LCD set nibble at display databus |
71+
// +---------------------------------------------------------------+
72+
// | Parameter: data(7:4) -> higher nibble data |
73+
// +---------------------------------------------------------------+
74+
void lcd_set(unsigned char data)
75+
{
76+
// Reset LCD data port
77+
LCD_PORT_DATA.OUTCLR = LCD_DB3 | LCD_DB2 | LCD_DB1 | LCD_DB0;
78+
79+
if(data & (1<<7)) // Check if data bit 7 is set
80+
LCD_PORT_DATA.OUTSET = LCD_DB3; // Set data bit 3 @ lcd bus
81+
if(data & (1<<6)) // Check if data bit 6 is set
82+
LCD_PORT_DATA.OUTSET = LCD_DB2; // Set data bit 2 @ lcd bus
83+
if(data & (1<<5)) // Check if data bit 5 is set
84+
LCD_PORT_DATA.OUTSET = LCD_DB1; // Set data bit 1 @ lcd bus
85+
if(data & (1<<4)) // Check if data bit 4 is set
86+
LCD_PORT_DATA.OUTSET = LCD_DB0; // Set data bit 0 @ lcd bus
87+
88+
// Generate a clock period
89+
lcd_clock();
90+
}
91+
92+
// +---------------------------------------------------------------+
93+
// | LCD instruction transfer |
94+
// +---------------------------------------------------------------+
95+
// | Parameter: instruction -> display command |
96+
// +---------------------------------------------------------------+
97+
void lcd_cmd(unsigned char instruction)
98+
{
99+
// Select instruction register
100+
LCD_PORT_CTRL.OUTCLR = LCD_RS;
101+
102+
lcd_set(instruction); // Write high nibble to databus
103+
lcd_set((instruction<<4)); // Write low nibble to databus
104+
105+
// Wait until instruction is accessed on the LCD
106+
_delay_us(LCD_CMD_TIME);
107+
}
108+
109+
// +---------------------------------------------------------------+
110+
// | LCD character transfer |
111+
// +---------------------------------------------------------------+
112+
// | Parameter: data -> ASCII/defined character |
113+
// +---------------------------------------------------------------+
114+
void lcd_char(unsigned char data)
115+
{
116+
// Select data register
117+
LCD_PORT_CTRL.OUTSET = LCD_RS;
118+
119+
lcd_set(data); // Write high nibble to databus
120+
lcd_set((data<<4)); // Write low nibble to databus
121+
122+
// Wait until data is accessed on the LCD
123+
_delay_us(LCD_WRITE_TIME);
124+
}
125+
126+
// +---------------------------------------------------------------+
127+
// | LCD string transfer |
128+
// +---------------------------------------------------------------+
129+
// | Parameter: data (ptr) -> ASCII/ defined character array |
130+
// +---------------------------------------------------------------+
131+
void lcd_string(const char *data)
132+
{
133+
// Wait until \0 escape char is reached
134+
while(*data != LCD_NULL)
135+
{
136+
lcd_char((unsigned char)*data); // Send character
137+
data++; // Increment data
138+
}
139+
}
140+
141+
// +---------------------------------------------------------------+
142+
// | LCD clear screen |
143+
// +---------------------------------------------------------------+
144+
void lcd_clear(void)
145+
{
146+
lcd_cmd(LCD_CLEAR); // Clear the LCD screen
147+
_delay_ms(LCD_RETURN_TIME); // Wait LCD is cleared
148+
}
149+
150+
// +---------------------------------------------------------------+
151+
// | LCD cursor to home position |
152+
// +---------------------------------------------------------------+
153+
void lcd_home(void)
154+
{
155+
lcd_cmd(LCD_HOME); // Return cursor to the start position (0/0)
156+
_delay_ms(LCD_RETURN_TIME); // Wait until CURSOR is at home position
157+
}
158+
159+
// +---------------------------------------------------------------+
160+
// | LCD cursor position |
161+
// +---------------------------------------------------------------+
162+
// | Parameter: x -> cursor to X position |
163+
// | y -> cursor to Y position |
164+
// +---------------------------------------------------------------+
165+
void lcd_cursor(unsigned char x, unsigned char y)
166+
{
167+
// Switch to LCD display line
168+
switch(y)
169+
{
170+
case 0 : lcd_cmd(LCD_START_ADDR + x); break; // Start at display line 0 and column x
171+
case 1 : lcd_cmd(LCD_START_ADDR + 0x40 + x); break; // Start at display line 1 and column x
172+
case 2 : lcd_cmd(LCD_START_ADDR + LCD_COLUMNS * 2 + x); break; // Start at display line 2 and column x
173+
case 3 : lcd_cmd(LCD_START_ADDR + 0x50 + x); break; // Start at display line 3 and column x
174+
default : return; // Return if no LCD display line is set
175+
}
176+
}
177+
178+
// +---------------------------------------------------------------+
179+
// | LCD character to next block |
180+
// +---------------------------------------------------------------+
181+
// | Parameter: shift -> 0 = right |
182+
// | 1 = left |
183+
// +---------------------------------------------------------------+
184+
void lcd_shift(LCD_Shift shift)
185+
{
186+
if(shift == LCD_Right)
187+
lcd_cmd(LCD_SHIFT | LCD_SHIFT_DISPLAY | LCD_SHIFT_RIGHT);
188+
else
189+
lcd_cmd(LCD_SHIFT | LCD_SHIFT_DISPLAY);
190+
191+
_delay_us(LCD_SHIFT_TIME);
192+
}
193+
194+
// +---------------------------------------------------------------+
195+
// | LCD save patterns to RAM |
196+
// +---------------------------------------------------------------+
197+
// | Parameter: address -> pattern ram address |
198+
// | predefined: LCD_CGADDR_CHAR0 - (n) |
199+
// | data (ptr) -> pattern array (5 bit x 7 rows) |
200+
// +---------------------------------------------------------------+
201+
void lcd_pattern(LCD_Char address, const unsigned char *data)
202+
{
203+
// Check if address is greater than max. allowed address
204+
if(address > LCD_CGADDDR_MAX)
205+
return;
206+
207+
lcd_cmd(LCD_CGADDR + (address * 8)); // Setup LCD display CGADDR start address + which character
208+
209+
// Write data to LCD display CGRAM
210+
for(unsigned char i=0; i < 8; i++)
211+
lcd_char(data[i]);
212+
213+
lcd_cmd(LCD_DDADDR); // Setup LCD display DDADDR (HOME position)
214+
}
215+
216+
// +---------------------------------------------------------------+
217+
// | LCD unsigned long to ASCII |
218+
// +---------------------------------------------------------------+
219+
// | Parameter: data -> number to convert |
220+
// | radix -> 2/10/16 |
221+
// | length -> ASCII characters 1 - 10 |
222+
// +---------------------------------------------------------------+
223+
void lcd_ul2ascii(const unsigned long data, LCD_Base base, unsigned char length)
224+
{
225+
// If base is wrong or length is to short/wide return
226+
if((base != 2 && base != 10 && base != 16) || (length < 1 || length > 10))
227+
return;
228+
229+
unsigned char count = 0; // Internal counter for character length
230+
char buffer[(sizeof(unsigned long) * 8 + 1)]; // ASCII buffer 9 digits + \0 escape character
231+
232+
// Convert unsigned long to ASCII
233+
ultoa(data, buffer, base);
234+
235+
// Loop until \0 escape char is reached
236+
for(unsigned char i=0; i < sizeof(buffer); i++)
237+
{
238+
// Check if buffer data is not equal to \0 escape char
239+
if(buffer[i] != LCD_NULL)
240+
count++; // increment data counter
241+
else
242+
break; // exit loop
243+
}
244+
245+
// Check if length is greater than count
246+
if(count < length)
247+
{
248+
// Write spaces to LCD display until position adjustment is done
249+
for(unsigned char i=0; i < (length - count); i++)
250+
{
251+
if(base != 10)
252+
lcd_char('0');
253+
else
254+
lcd_char(LCD_SPACE);
255+
}
256+
}
257+
// Check if length is lower than count
258+
else if(count > length)
259+
{
260+
// Write \0 escape char to the max. length allowed through position adjustment
261+
buffer[length] = LCD_NULL;
262+
}
263+
264+
// Write string to LCD
265+
lcd_string(buffer);
266+
}
267+
268+
// +---------------------------------------------------------------+
269+
// | LCD signed long to ASCII |
270+
// +---------------------------------------------------------------+
271+
// | Parameter: data -> number to convert |
272+
// | radix -> 2/10/16 |
273+
// | length -> ASCII characters 1 - 10 |
274+
// +---------------------------------------------------------------+
275+
void lcd_sl2ascii(const signed long data, LCD_Base base, unsigned char length)
276+
{
277+
// If base is wrong or length is to short/wide return
278+
if((base != 2 && base != 10 && base != 16) || (length < 1 || length > 10))
279+
return;
280+
281+
unsigned char count = 0; // Internal counter for character length
282+
char buffer[(sizeof(long) * 8 + 2)]; // ASCII buffer 10 digits + \0 escape character
283+
284+
// Convert data to ASCII
285+
ltoa(data, buffer, base);
286+
287+
// Loop until \0 escape char is reached
288+
for(unsigned char i=0; i < sizeof(buffer); i++)
289+
{
290+
// Check if buffer data is not equal to \0 escape char
291+
if(buffer[i] != LCD_NULL)
292+
count++; // increment data counter
293+
else
294+
break; // exit loop
295+
}
296+
297+
// Check if length is greater than count
298+
if(count < length)
299+
{
300+
// Write spaces to LCD display until position adjustment is done
301+
for(unsigned char i=0; i < (length - count); i++)
302+
{
303+
if(base != 10)
304+
lcd_char('0');
305+
else
306+
lcd_char(LCD_SPACE);
307+
}
308+
}
309+
// Check if length is lower than count
310+
else if(count > length)
311+
{
312+
// Write \0 escape char to the max. length allowed through position adjustment
313+
buffer[length] = LCD_NULL;
314+
}
315+
316+
if(base == 10)
317+
{
318+
// Write string to LCD
319+
lcd_string(buffer);
320+
}
321+
else
322+
{
323+
if(data < 0)
324+
lcd_string(&buffer[count - length]);
325+
else
326+
lcd_string(buffer);
327+
}
328+
}
329+
330+
// +---------------------------------------------------------------+
331+
// | LCD double to ASCII |
332+
// +---------------------------------------------------------------+
333+
// | Parameter: data -> number to convert |
334+
// | radix -> 2/10/16 |
335+
// | length -> ASCII characters 1 - 10 |
336+
// +---------------------------------------------------------------+
337+
void lcd_d2ascii(const double data, signed char length, unsigned char precision)
338+
{
339+
char buffer[60];
340+
341+
// Convert double to ASCII
342+
if((length > 0) && (length < 60))
343+
dtostrf(data, length, precision, buffer);
344+
else
345+
dtostre(data, buffer, precision, DTOSTR_ALWAYS_SIGN | DTOSTR_UPPERCASE);
346+
347+
// Write string to LCD
348+
lcd_string(buffer);
349+
}

0 commit comments

Comments
 (0)