pikapython/package/PikaStdDevice/pika_hal_SOFT_SPI.c

243 lines
7.3 KiB
C

#include "pika_hal.h"
static int _GPIO_write(pika_dev* dev, uint32_t val) {
return pika_hal_write(dev, &val, sizeof(val));
}
static uint32_t _GPIO_read(pika_dev* dev) {
uint32_t val = 0;
pika_hal_read(dev, &val, sizeof(val));
return val;
}
int pika_hal_platform_SOFT_SPI_open(pika_dev* dev, char* name) {
return 0;
}
int pika_hal_platform_SOFT_SPI_close(pika_dev* dev) {
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
if (cfg->CS != NULL) {
pika_hal_close(cfg->CS);
}
if (cfg->SCK != NULL) {
pika_hal_close(cfg->SCK);
}
if (cfg->MOSI != NULL) {
pika_hal_close(cfg->MOSI);
}
if (cfg->MISO != NULL) {
pika_hal_close(cfg->MISO);
}
return 0;
}
int pika_hal_platform_SOFT_SPI_ioctl_config(pika_dev* dev,
pika_hal_SOFT_SPI_config* cfg) {
return 0;
}
int pika_hal_platform_SOFT_SPI_ioctl_enable(pika_dev* dev) {
pika_debug("SOFT_SPI_ioctl_enable, dev[0x%p]", dev);
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
if (cfg->SCK == NULL || cfg->MOSI == NULL) {
__platform_printf(
"Error: SOFT SPI config error, CS, SCK, MOSI, MISO must be "
"set\r\n");
return -1;
}
pika_hal_GPIO_config cfg_CS = {0};
pika_hal_GPIO_config cfg_SCK = {0};
pika_hal_GPIO_config cfg_MOSI = {0};
pika_hal_GPIO_config cfg_MISO = {0};
cfg_CS.dir = PIKA_HAL_GPIO_DIR_OUT;
cfg_SCK.dir = PIKA_HAL_GPIO_DIR_OUT;
cfg_MOSI.dir = PIKA_HAL_GPIO_DIR_OUT;
cfg_MISO.dir = PIKA_HAL_GPIO_DIR_IN;
if (NULL != cfg->CS) {
pika_debug("CS[0x%p] config", cfg->CS);
pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_CONFIG, &cfg_CS);
}
pika_debug("SCK[0x%p] config", cfg->SCK);
pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_CONFIG, &cfg_SCK);
pika_debug("MOSI[0x%p] config", cfg->MOSI);
pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_CONFIG, &cfg_MOSI);
if (NULL != cfg->MISO) {
pika_debug("MISO[0x%p] config", cfg->MISO);
pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_CONFIG, &cfg_MISO);
}
if (NULL != cfg->CS) {
pika_debug("CS[0x%p] enable", cfg->CS);
pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_ENABLE);
}
pika_debug("SCK[0x%p] enable", cfg->SCK);
pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_ENABLE);
pika_debug("MOSI[0x%p] enable", cfg->MOSI);
pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_ENABLE);
if (NULL != cfg->MISO) {
pika_debug("MISO[0x%p] enable", cfg->MISO);
pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_ENABLE);
}
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 1);
}
_GPIO_write(cfg->SCK, 1);
_GPIO_write(cfg->MOSI, 1);
return 0;
}
int pika_hal_platform_SOFT_SPI_ioctl_disable(pika_dev* dev) {
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
if (NULL != cfg->CS) {
pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_DISABLE);
}
pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_DISABLE);
pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_DISABLE);
if (NULL != cfg->MISO) {
pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_DISABLE);
}
return 0;
}
static inline void sleep_us(uint32_t us) {
pika_platform_sleep_us(us);
}
static inline void _SPI_delay(void) {
sleep_us(1);
}
static inline int SPIv_TransferByte(pika_hal_SOFT_SPI_config* cfg,
uint8_t tx,
uint8_t* rx,
int is_msb) {
unsigned char i = 0;
uint8_t received_data = 0; // Used to store the received data
if (is_msb) {
for (i = 0; i < 8; i++) {
if (tx & 0x80) {
_GPIO_write(cfg->MOSI, 1);
} else {
_GPIO_write(cfg->MOSI, 0);
}
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
received_data <<=
1; // Shift received data left, preparing for the new bit
if (NULL != cfg->MISO) {
if (_GPIO_read(cfg->MISO)) { // Read data from the MISO line
received_data |= 0x01; // If MISO is high, set the lowest
// bit of the received data to 1
}
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
tx <<= 1;
}
} else {
for (i = 0; i < 8; i++) {
if (tx & 0x01) {
_GPIO_write(cfg->MOSI, 1);
} else {
_GPIO_write(cfg->MOSI, 0);
}
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
received_data >>=
1; // Shift received data right, preparing for the new bit
if (NULL != cfg->MISO) {
if (_GPIO_read(cfg->MISO)) { // Read data from the MISO line
received_data |= 0x80; // If MISO is high, set the highest
// bit of the received data to 1
}
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
tx >>= 1;
}
}
*rx = received_data; // Store the received data into the variable pointed
// to by rx
return 0;
}
static inline int SPIv_ReadByte(pika_hal_SOFT_SPI_config* cfg, int is_msb) {
unsigned char i = 0;
unsigned char Data = 0;
if (is_msb) {
for (i = 0; i < 8; i++) {
Data <<= 1;
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
if (_GPIO_read(cfg->MISO)) {
Data++;
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
}
} else {
for (i = 0; i < 8; i++) {
Data >>= 1;
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
if (_GPIO_read(cfg->MISO)) {
Data |= 0x80;
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
}
}
return Data;
}
int pika_hal_platform_SOFT_SPI_write(pika_dev* dev, void* buf, size_t count) {
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
uint8_t* data = (uint8_t*)buf;
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 0);
_SPI_delay();
}
int is_msb = cfg->lsb_or_msb == PIKA_HAL_SPI_MSB ? 1 : 0;
for (int i = 0; i < count; i++) {
SPIv_TransferByte(
cfg, data[i],
&cfg->tranfer_rx_buffer[i % PIKA_HAL_SPI_RX_BUFFER_SIZE], is_msb);
}
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 1);
_SPI_delay();
}
return count;
}
int pika_hal_platform_SOFT_SPI_read(pika_dev* dev, void* buf, size_t count) {
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
if (NULL == cfg->MISO) {
__platform_printf("Error: SOFT SPI config error, MISO must be set\r\n");
return -1;
}
uint8_t* data = (uint8_t*)buf;
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 0);
_SPI_delay();
}
int is_msb = cfg->lsb_or_msb == PIKA_HAL_SPI_MSB ? 1 : 0;
for (int i = 0; i < count; i++) {
data[i] = SPIv_ReadByte(cfg, is_msb);
}
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 1);
_SPI_delay();
}
return count;
}