Beispiel #1
0
/* Set the number of averages: 0, 4, 8, 16 or 32.
*
*/
void ADC_Module::setAveraging(uint8_t num) {

	if (calibrating) wait_for_cal();

	if (num <= 1) {
		num = 0;
		//*ADC_SC3 &= ~ADC_SC3_AVGE;
		*ADC_SC3_avge = 0;
	} else {
	    *ADC_SC3_avge = 1;
	    if (num <= 4) {
            num = 4;
            //*ADC_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(0);
            *ADC_SC3_avgs0 = 0;
            *ADC_SC3_avgs1 = 0;
        } else if (num <= 8) {
            num = 8;
            //*ADC_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(1);
            *ADC_SC3_avgs0 = 1;
            *ADC_SC3_avgs1 = 0;
        } else if (num <= 16) {
            num = 16;
            //*ADC_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(2);
            *ADC_SC3_avgs0 = 0;
            *ADC_SC3_avgs1 = 1;
        } else {
            num = 32;
            //*ADC_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(3);
            *ADC_SC3_avgs0 = 1;
            *ADC_SC3_avgs1 = 1;
        }
	}
	analog_num_average = num;
}
Beispiel #2
0
/* Enable the compare function: A conversion will be completed only when the ADC value
*  is inside (insideRange=1) or outside (=0) the range given by (lowerLimit, upperLimit),
*  including (inclusive=1) the limits or not (inclusive=0).
*  See Table 31-78, p. 617 of the freescale manual.
*  Call it after changing the resolution
*/
void ADC_Module::enableCompareRange(int16_t lowerLimit, int16_t upperLimit, bool insideRange, bool inclusive) {

    if (calibrating) wait_for_cal(); // if we modify the adc's registers when calibrating, it will fail

    *ADC_SC2_cfe = 1; // enable compare
    *ADC_SC2_cren = 1; // enable compare range

    if(insideRange && inclusive) { // True if value is inside the range, including the limits. CV1 <= CV2 and ACFGT=1
        //*ADC_SC2 |= ADC_SC2_ACFE | ADC_SC2_ACFGT | ADC_SC2_ACREN;
        *ADC_SC2_cfgt = 1;

        *ADC_CV1 = (int16_t)lowerLimit;
        *ADC_CV2 = (int16_t)upperLimit;
    } else if(insideRange && !inclusive) {// True if value is inside the range, excluding the limits. CV1 > CV2 and ACFGT=0
        //*ADC_SC2 |= ADC_SC2_ACFE | ADC_SC2_ACREN;
        *ADC_SC2_cfgt = 0;

        *ADC_CV2 = (int16_t)lowerLimit;
        *ADC_CV1 = (int16_t)upperLimit;
    } else if(!insideRange && inclusive) { // True if value is outside of range or is equal to either limit. CV1 > CV2 and ACFGT=1
        //*ADC_SC2 |= ADC_SC2_ACFE | ADC_SC2_ACFGT | ADC_SC2_ACREN;
        *ADC_SC2_cfgt = 1;

        *ADC_CV2 = (int16_t)lowerLimit;
        *ADC_CV1 = (int16_t)upperLimit;
    } else if(!insideRange && !inclusive) { // True if value is outside of range and not equal to either limit. CV1 > CV2 and ACFGT=0
        //*ADC_SC2 |= ADC_SC2_ACFE | ADC_SC2_ACREN;
        *ADC_SC2_cfgt = 0;

        *ADC_CV1 = (int16_t)lowerLimit;
        *ADC_CV2 = (int16_t)upperLimit;
    }
}
Beispiel #3
0
/* Enable DMA request: An ADC DMA request will be raised when the conversion is completed
*  (including hardware averages and if the comparison (if any) is true).
*/
void ADC_Module::enableDMA() {

    if (calibrating) wait_for_cal();

    //*ADC_SC2 |= ADC_SC2_DMAEN;
    *ADC_SC2_dma = 1;
}
Beispiel #4
0
/* Starts continuous and differential conversion between the pins (pinP-pinN)
 * It returns as soon as the ADC is set, use analogReadContinuous() to read the value
 * Set the resolution, number of averages and voltage reference using the appropriate functions BEFORE calling this function
*/
bool ADC_Module::startContinuousDifferential(uint8_t pinP, uint8_t pinN) {

    if(!checkDifferentialPins(pinP, pinN)) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return false;   // all others are invalid
    }

    // increase the counter of measurements
    num_measurements++;

    // check for calibration before setting channels,
    // because conversion will start as soon as we write to *ADC_SC1A
    if (calibrating) wait_for_cal();

    // save the current state of the ADC in case it's in use
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        saveConfig(&adc_config);
        __enable_irq();
    }

    // set continuous mode
    continuousMode();

    // start conversions
    startDifferentialFast(pinP, pinN);

    return true;
}
Beispiel #5
0
/* Enables the PGA and sets the gain
*   Use only for signals lower than 1.2 V
*   \param gain can be 1, 2, 4, 8, 16 32 or 64
*
*/
void ADC_Module::enablePGA(uint8_t gain) {
    #if defined(__MK20DX256__)

    if (calibrating) wait_for_cal();

    uint8_t setting;
    if(gain <= 1) {
        setting = 0;
    } else if(gain<=2){
        setting = 1;
    } else if(gain<=4){
        setting = 2;
    } else if(gain<=8){
        setting = 3;
    } else if(gain<=16){
        setting = 4;
    } else if(gain<=32){
        setting = 5;
    } else { // 64
        setting = 6;
    }

    *ADC_PGA = ADC_PGA_PGAEN | ADC_PGA_PGAG(setting);
    pga_value=1<<setting;
    #endif
}
Beispiel #6
0
/* Starts an analog measurement on the pin.
*  It returns inmediately, read value with readSingle().
*  If the pin is incorrect it returns ADC_ERROR_VALUE.
*/
bool ADC_Module::startSingleRead(uint8_t pin) {

    // check whether the pin is correct
    if(!checkPin(pin)) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return false;
    }

    if (calibrating) wait_for_cal();

    // save the current state of the ADC in case it's in use
    adcWasInUse = isConverting(); // is the ADC running now?

    if(adcWasInUse) { // this means we're interrupting a conversion
        // save the current conversion config, the adc isr will restore the adc
        __disable_irq();
        saveConfig(&adc_config);
        __enable_irq();
    }

    // no continuous mode
    singleMode();

    // start measurement
    startReadFast(pin);

    return true;
}
Beispiel #7
0
/* Reads the differential analog value of two pins (pinP - pinN)
* It waits until the value is read and then returns the result
* If a comparison has been set up and fails, it will return ADC_ERROR_DIFF_VALUE
* Set the resolution, number of averages and voltage reference using the appropriate functions
*/
int ADC_Module::analogReadDifferential(uint8_t pinP, uint8_t pinN)
{
	int32_t result;

	if( ((pinP != A10) && (pinP != A12)) || ((pinN != A11) && (pinN != A13)) ) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return ADC_ERROR_DIFF_VALUE;   // all others are invalid
	}

	// increase the counter of measurements
	num_measurements++;

	// check for calibration before setting channels,
	// because conversion will start as soon as we write to *ADC_SC1A
	if (calibrating) wait_for_cal();

	uint8_t res = getResolution();

    // vars to saved the current state of the ADC in case it's in use
    ADC_Config old_config = {0};
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        old_config.savedSC1A = *ADC_SC1A;
        old_config.savedCFG1 = *ADC_CFG1;
        old_config.savedCFG2 = *ADC_CFG2;
        old_config.savedSC2 = *ADC_SC2;
        old_config.savedSC3 = *ADC_SC3;
        __enable_irq();
    }

    // no continuous mode
    *ADC_SC3_adco = 0;

    // once *ADC_SC1A is set, conversion will start, enable interrupts if requested
	if ( (pinP == A10) && (pinN == A11) ) { // pins 34 and 35
        __disable_irq();
        #if defined(__MK20DX256__)
        if ( *ADC_PGA & ADC_PGA_PGAEN ) { // PGA is enabled
            if(ADC_num == 0) { // PGA0 connects to A10-A11
                *ADC_SC1A = ADC_SC1_DIFF + 0x2 + var_enableInterrupts*ADC_SC1_AIEN;
                __enable_irq();
            } else { // If this is ADC1 we can't connect to PGA0
                __enable_irq();
                fail_flag |= ADC_ERROR_WRONG_ADC;
                num_measurements--;
                return ADC_ERROR_DIFF_VALUE;
            }
        } else { // no pga
            if(ADC_num == 0) {
                *ADC_SC1A = ADC_SC1_DIFF + 0x0 + var_enableInterrupts*ADC_SC1_AIEN; // In ADC0, A10-A11 is DAD0
                __enable_irq();
            } else if(ADC_num == 1) {
                *ADC_SC1A = ADC_SC1_DIFF + 0x3 + var_enableInterrupts*ADC_SC1_AIEN; // In ADC1, A10-A11 is DAD3
                __enable_irq()
            }
        }
Beispiel #8
0
int analogRead(uint8_t pin)
{
	int result;

	if (pin >= 14) {
		if (pin <= 23) {
			pin -= 14;  // 14-23 are A0-A9
		} else if (pin >= 34 && pin <= 39) {
			pin -= 24;  // 34-37 are A10-A13, 38 is temp sensor, 39 is vref
		} else {
			return 0;   // all others are invalid
		}
	}
	//serial_print("analogRead");
	//return 0;
	if (calibrating) wait_for_cal();
	//pin = 5; // PTD1/SE5b, pin 14, analog 0

	ADC0_SC1A = channel2sc1a[pin];
	while ((ADC0_SC1A & ADC_SC1_COCO) == 0) {
		// wait
		//serial_print(".");
	}
	//serial_print("\n");
	result = ADC0_RA >> analog_right_shift;
	//serial_phex16(result >> 3);
	//serial_print("\n");
	return result;
}
Beispiel #9
0
void analogReadAveraging(unsigned int num)
{

	if (calibrating) wait_for_cal();
	if (num <= 1) {
		num = 0;
		ADC0_SC3 = 0;
	} else if (num <= 4) {
		num = 4;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#ifdef HAS_KINETIS_ADC1
		ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#endif
	} else if (num <= 8) {
		num = 8;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#ifdef HAS_KINETIS_ADC1
		ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#endif
	} else if (num <= 16) {
		num = 16;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#ifdef HAS_KINETIS_ADC1
		ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#endif
	} else {
		num = 32;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#ifdef HAS_KINETIS_ADC1
		ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#endif
	}
	analog_num_average = num;
}
Beispiel #10
0
/* Enable DMA request: An ADC DMA request will be raised when the conversion is completed
*  (including hardware averages and if the comparison (if any) is true).
*/
void ADC_Module::enableDMA() {

    if (calibrating) wait_for_cal();

    // *ADC_SC2_dma = 1;
    setBit(ADC_SC2, ADC_SC2_DMAEN_BIT);
}
Beispiel #11
0
/* Enable the compare function: A conversion will be completed only when the ADC value
*  is >= compValue (greaterThan=1) or < compValue (greaterThan=0)
*  Call it after changing the resolution
*  Use with interrupts or poll conversion completion with isADC_Complete()
*/
void ADC_Module::enableCompare(int16_t compValue, bool greaterThan) {

    if (calibrating) wait_for_cal(); // if we modify the adc's registers when calibrating, it will fail

    //*ADC_SC2 |= ADC_SC2_ACFE | greaterThan*ADC_SC2_ACFGT;
    *ADC_SC2_cfe = 1; // enable compare
    *ADC_SC2_cfgt = (int32_t)greaterThan; // greater or less than?
    *ADC_CV1 = (int16_t)compValue; // comp value
}
Beispiel #12
0
/* Enable interrupts: An ADC Interrupt will be raised when the conversion is completed
*  (including hardware averages and if the comparison (if any) is true).
*/
void ADC_Module::enableInterrupts() {

    if (calibrating) wait_for_cal();

    var_enableInterrupts = 1;
    // *ADC_SC1A_aien = 1;
    setBit(ADC_SC1A, ADC_SC1A_AIEN_BIT);

    NVIC_ENABLE_IRQ(IRQ_ADC);
}
Beispiel #13
0
/* Increase the sampling speed for low impedance sources, decrease it for higher impedance ones.
* \param speed can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
    ADC_VERY_LOW_SPEED is the lowest possible sampling speed (+24 ADCK).
    ADC_LOW_SPEED adds +16 ADCK.
    ADC_MED_SPEED adds +10 ADCK.
    ADC_HIGH_SPEED (or ADC_HIGH_SPEED_16BITS) adds +6 ADCK.
    ADC_VERY_HIGH_SPEED is the highest possible sampling speed (0 ADCK added).
* It doesn't recalibrate at the end.
*/
void ADC_Module::setSamplingSpeed(uint8_t speed) {

    if(speed==sampling_speed) { // no change
        return;
    }

    if (calibrating) wait_for_cal();

    // Select between the settings
    if(speed == ADC_VERY_LOW_SPEED) {
        // *ADC_CFG1_adlsmp = 1; // long sampling time enable
        // *ADC_CFG2_adlsts1 = 0; // maximum sampling time (+24 ADCK)
        // *ADC_CFG2_adlsts0 = 0;
        setBit(ADC_CFG1, ADC_CFG1_ADLSMP_BIT);
        clearBit(ADC_CFG2, ADC_CFG2_ADLSTS1_BIT);
        clearBit(ADC_CFG2, ADC_CFG2_ADLSTS0_BIT);

    } else if(speed == ADC_LOW_SPEED) {
        // *ADC_CFG1_adlsmp = 1; // long sampling time enable
        // *ADC_CFG2_adlsts1 = 0;// high sampling time (+16 ADCK)
        // *ADC_CFG2_adlsts0 = 1;
        setBit(ADC_CFG1, ADC_CFG1_ADLSMP_BIT);
        clearBit(ADC_CFG2, ADC_CFG2_ADLSTS1_BIT);
        setBit(ADC_CFG2, ADC_CFG2_ADLSTS0_BIT);

    } else if(speed == ADC_MED_SPEED) {
        // *ADC_CFG1_adlsmp = 1; // long sampling time enable
        // *ADC_CFG2_adlsts1 = 1;// medium sampling time (+10 ADCK)
        // *ADC_CFG2_adlsts0 = 0;
        setBit(ADC_CFG1, ADC_CFG1_ADLSMP_BIT);
        setBit(ADC_CFG2, ADC_CFG2_ADLSTS1_BIT);
        clearBit(ADC_CFG2, ADC_CFG2_ADLSTS0_BIT);

    } else if( (speed == ADC_HIGH_SPEED) || (speed == ADC_HIGH_SPEED_16BITS) ) {
        // *ADC_CFG1_adlsmp = 1; // long sampling time enable
        // *ADC_CFG2_adlsts1 = 1;// low sampling time (+6 ADCK)
        // *ADC_CFG2_adlsts0 = 1;
        setBit(ADC_CFG1, ADC_CFG1_ADLSMP_BIT);
        setBit(ADC_CFG2, ADC_CFG2_ADLSTS1_BIT);
        setBit(ADC_CFG2, ADC_CFG2_ADLSTS0_BIT);

    } else if(speed == ADC_VERY_HIGH_SPEED) {
        // *ADC_CFG1_adlsmp = 0; // shortest sampling time
        clearBit(ADC_CFG1, ADC_CFG1_ADLSMP_BIT);

    } else { // incorrect speeds have no effect.
        return;
    }

    sampling_speed =  speed;

}
Beispiel #14
0
/* Change the resolution of the measurement
*  For single-ended measurements: 8, 10, 12 or 16 bits.
*  For differential measurements: 9, 11, 13 or 16 bits.
*  If you want something in between (11 bits single-ended for example) select the inmediate higher
*  and shift the result one to the right.
*
*  It doesn't recalibrate
*/
void ADC_Module::setResolution(uint8_t bits) {

    if(analog_res_bits==bits) {
        return;
    }

    uint8_t config;

    if (calibrating) wait_for_cal();

    if (bits <8) {
        config = 8;
    } else if (bits >= 14) {
        config = 16;
    } else {
        config = bits;
    }

    // conversion resolution
    // single-ended 8 bits is the same as differential 9 bits, etc.
    if ( (config == 8) || (config == 9) )  {
        // *ADC_CFG1_mode1 = 0;
        // *ADC_CFG1_mode0 = 0;
        clearBit(ADC_CFG1, ADC_CFG1_MODE1_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_MODE0_BIT);
        analog_max_val = 255; // diff mode 9 bits has 1 bit for sign, so max value is the same as single 8 bits
    } else if ( (config == 10 )|| (config == 11) ) {
        // *ADC_CFG1_mode1 = 1;
        // *ADC_CFG1_mode0 = 0;
        setBit(ADC_CFG1, ADC_CFG1_MODE1_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_MODE0_BIT);
        analog_max_val = 1023;
    } else if ( (config == 12 )|| (config == 13) ) {
        // *ADC_CFG1_mode1 = 0;
        // *ADC_CFG1_mode0 = 1;
        clearBit(ADC_CFG1, ADC_CFG1_MODE1_BIT);
        setBit(ADC_CFG1, ADC_CFG1_MODE0_BIT);
        analog_max_val = 4095;
    } else {
        // *ADC_CFG1_mode1 = 1;
        // *ADC_CFG1_mode0 = 1;
        setBit(ADC_CFG1, ADC_CFG1_MODE1_BIT);
        setBit(ADC_CFG1, ADC_CFG1_MODE0_BIT);
        analog_max_val = 65535;
    }

    analog_res_bits = config;

    // no recalibration is needed when changing the resolution, p. 619

}
Beispiel #15
0
int analogRead(uint8_t pin)
{
	int result;
	uint8_t channel;

	//serial_phex(pin);
	//serial_print(" ");

	if (pin >= sizeof(pin2sc1a)) return 0;
	channel = pin2sc1a[pin];
	if (channel == 255) return 0;

	if (calibrating) wait_for_cal();

#ifdef HAS_KINETIS_ADC1
	if (channel & 0x80) goto beginADC1;
#endif

	__disable_irq();
startADC0:
	//serial_print("startADC0\n");
#if defined(__MKL26Z64__)
	if (channel & 0x40) {
		ADC0_CFG2 &= ~ADC_CFG2_MUXSEL;
		channel &= 0x3F;
	} else {
		ADC0_CFG2 |= ADC_CFG2_MUXSEL;
	}
#endif
	ADC0_SC1A = channel;
	analogReadBusyADC0 = 1;
	__enable_irq();
	while (1) {
		__disable_irq();
		if ((ADC0_SC1A & ADC_SC1_COCO)) {
			result = ADC0_RA;
			analogReadBusyADC0 = 0;
			__enable_irq();
			result >>= analog_right_shift;
			return result;
		}
		// detect if analogRead was used from an interrupt
		// if so, our analogRead got canceled, so it must
		// be restarted.
		if (!analogReadBusyADC0) goto startADC0;
		__enable_irq();
		yield();
	}
Beispiel #16
0
/* Enable interrupts: An ADC Interrupt will be raised when the conversion is completed
*  (including hardware averages and if the comparison (if any) is true).
*/
void ADC_Module::enableInterrupts() {

    if (calibrating) wait_for_cal();

    var_enableInterrupts = 1;
    *ADC_SC1A_aien = 1;
    #if defined(__MK20DX128__)
    NVIC_ENABLE_IRQ(IRQ_ADC0);
    #elif defined(__MK20DX256__)
    if(ADC_num==1) { // enable correct interrupt
        NVIC_ENABLE_IRQ(IRQ_ADC1);
    } else {
        NVIC_ENABLE_IRQ(IRQ_ADC0);
    }
    #endif // defined
}
Beispiel #17
0
/* Starts continuous conversion on the pin
 * It returns as soon as the ADC is set, use analogReadContinuous() to read the values
 * Set the resolution, number of averages and voltage reference using the appropriate functions BEFORE calling this function
*/
bool ADC_Module::startContinuous(uint8_t pin) {

    // check whether the pin is correct
    if(!checkPin(pin)) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return false;
    }

    // check for calibration before setting channels,
    if (calibrating) wait_for_cal();

    // increase the counter of measurements
    num_measurements++;

    // set continuous conversion flag
    continuousMode();

    startReadFast(pin);

    return true;
}
Beispiel #18
0
/* Set the number of averages: 0, 4, 8, 16 or 32.
*
*/
void ADC_Module::setAveraging(uint8_t num) {

    if (calibrating) wait_for_cal();

    if (num <= 1) {
        num = 0;
        // *ADC_SC3_avge = 0;
        clearBit(ADC_SC3, ADC_SC3_AVGE_BIT);
    } else {
        // *ADC_SC3_avge = 1;
        setBit(ADC_SC3, ADC_SC3_AVGE_BIT);
        if (num <= 4) {
            num = 4;
            // *ADC_SC3_avgs0 = 0;
            // *ADC_SC3_avgs1 = 0;
            clearBit(ADC_SC3, ADC_SC3_AVGS0_BIT);
            clearBit(ADC_SC3, ADC_SC3_AVGS1_BIT);
        } else if (num <= 8) {
            num = 8;
            // *ADC_SC3_avgs0 = 1;
            // *ADC_SC3_avgs1 = 0;
            setBit(ADC_SC3, ADC_SC3_AVGS0_BIT);
            clearBit(ADC_SC3, ADC_SC3_AVGS1_BIT);
        } else if (num <= 16) {
            num = 16;
            // *ADC_SC3_avgs0 = 0;
            // *ADC_SC3_avgs1 = 1;
            clearBit(ADC_SC3, ADC_SC3_AVGS0_BIT);
            setBit(ADC_SC3, ADC_SC3_AVGS1_BIT);
        } else {
            num = 32;
            // *ADC_SC3_avgs0 = 1;
            // *ADC_SC3_avgs1 = 1;
            setBit(ADC_SC3, ADC_SC3_AVGS0_BIT);
            setBit(ADC_SC3, ADC_SC3_AVGS1_BIT);
        }
    }
    analog_num_average = num;
}
Beispiel #19
0
/* Set the number of averages: 0, 4, 8, 16 or 32.
*
*/
void ADC::setAveraging(uint8_t num)
{

	if (calibrating) wait_for_cal();
	if (num <= 1) {
		num = 0;
		ADC0_SC3 &= !ADC_SC3_AVGE;
	} else if (num <= 4) {
		num = 4;
		ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(0);
	} else if (num <= 8) {
		num = 8;
		ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(1);
	} else if (num <= 16) {
		num = 16;
		ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(2);
	} else {
		num = 32;
		ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(3);
	}
	analog_num_average = num;
}
Beispiel #20
0
/* Increase the sampling speed for low impedance sources, decrease it for higher impedance ones.
* \param speed can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
    ADC_VERY_LOW_SPEED is the lowest possible sampling speed (+24 ADCK).
    ADC_LOW_SPEED adds +16 ADCK.
    ADC_MED_SPEED adds +10 ADCK.
    ADC_HIGH_SPEED (or ADC_HIGH_SPEED_16BITS) adds +6 ADCK.
    ADC_VERY_HIGH_SPEED is the highest possible sampling speed (0 ADCK added).
* It doesn't recalibrate at the end.
*/
void ADC_Module::setSamplingSpeed(uint8_t speed) {

    if(speed==sampling_speed) { // no change
        return;
    }

    if (calibrating) wait_for_cal();

    // Select between the settings
    if(speed == ADC_VERY_LOW_SPEED) {
        *ADC_CFG1_adlsmp = 1; // long sampling time enable
        *ADC_CFG2_adlsts1 = 0; // maximum sampling time (+24 ADCK)
        *ADC_CFG2_adlsts0 = 0;

    } else if(speed == ADC_LOW_SPEED) {
        *ADC_CFG1_adlsmp = 1; // long sampling time enable
        *ADC_CFG2_adlsts1 = 0;// high sampling time (+16 ADCK)
        *ADC_CFG2_adlsts0 = 1;

    } else if(speed == ADC_MED_SPEED) {
        *ADC_CFG1_adlsmp = 1; // long sampling time enable
        *ADC_CFG2_adlsts1 = 1;// medium sampling time (+10 ADCK)
        *ADC_CFG2_adlsts0 = 0;

    } else if( (speed == ADC_HIGH_SPEED) || (speed == ADC_HIGH_SPEED_16BITS) ) {
        *ADC_CFG1_adlsmp = 1; // long sampling time enable
        *ADC_CFG2_adlsts1 = 1;// low sampling time (+6 ADCK)
        *ADC_CFG2_adlsts0 = 1;

    } else if(speed == ADC_VERY_HIGH_SPEED) {
        *ADC_CFG1_adlsmp = 0; // shortest sampling time

    }

    sampling_speed =  speed;

}
Beispiel #21
0
/* Reads the analog value of the pin.
* It waits until the value is read and then returns the result.
* If a comparison has been set up and fails, it will return ADC_ERROR_VALUE.
* Set the resolution, number of averages and voltage reference using the appropriate functions.
*/
int ADC_Module::analogRead(uint8_t pin) {

    //digitalWriteFast(LED_BUILTIN, HIGH);

    // check whether the pin is correct
    if(!checkPin(pin)) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return ADC_ERROR_VALUE;
    }

    // increase the counter of measurements
    num_measurements++;

    //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));

    if (calibrating) wait_for_cal();

    //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));

    // check if we are interrupting a measurement, store setting if so.
    // vars to save the current state of the ADC in case it's in use
    ADC_Config old_config = {0};
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        saveConfig(&old_config);
        __enable_irq();
    }


    // no continuous mode
    singleMode();

    startReadFast(pin); // start single read

    // wait for the ADC to finish
    while(isConverting()) {
        yield();
    }

    // it's done, check if the comparison (if any) was true
    int32_t result;
    __disable_irq(); // make sure nothing interrupts this part
    if (isComplete()) { // conversion succeded
        result = (uint16_t)*ADC_RA;
    } else { // comparison was false
        fail_flag |= ADC_ERROR_COMPARISON;
        result = ADC_ERROR_VALUE;
    }
    __enable_irq();

    // if we interrupted a conversion, set it again
    if (wasADCInUse) {
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        __disable_irq();
        loadConfig(&old_config);
        __enable_irq();
    }

    num_measurements--;
    return result;

} // analogRead
Beispiel #22
0
void analogReference(uint8_t type)
{
	if (calibrating) wait_for_cal();

	// TODO: implement this
}
Beispiel #23
0
int analogRead(uint8_t pin)
{
	int result;
	uint8_t index, channel;

	//serial_phex(pin);
	//serial_print(" ");

	if (pin <= 13) {
		index = pin;      // 0-13 refer to A0-A13
	} else if (pin <= 23) {
		index = pin - 14; // 14-23 are A0-A9
#if defined(__MK20DX256__)
	} else if (pin >= 26 && pin <= 31) {
		index = pin - 9;  // 26-31 are A15-A20
#endif
	} else if (pin >= 34 && pin <= 40) {
		index = pin - 24;  // 34-37 are A10-A13, 38 is temp sensor,
			    // 39 is vref, 40 is unused (A14 on Teensy 3.1)
	} else {
		return 0;   // all others are invalid
	}

	//serial_phex(index);
	//serial_print(" ");

	channel = channel2sc1a[index];
	//serial_phex(channel);
	//serial_print(" ");

	//serial_print("analogRead");
	//return 0;
	if (calibrating) wait_for_cal();
	//pin = 5; // PTD1/SE5b, pin 14, analog 0

#if defined(__MK20DX256__)
	if (channel & 0x80) goto beginADC1;
#endif

	__disable_irq();
startADC0:
	//serial_print("startADC0\n");
	ADC0_SC1A = channel;
	analogReadBusyADC0 = 1;
	__enable_irq();
	while (1) {
		__disable_irq();
		if ((ADC0_SC1A & ADC_SC1_COCO)) {
			result = ADC0_RA;
			analogReadBusyADC0 = 0;
			__enable_irq();
			result >>= analog_right_shift;
			return result;
		}
		// detect if analogRead was used from an interrupt
		// if so, our analogRead got canceled, so it must
		// be restarted.
		if (!analogReadBusyADC0) goto startADC0;
		__enable_irq();
		//yield();
	}
Beispiel #24
0
/* Reads the analog value of the pin.
* It waits until the value is read and then returns the result.
* If a comparison has been set up and fails, it will return ADC_ERROR_VALUE.
* Set the resolution, number of averages and voltage reference using the appropriate functions.
*/
int ADC_Module::analogRead(uint8_t pin)
{
	int32_t result;

	if ( (pin < 0) || (pin > 43) ) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return ADC_ERROR_VALUE;   // all others are invalid
    }

    // increase the counter of measurements
	num_measurements++;

	if (calibrating) wait_for_cal();

    // check if we are interrupting a measurement, store setting if so.
    // vars to save the current state of the ADC in case it's in use
    ADC_Config old_config = {0};
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        old_config.savedSC1A = *ADC_SC1A;
        old_config.savedCFG1 = *ADC_CFG1;
        old_config.savedCFG2 = *ADC_CFG2;
        old_config.savedSC2 = *ADC_SC2;
        old_config.savedSC3 = *ADC_SC3;
        __enable_irq();
    }

	#if defined(__MK20DX256__)
	// ADC1 has A15=5a and A20=4a so we have to change the mux to read the "a" channels
	if( (ADC_num==1) && ( (pin==26) || (pin==31) ) ) { // mux a
        //*ADC_CFG2 &= ~ADC_CFG2_MUXSEL;
        *ADC_CFG2_muxsel = 0;
	} else { // mux b
        //*ADC_CFG2 |= ADC_CFG2_MUXSEL;
        *ADC_CFG2_muxsel = 1;
	}
	#endif

    // no continuous mode
    *ADC_SC3_adco = 0;

    __disable_irq();
    *ADC_SC1A = channel2sc1a[pin] + var_enableInterrupts*ADC_SC1_AIEN; // start conversion on pin and with interrupts enabled if requested
	__enable_irq();

	// wait for the ADC to finish
    while(isConverting()) {
        yield();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
    }

    // it's done, check if the comparison (if any) was true
    __disable_irq(); // make sure nothing interrupts this part
    if (isComplete()) { // conversion succeded
        result = (uint16_t)*ADC_RA;
    } else { // comparison was false
        fail_flag |= ADC_ERROR_COMPARISON;
        result = ADC_ERROR_VALUE;
    }
    __enable_irq();

    // if we interrupted a conversion, set it again
    if (wasADCInUse) {
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
        *ADC_CFG1 = old_config.savedCFG1;
        *ADC_CFG2 = old_config.savedCFG2;
        *ADC_SC2 = old_config.savedSC2;
        *ADC_SC3 = old_config.savedSC3;
        *ADC_SC1A = old_config.savedSC1A;
    }

    num_measurements--;
    return result;

} // analogRead
Beispiel #25
0
/* Reads the differential analog value of two pins (pinP - pinN)
* It waits until the value is read and then returns the result
* If a comparison has been set up and fails, it will return ADC_ERROR_DIFF_VALUE
* Set the resolution, number of averages and voltage reference using the appropriate functions
*/
int ADC_Module::analogReadDifferential(uint8_t pinP, uint8_t pinN) {

    if(!checkDifferentialPins(pinP, pinN)) {
        fail_flag |= ADC_ERROR_WRONG_PIN;
        return ADC_ERROR_VALUE;   // all others are invalid
    }

    // increase the counter of measurements
    num_measurements++;

    // check for calibration before setting channels,
    // because conversion will start as soon as we write to *ADC_SC1A
    if (calibrating) wait_for_cal();

    uint8_t res = getResolution();

    // vars to saved the current state of the ADC in case it's in use
    ADC_Config old_config = {0};
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        saveConfig(&old_config);
        __enable_irq();
    }

    // no continuous mode
    singleMode();

    startDifferentialFast(pinP, pinN); // start conversion

    // wait for the ADC to finish
    while( isConverting() ) {
        yield();
        //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
    }

    // it's done, check if the comparison (if any) was true
    int32_t result;
    __disable_irq(); // make sure nothing interrupts this part
    if (isComplete()) { // conversion succeded
        result = (int16_t)(int32_t)(*ADC_RA); // cast to 32 bits
        if(res==16) { // 16 bit differential is actually 15 bit + 1 bit sign
            result *= 2; // multiply by 2 as if it were really 16 bits, so that getMaxValue gives a correct value.
        }
    } else { // comparison was false
        result = ADC_ERROR_VALUE;
        fail_flag |= ADC_ERROR_COMPARISON;
    }
    __enable_irq();

    // if we interrupted a conversion, set it again
    if (wasADCInUse) {
        __disable_irq();
        loadConfig(&old_config);
        __enable_irq();
    }

    num_measurements--;
    return result;

} // analogReadDifferential
Beispiel #26
0
/*
* \param speed can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
    ADC_VERY_LOW_SPEED is guaranteed to be the lowest possible speed within specs for resolutions less than 16 bits (higher than 1 MHz),
    it's different from ADC_LOW_SPEED only for 24, 4 or 2 MHz.
    ADC_LOW_SPEED is guaranteed to be the lowest possible speed within specs for all resolutions (higher than 2 MHz).
    ADC_MED_SPEED is always >= ADC_LOW_SPEED and <= ADC_HIGH_SPEED.
    ADC_HIGH_SPEED_16BITS is guaranteed to be the highest possible speed within specs for all resolutions (lower or eq than 12 MHz).
    ADC_HIGH_SPEED is guaranteed to be the highest possible speed within specs for resolutions less than 16 bits (lower or eq than 18 MHz).
    ADC_VERY_HIGH_SPEED may be out of specs, it's different from ADC_HIGH_SPEED only for 48, 40 or 24 MHz.
* It doesn't recalibrate at the end.
*/
void ADC_Module::setConversionSpeed(uint8_t speed) {

    if(speed==conversion_speed) { // no change
        return;
    }

    if (calibrating) wait_for_cal();

    // internal asynchronous clock settings: fADK = 2.4, 4.0, 5.2 or 6.2 MHz
    if(speed >= ADC_ADACK_2_4) {
        setBit(ADC_CFG2, ADC_CFG2_ADACKEN_BIT); // enable ADACK (takes max 5us to be ready)
        setBit(ADC_CFG1, ADC_CFG1_ADICLK1_BIT); // select ADACK as clock source
        setBit(ADC_CFG1, ADC_CFG1_ADICLK0_BIT);

        clearBit(ADC_CFG1, ADC_CFG1_ADIV0_BIT); // select divider 1
        clearBit(ADC_CFG1, ADC_CFG1_ADIV1_BIT); // we could divide this clk, but it would be too small for ADC use.

        if(speed == ADC_ADACK_2_4) {
            clearBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
            setBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);
        } else if(speed == ADC_ADACK_4_0) {
            setBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
            setBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);
        } else if(speed == ADC_ADACK_5_2) {
            clearBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
            clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);
        } else if(speed == ADC_ADACK_6_2) {
            setBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
            clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);
        }
        conversion_speed = speed;
        return;
    }


    // normal bus clock used

    // *ADC_CFG2_adacken = 0; // disable the internal asynchronous clock
    clearBit(ADC_CFG2, ADC_CFG2_ADACKEN_BIT);

    uint32_t ADC_CFG1_speed; // store the clock and divisor

    if(speed == ADC_VERY_LOW_SPEED) {
        // *ADC_CFG2_adhsc = 0; // no high-speed config
        // *ADC_CFG1_adlpc  = 1; // use low power conf.
        clearBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        setBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_VERY_LOW_SPEED;

    } else if(speed == ADC_LOW_SPEED) {
        // *ADC_CFG2_adhsc = 0; // no high-speed config
        // *ADC_CFG1_adlpc  = 1; // use low power conf.
        clearBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        setBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_LOW_SPEED;

    } else if(speed == ADC_MED_SPEED) {
        // *ADC_CFG2_adhsc = 0; // no high-speed config
        // *ADC_CFG1_adlpc  = 0; // no low power conf.
        clearBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_MED_SPEED;

    } else if(speed == ADC_HIGH_SPEED_16BITS) {
        // *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        // *ADC_CFG1_adlpc  = 0; // no low power conf.
        setBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_HI_SPEED_16_BITS;

    } else if(speed == ADC_HIGH_SPEED) {
        // *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        // *ADC_CFG1_adlpc  = 0; // no low power conf.
        setBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_HI_SPEED;

    } else if(speed == ADC_VERY_HIGH_SPEED) { // this speed is most likely out of specs, so accurancy can be bad
        // *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        // *ADC_CFG1_adlpc  = 0; // no low power conf.
        setBit(ADC_CFG2, ADC_CFG2_ADHSC_BIT);
        clearBit(ADC_CFG1, ADC_CFG1_ADLPC_BIT);

        ADC_CFG1_speed = ADC_CFG1_VERY_HIGH_SPEED;

    } else {
        fail_flag |= ADC_ERROR_OTHER;
        return;
    }

    // clock source is bus or bus/2
    // *ADC_CFG1_adiclk1 = !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_1); // !!x converts the number x to either 0 or 1.
    // *ADC_CFG1_adiclk0 = !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_0);
    changeBit(ADC_CFG1, ADC_CFG1_ADICLK1_BIT, !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_1));
    changeBit(ADC_CFG1, ADC_CFG1_ADICLK0_BIT, !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_0));

    // divisor for the clock source: 1, 2, 4 or 8.
    // so total speed can be: bus, bus/2, bus/4, bus/8 or bus/16.
    // *ADC_CFG1_adiv1 = !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_1);
    // *ADC_CFG1_adiv0 = !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_0);
    changeBit(ADC_CFG1, ADC_CFG1_ADIV1_BIT, !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_1));
    changeBit(ADC_CFG1, ADC_CFG1_ADIV0_BIT, !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_0));

    conversion_speed = speed;

}
Beispiel #27
0
/* Reads the analog value of the pin.
* It waits until the value is read and then returns the result.
* If a comparison has been set up and fails, it will return -1.
* Set the resolution, number of averages and voltage reference using the appropriate functions.
*/
int ADC::analogRead(uint8_t pin)
{
	uint16_t result;

	if (pin >= 14 && pin <= 39) {
		if (pin <= 23) {
			pin -= 14;  // 14-23 are A0-A9
		} else if (pin >= 34) {
			pin -= 24;  // 34-37 are A10-A13, 38 is temp sensor, 39 is vref
		}
    } else {
        return ADC_ERROR_VALUE;   // all others are invalid
    }

	if (calibrating) wait_for_cal();

	uint8_t res = getResolution();
	uint8_t diffRes = 0; // is the new resolution different from the old one?

    // vars to save the current state of the ADC in case it's in use
    uint32_t savedSC1A, savedSC2, savedSC3, savedCFG1, savedCFG2, savedRes;
    uint8_t wasADCInUse = isConverting(); // is the ADC running now?

    if(wasADCInUse) { // this means we're interrupting a conversion
        // save the current conversion config, we don't want any other interrupts messing up the configs
        __disable_irq();
        //GPIOC_PSOR = 1<<5;
        savedRes = res;
        savedSC1A = ADC0_SC1A;
        savedCFG1 = ADC0_CFG1;
        savedSC2 = ADC0_SC2;
        savedSC3 = ADC0_SC3;

        // change the comparison values if interrupting a 16 bits and diff mode
        if(res==16 && isDifferential()) {
            ADC0_CV1 /= 2;
            ADC0_CV2 /= 2;
        }

        // disable continuous mode in case analogRead is interrupting a continuous mode
        ADC0_SC3 &= !ADC_SC3_ADCO;

        __enable_irq(); ////keep irq disabled until we start our conversion

    }


    // if the resolution is incorrect (i.e. 9, 11 or 13) silently correct it
	if( (res==9) || (res==11) || (res==13) ) {
        setResolution(res-1);
        diffRes = 1; // resolution changed
	}

    __disable_irq();
    ADC0_SC1A = channel2sc1a[pin] + var_enableInterrupts*ADC_SC1_AIEN; // start conversion on pin and with interrupts enabled if requested
	__enable_irq();


	while (1) {
		__disable_irq();
		if ((ADC0_SC1A & ADC_SC1_COCO)) { // conversion completed
			result = ADC0_RA;

			// if we interrupted a conversion, set it again
            if (wasADCInUse) {
                //GPIOC_PCOR = 1<<5;

                // restore ADC config, and restart conversion
                if(diffRes) setResolution(savedRes); // don't change res if isn't necessary
                if(res==16 && ((savedSC1A & ADC_SC1_DIFF) >> 5) )  { // change back the comparison values if interrupting a 16 bits and diff mode
                    ADC0_CV1 *= 2;
                    ADC0_CV2 *= 2;
                }
                ADC0_CFG1 = savedCFG1;
                ADC0_SC2 = savedSC2 & 0x7F; // restore first 8 bits
                ADC0_SC3 = savedSC3 & 0xF; // restore first 4 bits
                ADC0_SC1A = savedSC1A & 0x7F; // restore first 8 bits
            }
			__enable_irq();
			return result;
		} else if( ((ADC0_SC2 & ADC_SC2_ADACT) == 0) && ((ADC0_SC1A & ADC_SC1_COCO) == 0) ) { // comparison was false
int analogRead(uint8_t pin)
{
	int result;
	uint8_t index, channel;

	//serial_phex(pin);
	//serial_print(" ");

#if defined(__MK20DX128__)
	if (pin <= 13) {
		index = pin;      // 0-13 refer to A0-A13
	} else if (pin <= 23) {
		index = pin - 14; // 14-23 are A0-A9
	} else if (pin >= 34 && pin <= 40) {
		index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
			          // 39 is vref, 40 is unused analog pin
	} else {
		return 0;
	}
#elif defined(__MK20DX256__)
	if (pin <= 13) {
		index = pin;      // 0-13 refer to A0-A13
	} else if (pin <= 23) {
		index = pin - 14; // 14-23 are A0-A9
	} else if (pin >= 26 && pin <= 31) {
		index = pin - 9;  // 26-31 are A15-A20
	} else if (pin >= 34 && pin <= 40) {
		index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
			          // 39 is vref, 40 is A14
	} else {
		return 0;
	}
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
	if (pin <= 13) {
		index = pin;       // 0-13 refer to A0-A13
	} else if (pin <= 23) {
		index = pin - 14;  // 14-23 are A0-A9
	} else if (pin >= 31 && pin <= 39) {
		index = pin - 19;  // 31-39 are A12-A20
	} else if (pin >= 40 && pin <= 41) {
		index = pin - 30;  // 40-41 are A10-A11
	} else if (pin >= 42 && pin <= 45) {
		index = pin - 21;  // 42-43 are A21-A22, 44 is temp sensor, 45 is vref
	} else {
		return 0;
	}
#elif defined(__MKL26Z64__)
	if (pin <= 12) {
		index = pin;      // 0-12 refer to A0-A12
	} else if (pin >= 14 && pin <= 26) {
		index = pin - 14; // 14-26 are A0-A12
	} else if (pin >= 38 && pin <= 39) {
		index = pin - 25; // 38=temperature
		                  // 39=bandgap ref (PMC_REGSC |= PMC_REGSC_BGBE)
	} else {
		return 0;
	}

#endif

	//serial_phex(index);
	//serial_print(" ");

	channel = channel2sc1a[index];
	//serial_phex(channel);
	//serial_print(" ");

	//serial_print("analogRead");
	//return 0;
	if (calibrating) wait_for_cal();
	//pin = 5; // PTD1/SE5b, pin 14, analog 0

#ifdef HAS_KINETIS_ADC1
	if (channel & 0x80) goto beginADC1;
#endif

	__disable_irq();
startADC0:
	//serial_print("startADC0\n");
#if defined(__MKL26Z64__)
	if (channel & 0x40) {
		ADC0_CFG2 &= ~ADC_CFG2_MUXSEL;
		channel &= 0x3F;
	} else {
		ADC0_CFG2 |= ADC_CFG2_MUXSEL;
	}
#endif
	ADC0_SC1A = channel;
	analogReadBusyADC0 = 1;
	__enable_irq();
	while (1) {
		__disable_irq();
		if ((ADC0_SC1A & ADC_SC1_COCO)) {
			result = ADC0_RA;
			analogReadBusyADC0 = 0;
			__enable_irq();
			result >>= analog_right_shift;
			return result;
		}
		// detect if analogRead was used from an interrupt
		// if so, our analogRead got canceled, so it must
		// be restarted.
		if (!analogReadBusyADC0) goto startADC0;
		__enable_irq();
		yield();
	}
Beispiel #29
0
/** Usually it's not necessary to call this function directly, but do it if the "enviroment" changed
*   significantly since the program was started.
*/
void ADC_Module::recalibrate() {

    calibrate();

    wait_for_cal();
}
Beispiel #30
0
/*
* \param speed can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
    ADC_VERY_LOW_SPEED is guaranteed to be the lowest possible speed within specs for resolutions less than 16 bits (higher than 1 MHz),
    it's different from ADC_LOW_SPEED only for 24, 4 or 2 MHz.
    ADC_LOW_SPEED is guaranteed to be the lowest possible speed within specs for all resolutions (higher than 2 MHz).
    ADC_MED_SPEED is always >= ADC_LOW_SPEED and <= ADC_HIGH_SPEED.
    ADC_HIGH_SPEED_16BITS is guaranteed to be the highest possible speed within specs for all resolutions (lower or eq than 12 MHz).
    ADC_HIGH_SPEED is guaranteed to be the highest possible speed within specs for resolutions less than 16 bits (lower or eq than 18 MHz).
    ADC_VERY_HIGH_SPEED may be out of specs, it's different from ADC_HIGH_SPEED only for 48, 40 or 24 MHz.
* It doesn't recalibrate at the end.
*/
void ADC_Module::setConversionSpeed(uint8_t speed) {

    if(speed==conversion_speed) { // no change
        return;
    }

    if (calibrating) wait_for_cal();

    // in the future allow the user to select this clock source
    *ADC_CFG2_adacken = 0; // disable the internal asynchronous clock

    uint32_t ADC_CFG1_speed; // store the clock and divisor

    if(speed == ADC_VERY_LOW_SPEED) {
        *ADC_CFG2_adhsc = 0; // no high-speed config
        *ADC_CFG1_adlpc  = 1; // use low power conf.

        ADC_CFG1_speed = ADC_CFG1_VERY_LOW_SPEED;

    } else if(speed == ADC_LOW_SPEED) {
        *ADC_CFG2_adhsc = 0; // no high-speed config
        *ADC_CFG1_adlpc  = 1; // use low power conf.

        ADC_CFG1_speed = ADC_CFG1_LOW_SPEED;

    } else if(speed == ADC_MED_SPEED) {
        *ADC_CFG2_adhsc = 0; // no high-speed config
        *ADC_CFG1_adlpc  = 0; // no low power conf.

        ADC_CFG1_speed = ADC_CFG1_MED_SPEED;

    } else if(speed == ADC_HIGH_SPEED_16BITS) {
        *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        *ADC_CFG1_adlpc  = 0; // no low power conf.

        ADC_CFG1_speed = ADC_CFG1_HI_SPEED_16_BITS;

    } else if(speed == ADC_HIGH_SPEED) {
        *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        *ADC_CFG1_adlpc  = 0; // no low power conf.

        ADC_CFG1_speed = ADC_CFG1_HI_SPEED;

    } else if(speed == ADC_VERY_HIGH_SPEED) { // this speed is most likely out of specs, so accurancy can be bad
        *ADC_CFG2_adhsc = 1; // high-speed config: add 2 ADCK
        *ADC_CFG1_adlpc  = 0; // no low power conf.

        ADC_CFG1_speed = ADC_CFG1_VERY_HIGH_SPEED;

    } else {
        fail_flag |= ADC_ERROR_OTHER;
        return;
    }

    // clock source is bus or bus/2
    *ADC_CFG1_adiclk1 = !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_1); // !!x converts the number x to either 0 or 1.
    *ADC_CFG1_adiclk0 = !!(ADC_CFG1_speed & ADC_CFG1_ADICLK_MASK_0);

    // divisor for the clock source: 1, 2, 4 or 8.
    // so total speed can be: bus, bus/2, bus/4, bus/8 or bus/16.
    *ADC_CFG1_adiv1 = !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_1);
    *ADC_CFG1_adiv0 = !!(ADC_CFG1_speed & ADC_CFG1_ADIV_MASK_0);

    conversion_speed = speed;

}