diff options
Diffstat (limited to 'platforms/avr/drivers/analog.c')
-rw-r--r-- | platforms/avr/drivers/analog.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/platforms/avr/drivers/analog.c b/platforms/avr/drivers/analog.c new file mode 100644 index 000000000..8d299ffdb --- /dev/null +++ b/platforms/avr/drivers/analog.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* Copyright 2015 Jack Humbert | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <avr/io.h> | ||
18 | #include <avr/pgmspace.h> | ||
19 | #include <stdint.h> | ||
20 | #include "analog.h" | ||
21 | |||
22 | static uint8_t aref = ADC_REF_POWER; | ||
23 | |||
24 | void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); } | ||
25 | |||
26 | // Arduino compatible pin input | ||
27 | int16_t analogRead(uint8_t pin) { | ||
28 | #if defined(__AVR_ATmega32U4__) | ||
29 | // clang-format off | ||
30 | static const uint8_t PROGMEM pin_to_mux[] = { | ||
31 | //A0 A1 A2 A3 A4 A5 | ||
32 | //F7 F6 F5 F4 F1 F0 | ||
33 | 0x07, 0x06, 0x05, 0x04, 0x01, 0x00, | ||
34 | //A6 A7 A8 A9 A10 A11 | ||
35 | //D4 D7 B4 B5 B6 D6 | ||
36 | 0x20, 0x22, 0x23, 0x24, 0x25, 0x21 | ||
37 | }; | ||
38 | // clang-format on | ||
39 | if (pin >= 12) return 0; | ||
40 | return adc_read(pgm_read_byte(pin_to_mux + pin)); | ||
41 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) | ||
42 | if (pin >= 8) return 0; | ||
43 | return adc_read(pin); | ||
44 | #else | ||
45 | return 0; | ||
46 | #endif | ||
47 | } | ||
48 | |||
49 | int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); } | ||
50 | |||
51 | uint8_t pinToMux(pin_t pin) { | ||
52 | switch (pin) { | ||
53 | // clang-format off | ||
54 | #if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) | ||
55 | case F0: return 0; // ADC0 | ||
56 | case F1: return _BV(MUX0); // ADC1 | ||
57 | case F2: return _BV(MUX1); // ADC2 | ||
58 | case F3: return _BV(MUX1) | _BV(MUX0); // ADC3 | ||
59 | case F4: return _BV(MUX2); // ADC4 | ||
60 | case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 | ||
61 | case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 | ||
62 | case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 | ||
63 | default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V | ||
64 | #elif defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | ||
65 | case F0: return 0; // ADC0 | ||
66 | case F1: return _BV(MUX0); // ADC1 | ||
67 | case F4: return _BV(MUX2); // ADC4 | ||
68 | case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 | ||
69 | case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 | ||
70 | case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 | ||
71 | case D4: return _BV(MUX5); // ADC8 | ||
72 | case D6: return _BV(MUX5) | _BV(MUX0); // ADC9 | ||
73 | case D7: return _BV(MUX5) | _BV(MUX1); // ADC10 | ||
74 | case B4: return _BV(MUX5) | _BV(MUX1) | _BV(MUX0); // ADC11 | ||
75 | case B5: return _BV(MUX5) | _BV(MUX2); // ADC12 | ||
76 | case B6: return _BV(MUX5) | _BV(MUX2) | _BV(MUX0); // ADC13 | ||
77 | default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V | ||
78 | #elif defined(__AVR_ATmega32A__) | ||
79 | case A0: return 0; // ADC0 | ||
80 | case A1: return _BV(MUX0); // ADC1 | ||
81 | case A2: return _BV(MUX1); // ADC2 | ||
82 | case A3: return _BV(MUX1) | _BV(MUX0); // ADC3 | ||
83 | case A4: return _BV(MUX2); // ADC4 | ||
84 | case A5: return _BV(MUX2) | _BV(MUX0); // ADC5 | ||
85 | case A6: return _BV(MUX2) | _BV(MUX1); // ADC6 | ||
86 | case A7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 | ||
87 | default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V | ||
88 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) | ||
89 | case C0: return 0; // ADC0 | ||
90 | case C1: return _BV(MUX0); // ADC1 | ||
91 | case C2: return _BV(MUX1); // ADC2 | ||
92 | case C3: return _BV(MUX1) | _BV(MUX0); // ADC3 | ||
93 | case C4: return _BV(MUX2); // ADC4 | ||
94 | case C5: return _BV(MUX2) | _BV(MUX0); // ADC5 | ||
95 | // ADC7:6 not present in DIP package and not shared by GPIO pins | ||
96 | default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V | ||
97 | #endif | ||
98 | // clang-format on | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int16_t adc_read(uint8_t mux) { | ||
104 | uint16_t low; | ||
105 | |||
106 | // Enable ADC and configure prescaler | ||
107 | ADCSRA = _BV(ADEN) | ADC_PRESCALER; | ||
108 | |||
109 | #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | ||
110 | // High speed mode and ADC8-13 | ||
111 | ADCSRB = _BV(ADHSM) | (mux & _BV(MUX5)); | ||
112 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) | ||
113 | // High speed mode only | ||
114 | ADCSRB = _BV(ADHSM); | ||
115 | #endif | ||
116 | |||
117 | // Configure mux input | ||
118 | #if defined(MUX4) | ||
119 | ADMUX = aref | (mux & (_BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); | ||
120 | #else | ||
121 | ADMUX = aref | (mux & (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); | ||
122 | #endif | ||
123 | |||
124 | // Start the conversion | ||
125 | ADCSRA |= _BV(ADSC); | ||
126 | // Wait for result | ||
127 | while (ADCSRA & _BV(ADSC)) | ||
128 | ; | ||
129 | // Must read LSB first | ||
130 | low = ADCL; | ||
131 | // Must read MSB only once! | ||
132 | low |= (ADCH << 8); | ||
133 | |||
134 | // turn off the ADC | ||
135 | ADCSRA &= ~(1 << ADEN); | ||
136 | |||
137 | return low; | ||
138 | } | ||