fremoclock  1_3A01
FREMO Clock - Software for UTG
lcd.c
Go to the documentation of this file.
1 
19 #include <stdint.h> // typedef uint8_t
20 #include <string.h> // memset(), strlen()
21 #include <stdlib.h> // utoa()
22 #include <avr/io.h> // DDRC, PORTC, DDRD, PORTD
23 #include <avr/pgmspace.h> // pgm_read_byte()
24 #include <compat/deprecated.h> // cbi(), inp(), outb(), sbi()
25 
26 #include "sysdef.h" // #define BOARD_LOCO_DEV, BOARD_PROTO_48, BOARD_PROTO_128
27 #include "lcd.h"
28 
29 /* [BA040321] added ifdef for different PCB. Value defined in sysdef.h */
30 #if defined BOARD_LOCO_DEV //EmbeddedLocoNet
31 #define LCD_DATA_PORT PORTC
32 #define LCD_DATA_DDR DDRC
34 #define LCD_DATA_D4_PIN 1
35 #define LCD_DATA_D5_PIN 0
36 #define LCD_DATA_D6_PIN 3
37 #define LCD_DATA_D7_PIN 2
38 
39 #define LCD_RS_PORT PORTD
40 #define LCD_RS_DDR DDRD
41 #define LCD_RS_PIN 5
42 
43 #define LCD_E_PORT PORTD
44 #define LCD_E_DDR DDRD
45 #define LCD_E_PIN 4
46 
47 #elif defined BOARD_PROTO_128 //ProtoBoardMega128
48 #define LCD_DATA_PORT PORTC
49 #define LCD_DATA_DDR DDRC
51 #define LCD_DATA_D4_PIN 0
52 #define LCD_DATA_D5_PIN 1
53 #define LCD_DATA_D6_PIN 2
54 #define LCD_DATA_D7_PIN 3
55 
56 #define LCD_RS_PORT PORTC
57 #define LCD_RS_DDR DDRC
58 #define LCD_RS_PIN 5
59 
60 #define LCD_E_PORT PORTC
61 #define LCD_E_DDR DDRC
62 #define LCD_E_PIN 4
63 
64 #elif defined BOARD_PROTO_48 //ProtoBoardMega48
65 #define LCD_DATA_PORT PORTD
66 #define LCD_DATA_DDR DDRD
68 #define LCD_DATA_D4_PIN 4
69 #define LCD_DATA_D5_PIN 5
70 #define LCD_DATA_D6_PIN 6
71 #define LCD_DATA_D7_PIN 7
72 
73 #define LCD_RS_PORT PORTD
74 #define LCD_RS_DDR DDRD
75 #define LCD_RS_PIN 2
76 
77 #define LCD_E_PORT PORTD
78 #define LCD_E_DDR DDRD
79 #define LCD_E_PIN 3
80 
81 
82 #else //No Board defined (Error)
83 # warning "Board not defined"
84 #endif //Boardtype
85 
86 /* instruction register bit positions */
87 #define LCD_CLR 0
88 #define LCD_HOME 1
89 #define LCD_ENTRY_MODE 2
90 #define LCD_ENTRY_INC 1
91 #define LCD_ENTRY_SHIFT 2
92 #define LCD_ON 3
93 #define LCD_ON_DISPLAY 2
94 #define LCD_ON_CURSOR 1
95 #define LCD_ON_BLINK 0
96 #define LCD_MOVE 4
97 #define LCD_MOVE_DISP 3
98 #define LCD_MOVE_RIGHT 2
99 #define LCD_FUNCTION 5
100 #define LCD_FUNCTION_8BIT 4
101 #define LCD_FUNCTION_2LINES 3
102 #define LCD_FUNCTION_10DOTS 2
103 #define LCD_CGRAM 6
104 #define LCD_DDRAM 7
105 #define LCD_BUSY 7
107 /* set entry mode: display shift on/off, dec/inc cursor move direction */
108 #define LCD_ENTRY_DEC 0x04
109 #define LCD_ENTRY_DEC_SHIFT 0x05
110 #define LCD_ENTRY_INC_ 0x06
111 #define LCD_ENTRY_INC_SHIFT 0x07
113 /* move cursor/shift display */
114 #define LCD_MOVE_CURSOR_LEFT 0x10
115 #define LCD_MOVE_CURSOR_RIGHT 0x14
116 #define LCD_MOVE_DISP_LEFT 0x18
117 #define LCD_MOVE_DISP_RIGHT 0x1C
119 /* function set: set interface data length and number of display lines */
120 #define LCD_FUNCTION_4BIT_1LINE 0x20
121 #define LCD_FUNCTION_4BIT_2LINES 0x28
122 #define LCD_FUNCTION_8BIT_1LINE 0x30
123 #define LCD_FUNCTION_8BIT_2LINES 0x38
125 #define LCD_START_LINE1 0x00
126 #define LCD_START_LINE2 0x40
127 #define LCD_START_LINE3 0x10
128 #define LCD_START_LINE4 0x50
130 #define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
131 
132 #define LCD_STROBE() (sbi(LCD_E_PORT, LCD_E_PIN), cbi(LCD_E_PORT, LCD_E_PIN))
133 #define LCD_DATA_BITS (_BV(LCD_DATA_D7_PIN) | _BV(LCD_DATA_D6_PIN) | _BV(LCD_DATA_D5_PIN) | _BV(LCD_DATA_D4_PIN))
134 
135 #define TIME_S1_MS ( 1*(F_CPU/4000) )
136 #define delay_us(us) delay_short( ((TIME_S1_MS*(us))/1000) )
137 
138 static void delay_short(uint16_t number_of_loops)
139 {
140  /* 4 cpu cycles per loop + 12 cycles overhead when a constant is passed. */
141  __asm__ volatile ( "cp %A0,__zero_reg__ \n\t" \
142  "cpc %B0,__zero_reg__ \n\t" \
143  "breq L_EXIT_%= \n\t" \
144  "L_%=: \n\t" \
145  "sbiw r24,1 \n\t" \
146  "brne L_%= \n\t" \
147  "L_EXIT_%=: \n\t" \
148  : /* NO OUTPUT */ \
149  : "w" (number_of_loops) \
150  );
151 }
152 
157 static void lcd_write(uint8_t c)
158 {
159  uint8_t dataBits;
160 
161  dataBits = LCD_DATA_PORT & ~LCD_DATA_BITS;
162  if (c & 0x80) dataBits |= _BV(LCD_DATA_D7_PIN);
163  if (c & 0x40) dataBits |= _BV(LCD_DATA_D6_PIN);
164  if (c & 0x20) dataBits |= _BV(LCD_DATA_D5_PIN);
165  if (c & 0x10) dataBits |= _BV(LCD_DATA_D4_PIN);
166  LCD_DATA_PORT = dataBits;
167  LCD_STROBE();
168 
169  dataBits &= ~LCD_DATA_BITS;
170  if (c & 0x08) dataBits |= _BV(LCD_DATA_D7_PIN);
171  if (c & 0x04) dataBits |= _BV(LCD_DATA_D6_PIN);
172  if (c & 0x02) dataBits |= _BV(LCD_DATA_D5_PIN);
173  if (c & 0x01) dataBits |= _BV(LCD_DATA_D4_PIN);
174  LCD_DATA_PORT = dataBits;
175  LCD_STROBE();
176  delay_us(160);
177 }
178 
179 void lcd_clear(void)
180 {
181  cbi(LCD_RS_PORT, LCD_RS_PIN);
182  lcd_write(0x1);
183  delay_us(4100);
184 }
185 
186 void lcd_puts(const char * s)
187 {
188  sbi(LCD_RS_PORT, LCD_RS_PIN);
189  while (*s) lcd_write( (uint8_t)(*s++) );
190 }
191 
192 void lcd_puts_P(const char * s)
193 {
194  char c;
195  sbi(LCD_RS_PORT, LCD_RS_PIN);
196 
197  for (c = pgm_read_byte(s); c; ++s, c = pgm_read_byte(s))
198  {
199  lcd_write( (uint8_t)c );
200  }
201  //while(*s) lcd_write(*s++);
202 }
203 
204 void lcd_putc(char c)
205 {
206  sbi(LCD_RS_PORT, LCD_RS_PIN);
207  lcd_write( (uint8_t)c );
208 }
209 
210 void lcd_goto(uint8_t x, uint8_t y)
211 {
212  cbi(LCD_RS_PORT, LCD_RS_PIN);
213 
214  if (y == 0) { x += LCD_START_LINE1; }
215  else if (y == 1) { x += LCD_START_LINE2; }
216  else if (y == 2) { x += LCD_START_LINE3; }
217  else { x += LCD_START_LINE4; }
218 
219  lcd_write(_BV(LCD_DDRAM) | x);
220 }
221 
222 void lcd_clrxy(uint8_t x, uint8_t y, uint8_t count)
223 {
224  lcd_goto(x, y);
225 
226  while (count--)
227  lcd_putc(' ');
228 
229  lcd_goto(x, y);
230 }
231 
232 void lcd_word(uint16_t value, uint8_t width)
233 {
234  /*unsigned */char outstr[11];
235  uint8_t len;
236 
237  memset(outstr, ' ', 11);
238 
239  len = strlen(utoa(value, outstr + 5, 10));
240 
241  lcd_puts(outstr + len + 5 - width);
242 }
243 
245 {
246  sbi(LCD_RS_DDR, LCD_RS_PIN);
247  sbi(LCD_E_DDR, LCD_E_PIN);
248  LCD_DATA_DDR |= LCD_DATA_BITS ;
249  cbi(LCD_RS_PORT, LCD_RS_PIN);
250  cbi(LCD_E_PORT, LCD_E_PIN);
251 
252  // power on delay
253  delay_us(16000);
254 
255  // Initially configure for 8 bit mode
256  sbi(LCD_DATA_PORT, LCD_DATA_D4_PIN);
257  sbi(LCD_DATA_PORT, LCD_DATA_D5_PIN);
258  LCD_STROBE();
259  delay_us(5000);
260 
261  // Repeat last command
262  LCD_STROBE();
263  delay_us(160);
264 
265  // Repeat last command a third time
266  LCD_STROBE();
267  delay_us(160);
268 
269  // Now configure for 4 bit mode
270  cbi(LCD_DATA_PORT, LCD_DATA_D4_PIN);
271  LCD_STROBE();
272  delay_us(160);
273 
276  lcd_clear();
278 
279  // entry mode advance cursor
281 
282  // set passed display attributes
283  lcd_write(dispAttr);
284 }
#define LCD_START_LINE3
DDRAM address of first char of line 3.
Definition: lcd.c:127
#define LCD_DDRAM
DB7: set DD RAM address.
Definition: lcd.c:104
#define LCD_MODE_DEFAULT
Definition: lcd.c:130
#define LCD_START_LINE1
DDRAM address of first char of line 1.
Definition: lcd.c:125
display off
Definition: lcd.h:27
void lcd_puts(const char *s)
Write a string of characters to the LCD.
Definition: lcd.c:186
#define LCD_DATA_BITS
Definition: lcd.c:133
#define LCD_START_LINE4
DDRAM address of first char of line 4.
Definition: lcd.c:128
void lcd_clear(void)
Clear and home the LCD.
Definition: lcd.c:179
void lcd_goto(uint8_t x, uint8_t y)
Go to the specified position.
Definition: lcd.c:210
static void delay_short(uint16_t number_of_loops)
Definition: lcd.c:138
lcdDisplayMode_t
display on/off, cursor on/off, blinking char at cursor position
Definition: lcd.h:26
void lcd_puts_P(const char *s)
Write a string from progmem of chars to the LCD.
Definition: lcd.c:192
void lcd_word(uint16_t value, uint8_t width)
Write numeric value to the LCD.
Definition: lcd.c:232
static void lcd_write(uint8_t c)
Write a byte to the LCD in 4 bit mode.
Definition: lcd.c:157
#define LCD_ENTRY_INC_
display shift off, inc cursor move dir
Definition: lcd.c:110
#define LCD_START_LINE2
DDRAM address of first char of line 2.
Definition: lcd.c:126
LCD interface header file.
System wide Definitions for FREMO Clock.
#define delay_us(us)
Definition: lcd.c:136
#define LCD_STROBE()
Definition: lcd.c:132
void lcd_init(lcdDisplayMode_t dispAttr)
Initialize the LCD - call before anything else.
Definition: lcd.c:244
#define LCD_FUNCTION_4BIT_2LINES
4-bit interface, dual line, 5x7 dots
Definition: lcd.c:121
void lcd_putc(char c)
Write a character to the LCD.
Definition: lcd.c:204
void lcd_clrxy(uint8_t x, uint8_t y, uint8_t count)
Clear count characters starting at position (x,y).
Definition: lcd.c:222