1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-24 08:45:10 +03:00
2015-04-10 22:35:44 +03:00

110 lines
2.8 KiB
C

#include "driver/hspi.h"
/*
Pinout:
MISO GPIO12
MOSI GPIO13
CLK GPIO14
CS GPIO15
DC GPIO2
*/
#define __min(a,b) ((a > b) ? (b):(a))
uint32_t *spi_fifo;
uint32_t current_spi_port;
spi_config spi_init(uint32_t spi_port, uint32_t prescaler, spi_mode mode)
{
spi_config config;
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
if (spi_port == SPI)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 2); // SD_D0 MISO
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 2); // SD_D1 MOSI
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 2); // CLK
} else if (spi_port == HSPI)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // HSPIQ MISO GPIO12
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); // HSPID MOSI GPIO13
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); // CLK GPIO14
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); // CS GPIO15
}
config.mode = mode;
config.spi_port = spi_port;
// SPI clock = CPU clock / 10 / 4
// time length HIGHT level = (CPU clock / 10 / 2) ^ -1,
// time length LOW level = (CPU clock / 10 / 2) ^ -1
config.clock_reg_val = (((prescaler - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
((1 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
((0 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((1 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S);
spi_reinit(&config);
return config;
}
void spi_reinit(spi_config *config)
{
current_spi_port = config->spi_port;
spi_fifo = (uint32_t*)SPI_FLASH_C0(current_spi_port);
uint32_t regvalue = SPI_FLASH_DOUT;
WRITE_PERI_REG(SPI_FLASH_CLOCK(current_spi_port), config->clock_reg_val);
WRITE_PERI_REG(SPI_FLASH_CTRL1(current_spi_port), 0);
switch(config->mode)
{
case spi_mode_tx:
regvalue &= ~(BIT2 | SPI_FLASH_USR_ADDR | SPI_FLASH_USR_DUMMY | SPI_FLASH_USR_DIN | SPI_USR_COMMAND | SPI_DOUTDIN);
break;
case spi_mode_txrx:
regvalue |= SPI_DOUTDIN | SPI_CK_I_EDGE;
regvalue &= ~(BIT2 | SPI_FLASH_USR_ADDR | SPI_FLASH_USR_DUMMY | SPI_FLASH_USR_DIN | SPI_USR_COMMAND);
break;
}
WRITE_PERI_REG(SPI_FLASH_USER(current_spi_port), regvalue);
}
void spi_send_uint16_r(uint16_t data, int32_t repeats)
{
uint32_t i;
uint32_t word = data << 16 | data;
while(repeats > 0)
{
uint16_t bytes_to_transfer = __min(repeats * sizeof(uint16_t) , SPIFIFOSIZE * sizeof(uint32_t));
spi_wait_ready();
spi_prepare_tx(bytes_to_transfer);
for(i = 0; i < (bytes_to_transfer + 3) / 4;i++)
spi_fifo[i] = word;
spi_start_tx();
repeats -= bytes_to_transfer / 2;
}
}
void spi_send_data(const uint8_t * data, uint8_t datasize)
{
uint32_t *_data = (uint32_t*)data;
uint8_t i;
uint8_t words_to_send = __min((datasize + 3) / 4, SPIFIFOSIZE);
spi_prepare_tx(datasize);
for(i = 0; i < words_to_send;i++)
spi_fifo[i] = _data[i];
spi_start_tx();
}
uint16_t spi_send_uint8_receive_13bits(uint8_t to_send)
{
spi_prepare_txrx_bits(8, 13);
*spi_fifo = to_send;
spi_start_tx();
spi_wait_ready();
return (*spi_fifo) & 0x1FFF;
}