From de4eb2cf097eb1b948e93714f68bce4d966d8ae3 Mon Sep 17 00:00:00 2001 From: Christos Houtouridis Date: Sat, 27 Oct 2018 23:17:55 +0300 Subject: [PATCH] com: A 1-wire interface rework --- include/utl/com/_1wire.h | 465 +++++++++++++++++----------------- include/utl/com/_1wire_uart.h | 173 ++++--------- include/utl/container/id.h | 2 +- 3 files changed, 286 insertions(+), 354 deletions(-) diff --git a/include/utl/com/_1wire.h b/include/utl/com/_1wire.h index 0fa34c9..877a5e4 100644 --- a/include/utl/com/_1wire.h +++ b/include/utl/com/_1wire.h @@ -26,19 +26,28 @@ #include #include -#include -using gsl::span; namespace utl { - - /*! * \ingroup Communication * \brief Abstract base class interface for 1-wire bus */ //!@{ + /*! + * \name Friend API to provide common functionality to all specializations + */ + namespace _1wire_i_det { + template byte_t _touch (_T& obj, byte_t out, typename _T::Speed s); + template void _match (_T& obj, _1wire_id_t& id, typename _T::Speed s); + template void _match_n_ovdr (_T& obj, _1wire_id_t& id); + template void _skip (_T& obj, typename _T::Speed s); + template void _skip_n_ovdr (_T& obj); + template _1wire_id_t _first (_T& obj, typename _T::Speed s, bool alarm); + template _1wire_id_t _next (_T& obj, typename _T::Speed s, bool alarm); + } + /*! * \brief * Template base class for 1-wire communication interface using CRTP @@ -73,11 +82,11 @@ namespace utl { */ //!@{ private: - Speed speed () { return impl().speed(); } //!< Get the 1-wire bus speed + Speed speed () const { return impl().speed(); } //!< Get the 1-wire bus speed void speed (Speed s) { return impl().speed(s); } //!< Set the 1-wire bus speed - bool bit () { return impl().bit(); } //!< Read a bit from the 1-Wire bus, return it and provide the recovery time. - bool bit (bool b) { return impl().bit(b); } //!< Write a bit to the 1-Wire bus, return write status and provide the recovery time. - bool _reset () { return impl()._reset(); } //!< Generate a 1-wire reset and return the operation status + //! Write a bit to the 1-Wire bus, return response/write status and provide the recovery time. + bool bit (bool b) { return impl().bit(b); } + bool _reset (Speed s){ return impl()._reset(s); } //!< Generate a 1-wire reset and return the operation status //!@} /*! @@ -94,18 +103,13 @@ namespace utl { CMD_ALARM_SEARCH = 0xEC, CMD_SEARCH_ROM = 0xF0 }; - template friend bool _1wire_i_reset (_T&, typename _T::Speed); - template friend byte_t _1wire_i_rw (_T&, byte_t, typename _T::Speed); - template friend byte_t _1wire_i_rx (_T&, typename _T::Speed); - template friend size_t _1wire_i_rx (_T&, span, typename _T::Speed); - template friend size_t _1wire_i_tx (_T&, byte_t, typename _T::Speed); - template friend size_t _1wire_i_tx (_T&, const span, typename _T::Speed); - template friend void _1wire_i_match (_T& obj, _1wire_id_t& id, typename _T::Speed s); - template friend void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id); - template friend void _1wire_i_skip (_T& obj, typename _T::Speed s); - template friend void _1wire_i_skip_n_ovdr (_T& obj); - template friend _1wire_id_t _1wire_i_first (_T&, typename _T::Speed, bool); - template friend _1wire_id_t _1wire_i_next (_T&, typename _T::Speed, bool); + template friend byte_t _1wire_i_det::_touch (_T&, byte_t, typename _T::Speed); + template friend void _1wire_i_det::_match (_T& obj, _1wire_id_t& id, typename _T::Speed s); + template friend void _1wire_i_det::_match_n_ovdr (_T& obj, _1wire_id_t& id); + template friend void _1wire_i_det::_skip (_T& obj, typename _T::Speed s); + template friend void _1wire_i_det::_skip_n_ovdr (_T& obj); + template friend _1wire_id_t _1wire_i_det::_first (_T&, typename _T::Speed, bool); + template friend _1wire_id_t _1wire_i_det::_next (_T&, typename _T::Speed, bool); //!@} /*! @@ -121,39 +125,75 @@ namespace utl { * \arg 0 Fail * \arg 1 Success */ - bool reset (Speed s) { return _1wire_i_reset (*this, s); }; - //! Read a byte from 1-Wire bus - //! @param s The bus speed - //! @return The received byte - byte_t read (Speed s) { return _1wire_i_rx (*this, s); } - //! Read a span of bytes from 1-wire bus - //! \param data Ref to data span - //! \param s The speed to use - //! \return The number of received bytes - size_t read (span data, Speed s) { return _1wire_i_rx (*this, data, s); } - //! \brief Write a byte to 1-Wire bus - //! \param b The byte to write - //! \param s Bus speed to use - //! \return The number of transmitted bytes - size_t write (byte_t byte, Speed s) { return _1wire_i_tx (*this, byte, s); } - //! \brief Write a span of bytes to 1-wire bus - //! \param data Ref to data span - //! \param s Bus speed to use - //! \return The number of transmitted bytes - size_t write (const span data, Speed s) { return _1wire_i_tx (*this, data, s); } + bool reset (Speed s = Speed::STD) { + return _reset (s); + } + + /*! + * Transmit a byte to 1-Wire bus and read the response + * \param out The byte to write + * \param s Bus speed to use + * \return The byte received. + */ + byte_t tx_data (byte_t out, Speed s = Speed::STD) { + return _1wire_i_det::_touch (*this, out, s); + } + /*! - * \brief - * Write a byte to 1-Wire bus and read the response - * \param b The byte to write + * Transmit a number of bytes to 1-wire bus and read the response + * \param out Pointer to data to transmit + * \param in Pointer to data to store + * \param n Number of bytes + * \param s Speed to use + * \return The number of transmitted bytes + */ + size_t tx_data (const byte_t *out, byte_t *in, size_t n, Speed s = Speed::STD); + /*! + * Receive a byte from 1-Wire bus while transmitting 0xFF * \param s Bus speed to use * \return The byte received. */ - byte_t rw (byte_t b, Speed s) { return _1wire_i_rw (*this, b, s); } + byte_t rx_data (Speed s = Speed::STD) { + return _1wire_i_det::_touch (*this, 0xFF, s); + } + /*! + * Receive a number of bytes from 1-wire bus while transmitting 0xFFs + * \param in Pointer to data to store + * \param n Number of bytes + * \param s Speed to use + * \return The number of transmitted bytes + */ + size_t rx_data (byte_t *in, size_t n, Speed s = Speed::STD); - void match (_1wire_id_t& id, Speed s) { _1wire_i_match (*this, id, s); } - void match_n_ovdr (_1wire_id_t& id) { _1wire_i_match_n_ovdr (*this, id); } - void skip (Speed s) { _1wire_i_skip (*this, s); } - void skip_n_ovdr () { _1wire_i_skip_n_ovdr (*this); } + /*! + * Send match rom command + * \param id The ID to select on the bus + * \param s The speed to use for the command + */ + void match (_1wire_id_t& id, Speed s = Speed::STD) { + _1wire_i_det::_match (*this, id, s); + } + /*! + * Match and overdrive sequence + * \param obj The object from which we call private members + * \param id The ID to select on the bus + */ + void match_n_ovdr (_1wire_id_t& id) { + _1wire_i_det::_match_n_ovdr (*this, id); + } + /*! + * Send skip command to the bus + * \param id The ID to select on the bus + */ + void skip (Speed s = Speed::STD) { + _1wire_i_det::_skip (*this, s); + } + /*! + * Send the Skip and Overdrive sequence + */ + void skip_n_ovdr () { + _1wire_i_det::_skip_n_ovdr (*this); + } /*! * \brief @@ -164,7 +204,9 @@ namespace utl { * \return ID The romID * \arg nullDev Indicate no [more] device[s] */ - _1wire_id_t first (Speed s, bool alarm =false) { return _1wire_i_first (*this, s, alarm); } + _1wire_id_t first (Speed s = Speed::STD, bool alarm =false) { + return _1wire_i_det::_first (*this, s, alarm); + } /*! * \brief * 'next' operation, to search on the 1-Wire for the next device. @@ -175,10 +217,11 @@ namespace utl { * \return ID The romID * \arg nullDev Indicate no [more] device[s] */ - _1wire_id_t next (Speed s, bool alarm =false) { return _1wire_i_next (*this, s, alarm); } + _1wire_id_t next (Speed s = Speed::STD, bool alarm =false) { + return _1wire_i_det::_next (*this, s, alarm); + } //!@} - private: _1wire_id_t dec_ {_1wire_id_t::nullDev()}; /*!< * Hold the algorithm's select bit when a discrepancy @@ -194,7 +237,19 @@ namespace utl { _1wire_id_t cur_ {_1wire_id_t::nullDev()}; //! Current rom discrepancy state }; + template + size_t _1wire_i<_I>::tx_data (const byte_t *out, byte_t *in, size_t n, Speed s){ + for (size_t nn {n} ; nn ; --nn) + *in++ = tx_data (*out++, s); + return n; + } + template + size_t _1wire_i<_I>::rx_data(byte_t *in, size_t n, Speed s) { + for (size_t nn {n} ; nn ; --nn) + *in++ = tx_data (0xFF, s); + return n; + } /*! * \brief @@ -226,11 +281,11 @@ namespace utl { */ //!@{ private: - virtual Speed speed () =0; //!< Get the 1-wire bus speed + virtual Speed speed () const =0; //!< Get the 1-wire bus speed virtual void speed (Speed) =0; //!< Set the 1-wire bus speed virtual bool bit () =0; //!< Read a bit from the 1-Wire bus, return it and provide the recovery time. virtual bool bit (bool) =0; //!< Write a bit to the 1-Wire bus, return write status and provide the recovery time. - virtual bool _reset () =0; //!< Generate a 1-wire reset and return the operation status + virtual bool _reset (Speed) =0; //!< Generate a 1-wire reset and return the operation status //!@} /*! @@ -247,18 +302,13 @@ namespace utl { CMD_ALARM_SEARCH = 0xEC, CMD_SEARCH_ROM = 0xF0 }; - template friend bool _1wire_i_reset (_T&, typename _T::Speed); - template friend byte_t _1wire_i_rw (_T&, byte_t, typename _T::Speed); - template friend byte_t _1wire_i_rx (_T&, typename _T::Speed); - template friend size_t _1wire_i_rx (_T&, span, typename _T::Speed); - template friend size_t _1wire_i_tx (_T&, byte_t, typename _T::Speed); - template friend size_t _1wire_i_tx (_T&, const span, typename _T::Speed); - template friend void _1wire_i_match (_T& obj, _1wire_id_t& id, typename _T::Speed s); - template friend void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id); - template friend void _1wire_i_skip (_T& obj, typename _T::Speed s); - template friend void _1wire_i_skip_n_ovdr (_T& obj); - template friend _1wire_id_t _1wire_i_first (_T&, typename _T::Speed, bool); - template friend _1wire_id_t _1wire_i_next (_T&, typename _T::Speed, bool); + template friend byte_t _1wire_i_det::_touch (_T&, byte_t, typename _T::Speed); + template friend void _1wire_i_det::_match (_T& obj, _1wire_id_t& id, typename _T::Speed s); + template friend void _1wire_i_det::_match_n_ovdr (_T& obj, _1wire_id_t& id); + template friend void _1wire_i_det::_skip (_T& obj, typename _T::Speed s); + template friend void _1wire_i_det::_skip_n_ovdr (_T& obj); + template friend _1wire_id_t _1wire_i_det::_first (_T&, typename _T::Speed, bool); + template friend _1wire_id_t _1wire_i_det::_next (_T&, typename _T::Speed, bool); //!@} /*! @@ -274,39 +324,75 @@ namespace utl { * \arg 0 Fail * \arg 1 Success */ - bool reset (Speed s) { return _1wire_i_reset (*this, s); }; - //! Read a byte from 1-Wire bus - //! @param s The bus speed - //! @return The received byte - byte_t read (Speed s) { return _1wire_i_rx (*this, s); } - //! Read a span of bytes from 1-wire bus - //! \param data Ref to data span - //! \param s The speed to use - //! \return The number of received bytes - size_t read (span data, Speed s) { return _1wire_i_rx (*this, data, s); } - //! \brief Write a byte to 1-Wire bus - //! \param b The byte to write - //! \param s Bus speed to use - //! \return The number of transmitted bytes - size_t write (byte_t byte, Speed s) { return _1wire_i_tx (*this, byte, s); } - //! \brief Write a span of bytes to 1-wire bus - //! \param data Ref to data span - //! \param s Bus speed to use - //! \return The number of transmitted bytes - size_t write (const span data, Speed s) { return _1wire_i_tx (*this, data, s); } + bool reset (Speed s = Speed::STD) { + return _reset (s); + } + + /*! + * Transmit a byte to 1-Wire bus and read the response + * \param out The byte to write + * \param s Bus speed to use + * \return The byte received. + */ + byte_t tx_data (byte_t out, Speed s = Speed::STD) { + return _1wire_i_det::_touch (*this, out, s); + } + /*! - * \brief - * Write a byte to 1-Wire bus and read the response - * \param b The byte to write + * Transmit a number of bytes to 1-wire bus and read the response + * \param out Pointer to data to transmit + * \param in Pointer to data to store + * \param n Number of bytes + * \param s Speed to use + * \return The number of transmitted bytes + */ + size_t tx_data (const byte_t *out, byte_t *in, size_t n, Speed s = Speed::STD); + /*! + * Receive a byte from 1-Wire bus while transmitting 0xFF * \param s Bus speed to use * \return The byte received. */ - byte_t rw (byte_t b, Speed s) { return _1wire_i_rw (*this, b, s); } + byte_t rx_data (Speed s = Speed::STD) { + return _1wire_i_det::_touch (*this, 0xFF, s); + } + /*! + * Receive a number of bytes from 1-wire bus while transmitting 0xFFs + * \param in Pointer to data to store + * \param n Number of bytes + * \param s Speed to use + * \return The number of transmitted bytes + */ + size_t rx_data (byte_t *in, size_t n, Speed s = Speed::STD); - void match (_1wire_id_t& id, Speed s) { _1wire_i_match (*this, id, s); } - void match_n_ovdr (_1wire_id_t& id) { _1wire_i_match_n_ovdr (*this, id); } - void skip (Speed s) { _1wire_i_skip (*this, s); } - void skip_n_ovdr () { _1wire_i_skip_n_ovdr (*this); } + /*! + * Send match rom command + * \param id The ID to select on the bus + * \param s The speed to use for the command + */ + void match (_1wire_id_t& id, Speed s = Speed::STD) { + _1wire_i_det::_match (*this, id, s); + } + /*! + * Match and overdrive sequence + * \param obj The object from which we call private members + * \param id The ID to select on the bus + */ + void match_n_ovdr (_1wire_id_t& id) { + _1wire_i_det::_match_n_ovdr (*this, id); + } + /*! + * Send skip command to the bus + * \param id The ID to select on the bus + */ + void skip (Speed s = Speed::STD) { + _1wire_i_det::_skip (*this, s); + } + /*! + * Send the Skip and Overdrive sequence + */ + void skip_n_ovdr () { + _1wire_i_det::_skip_n_ovdr (*this); + } /*! * \brief @@ -317,7 +403,9 @@ namespace utl { * \return ID The romID * \arg nullDev Indicate no [more] device[s] */ - _1wire_id_t first (Speed s, bool alarm =false) { return _1wire_i_first (*this, s, alarm); } + _1wire_id_t first (Speed s = Speed::STD, bool alarm =false) { + return _1wire_i_det::_first (*this, s, alarm); + } /*! * \brief * 'next' operation, to search on the 1-Wire for the next device. @@ -328,10 +416,11 @@ namespace utl { * \return ID The romID * \arg nullDev Indicate no [more] device[s] */ - _1wire_id_t next (Speed s, bool alarm =false) { return _1wire_i_next (*this, s, alarm); } + _1wire_id_t next (Speed s = Speed::STD, bool alarm =false) { + return _1wire_i_det::_next (*this, s, alarm); + } //!@} - private: _1wire_id_t dec_ {_1wire_id_t::nullDev()}; /*!< * Hold the algorithm's select bit when a discrepancy @@ -348,27 +437,24 @@ namespace utl { }; - /*! - * \name Friend API to provide common functionality to all specializations - */ - //!@{ + size_t _1wire_i::tx_data (const byte_t *out, byte_t *in, size_t n, Speed s){ + for (size_t nn {n} ; nn ; --nn) + *in++ = tx_data (*out++, s); + return n; + } - /*! - * \brief - * Generate a 1-wire reset - * \param obj The object from which we call private members - * \param s Bus speed - * \return The status of the operation - * \arg 0 Fail - * \arg 1 Success - */ - template - bool _1wire_i_reset (_T& obj, typename _T::Speed s) { - if (obj.speed () != s) - obj.speed (s); - return obj._reset (); + size_t _1wire_i::rx_data(byte_t *in, size_t n, Speed s) { + for (size_t nn {n} ; nn ; --nn) + *in++ = tx_data (0xFF, s); + return n; } +/*! + * \name Friend API to provide common functionality to all specializations + */ +//!@{ +namespace _1wire_i_det { + /*! * \brief * Write a byte to 1-Wire bus and read the response @@ -378,7 +464,7 @@ namespace utl { * \return The byte received. */ template - byte_t _1wire_i_rw (_T& obj, byte_t b, typename _T::Speed s) { + byte_t _touch (_T& obj, byte_t out, typename _T::Speed s) { byte_t ret {0}; // Select speed once @@ -386,90 +472,16 @@ namespace utl { obj.speed (s); for (uint8_t i =8; i>0 ; --i) { ret >>= 1; - if ((b & 0x01) != 0) ret |= (obj.bit ()) ? 0x80 : 0x00; - else obj.bit (0); - b >>= 1; + ret |= (obj.bit (out & 0x01)) ? 0x80 : 0x00; + out >>= 1; /*^ - * If the bit is 1 we use the read sequence, as it has the same - * waveform with write-1 and we get the slave response - * If the bit is 0, we can not read the slave response so we just write-0 + * We shift bits to right as LSB comes first and mask it to MSB + * If we need to read we have to write 1 */ } return ret; } - /*! - * \brief Read a byte from 1-Wire bus - * \param obj The object from which we call private members - * \param s Bus speed to use - * \return The byte received. - */ - template - byte_t _1wire_i_rx (_T& obj, typename _T::Speed s) { - byte_t byte {0}; - // Select speed once - if (obj.speed () != s) - obj.speed (s); - for (uint8_t i =8; i>0 ; --i) { - // shift bits to right as LSB comes first and mask it to MSB - byte >>= 1; - byte |= (obj.bit ()) ? 0x80 : 0x00; - } - return byte; - } - /*! - * \brief Read a span of bytes from 1-Wire bus - * \param obj The object from which we call private members - * \param data Reference to byte span - * \param s Bus speed to use - * \return The number of received bytes. Actual return data.size() - */ - template - size_t _1wire_i_rx (_T& obj, span data, typename _T::Speed s) { - // Select speed once - if (obj.speed () != s) - obj.speed (s); - for (byte_t& byte : data) { - byte = 0; - for (uint8_t i =8; i>0 ; --i) { - // shift bits to right as LSB comes first and mask it to MSB - byte >>= 1; - byte |= (obj.bit ()) ? 0x80 : 0x00; - } - } - return data.size(); - } - /*! - * \brief Write a byte to 1-Wire bus - * \param obj The object from which we call private members - * \param byte The byte to write - * \param s Bus speed to use - * \return The number of transmitted bytes. So "1" of "0" - */ - template - size_t _1wire_i_tx (_T& obj, byte_t byte, typename _T::Speed s) { - return (_1wire_i_rw (obj, byte, s) == byte) ? 1 : 0; - } - /*! - * \brief Write a byte to 1-Wire bus - * \param obj The object from which we call private members - * \param data Reference to byte span - * \param s Bus speed to use - * \return The number of transmitted bytes. - * \note - * The procedure breaks on first transmission error - */ - template - size_t _1wire_i_tx (_T& obj, const span data, typename _T::Speed s) { - size_t ret {0}; - for (byte_t byte : data) { - if (_1wire_i_rw (obj, byte, s) == byte) - ++ret; - else - break; - } - return ret; - } /*! * Send match rom command @@ -478,10 +490,10 @@ namespace utl { * \param s The speed to use for the command */ template - void _1wire_i_match (_T& obj, _1wire_id_t& id, typename _T::Speed s) { - _1wire_i_tx (obj, (s == _T::Speed::STD) ? _T::CMD_MATCH : _T::CMD_OVDR_MATCH, s); + void _match (_T& obj, _1wire_id_t& id, typename _T::Speed s) { + _touch (obj, (s == _T::Speed::STD) ? _T::CMD_MATCH : _T::CMD_OVDR_MATCH, s); for (uint8_t& b : id) - _1wire_i_tx (obj, b, s); + _touch (obj, b, s); } /*! @@ -490,10 +502,10 @@ namespace utl { * \param id The ID to select on the bus */ template - void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id) { - _1wire_i_tx (obj, _T::CMD_MATCH, _T::Speed::STD); + void _match_n_ovdr (_T& obj, _1wire_id_t& id) { + _touch (obj, _T::CMD_MATCH, _T::Speed::STD); for (uint8_t& b : id) - _1wire_i_tx (obj, b, _T::Speed::OVDR); + _touch (obj, b, _T::Speed::OVDR); } /*! @@ -502,8 +514,8 @@ namespace utl { * \param id The ID to select on the bus */ template - void _1wire_i_skip (_T& obj, typename _T::Speed s) { - _1wire_i_tx (obj, (s == _T::Speed::STD) ? _T::CMD_SKIP : _T::CMD_SKIP, s); + void _skip (_T& obj, typename _T::Speed s) { + _touch (obj, (s == _T::Speed::STD) ? _T::CMD_SKIP : _T::CMD_SKIP, s); } /*! @@ -511,8 +523,8 @@ namespace utl { * \param obj The object from which we call private members */ template - void _1wire_i_skip_n_ovdr (_T& obj) { - _1wire_i_tx (obj, _T::CMD_OVDR_SKIP, _T::Speed::STD); + void _skip_n_ovdr (_T& obj) { + _touch (obj, _T::CMD_OVDR_SKIP, _T::Speed::STD); } /*! @@ -525,9 +537,9 @@ namespace utl { * \arg nullDev Indicate no [more] device[s] */ template - _1wire_id_t _1wire_i_first (_T& obj, typename _T::Speed s, bool alarm) { + _1wire_id_t _first (_T& obj, typename _T::Speed s, bool alarm) { obj.dec_ = obj.pos_ = obj.cur_ = _1wire_id_t::nullDev(); - return _1wire_i_next (obj, s, alarm); + return _next (obj, s, alarm); } /*! @@ -541,7 +553,7 @@ namespace utl { * \arg nullDev Indicate no [more] device[s] */ template - _1wire_id_t _1wire_i_next (_T& obj, typename _T::Speed s, bool alarm) { + _1wire_id_t _next (_T& obj, typename _T::Speed s, bool alarm) { uint8_t b, bxx; // bit helper vars uint8_t i; _1wire_id_t ID; @@ -558,15 +570,19 @@ namespace utl { break; } // Issue search command - if (alarm) obj.write (_T::CMD_ALARM_SEARCH, s); - else obj.write (_T::CMD_SEARCH_ROM, s); + if (alarm) obj.tx_data (_T::CMD_ALARM_SEARCH, s); + else obj.tx_data (_T::CMD_SEARCH_ROM, s); + + // Select speed once + if (obj.speed () != s) + obj.speed (s); // traverse entire RomID from LSB to MSB for (i =0 ; i<64 ; ++i) { // Get response pair bits - bxx = obj.bit (); // bit + bxx = obj.bit (1); // bit bxx <<= 1; - bxx |= obj.bit (); // complementary bit + bxx |= obj.bit (1); // complementary bit if (bxx == 0x00) { // 00 - We have discrepancy @@ -621,7 +637,8 @@ namespace utl { return ID; } - //!@} +} // namespace _1wire_i_det +//!@} #if defined _utl_have_concepts @@ -638,9 +655,8 @@ namespace utl { // typename T::Command; // Methods {t.reset(s)} -> bool; - {t.read(s)} -> byte_t; - {t.write(0, s)} -> size_t; - {t.rw(0, s)} -> byte_t; + {t.tx_data(1)} -> byte_t; + {t.rx_data(s)} -> byte_t; t.match(id, s); t.match_n_ovdr(id); t.skip(s); @@ -649,16 +665,12 @@ namespace utl { {t.next(s)} -> _1wire_id_t; }; #else - namespace _1wire_i_cnpt { + namespace _1wire_i_det { using std::declval; template using try_reset_t = decltype (declval<_Tp>().reset (declval())); - template using try_rw_t = decltype (declval<_Tp>().rw (declval(), declval())); - template using try_rx1_t = decltype (declval<_Tp>().read (declval())); - template using try_rx2_t = decltype (declval<_Tp>().read (declval>(), declval())); - template using try_tx1_t = decltype (declval<_Tp>().write (declval(), declval())); - template using try_tx2_t = decltype (declval<_Tp>().write (declval>(), declval())); - + template using try_rx1_t = decltype (declval<_Tp>().rx_data (declval())); + template using try_tx1_t = decltype (declval<_Tp>().tx_data (declval(), declval())); template using try_match_t = decltype (declval<_Tp>().match (declval<_1wire_id_t&>(), declval())); template using try_match_n_ovdr_t = decltype (declval<_Tp>().match_n_ovdr (declval<_1wire_id_t&>())); @@ -678,11 +690,10 @@ namespace utl { // typename _Tp::Speed, // typename _Tp::Command, use_if_same_t , bool>, - use_if_same_t , byte_t>, use_if_same_t , byte_t>, - use_if_same_t , size_t>, - use_if_same_t , size_t>, - use_if_same_t , size_t>, + //use_if_same_t , size_t>, + use_if_same_t , byte_t>, + //use_if_same_t , size_t>, use_if_same_t , void>, use_if_same_t , void>, use_if_same_t , void>, @@ -691,7 +702,7 @@ namespace utl { use_if_same_t , _1wire_id_t> > //!^ SFINAE may apply > : true_ {}; - } + } // namespace _1wire_i_det /*! * Value meta-programming function for 1-wire interface checking @@ -699,7 +710,7 @@ namespace utl { * \return True if _Tp is a 1-wire interface */ template - constexpr bool _1wire_c = _1wire_i_cnpt::is_1wire_<_Tp>::value; + constexpr bool _1wire_c = _1wire_i_det::is_1wire_<_Tp>::value; #endif //!@} diff --git a/include/utl/com/_1wire_uart.h b/include/utl/com/_1wire_uart.h index 546d19b..18876ab 100644 --- a/include/utl/com/_1wire_uart.h +++ b/include/utl/com/_1wire_uart.h @@ -3,9 +3,9 @@ * \brief * A 1-wire implementation using a microprocessor's uart for bit timing * \note - * This 1-wire implementation is based on MCU UART io functionality. In order - * to work it needs: - * 1) A Open drain tx and floating(or pull-up) rx UART pin configuration with both pins + * This 1-wire implementation is based on MCU UART functionality. The implementation + * expects: + * 1) An Open drain tx and a floating(or pull-up) rx UART pin configuration with both pins * connected to the 1-wire bus wire * 2) A Transmit/receive function even in blocking/polling mode * 3) A baudrate set function @@ -70,19 +70,13 @@ namespace utl { * \note * In order for the implementation to have the following as private members * it also need to declare this class as friend - * for ex: - * class Foo : public _1wire_uart { - * friend _1wire_uart; - * byte_t UART_RW (byte_t byte); - * void UART_BR (uint32_t br); - * // ... - * }; */ //!@{ private: /*! * \brief - * Implementers's (driver) read-write function. We use the following USART configuration. + * Implementers's (driver) read-write function. We expect the following + * USART configuration: * - Word Length = 8 Bits * - Stop Bit = One Stop bit * - Parity = No parity @@ -114,55 +108,22 @@ namespace utl { }; Speed _speed {Speed::STD}; - Speed speed () { return _speed; } //!< Get the 1-wire bus speed - void speed (Speed s); //!< Set the 1-wire bus speed + Speed speed () const { return _speed; } //!< Get the 1-wire bus speed + void speed (Speed s); //!< Set the 1-wire bus speed /*! * \brief - * Read a bit from the 1-Wire bus, return it and provide - * the recovery time. + * Send a 1-Wire write bit and read the response * - * --- - - - - - - - - - - - - - - - - ------ - * Read \ / X X X X X X X X X X X X X X X / - * ---- - - - - - - - - - - - - - - - - - * RS: | | | | | | | | | | | - * bit: ST 0 1 2 3 4 5 6 7 SP - * < ------------- 87/11 usec -------------> - * ^ - * | - * Master sample - * - * 8 bits, no parity, 1 stop - * standard: BR: 115200 - * Overdrive: BR: 921600 - * TX: 0xFF - * RX: {1 - 0xFF, 0 - [0x00 - 0xFE] } - * - * \return The answer - * \arg 0 Read 0 - * \arg 1 Read 1 (This is also returned on transition error). - */ - bool bit () { - return (impl().UART_RW (0xFF) < 0xFF); - } - - - /*! - * \brief - * Send a 1-Wire write bit - * 8 bits, no parity, 1 stop - * standard: BR: 115200 - * Overdrive: BR: 921600 - * - * --- -------------------------------------- - * Write 1 \ / + * Write 1 --- -------------------------------------- + * Read 0/1 \ / * ---- * RS: | | | | | | | | | | | * bit: ST 0 1 2 3 4 5 6 7 SP - * TX: 0xFF RX: 0xFF + * TX: 0xFF RX: 0xFF->1, less->0 * - * --- ------ - * Write 0 \ / + * Write 0 --- ------ + * Read 0 \ / * ------------------------------------- * RS: | | | | | | | | | | | * bit: ST 0 1 2 3 4 5 6 7 SP @@ -170,15 +131,17 @@ namespace utl { * TX: 0x00 RX: 0x00 * * \param b The bit to send - * \return Status of the operation - * \arg 0 Fail - * \arg 1 Success + * \return The response */ bool bit (bool b) { - uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send - return (w == impl().UART_RW (w)); // Return status + if (b) + return (UART_RW (0xFF) < 0xFF) ? 0 : 1; + else { + UART_RW (0x00); + return 0; + } } - bool _reset (); + bool _reset (Speed s); //!@} }; @@ -192,15 +155,14 @@ namespace utl { template void _1wire_uart_i::speed (Speed s) { switch (_speed = s) { - case Speed::STD: impl().UART_BR (BR_STD); break; - case Speed::OVDR: impl().UART_BR (BR_OVR); break; + case Speed::STD: UART_BR (BR_STD); break; + case Speed::OVDR: UART_BR (BR_OVR); break; } } /*! * \brief * Generate a 1-wire reset - * * --- ---- - - - ------- * Reset \ / \ X X X / * -------------------- - - - - @@ -208,12 +170,7 @@ namespace utl { * bit: ST 0 1 2 3 4 5 6 7 SP * < ---------- 1024/174 usec -------------> * - * 8 bits, no parity, 1 stop - * Standard: Overdrive : - * BR: 9600, BR: 57600 - * TX: 0xF0, TX: 0xF8 - * RX: 0xF0 not present RX: 0xF8 not present - * less if present less if present + * TX: (STD)0xF0, (OVDR)0xF8 RX: less if present * * \param t Timing * \return The status of the operation @@ -221,9 +178,9 @@ namespace utl { * \arg 1 Success */ template - bool _1wire_uart_i::_reset () { + bool _1wire_uart_i::_reset (Speed s) { // Select frame to send - uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8; + uint8_t w = ((_speed = s) == Speed::STD) ? 0xF0 : 0xF8; // Select baudrate impl().UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST); // Send frame and check the result @@ -259,7 +216,8 @@ namespace utl { private: /*! * \brief - * Implementers's (driver) read-write function. We use the following USART configuration. + * Implementers's (driver) read-write function. We use the following + * USART configuration: * - Word Length = 8 Bits * - Stop Bit = One Stop bit * - Parity = No parity @@ -291,55 +249,22 @@ namespace utl { }; Speed _speed {Speed::STD}; - Speed speed () { return _speed; } //!< Get the 1-wire bus speed - void speed (Speed s); //!< Set the 1-wire bus speed + Speed speed () const { return _speed; } //!< Get the 1-wire bus speed + void speed (Speed s); //!< Set the 1-wire bus speed /*! * \brief - * Read a bit from the 1-Wire bus, return it and provide - * the recovery time. + * Send a 1-Wire write bit and read the response * - * --- - - - - - - - - - - - - - - - - ------ - * Read \ / X X X X X X X X X X X X X X X / - * ---- - - - - - - - - - - - - - - - - - * RS: | | | | | | | | | | | - * bit: ST 0 1 2 3 4 5 6 7 SP - * < ------------- 87/11 usec -------------> - * ^ - * | - * Master sample - * - * 8 bits, no parity, 1 stop - * standard: BR: 115200 - * Overdrive: BR: 921600 - * TX: 0xFF - * RX: {1 - 0xFF, 0 - [0x00 - 0xFE] } - * - * \return The answer - * \arg 0 Read 0 - * \arg 1 Read 1 (This is also returned on transition error). - */ - bool bit () { - return (UART_RW (0xFF) < 0xFF); - } - - - /*! - * \brief - * Send a 1-Wire write bit - * 8 bits, no parity, 1 stop - * standard: BR: 115200 - * Overdrive: BR: 921600 - * - * --- -------------------------------------- - * Write 1 \ / + * Write 1 --- -------------------------------------- + * Read 0/1 \ / * ---- * RS: | | | | | | | | | | | * bit: ST 0 1 2 3 4 5 6 7 SP - * TX: 0xFF RX: 0xFF + * TX: 0xFF RX: 0xFF->1, less->0 * - * --- ------ - * Write 0 \ / + * Write 0 --- ------ + * Read 0 \ / * ------------------------------------- * RS: | | | | | | | | | | | * bit: ST 0 1 2 3 4 5 6 7 SP @@ -347,15 +272,17 @@ namespace utl { * TX: 0x00 RX: 0x00 * * \param b The bit to send - * \return Status of the operation - * \arg 0 Fail - * \arg 1 Success + * \return The response */ bool bit (bool b) { - uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send - return (w == UART_RW (w)); // Return status + if (b) + return (UART_RW (0xFF) < 0xFF) ? 0 : 1; + else { + UART_RW (0x00); + return 0; + } } - bool _reset (); + bool _reset (Speed s); //!@} }; @@ -376,7 +303,6 @@ namespace utl { /*! * \brief * Generate a 1-wire reset - * * --- ---- - - - ------- * Reset \ / \ X X X / * -------------------- - - - - @@ -384,21 +310,16 @@ namespace utl { * bit: ST 0 1 2 3 4 5 6 7 SP * < ---------- 1024/174 usec -------------> * - * 8 bits, no parity, 1 stop - * Standard: Overdrive : - * BR: 9600, BR: 57600 - * TX: 0xF0, TX: 0xF8 - * RX: 0xF0 not present RX: 0xF8 not present - * less if present less if present + * TX: (STD)0xF0, (OVDR)0xF8 RX: less if present * * \param t Timing * \return The status of the operation * \arg 0 Fail * \arg 1 Success */ - bool _1wire_uart_i::_reset () { + bool _1wire_uart_i::_reset (Speed s) { // Select frame to send - uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8; + uint8_t w = ((_speed = s) == Speed::STD) ? 0xF0 : 0xF8; // Select baudrate UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST); // Send frame and check the result diff --git a/include/utl/container/id.h b/include/utl/container/id.h index 1b12dcf..cd40256 100644 --- a/include/utl/container/id.h +++ b/include/utl/container/id.h @@ -1,6 +1,6 @@ /*! * \file utl/container/id.h - * \brief A container for device ID's + * \brief A container for device IDs * * Copyright (C) 2018 Christos Choutouridis *