197 lines
4.4 KiB
Plaintext
197 lines
4.4 KiB
Plaintext
// Copyright 2022 XMOS LIMITED.
|
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
|
|
|
/* Simple test to ensure reference clock to CS2100 device continues when SOF clock not available
|
|
* Note, this test uses "nice" numbers (i.e. MISSIG_SOFS %8 == 0) and therefore doesn't check
|
|
* for a graceful change over from internal to SOF clock
|
|
*/
|
|
|
|
#include "platform.h"
|
|
#include "xua.h"
|
|
#include "print.h"
|
|
#include "xud.h"
|
|
|
|
#define EP_COUNT_IN (3)
|
|
#define EP_COUNT_OUT (3)
|
|
|
|
out port p_pll_ref = XS1_PORT_1A;
|
|
in port p_off_mclk = XS1_PORT_1M;
|
|
in port p_pll_loop = XS1_PORT_1B; /* Note, this is externally looped back using the loopback plugin */
|
|
|
|
/* Purely for debug/viewing on VCD */
|
|
out port p_test0 = XS1_PORT_1C;
|
|
out port p_test1 = XS1_PORT_1D;
|
|
|
|
#ifndef BUS_SPEED
|
|
#error BUS_SPEED should be defined
|
|
#endif
|
|
|
|
/* To speed this test up we divide all delays by 10. This is also the case for the delays in the clock generation code */
|
|
#if(BUS_SPEED == 2) // XUD_SPEED_HS
|
|
#define SOF_PERIOD_TICKS (12500/10)
|
|
#define SOF_DIVIDE (1)
|
|
#else
|
|
#define SOF_PERIOD_TICKS ((12500*8)/10)
|
|
#define SOF_DIVIDE (8)
|
|
#endif
|
|
|
|
#ifndef MISSING_SOF_PERIOD
|
|
/* By default skip a whole number of SOF periods (easy case)
|
|
* Note, app_test_sync_plugin/Makefiles sets this to something more nasty */
|
|
#define MISSING_SOF_PERIOD (8 * SOF_PERIOD_TICKS)
|
|
#endif
|
|
|
|
void exit(int);
|
|
|
|
void delay(unsigned d)
|
|
{
|
|
timer t;
|
|
unsigned time;
|
|
t :> time;
|
|
t when timerafter(time + d) :> int x;
|
|
}
|
|
|
|
/* From lib_xud */
|
|
void SetupEndpoints(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEpIn, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[]);
|
|
|
|
void AudioHwInit()
|
|
{
|
|
return;
|
|
}
|
|
|
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void driveSofs(chanend c_sof, int count)
|
|
{
|
|
static int frame = 0;
|
|
|
|
/* For HS frame should only increment every 8 SOFs, but this is a "dont care" */
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
outuint(c_sof, frame++);
|
|
delay(SOF_PERIOD_TICKS);
|
|
}
|
|
}
|
|
|
|
void fake_xud(chanend c_out[], chanend c_in[], chanend c_sof)
|
|
{
|
|
timer t;
|
|
unsigned time;
|
|
|
|
|
|
/* Makes traces a bit nicer to look at */
|
|
t :> time;
|
|
t when timerafter(SOF_PERIOD_TICKS * 2) :> int x;
|
|
|
|
p_test0 <: 1;
|
|
|
|
/* Endpoint type tables */
|
|
XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_DIS};
|
|
XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_ISO};
|
|
|
|
SetupEndpoints(c_out, EP_COUNT_OUT, c_in, EP_COUNT_IN, epTypeTableOut, epTypeTableIn);
|
|
|
|
driveSofs(c_sof, 32/SOF_DIVIDE);
|
|
|
|
p_test0 <: 0;
|
|
|
|
/* Sim missing SOFs */
|
|
delay(MISSING_SOF_PERIOD);
|
|
|
|
p_test0 <: 1;
|
|
|
|
driveSofs(c_sof, 16/SOF_DIVIDE);
|
|
|
|
p_test0 <: 0;
|
|
|
|
delay(MISSING_SOF_PERIOD);
|
|
|
|
p_test0 <: 1;
|
|
|
|
driveSofs(c_sof, 16/SOF_DIVIDE);
|
|
|
|
p_test0 <: 0;
|
|
|
|
}
|
|
|
|
extern XUD_BusSpeed_t g_curUsbSpeed;
|
|
|
|
#define MARGIN (1500/10)
|
|
#define EXPECTED_PERIOD (100000/10)
|
|
|
|
void checker()
|
|
{
|
|
timer t;
|
|
unsigned t0, t1;
|
|
unsigned x = 0;
|
|
int fail = 0;
|
|
|
|
p_test1 <: 1;
|
|
|
|
p_pll_loop when pinseq(1) :> x;
|
|
p_pll_loop when pinseq(0) :> x;
|
|
p_pll_loop when pinseq(1) :> x;
|
|
|
|
for(int i = 0; i < 12; i++)
|
|
{
|
|
p_pll_loop when pinsneq(x) :> x;
|
|
t :> t0;
|
|
p_pll_loop when pinsneq(x) :> x;
|
|
t :> t1;
|
|
|
|
int period = t1-t0;
|
|
|
|
/* Check the period of the reference clock we are generating */
|
|
if(period > (EXPECTED_PERIOD + MARGIN))
|
|
{
|
|
printstr("Period too long: ");
|
|
printintln(period);
|
|
fail = 1;
|
|
}
|
|
else if(period < (EXPECTED_PERIOD - MARGIN))
|
|
{
|
|
printstr("Period too short: ");
|
|
printintln(period);
|
|
fail = 1;
|
|
}
|
|
}
|
|
if(!fail)
|
|
printstrln("PASS");
|
|
|
|
p_test1 <: 0;
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
chan c_out[EP_COUNT_OUT];
|
|
chan c_in[EP_COUNT_IN];
|
|
chan c_sof;
|
|
chan c_aud_ctl;
|
|
|
|
interface pll_ref_if i_pll_ref;
|
|
|
|
par
|
|
{
|
|
PllRefPinTask(i_pll_ref, p_pll_ref);
|
|
|
|
{
|
|
g_curUsbSpeed = BUS_SPEED;
|
|
|
|
XUA_Buffer_Ep(c_out[1], /* USB Audio Out*/
|
|
c_in[1], /* USB Audio In */
|
|
c_sof, c_aud_ctl, p_off_mclk, i_pll_ref
|
|
);
|
|
}
|
|
|
|
fake_xud(c_out, c_in, c_sof);
|
|
|
|
checker();
|
|
}
|
|
}
|