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
11 changes: 9 additions & 2 deletions lib_mic_array/src/mic_array_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ bool use_3_stg_decimator = false;
// until mic_array_start() completes. mic_array_start() performs shutdown and
// then sets g_mics back to nullptr.

#ifdef __XS3A__
#if !defined(XS2A)
////////////////////
// Mic array init //
////////////////////
Expand Down Expand Up @@ -171,4 +171,11 @@ void _mic_array_override_pdm_port(chanend_t c_pdm)
g_mics->PdmRx.SetPort((port_t)c_pdm);
}
}
#endif

// C wrapper
extern "C" void _mic_array_override_pdm_port_c(chanend_t c_pdm)
{
_mic_array_override_pdm_port(c_pdm);
}

#endif // !defined(XS2A)
3 changes: 1 addition & 2 deletions tests/signal/BasicMicArray/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(test_ma)

set(XMOS_SANDBOX_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../..)

include(${CMAKE_CURRENT_LIST_DIR}/../../../examples/deps.cmake)
set(APP_DEPENDENT_MODULES "lib_mic_array")

set(APP_HW_TARGET XK-EVK-XU316)

Expand Down Expand Up @@ -113,4 +113,3 @@ foreach(target ${APP_BUILD_TARGETS})
add_dependencies(${target} gen_custom_filter)
endif()
endforeach()

Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
// Copyright 2022-2026 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <print.h>
#include <string.h>
#include <platform.h>

#include <xcore/select.h>
#include <xcore/parallel.h>
#include <xcore/chanend.h>
#include <xcore/channel.h>
#include <xcore/hwtimer.h>
#include <xcore/channel_streaming.h>

extern "C" {
#include "xscope.h"
}
#include <xscope.h>

#include "mic_array.h"

#include "app.h"
#if USE_CUSTOM_FILTER
#include "custom_filter.h"
#endif

#define BUFF_SIZE (256)

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));


