pwcdecode

view pwcdecode.c @ 0:050c04723d37

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 01 Nov 2013 09:40:20 +0200
parents
children 4ea5d2920f89
line source
1 #define F_CLK 1000000
2 #define F_CPU 1000000
4 #include <stdio.h>
5 #include <avr/io.h>
6 #include <avr/interrupt.h>
7 #include <util/delay.h>
9 /* hardware setup
10 * - PORT D: data bits
11 * - PORT C
12 * bit 3: RS
13 * bit 4: R/W
14 * bit 5: E
15 */
16 #define LCD_BUS_WIDTH 8
18 #define BIT_RS 3
19 #define BIT_RW 4
20 #define BIT_E 5
22 #define CMD_CLEAR 1
23 #define CMD_RET (1 << 1)
24 #define CMD_ENTRY_MODE (1 << 2)
25 #define CMD_ONOFF (1 << 3)
26 #define CMD_SHIFT (1 << 4)
27 #define CMD_FUNC (1 << 5)
28 #define CMD_CGRAM_ADDR (1 << 6)
29 #define CMD_DDRAM_ADDR (1 << 7)
31 #define FUNC_BUS_4BIT 0
32 #define FUNC_BUS_8BIT (1 << 4)
33 #define FUNC_LINES_1 0
34 #define FUNC_LINES_2 (1 << 3)
35 #define FUNC_FONT_5x8 0
36 #define FUNC_FONT_5x11 (1 << 2)
38 #define ONOFF_DISP (1 << 2)
39 #define ONOFF_CURSOR (1 << 1)
40 #define ONOFF_CURSOR_POS 1
42 void lcd_init(void);
43 void lcd_clear(void);
44 void lcd_set_cursor_addr(unsigned int addr);
45 void lcd_putchar(char c);
46 void lcd_putstr(const char *str);
47 int lcd_stream_write(char c, FILE *fp);
48 void lcd_wait_busy(void);
49 static void enable(void);
50 static void set_bit(int bit);
51 static void clear_bit(int bit);
52 void delay(int x);
54 #define NSDELAY() asm volatile ("nop")
55 #define DEBUG(i) (PORTB = (1 << (i)))
57 FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE);
59 unsigned int pulse_time;
61 int main(void)
62 {
63 stdout = stderr = &stream_lcd;
65 DDRB = 0; /* set port B as input (bit 0 is used to measure pulse width) */
66 PORTB = 0; /* disable pullups */
68 DDRD = 0xff;
69 DDRC = 0xfe;
70 PORTC = 0; /* disable pullups */
72 lcd_init();
73 lcd_clear();
75 printf("initializing...");
77 TCCR1B |= (1 << ICES1); /* set first capture to occur on a rising edge */
78 TCCR1B = (TCCR1B & 0xf8) | 1; /* no prescaling */
79 TIMSK1 |= (1 << ICIE1); /* enable timer1 input capture interrupt */
80 sei();
82 for(;;) {
83 static int blink = 0;
85 PORTB = blink ? 1 : 0;
86 blink = (blink + 1) & 1;
88 lcd_set_cursor_addr(0);
89 printf("pulse time: %u us ", pulse_time);
90 lcd_set_cursor_addr(64);
91 printf("pos: %u%% ", (pulse_time - 1000) / 10);
92 _delay_ms(100);
93 }
94 return 0;
95 }
97 ISR(TIMER1_CAPT_vect)
98 {
99 static int rising;
101 rising = !rising;
102 if(rising) {
103 /* rising edge: reset the timer */
104 TCNT1 = 0;
105 /* and set a falling edge trigger */
106 TCCR1B &= ~(1 << ICES1);
107 } else {
108 /* falling edge: calculate the time since the last rise */
109 pulse_time = ICR1;
110 /* and set a rising edge trigger */
111 TCCR1B |= 1 << ICES1;
112 }
113 }
115 void lcd_write_byte(unsigned char byte)
116 {
117 #if LCD_BUS_WIDTH == 8
118 DDRD = 0xff;
119 PORTD = byte;
120 #else
121 DDRD = (DDRD & 0xf0) | 0xf;
123 PORTD = (PORTD & 0xf0) | ((byte >> 4) & 0xf);
124 PORTD = (PORTD & 0xf0) | (byte & 0xf);
125 #endif
126 }
128 unsigned char lcd_read_byte(void)
129 {
130 #if LCD_BUS_WIDTH == 8
131 DDRD = 0;
132 PORTD = 0; /* disable pull-ups */
134 return PIND;
135 #else
136 unsigned char byte;
138 DDRD = DDRD & 0xf0;
139 PORTD &= 0xf0; /* disable pull-ups */
141 byte = (PIND & 0xf) << 4;
142 return byte | (PIND & 0xf);
143 #endif
144 }
146 void lcd_init(void)
147 {
148 /* make sure the display has time to boot up */
149 _delay_ms(20);
151 clear_bit(BIT_RW);
153 clear_bit(BIT_E);
154 clear_bit(BIT_RS);
155 #if LCD_BUS_WIDTH == 8
156 lcd_write_byte(CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
157 #else
158 lcd_write_byte(CMD_FUNC | FUNC_BUS_4BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
159 #endif
160 enable();
161 lcd_wait_busy();
163 clear_bit(BIT_RS);
164 lcd_write_byte(CMD_ONOFF | ONOFF_DISP);
165 enable();
166 lcd_wait_busy();
168 clear_bit(BIT_RS);
169 lcd_write_byte(CMD_ENTRY_MODE | (1 << 1));
170 enable();
171 lcd_wait_busy();
172 }
174 void lcd_clear(void)
175 {
176 clear_bit(BIT_RW);
178 clear_bit(BIT_E);
179 clear_bit(BIT_RS);
180 lcd_write_byte(CMD_CLEAR);
181 enable();
182 lcd_wait_busy();
183 }
185 void lcd_set_cursor_addr(unsigned int addr)
186 {
187 clear_bit(BIT_RW);
189 clear_bit(BIT_E);
190 clear_bit(BIT_RS);
191 lcd_write_byte(CMD_DDRAM_ADDR | addr);
192 enable();
193 lcd_wait_busy();
194 }
196 void lcd_putchar(char c)
197 {
198 clear_bit(BIT_RW);
200 set_bit(BIT_RS);
201 lcd_write_byte(c);
202 enable();
203 lcd_wait_busy();
204 }
206 void lcd_putstr(const char *str)
207 {
208 while(*str) {
209 lcd_putchar(*str++);
210 }
211 }
213 int lcd_stream_write(char c, FILE *fp)
214 {
215 /* TODO terminal shit handling */
216 lcd_putchar(c);
217 return 0;
218 }
220 void lcd_wait_busy(void)
221 {
222 unsigned char data;
224 do {
225 NSDELAY();
226 clear_bit(BIT_E);
227 clear_bit(BIT_RS);
228 set_bit(BIT_RW);
229 /*PIND = 0xff;*/
231 NSDELAY();
232 set_bit(BIT_E);
233 NSDELAY();
234 data = lcd_read_byte();
235 clear_bit(BIT_E);
236 clear_bit(BIT_RW);
238 } while(data & (1 << 7));
239 }
241 static void enable(void)
242 {
243 NSDELAY();
244 set_bit(BIT_E);
245 NSDELAY();
246 clear_bit(BIT_E);
247 NSDELAY();
248 }
250 static void set_bit(int bit)
251 {
252 PORTC |= 1 << bit;
253 }
255 static void clear_bit(int bit)
256 {
257 PORTC &= ~(1 << bit);
258 }
261 void delay(int x)
262 {
263 int i, j;
265 while(x-- > 0) {
266 for(i=0; i<90; i++) {
267 for(j=0; j<6; j++) {
268 asm volatile("nop");
269 }
270 }
271 }
272 }