diff --git a/adc/adc.ino b/adc/adc.ino
index a7485445e5ff63e6ce4a914e4a9e8cc21ddb7823..f801821389a7952f89054a1d8967d4ade0034640 100644
--- a/adc/adc.ino
+++ b/adc/adc.ino
@@ -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.