voltmeter

view voltmeter.c @ 0:d26d73ef2db7

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Jan 2013 10:11:40 +0200
parents
children 40b150fedb0e
line source
1 #define F_CLK 1000000
2 #define F_CPU 1000000
4 #include <stdio.h>
5 #include <avr/io.h>
6 #include <util/delay.h>
8 /* hardware setup
9 * - PORT D: data bits
10 * - PORT C
11 * bit 0: RS
12 * bit 1: R/W
13 * bit 2: E
14 */
16 #define BIT_RS 3
17 #define BIT_RW 4
18 #define BIT_E 5
20 #define CMD_CLEAR 1
21 #define CMD_RET (1 << 1)
22 #define CMD_ENTRY_MODE (1 << 2)
23 #define CMD_ONOFF (1 << 3)
24 #define CMD_SHIFT (1 << 4)
25 #define CMD_FUNC (1 << 5)
26 #define CMD_CGRAM_ADDR (1 << 6)
27 #define CMD_DDRAM_ADDR (1 << 7)
29 #define FUNC_BUS_4BIT 0
30 #define FUNC_BUS_8BIT (1 << 4)
31 #define FUNC_LINES_1 0
32 #define FUNC_LINES_2 (1 << 3)
33 #define FUNC_FONT_5x8 0
34 #define FUNC_FONT_5x11 (1 << 2)
36 #define ONOFF_DISP (1 << 2)
37 #define ONOFF_CURSOR (1 << 1)
38 #define ONOFF_CURSOR_POS 1
40 void setup_adc(void);
41 long read_adc(void);
43 void lcd_init(void);
44 void lcd_clear(void);
45 void lcd_set_cursor_addr(unsigned int addr);
46 void lcd_putchar(char c);
47 void lcd_putstr(const char *str);
48 int lcd_stream_write(char c, FILE *fp);
49 void lcd_wait_busy(void);
50 static void enable(void);
51 static void set_bit(int bit);
52 static void clear_bit(int bit);
53 void delay(int x);
55 #define NSDELAY() asm volatile ("nop")
56 #define DEBUG(i) (PORTB = (1 << (i)))
58 FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE);
60 int main(void)
61 {
62 stdout = stderr = &stream_lcd;
64 DDRC = 0xfe;
65 PORTC = 0; /* disable pullups */
67 lcd_init();
68 lcd_clear();
70 printf("initializing...");
71 setup_adc();
73 for(;;) {
74 long val = read_adc();
75 double ref = 1.08 * 1.47 / 0.47;
76 double voltage = ref * (double)val / (double)1024;
77 lcd_clear();
79 if(val == 1023) {
80 printf("*** RANGE *** ");
81 } else {
82 printf("%.2f volts ", voltage);
83 }
84 _delay_ms(500);
85 }
86 return 0;
87 }
89 void setup_adc(void)
90 {
91 /* disable digital input buffer on ADC0 pin */
92 DIDR0 = 1;
94 /* use the internal bandgap as a reference */
95 ADMUX = 3 << REFS0;
97 /* - enable ADC
98 * - set ADC clock prescaler to clock / 8
99 */
100 ADCSRA = (1 << ADEN) | (3 << ADPS0);
101 }
103 long read_adc(void)
104 {
105 long low;
107 /* start conversion */
108 ADCSRA |= (1 << ADSC);
110 /* wait while converting */
111 while(ADCSRA & (1 << ADSC));
113 low = ADCL;
114 return low | ((long)ADCH << 8);
115 }
117 void lcd_init(void)
118 {
119 DDRD = 0x0f; /* port d[0, 3] -> output */
121 /* make sure the display has time to boot up */
122 _delay_ms(20);
124 clear_bit(BIT_RW);
126 clear_bit(BIT_E);
127 clear_bit(BIT_RS);
128 PORTD = CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8;
129 enable();
130 lcd_wait_busy();
132 clear_bit(BIT_RS);
133 PORTD = CMD_ONOFF | ONOFF_DISP | ONOFF_CURSOR;
134 enable();
135 lcd_wait_busy();
137 clear_bit(BIT_RS);
138 PORTD = CMD_ENTRY_MODE | (1 << 1);
139 enable();
140 lcd_wait_busy();
141 }
143 void lcd_clear(void)
144 {
145 DDRD = 0xff; /* port d -> output */
147 clear_bit(BIT_RW);
149 clear_bit(BIT_E);
150 clear_bit(BIT_RS);
151 PORTD = CMD_CLEAR;
152 enable();
153 lcd_wait_busy();
154 }
156 void lcd_set_cursor_addr(unsigned int addr)
157 {
158 DDRD = 0xff; /* port d -> output */
160 clear_bit(BIT_RW);
162 clear_bit(BIT_E);
163 clear_bit(BIT_RS);
164 PORTD = CMD_DDRAM_ADDR | addr;
165 enable();
166 lcd_wait_busy();
167 }
169 void lcd_putchar(char c)
170 {
171 DDRD = 0xff; /* port d -> output */
173 clear_bit(BIT_RW);
175 set_bit(BIT_RS);
176 PORTD = c;
177 enable();
178 lcd_wait_busy();
179 }
181 void lcd_putstr(const char *str)
182 {
183 while(*str) {
184 lcd_putchar(*str++);
185 }
186 }
188 int lcd_stream_write(char c, FILE *fp)
189 {
190 /* TODO terminal shit handling */
191 lcd_putchar(c);
192 return 0;
193 }
195 void lcd_wait_busy(void)
196 {
197 unsigned char data;
199 DDRD = 0; /* port d -> input */
200 PORTD = 0; /* disable pull-ups */
202 do {
203 NSDELAY();
204 clear_bit(BIT_E);
205 clear_bit(BIT_RS);
206 set_bit(BIT_RW);
207 /*PIND = 0xff;*/
209 NSDELAY();
210 set_bit(BIT_E);
211 NSDELAY();
212 data = PIND;
213 clear_bit(BIT_E);
214 clear_bit(BIT_RW);
216 } while(data & (1 << 7));
218 DDRD = 0xff; /* port d -> output */
219 }
221 static void enable(void)
222 {
223 NSDELAY();
224 set_bit(BIT_E);
225 NSDELAY();
226 clear_bit(BIT_E);
227 NSDELAY();
228 }
230 static void set_bit(int bit)
231 {
232 PORTC |= 1 << bit;
233 }
235 static void clear_bit(int bit)
236 {
237 PORTC &= ~(1 << bit);
238 }
241 void delay(int x)
242 {
243 int i, j;
245 while(x-- > 0) {
246 for(i=0; i<90; i++) {
247 for(j=0; j<6; j++) {
248 asm volatile("nop");
249 }
250 }
251 }
252 }