Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/deps.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if(NOT EXISTS ${XMOS_SANDBOX_DIR}/fwk_io)
FetchContent_Declare(
fwk_io
GIT_REPOSITORY git@github.com:xmos/fwk_io
GIT_TAG feature/xcommon_cmake
GIT_TAG b88f0d700a8f8eda8e686c4a088ff7d648ef69f6
SOURCE_DIR ${XMOS_SANDBOX_DIR}/fwk_io
)
FetchContent_Populate(fwk_io)
Expand Down
7 changes: 5 additions & 2 deletions lib_mic_array/api/mic_array/cpp/PdmRx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,10 @@ void mic_array::StandardPdmRxService<CHANNELS_IN, CHANNELS_OUT>
}
// Now that we're sure that PdmRx thread has exited, drain any pending blocks
chanend_t c_pdm_blocks_end_b = this->c_pdm_blocks.end_b;
SELECT_RES(CASE_THEN(c_pdm_blocks_end_b, rx_pending_block),
DEFAULT_THEN(empty))
SELECT_RES(
CASE_THEN(c_pdm_blocks_end_b, rx_pending_block),
DEFAULT_THEN(empty)
)
{
rx_pending_block:
pdm_samples = GetPdmBlock();
Expand All @@ -623,6 +625,7 @@ void mic_array::StandardPdmRxService<CHANNELS_IN, CHANNELS_OUT>
empty:
break;
}
(void)pdm_samples; // Avoid unused variable warning.
}
// Now that shutdown is complete, free the pdmrx channel
s_chan_free(this->c_pdm_blocks);
Expand Down
10 changes: 4 additions & 6 deletions lib_mic_array/api/mic_array/etc/fir_1x16_bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@ C_API_START

