Yes sure. This is the main.cpp file. The same code is running fine on ESP32 which I have built using the instructions for the same.
int extract_ecg_analysis_features(signal_t *signal, matrix_t *output_matrix, void *config_ptr, const float frequency){
// Implement the DSP block
ei_dsp_config_ecg_analysis_t config = *((ei_dsp_config_ecg_analysis_t*)config_ptr);
int ret;
const float sampling_freq = frequency;
matrix_t input_matrix(signal->total_length/config.axes, config.axes);
if(!input_matrix.buffer){
EIDSP_ERR(EIDSP_OUT_OF_MEM);
}
signal->get_data(0, signal->total_length, input_matrix.buffer);
// transpose the matrix so we have one row per axis (nifty!)
ret = numpy::transpose(&input_matrix);
if (ret != EIDSP_OK) {
ei_printf("ERR: Failed to transpose matrix (%d)\n", ret);
EIDSP_ERR(ret);
}
// Applying the butterworth high pass filter to the signal
ret = spectral::processing::butterworth_highpass_filter(&input_matrix, sampling_freq, 20, 1);
if(ret != EIDSP_OK){
ei_printf("ERR: Failed to filter the frequency (%d)\n", ret);
EIDSP_ERR(ret);
}
//ei_printf("\nAfter filtering:(%f)", input_matrix.buffer[10]);
// Printing the size of the input_matrix
//ei_printf("\nThe size of the signal matrix is (%zu),",signal->total_length);
//ei_printf("\nThe size of the input_matrix is ((%zu), (%zu))", input_matrix.rows, input_matrix.cols);
// Calculate the RR intervals and the heart rates
matrix_t mean_matrix(1,1);
matrix_t std_matrix(1,1);
numpy::mean(&input_matrix, &mean_matrix);
numpy::stdev(&input_matrix, &std_matrix);
//ei_printf("\nThe mean is (%f)", mean_matrix.buffer[0]);
//ei_printf("\nThe std deviation is (%f)", std_matrix.buffer[0]);
//ei_printf("\nThe first element is (%f)", input_matrix.buffer[0]);
float thres = mean_matrix.buffer[0]+ 2*(std_matrix.buffer[0]);
//ei_printf("Threshold :(%f)", thres);
matrix_t overThres(input_matrix.rows, input_matrix.cols);
for(size_t row = 0; row < input_matrix.rows; row++){
for(size_t col = 0; col < input_matrix.cols; col++){
overThres.buffer[(row*input_matrix.cols)+col]=(1*(input_matrix.buffer[(row*input_matrix.cols)+col]>thres));
}
}
//ei_printf("\nThe size of the overThres:(%zu)", overThres.cols);
matrix_t changes(1,input_matrix.cols-2);
for(size_t col = 0; col < changes.cols; col++){
changes.buffer[col]=overThres.buffer[col+2]-overThres.buffer[col+1];
}
matrix_t ndx(1, changes.cols/2);
int count = 0;
for(size_t col = 0; col < changes.cols; col++){
if(changes.buffer[col]>0){
ndx.buffer[count] = col+2;
count++;
}
if(count>changes.cols/2)
break;
}
size_t ndxlen = count;
matrix_t RRIntervals(1, (ndxlen)/2);
RRIntervals.buffer[0] = 0.0f;
for(size_t col = 0; col < RRIntervals.cols; col++){
RRIntervals.buffer[col] = ndx.buffer[col+2]-ndx.buffer[col+1];
}
float sum1 = 0.0f;
for(size_t col = 0; col < RRIntervals.cols; col++){
sum1+=RRIntervals.buffer[col];
}
float AmeanRR = sum1/RRIntervals.cols;
for(size_t col=0; col < RRIntervals.cols; col++){
if(RRIntervals.buffer[col]>(AmeanRR+(AmeanRR/3)))
RRIntervals.buffer[col]=AmeanRR;
if(RRIntervals.buffer[col]<(AmeanRR-(AmeanRR/3)))
RRIntervals.buffer[col]=AmeanRR;
}
output_matrix->cols = 150;
output_matrix->rows = 1;
for(size_t col = 0; col < 150; col++){
output_matrix->buffer[col] = RRIntervals.buffer[col];
}
return EIDSP_OK;
}
int raw_feature_get_data(size_t offset, size_t length, float *out_ptr)
{
memcpy(out_ptr, features + offset, length * sizeof(float));
return 0;
}
int main()
{
stdio_usb_init();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
ei_impulse_result_t result = {nullptr};
while (true)
{
ei_printf("Edge Impulse standalone inferencing (Raspberry Pi Pico)\n");
if (sizeof(features) / sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE)
{
ei_printf("The size of your 'features' array is not correct. Expected %d items, but had %u\n",
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) / sizeof(float));
return 1;
}
while (1)
{
// blink LED
gpio_put(LED_PIN, !gpio_get(LED_PIN));
// the features are stored into flash, and we don't want to load everything into RAM
signal_t features_signal;
features_signal.total_length = sizeof(features) / sizeof(features[0]);
features_signal.get_data = &raw_feature_get_data;
// invoke the impulse
EI_IMPULSE_ERROR res = run_classifier(&features_signal, &result, false);
ei_printf("run_classifier returned: %d\n", res);
if (res != 0)
return 1;
ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
// print the predictions
ei_printf("[");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++)
{
ei_printf("%.5f", result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(", ");
#else
if (ix != EI_CLASSIFIER_LABEL_COUNT - 1)
{
ei_printf(", ");
}
#endif
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
printf("%.3f", result.anomaly);
#endif
printf("]\n");
ei_sleep(2000);
}
}
}