aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorfauxpark <fauxpark@gmail.com>2019-12-08 12:11:29 +1100
committerGitHub <noreply@github.com>2019-12-08 12:11:29 +1100
commita8320f20f76782789b274f7a8c3e3ad4278a075c (patch)
treeb86b8ae732cb995dcccf5de1effa6af32149d98c /drivers
parentf275ffbdfc1cbd1965cd3546b45a7838012321da (diff)
downloadqmk_firmware-a8320f20f76782789b274f7a8c3e3ad4278a075c.tar.gz
qmk_firmware-a8320f20f76782789b274f7a8c3e3ad4278a075c.zip
Improve support and docs for ADC driver (#7191)
* Improve support and docs for ADC driver * Comment ADC channels * Move to Makers and Modders section, and fix usage instructions * Flesh out intro * Superscript 328P note * Fix pin_to_mux LUT * Support USB64/1287 as well * analogReadPin() defaults to 0V mux on invalid pin * Update pinToMux() function documentation * Dot * Accept (some of) the `qmk cformat` changes * Do clang-format properly * More wording tweaks * Link to encoder docs
Diffstat (limited to 'drivers')
-rw-r--r--drivers/avr/analog.c110
-rw-r--r--drivers/avr/analog.h37
2 files changed, 108 insertions, 39 deletions
diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c
index 1a8da4261..abe478b71 100644
--- a/drivers/avr/analog.c
+++ b/drivers/avr/analog.c
@@ -14,24 +14,31 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16 16
17// Simple analog to digitial conversion
18
19#include <avr/io.h> 17#include <avr/io.h>
20#include <avr/pgmspace.h> 18#include <avr/pgmspace.h>
21#include <stdint.h> 19#include <stdint.h>
22#include "analog.h" 20#include "analog.h"
23 21
24static uint8_t aref = (1 << REFS0); // default to AREF = Vcc 22static uint8_t aref = ADC_REF_POWER;
25 23
26void analogReference(uint8_t mode) { aref = mode & 0xC0; } 24void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); }
27 25
28// Arduino compatible pin input 26// Arduino compatible pin input
29int16_t analogRead(uint8_t pin) { 27int16_t analogRead(uint8_t pin) {
30#if defined(__AVR_ATmega32U4__) 28#if defined(__AVR_ATmega32U4__)
31 static const uint8_t PROGMEM pin_to_mux[] = {0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; 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
32 if (pin >= 12) return 0; 39 if (pin >= 12) return 0;
33 return adc_read(pgm_read_byte(pin_to_mux + pin)); 40 return adc_read(pgm_read_byte(pin_to_mux + pin));
34#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 41#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__)
35 if (pin >= 8) return 0; 42 if (pin >= 8) return 0;
36 return adc_read(pin); 43 return adc_read(pin);
37#else 44#else
@@ -39,20 +46,87 @@ int16_t analogRead(uint8_t pin) {
39#endif 46#endif
40} 47}
41 48
42// Mux input 49int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); }
50
51uint8_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__)
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}
101
43int16_t adc_read(uint8_t mux) { 102int16_t adc_read(uint8_t mux) {
44#if defined(__AVR_AT90USB162__)
45 return 0;
46#else
47 uint8_t low; 103 uint8_t low;
48 104
49 ADCSRA = (1 << ADEN) | ADC_PRESCALER; // enable ADC 105 // Enable ADC and configure prescaler
50 ADCSRB = (1 << ADHSM) | (mux & 0x20); // high speed mode 106 ADCSRA = _BV(ADEN) | ADC_PRESCALER;
51 ADMUX = aref | (mux & 0x1F); // configure mux input 107
52 ADCSRA = (1 << ADEN) | ADC_PRESCALER | (1 << ADSC); // start the conversion 108#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
53 while (ADCSRA & (1 << ADSC)) 109 // High speed mode and ADC8-13
54 ; // wait for result 110 ADCSRB = _BV(ADHSM) | (mux & _BV(MUX5));
55 low = ADCL; // must read LSB first 111#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
56 return (ADCH << 8) | low; // must read MSB only once! 112 // High speed mode only
113 ADCSRB = _BV(ADHSM);
114#endif
115
116 // Configure mux input
117#if defined(MUX4)
118 ADMUX = aref | (mux & (_BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)));
119#else
120 ADMUX = aref | (mux & (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)));
57#endif 121#endif
122
123 // Start the conversion
124 ADCSRA |= _BV(ADSC);
125 // Wait for result
126 while (ADCSRA & _BV(ADSC))
127 ;
128 // Must read LSB first
129 low = ADCL;
130 // Must read MSB only once!
131 return (ADCH << 8) | low;
58} 132}
diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h
index 1b773d82c..058882450 100644
--- a/drivers/avr/analog.h
+++ b/drivers/avr/analog.h
@@ -14,45 +14,40 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16 16
17#ifndef _analog_h_included__ 17#pragma once
18#define _analog_h_included__
19 18
20#include <stdint.h> 19#include <stdint.h>
20#include "quantum.h"
21 21
22#ifdef __cplusplus 22#ifdef __cplusplus
23extern "C" { 23extern "C" {
24#endif 24#endif
25void analogReference(uint8_t mode); 25void analogReference(uint8_t mode);
26int16_t analogRead(uint8_t pin); 26int16_t analogRead(uint8_t pin);
27
28int16_t analogReadPin(pin_t pin);
29uint8_t pinToMux(pin_t pin);
30
27int16_t adc_read(uint8_t mux); 31int16_t adc_read(uint8_t mux);
28#ifdef __cplusplus 32#ifdef __cplusplus
29} 33}
30#endif 34#endif
31 35
32#define ADC_REF_POWER (1 << REFS0) 36#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off
33#define ADC_REF_INTERNAL ((1 << REFS1) | (1 << REFS0)) 37#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin
34#define ADC_REF_EXTERNAL (0) 38#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P)
35 39
36// These prescaler values are for high speed mode, ADHSM = 1 40// These prescaler values are for high speed mode, ADHSM = 1
37#if F_CPU == 16000000L 41#if F_CPU == 16000000L || F_CPU == 12000000L
38# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS1)) 42# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64
39#elif F_CPU == 8000000L 43#elif F_CPU == 8000000L
40# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS0)) 44# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32
41#elif F_CPU == 4000000L 45#elif F_CPU == 4000000L
42# define ADC_PRESCALER ((1 << ADPS2)) 46# define ADC_PRESCALER (_BV(ADPS2)) // /16
43#elif F_CPU == 2000000L 47#elif F_CPU == 2000000L
44# define ADC_PRESCALER ((1 << ADPS1) | (1 << ADPS0)) 48# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8
45#elif F_CPU == 1000000L 49#elif F_CPU == 1000000L
46# define ADC_PRESCALER ((1 << ADPS1)) 50# define ADC_PRESCALER _BV(ADPS1) // /4
47#else 51#else
48# define ADC_PRESCALER ((1 << ADPS0)) 52# define ADC_PRESCALER _BV(ADPS0) // /2
49#endif
50
51// some avr-libc versions do not properly define ADHSM
52#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
53# if !defined(ADHSM)
54# define ADHSM (7)
55# endif
56#endif
57
58#endif 53#endif