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