spi_bb.h
Go to the documentation of this file.
#ifndef __utl_com_spi_bb_h__
#define __utl_com_spi_bb_h__
#include <utl/core/impl.h>
#include <utl/core/crtp.h>
#include <utl/com/spi.h>
#include <utl/meta/meta.h>
namespace utl {
template <typename impl_t,
spi::cpol CPOL,
spi::cpha CPHA,
spi::bitOrder BitOrder =spi::bitOrder::MSB_First>
class spi_bb_i : public spi_i<spi_bb_i<impl_t, CPOL, CPHA, BitOrder>> {
_CRTP_IMPL(impl_t);
friend spi_i<spi_bb_i<impl_t, CPOL, CPHA, BitOrder>>;
public:
using type = spi_bb_i<impl_t, CPOL, CPHA, BitOrder>;
protected:
~spi_bb_i () = default;
spi_bb_i (uint32_t clk) noexcept
: nsec_ {1000000000/(2*clk)} {
}
private:
template <spi::bitOrder B =BitOrder> constexpr
meta::enable_if_t <(B == spi::bitOrder::LSB_First), void> shift (byte_t& b) { b <<=1; }
template <spi::bitOrder B =BitOrder> constexpr
meta::enable_if_t <(B == spi::bitOrder::MSB_First), void> shift (byte_t& b) { b >>=1; }
template <spi::cpol C =CPOL> static constexpr bool clkHigh () {
return !static_cast<bool>(C);
}
template <spi::cpol C =CPOL> static constexpr bool clkLow () {
return static_cast<bool>(C);
}
static constexpr bool clkH_ {clkHigh()};
static constexpr bool clkL_ {clkLow()};
private:
void MOSI (bool st) { impl().MOSI(st); }
bool MISO () { return impl().MISO(); }
void SCLK (bool st) { impl().SCLK (st); }
void delay (uint32_t nsec) { impl().delay (nsec); }
private:
uint32_t _clock () const { return 1000000000/(2*nsec_); }
void _clock (uint32_t c) { nsec_ = 1000000000/(2*c); }
byte_t _tx_data (byte_t out) { return _tx_data_impl (out); }
template <spi::cpha C =CPHA>
meta::enable_if_t <(C == spi::cpha::LOW), byte_t> _tx_data_impl (byte_t out);
template <spi::cpha C =CPHA>
meta::enable_if_t <(C == spi::cpha::HIGH), byte_t> _tx_data_impl (byte_t out);
private:
uint32_t nsec_;
};
template <typename impl_t, spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
template <spi::cpha C>
meta::enable_if_t <(C == spi::cpha::LOW), byte_t>
spi_bb_i<impl_t, CPOL, CPHA, BitOrder>::_tx_data_impl (byte_t out) {
byte_t in {};
SCLK (clkL_);
for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
MOSI (out & bit); // Out at preceding clock trailing edge
delay (nsec_); // Half cycle delay
SCLK (clkH_); // Leading edge
in |= (MISO ()) ? bit : 0; // In at leading clock edge
delay (nsec_); // Half cycle delay
SCLK (clkL_); // Trailing edge
}
return in;
}
template <typename impl_t, spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
template <spi::cpha C>
meta::enable_if_t <(C == spi::cpha::HIGH), byte_t>
spi_bb_i<impl_t, CPOL, CPHA, BitOrder>::_tx_data_impl (byte_t out) {
byte_t in {};
SCLK (clkL_);
for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
delay (nsec_); // Half cycle delay
SCLK (clkH_); // Leading edge
MOSI (out & bit); // Out at leading clock edge
delay (nsec_); // Half cycle delay
SCLK (clkL_); // Trailing edge
in |= (MISO ()) ? bit : 0; // In at trailing clock edge
}
return in;
}
template <spi::cpol CPOL,
spi::cpha CPHA,
spi::bitOrder BitOrder>
class spi_bb_i <virtual_tag, CPOL, CPHA, BitOrder> : public spi_i<virtual_tag> {
public:
using type = spi_bb_i<virtual_tag, CPOL, CPHA, BitOrder>;
protected:
~spi_bb_i () = default;
spi_bb_i (uint32_t clk) noexcept
: nsec_ {1000000000/(2*clk)} {
}
private:
template <spi::bitOrder B =BitOrder> constexpr
meta::enable_if_t <(B == spi::bitOrder::LSB_First), void> shift (byte_t& b) { b <<=1; }
template <spi::bitOrder B =BitOrder> constexpr
meta::enable_if_t <(B == spi::bitOrder::MSB_First), void> shift (byte_t& b) { b >>=1; }
template <spi::cpol C =CPOL> static constexpr bool clkHigh () {
return !static_cast<bool>(C);
}
template <spi::cpol C =CPOL> static constexpr bool clkLow () {
return static_cast<bool>(C);
}
static constexpr bool clkH_ {clkHigh()};
static constexpr bool clkL_ {clkLow()};
private:
virtual void MOSI (bool) =0;
virtual bool MISO () =0;
virtual void SCLK (bool) =0;
virtual void delay (uint32_t) =0;
private:
uint32_t _clock () const final { return 1000000000/(2*nsec_); }
void _clock (uint32_t c) final { nsec_ = 1000000000/(2*c); }
byte_t _tx_data (byte_t out) final { return _tx_data_impl (out); }
template <spi::cpha C =CPHA>
meta::enable_if_t <(C == spi::cpha::LOW), byte_t> _tx_data_impl (byte_t out);
template <spi::cpha C =CPHA>
meta::enable_if_t <(C == spi::cpha::HIGH), byte_t> _tx_data_impl (byte_t out);
private:
uint32_t nsec_;
};
template <spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
template <spi::cpha C>
meta::enable_if_t <(C == spi::cpha::LOW), byte_t>
spi_bb_i<virtual_tag, CPOL, CPHA, BitOrder>::_tx_data_impl (byte_t out) {
byte_t in {};
SCLK (clkL_);
for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
MOSI (out & bit); // Out at preceding clock trailing edge
delay (nsec_); // Half cycle delay
SCLK (clkH_); // Leading edge
in |= (MISO ()) ? bit : 0; // In at leading clock edge
delay (nsec_); // Half cycle delay
SCLK (clkL_); // Trailing edge
}
return in;
}
template <spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
template <spi::cpha C>
meta::enable_if_t <(C == spi::cpha::HIGH), byte_t>
spi_bb_i<virtual_tag, CPOL, CPHA, BitOrder>::_tx_data_impl (byte_t out) {
byte_t in {};
SCLK (clkL_);
for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
delay (nsec_); // Half cycle delay
SCLK (clkH_); // Leading edge
MOSI (out & bit); // Out at leading clock edge
delay (nsec_); // Half cycle delay
SCLK (clkL_); // Trailing edge
in |= (MISO ()) ? bit : 0; // In at trailing clock edge
}
return in;
}
}
#endif //#ifndef __spi_bb_h__
utl::spi_bb_i::MISO
bool MISO()
Implementers&#39;s MISO pin function.
Definition: spi_bb.h:100
meta.h
Include all meta library.
utl::spi::cpol
cpol
Definition: spi.h:47
utl::spi::bitOrder::MSB_First
Less significant first.
utl::spi_bb_i::clkLow
static constexpr bool clkLow()
Definition: spi_bb.h:84
utl::spi_bb_i::_clock
uint32_t _clock() const
Definition: spi_bb.h:111
utl::spi_bb_i::clkHigh
static constexpr bool clkHigh()
Definition: spi_bb.h:81
utl::spi_bb_i::_tx_data_impl
meta::enable_if_t<(C==spi::cpha::LOW), byte_t > _tx_data_impl(byte_t out)
_tx_data implementation for CPHA == LOW Out at preceding clock trailing edge, In at leading clock edg...
Definition: spi_bb.h:138
utl::spi::bitOrder
bitOrder
Definition: spi.h:40
crtp.h
utl::spi_bb_i::~spi_bb_i
~spi_bb_i()=default
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::clkLow
static constexpr bool clkLow()
Definition: spi_bb.h:216
utl::spi_bb_i::delay
void delay(uint32_t nsec)
Definition: spi_bb.h:102
spi.h
An Abstract base class interface for the spi bus.
utl::spi_i< virtual_tag >
A virtual base class implementation.
Definition: spi.h:177
utl::spi_bb_i::nsec_
uint32_t nsec_
Definition: spi_bb.h:124
utl::spi::cpha
cpha
Definition: spi.h:54
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::shift
constexpr meta::enable_if_t<(B==spi::bitOrder::LSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:210
utl::spi_bb_i::clkL_
static constexpr bool clkL_
Definition: spi_bb.h:88
utl
STL&#39;s core language concepts.
Definition: _1wire.h:30
utl::spi_bb_i::shift
constexpr meta::enable_if_t<(B==spi::bitOrder::MSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:80
utl::spi_bb_i::_CRTP_IMPL
_CRTP_IMPL(impl_t)
utl::spi_bb_i
A bit banking implementation of spi bus inherited from spi_i base class.
Definition: spi_bb.h:56
utl::spi_bb_i::spi_bb_i
spi_bb_i(uint32_t clk) noexcept
A default constructor.
Definition: spi_bb.h:69
utl::meta::enable_if_t
eval< enable_if< If, _Tp > > enable_if_t
alias template for enable_if
Definition: sfinae.h:63
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >
A virtual base class interface specialization. Using the private virtual interface we provide the int...
Definition: spi_bb.h:190
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::clkHigh
static constexpr bool clkHigh()
Definition: spi_bb.h:213
utl::spi_bb_i::clkH_
static constexpr bool clkH_
Definition: spi_bb.h:87
utl::spi_bb_i::SCLK
void SCLK(bool st)
Implementers&#39;s SCLK pin function.
Definition: spi_bb.h:101
utl::spi_i
Definition: spi.h:67
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::nsec_
uint32_t nsec_
Definition: spi_bb.h:252
utl::spi_bb_i::_clock
void _clock(uint32_t c)
Definition: spi_bb.h:112
utl::byte_t
uint8_t byte_t
8 bits wide
Definition: types.h:31
utl::virtual_tag
virtual support tag type
Definition: crtp.h:40
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::_tx_data
byte_t _tx_data(byte_t out) final
Definition: spi_bb.h:241
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::_clock
void _clock(uint32_t c) final
Set the clock frequency of the bus.
Definition: spi_bb.h:240
utl::spi_bb_i::MOSI
void MOSI(bool st)
Implementers&#39;s MOSI pin function.
Definition: spi_bb.h:99
utl::spi_bb_i::shift
constexpr meta::enable_if_t<(B==spi::bitOrder::LSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:78
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::shift
constexpr meta::enable_if_t<(B==spi::bitOrder::MSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:212
impl.h
Implementation detail main forward header.
utl::spi_bb_i::_tx_data
byte_t _tx_data(byte_t out)
Definition: spi_bb.h:113
utl::spi_bb_i< virtual_tag, CPOL, CPHA, BitOrder >::_clock
uint32_t _clock() const final
Read the clock frequency of the bus.
Definition: spi_bb.h:239