-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
samples: cmsis_dsp: add moving average sample #66726
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.20.0) | ||
|
||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(moving_average) | ||
|
||
target_sources(app PRIVATE src/main.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
.. zephyr:code-sample:: cmsis-dsp-moving-average | ||
:name: CMSIS-DSP moving average | ||
|
||
Use the CMSIS-DSP library to calculate the moving average of a signal. | ||
|
||
Overview | ||
******** | ||
|
||
This sample demonstrates how to use the CMSIS-DSP library to calculate the moving average of a | ||
signal. | ||
|
||
It can be run on any board supported in Zephyr, but note that CMSIS-DSP is specifically optimized | ||
for ARM Cortex-A and Cortex-M processors. | ||
|
||
A **moving average** filter is a common method used for smoothing noisy data. It can be implemented | ||
as a finite impulse response (FIR) filter where the filter coefficients are all equal to 1/N, where | ||
N is the number of "taps" (i.e. the size of the moving average window). | ||
|
||
The sample uses a very simple input signal of 32 samples, and computes the moving average using a | ||
"window" of 10 samples. The resulting output is computed in one single call to the ``arm_fir_q31()`` | ||
CMSIS-DSP function, and displayed on the console. | ||
|
||
.. note:: | ||
In order to allow an easy comparison of the efficiency of the CMSIS-DSP library when used on ARM | ||
processors vs. other architectures, the sample outputs the time and number of cycles it took to | ||
compute the moving average. | ||
|
||
Requirements | ||
************ | ||
|
||
CMSIS-DSP is an optional module and needs to be added explicitly to your Zephyr workspace: | ||
|
||
.. code-block:: shell | ||
|
||
west config manifest.project-filter -- +cmsis-dsp | ||
west update cmsis-dsp | ||
|
||
Building and Running | ||
********************* | ||
|
||
The demo can be built as follows: | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/modules/cmsis-dsp/moving_average | ||
:host-os: unix | ||
:board: qemu_cortex_m0 | ||
:goals: run | ||
:compact: | ||
|
||
The sample will output the number of cycles it took to compute the moving averages, as well as the | ||
computed average for each 10-sample long window of the input signal. | ||
|
||
.. code-block:: console | ||
|
||
*** Booting Zephyr OS build v3.6.0-224-gb55824751d6c *** | ||
Time: 244 us (244 cycles) | ||
Input[00]: 0 0 0 0 0 0 0 0 0 0 | Output[00]: 0.00 | ||
Input[01]: 0 0 0 0 0 0 0 0 0 1 | Output[01]: 0.10 | ||
Input[02]: 0 0 0 0 0 0 0 0 1 2 | Output[02]: 0.30 | ||
Input[03]: 0 0 0 0 0 0 0 1 2 3 | Output[03]: 0.60 | ||
... | ||
Input[30]: 21 22 23 24 25 26 27 28 29 30 | Output[30]: 25.50 | ||
Input[31]: 22 23 24 25 26 27 28 29 30 31 | Output[31]: 26.50 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
CONFIG_REQUIRES_FULL_LIBC=y | ||
CONFIG_REQUIRES_FLOAT_PRINTF=y | ||
|
||
CONFIG_CMSIS_DSP=y | ||
CONFIG_CMSIS_DSP_FILTERING=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
sample: | ||
description: Use CMSIS DSP to calculate moving average | ||
name: CMSIS DSP Moving Average | ||
tests: | ||
sample.modules.cmsis_dsp.moving_average: | ||
tags: | ||
- samples | ||
integration_platforms: | ||
- qemu_cortex_m0 | ||
- native_sim | ||
modules: | ||
- cmsis-dsp | ||
harness: console | ||
harness_config: | ||
type: multi_line | ||
regex: | ||
- "Input\\[00\\]: 0 0 0 0 0 0 0 0 0 0 | Output\\[00\\]: 0.00" | ||
- "Input\\[01\\]: 0 0 0 0 0 0 0 0 0 1 | Output\\[01\\]: 0.10" | ||
- "Input\\[02\\]: 0 0 0 0 0 0 0 0 1 2 | Output\\[02\\]: 0.30" | ||
- "Input\\[03\\]: 0 0 0 0 0 0 0 1 2 3 | Output\\[03\\]: 0.60" | ||
- "Input\\[04\\]: 0 0 0 0 0 0 1 2 3 4 | Output\\[04\\]: 1.00" | ||
- "Input\\[05\\]: 0 0 0 0 0 1 2 3 4 5 | Output\\[05\\]: 1.50" | ||
- "Input\\[06\\]: 0 0 0 0 1 2 3 4 5 6 | Output\\[06\\]: 2.10" | ||
- "Input\\[07\\]: 0 0 0 1 2 3 4 5 6 7 | Output\\[07\\]: 2.80" | ||
- "Input\\[08\\]: 0 0 1 2 3 4 5 6 7 8 | Output\\[08\\]: 3.60" | ||
- "Input\\[09\\]: 0 1 2 3 4 5 6 7 8 9 | Output\\[09\\]: 4.50" | ||
- "Input\\[10\\]: 1 2 3 4 5 6 7 8 9 10 | Output\\[10\\]: 5.50" | ||
- "Input\\[11\\]: 2 3 4 5 6 7 8 9 10 11 | Output\\[11\\]: 6.50" | ||
- "Input\\[12\\]: 3 4 5 6 7 8 9 10 11 12 | Output\\[12\\]: 7.50" | ||
- "Input\\[13\\]: 4 5 6 7 8 9 10 11 12 13 | Output\\[13\\]: 8.50" | ||
- "Input\\[14\\]: 5 6 7 8 9 10 11 12 13 14 | Output\\[14\\]: 9.50" | ||
- "Input\\[15\\]: 6 7 8 9 10 11 12 13 14 15 | Output\\[15\\]: 10.50" | ||
- "Input\\[16\\]: 7 8 9 10 11 12 13 14 15 16 | Output\\[16\\]: 11.50" | ||
- "Input\\[17\\]: 8 9 10 11 12 13 14 15 16 17 | Output\\[17\\]: 12.50" | ||
- "Input\\[18\\]: 9 10 11 12 13 14 15 16 17 18 | Output\\[18\\]: 13.50" | ||
- "Input\\[19\\]: 10 11 12 13 14 15 16 17 18 19 | Output\\[19\\]: 14.50" | ||
- "Input\\[20\\]: 11 12 13 14 15 16 17 18 19 20 | Output\\[20\\]: 15.50" | ||
- "Input\\[21\\]: 12 13 14 15 16 17 18 19 20 21 | Output\\[21\\]: 16.50" | ||
- "Input\\[22\\]: 13 14 15 16 17 18 19 20 21 22 | Output\\[22\\]: 17.50" | ||
- "Input\\[23\\]: 14 15 16 17 18 19 20 21 22 23 | Output\\[23\\]: 18.50" | ||
- "Input\\[24\\]: 15 16 17 18 19 20 21 22 23 24 | Output\\[24\\]: 19.50" | ||
- "Input\\[25\\]: 16 17 18 19 20 21 22 23 24 25 | Output\\[25\\]: 20.50" | ||
- "Input\\[26\\]: 17 18 19 20 21 22 23 24 25 26 | Output\\[26\\]: 21.50" | ||
- "Input\\[27\\]: 18 19 20 21 22 23 24 25 26 27 | Output\\[27\\]: 22.50" | ||
- "Input\\[28\\]: 19 20 21 22 23 24 25 26 27 28 | Output\\[28\\]: 23.50" | ||
- "Input\\[29\\]: 20 21 22 23 24 25 26 27 28 29 | Output\\[29\\]: 24.50" | ||
- "Input\\[30\\]: 21 22 23 24 25 26 27 28 29 30 | Output\\[30\\]: 25.50" | ||
- "Input\\[31\\]: 22 23 24 25 26 27 28 29 30 31 | Output\\[31\\]: 26.50" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (c) 2024 Benjamin Cabé <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <zephyr/kernel.h> | ||
|
||
#include "arm_math.h" | ||
|
||
#define NUM_TAPS 10 /* Number of taps in the FIR filter (length of the moving average window) */ | ||
#define BLOCK_SIZE 32 /* Number of samples processed per block */ | ||
|
||
/* | ||
* Filter coefficients are all equal for a moving average filter. Here, 1/NUM_TAPS = 0.1f. | ||
*/ | ||
q31_t firCoeffs[NUM_TAPS] = {0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, | ||
0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD}; | ||
|
||
arm_fir_instance_q31 sFIR; | ||
q31_t firState[NUM_TAPS + BLOCK_SIZE - 1]; | ||
|
||
int main(void) | ||
{ | ||
q31_t input[BLOCK_SIZE]; | ||
q31_t output[BLOCK_SIZE]; | ||
uint32_t start, end; | ||
|
||
/* Initialize input data with a ramp from 0 to 31 */ | ||
for (int i = 0; i < BLOCK_SIZE; i++) { | ||
input[i] = i << 24; /* Convert to Q31 format */ | ||
} | ||
|
||
/* Initialize the FIR filter */ | ||
arm_fir_init_q31(&sFIR, NUM_TAPS, firCoeffs, firState, BLOCK_SIZE); | ||
|
||
/* Apply the FIR filter to the input data and measure how many cycles this takes */ | ||
start = k_cycle_get_32(); | ||
arm_fir_q31(&sFIR, input, output, BLOCK_SIZE); | ||
end = k_cycle_get_32(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does averaging 32 samples take long enough to show up at the cycle resolution? |
||
|
||
printf("Time: %u us (%u cycles)\n", k_cyc_to_us_floor32(end - start), end - start); | ||
|
||
for (int i = 0; i < BLOCK_SIZE; i++) { | ||
printf("Input[%02d]: ", i); | ||
for (int j = NUM_TAPS - 1; j >= 0; j--) { | ||
if (j <= i) { | ||
printf("%2d ", (int)(input[i - j] >> 24)); | ||
} else { | ||
printf("%2d ", 0); | ||
} | ||
} | ||
printf("| Output[%02d]: %6.2f\n", i, (double)output[i] / (1 << 24)); | ||
} | ||
|
||
return 0; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
mps2_an521_remote
here would be a nice opportunity to show MVE in action :).