int main(void) { wdt_enable(WDTO_1S); initPodControls(); /* Even if you don't use the watchdog, turn it off here. On newer devices, * the status of the watchdog (on/off, period) is PRESERVED OVER RESET! */ /* RESET status: all port bits are inputs without pull-up. * That's the way we need D+ and D-. Therefore we don't need any * additional hardware initialization. */ usbInit(); usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */ uchar i = 0; while(--i){ /* fake USB disconnect for > 250 ms */ wdt_reset(); _delay_ms(1); } usbDeviceConnect(); sei(); for(;;){ /* main event loop */ wdt_reset(); usbPoll(); if(usbInterruptIsReady()){ /* called after every poll of the interrupt endpoint */ usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer)); } else { updateSensorData(); updateLEDState(); } } }
/************************************************************************************************** * @fn DataUpdate_ProcessEvent * * @brief Update values from A/D sensor and diags * * @param uint8 task_id * @param uint16 events - event mask * * @return uint16 - 0 (for now) ************************************************************************************************** */ uint16 DataUpdate_ProcessEvent(uint8 task_id, uint16 events) { #if ADV_DEBUG_MESSAGE_FORMAT==1 // variables that are needed if we're running the advanced debugging message format int vdd_div_3; int vdd; int16 tempvalCC2541; int spare; #endif int tempval; int16 tempval2; int16 tempval3; int16 tempval4; int16 tempavg; uint16 timeval; uint16 sensorval; #if USE_SEPARATE_TEMP_AD_CHANNEL==0 uint8 lmp_configured; uint8 lmp_configure_tries; #endif #ifdef FAKE_SENS_DATA #ifdef O2_SENSOR uint16 max_fake = 1000; uint16 min_fake = 600; static int16 fake_adj = 1; static uint16 fakesensorval = 600; #endif #ifdef CO_SENSOR uint16 max_fake = 1300; uint16 min_fake = 380; static int16 fake_adj = 1; static uint16 fakesensorval = 380; #endif #endif if (events & 1) { timeval = (uint16) (osal_GetSystemClock() & 0xffff); cyclecount++; if (cyclecount>9) { cyclecount=0; // Also, set P1_0 (the LED) as an output, and drive high P1DIR = P1DIR | 0x01; P1 = P1 | 0x01; } /* Enable channel */ ADCCFG |= 0x80; P0DIR = 0x83; // force P0.0, P0.1, and P0.7 to be inputs APCFG = 0x83; HalAdcSetReference (0x40); // use AIN7 for ref (0x08 would be AVDD5, 0x00 would be internal ref #if USE_SEPARATE_TEMP_AD_CHANNEL==0 // Configure LMP9100 to output temperature if (lmp91KinitComplete) { // Because the processor may have been sleeping, re-configure I2C intf. before // performing the I2C transaction HalI2CExitSleep(); lmp_configure_tries=0; lmp_configured=0; // We can't hang out in this loop forever, but we can retry a couple // of times, to get over any instability on the I2C bus while ((lmp_configure_tries<4) && (!lmp_configured)) { // Set this flag so that we presume that communication is working. // The flag will get cleared (quickly) as a side-effect in the // communication routines if we fail again. lmp91kOK=1; lmp_configured=LMP91000_I2CSwitchVoutToTempSensor(); lmp_configure_tries++; } // end while // Because the processor may go into sleep mode, save the state of the I2C // interface before continuing. HalI2CEnterSleep(); } // end if (lmp91KinitComplete) #endif // Read temperature from LMP9100 if (!lmp91kOK) { // If we're not communicating, then the LMP91000 may not be in the right // state, so just use a previous value. tempval = oldtempval; } else { tempval = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_12); tempval2 = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_12); tempval3 = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_12); tempval4 = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_12); // Get a bit of noise out of the temperature measurment by averaging 4 // samples. // By the way, we expect nominal values to be around 1100 or so // at room temperature, so we can fairly safely add 4 16-bit values // together without thinking too much about overflow. // If the nominal values were larger, we'd promote to a larger // data type before averaging. tempavg = (tempval+tempval2+tempval3+tempval4)/4; oldtempval=tempavg; } // Convert temp to tenths of degrees C, based on the table in // the datasheet for the LMP91000, and assuming a 2.5v ref tempval = convertTemp(tempavg); // Now, get ready to measure the oxygen sensor HalAdcSetReference (0x40); // use AIN7 for ref #if USE_SEPARATE_TEMP_AD_CHANNEL==0 if (lmp91KinitComplete) { // Because the processor may have been sleeping, re-configure I2C intf. before // performing the I2C transaction(s) HalI2CExitSleep(); lmp_configure_tries=0; lmp_configured=0; // we can't hang out in this loop forever, but we can retry a couple // of times, to get over any instability on the I2C while ((lmp_configure_tries<4) && (!lmp_configured)) { // Set this flag so that we presume that communication is working. // The flag will get cleared (quickly) as a side-effect in the // communication routines if we fail again. lmp91kOK=1; // Likely redundant, but doesn't hurt LMP91000_I2CConfigureForO2Sensor( SensTIAGain , SensRLoad, SensRefVoltageSource, SensIntZSel); if (lmp91kOK) { lmp_configured = LMP91000_I2CSwitchVoutToO2Sensor(SensModeOp); } lmp_configure_tries++; } // end while // Because the processor may go into sleep mode, save the state of the I2C // interface before continuing. HalI2CEnterSleep(); } // end if (lmp91KinitComplete) #endif if (!lmp91kOK) { // If we're not communicating, then the LMP91000 may not be in the right // state, so just use a previous value. sensorval = oldsensorval; } else { #if USE_SEPARATE_TEMP_AD_CHANNEL==1 sensorval = HalAdcRead(HAL_ADC_CHANNEL_1,HAL_ADC_RESOLUTION_12); #else sensorval = HalAdcRead(HAL_ADC_CHANNEL_0,HAL_ADC_RESOLUTION_12); #endif oldsensorval = sensorval; } // Depending on compile options, build the message, or gather // additional diagnostic info and then build the debug mode message #ifdef FAKE_SENS_DATA fakesensorval += fake_adj; if ((fakesensorval >= max_fake) || (fakesensorval <= min_fake)) fake_adj = -1 * fake_adj; sensorval = fakesensorval; #endif #if ADV_DEBUG_MESSAGE_FORMAT==0 updateSensorData ((uint16)timeval, (uint16)tempval, (uint16)sensorval); DataReadyFlag = 1; #else // Gather additional interesting diagnostic info before updating structure spare = HalAdcRead(0x01, HAL_ADC_RESOLUTION_12); // Spare A/D chan - use for battery measurement later // Turn on the test mode to enable temperature measurement // from the CC2544's internal temp sensor ATEST=1; // ATEST.ATEST_CTRL=0x01; TR0=1; // TR0.ADCTM=1; HalAdcSetReference(0); // use internal ref voltage (1.15 V) //HalAdcSetReference ( 0x80); // use AVDD5 pin for ref // CC2541 Internal temp sensor is A/D input 14 (0x0e) tempvalCC2541 = HalAdcRead(0x0E, HAL_ADC_RESOLUTION_12); /* Turn off test modes */ TR0=0; // TR0.ADCTM=0; ATEST=0; // The analog temperature sensor in the CC2544 should give back a value // of 1480 at 25 degrees C and VDD=3, // and will change by a value of 4.5 per degree C // // So, to get temperature in 0.1 degrees C units, consider the // following formula: // tempval2 = tempvalCC2541-1480; tempvalCC2541 = (int16) (250.0 + (tempval2/4.5)); HalAdcSetReference(0); // use internal ref voltage (1.15 V) // Pick up VDD divided by 3 vdd_div_3 = HalAdcRead(0x0F, HAL_ADC_RESOLUTION_12); // VDD/3 // Convert to millivolts (and get rid of the divide by 3, since we're doing math // vdd = (int) (1.15*vdd_div_3*3.0*1000.0 / 2047.0); // convert to millivolts // vdd = (int) (vdd_div_3 * 1.6853932584269662921348314606742); // more precisely vdd = (int) (vdd_div_3 * 1.6853); // close enough // Pick up the spare A/D input HalAdcSetReference (0x40); // use AIN7 for ref spare = HalAdcRead(0x01, HAL_ADC_RESOLUTION_12); updateSensorData ((uint16)timeval, (uint16)tempval, (uint16)sensorval, (uint16)tempvalCC2541, (uint16)vdd, (uint16)spare); DataReadyFlag = 1; #endif // Set the light control I/O (LightOn=1 => P1_1=0) nuSOCKET_updateLight(); // Also, set P1_0 (the LED) as an output, and drive low P1DIR = P1DIR | 0x01; P1 = P1&0xFE; return (events ^ 1);; } return (0); } // end DataUpdate_ProcessEvent()