/*************************************************************************************************** * @fn MT_SysAdcRead * * @brief Reading ADC value, temperature sensor and voltage * * @param uint8 pData - pointer to the data * * @return None ***************************************************************************************************/ void MT_SysAdcRead(uint8 *pBuf) { #ifndef HAL_BOARD_LM3S uint8 channel, resolution; uint16 tempValue; uint8 retArray[2]; uint8 cmdId; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Channel */ channel = *pBuf++; /* Resolution */ resolution = *pBuf++; /* Voltage reading */ switch (channel) { /* Analog input channel */ case HAL_ADC_CHANNEL_0: case HAL_ADC_CHANNEL_1: case HAL_ADC_CHANNEL_2: case HAL_ADC_CHANNEL_3: case HAL_ADC_CHANNEL_4: case HAL_ADC_CHANNEL_5: case HAL_ADC_CHANNEL_6: case HAL_ADC_CHANNEL_7: tempValue = HalAdcRead(channel, resolution); break; /* Temperature sensor */ case(HAL_ADC_CHANNEL_TEMP): tempValue = HalAdcRead(HAL_ADC_CHANNEL_TEMP, HAL_ADC_RESOLUTION_14); break; /* Voltage reading */ case(HAL_ADC_CHANNEL_VDD): tempValue = HalAdcRead(HAL_ADC_CHANNEL_VDD, HAL_ADC_RESOLUTION_14); break; /* Undefined channels */ default: tempValue = 0x00; break; } retArray[0] = LO_UINT16(tempValue); retArray[1] = HI_UINT16(tempValue); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), cmdId, 2, retArray); #endif /* #ifndef HAL_BOARD_LM3S */ }
/********************************************************************* * @fn readAdcData * * @brief Read ADC channel value * * @return none */ static uint16 readAdcData( uint8 channel ) { uint16 adcVdd3, adcChannel, vdd, voltage; HalAdcSetReference(HAL_ADC_REF_125V); adcVdd3 = HalAdcRead(HAL_ADC_CHN_VDD3, HAL_ADC_RESOLUTION_8); vdd = (adcVdd3) * 29; // (1240 * 3 / 127), ADC internal voltage for CC254x is 1.24V HalAdcSetReference( HAL_ADC_REF_AVDD ); adcChannel = HalAdcRead( channel, HAL_ADC_RESOLUTION_8); voltage = (uint16)( ((uint32)adcChannel * (uint32)vdd) / 127 ); return voltage; }
/*************************************************************************************************** * @fn BspRubyTmpMeas_offchip * * @brief Get temperature value from offchip sensor * * @param None * * * * * @return None ***************************************************************************************************/ uint16 BspRubyTmpMeas() { uint8 i; uint32 tmp=0; uint32 voltage; BSP_TMP_CHG_SBIT = 1; HalAdcSetReference(HAL_ADC_REF_AVDD); for(i=0;i<4;i++){ voltage = HalAdcRead(HAL_ADC_CHN_AIN6,HAL_ADC_RESOLUTION_14); // tmp = tmp+(1000*voltage/(8192-voltage)); tmp += voltage; } BSP_TMP_CHG_SBIT = 0; tmp = tmp/4; // tmp = voltage/4; // for(i=0;i<140;i++) // { // if((tmp<=tmp_table[i])&&(tmp>tmp_table[i+1])) // { // result = i/2; // break; // } // } return (uint16)tmp; }
/** * @fn batt_measure * * @brief Measure the battery level with the ADC * * @param none * * @return */ static unsigned char batt_measure(void) { unsigned short adc; // configure ADC and perform a read HalAdcSetReference(HAL_ADC_REF_125V); adc = HalAdcRead(HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_14); if (!BATCD_SBIT) { batt_level = 7; // battery charge } else if ((adc >= BATT_LEVEL_01)) { batt_level = 6; // battery full } else if ((adc >= BATT_LEVEL_02) && (adc < BATT_LEVEL_01)) { batt_level = 5; } else if ((adc >= BATT_LEVEL_03) && (adc < BATT_LEVEL_02)) { batt_level = 4; } else if ((adc >= BATT_LEVEL_04) && (adc < BATT_LEVEL_03)) { batt_level = 3; } else if ((adc >= BATT_LEVEL_05) && (adc < BATT_LEVEL_04)) { batt_level = 2; } else if ((adc >= BATT_LEVEL_06) && (adc < BATT_LEVEL_05)) { batt_level = 1; // battery empty } else { batt_level = 0; // battery shutdown } battmsg(("adc=%04x, lv=%02x\n", adc, batt_level)); return batt_level; }
/********************************************************************* * @fn battMeasure * * @brief Measure the battery level with the ADC and return * it as a percentage 0-100%. * * @return Battery level. */ static uint8 battMeasure( void ) { uint16 adc; uint8 percent; /** * Battery level conversion from ADC to a percentage: * * The maximum ADC value for the battery voltage level is 511 for a * 10-bit conversion. The ADC value is references vs. 1.25v and * this maximum value corresponds to a voltage of 3.75v. * * For a coin cell battery 3.0v = 100%. The minimum operating * voltage of the CC2540 is 2.0v so 2.0v = 0%. * * To convert a voltage to an ADC value use: * * (v/3)/1.25 * 511 = adc * * 3.0v = 409 ADC * 2.0v = 273 ADC * * We need to map ADC values from 409-273 to 100%-0%. * * Normalize the ADC values to zero: * * 409 - 273 = 136 * * And convert ADC range to percentage range: * * percent/adc = 100/136 = 25/34 * * Resulting in the final equation, with round: * * percent = ((adc - 273) * 25) + 33 / 34 */ // Configure ADC and perform a read HalAdcSetReference( HAL_ADC_REF_125V ); adc = HalAdcRead( HAL_ADC_CHANNEL_VDD, HAL_ADC_RESOLUTION_10 ); if (adc >= BATT_ADC_LEVEL_3V) { percent = 100; } else if (adc <= BATT_ADC_LEVEL_2V) { percent = 0; } else { percent = (uint8) ((((adc - BATT_ADC_LEVEL_2V) * 25) + 33) / 34); } return percent; }
void CurrentDetectionT1_SampleCurrentAdcValue(bool clear) { static uint16 maxAdcValueInCycle[2] = {0, 0}; static uint16 timerCountInCycle = 0; uint16 currentAdcValue = 0; if (clear) { timerCountInCycle = 0; adcValueSum[0] = 0; adcValueSum[1] = 0; maxAdcValueInCycle[0] = 0; maxAdcValueInCycle[1] = 0; return; } //AC_IN0: P0_7 currentAdcValue = HalAdcRead(HAL_ADC_CHN_AIN7, HAL_ADC_RESOLUTION_12); if (currentAdcValue > maxAdcValueInCycle[0]) { maxAdcValueInCycle[0] = currentAdcValue; } //AC-IN1: P0_6 currentAdcValue = HalAdcRead(HAL_ADC_CHN_AIN6, HAL_ADC_RESOLUTION_12); if (currentAdcValue > maxAdcValueInCycle[1]) { maxAdcValueInCycle[1] = currentAdcValue; } if (++timerCountInCycle == ADC_ACCQUIRE_RATE) { adcValueSum[0] += maxAdcValueInCycle[0]; adcValueSum[1] += maxAdcValueInCycle[1]; maxAdcValueInCycle[0] = 0; maxAdcValueInCycle[1] = 0; timerCountInCycle = 0; } return; }
/********************************************************************* * @fn zclSampleSw_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_4 * HAL_KEY_SW_3 * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ static void zclSampleSw_HandleKeys( byte shift, byte keys ) { zAddrType_t dstAddr; (void)shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_SW_1 ) { // Using this as the "Light Switch" #ifdef ZCL_ON_OFF zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, false, 0 ); #endif } if ( keys & HAL_KEY_SW_2 ) { HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF ); // Initiate an End Device Bind Request, this bind request will // only use a cluster list that is important to binding. dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = 0; // Coordinator makes the match ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(), SAMPLESW_ENDPOINT, ZCL_HA_PROFILE_ID, 0, NULL, // No incoming clusters to bind ZCLSAMPLESW_BINDINGLIST, bindingOutClusters, TRUE ); } if ( keys & HAL_KEY_SW_3 ) { #ifdef ZCL_LEVEL_CTRL uint16 potiVal = HalAdcRead ( SAMPLESW_POTI_CHANNEL, HAL_ADC_RESOLUTION_8 ); zclGeneral_SendLevelControlMoveToLevel( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, potiVal, SAMPLESW_STD_TRANSTIME, false, 0 ); #endif } if ( keys & HAL_KEY_SW_4 ) { HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF ); // Initiate a Match Description Request (Service Discovery) dstAddr.addrMode = AddrBroadcast; dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR; ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR, ZCL_HA_PROFILE_ID, ZCLSAMPLESW_BINDINGLIST, bindingOutClusters, 0, NULL, // No incoming clusters to bind FALSE ); } }
void getTemperature(void) { int16 value; HalAdcSetReference(HAL_ADC_REF_125V); TR0 |= 1; ATEST |= 1; value = HalAdcRead(HAL_ADC_CHANNEL_TEMP, HAL_ADC_RESOLUTION_12); ATEST &= ~1; TR0 &= ~1; HalAdcSetReference(HAL_ADC_REF_AVDD); zclHomelink_Temperature = 2500 + ((value - ADC_TEMP_25C) * (int16)(100 / ADC_TEMP_BITS_PER_C)); }
/************************************************************************************************** * @fn HalGetBattVol * * @brief Get Battery Volage * * @param none * * @return Battery Volage **************************************************************************************************/ float HalGetBattVol(void) { float tempVol = 0; BATTER_MINITOR_ENABLE; // Enable BATT_MON_EN, P0.1 high tempVol = HalAdcRead( BATTER_MONITOR_CHANNEL, BATTER_MONITOR_RESOLUTION ); //max value = 0x3fff/2, battery voltage = input voltage x 2 //ref volage=3.3V tempVol = tempVol*3.3*2*2/0x3fff; BATTER_MINITOR_DISABLE; // Disable BATT_MON_EN, P0.1 low return tempVol; }
uint16 readSensValue(uint8 sensId) { uint16 sensVal; switch(sensId) { #if defined ( SENS_TEMP_ID ) case SENS_TEMP_ID: //Temperatura HalAdcInit(); sensVal=HalAdcRead(SENS_TEMP_CH, SENS_TEMP_RES); //X leggere i valori break; #endif #if defined ( SENS_BATT_ID ) case SENS_BATT_ID: //Valore di tensione della batteria HalAdcInit(); sensVal=HalAdcRead(SENS_BATT_CH, SENS_BATT_RES); //ris sempre su 12 bit break; #endif #if defined ( SENS_LIGHT_ID ) case SENS_LIGHT_ID: //Luce HalAdcInit(); sensVal=HalAdcRead(SENS_LIGHT_CH, SENS_LIGHT_RES); break; #endif #if defined ( SENS_X_ACC_ID ) case SENS_X_ACC_ID: //X_Accelerometro HalAdcInit(); sensVal=HalAdcRead(SENS_X_ACC_CH, SENS_X_ACC_RES); break; #endif #if defined ( SENS_Y_ACC_ID ) case SENS_Y_ACC_ID: //Y_Accelerometro HalAdcInit(); sensVal=HalAdcRead(SENS_Y_ACC_CH, SENS_Y_ACC_RES); break; #endif #if defined ( SENS_POTENT_ID ) case SENS_POTENT_ID: //Potenziometro HalAdcInit(); sensVal=HalAdcRead(SENS_POTENT_CH, SENS_POTENT_RES); break; #endif #if defined ( SENS_SWITCH_ID ) case SENS_SWITCH_ID: //Switch HalAdcInit(); sensVal=HalAdcRead(SENS_SWITCH_CH, SENS_SWITCH_RES); break; #endif default: sensVal=0xFFFF; //caso in cui non è stato trovato o definito sensId } return sensVal; }
/************************************************************************************************** * @fn halGetJoyKeyInput * * @brief Map the ADC value to its corresponding key. * * @param None * * @return keys - current joy key status **************************************************************************************************/ uint8 halGetJoyKeyInput(void) { /* The joystick control is encoded as an analog voltage. * Read the JOY_LEVEL analog value and map it to joy movement. */ uint8 adc; uint8 ksave0 = 0; uint8 ksave1; /* Keep on reading the ADC until two consecutive key decisions are the same. */ do { ksave1 = ksave0; /* save previouse key reading */ adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8); if ((adc >= 2) && (adc <= 38)) { ksave0 |= HAL_KEY_UP; } else if ((adc >= 74) && (adc <= 88)) { ksave0 |= HAL_KEY_RIGHT; } else if ((adc >= 60) && (adc <= 73)) { ksave0 |= HAL_KEY_LEFT; } else if ((adc >= 39) && (adc <= 59)) { ksave0 |= HAL_KEY_DOWN; } else if ((adc >= 89) && (adc <= 100)) { ksave0 |= HAL_KEY_CENTER; } } while (ksave0 != ksave1); return ksave0; }
/********************************************************************* * @fn battMeasure * * @brief Measure the battery level with the ADC and return * it as a percentage 0-100%. * * @return Battery level. */ static uint8 battMeasure( void ) { uint16 adc; uint8 percent; /** * Battery level conversion from ADC to a percentage: * * The maximum ADC value for the battery voltage level is 511 for a * 10-bit conversion. The ADC value is references vs. 1.25v and * this maximum value corresponds to a voltage of 3.75v. * * For a coin cell battery 3.0v = 100%. The minimum operating * voltage of the CC2540 is 2.0v so 2.0v = 0%. * * To convert a voltage to an ADC value use: * * (v/3)/1.25 * 511 = adc * * 3.0v = 409 ADC * 2.0v = 273 ADC * * We need to map ADC values from 409-273 to 100%-0%. * * Normalize the ADC values to zero: * * 409 - 273 = 136 * * And convert ADC range to percentage range: * * percent/adc = 100/136 = 25/34 * * Resulting in the final equation, with round: * * percent = ((adc - 273) * 25) + 33 / 34 */ // Call measurement setup callback if (battServiceSetupCB != NULL) { battServiceSetupCB(); } // Configure ADC and perform a read HalAdcSetReference( HAL_ADC_REF_125V ); adc = HalAdcRead( battServiceAdcCh, HAL_ADC_RESOLUTION_10 ); // Call measurement teardown callback if (battServiceTeardownCB != NULL) { battServiceTeardownCB(); } if (adc >= battMaxLevel) { percent = 100; } else if (adc <= battMinLevel) { percent = 0; } else { if (battServiceCalcCB != NULL) { percent = battServiceCalcCB(adc); } else { uint16 range = battMaxLevel - battMinLevel + 1; // optional if you want to keep it even, otherwise just take floor of divide // range += (range & 1); range >>= 2; // divide by 4 percent = (uint8) ((((adc - battMinLevel) * 25) + (range - 1)) / range); } } return percent; }
static void simpleBLECentral_HandleKeys( uint8 shift, uint8 keys ) { (void)shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_UP ) { // Start or stop discovery if ( simpleBLEState != BLE_STATE_CONNECTED ) { if ( !simpleBLEScanning ) { uint8 adc7 = HalAdcRead (HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8); LCD_WRITE_STRING_VALUE( "Value",adc7, 16, HAL_LCD_LINE_2); advertData[6]= var1[6]; advertData[8]= 0xA9; if(adc7>0x7E) advertData[9]= 0x01; else advertData[9]= 0x02; advertData[10]= 0xB9; GAP_UpdateAdvertisingData( GAPROLE_ADVERT_ENABLED,TRUE, sizeof(advertData),advertData); simpleBLEScanning = TRUE; simpleBLEScanRes = 0; LCD_WRITE_STRING( "Discovering...", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST ); } else { GAPCentralRole_CancelDiscovery(); } } else if ( simpleBLEState == BLE_STATE_CONNECTED && simpleBLECharHdl != 0 && simpleBLEProcedureInProgress == FALSE ) { uint8 status; // Do a read or write as long as no other read or write is in progress if ( simpleBLEDoWrite ) { // Do a write attWriteReq_t req; req.handle = simpleBLECharHdl; req.len = 1; req.value[0] = simpleBLECharVal; req.sig = 0; req.cmd = 0; status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId ); } else { // Do a read attReadReq_t req; req.handle = simpleBLECharHdl; status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId ); } if ( status == SUCCESS ) { simpleBLEProcedureInProgress = TRUE; simpleBLEDoWrite = !simpleBLEDoWrite; } } } if ( keys & HAL_KEY_LEFT ) { // Display discovery results if ( !simpleBLEScanning && simpleBLEScanRes > 0 ) { // Increment index of current result (with wraparound) simpleBLEScanIdx++; if ( simpleBLEScanIdx >= simpleBLEScanRes ) { simpleBLEScanIdx = 0; } LCD_WRITE_STRING_VALUE( "Device", simpleBLEScanIdx + 1, 10, HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( simpleBLEDevList[simpleBLEScanIdx].addr ), HAL_LCD_LINE_2 ); } } //////////////////////////////////////////////////////////////////////////////// // Advertising if ( keys & HAL_KEY_RIGHT ) { // ressing the right key should toggle advertising on and off uint8 current_adv_enabled_status; uint8 new_adv_enabled_status; uint8 adc7 = HalAdcRead (HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8); LCD_WRITE_STRING_VALUE( "Value",adc7, 16, HAL_LCD_LINE_2); advertData[6]= var1[6]; advertData[8]= 0xA9; if(adc7>0x7E) advertData[9]= 0x01; else advertData[9]= 0x02; advertData[10]= 0xB9; GAP_UpdateAdvertisingData( GAPROLE_ADVERT_ENABLED,TRUE, sizeof(advertData),advertData); //Find the current GAP advertisement status if( current_adv_enabled_status == FALSE ) { new_adv_enabled_status = TRUE; } else { new_adv_enabled_status = FALSE; } // if(var1[2] == 0x53) { //scanRspData[18] =0xAA; //scanRspData[19] =(uint8) var1[2]; //bStatus_t stat; //stat = GAP_UpdateAdvertisingData( 0, TRUE, 1, scanRspData); //} //change the GAP advertisement status to opposite of current status GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &new_adv_enabled_status ); } //////////////////////////////////////////////////////////////////////////////// /*if ( keys & HAL_KEY_CENTER ) { uint8 addrType; uint8 *peerAddr; // Connect or disconnect if ( simpleBLEState == BLE_STATE_IDLE ) { // if there is a scan result if ( simpleBLEScanRes > 0 ) { // connect to current device in scan result peerAddr = simpleBLEDevList[simpleBLEScanIdx].addr; addrType = simpleBLEDevList[simpleBLEScanIdx].addrType; simpleBLEState = BLE_STATE_CONNECTING; GAPCentralRole_EstablishLink( DEFAULT_LINK_HIGH_DUTY_CYCLE, DEFAULT_LINK_WHITE_LIST, addrType, peerAddr ); LCD_WRITE_STRING( "Connecting", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( peerAddr ), HAL_LCD_LINE_2 ); } } else if ( simpleBLEState == BLE_STATE_CONNECTING || simpleBLEState == BLE_STATE_CONNECTED ) { // disconnect simpleBLEState = BLE_STATE_DISCONNECTING; gStatus = GAPCentralRole_TerminateLink( simpleBLEConnHandle ); LCD_WRITE_STRING( "Disconnecting", HAL_LCD_LINE_1 ); } }*/ if ( keys & HAL_KEY_DOWN ) { // Start or cancel RSSI polling if ( simpleBLEState == BLE_STATE_CONNECTED ) { if ( !simpleBLERssi ) { simpleBLERssi = TRUE; GAPCentralRole_StartRssi( simpleBLEConnHandle, DEFAULT_RSSI_PERIOD ); } else { simpleBLERssi = FALSE; GAPCentralRole_CancelRssi( simpleBLEConnHandle ); LCD_WRITE_STRING( "RSSI Cancelled", HAL_LCD_LINE_1 ); } } } }
/************************************************************************************************** * @fn pulseBPM * * @brief This function is called by pulseDataCalc(). This function contains the main algorithm for * pulse calculation that was originally develop for the arduino by Joel Murphy and Yury Gitman from * www.pulsesensor.com. The code has been migrated to work in the MSP430 with minor adjustments to * deal with problems caused by high frequency noise. * * * input parameters * * Pointer to the MHMSdata array that will be sent over the air. * * output parameters * * None. * * @return None. **************************************************************************************************/ static void pulseBPM(uint8 *pulsedata) { static int BPM; // used to hold the pulse rate static int Signal; // holds the incoming raw data static int IBI = 600; // holds the time between beats, the Inter-Beat Interval static bool Pulse = FALSE; // TRUE when pulse wave is high, FALSE when it's low static int rate[10]; // used to hold last ten IBI values static uint32 sampleCounter = 0; // used to determine pulse timing static uint32 lastBeatTime = 0; // used to find the inter beat interval static int P = 512; // used to find peak in pulse wave static int T = 512; // used to find trough in pulse wave static int thresh = 512; // used to find instant moment of heart beat static int amp = 100; // used to hold amplitude of pulse waveform static bool firstBeat = TRUE; // used to seed rate array so we startup with reasonable BPM static bool secondBeat = TRUE; // used to seed rate array so we startup with reasonable BPM BPM = pulsedata[MHMS_BPM]; // used to hold the pulse rate IBI = pulsedata[MHMS_IBI]; // holds the time between beats, the Inter-Beat Interval //MHMS using HAL layer API to set channel to read and 10 Bit resolution Signal = HalAdcRead(HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_10); sampleCounter +=2; // keep track of the time in mS with this variable int Number = (sampleCounter - lastBeatTime); // monitor the time since the last beat to avoid noise // find the peak and trough of the pulse wave if(Signal < thresh && Number > (IBI/5)*3){ // avoid dichrotic noise by waiting 3/5 of last IBI if (Signal < T){ // T is the trough T = Signal; // keep track of lowest point in pulse wave } } if(Signal > thresh && Signal > P){ // thresh condition helps avoid noise P = Signal; // P is the peak } // keep track of highest point in pulse wave // NOW IT'S TIME TO LOOK FOR THE HEART BEAT // signal surges up in value every time there is a pulse if (Number > 500){ // avoid high frequency noise //MHMS increased from 250 to 500 to reduce high freq noise if ((Signal > thresh) && (Pulse == FALSE) && (Number > (int)(IBI/5)*3) ){ Pulse = TRUE; // set the Pulse flag when we think there is a pulse //MHMS could define some external LED or just write to LCD screen "Pulse found" HalLedSet (HAL_LED_2, HAL_LED_MODE_OFF); //MHMS beat found HalLedSet (HAL_LED_1, HAL_LED_MODE_ON); //MHMS LED on during upbeat IBI = sampleCounter - lastBeatTime; // measure time between beats in mS lastBeatTime = sampleCounter; // keep track of time for next pulse if(firstBeat){ // if it's the first time we found a beat, if firstBeat == TRUE firstBeat = FALSE; // clear firstBeat flag return; // IBI value is unreliable so discard it } if(secondBeat){ // if this is the second beat, if secondBeat == TRUE secondBeat = FALSE; // clear secondBeat flag for(int i=0; i<=9; i++){ // seed the running total to get a realisitic BPM at startup rate[i] = IBI; } } // keep a running total of the last 10 IBI values int16 runningTotal = 0; // clear the runningTotal variable for(int i=0; i<=8; i++){ // shift data in the rate array rate[i] = rate[i+1]; // and drop the oldest IBI value runningTotal += rate[i]; // add up the 9 oldest IBI values } rate[9] = IBI; // add the latest IBI to the rate array runningTotal += rate[9]; // add the latest IBI to runningTotal runningTotal /= 10; // average the last 10 IBI values BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! QS = TRUE; // set Quantified Self flag //MHMS we will use this to flag other event to transmit data over network HalLcdWriteStringValue("BPM:",BPM, 10, HAL_LCD_LINE_5); //MHMS display BPM on LCD screen } } if (Signal < thresh && Pulse == TRUE){ // when the values are going down, the beat is over HalLedSet (HAL_LED_1, HAL_LED_MODE_OFF); //MHMS turn LED light off for the off beat Pulse = FALSE; // reset the Pulse flag so we can do it again amp = P - T; // get amplitude of the pulse wave thresh = amp/2 + T + 100; // set thresh at 50% of the amplitude //MHMS offset up by 100 to ignore small flucuations due to noise P = thresh; // reset these for next time T = thresh; } if (Number > 2500){ // if 2.5 seconds go by without a beat HalLedSet (HAL_LED_2, HAL_LED_MODE_ON);// MHMS Indicate that no beat found thresh = 512 + 100; // set thresh default //MHMS offset by 100 to ignore small flucuations due to noise P = 512; // set P default T = 512; // set T default lastBeatTime = sampleCounter; // bring the lastBeatTime up to date firstBeat = TRUE; // set these to avoid noise secondBeat = TRUE; // when we get the heartbeat back QS = FALSE; // Clears Pulse measurement quantifier flag so no data is sent over the air } //MHMS Loading 16 bit results into 8 bit blocks for pulsedata array for pulsedata[MHMS_BPM] = (uint8)((BPM & 0x00FF)); pulsedata[MHMS_RAW_MSB] = (uint8)((Signal >> 8)); pulsedata[MHMS_RAW_LSB] = (uint8)((Signal & 0x00FF)); pulsedata[MHMS_IBI] = (uint8)((IBI & 0x00FF)); pulsedata[MHMS_BPM_CHAR] = 'B'; pulsedata[MHMS_RAW_CHAR] = 'S'; pulsedata[MHMS_IBI_CHAR] = 'Q'; }
uint8 simpleProfileReadConfig(uint16 uuid, uint8 *newValue) { uint8 len = 0; switch ( uuid ) { case SIMPLEPROFILE_CHAR1_UUID: case SIMPLEPROFILE_CHAR2_UUID: case SIMPLEPROFILE_CHAR4_UUID: break; case SIMPLEPROFILE_CHAR5_UUID: HalLcdWriteString( "Char 5 read", HAL_LCD_LINE_6 ); newValue[len++] = sys_config.update_time_ms>>24; newValue[len++] = sys_config.update_time_ms>>16; newValue[len++] = sys_config.update_time_ms>>8; newValue[len++] = sys_config.update_time_ms>>0; break; case SIMPLEPROFILE_CHAR6_UUID: { break; } case SIMPLEPROFILE_CHAR7_UUID: HalLcdWriteString( "Char 7 read", HAL_LCD_LINE_6 ); len = osal_strlen((char*)sys_config.name); osal_memcpy(newValue, sys_config.name, len); break; case SIMPLEPROFILE_CHAR8_UUID: HalLcdWriteString( "Char 8 read", HAL_LCD_LINE_6 ); // 最高温度报警 newValue[len++] = sys_config.tempeature_hight>>8; newValue[len++] = sys_config.tempeature_hight & 0xff; // 最低温度报警 newValue[len++] = sys_config.tempeature_low>>8; newValue[len++] = sys_config.tempeature_low & 0xff; break; case SIMPLEPROFILE_CHAR9_UUID: HalLcdWriteString( "Char 9 read", HAL_LCD_LINE_6 ); HalAdcSetReference( HAL_ADC_REF_AVDD ); { uint16 adc0, adc1; adc0 = HalAdcRead( HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_14 ) & 0x1fff; adc1 = HalAdcRead( HAL_ADC_CHANNEL_1, HAL_ADC_RESOLUTION_14 ) & 0x1fff; newValue[len++] = adc0>>8; newValue[len++] = adc0 & 0xFF; newValue[len++] = adc1>>8; newValue[len++] = adc1 & 0xFF; } break; case SIMPLEPROFILE_CHARA_UUID:// pwm HalLcdWriteString( "Char A read", HAL_LCD_LINE_6 ); newValue[len++] = sys_config.pwm[3]; newValue[len++] = sys_config.pwm[2]; newValue[len++] = sys_config.pwm[1]; newValue[len++] = sys_config.pwm[0]; break; default: len = 0; } return len; }
/********************************************************************* * @fn battMeasure * * @brief Measure the battery level with the ADC and return * it as a percentage 0-100%. * * @return Battery level. */ uint8 battMeasure( void ) { static unsigned char i; unsigned char j; static uint8 percent[16]; uint16 adc; uint16 buffer; /** * Battery level conversion from ADC to a percentage: * * The maximum ADC value for the battery voltage level is 511 for a * 10-bit conversion. The ADC value is references vs. 1.25v and * this maximum value corresponds to a voltage of 3.75v. * * For a coin cell battery 4.2v = 100%. The minimum operating * voltage of the CC2540 is 4.2v so 3.4v = 0%. * * To convert a voltage to an ADC value use: * * (v*1/3)/3.3 * 4095 = adc * * 4.2v = 1737 ADC * 3.4v = 1406 ADC * * We need to map ADC values from 434-351 to 100%-0%. * * Normalize the ADC values to zero: * * 433 - 351 = 82 * * And convert ADC range to percentage range: * * percent/adc = 100/82 = 50/41 * * Resulting in the final equation, with round: * * percent = ((adc - 351) * 50) / 41 */ // Call measurement setup callback if (battServiceSetupCB != NULL) { battServiceSetupCB(); } // Configure ADC and perform a read // HalAdcSetReference( HAL_ADC_REF_125V ); HalAdcSetReference(HAL_ADC_REF_AVDD); adc = HalAdcRead( battServiceAdcCh, HAL_ADC_RESOLUTION_12 ); // Call measurement teardown callback if (battServiceTeardownCB != NULL) { battServiceTeardownCB(); } if (adc >= battMaxLevel) { percent[i++] = (battMaxLevel - battMinLevel)>>1; }
/************************************************************************************************** * @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()
/********************************************************************* * @fn simpleBLECentralEventCB * * @brief Central event callback function. * * @param pEvent - pointer to event structure * * @return none */ static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent ) { switch ( pEvent->gap.opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { LCD_WRITE_STRING( "BLE Central", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( pEvent->initDone.devAddr ), HAL_LCD_LINE_2 ); } break; case GAP_DEVICE_INFO_EVENT: { var1= pEvent->deviceInfo.pEvtData; dataToPrint = var1[5]; //LCD_WRITE_STRING( bdAddr2Str(var1), HAL_LCD_LINE_3 ); if(dataToPrint == 0xA1) { LCD_WRITE_STRING_VALUE( "Value",var1[6], 16, HAL_LCD_LINE_3); } // if filtering device discovery results based on service UUID if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE ) { if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID, pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen ) ) { simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType ); } } } break; case GAP_DEVICE_DISCOVERY_EVENT: { // discovery complete simpleBLEScanning = FALSE; // if not filtering device discovery results based on service UUID if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE ) { // Copy results simpleBLEScanRes = pEvent->discCmpl.numDevs; osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList, (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) ); } LCD_WRITE_STRING_VALUE( "Devices Found", simpleBLEScanRes, 10, HAL_LCD_LINE_1 ); if ( simpleBLEScanRes > 0 ) { LCD_WRITE_STRING( "<- To Select", HAL_LCD_LINE_2 ); simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; } if ( simpleBLEState != BLE_STATE_CONNECTED ) { if ( !simpleBLEScanning ) { uint8 adc7 = HalAdcRead (HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8); LCD_WRITE_STRING_VALUE( "Value",adc7, 16, HAL_LCD_LINE_2); advertData[6]= var1[6]; advertData[8]= 0xA9; if(adc7>0x7E) advertData[9]= 0x01; else advertData[9]= 0x02; advertData[10]= 0xB9; GAP_UpdateAdvertisingData( GAPROLE_ADVERT_ENABLED,TRUE, sizeof(advertData),advertData); simpleBLEScanning = TRUE; simpleBLEScanRes = 0; LCD_WRITE_STRING( "Discovering...", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST ); } else { GAPCentralRole_CancelDiscovery(); } } // initialize scan index to last device simpleBLEScanIdx = simpleBLEScanRes; } break; case GAP_LINK_ESTABLISHED_EVENT: { if ( pEvent->gap.hdr.status == SUCCESS ) { simpleBLEState = BLE_STATE_CONNECTED; simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle; simpleBLEProcedureInProgress = TRUE; // If service discovery not performed initiate service discovery if ( simpleBLECharHdl == 0 ) { osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY ); } LCD_WRITE_STRING( bdAddr2Str(var1), HAL_LCD_LINE_3 ); LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( pEvent->linkCmpl.devAddr ), HAL_LCD_LINE_2 ); } else { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; LCD_WRITE_STRING( "Connect Failed", HAL_LCD_LINE_1 ); LCD_WRITE_STRING_VALUE( "Reason:", pEvent->gap.hdr.status, 10, HAL_LCD_LINE_2 ); } } break; case GAP_LINK_TERMINATED_EVENT: { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; simpleBLECharHdl = 0; simpleBLEProcedureInProgress = FALSE; LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason, 10, HAL_LCD_LINE_2 ); } break; case GAP_LINK_PARAM_UPDATE_EVENT: { LCD_WRITE_STRING( "Connected Update", HAL_LCD_LINE_1 ); } break; default: break; } }