/** Function that computes an FIR over a 1-bit signal with 16-bit coefficients.
* The one-bit signal is stored as a sequence of bits, each of them representing
* -1 or +1. The coefficients are notionally a vector of 16-bti values, but with
* -1 or +1. The coefficients are notionally a vector of 16-bit values, but with
* a few provisos:
*
* * The number of coefficients must be a multiple of 256, and N_256 (the third
* parameter) represents how many multiples there are. N must be at least 1
*
* * The coefficients shall be in the range [-32767 .. 32767]
*
* * Coefficients are stored in slices of bits. A slice of the coefficient vector
* comprises 256 coefficients, so there are N_256 slices.
* comprises 256 coefficients.
* Each slice occupies 256 * 16 / 32 = 128 words: 16 bits for each of the 256
* elements, and there are 23 bits per word. The coefficients are decomposed
* elements, and there are 32 bits per word. The coefficients are decomposed
* over the words, and each group of eight words (256 bits) store subsequent
* bits of the coefficients values as follows. The bits in
* - words 0..7 have magnitude +/-1
Expand All @@ -48,4 +46,4 @@ C_API_START
MA_C_API
int fir_1x16_bit(uint32_t signal[], const uint32_t coeff_1[]);

C_API_END
C_API_END
87 changes: 59 additions & 28 deletions tests/signal/BasicMicArray/src/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@
#define DATA_OUT (1)
#endif

#define FIFO_ENTRIES (8)

typedef chanend_t streaming_chanend_t;

DECLARE_JOB(app_output_task, (chanend_t, chanend_t));
DECLARE_JOB(app_fifo_to_xscope_task, (chanend_t));
DECLARE_JOB(app_mic, (chanend_t, chanend_t));
DECLARE_JOB(host_words_to_app, (chanend_t, streaming_chanend_t));
DECLARE_JOB(app_output_task, (chanend_t, chanend_t, chanend_t));
DECLARE_JOB(app_fifo_to_xscope_task, (chanend_t, chanend_t));
DECLARE_JOB(host_words_to_app, (chanend_t, streaming_chanend_t, chanend_t, chanend_t));


typedef struct {
Expand Down Expand Up @@ -203,17 +205,18 @@ void cmd_print_msg(unsigned i){
}

static inline
void cmd_perform_action(unsigned cmd){
unsigned cmd_perform_action(unsigned cmd){
switch(cmd){
case 0: break;
case 1: exit(0); break;
case 1: return 1;
case 2: app_print_filters(); break;
default: assert(0); break;
}
return 0;
}

static inline
void cmd_loop(chanend_t c_from_host)
void cmd_loop(chanend_t c_from_host, chanend_t c_end_htf, chanend_t c_end_hta)
{
char cmd_buff[BUFF_SIZE];
int pp;
Expand All @@ -225,7 +228,12 @@ void cmd_loop(chanend_t c_from_host)
assert((pp-1) == 4);
uint32_t cmd = ((uint32_t*)(void*) &cmd_buff[0])[0];
cmd_print_msg(cmd);
cmd_perform_action(cmd);
unsigned ret = cmd_perform_action(cmd);
if(ret){
chanend_out_byte(c_end_htf, 1); // signal host fifo task to end
chanend_out_byte(c_end_hta, 1); // signal host to app task to end
return;
}
break;
}
}
Expand Down Expand Up @@ -378,12 +386,11 @@ void app_mic(

// Sometimes xscope doesn't keep up causing backpressure so add a FIFO to decouple this, at least up to 8 frames.
// We can buffer up to 8 chars in a same tile chanend.
const unsigned fifo_entries = 8;
typedef int32_t ma_frame_t[APP_MIC_COUNT][MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME];
ma_frame_t frame_fifo[fifo_entries];
ma_frame_t frame_fifo[FIFO_ENTRIES];


void app_output_task(chanend_t c_frames_in, chanend_t c_fifo)
void app_output_task(chanend_t c_frames_in, chanend_t c_fifo, chanend_t c_end_hta)
{
// Before listening for any frames, use the META_OUT xscope probe to report
// our configuration to the host. This will help make sure the right version
Expand All @@ -405,25 +412,40 @@ void app_output_task(chanend_t c_frames_in, chanend_t c_fifo)
// receive the output of the mic array and send it to the host via a fifo to decouple the backpressure from xscope
int32_t frame[APP_MIC_COUNT][MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME];
uint8_t fifo_idx = 0;
while(1){
ma_frame_rx(&frame[0][0], c_frames_in, APP_MIC_COUNT, MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME);
memcpy(frame_fifo[fifo_idx], &frame[0][0], sizeof(ma_frame_t));
int t0 = get_reference_time();
chanend_out_byte(c_fifo, fifo_idx++);
int t1 = get_reference_time();
if(t1 - t0 > 10){
printstrln("ERROR - Timing fail");
SELECT_RES(
CASE_THEN(c_end_hta, c_end_hta_handler),
DEFAULT_THEN(default_handler))
{
default_handler: {
ma_frame_rx(&frame[0][0], c_frames_in, APP_MIC_COUNT, MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME);
memcpy(frame_fifo[fifo_idx], &frame[0][0], sizeof(ma_frame_t));
int t0 = get_reference_time();
chanend_out_byte(c_fifo, fifo_idx++);
int t1 = get_reference_time();
if(t1 - t0 > 10){
printstrln("ERROR - Timing fail");
}
if(fifo_idx == FIFO_ENTRIES){
fifo_idx = 0;
}
continue;
}
if(fifo_idx == fifo_entries){
fifo_idx = 0;
c_end_hta_handler:{
(void)chanend_in_byte(c_end_hta);
ma_shutdown(c_frames_in);
return; // end signal received from host, end the task
}
}
}


void app_fifo_to_xscope_task(chanend_t c_fifo)
void app_fifo_to_xscope_task(chanend_t c_fifo, chanend_t c_end_htf)
{
while(1){
SELECT_RES(
CASE_THEN(c_fifo, c_fifo_handler),
CASE_THEN(c_end_htf, c_end_htf_handler))
{
c_fifo_handler:{
uint8_t idx = chanend_in_byte(c_fifo);
ma_frame_t *ptr = &frame_fifo[idx];

Expand All @@ -433,11 +455,16 @@ void app_fifo_to_xscope_task(chanend_t c_fifo)
xscope_int(DATA_OUT, (*ptr)[ch][smp]);
}
}
continue;
}
c_end_htf_handler:{
(void)chanend_in_byte(c_end_htf);
return; // end signal received from host, end the task
}
}
}


void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app)
void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app, chanend_t c_end_htf, chanend_t c_end_hta)
{
xscope_connect_data_from_host(c_from_host);

Expand All @@ -453,7 +480,7 @@ void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app)
dd--;
buff_lvl += dd;
if(dd == 0) {
cmd_loop(c_from_host);
cmd_loop(c_from_host, c_end_htf, c_end_hta);
}
else {
buff_lvl = send_words_to_app(c_to_app, buff, buff_lvl);
Expand All @@ -474,11 +501,15 @@ int main(){
chanend_t xscope_chan = chanend_alloc();
xscope_mode_lossless();

// end of program channels
channel_t c_end_hta = chan_alloc(); // host to app (hta)
channel_t c_end_htf = chan_alloc(); // host to fifo (htf)

PAR_JOBS(
PJOB(app_mic, (c_to_app.end_a, c_frames.end_a)),
PJOB(app_output_task, (c_frames.end_b, c_fifo.end_a)),
PJOB(app_fifo_to_xscope_task, (c_fifo.end_b)),
PJOB(host_words_to_app, (xscope_chan, c_to_app.end_b))
PJOB(app_output_task, (c_frames.end_b, c_fifo.end_a, c_end_hta.end_b)),
PJOB(app_fifo_to_xscope_task, (c_fifo.end_b, c_end_htf.end_b)),
PJOB(host_words_to_app, (xscope_chan, c_to_app.end_b, c_end_htf.end_a, c_end_hta.end_a))
);
s_chan_free(c_to_app);
chan_free(c_frames);
Expand Down
24 changes: 18 additions & 6 deletions tests/signal/BasicMicArray/test_mic_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
from pathlib import Path
from mic_array_shared import MicArraySharedBase

MAX_DIFF_TH = 12

with open(Path(__file__).parent / "test_params.json") as f:
params = json.load(f)

Expand Down Expand Up @@ -151,8 +153,13 @@ def test_BasicMicArray(self, request, chans, frame_size, use_isr, one_mic_overri
# applied to them prior to being summed.
result_diff = np.max(np.abs(expected - device_output))
print(f"result_diff = {result_diff}")
threshold = 12
assert result_diff <= threshold, f"max diff between python and xcore mic array output ({result_diff}) exceeds threshold ({threshold})"

exp_size = expected.size
dev_size = device_output.size
print(f"expected size: {exp_size}, device output size: {dev_size}")

assert result_diff <= MAX_DIFF_TH, f"max diff between python and xcore mic array output ({result_diff}) exceeds MAX_DIFF_TH ({MAX_DIFF_TH})"
assert exp_size == dev_size, f"Expected and device output sizes differ"


@pytest.mark.parametrize("chans", [1, 2], ids=["1mic_override", "2mic"])
Expand Down Expand Up @@ -227,12 +234,17 @@ def test_BasicMicArrayOneStageFilter(self, request, chans):
end = -device_output_delay_samps or None
start = device_output_delay_samps

exp_size = expected[:, :end].size
dev_size = device_output[:, start:].size
result_diff = np.max(np.abs(expected[:, :end] - device_output[:, start:]))

print(f"result_diff = {result_diff}")
print(f"expected size: {exp_size}, device output size: {dev_size}")

threshold = 12
assert result_diff <= threshold, (
assert exp_size == dev_size, (
f"Expected and device output sizes differ"
)
assert result_diff <= MAX_DIFF_TH, (
f"max diff between python and xcore mic array output ({result_diff}) "
f"exceeds threshold ({threshold})"
)
f"exceeds MAX_DIFF_TH ({MAX_DIFF_TH})"
)
7 changes: 5 additions & 2 deletions tests/signal/profile/test_measure_mips.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

cwd = Path(__file__).parent

MIC_LIST = [1, 2]
FS_LIST = [16000, 32000, 48000]

def get_xcc_version() -> str:
output = subprocess.check_output(["xcc", "--version"], text=True)
for line in output.splitlines():
Expand Down Expand Up @@ -102,9 +105,9 @@ def test_measure_mips(pytestconfig):
mic_array_mips_table.rst - autogenerated RST table of results
"""
update = pytestconfig.getoption("--update")
mics = [1, 2]
pdmrx = get_isr_list()
fs = [16000, 32000, 48000]
mics = MIC_LIST
fs = FS_LIST
results = {}
print("\n\n")
for chans, pdmrx_type, samp_freq in itertools.product(mics, pdmrx, fs):
Expand Down