#pragma once #include "../inout/inout.h" #include 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); static void setCPHA(bool bCPHA); static constexpr InOut::Pin sm_enmSCK = InOut::Pin::P_B5; static constexpr InOut::Pin sm_enmMISO = InOut::Pin::P_B4; static constexpr InOut::Pin sm_enmMOSI = InOut::Pin::P_B3; static constexpr InOut::Pin sm_enmSS = InOut::Pin::P_B2; static InOutPin sm_cSCK; static InOutPin sm_cMISO; static InOutPin sm_cMOSI; static InOutPin 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); static void deinit(); static void setClockDiv(ClockDiv enmClockDiv); static void setMode(Mode enmMode); static void setMaster(bool bMaster); static void setBitOrder(bool bLSBFirst); static uint8_t transfer(uint8_t ui8Data); static void select(bool bSelect); }; ////////////////////////////////////////////////////////////////////////// InOutPin SPI::sm_cSCK; InOutPin SPI::sm_cMISO; InOutPin SPI::sm_cMOSI; InOutPin SPI::sm_cSS; ////////////////////////////////////////////////////////////////////////// void SPI::setCPOL(bool bCPOL) { if (bCPOL) { SPCR |= (1 << CPOL); } else { SPCR &= ~(1 << CPOL); } } ////////////////////////////////////////////////////////////////////////// void SPI::setCPHA(bool bCPHA) { if (bCPHA) { SPCR |= (1 << CPHA); } else { SPCR &= ~(1 << CPHA); } } ////////////////////////////////////////////////////////////////////////// void SPI::init(ClockDiv enmClockDiv /* = ClockDiv::CLKDIV_128 */, Mode enmMode /* = Mode::MODE_0 */, bool bMaster /* = true */, bool bLSBFirst /* = false */, bool bMISOPullup /* = false */) { sm_cSCK.setPin(sm_enmSCK); sm_cMISO.setPin(sm_enmMISO); sm_cMOSI.setPin(sm_enmMOSI); sm_cSS.setPin(sm_enmSS); if (bMaster) { sm_cSS.write(true); sm_cSCK.setDirection(InOut::Dir::D_OUT, false); sm_cMISO.setDirection(InOut::Dir::D_IN, bMISOPullup); sm_cMOSI.setDirection(InOut::Dir::D_OUT, false); sm_cSS.setDirection(InOut::Dir::D_OUT, false); } else { sm_cSCK.setDirection(InOut::Dir::D_IN, false); sm_cMISO.setDirection(InOut::Dir::D_OUT, false); sm_cMOSI.setDirection(InOut::Dir::D_IN, false); sm_cSS.setDirection(InOut::Dir::D_IN, true); } setClockDiv(enmClockDiv); setMode(enmMode); setMaster(bMaster); setBitOrder(bLSBFirst); SPCR |= (1 << SPE); } ////////////////////////////////////////////////////////////////////////// void SPI::deinit() { SPCR = 0; sm_cSCK.setDirection(InOut::Dir::D_IN, false); sm_cMISO.setDirection(InOut::Dir::D_IN, false); sm_cMOSI.setDirection(InOut::Dir::D_IN, false); sm_cSS.setDirection(InOut::Dir::D_IN, false); } ////////////////////////////////////////////////////////////////////////// void SPI::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); } } ////////////////////////////////////////////////////////////////////////// void SPI::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); } } ////////////////////////////////////////////////////////////////////////// void SPI::setMaster(bool bMaster) { if (bMaster) { SPCR |= (1 << MSTR); } else { SPCR &= ~(1 << MSTR); } } ////////////////////////////////////////////////////////////////////////// void SPI::setBitOrder(bool bLSBFirst) { if (bLSBFirst) { SPCR |= (1 << DORD); } else { SPCR &= ~(1 << DORD); } } ////////////////////////////////////////////////////////////////////////// uint8_t SPI::transfer(uint8_t ui8Data) { SPDR = ui8Data; while (!(SPSR & (1 << SPIF))) ; return SPDR; } ////////////////////////////////////////////////////////////////////////// void SPI::select(bool bSelect) { sm_cSS.write(!bSelect); }