Update FIFO to use true shorts + add/use fast block fifo API

This commit is contained in:
Ed Clarke
2018-11-09 17:32:32 +00:00
parent 7af92668f5
commit e93901f0cc
6 changed files with 182 additions and 55 deletions

View File

@@ -137,13 +137,15 @@ int main()
// c_ep_in[XUA_ENDPOINT_COUNT_IN - 1], // c_ep_in[XUA_ENDPOINT_COUNT_IN - 1],
// c_sof, p_for_mclk_count, c_audio); // c_sof, p_for_mclk_count, c_audio);
//[[combine]]
par{
XUA_Buffer_lite2(i_ep0_ctl, XUA_Buffer_lite2(i_ep0_ctl,
c_ep_out[1], c_ep_out[1],
null, //c_ep_in[XUA_ENDPOINT_COUNT_IN - 2],/*feedback*/ null, //c_ep_in[XUA_ENDPOINT_COUNT_IN - 2],/*feedback*/
c_ep_in[XUA_ENDPOINT_COUNT_IN - 1], c_ep_in[XUA_ENDPOINT_COUNT_IN - 1],
c_sof, p_for_mclk_count, c_audio); c_sof, p_for_mclk_count, c_audio);
XUA_Endpoint0_select(c_ep_out[0], c_ep_in[0], i_ep0_ctl, null VENDOR_REQUESTS_PARAMS_DEC_); XUA_Endpoint0_select(c_ep_out[0], c_ep_in[0], i_ep0_ctl, null VENDOR_REQUESTS_PARAMS_DEC_);
}
par (int i = 0; i < 3; i++) burn_normal_priority(); par (int i = 0; i < 3; i++) burn_normal_priority();
par (int i = 0; i < 2; i++) burn_high_priority(); par (int i = 0; i < 2; i++) burn_high_priority();
} }

View File

