aboutsummaryrefslogtreecommitdiffstats
path: root/source/adc.cpp
blob: 4e68a6e742050e1c29c84dbe4b296bdcb77dfc53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
 * @file adc.cpp
 * @brief Wrapper for ChibiOS's ADCDriver.
 *
 * Copyright (C) 2020 Clyne Sullivan
 *
 * Distributed under the GNU GPL v3 or later. You should have received a copy of
 * the GNU General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 */

#include "adc.hpp"

const GPTConfig ADCd::m_gpt_config = {
  .frequency    =  1000000,
  .callback     =  NULL,
  .cr2          =  TIM_CR2_MMS_1,   /* MMS = 010 = TRGO on Update Event.    */
  .dier         =  0
};

void ADCd::start()
{
    initPins();
    gptStart(m_gptd, &m_gpt_config);

    m_adc_config.difsel = 0;
    m_adc_config.adcdinst = this;

    adcStart(m_adcd, &m_adc_config);
    adcSTM32EnableVREF(m_adcd);
}

adcsample_t *ADCd::getSamples(adcsample_t *buffer, size_t count)
{
    m_is_adc_finished = false;
    adcStartConversion(m_adcd, &m_adc_group_config, buffer, count);
    gptStartContinuous(m_gptd, 100); // 10kHz
    while (!m_is_adc_finished);
    return buffer;
}

void ADCd::setSampleRate(ADCdRate rate)
{
    uint32_t val = 0;

    switch (rate) {
    case ADCdRate::R2P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5);
        break;
    case ADCdRate::R6P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_6P5);
        break;
    case ADCdRate::R12P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5);
        break;
    case ADCdRate::R24P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5);
        break;
    case ADCdRate::R47P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_47P5);
        break;
    case ADCdRate::R92P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_92P5);
        break;
    case ADCdRate::R247P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5);
        break;
    case ADCdRate::R640P5:
        val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_640P5);
        break;
    }

    m_adc_group_config.smpr[0] = val;
}

void ADCd::initPins()
{
    palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG);
}

void ADCd::adcEndCallback(ADCDriver *adcd)
{
    auto *_this = reinterpret_cast<const ADCdConfig *>(adcd->config)->adcdinst;
    gptStopTimer(_this->m_gptd);
    _this->m_is_adc_finished = true;
}