uTL
micro Template library
spi.h
Go to the documentation of this file.
1 
21 #ifndef _utl_com_spi_h__
22 #define _utl_com_spi_h__
23 
24 #include <utl/core/impl.h>
25 #include <utl/core/crtp.h>
26 #include <utl/meta/meta.h>
27 
28 namespace utl {
29 
34 
36  namespace spi {
40  enum class bitOrder {
41  LSB_First =0x01,
42  MSB_First =0x80
43  };
47  enum class cpol {
48  LOW =0,
49  HIGH
50  };
54  enum class cpha {
55  LOW =0,
56  HIGH
57  };
58  }
59 
66  template <typename impl_t>
67  class spi_i {
68  _CRTP_IMPL(impl_t);
69 
70  public:
71  using type = spi_i<impl_t>;
72 
76  protected:
78  spi_i () = default;
79  ~spi_i () = default;
80  spi_i (const type&) = delete;
81  type& operator= (const type&) = delete;
83 
90  private:
92  uint32_t _clock () const { return impl()._clock (); }
93  void _clock (uint32_t c) { impl()._clock (c); }
94  byte_t _tx_data (byte_t b) { return impl()._tx_data (b); }
95 
100  public:
102  uint32_t clock () const { return _clock (); }
103  void clock (uint32_t c) { _clock (c); }
104 
109  public:
115  return _tx_data (out);
116  }
125  size_t tx_data (const byte_t *out, byte_t *in, size_t n);
130  return _tx_data(0xFF);
131  }
139  size_t rx_data (byte_t *in, size_t n);
141  };
142 
151  template<typename _I>
152  size_t spi_i<_I>::tx_data (const byte_t *out, byte_t *in, size_t n) {
153  for (size_t nn {n} ; nn ; --nn)
154  *in++ = _tx_data (*out++);
155  return n;
156  }
164  template<typename _I>
165  size_t spi_i<_I>::rx_data (byte_t *in, size_t n) {
166  for (size_t nn {n} ; nn ; --nn)
167  *in++ = _tx_data (0xFF);
168  return n;
169  }
170 
176  template <>
177  class spi_i <virtual_tag> {
178  public:
180 
184  protected:
186  spi_i () = default;
187  spi_i (const type&) = delete;
188  type& operator= (const type&) = delete;
189  public:
190  virtual ~spi_i () = default;
191 
196  private:
198  virtual uint32_t _clock () const =0;
199  virtual void _clock (uint32_t) =0;
200  virtual byte_t _tx_data (byte_t) =0;
201 
206  public:
208  uint32_t clock () const { return _clock (); }
209  void clock (uint32_t c) { _clock (c); }
210 
215  public:
221  return _tx_data (out);
222  }
231  size_t tx_data (const byte_t *out, byte_t *in, size_t n);
236  return _tx_data (0xFF);
237  }
245  size_t rx_data (byte_t *in, size_t n);
247 
248  };
249 
258  size_t spi_i<virtual_tag>::tx_data (const byte_t *out, byte_t *in, size_t n) {
259  for (size_t nn {n} ; nn ; --nn)
260  *in++ = _tx_data (*out++);
261  return n;
262  }
270  size_t spi_i<virtual_tag>::rx_data (byte_t *in, size_t n) {
271  for (size_t nn {n} ; nn ; --nn)
272  *in++ = _tx_data (0xFF);
273  return n;
274  }
275 
276 
277 
281 #if defined _utl_have_concepts
283  template <typename T>
284  concept bool Spi_i = requires (T t, const T ct, typename T::Sequence s) {
285  // Object type
286  requires not_<std::is_copy_constructible<T>::value>::value;
287  requires not_<std::is_copy_assignable<T>::value>::value;
288  // Methods
289  {ct.clock()} -> uint32_t;
290  {t.clock(0)} -> void;
291  {t.tx_data(1)} -> byte_t;
292  {t.rx_data()} -> byte_t;
293  };
294 #else
295  namespace spi_i_details {
296  using std::declval;
297 
298  template <class _Tp> using try_cclock_t= decltype (declval<const _Tp>().clock());
299  template <class _Tp> using try_clock_t = decltype (declval<_Tp>().clock(declval<uint32_t>()));
300  template <class _Tp> using try_tx_t = decltype (declval<_Tp>().tx_data(declval<byte_t>()));
301  template <class _Tp> using try_rx_t = decltype (declval<_Tp>().rx_data());
302 
304  template <typename _Tp, typename =void>
305  struct is_spi_ : meta::false_ {};
306 
308  template <typename _Tp>
309  struct is_spi_ <
310  _Tp,
311  meta::void_t <
312  meta::use_if_same_t <try_cclock_t<_Tp>, uint32_t>,
313  meta::use_if_same_t <try_clock_t<_Tp>, void>,
314  meta::use_if_same_t <try_tx_t<_Tp>, byte_t>,
315  meta::use_if_same_t <try_rx_t<_Tp>, byte_t>
316  >
317  > : meta::true_ {};
318  }
324 // template <typename _Tp>
325 // constexpr bool Spi_i = spi_i_details::is_spi_<_Tp>::value;
326 #endif
327 
330 
331 } // namespace utl
332 
333 #endif /* #ifndef _utl_com_spi_h__ */
Include all meta library.
cpol
Definition: spi.h:47
Less significant first.
void void_t
void_t type alias
Definition: detection.h:55
spi_i()=default
Allow constructor from derived only.
Most significant first.
uint32_t clock() const
Definition: spi.h:102
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
uint32_t clock() const
Definition: spi.h:208
bitOrder
Definition: spi.h:40
~spi_i()=default
Allow destructor from derived only.
void clock(uint32_t c)
set clock frequency of the bus
Definition: spi.h:209
void clock(uint32_t c)
set clock frequency of the bus
Definition: spi.h:103
decltype(declval< _Tp >().rx_data()) try_rx_t
Definition: spi.h:301
A virtual base class implementation.
Definition: spi.h:177
_CRTP_IMPL(impl_t)
byte_t rx_data()
Definition: spi.h:129
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
byte_t tx_data(byte_t out)
Definition: spi.h:114
cpha
Definition: spi.h:54
byte_t tx_data(byte_t out)
Definition: spi.h:220
STL&#39;s core language concepts.
Definition: _1wire.h:30
byte_t _tx_data(byte_t b)
Definition: spi.h:94
decltype(declval< _Tp >().tx_data(declval< byte_t >())) try_tx_t
Definition: spi.h:300
decltype(declval< _Tp >().clock(declval< uint32_t >())) try_clock_t
Definition: spi.h:299
Definition: spi.h:67
uint32_t _clock() const
clock frequency of the bus [Hz]
Definition: spi.h:92
uint8_t byte_t
8 bits wide
Definition: types.h:31
virtual support tag type
Definition: crtp.h:40
void _clock(uint32_t c)
set clock frequency of the bus [Hz]
Definition: spi.h:93
decltype(declval< const _Tp >().clock()) try_cclock_t
Definition: spi.h:298
type & operator=(const type &)=delete
Implementation detail main forward header.
Primary template to catch any non SPI interface types.
Definition: spi.h:305