qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

analog.c (21789B)


      1 /* Copyright 2019 Drew Mills
      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 "analog.h"
     18 #include <ch.h>
     19 #include <hal.h>
     20 
     21 #if !HAL_USE_ADC
     22 #    error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC."
     23 #endif
     24 
     25 #if !RP_ADC_USE_ADC1 && !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 && !WB32_ADC_USE_ADC1 && !AT32_ADC_USE_ADC1
     26 #    error "You need to set one of the 'xxx_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC."
     27 #endif
     28 
     29 #if STM32_ADC_DUAL_MODE
     30 #    error "STM32 ADC Dual Mode is not supported at this time."
     31 #endif
     32 
     33 #if STM32_ADCV3_OVERSAMPLING
     34 // Apparently all ADCV3 chips that support oversampling (STM32L4xx, STM32L4xx+,
     35 // STM32G4xx, STM32WB[35]x) have errata like “Wrong ADC result if conversion
     36 // done late after calibration or previous conversion”; the workaround is to
     37 // perform a dummy conversion and discard its result.  STM32G4xx chips also
     38 // have the “ADC channel 0 converted instead of the required ADC channel”
     39 // errata, one workaround for which is also to perform a dummy conversion.
     40 #    define ADC_DUMMY_CONVERSIONS_AT_START 1
     41 #else
     42 #    define ADC_DUMMY_CONVERSIONS_AT_START 0
     43 #endif
     44 
     45 // Otherwise assume V3
     46 #if defined(STM32F0XX) || defined(STM32L0XX) || defined(STM32G0XX)
     47 #    define USE_ADCV1
     48 #elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
     49 #    define USE_ADCV2
     50 #endif
     51 
     52 // BODGE to make v2 look like v1,3 and 4
     53 #if defined(USE_ADCV2) || defined(RP2040)
     54 #    if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_3)
     55 #        define ADC_SMPR_SMP_1P5 ADC_SAMPLE_3
     56 #        define ADC_SMPR_SMP_7P5 ADC_SAMPLE_15
     57 #        define ADC_SMPR_SMP_13P5 ADC_SAMPLE_28
     58 #        define ADC_SMPR_SMP_28P5 ADC_SAMPLE_56
     59 #        define ADC_SMPR_SMP_41P5 ADC_SAMPLE_84
     60 #        define ADC_SMPR_SMP_55P5 ADC_SAMPLE_112
     61 #        define ADC_SMPR_SMP_71P5 ADC_SAMPLE_144
     62 #        define ADC_SMPR_SMP_239P5 ADC_SAMPLE_480
     63 #    endif
     64 
     65 #    if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_1P5)
     66 #        define ADC_SMPR_SMP_1P5 ADC_SAMPLE_1P5
     67 #        define ADC_SMPR_SMP_7P5 ADC_SAMPLE_7P5
     68 #        define ADC_SMPR_SMP_13P5 ADC_SAMPLE_13P5
     69 #        define ADC_SMPR_SMP_28P5 ADC_SAMPLE_28P5
     70 #        define ADC_SMPR_SMP_41P5 ADC_SAMPLE_41P5
     71 #        define ADC_SMPR_SMP_55P5 ADC_SAMPLE_55P5
     72 #        define ADC_SMPR_SMP_71P5 ADC_SAMPLE_71P5
     73 #        define ADC_SMPR_SMP_239P5 ADC_SAMPLE_239P5
     74 #    endif
     75 
     76 // we still sample at 12bit, but scale down to the requested bit range
     77 #    define ADC_CFGR1_RES_12BIT 12
     78 #    define ADC_CFGR1_RES_10BIT 10
     79 #    define ADC_CFGR1_RES_8BIT 8
     80 #    define ADC_CFGR1_RES_6BIT 6
     81 #endif
     82 
     83 /* User configurable ADC options */
     84 #ifndef ADC_COUNT
     85 #    if defined(RP2040) || defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(STM32G0XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
     86 #        define ADC_COUNT 1
     87 #    elif defined(STM32F3XX) || defined(STM32G4XX)
     88 #        define ADC_COUNT 4
     89 #    elif defined(STM32L4XX)
     90 #        define ADC_COUNT 3
     91 #    else
     92 #        error "ADC_COUNT has not been set for this ARM microcontroller."
     93 #    endif
     94 #endif
     95 
     96 #ifndef ADC_NUM_CHANNELS
     97 #    define ADC_NUM_CHANNELS 1
     98 #elif ADC_NUM_CHANNELS != 1
     99 #    error "The ARM ADC implementation currently only supports reading one channel at a time."
    100 #endif
    101 
    102 // Add dummy conversions as extra channels (this would work only on chips that
    103 // have multiple channel index fields instead of a channel mask, but all chips
    104 // that need that workaround are like that).
    105 #define ADC_TOTAL_CHANNELS (ADC_DUMMY_CONVERSIONS_AT_START + ADC_NUM_CHANNELS)
    106 
    107 #ifndef ADC_BUFFER_DEPTH
    108 #    define ADC_BUFFER_DEPTH 1
    109 #endif
    110 
    111 // For more sampling rate options, look at hal_adc_lld.h in ChibiOS
    112 #if !defined(ADC_SAMPLING_RATE) && !defined(RP2040)
    113 #    if defined(ADC_SMPR_SMP_1P5)
    114 #        define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5
    115 #    elif defined(ADC_SMPR_SMP_2P5) // STM32L4XX, STM32L4XXP, STM32G4XX, STM32WBXX
    116 #        define ADC_SAMPLING_RATE ADC_SMPR_SMP_2P5
    117 #    elif defined(ADC_SMPR_SMP1_1P5) // STM32G0XX
    118 #        define ADC_SAMPLING_RATE ADC_SMPR_SMP1_1P5
    119 #    else
    120 #        error "Cannot determine the default ADC_SAMPLING_RATE for this MCU."
    121 #    endif
    122 #endif
    123 
    124 // Options are 12, 10, 8, and 6 bit.
    125 #ifndef ADC_RESOLUTION
    126 #    ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4
    127 #        define ADC_RESOLUTION ADC_CFGR_RES_10BITS
    128 #    else // ADCv1, ADCv5, or the bodge for ADCv2 above
    129 #        define ADC_RESOLUTION ADC_CFGR1_RES_10BIT
    130 #    endif
    131 #endif
    132 
    133 static ADCConfig   adcCfg = {};
    134 static adcsample_t sampleBuffer[ADC_TOTAL_CHANNELS * ADC_BUFFER_DEPTH];
    135 
    136 // Initialize to max number of ADCs, set to empty object to initialize all to false.
    137 static bool adcInitialized[ADC_COUNT] = {};
    138 
    139 // TODO: add back TR handling???
    140 static ADCConversionGroup adcConversionGroup = {
    141     .circular     = FALSE,
    142     .num_channels = (uint16_t)(ADC_TOTAL_CHANNELS),
    143 #if defined(USE_ADCV1)
    144     .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
    145     .smpr  = ADC_SAMPLING_RATE,
    146 #elif defined(USE_ADCV2)
    147 #    if !defined(STM32F1XX) && !defined(GD32VF103) && !defined(WB32F3G71xx) && !defined(WB32FQ95xx) && !defined(AT32F415)
    148     .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
    149 #    endif
    150 #    if defined(AT32F415)
    151     .spt2 = ADC_SPT2_CSPT_AN0(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN1(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN2(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN3(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN4(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN5(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN6(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN7(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN8(ADC_SAMPLING_RATE) | ADC_SPT2_CSPT_AN9(ADC_SAMPLING_RATE),
    152     .spt1 = ADC_SPT1_CSPT_AN10(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN11(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN12(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN13(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN14(ADC_SAMPLING_RATE) | ADC_SPT1_CSPT_AN15(ADC_SAMPLING_RATE),
    153 #    else
    154     .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
    155     .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),
    156 #    endif
    157 #elif defined(RP2040)
    158 // RP2040 does not have any extra config here
    159 #else
    160     .cfgr = ADC_CFGR_CONT | ADC_RESOLUTION,
    161     .smpr = {ADC_SMPR1_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN9(ADC_SAMPLING_RATE), ADC_SMPR2_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN15(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN16(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN17(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN18(ADC_SAMPLING_RATE)},
    162 #endif
    163 };
    164 
    165 // clang-format off
    166 __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
    167     switch (pin) {
    168 #if defined(STM32F0XX)
    169         case A0:  return TO_MUX( 0,  0 );
    170         case A1:  return TO_MUX( 1,  0 );
    171         case A2:  return TO_MUX( 2,  0 );
    172         case A3:  return TO_MUX( 3,  0 );
    173         case A4:  return TO_MUX( 4,  0 );
    174         case A5:  return TO_MUX( 5,  0 );
    175         case A6:  return TO_MUX( 6,  0 );
    176         case A7:  return TO_MUX( 7,  0 );
    177         case B0:  return TO_MUX( 8,  0 );
    178         case B1:  return TO_MUX( 9,  0 );
    179         case C0:  return TO_MUX( 10, 0 );
    180         case C1:  return TO_MUX( 11, 0 );
    181         case C2:  return TO_MUX( 12, 0 );
    182         case C3:  return TO_MUX( 13, 0 );
    183         case C4:  return TO_MUX( 14, 0 );
    184         case C5:  return TO_MUX( 15, 0 );
    185 #elif defined(STM32F3XX)
    186         case A0:  return TO_MUX( ADC_CHANNEL_IN1,  0 );
    187         case A1:  return TO_MUX( ADC_CHANNEL_IN2,  0 );
    188         case A2:  return TO_MUX( ADC_CHANNEL_IN3,  0 );
    189         case A3:  return TO_MUX( ADC_CHANNEL_IN4,  0 );
    190         case A4:  return TO_MUX( ADC_CHANNEL_IN1,  1 );
    191         case A5:  return TO_MUX( ADC_CHANNEL_IN2,  1 );
    192         case A6:  return TO_MUX( ADC_CHANNEL_IN3,  1 );
    193         case A7:  return TO_MUX( ADC_CHANNEL_IN4,  1 );
    194         case B0:  return TO_MUX( ADC_CHANNEL_IN12, 2 );
    195         case B1:  return TO_MUX( ADC_CHANNEL_IN1,  2 );
    196         case B2:  return TO_MUX( ADC_CHANNEL_IN12, 1 );
    197         case B12: return TO_MUX( ADC_CHANNEL_IN3,  3 );
    198         case B13: return TO_MUX( ADC_CHANNEL_IN5,  2 );
    199         case B14: return TO_MUX( ADC_CHANNEL_IN4,  3 );
    200         case B15: return TO_MUX( ADC_CHANNEL_IN5,  3 );
    201         case C0:  return TO_MUX( ADC_CHANNEL_IN6,  0 ); // Can also be ADC2
    202         case C1:  return TO_MUX( ADC_CHANNEL_IN7,  0 ); // Can also be ADC2
    203         case C2:  return TO_MUX( ADC_CHANNEL_IN8,  0 ); // Can also be ADC2
    204         case C3:  return TO_MUX( ADC_CHANNEL_IN9,  0 ); // Can also be ADC2
    205         case C4:  return TO_MUX( ADC_CHANNEL_IN5,  1 );
    206         case C5:  return TO_MUX( ADC_CHANNEL_IN11, 1 );
    207         case D8:  return TO_MUX( ADC_CHANNEL_IN12, 3 );
    208         case D9:  return TO_MUX( ADC_CHANNEL_IN13, 3 );
    209         case D10: return TO_MUX( ADC_CHANNEL_IN7,  2 ); // Can also be ADC4
    210         case D11: return TO_MUX( ADC_CHANNEL_IN8,  2 ); // Can also be ADC4
    211         case D12: return TO_MUX( ADC_CHANNEL_IN9,  2 ); // Can also be ADC4
    212         case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4
    213         case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4
    214         case E7:  return TO_MUX( ADC_CHANNEL_IN13, 2 );
    215         case E8:  return TO_MUX( ADC_CHANNEL_IN6,  2 ); // Can also be ADC4
    216         case E9:  return TO_MUX( ADC_CHANNEL_IN2,  2 );
    217         case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 );
    218         case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 );
    219         case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 );
    220         case E13: return TO_MUX( ADC_CHANNEL_IN3,  2 );
    221         case E14: return TO_MUX( ADC_CHANNEL_IN1,  3 );
    222         case E15: return TO_MUX( ADC_CHANNEL_IN2,  3 );
    223         case F2:  return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2
    224         case F4:  return TO_MUX( ADC_CHANNEL_IN5,  0 );
    225 #elif defined(STM32F4XX)
    226         case A0:  return TO_MUX( ADC_CHANNEL_IN0,  0 );
    227         case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 );
    228         case A2:  return TO_MUX( ADC_CHANNEL_IN2,  0 );
    229         case A3:  return TO_MUX( ADC_CHANNEL_IN3,  0 );
    230         case A4:  return TO_MUX( ADC_CHANNEL_IN4,  0 );
    231         case A5:  return TO_MUX( ADC_CHANNEL_IN5,  0 );
    232         case A6:  return TO_MUX( ADC_CHANNEL_IN6,  0 );
    233         case A7:  return TO_MUX( ADC_CHANNEL_IN7,  0 );
    234         case B0:  return TO_MUX( ADC_CHANNEL_IN8,  0 );
    235         case B1:  return TO_MUX( ADC_CHANNEL_IN9,  0 );
    236         case C0:  return TO_MUX( ADC_CHANNEL_IN10, 0 );
    237         case C1:  return TO_MUX( ADC_CHANNEL_IN11, 0 );
    238         case C2:  return TO_MUX( ADC_CHANNEL_IN12, 0 );
    239         case C3:  return TO_MUX( ADC_CHANNEL_IN13, 0 );
    240         case C4:  return TO_MUX( ADC_CHANNEL_IN14, 0 );
    241         case C5:  return TO_MUX( ADC_CHANNEL_IN15, 0 );
    242 #    if STM32_ADC_USE_ADC3
    243         case F3:  return TO_MUX( ADC_CHANNEL_IN9,  2 );
    244         case F4:  return TO_MUX( ADC_CHANNEL_IN14, 2 );
    245         case F5:  return TO_MUX( ADC_CHANNEL_IN15, 2 );
    246         case F6:  return TO_MUX( ADC_CHANNEL_IN4,  2 );
    247         case F7:  return TO_MUX( ADC_CHANNEL_IN5,  2 );
    248         case F8:  return TO_MUX( ADC_CHANNEL_IN6,  2 );
    249         case F9:  return TO_MUX( ADC_CHANNEL_IN7,  2 );
    250         case F10: return TO_MUX( ADC_CHANNEL_IN8,  2 );
    251 #    endif
    252 #elif defined(STM32F1XX) || defined(GD32VF103) || defined(WB32F3G71xx) || defined(WB32FQ95xx) || defined(AT32F415)
    253         case A0:  return TO_MUX( ADC_CHANNEL_IN0,  0 );
    254         case A1:  return TO_MUX( ADC_CHANNEL_IN1,  0 );
    255         case A2:  return TO_MUX( ADC_CHANNEL_IN2,  0 );
    256         case A3:  return TO_MUX( ADC_CHANNEL_IN3,  0 );
    257         case A4:  return TO_MUX( ADC_CHANNEL_IN4,  0 );
    258         case A5:  return TO_MUX( ADC_CHANNEL_IN5,  0 );
    259         case A6:  return TO_MUX( ADC_CHANNEL_IN6,  0 );
    260         case A7:  return TO_MUX( ADC_CHANNEL_IN7,  0 );
    261         case B0:  return TO_MUX( ADC_CHANNEL_IN8,  0 );
    262         case B1:  return TO_MUX( ADC_CHANNEL_IN9,  0 );
    263         case C0:  return TO_MUX( ADC_CHANNEL_IN10, 0 );
    264         case C1:  return TO_MUX( ADC_CHANNEL_IN11, 0 );
    265         case C2:  return TO_MUX( ADC_CHANNEL_IN12, 0 );
    266         case C3:  return TO_MUX( ADC_CHANNEL_IN13, 0 );
    267         case C4:  return TO_MUX( ADC_CHANNEL_IN14, 0 );
    268         case C5:  return TO_MUX( ADC_CHANNEL_IN15, 0 );
    269         // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the
    270         // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable.
    271 #elif defined(STM32L4XX)
    272         case A0: return TO_MUX( ADC_CHANNEL_IN5,  0 ); // Can also be ADC2 in some cases
    273         case A1: return TO_MUX( ADC_CHANNEL_IN6,  0 ); // Can also be ADC2 in some cases
    274         case A2: return TO_MUX( ADC_CHANNEL_IN7,  0 ); // Can also be ADC2
    275         case A3: return TO_MUX( ADC_CHANNEL_IN8,  0 ); // Can also be ADC2
    276         case A4: return TO_MUX( ADC_CHANNEL_IN9,  0 ); // Can also be ADC2
    277         case A5: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2
    278         case A6: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC2
    279         case A7: return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC2
    280         case B0: return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC2
    281         case B1: return TO_MUX( ADC_CHANNEL_IN16, 0 ); // Can also be ADC2
    282         case C0: return TO_MUX( ADC_CHANNEL_IN1,  0 ); // Can also be ADC2 or ADC3
    283         case C1: return TO_MUX( ADC_CHANNEL_IN2,  0 ); // Can also be ADC2 or ADC3
    284         case C2: return TO_MUX( ADC_CHANNEL_IN3,  0 ); // Can also be ADC2 or ADC3
    285         case C3: return TO_MUX( ADC_CHANNEL_IN4,  0 ); // Can also be ADC2 or ADC3
    286         case C4: return TO_MUX( ADC_CHANNEL_IN13, 0 ); // Can also be ADC2
    287         case C5: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2
    288 #    if STM32_HAS_GPIOF && STM32_ADC_USE_ADC3
    289         case F3:  return TO_MUX( ADC_CHANNEL_IN6,  2 );
    290         case F4:  return TO_MUX( ADC_CHANNEL_IN7,  2 );
    291         case F5:  return TO_MUX( ADC_CHANNEL_IN8,  2 );
    292         case F6:  return TO_MUX( ADC_CHANNEL_IN9,  2 );
    293         case F7:  return TO_MUX( ADC_CHANNEL_IN10, 2 );
    294         case F8:  return TO_MUX( ADC_CHANNEL_IN11, 2 );
    295         case F9:  return TO_MUX( ADC_CHANNEL_IN12, 2 );
    296         case F10: return TO_MUX( ADC_CHANNEL_IN13, 2 );
    297 #    endif
    298 #elif defined(STM32G0XX)
    299         case A0:  return TO_MUX( 0,  0 );
    300         case A1:  return TO_MUX( 1,  0 );
    301         case A2:  return TO_MUX( 2,  0 );
    302         case A3:  return TO_MUX( 3,  0 );
    303         case A4:  return TO_MUX( 4,  0 );
    304         case A5:  return TO_MUX( 5,  0 );
    305         case A6:  return TO_MUX( 6,  0 );
    306         case A7:  return TO_MUX( 7,  0 );
    307         case B0:  return TO_MUX( 8,  0 );
    308         case B1:  return TO_MUX( 9,  0 );
    309         case B2:  return TO_MUX( 10, 0 );
    310         case B10: return TO_MUX( 11, 0 );
    311         case B11: return TO_MUX( 15, 0 );
    312         case B12: return TO_MUX( 16, 0 );
    313         case C4:  return TO_MUX( 17, 0 );
    314         case C5:  return TO_MUX( 18, 0 );
    315 #elif defined(STM32G4XX)
    316         case A0:  return TO_MUX( ADC_CHANNEL_IN1,  0 ); // Can also be ADC2
    317         case A1:  return TO_MUX( ADC_CHANNEL_IN2,  0 ); // Can also be ADC2
    318         case A2:  return TO_MUX( ADC_CHANNEL_IN3,  0 );
    319         case A3:  return TO_MUX( ADC_CHANNEL_IN4,  0 );
    320         case A4:  return TO_MUX( ADC_CHANNEL_IN17, 1 );
    321         case A5:  return TO_MUX( ADC_CHANNEL_IN13, 1 );
    322         case A6:  return TO_MUX( ADC_CHANNEL_IN3,  1 );
    323         case A7:  return TO_MUX( ADC_CHANNEL_IN4,  1 );
    324         case B0:  return TO_MUX( ADC_CHANNEL_IN15, 0 ); // Can also be ADC3
    325         case B1:  return TO_MUX( ADC_CHANNEL_IN12, 0 ); // Can also be ADC3
    326         case B2:  return TO_MUX( ADC_CHANNEL_IN12, 1 );
    327         case B11: return TO_MUX( ADC_CHANNEL_IN14, 0 ); // Can also be ADC2
    328         case B12: return TO_MUX( ADC_CHANNEL_IN11, 0 ); // Can also be ADC4
    329         case B13: return TO_MUX( ADC_CHANNEL_IN5,  2 );
    330         case B14: return TO_MUX( ADC_CHANNEL_IN5,  0 ); // Can also be ADC4
    331         case B15: return TO_MUX( ADC_CHANNEL_IN15, 1 ); // Can also be ADC4
    332         case C0:  return TO_MUX( ADC_CHANNEL_IN6,  0 ); // Can also be ADC2
    333         case C1:  return TO_MUX( ADC_CHANNEL_IN7,  0 ); // Can also be ADC2
    334         case C2:  return TO_MUX( ADC_CHANNEL_IN8,  0 ); // Can also be ADC2
    335         case C3:  return TO_MUX( ADC_CHANNEL_IN9,  0 ); // Can also be ADC2
    336         case C4:  return TO_MUX( ADC_CHANNEL_IN5,  1 );
    337         case C5:  return TO_MUX( ADC_CHANNEL_IN11, 1 );
    338         case D8:  return TO_MUX( ADC_CHANNEL_IN12, 3 );
    339         case D9:  return TO_MUX( ADC_CHANNEL_IN13, 3 );
    340         case D10: return TO_MUX( ADC_CHANNEL_IN7,  2 ); // Can also be ADC4
    341         case D11: return TO_MUX( ADC_CHANNEL_IN8,  2 ); // Can also be ADC4
    342         case D12: return TO_MUX( ADC_CHANNEL_IN9,  2 ); // Can also be ADC4
    343         case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4
    344         case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4
    345         case E5:  return TO_MUX( ADC_CHANNEL_IN2,  3 );
    346         case E7:  return TO_MUX( ADC_CHANNEL_IN4,  2 );
    347         case E8:  return TO_MUX( ADC_CHANNEL_IN6,  2 ); // Can also be ADC4
    348         case E9:  return TO_MUX( ADC_CHANNEL_IN2,  2 );
    349         case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 ); // Can also be ADC4
    350         case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 ); // Can also be ADC4
    351         case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 ); // Can also be ADC4
    352         case E13: return TO_MUX( ADC_CHANNEL_IN3,  2 );
    353         case E14: return TO_MUX( ADC_CHANNEL_IN1,  3 );
    354         case F0:  return TO_MUX( ADC_CHANNEL_IN10, 0 );
    355         case F1:  return TO_MUX( ADC_CHANNEL_IN10, 1 );
    356 #elif defined(RP2040)
    357         case 26U: return TO_MUX(0, 0);
    358         case 27U: return TO_MUX(1, 0);
    359         case 28U: return TO_MUX(2, 0);
    360         case 29U: return TO_MUX(3, 0);
    361 #endif
    362     }
    363 
    364     // return an adc that would never be used so intToADCDriver will bail out
    365     return TO_MUX(0, 0xFF);
    366 }
    367 // clang-format on
    368 
    369 static inline ADCDriver* intToADCDriver(uint8_t adcInt) {
    370     switch (adcInt) {
    371 #if RP_ADC_USE_ADC1 || STM32_ADC_USE_ADC1 || WB32_ADC_USE_ADC1 || AT32_ADC_USE_ADC1
    372         case 0:
    373             return &ADCD1;
    374 #endif
    375 #if STM32_ADC_USE_ADC2
    376         case 1:
    377             return &ADCD2;
    378 #endif
    379 #if STM32_ADC_USE_ADC3
    380         case 2:
    381             return &ADCD3;
    382 #endif
    383 #if STM32_ADC_USE_ADC4
    384         case 3:
    385             return &ADCD4;
    386 #endif
    387     }
    388 
    389     return NULL;
    390 }
    391 
    392 static inline void manageAdcInitializationDriver(uint8_t adc, ADCDriver* adcDriver) {
    393     if (!adcInitialized[adc]) {
    394         adcStart(adcDriver, &adcCfg);
    395         adcInitialized[adc] = true;
    396     }
    397 }
    398 
    399 int16_t analogReadPin(pin_t pin) {
    400     palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
    401 
    402     return adc_read(pinToMux(pin));
    403 }
    404 
    405 int16_t analogReadPinAdc(pin_t pin, uint8_t adc) {
    406     palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
    407 
    408     adc_mux target = pinToMux(pin);
    409     target.adc     = adc;
    410     return adc_read(target);
    411 }
    412 
    413 int16_t adc_read(adc_mux mux) {
    414 #if defined(USE_ADCV1)
    415     // TODO: fix previous assumption of only 1 input...
    416     adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/
    417 #elif defined(USE_ADCV2)
    418 #    if defined(AT32F415)
    419     adcConversionGroup.osq3 = ADC_OSQ3_OSN1_N(mux.input);
    420 #    else
    421     adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input);
    422 #    endif
    423 #elif defined(RP2040)
    424     adcConversionGroup.channel_mask = 1 << mux.input;
    425 #else
    426     adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input)
    427 #    if ADC_DUMMY_CONVERSIONS_AT_START >= 1
    428                                 | ADC_SQR1_SQ2_N(mux.input)
    429 #    endif
    430         ;
    431 #endif
    432 
    433     ADCDriver* targetDriver = intToADCDriver(mux.adc);
    434     if (!targetDriver) {
    435         return 0;
    436     }
    437 
    438     manageAdcInitializationDriver(mux.adc, targetDriver);
    439     if (adcConvert(targetDriver, &adcConversionGroup, &sampleBuffer[0], ADC_BUFFER_DEPTH) != MSG_OK) {
    440         return 0;
    441     }
    442 
    443 #if defined(USE_ADCV2) || defined(RP2040)
    444     // fake 12-bit -> N-bit scale
    445     return (sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START]) >> (12 - ADC_RESOLUTION);
    446 #else
    447     // already handled as part of adcConvert
    448     return sampleBuffer[ADC_DUMMY_CONVERSIONS_AT_START];
    449 #endif
    450 }