@@ -57,6 +57,8 @@ void AudioHub(server i2s_frame_callback_if i2s,
case i2s.restart_check() -> i2s_restart_t restart: case i2s.restart_check() -> i2s_restart_t restart:
restart = I2S_NO_RESTART; // Keep on looping restart = I2S_NO_RESTART; // Keep on looping
timer tmr; int t0, t1; tmr :> t0; timer tmr; int t0, t1; tmr :> t0;
//Transfer samples
for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio :> samples_out[i]; for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio :> samples_out[i];
if (XUA_ADAPTIVE) c_audio :> clock_nudge; if (XUA_ADAPTIVE) c_audio :> clock_nudge;
for (int i = 0; i < NUM_USB_CHAN_IN; i++) c_audio <: raw_mics[i]; for (int i = 0; i < NUM_USB_CHAN_IN; i++) c_audio <: raw_mics[i];

View File

@@ -25,6 +25,19 @@ static inline unsigned fifo_get_fill(volatile mem_fifo_t * unsafe fifo) {
} }
} }
static inline unsigned fifo_get_fill_short(volatile mem_fifo_short_t * unsafe fifo) {
unsafe{
unsigned fifo_fill = 0;
if (fifo->write_idx >= fifo->read_idx){
fifo_fill = fifo->write_idx - fifo->read_idx;
}
else{
fifo_fill = (fifo->size + fifo->write_idx) - fifo->read_idx;
}
return fifo_fill;
}
}
#pragma unsafe arrays #pragma unsafe arrays
static inline fifo_ret_t fifo_block_push(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) { static inline fifo_ret_t fifo_block_push(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) {
unsafe{ unsafe{
@@ -44,23 +57,58 @@ static inline fifo_ret_t fifo_block_push(volatile mem_fifo_t * unsafe fifo, int
} }
#pragma unsafe arrays #pragma unsafe arrays
static inline fifo_ret_t fifo_block_push_short_pairs(volatile mem_fifo_t * unsafe fifo, short data[], unsigned n) { static inline fifo_ret_t fifo_block_push_short(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) {
unsafe{ unsafe{
//check there is a block of space large enough //check there is a block of space large enough
unsigned space_remaining = fifo->size - fifo_get_fill(fifo) - 1; unsigned space_remaining = fifo->size - fifo_get_fill_short(fifo) - 1;
if (n > space_remaining) { if (n > space_remaining) {
return FIFO_FULL; return FIFO_FULL;
} }
for (int i = 0; i < n; i++){ for (int i = 0; i < n; i++){
unsigned next_idx = fifo->write_idx + 1; unsigned next_idx = fifo->write_idx + 1;
if (next_idx == fifo->size) next_idx = 0; //Check for wrap if (next_idx == fifo->size) next_idx = 0; //Check for wrap
fifo->data_base_ptr[fifo->write_idx] = data[i] << 16; fifo->data_base_ptr[fifo->write_idx] = data[i];
fifo->write_idx = next_idx; fifo->write_idx = next_idx;
} }
return FIFO_SUCCESS; return FIFO_SUCCESS;
} }
} }
#pragma unsafe arrays
static inline fifo_ret_t fifo_block_push_short_fast(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) {
unsafe{
//check there is a block of space large enough
unsigned space_remaining = fifo->size - fifo_get_fill_short(fifo) - 1;
if (n > space_remaining) {
return FIFO_FULL;
}
//We will write either one or two blocks depending on wrap
unsigned first_block_size = 0;
unsigned second_block_size = 0;
//See if we need to wrap during block writes
unsigned space_left_at_top = fifo->size - fifo->write_idx;
//printf("space_left_at_top %d\n", space_left_at_top);
//Yes, we do need to wrap
if (n > space_left_at_top){
first_block_size = space_left_at_top;
second_block_size = n - space_left_at_top;
memcpy(&fifo->data_base_ptr[fifo->write_idx], &data[0], first_block_size * sizeof(short));
memcpy(&fifo->data_base_ptr[0], &data[first_block_size], second_block_size * sizeof(short));
fifo->write_idx = second_block_size;
}
//No wrap, do all in one go
else{
first_block_size = n;
second_block_size = 0;
memcpy(&fifo->data_base_ptr[fifo->write_idx], &data[0], first_block_size * sizeof(short));
fifo->write_idx += first_block_size;
}
return FIFO_SUCCESS;
}
}
#pragma unsafe arrays #pragma unsafe arrays
static inline fifo_ret_t fifo_block_pop(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) { static inline fifo_ret_t fifo_block_pop(volatile mem_fifo_t * unsafe fifo, int data[], unsigned n) {
unsafe{ unsafe{
@@ -78,14 +126,14 @@ static inline fifo_ret_t fifo_block_pop(volatile mem_fifo_t * unsafe fifo, int d
} }
#pragma unsafe arrays #pragma unsafe arrays
static inline fifo_ret_t fifo_block_pop_short_pairs(volatile mem_fifo_t * unsafe fifo, short data[], unsigned n) { static inline fifo_ret_t fifo_block_pop_short(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) {
unsafe{ unsafe{
//Check we have a block big enough to send //Check we have a block big enough to send
if (n > fifo_get_fill(fifo)){ if (n > fifo_get_fill_short(fifo)){
return FIFO_EMPTY; return FIFO_EMPTY;
} }
for (int i = 0; i < n; i++){ for (int i = 0; i < n; i++){
data[i] = fifo->data_base_ptr[fifo->read_idx] >> 16; data[i] = fifo->data_base_ptr[fifo->read_idx];
fifo->read_idx++; fifo->read_idx++;
if (fifo->read_idx == fifo->size) fifo->read_idx = 0; //Check for wrap if (fifo->read_idx == fifo->size) fifo->read_idx = 0; //Check for wrap
} }
@@ -93,6 +141,43 @@ static inline fifo_ret_t fifo_block_pop_short_pairs(volatile mem_fifo_t * unsafe
} }
} }
#pragma unsafe arrays
static inline fifo_ret_t fifo_block_pop_short_fast(volatile mem_fifo_short_t * unsafe fifo, short data[], unsigned n) {
unsafe{
//Check we have a block big enough to send
if (n > fifo_get_fill_short(fifo)){
return FIFO_EMPTY;
}
//We will read either one or two blocks depending on wrap
unsigned first_block_size = 0;
unsigned second_block_size = 0;
//See if we need to wrap during block read
unsigned num_read_at_top = fifo->size - fifo->read_idx;
// printf("num_read_at_top %d\n", num_read_at_top);
//Yes, we do need to wrap
if (n > num_read_at_top){
first_block_size = num_read_at_top;
second_block_size = n - num_read_at_top;
memcpy(&data[0], &fifo->data_base_ptr[fifo->read_idx], first_block_size * sizeof(short));
memcpy( &data[first_block_size], &fifo->data_base_ptr[0], second_block_size * sizeof(short));
fifo->read_idx = second_block_size;
// printf("wrap\n");
}
//No wrap, do all in one go
else{
first_block_size = n;
second_block_size = 0;
memcpy(&data[0], &fifo->data_base_ptr[fifo->read_idx], first_block_size * sizeof(short));
fifo->read_idx += first_block_size;
// printf("no wrap\n");
}
return FIFO_SUCCESS;
}
}
//Version of above that returns fill level relative to half full //Version of above that returns fill level relative to half full
static inline int fifo_get_fill_relative_half(volatile mem_fifo_t * unsafe fifo){ static inline int fifo_get_fill_relative_half(volatile mem_fifo_t * unsafe fifo){
unsafe{ unsafe{
@@ -102,4 +187,12 @@ static inline int fifo_get_fill_relative_half(volatile mem_fifo_t * unsafe fifo)
} }
} }
//Version of above that returns fill level relative to half full
static inline int fifo_get_fill_relative_half_short(volatile mem_fifo_short_t * unsafe fifo){
unsafe{
int fifo_fill = (int)fifo_get_fill_short(fifo);
fifo_fill -= (fifo->size / 2);
return fifo_fill;
}
}
#endif #endif

View File

@@ -27,4 +27,11 @@ typedef struct mem_fifo_t {
unsigned read_idx; unsigned read_idx;
} mem_fifo_t; } mem_fifo_t;
typedef struct mem_fifo_short_t {
const unsigned size; //Size in SHORTs
short * const unsafe data_base_ptr; //Base of the data array - declared externally so we can have differnt sized FIFOs
unsigned write_idx;
unsigned read_idx;
} mem_fifo_short_t;
#endif #endif

View File

@@ -1,8 +1,6 @@
#include <xs1.h> #include <xs1.h>
#include "xua_ep0_wrapper.h" #include "xua_ep0_wrapper.h"
[[combinable]]
unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub); unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub);
[[combinable]] [[combinable]]
unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub); unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub);

View File

@@ -158,10 +158,10 @@ static void do_feedback_calculation(unsigned &sof_count
void fill_level_process(int fill_level, int &clock_nudge){ void fill_level_process(int fill_level, int &clock_nudge){
const int trigger_high_upper = 6; const int trigger_high_upper = 6;
const int trigger_high_lower = 8; //const int trigger_high_lower = 8;
const int trigger_low_upper = -6; const int trigger_low_upper = -6;
const int trigger_low_lower = -8; //const int trigger_low_lower = -8;
if (fill_level >= trigger_high_upper){ if (fill_level >= trigger_high_upper){
clock_nudge = 1; clock_nudge = 1;
@@ -190,7 +190,6 @@ void XUD_GetSetupData_Select(chanend c, XUD_ep e_out, unsigned &length, XUD_Resu
extern XUD_ep ep0_out; extern XUD_ep ep0_out;
extern XUD_ep ep0_in; extern XUD_ep ep0_in;
[[combinable]]
//Unsafe to allow us to use fifo API without local unsafe scope //Unsafe to allow us to use fifo API without local unsafe scope
unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub) { unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, chanend ?c_feedback, chanend c_aud_in, chanend c_sof, in port p_for_mclk_count, streaming chanend c_audio_hub) {
@@ -231,8 +230,8 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
unsigned num_samples_received_from_host = 0; unsigned num_samples_received_from_host = 0;
unsigned num_samples_to_send_to_host = 0; unsigned num_samples_to_send_to_host = 0;
int samples_out[NUM_USB_CHAN_OUT] = {0}; short samples_in_short[NUM_USB_CHAN_IN] = {0};
int samples_in[NUM_USB_CHAN_IN] = {0}; short samples_out_short[NUM_USB_CHAN_OUT] = {0};
#define c_audioControl null #define c_audioControl null
#define dfuInterface null #define dfuInterface null
@@ -251,21 +250,22 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
//Send initial samples so audiohub is not blocked //Send initial samples so audiohub is not blocked
for (int i = 0; i < NUM_USB_CHAN_OUT * 6; i++) c_audio_hub <: 0; for (int i = 0; i < NUM_USB_CHAN_OUT * 2; i++) c_audio_hub <: 0;
//FIFOs from EP buffers to audio //FIFOs from EP buffers to audio
int host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2]; short host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2];
int device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2]; short device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2];
mem_fifo_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0}; mem_fifo_short_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0};
mem_fifo_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0}; mem_fifo_short_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0};
volatile mem_fifo_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo; volatile mem_fifo_short_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo;
volatile mem_fifo_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo; volatile mem_fifo_short_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo;
//XUD transaction variables passed in by reference //XUD transaction variables passed in by reference
XUD_Result_t result; XUD_Result_t result;
unsigned length = 0; unsigned length = 0;
unsigned u_tmp; //For select channel input by ref unsigned u_tmp; //For select channel input by ref
while(1){ while(1){
#pragma ordered
select{ select{
//Handle EP0 requests //Handle EP0 requests
case XUD_GetSetupData_Select(c_ep0_out, ep0_out, length, result): case XUD_GetSetupData_Select(c_ep0_out, ep0_out, length, result):
@@ -276,7 +276,7 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
XUA_Endpoint0_lite_loop(result, sp, c_ep0_out, c_ep0_in, c_audioControl, null/*mix*/, null/*clk*/, null/*EA*/, dfuInterface, &input_interface_num, &output_interface_num); XUA_Endpoint0_lite_loop(result, sp, c_ep0_out, c_ep0_in, c_audioControl, null/*mix*/, null/*clk*/, null/*EA*/, dfuInterface, &input_interface_num, &output_interface_num);
XUD_SetReady_Out(ep0_out, sbuffer); XUD_SetReady_Out(ep0_out, sbuffer);
//tmr :> t1; debug_printf("c%d\n", t1 - t0); tmr :> t1; debug_printf("c%d\n", t1 - t0);
break; break;
@@ -287,7 +287,7 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
asm volatile(" getts %0, res[%1]" : "=r" (mclk_port_counter) : "r" (p_for_mclk_count)); asm volatile(" getts %0, res[%1]" : "=r" (mclk_port_counter) : "r" (p_for_mclk_count));
if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks); if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks);
sof_count++; sof_count++;
//tmr :> t1; debug_printf("s%d\n", t1 - t0); tmr :> t1; debug_printf("s%d\n", t1 - t0);
break; break;
@@ -297,16 +297,16 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
num_samples_received_from_host = length / out_subslot_size; num_samples_received_from_host = length / out_subslot_size;
fifo_ret_t ret = fifo_block_push_short_pairs(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host); fifo_ret_t ret = fifo_block_push_short(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host);
if (ret != FIFO_SUCCESS) debug_printf("h2d full\n"); if (ret != FIFO_SUCCESS) debug_printf("h2d full\n");
num_samples_to_send_to_host = num_samples_received_from_host; num_samples_to_send_to_host = num_samples_received_from_host;
int fill_level = fifo_get_fill_relative_half(host_to_device_fifo_ptr); int fill_level = fifo_get_fill_relative_half_short(host_to_device_fifo_ptr);
fill_level_process(fill_level, clock_nudge); fill_level_process(fill_level, clock_nudge);
//Mark EP as ready for next frame from host //Mark EP as ready for next frame from host
XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words); XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out.long_words);
//tmr :> t1; debug_printf("o%d\n", t1 - t0); tmr :> t1; debug_printf("o%d\n", t1 - t0);
break; break;
//Send asynch explicit feedback value, but only if enabled //Send asynch explicit feedback value, but only if enabled
@@ -315,7 +315,7 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
XUD_SetReady_In(ep_feedback, (fb_clocks, unsigned char[]), (AUDIO_CLASS == 2) ? 4 : 3); XUD_SetReady_In(ep_feedback, (fb_clocks, unsigned char[]), (AUDIO_CLASS == 2) ? 4 : 3);
//debug_printf("0x%x\n", fb_clocks[0]); //debug_printf("0x%x\n", fb_clocks[0]);
//tmr :> t1; debug_printf("f%d\n", t1 - t0); tmr :> t1; debug_printf("f%d\n", t1 - t0);
break; break;
@@ -325,7 +325,7 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
if (output_interface_num == 0) num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN; if (output_interface_num == 0) num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN;
fifo_ret_t ret = fifo_block_pop_short_pairs(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host); fifo_ret_t ret = fifo_block_pop_short(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host);
if (ret != FIFO_SUCCESS) debug_printf("d2h empty\n"); if (ret != FIFO_SUCCESS) debug_printf("d2h empty\n");
//Populate the input buffer ready for the next read //Populate the input buffer ready for the next read
@@ -335,28 +335,30 @@ unsafe void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_o
unsigned input_buffer_size = num_samples_to_send_to_host * in_subslot_size; unsigned input_buffer_size = num_samples_to_send_to_host * in_subslot_size;
XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, input_buffer_size); //loopback XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, input_buffer_size); //loopback
num_samples_to_send_to_host = 0; num_samples_to_send_to_host = 0;
//tmr :> t1; debug_printf("i%d\n", t1 - t0); tmr :> t1; debug_printf("i%d\n", t1 - t0);
break; break;
//Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO //Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO
case c_audio_hub :> samples_in[0]: case c_audio_hub :> u_tmp:
timer tmr; int t0, t1; tmr :> t0; timer tmr; int t0, t1; tmr :> t0;
samples_in_short[0] = (int)u_tmp >> 16;
for (int i = 1; i < NUM_USB_CHAN_IN; i++){ for (int i = 1; i < NUM_USB_CHAN_IN; i++){
c_audio_hub :> samples_in[i]; c_audio_hub :> u_tmp;
samples_in_short[i] = (int)u_tmp >> 16;
} }
fifo_ret_t ret = fifo_block_pop(host_to_device_fifo_ptr, samples_out, NUM_USB_CHAN_OUT); fifo_ret_t ret = fifo_block_pop_short(host_to_device_fifo_ptr, samples_out_short, NUM_USB_CHAN_OUT);
if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n"); if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n");
for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: samples_out[i]; for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: (int)samples_out_short[i] << 16;
if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge; if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge;
ret = fifo_block_push(device_to_host_fifo_ptr, samples_in, NUM_USB_CHAN_IN); ret = fifo_block_push_short(device_to_host_fifo_ptr, samples_in_short, NUM_USB_CHAN_IN);
if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n"); if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n");
//tmr :> t1; debug_printf("a%d\n", t1 - t0); tmr :> t1; debug_printf("a%d\n", t1 - t0);
break; break;
} }
} }
} }
extern port p_sda;
[[combinable]] [[combinable]]
//Unsafe to allow us to use fifo API without local unsafe scope //Unsafe to allow us to use fifo API without local unsafe scope
@@ -399,9 +401,6 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
unsigned num_samples_received_from_host = 0; unsigned num_samples_received_from_host = 0;
unsigned num_samples_to_send_to_host = 0; unsigned num_samples_to_send_to_host = 0;
int samples_out[NUM_USB_CHAN_OUT] = {0};
int samples_in[NUM_USB_CHAN_IN] = {0};
unsigned input_interface_num = 0; unsigned input_interface_num = 0;
unsigned output_interface_num = 0; unsigned output_interface_num = 0;
@@ -410,17 +409,30 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, num_samples_to_send_to_host); XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, num_samples_to_send_to_host);
if (!isnull(c_feedback)) XUD_SetReady_InPtr(ep_feedback, (unsigned)fb_clocks, (AUDIO_CLASS == 2) ? 4 : 3); if (!isnull(c_feedback)) XUD_SetReady_InPtr(ep_feedback, (unsigned)fb_clocks, (AUDIO_CLASS == 2) ? 4 : 3);
short samples_in_short[NUM_USB_CHAN_IN] = {0};
short samples_out_short[NUM_USB_CHAN_OUT] = {0};
//Send initial samples so audiohub is not blocked //Send initial samples so audiohub is not blocked
for (int i = 0; i < NUM_USB_CHAN_OUT * 6; i++) c_audio_hub <: 0; for (int i = 0; i < NUM_USB_CHAN_OUT * 6; i++) c_audio_hub <: 0;
//FIFOs from EP buffers to audio //FIFOs from EP buffers to audio
int host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2]; short host_to_device_fifo_storage[MAX_OUT_SAMPLES_PER_SOF_PERIOD * 2];
int device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2]; short device_to_host_fifo_storage[MAX_IN_SAMPLES_PER_SOF_PERIOD * 2];
mem_fifo_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0}; mem_fifo_short_t host_to_device_fifo = {sizeof(host_to_device_fifo_storage)/sizeof(host_to_device_fifo_storage[0]), host_to_device_fifo_storage, 0, 0};
mem_fifo_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0}; mem_fifo_short_t device_to_host_fifo = {sizeof(device_to_host_fifo_storage)/sizeof(device_to_host_fifo_storage[0]), device_to_host_fifo_storage, 0, 0};
volatile mem_fifo_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo; volatile mem_fifo_short_t * unsafe host_to_device_fifo_ptr = &host_to_device_fifo;
volatile mem_fifo_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo; volatile mem_fifo_short_t * unsafe device_to_host_fifo_ptr = &device_to_host_fifo;
//debug
const unsigned trig_period = 100000000; //1s
timer tmr;
unsigned sc = 0;
unsigned ac = 0;
unsigned hc = 0;
unsigned tmr_trig;
tmr :> tmr_trig;
tmr_trig += trig_period;
//XUD transaction variables passed in by reference //XUD transaction variables passed in by reference
XUD_Result_t result; XUD_Result_t result;
@@ -448,7 +460,9 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks); if (!isnull(c_feedback)) do_feedback_calculation(sof_count, mclk_hz, mclk_port_counter, mclk_port_counter_old, feedback_value, mod_from_last_time, fb_clocks);
sof_count++; sof_count++;
//tmr :> t1; debug_printf("s%d\n", t1 - t0); //tmr :> t1; debug_printf("s%d\n", t1 - t0);
p_sda <: 1;
p_sda <: 0;
sc++;
break; break;
//Receive samples from host //Receive samples from host
@@ -456,12 +470,13 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
timer tmr; int t0, t1; tmr :> t0; timer tmr; int t0, t1; tmr :> t0;
num_samples_received_from_host = length / out_subslot_size; num_samples_received_from_host = length / out_subslot_size;
hc += num_samples_received_from_host / NUM_USB_CHAN_OUT;
fifo_ret_t ret = fifo_block_push_short_pairs(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host); fifo_ret_t ret = fifo_block_push_short_fast(host_to_device_fifo_ptr, buffer_aud_out.short_words, num_samples_received_from_host);
if (ret != FIFO_SUCCESS) debug_printf("h2d full\n"); if (ret != FIFO_SUCCESS) debug_printf("h2d full\n");
num_samples_to_send_to_host = num_samples_received_from_host; num_samples_to_send_to_host = num_samples_received_from_host;
int fill_level = fifo_get_fill_relative_half(host_to_device_fifo_ptr); int fill_level = fifo_get_fill_relative_half_short(host_to_device_fifo_ptr);
fill_level_process(fill_level, clock_nudge); fill_level_process(fill_level, clock_nudge);
//Mark EP as ready for next frame from host //Mark EP as ready for next frame from host
@@ -483,9 +498,10 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
case XUD_SetData_Select(c_aud_in, ep_aud_in, result): case XUD_SetData_Select(c_aud_in, ep_aud_in, result):
timer tmr; int t0, t1; tmr :> t0; timer tmr; int t0, t1; tmr :> t0;
//If host is not streaming out, then send a fixed number of samples to host
if (output_interface_num == 0) num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN; if (output_interface_num == 0) num_samples_to_send_to_host = (DEFAULT_FREQ / SOF_FREQ_HZ) * NUM_USB_CHAN_IN;
fifo_ret_t ret = fifo_block_pop_short_pairs(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host); fifo_ret_t ret = fifo_block_pop_short_fast(device_to_host_fifo_ptr, buffer_aud_in.short_words, num_samples_received_from_host);
if (ret != FIFO_SUCCESS) debug_printf("d2h empty\n"); if (ret != FIFO_SUCCESS) debug_printf("d2h empty\n");
//Populate the input buffer ready for the next read //Populate the input buffer ready for the next read
@@ -496,21 +512,30 @@ unsafe void XUA_Buffer_lite2(server ep0_control_if i_ep0_ctl, chanend c_aud_out,
XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, input_buffer_size); //loopback XUD_SetReady_InPtr(ep_aud_in, (unsigned)buffer_aud_in.long_words, input_buffer_size); //loopback
num_samples_to_send_to_host = 0; num_samples_to_send_to_host = 0;
//tmr :> t1; debug_printf("i%d\n", t1 - t0); //tmr :> t1; debug_printf("i%d\n", t1 - t0);
break;
case tmr when timerafter(tmr_trig) :> int _:
tmr_trig += trig_period;
debug_printf("HOST: %d SAMP: %d SOF: %d\n", ac, hc, sc);
sc = 0;
ac = 0;
hc = 0;
break; break;
//Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO //Exchange samples with audiohub. Note we are using channel buffering here to act as a FIFO
case c_audio_hub :> samples_in[0]: case c_audio_hub :> u_tmp:
timer tmr; int t0, t1; tmr :> t0; timer tmr; int t0, t1; tmr :> t0;
samples_in_short[0] = (int)u_tmp >> 16;
ac++;
for (int i = 1; i < NUM_USB_CHAN_IN; i++){ for (int i = 1; i < NUM_USB_CHAN_IN; i++){
c_audio_hub :> samples_in[i]; c_audio_hub :> u_tmp;
samples_in_short[i] = (int)u_tmp >> 16;
} }
fifo_ret_t ret = fifo_block_pop(host_to_device_fifo_ptr, samples_out, NUM_USB_CHAN_OUT); fifo_ret_t ret = fifo_block_pop_short(host_to_device_fifo_ptr, samples_out_short, NUM_USB_CHAN_OUT);
if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n"); if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n");
for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: samples_out[i]; for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: (int)samples_out_short[i] << 16;
if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge; if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge;
ret = fifo_block_push(device_to_host_fifo_ptr, samples_in, NUM_USB_CHAN_IN); ret = fifo_block_push_short(device_to_host_fifo_ptr, samples_in_short, NUM_USB_CHAN_IN);
if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n"); if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n");
//tmr :> t1; debug_printf("a%d\n", t1 - t0); //tmr :> t1; debug_printf("a%d\n", t1 - t0);
break; break;