diff options
Diffstat (limited to 'ports/esp8266/hspi.c')
-rw-r--r-- | ports/esp8266/hspi.c | 112 |
1 files changed, 59 insertions, 53 deletions
diff --git a/ports/esp8266/hspi.c b/ports/esp8266/hspi.c index 554a50460..cecf0b755 100644 --- a/ports/esp8266/hspi.c +++ b/ports/esp8266/hspi.c @@ -36,7 +36,7 @@ void spi_init(uint8_t spi_no) { spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); - SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD); + SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP | SPI_CS_HOLD); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); } @@ -84,14 +84,14 @@ void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) { } if (spi_no == SPI) { // Set bit 8 if 80MHz sysclock required - WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8)); + WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag << 8)); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1); } else if (spi_no == HSPI) { // Set bit 9 if 80MHz sysclock required - WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9)); + WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag << 9)); // GPIO12 is HSPI MISO pin (Master Data In) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // GPIO13 is HSPI MOSI pin (Master Data Out) @@ -117,11 +117,11 @@ void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) { WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK); } else { WRITE_PERI_REG(SPI_CLOCK(spi_no), - (((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) | - (((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) | - (((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | - ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S) - ); + (((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) | + (((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) | + (((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | + ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S) + ); } } @@ -185,15 +185,17 @@ Note: all data is assumed to be stored in the lower bits of the data variables (for anything <32 bits). */ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, - uint32_t addr_bits, uint32_t addr_data, - uint32_t dout_bits, uint32_t dout_data, - uint32_t din_bits, uint32_t dummy_bits) { - while (spi_busy(spi_no)) {}; // Wait for SPI to be ready + uint32_t addr_bits, uint32_t addr_data, + uint32_t dout_bits, uint32_t dout_data, + uint32_t din_bits, uint32_t dummy_bits) { + while (spi_busy(spi_no)) { + } + ; // Wait for SPI to be ready // Enable SPI Functions // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO | - SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); + SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); // Enable functions based on number of bits. 0 bits = disabled. // This is rather inefficient but allows for a very generic function. @@ -213,25 +215,25 @@ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, WRITE_PERI_REG(SPI_USER1(spi_no), // Number of bits in Address ((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S | - // Number of bits to Send - ((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S | - // Number of bits to receive - ((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S | - // Number of Dummy bits to insert - ((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S); + // Number of bits to Send + ((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S | + // Number of bits to receive + ((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S | + // Number of Dummy bits to insert + ((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S); // Setup Command Data if (cmd_bits) { // Enable COMMAND function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND); // Align command data to high bits - uint16_t command = cmd_data << (16-cmd_bits); + uint16_t command = cmd_data << (16 - cmd_bits); // Swap byte order - command = ((command>>8)&0xff) | ((command<<8)&0xff00); + command = ((command >> 8) & 0xff) | ((command << 8) & 0xff00); WRITE_PERI_REG(SPI_USER2(spi_no), ( (((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | (command & SPI_USR_COMMAND_VALUE) - )); + )); } // Setup Address Data @@ -246,42 +248,44 @@ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, if (dout_bits) { // Enable MOSI function in SPI module SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI); - // Copy data to W0 - if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) { - WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits)); - } else { - uint8_t dout_extra_bits = dout_bits%8; - - if (dout_extra_bits) { - // If your data isn't a byte multiple (8/16/24/32 bits) and you - // don't have SPI_WR_BYTE_ORDER set, you need this to move the - // non-8bit remainder to the MSBs. Not sure if there's even a use - // case for this, but it's here if you need it... For example, - // 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output - // as if it were 0x0DA4, of which 0xA4, and then 0x0 would be - // shifted out (first 8 bits of low byte, then 4 MSB bits of high - // byte - ie reverse byte order). - // The code below shifts it out as 0xA4 followed by 0xD as you - // might require. - WRITE_PERI_REG(SPI_W0(spi_no), ( - (0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data) - << (8-dout_extra_bits) | - ((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits))) - & dout_data) - )); + // Copy data to W0 + if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) { + WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits)); } else { - WRITE_PERI_REG(SPI_W0(spi_no), dout_data); + uint8_t dout_extra_bits = dout_bits % 8; + + if (dout_extra_bits) { + // If your data isn't a byte multiple (8/16/24/32 bits) and you + // don't have SPI_WR_BYTE_ORDER set, you need this to move the + // non-8bit remainder to the MSBs. Not sure if there's even a use + // case for this, but it's here if you need it... For example, + // 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output + // as if it were 0x0DA4, of which 0xA4, and then 0x0 would be + // shifted out (first 8 bits of low byte, then 4 MSB bits of high + // byte - ie reverse byte order). + // The code below shifts it out as 0xA4 followed by 0xD as you + // might require. + WRITE_PERI_REG(SPI_W0(spi_no), ( + (0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data) + << (8 - dout_extra_bits) | + ((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits))) + & dout_data) + )); + } else { + WRITE_PERI_REG(SPI_W0(spi_no), dout_data); + } } } -} // Begin SPI Transaction SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); // Return DIN data if (din_bits) { - while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete - if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) { + while (spi_busy(spi_no)) { + } + ; // Wait for SPI transaction to complete + if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_RD_BYTE_ORDER) { // Assuming data in is written to MSB. TBC return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits); } else { @@ -301,19 +305,21 @@ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data, Just do minimal work needed to send 8 bits. */ inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) { - while (spi_busy(spi_no)) {}; // Wait for SPI to be ready + while (spi_busy(spi_no)) { + } + ; // Wait for SPI to be ready // Enable SPI Functions // Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO | - SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); + SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY); // Setup Bitlengths WRITE_PERI_REG(SPI_USER1(spi_no), // Number of bits to Send ((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S | - // Number of bits to receive - ((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S); + // Number of bits to receive + ((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S); // Setup DOUT data |