test-Ordner eingefügt
This commit is contained in:
21
simulation/test/Makefile
Normal file
21
simulation/test/Makefile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
build_dir:=./build
|
||||||
|
sources:= test.c ../signalProcessing/signal_path.c
|
||||||
|
|
||||||
|
#compile_cmd:=clang-17 -std=c2x -g -lm
|
||||||
|
compile_cmd_append:=-lm
|
||||||
|
compile_cmd_opt?=-g
|
||||||
|
compile_cmd:=gcc $(compile_cmd_opt)
|
||||||
|
|
||||||
|
#extra_defines:= -DDEBUG_PRINTS
|
||||||
|
pre_build_cmd:=mkdir -p $(build_dir)
|
||||||
|
|
||||||
|
|
||||||
|
$(build_dir)/cSensor_processing_single: $(sources)
|
||||||
|
$(pre_build_cmd)
|
||||||
|
$(compile_cmd) $(sources) -o $(build_dir)/cSensor_processing_single $(extra_defines) -DPLATFORM_GENERIC -DBLOCK_LEN=1 -DMAX_FIR_COEFFS=128 $(compile_cmd_append)
|
||||||
|
$(build_dir)/cSensor_processing_block: $(sources)
|
||||||
|
$(pre_build_cmd)
|
||||||
|
$(compile_cmd) $(sources) -o $(build_dir)/cSensor_processing_block $(extra_defines) -DPLATFORM_GENERIC -DBLOCK_LEN=2 -DMAX_FIR_COEFFS=128 $(compile_cmd_append)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(build_dir)/cSensor_processing_single $(build_dir)/cSensor_processing_block
|
||||||
124
simulation/test/helper.py
Normal file
124
simulation/test/helper.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from scipy import signal
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
def get_psd(data, fs, bin_width):
|
||||||
|
f, psd = signal.welch(data,
|
||||||
|
fs=fs,
|
||||||
|
nperseg=fs/bin_width,
|
||||||
|
window='hann',
|
||||||
|
axis=0
|
||||||
|
)
|
||||||
|
|
||||||
|
return f[1:], psd[1:] #drop the first value because it makes the plots look bad and is effectively 0
|
||||||
|
|
||||||
|
|
||||||
|
def setup_timeplot(figsize=(11, 6), plot_coeffs=False):
|
||||||
|
global plot1, line1, plot2, line2, plot3, line3, plot4
|
||||||
|
# time domain plot
|
||||||
|
cols = 1
|
||||||
|
rows = 4
|
||||||
|
plt.figure(0, figsize=figsize)
|
||||||
|
plt.clf()
|
||||||
|
|
||||||
|
plot1 = plt.subplot2grid( (rows, cols), (0,0), 1)
|
||||||
|
line1 = plot1.plot([0], label="mic")
|
||||||
|
plt.legend()
|
||||||
|
plot2 = plt.subplot2grid((rows,cols),(1,0), sharex=plot1)
|
||||||
|
line2 = plot2.plot([0], label="acc")
|
||||||
|
plt.legend()
|
||||||
|
plot3 = plt.subplot2grid((rows, cols), (2,0), sharex=plot1)
|
||||||
|
line3 = plot3.plot([0], label="out")
|
||||||
|
plt.legend()
|
||||||
|
|
||||||
|
if plot_coeffs:
|
||||||
|
plot4 = plt.subplot2grid( (rows, cols), (3,0), sharex=plot1, rowspan=3)
|
||||||
|
plt.legend(loc='upper right')
|
||||||
|
|
||||||
|
plt.xlabel("sample")
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def setup_freqplot(figsize=(11, 6)):
|
||||||
|
global plot_freq, line_freq1, line_freq2, line_freq3
|
||||||
|
cols = 1
|
||||||
|
rows = 1
|
||||||
|
# frequency domain plot
|
||||||
|
plt.figure(1, figsize=figsize)
|
||||||
|
plt.clf()
|
||||||
|
plt.title("Power spectrum")
|
||||||
|
plot_freq = plt.subplot2grid( (rows, cols), (0,0), 1)
|
||||||
|
line_freq1 = plot_freq.loglog([0], label="mic")
|
||||||
|
line_freq2 = plot_freq.loglog([0], label="acc")
|
||||||
|
line_freq3 = plot_freq.loglog([0], label="out")
|
||||||
|
plt.xlabel("frequency / Hz")
|
||||||
|
plt.ylabel("dB²/Hz")
|
||||||
|
plt.legend()
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def plot_freqdomain(fs, ch1, ch2, output):
|
||||||
|
|
||||||
|
x_min = []
|
||||||
|
x_max = []
|
||||||
|
y_min = []
|
||||||
|
y_max = []
|
||||||
|
|
||||||
|
f, psd = get_psd(ch1, fs, 10)
|
||||||
|
x_min.append(min(f))
|
||||||
|
x_max.append(max(f))
|
||||||
|
y_min.append(min(psd))
|
||||||
|
y_max.append(max(psd))
|
||||||
|
line_freq1[0].set_data(f, psd)
|
||||||
|
|
||||||
|
f, psd = get_psd(ch2, fs, 10)
|
||||||
|
x_min.append(min(f))
|
||||||
|
x_max.append(max(f))
|
||||||
|
y_min.append(min(psd))
|
||||||
|
y_max.append(max(psd))
|
||||||
|
line_freq2[0].set_data(f, psd)
|
||||||
|
|
||||||
|
f, psd = get_psd(output, fs, 10)
|
||||||
|
x_min.append(min(f))
|
||||||
|
x_max.append(max(f))
|
||||||
|
y_min.append(min(psd))
|
||||||
|
y_max.append(max(psd))
|
||||||
|
line_freq3[0].set_data(f, psd)
|
||||||
|
|
||||||
|
plot_freq.set_xlim(min(x_min), max(x_max))
|
||||||
|
plot_freq.set_ylim(min(y_min), max(y_max))
|
||||||
|
|
||||||
|
|
||||||
|
def plot_timedomain(ch1, ch2, output, coeffs: pd.DataFrame =None):
|
||||||
|
#Plot the result
|
||||||
|
data= output
|
||||||
|
line3[0].set_data(range(len(data)), data)
|
||||||
|
plot3.set_xlim(0, len(data))
|
||||||
|
plot3.set_ylim(np.min(data), np.max(data))
|
||||||
|
|
||||||
|
# plot the chirp with noise
|
||||||
|
data = ch1
|
||||||
|
line1[0].set_data(range(len(data)), data)
|
||||||
|
plot1.set_xlim(0, len(data))
|
||||||
|
plot1.set_ylim(min(data), max(data))
|
||||||
|
|
||||||
|
# Plot the noise
|
||||||
|
data = ch2
|
||||||
|
line2[0].set_data(range(len(data)), data)
|
||||||
|
plot2.set_xlim(0, len(data))
|
||||||
|
plot2.set_ylim(min(data), max(data))
|
||||||
|
|
||||||
|
# Plot the coeffs
|
||||||
|
if coeffs is not None:
|
||||||
|
data = coeffs
|
||||||
|
coeffs.plot(ax=plot4)
|
||||||
|
#plot4.legend(bbox_to_anchor=(1.2, 1.05))
|
||||||
|
|
||||||
|
#line4 = plot4.plot([0], label="coeffs")
|
||||||
|
#line4[0].set_data(range(len(data)), data)
|
||||||
|
|
||||||
|
#plot4.set_xlim(0, len(data))
|
||||||
|
#plot4.set_ylim(min(data), max(data))
|
||||||
78
simulation/test/plot_sim_out.ipynb
Normal file
78
simulation/test/plot_sim_out.ipynb
Normal file
File diff suppressed because one or more lines are too long
114
simulation/test/test.c
Normal file
114
simulation/test/test.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*Test enviornment for testing of the signal path on a generic platform (pc)*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../signalProcessing/include/signal_path.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]){
|
||||||
|
|
||||||
|
/*Some environment related prints*/
|
||||||
|
#ifdef DEBUG_PRINTS
|
||||||
|
printf("The size of int in bytes is: %lu\n", sizeof(int));
|
||||||
|
printf("The size of accum_t in bytes is: %lu\n", sizeof(accum_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SingleSignalPath cSensorSignal;
|
||||||
|
static SingleSignalPath accSensorSignal;
|
||||||
|
//static LmsFilter lms;
|
||||||
|
//int lms_fir_coeffs[MAX_FIR_COEFFS];
|
||||||
|
|
||||||
|
static int16_t cSensor[BLOCK_LEN], accSensor[BLOCK_LEN];
|
||||||
|
static int16_t output_port[BLOCK_LEN];
|
||||||
|
|
||||||
|
// Deactivate preemphasis filter by initializing with coefficients {1., 0., 0., 0., 0.}
|
||||||
|
// can not be modeled on a generic platform (pc)
|
||||||
|
// biquad filter coefficients - off
|
||||||
|
double b0[5]={1., 0., 0., 0., 0.};
|
||||||
|
double b1[5]={1., 0., 0., 0., 0.};
|
||||||
|
int N_lms_fir_coeffs = MAX_FIR_COEFFS;
|
||||||
|
// get parameters from command line
|
||||||
|
OutputMode mode = (OutputMode) (*argv[1] - '0'); // Convert char to int (only works for single digits)
|
||||||
|
int pipe_input = (*argv[2] - '0');
|
||||||
|
int return_coeffs = (*argv[3] - '0');
|
||||||
|
|
||||||
|
init(
|
||||||
|
&cSensorSignal, &accSensorSignal,
|
||||||
|
//&lms, lms_fir_coeffs,
|
||||||
|
b0,
|
||||||
|
b1,
|
||||||
|
0, // sample delay
|
||||||
|
0,
|
||||||
|
1., // weight
|
||||||
|
1.,
|
||||||
|
0.005, // lms learning rate
|
||||||
|
N_lms_fir_coeffs // Numer of lms fir coefficients
|
||||||
|
);
|
||||||
|
|
||||||
|
if (mode == OUTPUT_MODE_FIR){ //FIR filter mit fixen coeffizienten
|
||||||
|
for (int i=0; i<N_lms_fir_coeffs; i++){
|
||||||
|
ptr_fir_lms_coeffs.ptr_start[i] = (int) ((pow(2,31)-1) / N_lms_fir_coeffs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Sample wise signalprocessing, called by an interrupt, use a for loop to simulate it*/
|
||||||
|
FILE *fp1 = fopen("testdata/input/chirp_disturber.txt", "r");
|
||||||
|
FILE *fp2 = fopen("testdata/input/disturber.txt", "r");
|
||||||
|
FILE *fp3 = fopen("testdata/output/out_sim_generic.txt", "w");
|
||||||
|
|
||||||
|
int loop_cnt=0;
|
||||||
|
int keep_loopin=1;
|
||||||
|
while (keep_loopin){
|
||||||
|
// Load a new block from the input
|
||||||
|
for (uint32_t i = 0; i < BLOCK_LEN; i++){ // process block wise
|
||||||
|
if (pipe_input){ // input from pipe
|
||||||
|
if ((scanf("%hd", &cSensor[i]) !=1) || (scanf("%hd", &accSensor[i])!=1)) {
|
||||||
|
keep_loopin=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{// input from file
|
||||||
|
if (feof(fp1)==1 || feof(fp2)==1){
|
||||||
|
keep_loopin=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fscanf(fp1, "%hd", &cSensor[i]);
|
||||||
|
fscanf(fp2, "%hd", &accSensor[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop_cnt++;
|
||||||
|
calc(
|
||||||
|
&cSensorSignal, &accSensorSignal,
|
||||||
|
//&lms, lms_fir_coeffs,
|
||||||
|
mode, cSensor, accSensor, output_port);
|
||||||
|
|
||||||
|
|
||||||
|
if (pipe_input){ // output to pipe
|
||||||
|
for (uint32_t i = 0; i < BLOCK_LEN; i++){ // return calculation results
|
||||||
|
printf("%d,", output_port[i]); // output to stdout
|
||||||
|
if (return_coeffs == 1){ // print the current coefficients
|
||||||
|
for (int i=0; i< N_lms_fir_coeffs; i++){
|
||||||
|
printf("%d,", ptr_fir_lms_coeffs.ptr_start[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for (uint32_t i = 0; i < BLOCK_LEN; i++){ // return calculation results
|
||||||
|
printf("%d\n, ", output_port[i]); // output to stdout
|
||||||
|
if (return_coeffs == 1){ // print the current coefficients
|
||||||
|
for (int i=0; i< N_lms_fir_coeffs; i++){
|
||||||
|
printf("%d,", ptr_fir_lms_coeffs.ptr_start[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
fprintf(fp3, "%d\n", output_port[i]); // output to file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pipe_input){
|
||||||
|
fclose(fp1);
|
||||||
|
fclose(fp2);
|
||||||
|
fclose(fp3);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
593
simulation/test/test.ipynb
Normal file
593
simulation/test/test.ipynb
Normal file
File diff suppressed because one or more lines are too long
68
simulation/test/test_hw.py
Normal file
68
simulation/test/test_hw.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import dwfpy as dwf
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
F_SYSCLK_ANALOG_DISCOVERY=100e6
|
||||||
|
BITS_PER_FRAME=32
|
||||||
|
F_BITCLK=640e3
|
||||||
|
F_FRAMECLK=20e3
|
||||||
|
|
||||||
|
print(f'DWF Version: {dwf.Application.get_version()}')
|
||||||
|
|
||||||
|
def gen_pcm(device, data, f_bitclk=F_BITCLK, words_per_frame=1, bits_per_word=16):
|
||||||
|
|
||||||
|
|
||||||
|
# Convert data to a list of bits
|
||||||
|
bits_list = []
|
||||||
|
for word in data:
|
||||||
|
# Check if word violates the 16-bit signed integer range
|
||||||
|
assert -32768 <= word <= 32767, 'Word value is out of range.'
|
||||||
|
|
||||||
|
# Convert word to binary representation
|
||||||
|
binary = bin(word & 0xFFFF)[2:].zfill(bits_per_word)
|
||||||
|
|
||||||
|
# Add binary representation to bits_list
|
||||||
|
bits_list.extend([int(bit) for bit in binary])
|
||||||
|
|
||||||
|
|
||||||
|
print(f'Found device: {device.name} ({device.serial_number})')
|
||||||
|
|
||||||
|
do_channels = device.digital_output
|
||||||
|
|
||||||
|
f_sysclk=do_channels[0]._module.clock_frequency
|
||||||
|
|
||||||
|
# Setup bitclock
|
||||||
|
counter_bitclk=round(f_sysclk/f_bitclk)
|
||||||
|
print(f"Set f bitclk to :{round(f_sysclk/counter_bitclk, 2)}Hz")
|
||||||
|
assert counter_bitclk % 2 == 0, 'Counter must be even.'
|
||||||
|
high_counter_bitclk=int(counter_bitclk/2)
|
||||||
|
low_counter_bitclk=int(counter_bitclk/2)
|
||||||
|
do_channels[0].setup(output_type=dwf.DigitalOutputType.PULSE, initial_counter=1, high_counter=high_counter_bitclk, low_counter=low_counter_bitclk)
|
||||||
|
|
||||||
|
# Setup frameclock
|
||||||
|
counter_frameclk= counter_bitclk*bits_per_word*words_per_frame
|
||||||
|
assert counter_frameclk % counter_bitclk == 0, 'Counter frameclk must be multiple of bit clock.'
|
||||||
|
do_channels[1].setup(output_type=dwf.DigitalOutputType.PULSE, high_counter=counter_bitclk, low_counter=counter_frameclk-counter_bitclk)
|
||||||
|
|
||||||
|
#setup data
|
||||||
|
do_channels[2].setup(output_type=dwf.DigitalOutputType.CUSTOM, divider=counter_bitclk, high_counter=1, low_counter=1)
|
||||||
|
do_channels[2].set_custom_bits(bits_list)
|
||||||
|
|
||||||
|
return do_channels
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# Generate sine wave
|
||||||
|
f_sine = 1e3
|
||||||
|
t = np.arange(0, 1/f_sine, 1/F_FRAMECLK)
|
||||||
|
sine_wave = np.sin(2 * np.pi * f_sine * t)*0.5
|
||||||
|
|
||||||
|
# Convert sine wave to PCM data
|
||||||
|
pcm_data = (sine_wave * 32767).astype(int)
|
||||||
|
|
||||||
|
# Generate PCM channels
|
||||||
|
with dwf.Device() as device:
|
||||||
|
channels = gen_pcm(device, pcm_data, f_bitclk=F_BITCLK, words_per_frame=1, bits_per_word=16)
|
||||||
|
channels.configure(start=True)
|
||||||
|
input('Press Enter key to continue.')
|
||||||
|
channels.reset()
|
||||||
BIN
simulation/test/testdata/input/1kHz_peak_1g_external_Speaker_0dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/1kHz_peak_1g_external_Speaker_0dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/breathing_peak_016g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/breathing_peak_016g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/breathing_peak_01g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/breathing_peak_01g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/chirp_disturber.wav
vendored
Normal file
BIN
simulation/test/testdata/input/chirp_disturber.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/chirp_noise.wav
vendored
Normal file
BIN
simulation/test/testdata/input/chirp_noise.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/chirp_sine.wav
vendored
Normal file
BIN
simulation/test/testdata/input/chirp_sine.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/eatCrunchy_peak_05g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/eatCrunchy_peak_05g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/eatCrunchy_peak_1g_clipping_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/eatCrunchy_peak_1g_clipping_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/eatCrunchy_peak_2g_clipping_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/eatCrunchy_peak_2g_clipping_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/ownVoice_shaker0.2g_speaker80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/ownVoice_shaker0.2g_speaker80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/peak_0g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
BIN
simulation/test/testdata/input/peak_0g_external_Speaker_80dBSPL_PDM.wav
vendored
Normal file
Binary file not shown.
BIN
simulation/test/testdata/input/sine_noise.wav
vendored
Normal file
BIN
simulation/test/testdata/input/sine_noise.wav
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user