Using the MBED BLE library and Nordic Puck library this is a simple scoring application using Bluetooth LE. It monitors three analog inputs and triggers on reception of a pulse on any one recording data for a short period on all three. This is then published via BLE characteristics. It's a demonstrator for a new UI dev toolkit that is under development.
Fork of Example_Puck_BLE by
SampleChannel.cpp@4:cc164ecf6a36, 2014-08-23 (annotated)
- Committer:
- Bobty
- Date:
- Sat Aug 23 09:31:01 2014 +0000
- Revision:
- 4:cc164ecf6a36
- Parent:
- 3:a155da1cbde3
- Child:
- 8:87a3708dca9c
Ticker working on 100ms intervals with BLE enabled but no analog activity
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bobty | 3:a155da1cbde3 | 1 | // Simple averaging filter |
Bobty | 3:a155da1cbde3 | 2 | #include "mbed.h" |
Bobty | 3:a155da1cbde3 | 3 | #include "UUID.h" |
Bobty | 3:a155da1cbde3 | 4 | #include "SampleChannel.h" |
Bobty | 3:a155da1cbde3 | 5 | |
Bobty | 3:a155da1cbde3 | 6 | SampleChannel::SampleChannel(PinName pin, const UUID uuid, Serial* pLogger) : chanUuid(uuid), ain(pin) |
Bobty | 3:a155da1cbde3 | 7 | { |
Bobty | 3:a155da1cbde3 | 8 | pLocalLogger = pLogger; |
Bobty | 3:a155da1cbde3 | 9 | for (int i = 0; i < NUM_FILTER_VALS; i++) |
Bobty | 3:a155da1cbde3 | 10 | filterBuf[i] = 0; |
Bobty | 3:a155da1cbde3 | 11 | curFilterIdx = 0; |
Bobty | 3:a155da1cbde3 | 12 | for (int i = 0; i < NUM_RETURN_SAMPLES; i++) |
Bobty | 3:a155da1cbde3 | 13 | sampleBuf[i] = 0; |
Bobty | 3:a155da1cbde3 | 14 | curSampleIdx = 0; |
Bobty | 3:a155da1cbde3 | 15 | isCapturing = false; |
Bobty | 3:a155da1cbde3 | 16 | sampleThreshold = 100; |
Bobty | 3:a155da1cbde3 | 17 | sampleDivisor = 10; |
Bobty | 3:a155da1cbde3 | 18 | testSampleCount = 0; |
Bobty | 3:a155da1cbde3 | 19 | sampleBaseVal = 0; |
Bobty | 3:a155da1cbde3 | 20 | } |
Bobty | 3:a155da1cbde3 | 21 | |
Bobty | 3:a155da1cbde3 | 22 | void SampleChannel::SetThreshold(uint16_t threshold) |
Bobty | 3:a155da1cbde3 | 23 | { |
Bobty | 3:a155da1cbde3 | 24 | sampleThreshold = threshold; |
Bobty | 3:a155da1cbde3 | 25 | } |
Bobty | 3:a155da1cbde3 | 26 | |
Bobty | 3:a155da1cbde3 | 27 | void SampleChannel::SetDivisor(uint16_t divisor) |
Bobty | 3:a155da1cbde3 | 28 | { |
Bobty | 3:a155da1cbde3 | 29 | sampleDivisor = divisor; |
Bobty | 3:a155da1cbde3 | 30 | } |
Bobty | 3:a155da1cbde3 | 31 | |
Bobty | 3:a155da1cbde3 | 32 | void SampleChannel::AddSample(uint16_t val) |
Bobty | 3:a155da1cbde3 | 33 | { |
Bobty | 3:a155da1cbde3 | 34 | testSampleCount++; |
Bobty | 4:cc164ecf6a36 | 35 | if (testSampleCount == 1000) |
Bobty | 3:a155da1cbde3 | 36 | { |
Bobty | 4:cc164ecf6a36 | 37 | // pLocalLogger->printf("%d AvgT %d, AvgW %d, low %d\n", val, GetAvgOfTriggerWindow(), GetAvgOutsideTriggerWindow(), GetLowest()); |
Bobty | 3:a155da1cbde3 | 38 | testSampleCount = 0; |
Bobty | 3:a155da1cbde3 | 39 | } |
Bobty | 3:a155da1cbde3 | 40 | |
Bobty | 3:a155da1cbde3 | 41 | // If capturing add to sample buf |
Bobty | 3:a155da1cbde3 | 42 | if (isCapturing) |
Bobty | 3:a155da1cbde3 | 43 | { |
Bobty | 3:a155da1cbde3 | 44 | if (curSampleIdx < NUM_RETURN_SAMPLES) |
Bobty | 3:a155da1cbde3 | 45 | { |
Bobty | 3:a155da1cbde3 | 46 | int mungedVal = val - sampleBaseVal; |
Bobty | 3:a155da1cbde3 | 47 | if (mungedVal < 0) |
Bobty | 3:a155da1cbde3 | 48 | mungedVal = 0; |
Bobty | 3:a155da1cbde3 | 49 | mungedVal = mungedVal / sampleDivisor; |
Bobty | 3:a155da1cbde3 | 50 | if (mungedVal > 255) |
Bobty | 3:a155da1cbde3 | 51 | mungedVal = 255; |
Bobty | 3:a155da1cbde3 | 52 | sampleBuf[curSampleIdx++] = (uint8_t)mungedVal; |
Bobty | 3:a155da1cbde3 | 53 | } |
Bobty | 3:a155da1cbde3 | 54 | } |
Bobty | 3:a155da1cbde3 | 55 | // Add to filter |
Bobty | 3:a155da1cbde3 | 56 | filterBuf[curFilterIdx] = val; |
Bobty | 3:a155da1cbde3 | 57 | curFilterIdx++; |
Bobty | 3:a155da1cbde3 | 58 | curFilterIdx = curFilterIdx % NUM_FILTER_VALS; |
Bobty | 3:a155da1cbde3 | 59 | } |
Bobty | 3:a155da1cbde3 | 60 | |
Bobty | 3:a155da1cbde3 | 61 | int SampleChannel::GetAvgOutsideTriggerWindow() |
Bobty | 3:a155da1cbde3 | 62 | { |
Bobty | 3:a155da1cbde3 | 63 | int sum = 0; |
Bobty | 3:a155da1cbde3 | 64 | for (int i = 0; i < NUM_FILTER_VALS-TRIGGER_WINDOW; i++) |
Bobty | 3:a155da1cbde3 | 65 | sum += filterBuf[(i + curFilterIdx) % NUM_FILTER_VALS]; |
Bobty | 3:a155da1cbde3 | 66 | return sum / (NUM_FILTER_VALS - TRIGGER_WINDOW); |
Bobty | 3:a155da1cbde3 | 67 | } |
Bobty | 3:a155da1cbde3 | 68 | |
Bobty | 3:a155da1cbde3 | 69 | int SampleChannel::GetAvgOfTriggerWindow() |
Bobty | 3:a155da1cbde3 | 70 | { |
Bobty | 3:a155da1cbde3 | 71 | int sum = 0; |
Bobty | 3:a155da1cbde3 | 72 | for (int i = 0; i < TRIGGER_WINDOW; i++) |
Bobty | 3:a155da1cbde3 | 73 | sum += filterBuf[(curFilterIdx + NUM_FILTER_VALS - 1 - i) % NUM_FILTER_VALS]; |
Bobty | 3:a155da1cbde3 | 74 | return sum / TRIGGER_WINDOW; |
Bobty | 3:a155da1cbde3 | 75 | } |
Bobty | 3:a155da1cbde3 | 76 | |
Bobty | 3:a155da1cbde3 | 77 | uint16_t SampleChannel::GetLowest() |
Bobty | 3:a155da1cbde3 | 78 | { |
Bobty | 3:a155da1cbde3 | 79 | uint16_t lowVal = 0xffff; |
Bobty | 3:a155da1cbde3 | 80 | for (int i = 0; i < NUM_FILTER_VALS; i++) |
Bobty | 3:a155da1cbde3 | 81 | if (lowVal > filterBuf[i]) |
Bobty | 3:a155da1cbde3 | 82 | lowVal = filterBuf[i]; |
Bobty | 3:a155da1cbde3 | 83 | return lowVal; |
Bobty | 3:a155da1cbde3 | 84 | } |
Bobty | 3:a155da1cbde3 | 85 | |
Bobty | 3:a155da1cbde3 | 86 | void SampleChannel::Service() |
Bobty | 3:a155da1cbde3 | 87 | { |
Bobty | 3:a155da1cbde3 | 88 | // take a sample and add to trigger buffer |
Bobty | 3:a155da1cbde3 | 89 | unsigned short val = ain.read_u16(); |
Bobty | 3:a155da1cbde3 | 90 | AddSample(val); |
Bobty | 3:a155da1cbde3 | 91 | } |
Bobty | 3:a155da1cbde3 | 92 | |
Bobty | 3:a155da1cbde3 | 93 | bool SampleChannel::IsSampling() |
Bobty | 3:a155da1cbde3 | 94 | { |
Bobty | 3:a155da1cbde3 | 95 | return isCapturing; |
Bobty | 3:a155da1cbde3 | 96 | } |
Bobty | 3:a155da1cbde3 | 97 | |
Bobty | 3:a155da1cbde3 | 98 | bool SampleChannel::AreSamplesReady() |
Bobty | 3:a155da1cbde3 | 99 | { |
Bobty | 3:a155da1cbde3 | 100 | // Check if sample ready |
Bobty | 3:a155da1cbde3 | 101 | return (isCapturing && (curSampleIdx == NUM_RETURN_SAMPLES)); |
Bobty | 3:a155da1cbde3 | 102 | } |
Bobty | 3:a155da1cbde3 | 103 | |
Bobty | 3:a155da1cbde3 | 104 | void SampleChannel::StopSampling() |
Bobty | 3:a155da1cbde3 | 105 | { |
Bobty | 3:a155da1cbde3 | 106 | isCapturing = false; |
Bobty | 3:a155da1cbde3 | 107 | } |
Bobty | 3:a155da1cbde3 | 108 | |
Bobty | 3:a155da1cbde3 | 109 | void SampleChannel::StartSampling() |
Bobty | 3:a155da1cbde3 | 110 | { |
Bobty | 3:a155da1cbde3 | 111 | curSampleIdx = 0; |
Bobty | 3:a155da1cbde3 | 112 | isCapturing = true; |
Bobty | 3:a155da1cbde3 | 113 | sampleBaseVal = GetLowest(); |
Bobty | 3:a155da1cbde3 | 114 | |
Bobty | 3:a155da1cbde3 | 115 | // Copy across values from trigger window |
Bobty | 3:a155da1cbde3 | 116 | for (int i = TRIGGER_WINDOW; i > 0; i--) |
Bobty | 3:a155da1cbde3 | 117 | AddSample(filterBuf[(curFilterIdx + NUM_FILTER_VALS - i) % NUM_FILTER_VALS]); |
Bobty | 3:a155da1cbde3 | 118 | } |
Bobty | 3:a155da1cbde3 | 119 | |
Bobty | 3:a155da1cbde3 | 120 | bool SampleChannel::CheckTrigger() |
Bobty | 3:a155da1cbde3 | 121 | { |
Bobty | 3:a155da1cbde3 | 122 | // Check if the samples in the trigger window are significantly different from the average |
Bobty | 4:cc164ecf6a36 | 123 | int spike = GetAvgOfTriggerWindow() - GetAvgOutsideTriggerWindow(); |
Bobty | 4:cc164ecf6a36 | 124 | if (spike < 0) |
Bobty | 4:cc164ecf6a36 | 125 | spike = -spike; |
Bobty | 4:cc164ecf6a36 | 126 | return spike > sampleThreshold; |
Bobty | 3:a155da1cbde3 | 127 | } |
Bobty | 3:a155da1cbde3 | 128 | |
Bobty | 3:a155da1cbde3 | 129 | uint8_t *SampleChannel::GetSamples() |
Bobty | 3:a155da1cbde3 | 130 | { |
Bobty | 3:a155da1cbde3 | 131 | return sampleBuf; |
Bobty | 3:a155da1cbde3 | 132 | } |
Bobty | 3:a155da1cbde3 | 133 | |
Bobty | 3:a155da1cbde3 | 134 | int SampleChannel::GetSamplesLen() |
Bobty | 3:a155da1cbde3 | 135 | { |
Bobty | 3:a155da1cbde3 | 136 | return NUM_RETURN_SAMPLES; |
Bobty | 3:a155da1cbde3 | 137 | } |
Bobty | 3:a155da1cbde3 | 138 |