#pragma once #include "../io/io.hpp" #include namespace spi { class Spi { public: enum class ClockDiv { CLKDIV_4 = 0, CLKDIV_16 = 1, CLKDIV_64 = 2, CLKDIV_128 = 3, CLKDIV_2X_2 = 4, CLKDIV_2X_8 = 5, CLKDIV_2X_32 = 6, CLKDIV_2X_64 = 7, }; enum class Mode { MODE_0 = 0, MODE_1 = 1, MODE_2 = 2, MODE_3 = 3, }; private: static void setCPOL(bool bCPOL) { if (bCPOL) { SPCR |= (1 << CPOL); } else { SPCR &= ~(1 << CPOL); } } static void setCPHA(bool bCPHA) { if (bCPHA) { SPCR |= (1 << CPHA); } else { SPCR &= ~(1 << CPHA); } } static io::Pin sm_cSCK; static io::Pin sm_cMISO; static io::Pin sm_cMOSI; static io::Pin sm_cSS; public: static void init(ClockDiv enmClockDiv = ClockDiv::CLKDIV_128, Mode enmMode = Mode::MODE_0, bool bMaster = true, bool bLSBFirst = false, bool bMISOPullup = false) { if (bMaster) { sm_cSS.write(true); sm_cSCK.dir(io::Dir::OUT); sm_cMISO.dir(io::Dir::IN); sm_cMISO.pullup(bMISOPullup); sm_cMOSI.dir(io::Dir::OUT); sm_cSS.dir(io::Dir::OUT); } else { sm_cSCK.dir(io::Dir::IN); sm_cMISO.dir(io::Dir::OUT); sm_cMOSI.dir(io::Dir::IN); sm_cSS.dir(io::Dir::IN); sm_cSS.pullup(true); } setClockDiv(enmClockDiv); setMode(enmMode); setMaster(bMaster); setBitOrder(bLSBFirst); SPCR |= (1 << SPE); } static void deinit() { SPCR = 0; sm_cSCK.dir(io::Dir::IN); sm_cMISO.dir(io::Dir::IN); sm_cMOSI.dir(io::Dir::IN); sm_cSS.dir(io::Dir::IN); } static void setClockDiv(ClockDiv enmClockDiv) { uint8_t ui8ClockDiv = static_cast(enmClockDiv); if (ui8ClockDiv & 1) { SPCR |= (1 << SPR0); } else { SPCR &= ~(1 << SPR0); } if (ui8ClockDiv & (1 << 1)) { SPCR |= (1 << SPR1); } else { SPCR &= ~(1 << SPR1); } if (ui8ClockDiv & (1 << 2)) { SPSR |= (1 << SPI2X); } else { SPSR &= ~(1 << SPI2X); } } static void setMode(Mode enmMode) { if (enmMode == Mode::MODE_0 || enmMode == Mode::MODE_1) { setCPOL(false); } else { setCPOL(true); } if (enmMode == Mode::MODE_0 || enmMode == Mode::MODE_2) { setCPHA(false); } else { setCPHA(true); } } static void setMaster(bool bMaster) { if (bMaster) { SPCR |= (1 << MSTR); } else { SPCR &= ~(1 << MSTR); } } static void setBitOrder(bool bLSBFirst) { if (bLSBFirst) { SPCR |= (1 << DORD); } else { SPCR &= ~(1 << DORD); } } static uint8_t transfer(uint8_t ui8Data) { SPDR = ui8Data; while (!(SPSR & (1 << SPIF))) ; return SPDR; } static void select(bool bSelect) { sm_cSS.write(!bSelect); } }; } // namespace spi