Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Example_Puck_BLE by
main.cpp
00001 /** 00002 Scoring Device - for generic game scoring 00003 Using Puck BLE MBED library from Nordic 00004 Copyright (C) Nodule.io 2014 00005 00006 */ 00007 00008 #define LOG_LEVEL_DEBUG 00009 #include "Puck.h" 00010 #include "SampleChannel.h" 00011 00012 // This is a singleton for the Nordic Puck library which helps with some BLE init, etc. 00013 Puck* puck = &Puck::getPuck(); 00014 00015 // Gatt characteristic and service UUIDs 00016 const UUID SCORING_GATT_SERVICE = stringToUUID("nod.score1.serv "); 00017 const UUID THRESHOLD_GATT_CHARACTERISTIC = stringToUUID("nod.score1.thres"); 00018 const UUID DIVISOR_GATT_CHARACTERISTIC = stringToUUID("nod.score1.div "); 00019 const UUID INTERVAL_US_GATT_CHARACTERISTIC = stringToUUID("nod.score1.intus"); 00020 00021 // Three channels for scoring 00022 const int NUM_SAMPLE_CHANNELS = 3; 00023 00024 // Sample interval (uS) 00025 volatile uint32_t sampleIntervalUs = 10000; 00026 00027 // Interrupt driven ticker to do the sampling 00028 Timeout sampleTimeout; 00029 00030 // Sample Channels 00031 SampleChannel sampleChannels[] = 00032 { 00033 SampleChannel(P0_1, stringToUUID("nod.score1.samp1"), &logger), 00034 SampleChannel(P0_2, stringToUUID("nod.score1.samp2"), &logger), 00035 SampleChannel(P0_3, stringToUUID("nod.score1.samp3"), &logger) 00036 }; 00037 00038 // Timer to avoid repeat sampling 00039 Timer intervalTimer; 00040 int lastTriggerTime = 0; 00041 int lastSampleTime = 0; 00042 const int MIN_MS_BETWEEN_TRIGGERS = 2000; 00043 00044 // Function called in interrupt driven timeout to handle sampling 00045 static volatile int serviceCount = 0; 00046 void SampleService() 00047 { 00048 // For debug timing 00049 serviceCount++; 00050 00051 // Service all channel's state machines 00052 bool isAnyChannelSampling = false; 00053 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00054 { 00055 sampleChannels[chanIdx].Service(); 00056 if (sampleChannels[chanIdx].IsSampling()) 00057 isAnyChannelSampling = true; 00058 } 00059 00060 // Check if any channel is being sampled already (if so don't check for triggering) 00061 if (!isAnyChannelSampling) 00062 { 00063 // Check for triggering only if previous trigger was a reasonable time ago 00064 int curTimerVal = intervalTimer.read_ms(); 00065 // Check for lastTriggerTime < curTimerVal is to handle (not perfectly) overflow/reset of intervalTimer 00066 if ((lastTriggerTime < curTimerVal) || (curTimerVal - lastTriggerTime > MIN_MS_BETWEEN_TRIGGERS)) 00067 { 00068 // Check each channel to see if it's been triggered 00069 bool anythingTriggered = false; 00070 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00071 { 00072 if (sampleChannels[chanIdx].CheckTrigger()) 00073 { 00074 anythingTriggered = true; 00075 LOG_INFO("Triggered\n"); 00076 break; 00077 } 00078 } 00079 // If any channel has triggered ... 00080 if(anythingTriggered) 00081 { 00082 // Start sampling on all channels 00083 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00084 sampleChannels[chanIdx].StartSampling(); 00085 // Set timer to disallow repeated readings 00086 lastTriggerTime = curTimerVal; 00087 } 00088 } 00089 } 00090 00091 // Request a callback to this function after the sample interval 00092 sampleTimeout.attach_us(&SampleService, sampleIntervalUs); 00093 } 00094 00095 // ThresholdSet ... BLE characteristic callback 00096 void onThresholdSet(uint8_t* value) 00097 { 00098 uint16_t threshold = value[0] * 256 + value[1]; 00099 LOG_INFO("Threshold=%d\n", threshold); 00100 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00101 sampleChannels[chanIdx].SetThreshold(threshold); 00102 } 00103 00104 // DivisorSet ... BLE characteristic callback 00105 void onDivisorSet(uint8_t* value) 00106 { 00107 uint16_t divisor = value[0] * 256 + value[1]; 00108 LOG_INFO("Divisor=%d\n", divisor); 00109 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00110 sampleChannels[chanIdx].SetDivisor(divisor); 00111 } 00112 00113 // Inverval ... BLE characteristic callback 00114 void onIntervalSet(uint8_t* value) 00115 { 00116 uint32_t intervalUs = (value[0] << 24) + (value[1] << 16) + (value[2] << 8) + value[3]; 00117 LOG_INFO("SampleInterval(uS)=%d\n", intervalUs); 00118 // Interval timer is restarted in the Ticker callback so just need to store this value 00119 if (intervalUs <= 1000000) 00120 sampleIntervalUs = intervalUs; 00121 } 00122 00123 // Main - Setup BLE and service the trigger sampling and BLE 00124 int main(void) 00125 { 00126 00127 // Set baud rate 00128 logger.baud(115200); 00129 00130 // Add the Gatt characteristic for samples 00131 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00132 { 00133 puck->addCharacteristic( 00134 SCORING_GATT_SERVICE, 00135 sampleChannels[chanIdx].GetUUID(), 00136 sampleChannels[chanIdx].GetSamplesLen(), 00137 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); 00138 } 00139 00140 // Add the Gatt characteristic for threshold 00141 puck->addCharacteristic( 00142 SCORING_GATT_SERVICE, 00143 THRESHOLD_GATT_CHARACTERISTIC, 00144 sizeof(uint16_t), 00145 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); 00146 puck->onCharacteristicWrite(&THRESHOLD_GATT_CHARACTERISTIC, onThresholdSet); 00147 00148 // Add the Gatt characteristic for sample divisor 00149 puck->addCharacteristic( 00150 SCORING_GATT_SERVICE, 00151 DIVISOR_GATT_CHARACTERISTIC, 00152 sizeof(uint16_t), 00153 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); 00154 puck->onCharacteristicWrite(&DIVISOR_GATT_CHARACTERISTIC, onDivisorSet); 00155 00156 // Add the Gatt characteristic for sample interval (us) 00157 puck->addCharacteristic( 00158 SCORING_GATT_SERVICE, 00159 INTERVAL_US_GATT_CHARACTERISTIC, 00160 sizeof(sampleIntervalUs), 00161 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); 00162 puck->onCharacteristicWrite(&INTERVAL_US_GATT_CHARACTERISTIC, onIntervalSet); 00163 00164 // Initialize the puck 00165 puck->init(0xCD01); 00166 00167 // Start timer 00168 intervalTimer.start(); 00169 00170 // Start timeout to service the sampling 00171 sampleTimeout.attach_us(&SampleService, sampleIntervalUs); 00172 00173 // Wait for something to be found 00174 unsigned int lastPuckDriveTime = 0; 00175 unsigned int driveLoops = 0; 00176 unsigned int lastDriveLoops = 0; 00177 unsigned int lastServiceCount = 0; 00178 while(true) 00179 { 00180 // Service the puck 00181 puck->drive(); 00182 driveLoops++; 00183 00184 // Handle 1 second updates 00185 unsigned int nowTime = intervalTimer.read_ms(); 00186 if ((nowTime - lastPuckDriveTime >= 1000) || (nowTime < lastPuckDriveTime)) 00187 { 00188 unsigned int elapsed = nowTime - lastPuckDriveTime; 00189 LOG_INFO("E%u C%u DC%u DTC%u L%u DL%u\n", elapsed, serviceCount, serviceCount-lastServiceCount, elapsed/(serviceCount-lastServiceCount), driveLoops, driveLoops-lastDriveLoops); 00190 00191 // Check for overflow of timer 00192 if (nowTime > 100000) 00193 { 00194 intervalTimer.reset(); 00195 nowTime = 0; 00196 } 00197 00198 // Record last timer value 00199 lastPuckDriveTime = nowTime; 00200 lastDriveLoops = driveLoops; 00201 lastServiceCount = serviceCount; 00202 } 00203 00204 // Check for data ready 00205 for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) 00206 { 00207 if (sampleChannels[chanIdx].AreSamplesReady()) 00208 { 00209 // Set the value of the characteristic 00210 //puck->updateCharacteristicValue(sampleChannels[chanIdx].GetUUID(), sampleChannels[chanIdx].GetSamples(), sampleChannels[chanIdx].GetSamplesLen()); 00211 sampleChannels[chanIdx].StopSampling(); 00212 LOG_INFO("StopSampling\n"); 00213 } 00214 } 00215 } 00216 }
Generated on Wed Jul 13 2022 12:34:33 by
1.7.2
