Tasmota/lib/lib_display/UDisplay/uDisplay_spi.cpp
2025-10-12 17:15:02 +02:00

154 lines
4.1 KiB
C++

#include "uDisplay.h"
#include "uDisplay_config.h"
#include "uDisplay_spi.h"
#ifndef ESP32
#include "spi_register.h"
#endif
// ===== Low-Level SPI Write Functions =====
// ===== RA8876 Controller Commands =====
static constexpr uint8_t RA8876_DATA_WRITE = 0x80;
static constexpr uint8_t RA8876_DATA_READ = 0xC0;
static constexpr uint8_t RA8876_CMD_WRITE = 0x00;
static constexpr uint8_t RA8876_STATUS_READ = 0x40;
#ifdef ESP32
void uDisplay::hw_write9(uint8_t val, uint8_t dc) {
if (spi_dc < -1) {
// RA8876 mode
if (!dc) {
uspi->write(RA8876_CMD_WRITE);
uspi->write(val);
} else {
uspi->write(RA8876_DATA_WRITE);
uspi->write(val);
}
} else {
uint32_t regvalue = val >> 1;
if (dc) regvalue |= 0x80;
else regvalue &= 0x7f;
if (val & 1) regvalue |= 0x8000;
REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI);
REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1);
uint32_t *dp = (uint32_t*)SPI_W0_REG(3);
*dp = regvalue;
REG_SET_BIT(SPI_CMD_REG(3), SPI_USR);
while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR));
}
}
#else
void uDisplay::hw_write9(uint8_t val, uint8_t dc) {
if (spi_dc < -1) {
// RA8876 mode
if (!dc) {
uspi->write(RA8876_CMD_WRITE);
uspi->write(val);
} else {
uspi->write(RA8876_DATA_WRITE);
uspi->write(val);
}
} else {
uint32_t regvalue;
uint8_t bytetemp;
if (!dc) {
bytetemp = (val>> 1) & 0x7f;
} else {
bytetemp = (val >> 1) | 0x80;
}
regvalue = ((8 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | ((uint32)bytetemp);
if (val & 0x01) regvalue |= BIT15;
while (READ_PERI_REG(SPI_CMD(1)) & SPI_USR);
WRITE_PERI_REG(SPI_USER2(1), regvalue);
SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR);
}
}
#endif
// ===== Software SPI (Slow) Functions =====
void uDisplay::write8(uint8_t val) {
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR(spi_clk);
if (val & bit) GPIO_SET(spi_mosi);
else GPIO_CLR(spi_mosi);
GPIO_SET(spi_clk);
}
}
void uDisplay::write8_slow(uint8_t val) {
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR_SLOW(spi_clk);
if (val & bit) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
}
}
void uDisplay::write9(uint8_t val, uint8_t dc) {
GPIO_CLR(spi_clk);
if (dc) GPIO_SET(spi_mosi);
else GPIO_CLR(spi_mosi);
GPIO_SET(spi_clk);
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR(spi_clk);
if (val & bit) GPIO_SET(spi_mosi);
else GPIO_CLR(spi_mosi);
GPIO_SET(spi_clk);
}
}
void uDisplay::write9_slow(uint8_t val, uint8_t dc) {
GPIO_CLR_SLOW(spi_clk);
if (dc) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR_SLOW(spi_clk);
if (val & bit) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
}
}
void uDisplay::write16(uint16_t val) {
for (uint16_t bit = 0x8000; bit; bit >>= 1) {
GPIO_CLR(spi_clk);
if (val & bit) GPIO_SET(spi_mosi);
else GPIO_CLR(spi_mosi);
GPIO_SET(spi_clk);
}
}
void uDisplay::write32(uint32_t val) {
for (uint32_t bit = 0x80000000; bit; bit >>= 1) {
GPIO_CLR(spi_clk);
if (val & bit) GPIO_SET(spi_mosi);
else GPIO_CLR(spi_mosi);
GPIO_SET(spi_clk);
}
}
// ===== RA8876 Specific Functions =====
uint8_t uDisplay::writeReg16(uint8_t reg, uint16_t wval) {
hw_write9(reg, 0);
hw_write9(wval, 1);
hw_write9(reg + 1, 0);
hw_write9(wval >> 8, 1);
return 0;
}
uint8_t uDisplay::readData(void) {
uspi->write(RA8876_DATA_READ);
uint8_t val = uspi->transfer(0);
return val;
}
uint8_t uDisplay::readStatus(void) {
uspi->write(RA8876_STATUS_READ);
uint8_t val = uspi->transfer(0);
return val;
}