void sub_adc_measurement(ot_int* buffer) { /// This is a blocking ADC capture routine. It should run in 50us or less. /// 1. Universal ADC config /// <LI> Reset REFMSTR, REFVSEL_1 = 2.0V </LI> /// <LI> Voltage Tsample > 1.2us, Temp Tsample > 30us, so use ADCCLK/32 /// for Voltage, ADCCLK/768 for Temp.</LI> /// <LI> Also in ADCCTL0, use multisample mode, use REF=2.0V </LI> /// <LI> Use MEM7 (Temp) & MEM8 (Volt), Use internal sampling timer, use MODCLK </LI> /// <LI> Use 12 bit mode, use fast mode </LI> /// <LI> MEM7 is Temp, MEM8 is Volt </LI> REFCTL0 = REFMSTR + REFON + REFVSEL_1; ADC12CTL0 = 0; ADC12CTL0 = ADC12SHT1_3 + ADC12SHT0_7 + ADC12MSC + ADC12REFON + ADC12ON; ADC12CTL1 = ADC12CSTARTADD_7 + ADC12SHP + ADC12CONSEQ_1; ADC12CTL2 = ADC12RES_2; ADC12MCTL7 = ADC12SREF_1 + ADC12INCH_10; ADC12MCTL8 = ADC12SREF_1 + ADC12INCH_11 + ADC12EOS; /// 2. Start ADC and Wait for ADC to finish. Wait 75us for REF. /// Grab the data, then kill everything platform_swdelay_us(75); ADC12CTL0 |= ADC12ENC; ADC12CTL0 |= ADC12SC; while ((ADC12CTL1 & ADC12BUSY) == ADC12BUSY); ADC12CTL0 &= ~(ADC12ENC | ADC12SC); ADC12CTL0 &= ~(ADC12ON + ADC12REFON); REFCTL0 &= ~(REFMSTR + REFON + REFGENACT); /// 3. Convert Temperature: ///@todo Build a Fixed-Point Model instead of this heavy floating point one. /// /// This temperature conversion method pulls device-specific calibration /// data from the TLV space and uses it to produce a linear model to map /// the acquired ADC value. { float val_dC; val_dC = tmodel.slope_dC*(float)ADC12MEM7 + tmodel.offset_dC; buffer[0] = (ot_int)val_dC; } /// 4. Convert Voltage: /// Vdd is acquired as 12 bit number representing Vdd/2 in 1/4095V units. /// x(V) = 4095*(Vdd/2)/1.93V; x(mV) = (4095/2*1930mV)Vdd ~= Vdd //buffer[1] = volt; // Cheap way, not accurate buffer[1] = (ot_int)((float)ADC12MEM8 * (3860.f/4095.f)); // Higher accuracy method }
void sub_adc_measurement(ot_int* buffer) { /// This is a blocking ADC capture routine. It should take about 1.6 ms. /// @todo change the algorithm to fixed-point. float scratch; ADC12CTL0 = 0; // Reset REFMSTR to hand over control to: REFVSEL_1 = 2.0V, ADC12_A ref control registers REFCTL0 = REFMSTR + REFON + REFVSEL_1; ADC12CTL0 = ADC12SHT1_12 + ADC12SHT0_12 + ADC12REFON + ADC12ON + ADC12MSC; ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1; // enable sample timer ADC12CTL2 = ADC12RES_2 + ADC12SR; // 12-bit mode, 50ksps ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_10; ADC12MCTL1 = ADC12SREF_1 + ADC12INCH_11 + ADC12EOS; // REFO is supposed to startup in 25us... platform_swdelay_us(25); // Start conversion ADC12CTL0 |= ADC12ENC; ADC12CTL0 |= ADC12SC; while ((ADC12CTL1 & ADC12BUSY) == ADC12BUSY); ///@note I think floats are bad, but at the moment I don't care to untangle /// this knot into fixed-point (same goes for below) scratch = (float)ADC12MEM1; scratch = ((scratch * 2.0f / 4095) * 2 * 1000 - 100); buffer[0] = (ot_int)scratch; scratch = (float)ADC12MEM0; scratch = ((scratch * 2.0f / 4095) * 100); scratch = scratch*24.0f/725*100; buffer[1] = (ot_int)scratch; // Shut everything down ADC12CTL0 &= ~(ADC12ENC | ADC12SC); ADC12CTL0 &= ~(ADC12ON + ADC12REFON); REFCTL0 &= ~(REFMSTR + REFVSEL_2 + REFON + REFGENACT); }