pwcdecode

view pwcdecode.c @ 1:4ea5d2920f89

made the timing more accurate
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 01 Nov 2013 21:33:14 +0200
parents 050c04723d37
children
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) | 2; /* /8 prescaling */
79 TIMSK1 |= (1 << ICIE1); /* enable timer1 input capture interrupt */
80 sei();
82 for(;;) {
83 lcd_set_cursor_addr(0);
84 printf("pulse time: %u us ", pulse_time);
85 lcd_set_cursor_addr(64);
86 printf("pos: %u %% ", (pulse_time - 1000) / 10);
87 _delay_ms(100);
88 }
89 return 0;
90 }
92 ISR(TIMER1_CAPT_vect)
93 {
94 static int rising;
95 static unsigned int start_time;
97 rising = !rising;
98 if(rising) {
99 /* start counting ... */
100 start_time = ICR1;
101 /* and set a falling edge trigger */
102 TCCR1B &= ~(1 << ICES1);
103 } else {
104 /* falling edge: calculate the time since the last rise */
105 pulse_time = (ICR1 - start_time) * 8; /* 8x to cancel out prescaling */
106 /* and set a rising edge trigger */
107 TCCR1B |= 1 << ICES1;
109 /* also clear the timer so it won't overflow */
110 TCNT1 = 0;
111 }
112 }
114 void lcd_write_byte(unsigned char byte)
115 {
116 #if LCD_BUS_WIDTH == 8
117 DDRD = 0xff;
118 PORTD = byte;
119 #else
120 DDRD = (DDRD & 0xf0) | 0xf;
122 PORTD = (PORTD & 0xf0) | ((byte >> 4) & 0xf);
123 PORTD = (PORTD & 0xf0) | (byte & 0xf);
124 #endif
125 }
127 unsigned char lcd_read_byte(void)
128 {
129 #if LCD_BUS_WIDTH == 8
130 DDRD = 0;
131 PORTD = 0; /* disable pull-ups */
133 return PIND;
134 #else
135 unsigned char byte;
137 DDRD = DDRD & 0xf0;
138 PORTD &= 0xf0; /* disable pull-ups */
140 byte = (PIND & 0xf) << 4;
141 return byte | (PIND & 0xf);
142 #endif
143 }
145 void lcd_init(void)
146 {
147 /* make sure the display has time to boot up */
148 _delay_ms(20);
150 clear_bit(BIT_RW);
152 clear_bit(BIT_E);
153 clear_bit(BIT_RS);
154 #if LCD_BUS_WIDTH == 8
155 lcd_write_byte(CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
156 #else
157 lcd_write_byte(CMD_FUNC | FUNC_BUS_4BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
158 #endif
159 enable();
160 lcd_wait_busy();
162 clear_bit(BIT_RS);
163 lcd_write_byte(CMD_ONOFF | ONOFF_DISP);
164 enable();
165 lcd_wait_busy();
167 clear_bit(BIT_RS);
168 lcd_write_byte(CMD_ENTRY_MODE | (1 << 1));
169 enable();
170 lcd_wait_busy();
171 }
173 void lcd_clear(void)
174 {
175 clear_bit(BIT_RW);
177 clear_bit(BIT_E);
178 clear_bit(BIT_RS);
179 lcd_write_byte(CMD_CLEAR);
180 enable();
181 lcd_wait_busy();
182 }
184 void lcd_set_cursor_addr(unsigned int addr)
185 {
186 clear_bit(BIT_RW);
188 clear_bit(BIT_E);
189 clear_bit(BIT_RS);
190 lcd_write_byte(CMD_DDRAM_ADDR | addr);
191 enable();
192 lcd_wait_busy();
193 }
195 void lcd_putchar(char c)
196 {
197 clear_bit(BIT_RW);
199 set_bit(BIT_RS);
200 lcd_write_byte(c);
201 enable();
202 lcd_wait_busy();
203 }
205 void lcd_putstr(const char *str)
206 {
207 while(*str) {
208 lcd_putchar(*str++);
209 }
210 }
212 int lcd_stream_write(char c, FILE *fp)
213 {
214 /* TODO terminal shit handling */
215 lcd_putchar(c);
216 return 0;
217 }
219 void lcd_wait_busy(void)
220 {
221 unsigned char data;
223 do {
224 NSDELAY();
225 clear_bit(BIT_E);
226 clear_bit(BIT_RS);
227 set_bit(BIT_RW);
228 /*PIND = 0xff;*/
230 NSDELAY();
231 set_bit(BIT_E);
232 NSDELAY();
233 data = lcd_read_byte();
234 clear_bit(BIT_E);
235 clear_bit(BIT_RW);
237 } while(data & (1 << 7));
238 }
240 static void enable(void)
241 {
242 NSDELAY();
243 set_bit(BIT_E);
244 NSDELAY();
245 clear_bit(BIT_E);
246 NSDELAY();
247 }
249 static void set_bit(int bit)
250 {
251 PORTC |= 1 << bit;
252 }
254 static void clear_bit(int bit)
255 {
256 PORTC &= ~(1 << bit);
257 }
260 void delay(int x)
261 {
262 int i, j;
264 while(x-- > 0) {
265 for(i=0; i<90; i++) {
266 for(j=0; j<6; j++) {
267 asm volatile("nop");
268 }
269 }
270 }
271 }