uTL
micro Template library
_1wire.h
Go to the documentation of this file.
1 
21 #ifndef __utl_com_1wire_h__
22 #define __utl_com_1wire_h__
23 
24 #include <utl/core/impl.h>
25 #include <utl/core/crtp.h>
26 #include <utl/com/_1wire_id.h>
27 #include <utl/meta/meta.h>
28 
29 
30 namespace utl {
31 
36 
41  namespace _1wire_i_det {
42  template <typename _T> byte_t _touch (_T& obj, byte_t out, typename _T::Speed s);
43  template <typename _T> void _match (_T& obj, _1wire_id_t& id, typename _T::Speed s);
44  template <typename _T> void _match_n_ovdr (_T& obj, _1wire_id_t& id);
45  template <typename _T> void _skip (_T& obj, typename _T::Speed s);
46  template <typename _T> void _skip_n_ovdr (_T& obj);
47  template <typename _T> _1wire_id_t _first (_T& obj, typename _T::Speed s, bool alarm);
48  template <typename _T> _1wire_id_t _next (_T& obj, typename _T::Speed s, bool alarm);
49  }
50 
56  template <typename impl_t>
57  class _1wire_i {
58  _CRTP_IMPL(impl_t);
59 
60  public:
61  using type = _1wire_i;
62 
64  enum class Speed { STD =0, OVDR };
65 
69  protected:
71  _1wire_i () = default;
72  ~_1wire_i () = default;
73  _1wire_i (const _1wire_i&) = delete;
74  _1wire_i& operator= (const _1wire_i&) = delete;
76 
83  private:
85  Speed speed () const { return impl().speed(); }
86  void speed (Speed s) { return impl().speed(s); }
87  bool bit (bool b) { return impl().bit(b); }
89  bool _reset (Speed s){ return impl()._reset(s); }
90 
95  private:
97  enum Command {
98  CMD_READ_ROM = 0x33,
99  CMD_OVDR_SKIP = 0x3C,
100  CMD_MATCH = 0x55,
102  CMD_SKIP = 0xCC,
105  };
106  template <typename _T> friend byte_t _1wire_i_det::_touch (_T&, byte_t, typename _T::Speed);
107  template <typename _T> friend void _1wire_i_det::_match (_T& obj, _1wire_id_t& id, typename _T::Speed s);
108  template <typename _T> friend void _1wire_i_det::_match_n_ovdr (_T& obj, _1wire_id_t& id);
109  template <typename _T> friend void _1wire_i_det::_skip (_T& obj, typename _T::Speed s);
110  template <typename _T> friend void _1wire_i_det::_skip_n_ovdr (_T& obj);
111  template <typename _T> friend _1wire_id_t _1wire_i_det::_first (_T&, typename _T::Speed, bool);
112  template <typename _T> friend _1wire_id_t _1wire_i_det::_next (_T&, typename _T::Speed, bool);
114 
118  public:
128  bool reset (Speed s = Speed::STD) {
129  return _reset (s);
130  }
131 
139  return _1wire_i_det::_touch (*this, out, s);
140  }
141 
150  size_t tx_data (const byte_t *out, byte_t *in, size_t n, Speed s = Speed::STD);
157  return _1wire_i_det::_touch (*this, 0xFF, s);
158  }
166  size_t rx_data (byte_t *in, size_t n, Speed s = Speed::STD);
167 
173  void match (_1wire_id_t& id, Speed s = Speed::STD) {
174  _1wire_i_det::_match (*this, id, s);
175  }
182  _1wire_i_det::_match_n_ovdr (*this, id);
183  }
188  void skip (Speed s = Speed::STD) {
189  _1wire_i_det::_skip (*this, s);
190  }
194  void skip_n_ovdr () {
196  }
197 
207  _1wire_id_t first (Speed s = Speed::STD, bool alarm =false) {
208  return _1wire_i_det::_first (*this, s, alarm);
209  }
220  _1wire_id_t next (Speed s = Speed::STD, bool alarm =false) {
221  return _1wire_i_det::_next (*this, s, alarm);
222  }
224 
225  private:
238  };
239 
240  template <typename _I>
241  size_t _1wire_i<_I>::tx_data (const byte_t *out, byte_t *in, size_t n, Speed s){
242  for (size_t nn {n} ; nn ; --nn)
243  *in++ = tx_data (*out++, s);
244  return n;
245  }
246 
247  template <typename _I>
248  size_t _1wire_i<_I>::rx_data(byte_t *in, size_t n, Speed s) {
249  for (size_t nn {n} ; nn ; --nn)
250  *in++ = tx_data (0xFF, s);
251  return n;
252  }
253 
259  template <>
261  public:
263 
265  enum class Speed { STD =0, OVDR };
266 
270  protected:
272  _1wire_i () = default;
273  _1wire_i (const type&) = delete;
274  type& operator= (const type&) = delete;
275  public:
276  virtual ~_1wire_i () = default;
277 
282  private:
284  virtual Speed speed () const =0;
285  virtual void speed (Speed) =0;
286  virtual bool bit () =0;
287  virtual bool bit (bool) =0;
288  virtual bool _reset (Speed) =0;
289 
294  private:
296  enum Command {
297  CMD_READ_ROM = 0x33,
299  CMD_MATCH = 0x55,
301  CMD_SKIP = 0xCC,
304  };
305  template <typename _T> friend byte_t _1wire_i_det::_touch (_T&, byte_t, typename _T::Speed);
306  template <typename _T> friend void _1wire_i_det::_match (_T& obj, _1wire_id_t& id, typename _T::Speed s);
307  template <typename _T> friend void _1wire_i_det::_match_n_ovdr (_T& obj, _1wire_id_t& id);
308  template <typename _T> friend void _1wire_i_det::_skip (_T& obj, typename _T::Speed s);
309  template <typename _T> friend void _1wire_i_det::_skip_n_ovdr (_T& obj);
310  template <typename _T> friend _1wire_id_t _1wire_i_det::_first (_T&, typename _T::Speed, bool);
311  template <typename _T> friend _1wire_id_t _1wire_i_det::_next (_T&, typename _T::Speed, bool);
313 
317  public:
327  bool reset (Speed s = Speed::STD) {
328  return _reset (s);
329  }
330 
338  return _1wire_i_det::_touch (*this, out, s);
339  }
340 
349  size_t tx_data (const byte_t *out, byte_t *in, size_t n, Speed s = Speed::STD);
356  return _1wire_i_det::_touch (*this, 0xFF, s);
357  }
365  size_t rx_data (byte_t *in, size_t n, Speed s = Speed::STD);
366 
372  void match (_1wire_id_t& id, Speed s = Speed::STD) {
373  _1wire_i_det::_match (*this, id, s);
374  }
381  _1wire_i_det::_match_n_ovdr (*this, id);
382  }
387  void skip (Speed s = Speed::STD) {
388  _1wire_i_det::_skip (*this, s);
389  }
393  void skip_n_ovdr () {
395  }
396 
406  _1wire_id_t first (Speed s = Speed::STD, bool alarm =false) {
407  return _1wire_i_det::_first (*this, s, alarm);
408  }
419  _1wire_id_t next (Speed s = Speed::STD, bool alarm =false) {
420  return _1wire_i_det::_next (*this, s, alarm);
421  }
423 
424  private:
437  };
438 
439 
440  size_t _1wire_i<virtual_tag>::tx_data (const byte_t *out, byte_t *in, size_t n, Speed s){
441  for (size_t nn {n} ; nn ; --nn)
442  *in++ = tx_data (*out++, s);
443  return n;
444  }
445 
446  size_t _1wire_i<virtual_tag>::rx_data(byte_t *in, size_t n, Speed s) {
447  for (size_t nn {n} ; nn ; --nn)
448  *in++ = tx_data (0xFF, s);
449  return n;
450  }
451 
455 namespace _1wire_i_det {
457 
466  template <typename _T>
467  byte_t _touch (_T& obj, byte_t out, typename _T::Speed s) {
468  byte_t ret {0};
469 
470  // Select speed once
471  if (obj.speed () != s)
472  obj.speed (s);
473  for (uint8_t i =8; i>0 ; --i) {
474  ret >>= 1;
475  ret |= (obj.bit (out & 0x01)) ? 0x80 : 0x00;
476  out >>= 1;
477  /*^
478  * We shift bits to right as LSB comes first and mask it to MSB
479  * If we need to read we have to write 1
480  */
481  }
482  return ret;
483  }
484 
485 
492  template <typename _T>
493  void _match (_T& obj, _1wire_id_t& id, typename _T::Speed s) {
494  _touch (obj, (s == _T::Speed::STD) ? _T::CMD_MATCH : _T::CMD_OVDR_MATCH, s);
495  for (uint8_t& b : id)
496  _touch (obj, b, s);
497  }
498 
504  template <typename _T>
505  void _match_n_ovdr (_T& obj, _1wire_id_t& id) {
506  _touch (obj, _T::CMD_MATCH, _T::Speed::STD);
507  for (uint8_t& b : id)
508  _touch (obj, b, _T::Speed::OVDR);
509  }
510 
516  template <typename _T>
517  void _skip (_T& obj, typename _T::Speed s) {
518  _touch (obj, (s == _T::Speed::STD) ? _T::CMD_SKIP : _T::CMD_SKIP, s);
519  }
520 
525  template <typename _T>
526  void _skip_n_ovdr (_T& obj) {
527  _touch (obj, _T::CMD_OVDR_SKIP, _T::Speed::STD);
528  }
529 
539  template <typename _T>
540  _1wire_id_t _first (_T& obj, typename _T::Speed s, bool alarm) {
541  obj.dec_ = obj.pos_ = obj.cur_ = _1wire_id_t::nullDev();
542  return _next (obj, s, alarm);
543  }
544 
555  template <typename _T>
556  _1wire_id_t _next (_T& obj, typename _T::Speed s, bool alarm) {
557  uint8_t b, bxx; // bit helper vars
558  uint8_t i;
559  _1wire_id_t ID;
560 
561  do {
562  if ((obj.pos_ != _1wire_id_t::nullDev()) && (obj.dec_ >= obj.pos_)) {
563  // dec_ == pos_: We have found all the leafs, already
564  // dec_ > pos_ : Error
565  ID = _1wire_id_t::nullDev();
566  break;
567  }
568  if (!obj.reset (s)) {
569  ID = _1wire_id_t::nullDev();
570  break;
571  }
572  // Issue search command
573  if (alarm) obj.tx_data (_T::CMD_ALARM_SEARCH, s);
574  else obj.tx_data (_T::CMD_SEARCH_ROM, s);
575 
576  // Select speed once
577  if (obj.speed () != s)
578  obj.speed (s);
579 
580  // traverse entire RomID from LSB to MSB
581  for (i =0 ; i<64 ; ++i) {
582  // Get response pair bits
583  bxx = obj.bit (1); // bit
584  bxx <<= 1;
585  bxx |= obj.bit (1); // complementary bit
586 
587  if (bxx == 0x00) {
588  // 00 - We have discrepancy
589  obj.cur_.bit (i, 1);
590  switch (_1wire_id_t::compare (obj.pos_, obj.cur_)) {
591  default:
592  case -1:
593  // pos_ < cur_: This discrepancy is the most far for now. Mark position and select 0.
594  b = 0;
595  //dec_.bit (i, (b = 0)); //<-- Its already 0
596  obj.pos_.bit (i, 1);
597  break;
598  case 0:
599  // pos_ == cur_: This was the last discrepancy in the last pass.
600  // Select the other branch this time (1)
601  obj.dec_.bit (i, (b = 1));
602  break;
603  case 1:
604  // pos_ > cur_: We had a discrepancy in a MSB than that, in a previous pass.
605  // Continue with the last pass decision.
606  b = obj.dec_.bit (i);
607  break;
608  }
609  // Send selection and update romid
610  obj.bit (b);
611  ID.bit (i, b);
612  }
613  else if (bxx == 0x01) {
614  // 01 - All bits of all ROMs are 0s
615  obj.bit (0);
616  ID.bit (i, 0);
617 
618  }
619  else if (bxx == 0x02) {
620  // 10 - All bits of all ROMs are 1s
621  obj.bit (1);
622  ID.bit (i, 1);
623  }
624  else {
625  // 11 - No device on the bus
626  ID = _1wire_id_t::nullDev();
627  break;
628  }
629  } // for
630 
631  if (i == 64 && obj.pos_ == _1wire_id_t::nullDev()) {
632  // Mark done with only one device
633  obj.pos_.bit (0, 1);
634  obj.dec_.bit (0, 1);
635  }
636  } while (0);
637 
638  return ID;
639  }
640 } // namespace _1wire_i_det
642 
643 
644 #if defined _utl_have_concepts
645 
648  template <typename T>
649  concept bool _1Wire_i = requires (T t, typename T::Speed s, _1wire_id_t id) {
650  // Object type
651  requires not_<std::is_copy_constructible<T>::value>::value;
652  requires not_<std::is_copy_assignable<T>::value>::value;
653  // Members
654 // typename T::Speed;
655 // typename T::Command;
656  // Methods
657  {t.reset(s)} -> bool;
658  {t.tx_data(1)} -> byte_t;
659  {t.rx_data(s)} -> byte_t;
660  t.match(id, s);
661  t.match_n_ovdr(id);
662  t.skip(s);
663  t.skip_n_ovdr();
664  {t.first(s)} -> _1wire_id_t;
665  {t.next(s)} -> _1wire_id_t;
666  };
667 #else
668  namespace _1wire_i_det {
669  using std::declval;
670 
671  template <class _Tp> using try_reset_t = decltype (declval<_Tp>().reset (declval<typename _Tp::Speed>()));
672  template <class _Tp> using try_rx1_t = decltype (declval<_Tp>().rx_data (declval<typename _Tp::Speed>()));
673  template <class _Tp> using try_tx1_t = decltype (declval<_Tp>().tx_data (declval<byte_t>(), declval<typename _Tp::Speed>()));
674 
675  template <class _Tp> using try_match_t = decltype (declval<_Tp>().match (declval<_1wire_id_t&>(), declval<typename _Tp::Speed>()));
676  template <class _Tp> using try_match_n_ovdr_t = decltype (declval<_Tp>().match_n_ovdr (declval<_1wire_id_t&>()));
677  template <class _Tp> using try_skip_t = decltype (declval<_Tp>().skip (declval<typename _Tp::Speed>()));
678  template <class _Tp> using try_skip_n_ovdr_t = decltype (declval<_Tp>().skip_n_ovdr ());
679  template <class _Tp> using try_first_t = decltype (declval<_Tp>().first (declval<typename _Tp::Speed>()));
680  template <class _Tp> using try_next_t = decltype (declval<_Tp>().next (declval<typename _Tp::Speed>()));
681 
683  template <typename _Tp, typename =void>
684  struct is_1wire_ : meta::false_ {};
685 
687  template <typename _Tp>
688  struct is_1wire_ <_Tp,
689  meta::void_t <
690 // typename _Tp::Speed,
691 // typename _Tp::Command,
692 // meta::use_if_same_t <try_reset_t <_Tp>, bool>,
693 // meta::use_if_same_t <try_rx1_t <_Tp>, byte_t>,
694 // //meta::use_if_same_t <try_rx2_t <_Tp>, size_t>,
695 // meta::use_if_same_t <try_tx1_t <_Tp>, byte_t>,
696 // //meta::use_if_same_t <try_tx2_t <_Tp>, size_t>,
697 // meta::use_if_same_t <try_match_t<_Tp>, void>,
698 // meta::use_if_same_t <try_match_n_ovdr_t<_Tp>, void>,
699 // meta::use_if_same_t <try_skip_t<_Tp>, void>,
700 // meta::use_if_same_t <try_skip_n_ovdr_t<_Tp>, void>,
701 // meta::use_if_same_t <try_first_t <_Tp>, _1wire_id_t>,
702 // meta::use_if_same_t <try_next_t <_Tp>, _1wire_id_t>
703  void
704  >
705  > : meta::true_ {};
706  } // namespace _1wire_i_det
707 
713 // template <typename _Tp>
714 // constexpr bool _1Wire_i = _1wire_i_det::is_1wire_<_Tp>::value;
715 #endif
716 
718 } //namespace utl
719 
720 #endif /* __utl_com_1wire_h__ */
_1wire_id_t first(Speed s=Speed::STD, bool alarm=false)
&#39;first&#39; operation, to search on the 1-Wire for the first device. This is performed by setting dec_...
Definition: _1wire.h:207
Include all meta library.
bool bit(bool b)
Write a bit to the 1-Wire bus, return response/write status and provide the recovery time...
Definition: _1wire.h:88
void void_t
void_t type alias
Definition: detection.h:55
void match_n_ovdr(_1wire_id_t &id)
Definition: _1wire.h:181
decltype(declval< _Tp >().match_n_ovdr(declval< _1wire_id_t & >())) try_match_n_ovdr_t
Definition: _1wire.h:676
Primary template to catch any non 1-wire interface types.
Definition: _1wire.h:684
void match(_1wire_id_t &id, Speed s=Speed::STD)
Definition: _1wire.h:173
bool _reset(Speed s)
Definition: _1wire.h:89
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
static int compare(const _1wire_id_t &lhs, const _1wire_id_t &rhs) noexcept
Full compare two dev_ids.
Definition: _1wire_id.h:72
decltype(declval< _Tp >().match(declval< _1wire_id_t & >(), declval< typename _Tp::Speed >())) try_match_t
Definition: _1wire.h:675
void match(_1wire_id_t &id, Speed s=Speed::STD)
Definition: _1wire.h:372
void speed(Speed s)
Definition: _1wire.h:86
void _match_n_ovdr(_T &obj, _1wire_id_t &id)
Definition: _1wire.h:505
Speed
1-wire bus speed
Definition: _1wire.h:64
byte_t tx_data(byte_t out, Speed s=Speed::STD)
Definition: _1wire.h:138
byte_t rx_data(Speed s=Speed::STD)
Definition: _1wire.h:156
_1wire_id_t _first(_T &obj, typename _T::Speed s, bool alarm)
&#39;first&#39; operation, to search on the 1-Wire for the first device. This is performed by setting dec_...
Definition: _1wire.h:540
bool reset(Speed s=Speed::STD)
Generate a 1-wire reset.
Definition: _1wire.h:128
_CRTP_IMPL(impl_t)
_1wire_id_t _next(_T &obj, typename _T::Speed s, bool alarm)
&#39;next&#39; operation, to search on the 1-Wire for the next device. This search is usually performed after...
Definition: _1wire.h:556
_1wire_id_t next(Speed s=Speed::STD, bool alarm=false)
&#39;next&#39; operation, to search on the 1-Wire for the next device. This search is usually performed after...
Definition: _1wire.h:419
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
An 1-wire Rom ID type.
A virtual base class implementation.
Definition: _1wire.h:260
bool reset(Speed s=Speed::STD)
Generate a 1-wire reset.
Definition: _1wire.h:327
_1wire_id_t first(Speed s=Speed::STD, bool alarm=false)
&#39;first&#39; operation, to search on the 1-Wire for the first device. This is performed by setting dec_...
Definition: _1wire.h:406
STL&#39;s core language concepts.
Definition: _1wire.h:30
decltype(declval< _Tp >().skip(declval< typename _Tp::Speed >())) try_skip_t
Definition: _1wire.h:677
void match_n_ovdr(_1wire_id_t &id)
Definition: _1wire.h:380
_1wire_id_t pos_
Definition: _1wire.h:232
byte_t rx_data(Speed s=Speed::STD)
Definition: _1wire.h:355
decltype(declval< _Tp >().tx_data(declval< byte_t >(), declval< typename _Tp::Speed >())) try_tx1_t
Definition: _1wire.h:673
void _skip_n_ovdr(_T &obj)
Definition: _1wire.h:526
_1wire_i type
Export type as identity meta-function.
Definition: _1wire.h:61
void skip(Speed s=Speed::STD)
Definition: _1wire.h:188
decltype(declval< _Tp >().skip_n_ovdr()) try_skip_n_ovdr_t
Definition: _1wire.h:678
Speed speed() const
Get the 1-wire bus speed.
Definition: _1wire.h:85
decltype(declval< _Tp >().first(declval< typename _Tp::Speed >())) try_first_t
Definition: _1wire.h:679
byte_t tx_data(byte_t out, Speed s=Speed::STD)
Definition: _1wire.h:337
_1wire_i & operator=(const _1wire_i &)=delete
void skip(Speed s=Speed::STD)
Definition: _1wire.h:387
static constexpr const _1wire_id_t & nullDev()
Return nullDev reference.
Definition: _1wire_id.h:50
~_1wire_i()=default
Allow destructor from derived only.
_1wire_id_t next(Speed s=Speed::STD, bool alarm=false)
&#39;next&#39; operation, to search on the 1-Wire for the next device. This search is usually performed after...
Definition: _1wire.h:220
decltype(declval< _Tp >().rx_data(declval< typename _Tp::Speed >())) try_rx1_t
Definition: _1wire.h:672
Template base class for 1-wire communication interface using CRTP.
Definition: _1wire.h:57
uint8_t byte_t
8 bits wide
Definition: types.h:31
virtual support tag type
Definition: crtp.h:40
void skip_n_ovdr()
Definition: _1wire.h:194
decltype(declval< _Tp >().reset(declval< typename _Tp::Speed >())) try_reset_t
Definition: _1wire.h:671
void _skip(_T &obj, typename _T::Speed s)
Definition: _1wire.h:517
decltype(declval< _Tp >().next(declval< typename _Tp::Speed >())) try_next_t
Definition: _1wire.h:680
Implementation detail main forward header.
_1wire_id_t cur_
Definition: _1wire.h:237
void _match(_T &obj, _1wire_id_t &id, typename _T::Speed s)
Definition: _1wire.h:493
_1wire_id_t dec_
Definition: _1wire.h:226
Speed
1-wire bus speed
Definition: _1wire.h:265
_1wire_i()=default
Allow constructor from derived only.
constexpr bool bit(uint8_t bit) const noexcept
Definition: id.h:159
byte_t _touch(_T &obj, byte_t out, typename _T::Speed s)
Write a byte to 1-Wire bus and read the response.
Definition: _1wire.h:467