40 lines
1.3 KiB
C++
40 lines
1.3 KiB
C++
#pragma once
|
|
#include <inttypes.h>
|
|
#include "gpio.h"
|
|
|
|
/// SPI interface
|
|
|
|
namespace hal {
|
|
namespace spi {
|
|
struct SPI_TypeDef {
|
|
volatile uint8_t SPCRx;
|
|
volatile uint8_t SPSRx;
|
|
volatile uint8_t SPDRx;
|
|
};
|
|
|
|
struct SPI_InitTypeDef {
|
|
hal::gpio::GPIO_pin miso_pin;
|
|
hal::gpio::GPIO_pin mosi_pin;
|
|
hal::gpio::GPIO_pin sck_pin;
|
|
hal::gpio::GPIO_pin ss_pin;
|
|
uint8_t prescaler;
|
|
};
|
|
|
|
__attribute__((always_inline)) inline void Init(SPI_TypeDef *const hspi, SPI_InitTypeDef *const conf) {
|
|
using namespace hal;
|
|
gpio::Init(conf->miso_pin, gpio::GPIO_InitTypeDef(gpio::Mode::input, gpio::Pull::none));
|
|
gpio::Init(conf->mosi_pin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::low));
|
|
gpio::Init(conf->sck_pin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::low));
|
|
gpio::Init(conf->ss_pin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high));
|
|
|
|
const uint8_t spi2x = (conf->prescaler == 7) ? 0 : (conf->prescaler & 0x01);
|
|
const uint8_t spr = ((conf->prescaler - 1) >> 1) & 0x03;
|
|
|
|
hspi->SPCRx = (0 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (spr << SPR0);
|
|
hspi->SPSRx = (spi2x << SPI2X);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define SPI0 ((hal::spi::SPI_TypeDef *)&SPCR)
|