p_dbg provides a line that I can probe with an oscilloscope to determine when and for how long the code runs. I have also been probing the SPI lines.
In production code this code will be notified every 10us. I an currently calling it in bursts of three, 100us apart, with one burst every 3ms. [In order to keep a laser eye safe].
My observation is that the first transfer starts 3.3us after the start of my function and the second 3us after that. The whole case takes 8us. This is all acceptable. Observed by measuring spi_clk relative to p_dbg line.
However, when the same code is called 100us later, the transfer does not start until after 600us! This is, obviously, not fit for my purpose. I assume that this is due to the transaction ending and then beginning again on the same device. My understanding is that this should take just 4 (SS_DASSERT_TIME) clocks extra.
How can I get repeated SPI reads to occur in good time?
Code: Select all
#define SS_DEASSERT_TIME 4
#define SPI_DEVICE_NUMBER 0
#define SPI_CLK_SPEED 48000
on tile[0] : out port p_dbg = XS1_PORT_4A; // XOD02/03/08/09
#define ADC_DELAY (ticks_per_us)
void intensity_task(client spi_master_if i_spi, client trigger_if i_reading)
{
BOOL awaitingADC = FALSE;
int adc_time;
timer tmr;
unsigned short value;
unsigned char* pValue = (unsigned char*)&value;
while(TRUE)
{
select
{
case i_reading.trigger():
tmr :> adc_time;
p_dbg <: 2;
i_reading.ack();
adc_time += ADC_DELAY;
awaitingADC = TRUE;
p_dbg <: 0;
break;
case awaitingADC => tmr when timerafter(adc_time) :> void:
p_dbg <: 1;
i_spi.begin_transaction(SPI_DEVICE_NUMBER, SPI_CLK_SPEED, SPI_MODE_3);
// Mode 3 required to correctly read in on the correct edges and correctly start on the first bit.
pValue[1] = i_spi.transfer8(0);
pValue[0] = i_spi.transfer8(0);
i_spi.end_transaction(SS_DEASSERT_TIME);
awaitingADC = FALSE;
p_dbg <: 0;
break;
}
}
}