root / branches / encoders / code / projects / colonet / utilities / robot_slave / analog.c @ 1390
History | View | Annotate | Download (2.74 KB)
1 | 13 | emarinel | /*
|
---|---|---|---|
2 | * analog.c - Contains the function implementations for manipulating the ADC
|
||
3 | * on the firefly+ board
|
||
4 | *
|
||
5 | * author: CMU Robotics Club, Colony Project
|
||
6 | * code mostly taken from fwr analog file (author: Tom Lauwers)
|
||
7 | */
|
||
8 | |||
9 | #include <util/delay.h> |
||
10 | #include <avr/interrupt.h> |
||
11 | #include "analog.h" |
||
12 | |||
13 | void set_adc_mux(int which) |
||
14 | { |
||
15 | // FIX THIS IN NEXT REVISION
|
||
16 | // ADDR2 ADDR1 ADDR0
|
||
17 | // G2.G4.G3 set mux to port 0-7 via binary selection
|
||
18 | // math would be much cleaner if it was G4.G3.G2
|
||
19 | |||
20 | // mask so only proper bits are possible.
|
||
21 | PORTG = (PORTG & 0xE3) | ((which & 0x03) << 3) | (which & 0x04); |
||
22 | } |
||
23 | |||
24 | void analog_init(void) |
||
25 | { |
||
26 | |||
27 | |||
28 | // ADC Status Register A
|
||
29 | // Bit 7 - ADEN is set (enables analog)
|
||
30 | // Bit 6 - Start conversion bit is set (must be done once for free-running mode)
|
||
31 | // Bit 5 - Enable Auto Trigger (for free running mode)
|
||
32 | // Bit 4 - ADC interrupt flag, 0
|
||
33 | // Bit 3 - Enable ADC Interrupt (required to run free-running mode)
|
||
34 | // Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/128
|
||
35 | ADCSRA |= 0xEF;
|
||
36 | |||
37 | // ADC Status Register B
|
||
38 | // Bit 7, 5-3 - Must be cleared
|
||
39 | // Bit 2:0 - Set mode, currently cleared for free running operation
|
||
40 | // Bit 6 - Analog comparator mode - cleared
|
||
41 | // ADCSRB = 0x00;
|
||
42 | |||
43 | // ADMUX register
|
||
44 | // Bit 7,6 - Set voltage reference to AVcc (0b01)
|
||
45 | // Bit 5 - Set ADLAR bit for left adjust to do simple 8-bit reads
|
||
46 | // Bit 4 - X
|
||
47 | // Bit 3:0 - Sets the current channel, set to ADC7 (the external mux)
|
||
48 | ADMUX = 0x67;
|
||
49 | |||
50 | // Set external mux lines to outputs
|
||
51 | DDRG |= 0x1C;
|
||
52 | set_adc_mux(0x07);
|
||
53 | |||
54 | |||
55 | } |
||
56 | |||
57 | |||
58 | |||
59 | unsigned int analog8(int which) |
||
60 | { |
||
61 | |||
62 | |||
63 | if(which < EXT_MUX)
|
||
64 | { |
||
65 | ADMUX = 0x60 + which;
|
||
66 | } |
||
67 | else if(which == EXT_MUX) |
||
68 | { |
||
69 | return 0; |
||
70 | } |
||
71 | else
|
||
72 | { |
||
73 | ADMUX = 0x60 + EXT_MUX;
|
||
74 | set_adc_mux(which - 8);
|
||
75 | _delay_ms(1);
|
||
76 | } |
||
77 | |||
78 | _delay_ms(1); // need at least 130 us between conversions |
||
79 | return ADCH;
|
||
80 | |||
81 | } |
||
82 | |||
83 | |||
84 | |||
85 | |||
86 | unsigned int analog10(int which) |
||
87 | { |
||
88 | unsigned int adc_h = 0; |
||
89 | unsigned int adc_l = 0; |
||
90 | |||
91 | if(which < EXT_MUX)
|
||
92 | { |
||
93 | ADMUX = 0x60 + which;
|
||
94 | } |
||
95 | else if(which == EXT_MUX) |
||
96 | { |
||
97 | return 0; |
||
98 | } |
||
99 | else
|
||
100 | { |
||
101 | ADMUX = 0x60 + EXT_MUX;
|
||
102 | set_adc_mux(which - 8);
|
||
103 | _delay_ms(1);
|
||
104 | } |
||
105 | |||
106 | _delay_ms(1);
|
||
107 | adc_l = ADCL; /* highest 2 bits of ADCL -> least 2 bits of analog val */
|
||
108 | adc_h = ADCH; /* ADCH -> 8 highest bits of analog val */
|
||
109 | |||
110 | return (adc_h << 2) | (adc_l >> 6); |
||
111 | } |
||
112 | |||
113 | int wheel(void) |
||
114 | { |
||
115 | return analog8(WHEEL_PORT);
|
||
116 | } |
||
117 | |||
118 | int battery8(void) |
||
119 | { |
||
120 | return analog8(BATT_PORT);
|
||
121 | } |
||
122 | |||
123 | int battery(void) |
||
124 | { |
||
125 | /* 5 volts is the max, 255 is the max 8bit number , *2 for the divider */
|
||
126 | return analog8(BATT_PORT) * 500 >>7; |
||
127 | } |
||
128 | |||
129 | SIGNAL (SIG_ADC) |
||
130 | { |
||
131 | // This is just here to catch ADC interrupts because ADC is free running.
|
||
132 | // No code needs to be in here.
|
||
133 | } |