Skip to content

Commit 754152a

Browse files
Run data processor on a circular-ish buffer.
1 parent 760e2e9 commit 754152a

File tree

5 files changed

+37
-16
lines changed

5 files changed

+37
-16
lines changed

main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
input.onButtonPressed(Button.A, function () {
22
basic.clearScreen()
33
})
4+
testrunner.onMlEvent(TestRunnerLabels.None, function () {
5+
basic.clearScreen()
6+
})
47
testrunner.onMlEvent(TestRunnerLabels.Shake, function () {
58
basic.showString("S")
69
})

mlrunner/filterdataprocessor.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414

1515
static float **input_samples = NULL;
16+
static float *temp_buffer = NULL;
1617
static int sample_dimensions = 0;
1718
static int sample_length = 0;
1819
static int sample_index = 0;
20+
static bool buffer_filled = false;
1921
static float *output_data = NULL;
2022
static int output_length = 0;
2123
static MlDataFilters_t *filters = NULL;
@@ -58,7 +60,7 @@ MldpReturn_t filterDataProcessor_init(const MlDataProcessorConfig_t* config) {
5860
return MLDP_ERROR_ALLOC;
5961
}
6062

61-
// Allocate for each sample dimension
63+
// Allocate for each sample dimension, and the temporary buffer
6264
sample_dimensions = config->dimensions;
6365
for (int i = 0; i < sample_dimensions; i++) {
6466
input_samples[i] = (float*)malloc(config->samples * sizeof(float));
@@ -67,6 +69,11 @@ MldpReturn_t filterDataProcessor_init(const MlDataProcessorConfig_t* config) {
6769
return MLDP_ERROR_ALLOC;
6870
}
6971
}
72+
temp_buffer = (float*)malloc(config->samples * sizeof(float));
73+
if (temp_buffer == NULL) {
74+
filterDataProcessor_deinit();
75+
return MLDP_ERROR_ALLOC;
76+
}
7077

7178
// Copy the filter pointers
7279
memcpy(filters, config->filters, config->filter_size * sizeof(MlDataFilters_t));
@@ -86,6 +93,7 @@ void filterDataProcessor_deinit() {
8693
free(input_samples[i]);
8794
}
8895
free(input_samples);
96+
free(temp_buffer);
8997
free(output_data);
9098
free(filters);
9199
input_samples = NULL;
@@ -111,6 +119,7 @@ MldpReturn_t filterDataProcessor_recordData(const float* samples, const int elem
111119
sample_index++;
112120
if (sample_index >= sample_length) {
113121
sample_index = 0;
122+
buffer_filled = true;
114123
}
115124
}
116125

