diff options
| author | fauxpark <fauxpark@gmail.com> | 2019-12-08 12:11:29 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-08 12:11:29 +1100 |
| commit | a8320f20f76782789b274f7a8c3e3ad4278a075c (patch) | |
| tree | b86b8ae732cb995dcccf5de1effa6af32149d98c /drivers | |
| parent | f275ffbdfc1cbd1965cd3546b45a7838012321da (diff) | |
| download | qmk_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.c | 110 | ||||
| -rw-r--r-- | drivers/avr/analog.h | 37 |
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 | ||
| 24 | static uint8_t aref = (1 << REFS0); // default to AREF = Vcc | 22 | static uint8_t aref = ADC_REF_POWER; |
| 25 | 23 | ||
| 26 | void analogReference(uint8_t mode) { aref = mode & 0xC0; } | 24 | void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); } |
| 27 | 25 | ||
| 28 | // Arduino compatible pin input | 26 | // Arduino compatible pin input |
| 29 | int16_t analogRead(uint8_t pin) { | 27 | int16_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 | 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__) | ||
| 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 | |||
| 43 | int16_t adc_read(uint8_t mux) { | 102 | int16_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 |
| 23 | extern "C" { | 23 | extern "C" { |
| 24 | #endif | 24 | #endif |
| 25 | void analogReference(uint8_t mode); | 25 | void analogReference(uint8_t mode); |
| 26 | int16_t analogRead(uint8_t pin); | 26 | int16_t analogRead(uint8_t pin); |
| 27 | |||
| 28 | int16_t analogReadPin(pin_t pin); | ||
| 29 | uint8_t pinToMux(pin_t pin); | ||
| 30 | |||
| 27 | int16_t adc_read(uint8_t mux); | 31 | int16_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 |
