uint8_t aiPollOD(subidx_t * pSubidx, uint8_t sleep) { uint8_t apin; uint16_t ActVal; apin = cvtBase2Apin(pSubidx->Base); #ifdef ASLEEP if(sleep != 0) { aiTimeout[apin] = POLL_TMR_FREQ; if(~PRR & (1<<PRADC)) DISABLE_ADC(); return 0; } #endif // ASLEEP if(PRR & (1<<PRADC)) // ADC Disabled { ai_isPos = 0xFF; ai_isCnt = 0xFF; ENABLE_ADC(); } if(--aiTimeout[apin] != 0) return 0; ActVal = (aiActVal[apin] + 8)>>4; if(aiOldVal[apin] != ActVal) { aiOldVal[apin] = ActVal; return 1; } return 0; }
/* 80 us * * conversion time = 13 * ADC12DIV * 1/FreqAdcClock * 13 * 8 * 1/5e6 = 20.8 us */ void BatterySenseCycle(void) { static unsigned char Index = 0; xSemaphoreTake(AdcMutex, portMAX_DELAY); BATTERY_SENSE_ENABLE(); ENABLE_REFERENCE(); /* low_bat_en assertion to bat_sense valid is ~100 ns */ /* Start battery sense conversion */ AdcCheck(); CLEAR_START_ADDR(); ADC12CTL1 |= ADC12CSTARTADD_1; ENABLE_ADC(); WaitForAdcBusy(); /* Convert the ADC count for the battery input into a voltage * ADC12MEM1: Counts Battery Voltage in ADC counts * Result: Battery voltage in millivolts */ unsigned int Value = (unsigned int)(CONVERSION_FACTOR_BATTERY * (double)ADC12MEM1); if (ValidCalibration()) Value += GetBatteryCalibrationValue(); /* smoothing algorithm: cut extreme values (gap > 20) */ unsigned char Prev = (Index == 0) ? MAX_SAMPLES - 1: Index - 1; if (Sample[BATTERY][Prev]) { int Gap = Value - Sample[BATTERY][Prev]; if (Charging()) { if (Gap > GAP_BIG) Gap = GAP_BIG; else if (Gap < GAP_SMALL_NEGATIVE) Gap = GAP_SMALL_NEGATIVE; } else { if (Gap > GAP_SMALL) Gap = GAP_SMALL; else if (Gap < GAP_BIG_NEGATIVE) Gap = GAP_BIG_NEGATIVE; } Sample[BATTERY][Index] = Sample[BATTERY][Prev] + Gap; } else Sample[BATTERY][Index] = Value; if (++Index >= MAX_SAMPLES) Index = 0; BATTERY_SENSE_DISABLE(); EndAdcCycle(); //xSemaphoreGive() }
/*! Initialize the Analog-to-Digital Conversion peripheral. Set the outputs from * the micro to the correct state. The ADC is used to read the * hardware configuration registers, the battery voltage, and the value from the * light sensor. */ void InitAdc(void) { /* * the internal voltage reference is not used ( AVcc is used ) * reference is controlled by ADC12MCTLx register * 2.5 volt reference cannot be used because it requires external AVcc of 2.8 * disable temperature sensor */ REFCTL0 = REFMSTR | REFTCOFF; LIGHT_SENSE_INIT(); BATTERY_SENSE_INIT(); HARDWARE_CFG_SENSE_INIT(); /* allow conditional request for modosc */ UCSCTL8 |= MODOSCREQEN; /* select ADC12SC bit as sample and hold source (00) * and use pulse mode * use modosc / 8 because frequency must be 0.45 MHz to 2.7 MHz (0.625 MHz) */ ADC12CTL1 = ADC12CSTARTADD_0 + ADC12SHP + ADC12SSEL_0 + ADC12DIV_7; /* 12 bit resolution, only use reference when doing a conversion */ ADC12CTL2 = ADC12TCOFF + ADC12RES_2 + ADC12REFBURST; /* setup input channels */ ADC12MCTL0 = HARDWARE_CFG_INPUT_CHANNEL + ADC12EOS; ADC12MCTL1 = BATTERY_SENSE_INPUT_CHANNEL + ADC12EOS; ADC12MCTL2 = LIGHT_SENSE_INPUT_CHANNEL + ADC12EOS; /* init to 0 */ memset(Sample, 0, MAX_SAMPLES << 2); /* control access to adc peripheral */ AdcMutex = xSemaphoreCreateMutex(); xSemaphoreGive(AdcMutex); WarningLevel = DEFAULT_WARNING_LEVEL; RadioOffLevel = DEFAULT_RADIO_OFF_LEVEL; /* * A voltage divider on the board is populated differently * for each revision of the board. * * determine configuration at start-up */ HARDWARE_CFG_SENSE_ENABLE(); ENABLE_REFERENCE(); /* Start Hardware Configuration Cycle */ AdcCheck(); /* setup the ADC channel */ CLEAR_START_ADDR(); ADC12CTL1 |= ADC12CSTARTADD_0; /* enable the ADC to start sampling and perform a conversion */ ENABLE_ADC(); WaitForAdcBusy(); /* Finish HardwareConfiguration Cycle */ /* Convert ADC counts to a voltage (truncates) * ADC12MEM0: Voltage in ADC counts * result: Voltage in millivolts * 10 */ unsigned int HwCfgVolt = (unsigned int)(CONVERSION_FACTOR * (double)ADC12MEM0); HARDWARE_CFG_SENSE_DISABLE(); DISABLE_ADC(); DISABLE_REFERENCE(); BoardType = HW_CONFIG_NUM - 1; for (; BoardType; --BoardType) if (HwCfgVolt > HwConfig[BoardType]) break; ConfigureDefaultIO(); }