Line data Source code
1 : // --------------------------------------------------------------------------- 2 : // USB EPROM/Flash Programmer 3 : // 4 : // Copyright (2022) Robson Martins 5 : // 6 : // This work is licensed under a Creative Commons Attribution-NonCommercial- 7 : // ShareAlike 4.0 International License. 8 : // --------------------------------------------------------------------------- 9 : /** 10 : * @ingroup Firmware 11 : * @file hal/adc.cpp 12 : * @brief Implementation of the Pico ADC Class. 13 : * 14 : * @author Robson Martins (https://www.robsonmartins.com) 15 : */ 16 : // --------------------------------------------------------------------------- 17 : 18 : #include <vector> 19 : 20 : #include "hal/adc.hpp" 21 : 22 : #include "hardware/gpio.h" 23 : #include "hardware/adc.h" 24 : 25 : // --------------------------------------------------------------------------- 26 : 27 : constexpr uint kGpioPinAdcChannel0 = 26; 28 : constexpr uint kAdcMaxChannel = 3; 29 : 30 : /** @cond */ 31 : float __not_in_flash_func(adc_capture)(uint channel, uint16_t *buf, 32 : size_t size); 33 : /** @endcond */ 34 : 35 : // --------------------------------------------------------------------------- 36 : 37 38 : Adc::Adc() : vref_(kAdcDefaultVRef) { 38 38 : adc_init(); 39 38 : } 40 : 41 18 : Adc::Adc(float vref) : vref_(vref) { 42 18 : adc_init(); 43 18 : } 44 : 45 2 : float Adc::capture(uint channel) { 46 2 : if (!initChannel_(channel)) { 47 0 : return -1.0f; 48 : } 49 2 : adc_select_input(channel); 50 2 : return calculate_(adc_read()); 51 : } 52 : 53 225396 : float Adc::capture(uint channel, size_t size) { 54 225396 : if (!size || !initChannel_(channel)) { 55 0 : return -1.0f; 56 : } 57 225396 : adc_select_input(channel); 58 225396 : std::vector<uint16_t> raw(size); 59 225396 : return calculate_(adc_capture(channel, raw.data(), size)); 60 225396 : } 61 : 62 1 : float Adc::capture(uint channel, float *buf, size_t size) { 63 1 : if (!size || !buf || !initChannel_(channel)) { 64 0 : return -1.0f; 65 : } 66 1 : adc_select_input(channel); 67 1 : std::vector<uint16_t> raw(size); 68 1 : float result = calculate_(adc_capture(channel, raw.data(), size)); 69 513 : for (size_t i = 0; i < size; i++) { 70 512 : buf[i] = calculate_(raw[i]); 71 : } 72 1 : return result; 73 1 : } 74 : 75 225399 : bool Adc::initChannel_(uint channel) { 76 225399 : if (channel > kAdcMaxChannel) { 77 0 : return false; 78 : } 79 225399 : if (initChannels_.find(channel) != initChannels_.end()) { 80 225388 : return true; 81 : } 82 : // Make sure GPIO is high-impedance, no pullups etc 83 11 : adc_gpio_init(channel + kGpioPinAdcChannel0); 84 11 : initChannels_.insert(channel); 85 11 : return true; 86 : } 87 : 88 225911 : float Adc::calculate_(uint16_t value) const { 89 225911 : float result = value * vref_ / (1 << 12); 90 225911 : return result; 91 : } 92 : 93 : // --------------------------------------------------------------------------- 94 : 95 : /** @cond */ 96 225397 : float __not_in_flash_func(adc_capture)(uint channel, uint16_t *buf, 97 : size_t size) { 98 225397 : adc_fifo_setup(true, false, 0, false, false); 99 225397 : adc_run(true); 100 225397 : float mbuf = 0.0f; 101 225621933 : for (int i = 0; i < size; i = i + 1) { 102 225396536 : buf[i] = adc_fifo_get_blocking(); 103 225396536 : mbuf += buf[i]; 104 : } 105 225397 : adc_run(false); 106 225397 : adc_fifo_drain(); 107 225397 : return (mbuf / size); 108 : } 109 : /** @endcond */