64 lines
1.7 KiB
C++
64 lines
1.7 KiB
C++
#include "spi_manager.h"
|
|
#include <Arduino.h>
|
|
#include <avr/io.h>
|
|
|
|
// =====================================================
|
|
// 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();
|
|
}
|