aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/src/adc.hpp
blob: bff03b0d6808615a43bf3ac76bc2667b04f928bd (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
#pragma once

#include "hardware/adc.h"
#include <array>
#include <cstdint>
#include <algorithm>

namespace
{

std::array<std::uint8_t, 2> previous_samples { 0xffu, 0xffu };

std::uint8_t
raw_to_midi(std::uint16_t new_raw, std::uint8_t previous_midi)
{
    std::int32_t constexpr interval = 4096 / 128;
    std::int32_t constexpr hysteresis = 3;
    std::int32_t const lower = std::max(0l, static_cast<std::int32_t>(previous_midi) * interval - hysteresis);
    std::int32_t const upper = std::min(4095l, lower + interval - 1l + hysteresis);
    std::uint8_t const new_midi = static_cast<uint8_t>(new_raw * 128u / 4096u);
    return new_raw > upper || new_raw < lower ? new_midi : previous_midi;
}

}

namespace adc
{

struct Sample
{
    std::uint16_t raw {0};
    std::uint8_t midi {0};
    bool changed {false};
};

void
init()
{
    adc_init();
    adc_gpio_init(26);
    adc_gpio_init(27);
}

std::array<Sample, 2>
get_samples()
{
    std::array<Sample, 2> samples {};
    for (std::size_t i = 0; i < samples.size(); i++)
    {
        adc_select_input(i);

        auto & sample = samples[i];
        sample.raw = adc_read();
        sample.midi = raw_to_midi(sample.raw, sample.midi);
        sample.changed = samples[i].midi != previous_samples[i];

        previous_samples[i] = sample.midi;
    }

    return samples;
}

}