Commit e9a40fad authored by Erik Strand's avatar Erik Strand

Expand initADC

parent 5fe09109
......@@ -23,32 +23,74 @@ static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
return value << (to-from);
}
/* ----------------------------------------------------------------------------------------------
* Initialize Analog Controller
*/
void bm_initADC(void) {
// Load ADC factory calibration values
#if !defined(DISABLE_ADC_CALIBRATION)
// ADC Bias Calibration
uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
// ADC Linearity bits 4:0
uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
// ADC Linearity bits 7:5
linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
syncADC(); // Wait for synchronization of registers between the clock domains
#endif
// Setting clock, prescaler and resolution
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY );
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 | // Divide Clock by 512.
ADC_CTRLB_RESSEL_10BIT; // 10 bits resolution as default
syncADC(); // Wait for synchronization of registers between the clock domains
// Setting configuration
ADC->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length
syncADC(); // Wait for synchronization of registers between the clock domains
ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground)
syncADC(); // Wait for synchronization of registers between the clock domains
// Averaging (see datasheet table in AVGCTRL register description)
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // 1 sample only (no oversampling nor averaging)
ADC_AVGCTRL_ADJRES(0x0ul); // Adjusting result by 0
syncADC(); // Wait for synchronization of registers between the clock domains
analogReference( VARIANT_AR_DEFAULT ) ; // Use default reference from variant.h
}
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) ;
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) ;
PORT->Group[pinPort].PMUX[pinNum >> 1].reg = temp | PORT_PMUX_PMUXE(PER_ANALOG) ;
}
// Set pin drive strength to normal, leave the input pullup setting alone, clear INEN, and
// enable peripheral mux.
uint8_t pinCfg = (PORT->Group[pinPort].PINCFG[pinNum].reg & PORT_PINCFG_PULLEN);
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 ;
}
uint32_t bm_analogRead( uint32_t pin )
{
uint32_t valueRead = 0;
......@@ -72,7 +114,7 @@ void setup() {
digitalWrite(CHARGE_LINE_0, LOW);
// Initialize the ADC
initADC();
bm_initADC();
// 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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment