SPI slave why does this work?

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
boeserbaer
Active Member
Posts: 51
Joined: Fri Jan 29, 2010 4:36 pm

SPI slave why does this work?

Post by boeserbaer »

Hi all, I needed to emulate an ADC0831 to work with legacy systems. I managed to get this to work properly, but I don't understand why. The port width is set to 8, but my shift data is in fact 9 bits (forced leading zero).

on stdcore[0] : in port d0Poll = PORT_SPI0_MOSI; // LEGACY_D0Poll
on stdcore[0] : out buffered port:8 legacyData = PORT_SPI0_MISO; // LEGACY_D0
on stdcore[0] : in port legacyClk = PORT_SPI0_CLK; // LEGACY_sync
on stdcore[0] : clock clk = XS1_CLKBLK_1;

void legacyInterface(chanend rx, chanend tx, in port poll ,in port inClk)
{
unsigned pollVal;
unsigned kv = 255;
unsigned ma = 150;
unsigned kvShift;
unsigned maShift;
unsigned activeCh;
unsigned val;

poll :> pollVal;

// Set up the buffered port so that writing a word to legacyData results in the legacyClk (inClk) shifting the data out on the falling edge
configure_clock_src(clk, inClk);
configure_out_port(legacyData, clk, 0);
start_clock(clk);
// The thread runs forever
while (1)
{
select
{
case poll when pinsneq (pollVal) :> pollVal: // d0Poll changed
if (pollVal == 1)
{
maShift = bitrev(ma) >> 23;
legacyData <: maShift;
}
else
{
kvShift = bitrev(kv) >> 23;
legacyData <: kvShift;
}
break;

case rx :> val: // The analog interface is running in another thread sending the kv and ma readbacks every 500us
if ( val >= 256 )
{
ma = (val & 0xff);
}
else
{
kv = (val & 0xff);
}
break;
}
}
}



int main(void) {
chan pg_ch, tx_ch, rx_ch, analogRX_ch, analogTX_ch, status_ch, flashRX_ch, flashTX_ch, legacyRx_ch, legacyTx_ch;
par {
on stdcore[0]: analogInterface(analogRX_ch,analogTX_ch, status_ch, legacyTx_ch, legacyRx_ch);
on stdcore[0]: handleComms(pg_ch, rx_ch,tx_ch,analogRX_ch, analogTX_ch, flashRX_ch, flashTX_ch);
on stdcore[0]: uart_tx(UART_TX_PORT, tx_ch);
on stdcore[0]: uart_rx(UART_RX_PORT, rx_ch);
on stdcore[0]: flashAccess(pg_ch, flashRX_ch, flashTX_ch, status_ch, spi_sclk, spi_mosi, rtc_ss, spi_ss, spi_miso);
on stdcore[0]: legacyInterface(legacyRx_ch, legacyTx_ch, d0Poll, legacyClk);
}
return 0;
}


User avatar
boeserbaer
Active Member
Posts: 51
Joined: Fri Jan 29, 2010 4:36 pm

Post by boeserbaer »

to answer my own question, It want't quite working. The LSB was not really being sent.

I modified the out buffer port width to 32:
on stdcore[0] : out buffered port:32 legacyData = PORT_SPI0_MISO; // LEGACY_D0

and added a clearbuf(legacyData) before briting out the data:

case poll when pinsneq (pollVal) :> pollVal: // d0Poll changed
clearbuf(legacyData);
if (pollVal == 1)
{
maShift = bitrev(ma) >> 23;
legacyData <: maShift;
}
else
{
kvShift = bitrev(kv) >> 23;
legacyData <: kvShift;
}
break;

And now it really works.
User avatar
f_petrini
Active Member
Posts: 43
Joined: Fri Dec 11, 2009 8:20 am
Contact:

Post by f_petrini »

You can use partout() to specify how many bits you want to output.

partout(legacyData, 9, bitrev(ma) >> 23);
void partout ( void port p, unsigned n, unsigned val )

Performs an output of the specified width on a buffered port.

The width must be less than the transfer width of the port, greater than zero and a multiple of the port width, otherwise an exception is raised. The n least significant bits of val are output.

Parameters:
p The buffered port to output on.
n The number of bits to output.
val The value to output.
Post Reply