/** Sends a Module Synchronous Request (SREQ) message and retrieves the response. A SREQ is a message to the Module that is immediately followed by a Synchronous Response (SRSP) message from the Module. As opposed to an Asynchronous Request (AREQ) message, which does not have a SRSP. This is a private method that gets wrapped by sendMessage() and spiPoll(). @pre Module has been initialized @pre zmBuf contains a properly formatted message. No validation is done. @post received data is written to zmBuf @return if FAST_PROCESSOR is defined then MODULE_SUCCESS, else an error code. If FAST_PROCESSOR is not defined, then MODULE_SUCCESS. */ moduleResult_t sendSreq() { #ifdef FAST_PROCESSOR //NOTE: only enable if using a processor with sufficient speed (25MHz+) uint32_t timeLeft1 = CHIP_SELECT_TO_SRDY_LOW_TIMEOUT; uint32_t timeLeft2 = WAIT_FOR_SRSP_TIMEOUT; SPI_SS_SET(); // Assert SS while (SRDY_IS_HIGH() && (timeLeft1 != 0)) //wait until SRDY goes low timeLeft1--; if (timeLeft1 == 0) //SRDY did not go low in time, so return an error return ZM_PHY_CHIP_SELECT_TIMEOUT; timeFromChipSelectToSrdyLow = (CHIP_SELECT_TO_SRDY_LOW_TIMEOUT - timeLeft1); spiWrite(zmBuf, (*zmBuf + 3)); // *bytes (first byte) is length after the first 3 bytes, all frames have at least the first 3 bytes *zmBuf = 0; *(zmBuf+1) = 0; *(zmBuf+2) = 0; //poll message is 0,0,0 //NOTE: MRDY must remain asserted here, but can de-assert SS if the two signals are separate /* Now: Data was sent, so we wait for Synchronous Response (SRSP) to be received. This will be indicated by SRDY transitioning to high */ while (SRDY_IS_LOW() && (timeLeft2 != 0)) //wait for data timeLeft2--; if (timeLeft2 == 0) return ZM_PHY_SRSP_TIMEOUT; timeWaitingForSrsp = (WAIT_FOR_SRSP_TIMEOUT - timeLeft2); //NOTE: if SS & MRDY are separate signals then can re-assert SS here. spiWrite(zmBuf, 3); if (*zmBuf > 0) // *bytes (first byte) contains number of bytes to receive spiWrite(zmBuf+3, *zmBuf); //write-to-read: read data into buffer SPI_SS_CLEAR(); return 0; #else // In a slow processor there's not enough time to set up the timeout so there will be errors SPI_SS_SET(); while (SRDY_IS_HIGH()) ; //wait until SRDY goes low spiWrite(zmBuf, (*zmBuf + 3)); // *bytes (first byte) is length after the first 3 bytes, all frames have at least the first 3 bytes *zmBuf = 0; *(zmBuf+1) = 0; *(zmBuf+2) = 0; //poll message is 0,0,0 //NOTE: MRDY must remain asserted here, but can de-assert SS if the two signals are separate //Now: Data was sent, wait for Synchronous Response (SRSP) while (SRDY_IS_LOW()) ; //wait for data //NOTE: if SS & MRDY are separate signals then can re-assert SS here. spiWrite(zmBuf, 3); if (*zmBuf > 0) // *bytes (first byte) contains number of bytes to receive spiWrite(zmBuf+3, *zmBuf); //write-to-read: read data into buffer SPI_SS_CLEAR(); // re-assert MRDY and SS return MODULE_SUCCESS; #endif }
/************************************************************************* Setup hardware SPI in Master mode Input: none Returns: none *************************************************************************/ void SPI_master_setup(void) { SPI_PORT.DIR |= SPI_MOSI | SPI_SS | SPI_CLK; SPI_SS_SET(); SPI.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_3_gc | SPI_PRESCALER_DIV4_gc | SPI_CLK2X_bm; SPI.INTCTRL = SPI_INTLVL_OFF_gc; }
/** From znp_interface_spi.c, implemented here to avoid pesky dependencies */ signed int sendSreq() { SPI_SS_SET(); while (SRDY_IS_HIGH()) ; //wait until SRDY goes low spiWrite(znpBuf, (*znpBuf + 3)); // *bytes (first byte) is length after the first 3 bytes, all frames have at least the first 3 bytes *znpBuf = 0; *(znpBuf+1) = 0; *(znpBuf+2) = 0; //poll message is 0,0,0 //SPI_SS_CLEAR(); //NOTE: MRDY must remain asserted here, but can de-assert SS if the two signals are separate while (SRDY_IS_LOW()) ; //wait for data //SPI_SS_SET(); //NOTE: if SS & MRDY are separate signals then can re-assert SS here. spiWrite(znpBuf, 3); if (*znpBuf > 0) // *bytes (first byte) contains number of bytes to receive spiWrite(znpBuf+3, *znpBuf); //write-to-read: read data into buffer SPI_SS_CLEAR(); return 0; }