*/
/**
- * Spi implementation using a USCI device.
+ * Spi implementation using a USCI device. When being used as a SPI slave, the
+ * CSn interface should be wired to the chip select driven by the SPI master so
+ * the module can know when a communications session is terminated unexpectedly.
*
* TODO: Implement error checking via UCxxSTAT
*
uses {
interface HplMsp430UsciReg as Registers;
interface HplMsp430UsciInt as Interrupts;
+ interface GeneralIO as CSn;
interface HplMsp430GeneralIO as STE;
interface HplMsp430GeneralIO as SIMO;
interface HplMsp430GeneralIO as SOMI;
uint16_t m_len;
uint16_t m_pos;
- inline bool is4pin() /* true if the SPI bus is in 4-pin mode */
+ inline bool is4pin() /* TRUE if the SPI bus is in 4-pin mode */
{
return (call Registers.getCtl0(UCMODE_3)) != UCMODE_0;
}
- inline bool isBusy() /* true if a SPI transaction is in progress */
+ inline bool isBusy() /* TRUE if a SPI transaction is in progress */
{
atomic return m_len != 0;
}
}
}
- async command uint8_t SpiByte.write(uint8_t byte)
+ bool waitOnRx()
{
- if (isBusy())
- return 0;
- else {
- while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST));
- call Registers.setTxbuf(byte);
- while(!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST));
- return call Registers.getRxbuf();
+ for (;;) {
+ if (call Registers.getIfgRx())
+ return TRUE;
+ if (call CSn.get()) /* SPI master has unselected us */
+ return FALSE;
}
}
- bool waitOnRx()
+ bool waitOnTx()
{
- if (call Registers.getCtl0(UCMST)) {
- while (!call Registers.getIfgRx() && !call Registers.getCtl1(UCSWRST));
- return TRUE;
- } else {
- /* If SPI slave, the host could quit clocking any time, so we need a
- * timeout.
- */
- unsigned i = 0;
-
- while (++i) {
- if (call Registers.getIfgRx())
- return TRUE;
- if (call Registers.getCtl1(UCSWRST))
- return FALSE;
- }
- return FALSE;
+ for (;;) {
+ if (call Registers.getIfgTx())
+ return TRUE;
+ if (call CSn.get()) /* SPI master has unselected us */
+ return FALSE;
}
}
- bool waitOnTx()
+ async command uint8_t SpiByte.write(uint8_t byte)
{
- if (call Registers.getCtl0(UCMST)) {
- while (!call Registers.getIfgTx() && !call Registers.getCtl1(UCSWRST));
- return TRUE;
- } else {
- /* If SPI slave, the host could quit clocking any time, so we need a
- * timeout.
- */
- unsigned i = 0;
-
- while (++i) {
- if (call Registers.getIfgTx())
- return TRUE;
- if (call Registers.getCtl1(UCSWRST))
- return FALSE;
- }
- return FALSE;
+ if (isBusy())
+ return 0;
+ else {
+ waitOnTx();
+ call Registers.setTxbuf(byte);
+ waitOnRx();
+ return call Registers.getRxbuf();
}
}
waitOnTx();
call Registers.setTxbuf(m_txBuf ? m_txBuf[m_pos] : 0);
}
- return call Registers.getCtl1(UCSWRST) ? FALSE : TRUE;
+ return call CSn.get() ? FALSE : TRUE;
}
}
async event void Interrupts.i2cCal() {}
async event void Interrupts.brk() {}
async event void Interrupts.i2cNak() {}
+
+ default async command bool CSn.get() { return FALSE; }
}