typedef struct {
unsigned stg1_tap_count;
unsigned stg1_decimation_factor;
Expand All @@ -39,14 +45,24 @@ typedef struct {
int32_t *stg3_coef_ptr;
}filt_config_t;

static void get_filter_config(unsigned fs, filt_config_t *cfg) {
// ------------------------------- HELPER FUNCTIONS -------------------------------

static inline
void hwtimer_delay_microseconds(unsigned delay) {
hwtimer_t tmr = hwtimer_alloc();
hwtimer_delay(tmr, delay * XS1_TIMER_MHZ);
hwtimer_free(tmr);
}

static
void get_filter_config(unsigned fs, filt_config_t *cfg) {
#if !USE_CUSTOM_FILTER
cfg->stg1_tap_count = 256;
cfg->stg1_decimation_factor = 32;

cfg->stg3_tap_count = 0;
cfg->stg3_decimation_factor = 1; // set as 1 to not mess up blocksize calculation at the host end for 2 stage decimator
cfg->stg3_coef_ptr = nullptr;
cfg->stg3_coef_ptr = NULL;
cfg->stg3_shr = 0;
if(fs == 16000) {
cfg->stg2_tap_count = STAGE2_TAP_COUNT;
Expand Down Expand Up @@ -91,7 +107,102 @@ static void get_filter_config(unsigned fs, filt_config_t *cfg) {
#endif
}

extern void _mic_array_override_pdm_port(chanend_t c_pdm);
static inline
void app_print_filters()
{
filt_config_t filt_cfg;
get_filter_config(APP_SAMP_FREQ, &filt_cfg);

unsigned stg1_tap_words = filt_cfg.stg1_tap_count / 2;


printf("stage1 filter length: %d 16bit coefs -> %d 32b words\n", stg1_tap_words*2, stg1_tap_words);
int initial_list = stg1_tap_words/4;
printf("stage1_coef = [\n");
for(int a = 0; a < initial_list; a++){
printf("0x%08X, 0x%08X, 0x%08X, 0x%08X, \n",
filt_cfg.stg1_coef_ptr[a*4+0], filt_cfg.stg1_coef_ptr[a*4+1],
filt_cfg.stg1_coef_ptr[a*4+2], filt_cfg.stg1_coef_ptr[a*4+3]);
}
for(int a = initial_list*4; a < stg1_tap_words; a++){
printf("0x%08X, ", filt_cfg.stg1_coef_ptr[a]);
}
printf("]\n");

printf("stage2 filter length: %d\n", filt_cfg.stg2_tap_count);
printf("stage2_coef = [\n");
initial_list = filt_cfg.stg2_tap_count/4;
for(int a = 0; a < initial_list; a++){
printf("0x%08X, 0x%08X, 0x%08X, 0x%08X, \n",
filt_cfg.stg2_coef_ptr[4*a+0], filt_cfg.stg2_coef_ptr[4*a+1],
filt_cfg.stg2_coef_ptr[4*a+2], filt_cfg.stg2_coef_ptr[4*a+3]);
}
for(int a = initial_list*4; a < filt_cfg.stg2_tap_count; a++){
printf("0x%08X, ", filt_cfg.stg2_coef_ptr[a]);
}
printf("]\n");

printf("stage2_shr = %d\n", filt_cfg.stg2_shr);
}

static inline
void cmd_print_msg(unsigned i){
const char* msg[4] = {
"[CMD] Resume data loop.\n",
"[CMD] Terminate application.\n",
"[CMD] Print Filters.\n",
"[CMD] Unknown command.\n"
};
printf("%s\n", msg[i]);
}

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

static inline
void cmd_loop(chanend_t c_from_host)
{
char cmd_buff[BUFF_SIZE];
int pp;
SELECT_RES(
CASE_THEN(c_from_host, c_from_host_handler)
)
c_from_host_handler:{
xscope_data_from_host(c_from_host, &cmd_buff[0], &pp);
assert((pp-1) == 4);
uint32_t cmd = ((uint32_t*)(void*) &cmd_buff[0])[0];
cmd_print_msg(cmd);
cmd_perform_action(cmd);
continue;
}
}

static inline
int send_words_to_app(streaming_chanend_t c_to_app, char* buff, int buff_lvl)
{
int* next_word = (int*)(void*) &buff[0];
while(buff_lvl >= sizeof(int)){
s_chan_out_word(c_to_app, next_word[0]);
next_word++;
buff_lvl -= sizeof(int);
hwtimer_delay_microseconds(15);
}
if(buff_lvl)
{
memmove(&buff[0], &next_word[0], buff_lvl);
}
return buff_lvl;
}


extern void _mic_array_override_pdm_port_c(chanend_t c_pdm);

// We'll be using a fairly standard mic array setup here, with one big
// exception. Instead of feeding the PDM rx service with a port, we're going
Expand All @@ -110,15 +221,15 @@ pdm_rx_resources_t pdm_res = PDM_RX_RESOURCES_SDR(
XS1_CLKBLK_1);

#if USE_CUSTOM_FILTER
void init_mic_conf(mic_array_conf_t &mic_array_conf, mic_array_filter_conf_t (&filter_conf)[NUM_DECIMATION_STAGES], unsigned *channel_map)
static void init_mic_conf(mic_array_conf_t *mic_array_conf, mic_array_filter_conf_t filter_conf[NUM_DECIMATION_STAGES], unsigned *channel_map)
{
static int32_t stg1_filter_state[MIC_ARRAY_CONFIG_MIC_COUNT][8];
static int32_t stg2_filter_state[MIC_ARRAY_CONFIG_MIC_COUNT][CUSTOM_FILTER_STG2_TAP_COUNT];
memset(&mic_array_conf, 0, sizeof(mic_array_conf_t));
memset(mic_array_conf, 0, sizeof(mic_array_conf_t));

//decimator
mic_array_conf.decimator_conf.filter_conf = &filter_conf[0];
mic_array_conf.decimator_conf.num_filter_stages = NUM_DECIMATION_STAGES;
mic_array_conf->decimator_conf.filter_conf = &filter_conf[0];
mic_array_conf->decimator_conf.num_filter_stages = NUM_DECIMATION_STAGES;
// stage 1
filter_conf[0].coef = (int32_t*)custom_filter_stg1_coef;
filter_conf[0].num_taps = CUSTOM_FILTER_STG1_TAP_COUNT;
Expand Down Expand Up @@ -148,13 +259,16 @@ void init_mic_conf(mic_array_conf_t &mic_array_conf, mic_array_filter_conf_t (&f
// pdm rx
static uint32_t pdmrx_out_block[MIC_ARRAY_CONFIG_MIC_COUNT][CUSTOM_FILTER_STG2_DECIMATION_FACTOR * CUSTOM_FILTER_STG3_DECIMATION_FACTOR];
static uint32_t __attribute__((aligned(8))) pdmrx_out_block_double_buf[2][MIC_ARRAY_CONFIG_MIC_COUNT * CUSTOM_FILTER_STG2_DECIMATION_FACTOR * CUSTOM_FILTER_STG3_DECIMATION_FACTOR];
mic_array_conf.pdmrx_conf.pdm_out_words_per_channel = CUSTOM_FILTER_STG2_DECIMATION_FACTOR * CUSTOM_FILTER_STG3_DECIMATION_FACTOR;
mic_array_conf.pdmrx_conf.pdm_out_block = (uint32_t*)pdmrx_out_block;
mic_array_conf.pdmrx_conf.pdm_in_double_buf = (uint32_t*)pdmrx_out_block_double_buf;
mic_array_conf.pdmrx_conf.channel_map = channel_map;
mic_array_conf->pdmrx_conf.pdm_out_words_per_channel = CUSTOM_FILTER_STG2_DECIMATION_FACTOR * CUSTOM_FILTER_STG3_DECIMATION_FACTOR;
mic_array_conf->pdmrx_conf.pdm_out_block = (uint32_t*)pdmrx_out_block;
mic_array_conf->pdmrx_conf.pdm_in_double_buf = (uint32_t*)pdmrx_out_block_double_buf;
mic_array_conf->pdmrx_conf.channel_map = channel_map;
}
#endif


// ------------------------------- THREADS -------------------------------

void app_mic(
chanend_t c_pdm_in,
chanend_t c_frames_out) //non-streaming
Expand All @@ -164,10 +278,10 @@ void app_mic(
#else
mic_array_conf_t mic_array_conf;
mic_array_filter_conf_t filter_conf[NUM_DECIMATION_STAGES];
init_mic_conf(mic_array_conf, filter_conf, NULL);
init_mic_conf(&mic_array_conf, filter_conf, NULL);
mic_array_init_custom_filter(&pdm_res, &mic_array_conf);
#endif
_mic_array_override_pdm_port((port_t)c_pdm_in); // get pdm input from channel instead of port.
_mic_array_override_pdm_port_c((port_t)c_pdm_in); // get pdm input from channel instead of port.
// mic_array_init() calls mic_array_resources_configure which would crash
// if a chanend were to be passed instead of a port for the pdm data port, so
// this overriding has to be done only after calling mic_array_init()
Expand Down Expand Up @@ -219,6 +333,7 @@ void app_output_task(chanend_t c_frames_in, chanend_t c_fifo)
}
}


void app_fifo_to_xscope_task(chanend_t c_fifo)
{
while(1){
Expand All @@ -235,40 +350,46 @@ void app_fifo_to_xscope_task(chanend_t c_fifo)
}



void app_print_filters()
void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app)
{
filt_config_t filt_cfg;
get_filter_config(APP_SAMP_FREQ, &filt_cfg);

unsigned stg1_tap_words = filt_cfg.stg1_tap_count / 2;


printf("stage1 filter length: %d 16bit coefs -> %d 32b words\n", stg1_tap_words*2, stg1_tap_words);
int initial_list = stg1_tap_words/4;
printf("stage1_coef = [\n");
for(int a = 0; a < initial_list; a++){
printf("0x%08X, 0x%08X, 0x%08X, 0x%08X, \n",
filt_cfg.stg1_coef_ptr[a*4+0], filt_cfg.stg1_coef_ptr[a*4+1],
filt_cfg.stg1_coef_ptr[a*4+2], filt_cfg.stg1_coef_ptr[a*4+3]);
}
for(int a = initial_list*4; a < stg1_tap_words; a++){
printf("0x%08X, ", filt_cfg.stg1_coef_ptr[a]);
}
printf("]\n");
xscope_connect_data_from_host(c_from_host);

char buff[100*BUFF_SIZE+3];
int buff_lvl = 0;
int dd = 0;

SELECT_RES(
CASE_THEN(c_from_host, c_from_host_handler)
){
c_from_host_handler:{
xscope_data_from_host(c_from_host, &buff[0], &dd);
dd--;
buff_lvl += dd;
if(dd == 0) {
cmd_loop(c_from_host);
}
else {
buff_lvl = send_words_to_app(c_to_app, buff, buff_lvl);
}
continue;
}}
}

printf("stage2 filter length: %d\n", filt_cfg.stg2_tap_count);
printf("stage2_coef = [\n");
initial_list = filt_cfg.stg2_tap_count/4;
for(int a = 0; a < initial_list; a++){
printf("0x%08X, 0x%08X, 0x%08X, 0x%08X, \n",
filt_cfg.stg2_coef_ptr[4*a+0], filt_cfg.stg2_coef_ptr[4*a+1],
filt_cfg.stg2_coef_ptr[4*a+2], filt_cfg.stg2_coef_ptr[4*a+3]);
}
for(int a = initial_list*4; a < filt_cfg.stg2_tap_count; a++){
printf("0x%08X, ", filt_cfg.stg2_coef_ptr[a]);
}
printf("]\n");

printf("stage2_shr = %d\n", filt_cfg.stg2_shr);
int main(){
channel_t c_frames = chan_alloc();
channel_t c_fifo = chan_alloc();
chanend_t xscope_chan = chanend_alloc(); // tools will start the other channel end
streaming_channel_t c_to_app = s_chan_alloc();

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))
);
s_chan_free(c_to_app);
chan_free(c_frames);
chan_free(c_fifo);
return 0;
}
26 changes: 0 additions & 26 deletions tests/signal/BasicMicArray/src/app.h

This file was deleted.

Loading