#include "spi_manager.h" #include #include // ===================================================== // SPI MANAGER — SPI0 DEFAULT MUX // PA1=MOSI (pin 20) PA2=MISO (pin 1) // PA3=SCK (pin 2) PA4=CS (pin 5, software) // No PORTMUX remapping required. // ===================================================== void SPI_Init(void) { pinMode(SPI_MOSI_PIN, OUTPUT); pinMode(SPI_MISO_PIN, INPUT); pinMode(SPI_SCK_PIN, OUTPUT); pinMode(SPI_CS_CAN_PIN, OUTPUT); digitalWrite(SPI_CS_CAN_PIN, HIGH); // CS inactive // Default SPI0 MUX is already PA1/PA2/PA3. PORTMUX.SPIROUTEA = PORTMUX_SPI0_DEFAULT_gc; SPI0.CTRLA = SPI_MASTER_bm | SPI_PRESC_DIV4_gc; // 20 MHz / 4 = 5 MHz SPI0.CTRLB = SPI_MODE_0_gc | SPI_SSD_bm; // Software SS SPI0.CTRLA |= SPI_ENABLE_bm; } void SPI_CS_Assert(void) { digitalWrite(SPI_CS_CAN_PIN, LOW); } void SPI_CS_Deassert(void) { digitalWrite(SPI_CS_CAN_PIN, HIGH); } uint8_t SPI_TransferByte(uint8_t txByte) { SPI0.DATA = txByte; while (!(SPI0.INTFLAGS & SPI_IF_bm)) { /* wait */ } return SPI0.DATA; } void SPI_TransferBuffer(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { uint8_t tx = (txBuf != nullptr) ? txBuf[i] : 0x00; uint8_t rx = SPI_TransferByte(tx); if (rxBuf != nullptr) rxBuf[i] = rx; } } void SPI_Write(const uint8_t *data, uint16_t len) { SPI_CS_Assert(); SPI_TransferBuffer(data, nullptr, len); SPI_CS_Deassert(); } void SPI_Read(uint8_t *buf, uint16_t len) { SPI_CS_Assert(); SPI_TransferBuffer(nullptr, buf, len); SPI_CS_Deassert(); }