@@ -120,18 +129,22 @@ MldpReturn_t filterDataProcessor_recordData(const float* samples, const int elem
120129
bool filterDataProcessor_isDataReady() {
121130
if (!initialised) return false;
122131

123-
return sample_index == 0;
132+
return buffer_filled;
124133
}
125134

126135
float* filterDataProcessor_getProcessedData() {
127136
if (!initialised) return NULL;
137+
if (!buffer_filled) return NULL;
128138

129139
// Run all filters and save their output to output_data
130140
int output_i = 0;
131141
for (int filter_i = 0; filter_i < filter_size; filter_i++) {
132142
for (int dimension_i = 0; dimension_i < sample_dimensions; dimension_i++) {
143+
const int elements_left = sample_length - sample_index;
144+
memcpy(temp_buffer, &input_samples[dimension_i][sample_index], elements_left * sizeof(float));
145+
memcpy(&temp_buffer[elements_left], input_samples[dimension_i], sample_index * sizeof(float));
133146
MldpReturn_t filter_result = filters[filter_i].filter(
134-
input_samples[dimension_i], sample_length,
147+
temp_buffer, sample_length,
135148
&output_data[output_i], filters[filter_i].out_size
136149
);
137150
if (filter_result != MLDP_SUCCESS) {

mlrunner/mldataprocessor.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ typedef struct {
3131
} MlDataFilters_t;
3232

3333
typedef struct {
34-
const int samples;
35-
const int dimensions;
36-
const int output_length;
37-
const int filter_size;
34+
const int samples; // How many samples are needed to calculated the processed output
35+
const int dimensions; // How many dimensions each sample contains (e.g. x, y, z is 3 dimensions)
36+
const int output_length; // Expected number elements produced by the processed output, depends on filters
37+
const int filter_size; // How many filters in the *filters array
3838
const MlDataFilters_t *filters;
3939
} MlDataProcessorConfig_t;
4040

testextension.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,11 @@ static inline uint32_t calcTicks(uint32_t ticks_start, uint32_t ticks_end) {
5353

5454

5555
namespace testrunner {
56+
static bool initialised = false;
5657
static ml_actions_t *actions = NULL;
5758
static ml_predictions_t *predictions = NULL;
58-
static bool initialised = false;
59+
static int ml_sample_counts_per_prediction = 0;
60+
static const int ML_PREDICTIONS_PER_SECOND = 4;
5961
static const uint16_t ML_CODAL_TIMER_VALUE = 1;
6062

6163
// Order is important for the outputData as set in:
@@ -119,22 +121,22 @@ namespace testrunner {
119121
void recordAccData(MicroBitEvent) {
120122
if (!initialised) return;
121123

124+
const Sample3D accSample = uBit.accelerometer.getSample();
122125
const float accData[3] = {
123-
uBit.accelerometer.getX() / 1000.0f,
124-
uBit.accelerometer.getY() / 1000.0f,
125-
uBit.accelerometer.getZ() / 1000.0f,
126+
accSample.x / 1000.0f,
127+
accSample.y / 1000.0f,
128+
accSample.z / 1000.0f,
126129
};
127130
MldpReturn_t recordDataResult = mlDataProcessor.recordData(accData, 3);
128131
if (recordDataResult != MLDP_SUCCESS) {
129132
DEBUG_PRINT("Failed to record accelerometer data\n");
130133
return;
131134
}
132135

133-
if (mlDataProcessor.isDataReady()) {
134-
// Stop firing timer events while running model and resume after
135-
uBit.messageBus.ignore(TEST_RUNNER_ID_TIMER, ML_CODAL_TIMER_VALUE, &recordAccData);
136+
// Run model every ml_sample_counts_per_prediction samples
137+
static unsigned int samplesTaken = 0;
138+
if (!(++samplesTaken % ml_sample_counts_per_prediction) && mlDataProcessor.isDataReady()) {
136139
runModel();
137-
uBit.messageBus.listen(TEST_RUNNER_ID_TIMER, ML_CODAL_TIMER_VALUE, &recordAccData, MESSAGE_BUS_LISTENER_DROP_IF_BUSY);
138140
}
139141
}
140142

@@ -236,6 +238,9 @@ namespace testrunner {
236238
uBit.panic(TEST_RUNNER_ERROR + 11);
237239
}
238240

241+
// Using sampling period to calculate how samples have to run for the next model run
242+
ml_sample_counts_per_prediction = (1000 / ML_PREDICTIONS_PER_SECOND) / samplesPeriodMillisec;
243+
239244
const MlDataProcessorConfig_t mlDataConfig = {
240245
.samples = samplesLen,
241246
.dimensions = sampleDimensions,

testextension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace testrunner {
1919
//% block="on ML event %value"
2020
export function onMlEvent(mlEvent: TestRunnerLabels, body: () => void): void {
2121
startRunning();
22-
control.onEvent(TestRunnerIds.TestRunnerInference, mlEvent, body)
22+
control.onEvent(TestRunnerIds.TestRunnerInference, mlEvent, body, EventFlags.DropIfBusy)
2323
}
2424

2525
/**

0 commit comments

Comments
 (0)