adc.ino 2.98 KB
Newer Older
Erik Strand's avatar
Erik Strand committed
1 2
#include "wiring_private.h"

3
#define LED_GREEN 23
4
#define CHARGE_LINE_0 14
5 6 7 8
#define SENSE_LINE_0 2

int value;

Erik Strand's avatar
Erik Strand committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Note that these values need to be kept in sync with the originals in analog_wiring.c.
static int _readResolution = 10;
static int _ADCResolution = 10;

// Wait for synchronization of registers between the clock domains
static __inline__ void syncADC() __attribute__((always_inline, unused));
static void syncADC() { while ( ADC->STATUS.bit.SYNCBUSY == 1 ); }

static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
{
    if (from == to) {
        return value;
    }
    if (from > to) {
        return value >> (from-to);
    }
    return value << (to-from);
}

Erik Strand's avatar
Erik Strand committed
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
void init_pin_adc(uint32_t pin) {
    uint8_t const pinPort = GetPort(pin);
    uint8_t const pinNum = GetPin(pin);

    // Preserve state of pullup/pulldown enable, clear the rest of the bits
    uint8_t pinCfg = (PORT->Group[pinPort].PINCFG[pinNum].reg & PORT_PINCFG_PULLEN);

    if ( pinNum & 1 ) // is pin odd?
    {
        // Get whole current setup for both odd and even pins and remove odd one, then set new muxing
        uint32_t temp = (PORT->Group[pinPort].PMUX[pinNum >> 1].reg) & PORT_PMUX_PMUXE( 0xF ) ;
        PORT->Group[pinPort].PMUX[pinNum >> 1].reg = temp|PORT_PMUX_PMUXO(PER_ANALOG) ;
    }
    else // even pin
    {
        // Get whole current setup for both odd and even pins and remove even one, then set new muxing
        uint32_t temp = (PORT->Group[pinPort].PMUX[pinNum >> 1].reg) & PORT_PMUX_PMUXO( 0xF ) ;
        PORT->Group[pinPort].PMUX[pinNum >> 1].reg = temp|PORT_PMUX_PMUXE(PER_ANALOG) ;
    }

    pinCfg |= PORT_PINCFG_PMUXEN; // Enable peripheral mux

    // Set pin drive strength, enable/disable pull resistor, enable/disable INEN, and enable/disable the peripheral mux
    PORT->Group[pinPort].PINCFG[pinNum].reg = (uint8_t)pinCfg ;
}
Erik Strand's avatar
Erik Strand committed
53 54 55 56 57

uint32_t bm_analogRead( uint32_t pin )
{
    uint32_t valueRead = 0;

Erik Strand's avatar
Erik Strand committed
58 59 60
    // Start conversion
    ADC->SWTRIG.bit.START = 1;
    syncADC();
Erik Strand's avatar
Erik Strand committed
61

Erik Strand's avatar
Erik Strand committed
62 63 64
    // Store the value
    while (ADC->INTFLAG.bit.RESRDY == 0);   // Waiting for conversion to complete
    valueRead = ADC->RESULT.reg;
Erik Strand's avatar
Erik Strand committed
65 66 67 68 69

    return mapResolution(valueRead, _ADCResolution, _readResolution);
}


70 71 72
void setup() {
    Serial.begin(9600);
    pinMode(LED_GREEN, OUTPUT);
73 74
    pinMode(CHARGE_LINE_0, OUTPUT);
    digitalWrite(CHARGE_LINE_0, LOW);
75 76 77

    // Initialize the ADC
    initADC();
78

Erik Strand's avatar
Erik Strand committed
79 80 81 82
    // Everything seems to function if I don't do this, but I'm leaving it in until I have a chance
    // to investigate what's happening.
    init_pin_adc(SENSE_LINE_0);

83 84 85 86 87 88 89
    // Selection for the positive ADC input
    ADC->INPUTCTRL.bit.MUXPOS = GetADC(SENSE_LINE_0);
    syncADC();

    // Enable ADC
    ADC->CTRLA.bit.ENABLE = 0x01;
    syncADC();
90 91 92
}

void loop() {
93 94 95
    digitalWrite(CHARGE_LINE_0, LOW);
    delay(1000);

Erik Strand's avatar
Erik Strand committed
96
    value = bm_analogRead(SENSE_LINE_0);
97
    Serial.println(value);
98 99

    digitalWrite(CHARGE_LINE_0, HIGH);
100
    delay(1000);
101 102 103

    value = bm_analogRead(SENSE_LINE_0);
    Serial.println(value);
104
}