uTL
micro Template library
spi_bb.h
Go to the documentation of this file.
1 
22 #ifndef __utl_com_spi_bb_h__
23 #define __utl_com_spi_bb_h__
24 
25 #include <utl/core/impl.h>
26 #include <utl/core/crtp.h>
27 #include <utl/com/spi.h>
28 #include <utl/meta/meta.h>
29 
30 
31 namespace utl {
32 
39 
52  template <typename impl_t,
53  spi::cpol CPOL,
54  spi::cpha CPHA,
56  class spi_bb_i : public spi_i<spi_bb_i<impl_t, CPOL, CPHA, BitOrder>> {
57  _CRTP_IMPL(impl_t);
59  public:
61 
65  protected:
67  ~spi_bb_i () = default;
68  spi_bb_i (uint32_t clk) noexcept
70  : nsec_ {1000000000/(2*clk)} {
71  }
73 
74  private:
77  template <spi::bitOrder B =BitOrder> constexpr
79  template <spi::bitOrder B =BitOrder> constexpr
81  template <spi::cpol C =CPOL> static constexpr bool clkHigh () {
82  return !static_cast<bool>(C);
83  }
84  template <spi::cpol C =CPOL> static constexpr bool clkLow () {
85  return static_cast<bool>(C);
86  }
87  static constexpr bool clkH_ {clkHigh()};
88  static constexpr bool clkL_ {clkLow()};
90 
97  private:
99  void MOSI (bool st) { impl().MOSI(st); }
100  bool MISO () { return impl().MISO(); }
101  void SCLK (bool st) { impl().SCLK (st); }
102  void delay (uint32_t nsec) { impl().delay (nsec); }
103 
105 
109  private:
111  uint32_t _clock () const { return 1000000000/(2*nsec_); }
112  void _clock (uint32_t c) { nsec_ = 1000000000/(2*c); }
113  byte_t _tx_data (byte_t out) { return _tx_data_impl (out); }
114 
115  template <spi::cpha C =CPHA>
117  template <spi::cpha C =CPHA>
120 
123  private:
124  uint32_t nsec_;
125  };
127 
135  template <typename impl_t, spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
136  template <spi::cpha C>
139  byte_t in {};
140  SCLK (clkL_);
141  for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
142  MOSI (out & bit); // Out at preceding clock trailing edge
143  delay (nsec_); // Half cycle delay
144  SCLK (clkH_); // Leading edge
145  in |= (MISO ()) ? bit : 0; // In at leading clock edge
146  delay (nsec_); // Half cycle delay
147  SCLK (clkL_); // Trailing edge
148  }
149  return in;
150  }
151 
159  template <typename impl_t, spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
160  template <spi::cpha C>
163  byte_t in {};
164  SCLK (clkL_);
165  for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
166  delay (nsec_); // Half cycle delay
167  SCLK (clkH_); // Leading edge
168  MOSI (out & bit); // Out at leading clock edge
169  delay (nsec_); // Half cycle delay
170  SCLK (clkL_); // Trailing edge
171  in |= (MISO ()) ? bit : 0; // In at trailing clock edge
172  }
173  return in;
174  }
175 
176 
187  template <spi::cpol CPOL,
188  spi::cpha CPHA,
189  spi::bitOrder BitOrder>
190  class spi_bb_i <virtual_tag, CPOL, CPHA, BitOrder> : public spi_i<virtual_tag> {
191  public:
193 
197  protected:
199  ~spi_bb_i () = default;
200  spi_bb_i (uint32_t clk) noexcept
202  : nsec_ {1000000000/(2*clk)} {
203  }
205 
206  private:
209  template <spi::bitOrder B =BitOrder> constexpr
211  template <spi::bitOrder B =BitOrder> constexpr
213  template <spi::cpol C =CPOL> static constexpr bool clkHigh () {
214  return !static_cast<bool>(C);
215  }
216  template <spi::cpol C =CPOL> static constexpr bool clkLow () {
217  return static_cast<bool>(C);
218  }
219  static constexpr bool clkH_ {clkHigh()};
220  static constexpr bool clkL_ {clkLow()};
222 
223 
226  private:
227  virtual void MOSI (bool) =0;
228  virtual bool MISO () =0;
229  virtual void SCLK (bool) =0;
230  virtual void delay (uint32_t) =0;
231 
233 
237  private:
239  uint32_t _clock () const final { return 1000000000/(2*nsec_); }
240  void _clock (uint32_t c) final { nsec_ = 1000000000/(2*c); }
241  byte_t _tx_data (byte_t out) final { return _tx_data_impl (out); }
242 
243  template <spi::cpha C =CPHA>
245  template <spi::cpha C =CPHA>
248 
251  private:
252  uint32_t nsec_;
253  };
255 
263  template <spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
264  template <spi::cpha C>
267  byte_t in {};
268  SCLK (clkL_);
269  for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
270  MOSI (out & bit); // Out at preceding clock trailing edge
271  delay (nsec_); // Half cycle delay
272  SCLK (clkH_); // Leading edge
273  in |= (MISO ()) ? bit : 0; // In at leading clock edge
274  delay (nsec_); // Half cycle delay
275  SCLK (clkL_); // Trailing edge
276  }
277  return in;
278  }
279 
287  template <spi::cpol CPOL, spi::cpha CPHA, spi::bitOrder BitOrder>
288  template <spi::cpha C>
291  byte_t in {};
292  SCLK (clkL_);
293  for (uint8_t bit {static_cast<uint8_t>(BitOrder)} ; bit ; shift (bit)) {
294  delay (nsec_); // Half cycle delay
295  SCLK (clkH_); // Leading edge
296  MOSI (out & bit); // Out at leading clock edge
297  delay (nsec_); // Half cycle delay
298  SCLK (clkL_); // Trailing edge
299  in |= (MISO ()) ? bit : 0; // In at trailing clock edge
300  }
301  return in;
302  }
303 
304 }
305 
306 #endif //#ifndef __spi_bb_h__
bool MISO()
Implementers&#39;s MISO pin function.
Definition: spi_bb.h:100
Include all meta library.
cpol
Definition: spi.h:47
Less significant first.
static constexpr bool clkLow()
Definition: spi_bb.h:84
uint32_t _clock() const
Definition: spi_bb.h:111
static constexpr bool clkHigh()
Definition: spi_bb.h:81
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
bitOrder
Definition: spi.h:40
~spi_bb_i()=default
void delay(uint32_t nsec)
Definition: spi_bb.h:102
An Abstract base class interface for the spi bus.
A virtual base class implementation.
Definition: spi.h:177
uint32_t nsec_
Definition: spi_bb.h:124
cpha
Definition: spi.h:54
constexpr meta::enable_if_t<(B==spi::bitOrder::LSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:210
static constexpr bool clkL_
Definition: spi_bb.h:88
STL&#39;s core language concepts.
Definition: _1wire.h:30
constexpr meta::enable_if_t<(B==spi::bitOrder::MSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:80
_CRTP_IMPL(impl_t)
A bit banking implementation of spi bus inherited from spi_i base class.
Definition: spi_bb.h:56
spi_bb_i(uint32_t clk) noexcept
A default constructor.
Definition: spi_bb.h:69
eval< enable_if< If, _Tp > > enable_if_t
alias template for enable_if
Definition: sfinae.h:63
A virtual base class interface specialization. Using the private virtual interface we provide the int...
Definition: spi_bb.h:190
static constexpr bool clkH_
Definition: spi_bb.h:87
void SCLK(bool st)
Implementers&#39;s SCLK pin function.
Definition: spi_bb.h:101
Definition: spi.h:67
void _clock(uint32_t c)
Definition: spi_bb.h:112
uint8_t byte_t
8 bits wide
Definition: types.h:31
virtual support tag type
Definition: crtp.h:40
void _clock(uint32_t c) final
Set the clock frequency of the bus.
Definition: spi_bb.h:240
void MOSI(bool st)
Implementers&#39;s MOSI pin function.
Definition: spi_bb.h:99
constexpr meta::enable_if_t<(B==spi::bitOrder::LSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:78
constexpr meta::enable_if_t<(B==spi::bitOrder::MSB_First), void > shift(byte_t &b)
Definition: spi_bb.h:212
Implementation detail main forward header.
byte_t _tx_data(byte_t out)
Definition: spi_bb.h:113
uint32_t _clock() const final
Read the clock frequency of the bus.
Definition: spi_bb.h:239