/** * @brief Receive status register from slave(ESP8266). * */ int ICACHE_FLASH_ATTR SPIMasterRecvStatus (SpiNum spiNum) { if (spiNum > SpiNum_HSPI) { return -1; } while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Enable MISO SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI | SPI_USR_DUMMY | SPI_USR_ADDR); // 8bits cmd, 0x06 is eps8266 slave read status cmd value WRITE_PERI_REG(SPI_USER2(spiNum), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | MASTER_READ_STATUS_FROM_SLAVE_CMD); // Set revcive buffer length. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN, 7, SPI_USR_MISO_BITLEN_S); // start spi module. SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; uint8_t data = (uint8) (READ_PERI_REG(SPI_W0(spiNum)) & 0xff); return (uint8) (READ_PERI_REG(SPI_W0(spiNum)) & 0xff); }
/** * @brief Send data to slave(ESP8266 register of RD_STATUS or WR_STATUS). * */ void ICACHE_FLASH_ATTR SPIMasterSendStatus (SpiNum spiNum, uint8_t data) { if (spiNum > SpiNum_HSPI) { return; } while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Enable MOSI SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR); // 8bits cmd, 0x04 is eps8266 slave write cmd value WRITE_PERI_REG(SPI_USER2(spiNum), ((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | MASTER_WRITE_STATUS_TO_SLAVE_CMD); // Set data send buffer length. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN, ( (sizeof (data) << 3) - 1), SPI_USR_MOSI_BITLEN_S); WRITE_PERI_REG(SPI_W0(spiNum), (uint32 ) (data)); // Start SPI SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); }
/* @defgroup SPI hardware implementation * @brief transfer32() * * private method used by transfer(byte) and transfer16(sort) * to send/recv one uint32_t * * SPI transfer is based on a simultaneous send and receive: * the received data is returned in receivedVal (or receivedVal16). * * receivedVal = SPI.transfer(val) : single byte * receivedVal16 = SPI.transfer16(val16) : single short */ uint32 SPIClass::transfer32(uint32 data, uint8 bits) { uint32_t regvalue = READ_PERI_REG(SPI_USER(SPI_NO)) & (SPI_WR_BYTE_ORDER | SPI_RD_BYTE_ORDER | SPI_CK_OUT_EDGE); while(READ_PERI_REG(SPI_CMD(SPI_NO))&SPI_USR); regvalue |= SPI_USR_MOSI | SPI_DOUTDIN | SPI_CK_I_EDGE; WRITE_PERI_REG(SPI_USER(SPI_NO), regvalue); WRITE_PERI_REG(SPI_USER1(SPI_NO), ( (bits-1 & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S ) | ( (bits-1 & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S ) ); // copy data to W0 if(READ_PERI_REG(SPI_USER(SPI_NO))&SPI_WR_BYTE_ORDER) { WRITE_PERI_REG(SPI_W0(SPI_NO), data<<(32-bits)); } else { WRITE_PERI_REG(SPI_W0(SPI_NO), data); } SET_PERI_REG_MASK(SPI_CMD(SPI_NO), SPI_USR); // send while (READ_PERI_REG(SPI_CMD(SPI_NO)) & SPI_USR); // wait a while before reading the register into the buffer // delayMicroseconds(2); if(READ_PERI_REG(SPI_USER(SPI_NO))&SPI_RD_BYTE_ORDER) { return READ_PERI_REG(SPI_W0(SPI_NO)) >> (32-bits); //Assuming data in is written to MSB. TBC } else { return READ_PERI_REG(SPI_W0(SPI_NO)); //Read in the same way as DOUT is sent. Note existing contents of SPI_W0 remain unless overwritten!
/** * @brief Receive data from slave. * */ int ICACHE_FLASH_ATTR SPIMasterRecvData (SpiNum spiNum, SpiData* pOutData) { char idx = 0; if ( (spiNum > SpiNum_HSPI) || (NULL == pOutData)) { return -1; } uint32_t *value = pOutData->data; while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Set command by user. if (pOutData->cmdLen != 0) { // Max command length 16 bits. SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN, ( (pOutData->cmdLen << 3) - 1), SPI_USR_COMMAND_BITLEN_S); // Enable command SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND); // Load command SPIMasterCfgCmd (spiNum, pOutData->cmd); } else { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND); SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN, 0, SPI_USR_COMMAND_BITLEN_S); } // Set Address by user. if (pOutData->addrLen == 0) { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR); SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN, 0, SPI_USR_ADDR_BITLEN_S); } else { if (NULL == pOutData->addr) { return -1; } SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN, ( (pOutData->addrLen << 3) - 1), SPI_USR_ADDR_BITLEN_S); // Enable address SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR); // Load address SPIMasterCfgAddr (spiNum, *pOutData->addr); } // Set data by user. if (pOutData->dataLen != 0) { if (NULL == value) { return -1; } // Clear MOSI enable CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); // Enable MOSI SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO); // Set data send buffer length.Max data length 64 bytes. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN, ( (pOutData->dataLen << 3) - 1), SPI_USR_MISO_BITLEN_S); } else { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO); SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN, 0, SPI_USR_MISO_BITLEN_S); } // Start send data SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Read data out do { *pOutData->data++ = READ_PERI_REG(SPI_W0(spiNum) + (idx << 2)); } while ( ++idx < (pOutData->dataLen / 4)); return 0; }
/** * @brief Send data to slave. * */ int ICACHE_FLASH_ATTR SPIMasterSendData (SpiNum spiNum, SpiData* pInData) { char idx = 0; if ( (spiNum > SpiNum_HSPI) || (NULL == pInData) || (64 < pInData->dataLen)) { return -1; } uint32_t *value = pInData->data; while (READ_PERI_REG(SPI_CMD(spiNum)) & SPI_USR) ; // Set command by user. if (pInData->cmdLen != 0) { // Max command length 16 bits. SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN, ( (pInData->cmdLen << 3) - 1), SPI_USR_COMMAND_BITLEN_S); // Enable command SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND); // Load command SPIMasterCfgCmd (spiNum, pInData->cmd); } else { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND); SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN, 0, SPI_USR_COMMAND_BITLEN_S); } // Set Address by user. if (pInData->addrLen == 0) { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR); SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN, 0, SPI_USR_ADDR_BITLEN_S); } else { if (NULL == pInData->addr) { return -1; } SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN, ( (pInData->addrLen << 3) - 1), SPI_USR_ADDR_BITLEN_S); // Enable address SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR); // Load address SPIMasterCfgAddr (spiNum, *pInData->addr); } // Set data by user. if (pInData->dataLen != 0) { if (NULL == value) { return -1; } // Enable MOSI SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO); // Load send buffer do { WRITE_PERI_REG((SPI_W0(spiNum) + (idx << 2)), *value++); } while ( ++idx < (pInData->dataLen / 4)); // Set data send buffer length.Max data length 64 bytes. SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN, ( (pInData->dataLen << 3) - 1), SPI_USR_MOSI_BITLEN_S); } else { CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI); SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN, 0, SPI_USR_MOSI_BITLEN_S); } // Start send data SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR); // Wait for transmit done while ( ! (READ_PERI_REG(SPI_SLAVE(spiNum)) & SPI_TRANS_DONE)) ; CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), SPI_TRANS_DONE); return 0; }