root / branches / encoders / code / projects / libdragonfly / analog.c @ 546
History | View | Annotate | Download (3.73 KB)
1 | 8 | bcoltin | /*
|
---|---|---|---|
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 | // Internal Function Prototypes
|
||
14 | void set_adc_mux(int which); |
||
15 | |||
16 | /**
|
||
17 | * @defgroup analog Analog
|
||
18 | * Functions for manipulation the ADC on the dragonfly board.
|
||
19 | * All definitions may be found in analog.h.
|
||
20 | *
|
||
21 | * @{
|
||
22 | **/
|
||
23 | |||
24 | |||
25 | /**
|
||
26 | * Initializes the ADC.
|
||
27 | * Call analog_init before reading from the analog ports.
|
||
28 | *
|
||
29 | * @see analog8, analog10
|
||
30 | **/
|
||
31 | void analog_init(void) |
||
32 | { |
||
33 | // ADC Status Register A
|
||
34 | // Bit 7 - ADEN is set (enables analog)
|
||
35 | // Bit 6 - Start conversion bit is set (must be done once for free-running mode)
|
||
36 | // Bit 5 - Enable Auto Trigger (for free running mode)
|
||
37 | // Bit 4 - ADC interrupt flag, 0
|
||
38 | // Bit 3 - Enable ADC Interrupt (required to run free-running mode)
|
||
39 | // Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/128
|
||
40 | ADCSRA |= 0xEF;
|
||
41 | |||
42 | // ADC Status Register B
|
||
43 | // Bit 7, 5-3 - Must be cleared
|
||
44 | // Bit 2:0 - Set mode, currently cleared for free running operation
|
||
45 | // Bit 6 - Analog comparator mode - cleared
|
||
46 | // ADCSRB = 0x00;
|
||
47 | |||
48 | // ADMUX register
|
||
49 | // Bit 7,6 - Set voltage reference to AVcc (0b01)
|
||
50 | // Bit 5 - Set ADLAR bit for left adjust to do simple 8-bit reads
|
||
51 | // Bit 4 - X
|
||
52 | // Bit 3:0 - Sets the current channel, set to ADC7 (the external mux)
|
||
53 | ADMUX = 0x67;
|
||
54 | |||
55 | // Set external mux lines to outputs
|
||
56 | DDRG |= 0x1C;
|
||
57 | set_adc_mux(0x07);
|
||
58 | } |
||
59 | |||
60 | |||
61 | /**
|
||
62 | * Reads an eight bit number from an analog port.
|
||
63 | * analog_init must be called before using this function.
|
||
64 | *
|
||
65 | * @param which the analog port to read from. One of
|
||
66 | * the constants AN0 - AN7.
|
||
67 | *
|
||
68 | * @return the eight bit input to the specified port
|
||
69 | *
|
||
70 | * @see analog_init, analog10
|
||
71 | **/
|
||
72 | unsigned int analog8(int which) |
||
73 | { |
||
74 | if(which < EXT_MUX)
|
||
75 | ADMUX = 0x60 + which;
|
||
76 | else if(which == EXT_MUX) |
||
77 | return 0; |
||
78 | else
|
||
79 | { |
||
80 | ADMUX = 0x60 + EXT_MUX;
|
||
81 | set_adc_mux(which - 8);
|
||
82 | _delay_ms(1);
|
||
83 | } |
||
84 | |||
85 | _delay_ms(1); // need at least 130 us between conversions |
||
86 | return ADCH;
|
||
87 | } |
||
88 | |||
89 | /**
|
||
90 | * Reads a ten bit number from the specified port.
|
||
91 | * analog_init must be called before using this function.
|
||
92 | *
|
||
93 | * @param which the analog port to read from. Typically
|
||
94 | * a constant, one of AN0 - AN7.
|
||
95 | *
|
||
96 | * @return the ten bit number input to the specified port
|
||
97 | *
|
||
98 | * @see analog_init, analog8
|
||
99 | **/
|
||
100 | unsigned int analog10(int which) |
||
101 | { |
||
102 | unsigned int adc_h = 0; |
||
103 | unsigned int adc_l = 0; |
||
104 | |||
105 | if(which < EXT_MUX)
|
||
106 | ADMUX = 0x60 + which;
|
||
107 | else if(which == EXT_MUX) |
||
108 | return 0; |
||
109 | else
|
||
110 | { |
||
111 | ADMUX = 0x60 + EXT_MUX;
|
||
112 | set_adc_mux(which - 8);
|
||
113 | _delay_ms(1);
|
||
114 | } |
||
115 | |||
116 | _delay_ms(1);
|
||
117 | adc_l = ADCL; /* highest 2 bits of ADCL -> least 2 bits of analog val */
|
||
118 | adc_h = ADCH; /* ADCH -> 8 highest bits of analog val */
|
||
119 | |||
120 | return (adc_h << 2) | (adc_l >> 6); |
||
121 | } |
||
122 | |||
123 | /**
|
||
124 | * Returns the current position of the wheel, as an integer
|
||
125 | * in the range 0 - 255.
|
||
126 | * analog_init must be called before using this function.
|
||
127 | *
|
||
128 | * @return the orientation of the wheel, as an integer in
|
||
129 | * the range 0 - 255.
|
||
130 | *
|
||
131 | * @see analog_init
|
||
132 | **/
|
||
133 | int wheel(void) |
||
134 | { |
||
135 | return analog8(WHEEL_PORT);
|
||
136 | } |
||
137 | |||
138 | /**@}**/ //end defgroup |
||
139 | |||
140 | SIGNAL (SIG_ADC) |
||
141 | { |
||
142 | // This is just here to catch ADC interrupts because ADC is free running.
|
||
143 | // No code needs to be in here.
|
||
144 | } |
||
145 | |||
146 | void set_adc_mux(int which) |
||
147 | { |
||
148 | // FIX THIS IN NEXT REVISION
|
||
149 | // ADDR2 ADDR1 ADDR0
|
||
150 | // G2.G4.G3 set mux to port 0-7 via binary selection
|
||
151 | // math would be much cleaner if it was G4.G3.G2
|
||
152 | |||
153 | // mask so only proper bits are possible.
|
||
154 | PORTG = (PORTG & 0xE3) | ((which & 0x03) << 3) | (which & 0x04); |
||
155 | } |