voltmeter
view voltmeter.c @ 1:40b150fedb0e
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 28 Jan 2013 09:52:15 +0200 |
parents | d26d73ef2db7 |
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 0: RS
13 * bit 1: R/W
14 * bit 2: 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 setup_adc(void);
43 long read_adc(void);
45 void lcd_init(void);
46 void lcd_clear(void);
47 void lcd_set_cursor_addr(unsigned int addr);
48 void lcd_putchar(char c);
49 void lcd_putstr(const char *str);
50 int lcd_stream_write(char c, FILE *fp);
51 void lcd_wait_busy(void);
52 static void enable(void);
53 static void set_bit(int bit);
54 static void clear_bit(int bit);
55 void delay(int x);
57 #define NSDELAY() asm volatile ("nop")
58 #define DEBUG(i) (PORTB = (1 << (i)))
60 FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE);
62 int bn_pressed;
63 unsigned char foo;
65 int main(void)
66 {
67 stdout = stderr = &stream_lcd;
69 /* port B[0] out -> backlight
70 * port B[1] in <- backlight switch
71 */
72 DDRB = 1;
73 PORTB = 0xfe; /* enable all pullups, leave bit0 -> 0 (backlight) */
74 /* enable PIN B1 interrupt */
75 PCMSK0 = 2;
76 PCICR = 1;
77 sei(); /* enable interrupts */
79 DDRC = 0xfe;
80 PORTC = 0; /* disable pullups */
82 lcd_init();
83 lcd_clear();
85 printf("initializing...");
86 setup_adc();
88 for(;;) {
89 long val = read_adc();
90 double ref = 1.08 * 1.47 / 0.47;
91 double voltage = ref * (double)val / (double)1024;
93 lcd_clear();
95 if(val == 1023) {
96 printf("*** RANGE ***");
97 } else {
98 printf("%.2f volts", voltage);
99 }
101 /* check if the backlight button was pressed */
102 if(bn_pressed & 1) {
103 if(PORTB & 1) {
104 PORTB &= 0xfe;
105 } else {
106 PORTB |= 1;
107 }
108 bn_pressed = 0;
109 }
110 _delay_ms(500);
111 }
112 return 0;
113 }
116 ISR(PCINT0_vect) {
117 if((PINB & 2) == 0) {
118 bn_pressed = 1;
119 }
120 }
122 void setup_adc(void)
123 {
124 /* disable digital input buffer on ADC0 pin */
125 DIDR0 = 1;
127 /* use the internal bandgap as a reference */
128 ADMUX = 3 << REFS0;
130 /* - enable ADC
131 * - set ADC clock prescaler to clock / 8
132 */
133 ADCSRA = (1 << ADEN) | (3 << ADPS0);
134 }
136 long read_adc(void)
137 {
138 long low;
140 /* start conversion */
141 ADCSRA |= (1 << ADSC);
143 /* wait while converting */
144 while(ADCSRA & (1 << ADSC));
146 low = ADCL;
147 return low | ((long)ADCH << 8);
148 }
150 void lcd_write_byte(unsigned char byte)
151 {
152 #if LCD_BUS_WIDTH == 8
153 DDRD = 0xff;
154 PORTD = byte;
155 #else
156 DDRD = (DDRD & 0xf0) | 0xf;
158 PORTD = (PORTD & 0xf0) | ((byte >> 4) & 0xf);
159 PORTD = (PORTD & 0xf0) | (byte & 0xf);
160 #endif
161 }
163 unsigned char lcd_read_byte(void)
164 {
165 #if LCD_BUS_WIDTH == 8
166 DDRD = 0;
167 PORTD = 0; /* disable pull-ups */
169 return PIND;
170 #else
171 unsigned char byte;
173 DDRD = DDRD & 0xf0;
174 PORTD &= 0xf0; /* disable pull-ups */
176 byte = (PIND & 0xf) << 4;
177 return byte | (PIND & 0xf);
178 #endif
179 }
181 void lcd_init(void)
182 {
183 /* make sure the display has time to boot up */
184 _delay_ms(20);
186 clear_bit(BIT_RW);
188 clear_bit(BIT_E);
189 clear_bit(BIT_RS);
190 #if LCD_BUS_WIDTH == 8
191 lcd_write_byte(CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
192 #else
193 lcd_write_byte(CMD_FUNC | FUNC_BUS_4BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
194 #endif
195 enable();
196 lcd_wait_busy();
198 clear_bit(BIT_RS);
199 lcd_write_byte(CMD_ONOFF | ONOFF_DISP);
200 enable();
201 lcd_wait_busy();
203 clear_bit(BIT_RS);
204 lcd_write_byte(CMD_ENTRY_MODE | (1 << 1));
205 enable();
206 lcd_wait_busy();
207 }
209 void lcd_clear(void)
210 {
211 clear_bit(BIT_RW);
213 clear_bit(BIT_E);
214 clear_bit(BIT_RS);
215 lcd_write_byte(CMD_CLEAR);
216 enable();
217 lcd_wait_busy();
218 }
220 void lcd_set_cursor_addr(unsigned int addr)
221 {
222 clear_bit(BIT_RW);
224 clear_bit(BIT_E);
225 clear_bit(BIT_RS);
226 lcd_write_byte(CMD_DDRAM_ADDR | addr);
227 enable();
228 lcd_wait_busy();
229 }
231 void lcd_putchar(char c)
232 {
233 clear_bit(BIT_RW);
235 set_bit(BIT_RS);
236 lcd_write_byte(c);
237 enable();
238 lcd_wait_busy();
239 }
241 void lcd_putstr(const char *str)
242 {
243 while(*str) {
244 lcd_putchar(*str++);
245 }
246 }
248 int lcd_stream_write(char c, FILE *fp)
249 {
250 /* TODO terminal shit handling */
251 lcd_putchar(c);
252 return 0;
253 }
255 void lcd_wait_busy(void)
256 {
257 unsigned char data;
259 do {
260 NSDELAY();
261 clear_bit(BIT_E);
262 clear_bit(BIT_RS);
263 set_bit(BIT_RW);
264 /*PIND = 0xff;*/
266 NSDELAY();
267 set_bit(BIT_E);
268 NSDELAY();
269 data = lcd_read_byte();
270 clear_bit(BIT_E);
271 clear_bit(BIT_RW);
273 } while(data & (1 << 7));
274 }
276 static void enable(void)
277 {
278 NSDELAY();
279 set_bit(BIT_E);
280 NSDELAY();
281 clear_bit(BIT_E);
282 NSDELAY();
283 }
285 static void set_bit(int bit)
286 {
287 PORTC |= 1 << bit;
288 }
290 static void clear_bit(int bit)
291 {
292 PORTC &= ~(1 << bit);
293 }
296 void delay(int x)
297 {
298 int i, j;
300 while(x-- > 0) {
301 for(i=0; i<90; i++) {
302 for(j=0; j<6; j++) {
303 asm volatile("nop");
304 }
305 }
306 }
307 }