com: 1wire interface base class[es] added.
Added: * A base class fot 1wire interface (both CRTP and virtual) * An UARD based implementation derived added (both CRTP and virtual)
This commit is contained in:
parent
846e98e150
commit
44f7dff3dd
708
include/utl/com/_1wire.h
Normal file
708
include/utl/com/_1wire.h
Normal file
@ -0,0 +1,708 @@
|
||||
/*!
|
||||
* \file /utl/com/_1wire.h
|
||||
* \brief An 1-wire interface implementation
|
||||
*
|
||||
* Copyright (C) 2018 Christos Choutouridis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __utl_com_1wire_h__
|
||||
#define __utl_com_1wire_h__
|
||||
|
||||
#include <utl/impl/impl.h>
|
||||
#include <utl/helper/crtp.h>
|
||||
#include <utl/meta/sfinae.h>
|
||||
#include <utl/com/_1wire_id.h>
|
||||
|
||||
#include <gsl/span>
|
||||
using gsl::span;
|
||||
|
||||
namespace utl {
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \ingroup Communication
|
||||
* \brief Abstract base class interface for 1-wire bus
|
||||
*/
|
||||
//!@{
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Template base class for 1-wire communication interface using CRTP
|
||||
* \param impl_t The CRTP type (the derived/implementation class typename).
|
||||
*/
|
||||
template <typename impl_t>
|
||||
class _1wire_i {
|
||||
_CRTP_IMPL(impl_t);
|
||||
|
||||
public:
|
||||
using type = _1wire_i; //!< Export type as identity meta-function
|
||||
|
||||
//! 1-wire bus speed
|
||||
enum class Speed { STD =0, OVDR };
|
||||
|
||||
/*!
|
||||
* \name Object lifetime
|
||||
*/
|
||||
//!@{
|
||||
protected:
|
||||
_1wire_i () = default; //!< Allow constructor from derived only
|
||||
~_1wire_i () = default; //!< Allow destructor from derived only
|
||||
_1wire_i (const _1wire_i&) = delete; //!< No copies
|
||||
_1wire_i& operator= (const _1wire_i&) = delete;
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Implementation requirements
|
||||
* \note
|
||||
* In order for the implementation to have the following as private members too
|
||||
* it need to declare this class as friend
|
||||
*/
|
||||
//!@{
|
||||
private:
|
||||
Speed speed () { 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
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Friends api to provide functionality to all class specializations
|
||||
*/
|
||||
//!@{
|
||||
private:
|
||||
enum Command {
|
||||
CMD_READ_ROM = 0x33,
|
||||
CMD_OVDR_SKIP = 0x3C,
|
||||
CMD_MATCH = 0x55,
|
||||
CMD_OVDR_MATCH = 0x69,
|
||||
CMD_SKIP = 0xCC,
|
||||
CMD_ALARM_SEARCH = 0xEC,
|
||||
CMD_SEARCH_ROM = 0xF0
|
||||
};
|
||||
template <typename _T> friend bool _1wire_i_reset (_T&, typename _T::Speed);
|
||||
template <typename _T> friend byte_t _1wire_i_rw (_T&, byte_t, typename _T::Speed);
|
||||
template <typename _T> friend byte_t _1wire_i_rx (_T&, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_rx (_T&, span<byte_t>, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_tx (_T&, byte_t, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_tx (_T&, const span<byte_t>, typename _T::Speed);
|
||||
template <typename _T> friend void _1wire_i_match (_T& obj, _1wire_id_t& id, typename _T::Speed s);
|
||||
template <typename _T> friend void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id);
|
||||
template <typename _T> friend void _1wire_i_skip (_T& obj, typename _T::Speed s);
|
||||
template <typename _T> friend void _1wire_i_skip_n_ovdr (_T& obj);
|
||||
template <typename _T> friend _1wire_id_t _1wire_i_first (_T&, typename _T::Speed, bool);
|
||||
template <typename _T> friend _1wire_id_t _1wire_i_next (_T&, typename _T::Speed, bool);
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name User functionality provided by the interface
|
||||
*/
|
||||
//!@{
|
||||
public:
|
||||
/*!
|
||||
* \brief
|
||||
* Generate a 1-wire reset
|
||||
* \param s Bus speed
|
||||
* \return The status of the operation
|
||||
* \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<byte_t> 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<byte_t> data, Speed s) { return _1wire_i_tx (*this, data, s); }
|
||||
/*!
|
||||
* \brief
|
||||
* Write a byte to 1-Wire bus and read the response
|
||||
* \param b The byte to write
|
||||
* \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); }
|
||||
|
||||
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); }
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* 'first' operation, to search on the 1-Wire for the first device.
|
||||
* This is performed by setting dec_, pos_ and cur_ to zero and then doing the search.
|
||||
* \param s The bus speed
|
||||
* \param alarm If set, search for alarm devices
|
||||
* \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); }
|
||||
/*!
|
||||
* \brief
|
||||
* 'next' operation, to search on the 1-Wire for the next device.
|
||||
* This search is usually performed after a 'first' operation or another 'next' operation.
|
||||
* Based on maxim-ic application note 187.
|
||||
* \param s The bus speed
|
||||
* \param alarm If set, search for alarm devices
|
||||
* \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); }
|
||||
//!@}
|
||||
|
||||
|
||||
private:
|
||||
_1wire_id_t dec_ {_1wire_id_t::nullDev()}; /*!<
|
||||
* Hold the algorithm's select bit when a discrepancy
|
||||
* is detected. We use this variable to navigate to the
|
||||
* ROM tree as we store the path we take each time (0-1).
|
||||
* Each bit represent a bit position in the ROM ID.
|
||||
*/
|
||||
_1wire_id_t pos_ {_1wire_id_t::nullDev()}; /*!<
|
||||
* Hold the discrepancy position. We use this variable to
|
||||
* navigate to the ROM tree as we store the crossroads(1) we encounter.
|
||||
* Each bit represent a bit position in the ROM ID.
|
||||
*/
|
||||
_1wire_id_t cur_ {_1wire_id_t::nullDev()}; //! Current rom discrepancy state
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* A virtual base class implementation
|
||||
* \param impl_t = virtual_tag
|
||||
*/
|
||||
template <>
|
||||
class _1wire_i <virtual_tag> {
|
||||
public:
|
||||
using type = _1wire_i<virtual_tag>; //!< Export type as identity meta-function
|
||||
|
||||
//! 1-wire bus speed
|
||||
enum class Speed { STD =0, OVDR };
|
||||
|
||||
/*!
|
||||
* \name Object lifetime
|
||||
*/
|
||||
//!@{
|
||||
protected:
|
||||
_1wire_i () = default; //!< Allow constructor from derived only
|
||||
_1wire_i (const type&) = delete; //!< No copies
|
||||
type& operator= (const type&) = delete;
|
||||
public:
|
||||
virtual ~_1wire_i () = default; //!< Virtual default destructor
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Implementation requirements
|
||||
*/
|
||||
//!@{
|
||||
private:
|
||||
virtual Speed speed () =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
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Friends api to provide functionality to all class specializations
|
||||
*/
|
||||
//!@{
|
||||
private:
|
||||
enum Command {
|
||||
CMD_READ_ROM = 0x33,
|
||||
CMD_OVDR_SKIP = 0x3C,
|
||||
CMD_MATCH = 0x55,
|
||||
CMD_OVDR_MATCH = 0x69,
|
||||
CMD_SKIP = 0xCC,
|
||||
CMD_ALARM_SEARCH = 0xEC,
|
||||
CMD_SEARCH_ROM = 0xF0
|
||||
};
|
||||
template <typename _T> friend bool _1wire_i_reset (_T&, typename _T::Speed);
|
||||
template <typename _T> friend byte_t _1wire_i_rw (_T&, byte_t, typename _T::Speed);
|
||||
template <typename _T> friend byte_t _1wire_i_rx (_T&, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_rx (_T&, span<byte_t>, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_tx (_T&, byte_t, typename _T::Speed);
|
||||
template <typename _T> friend size_t _1wire_i_tx (_T&, const span<byte_t>, typename _T::Speed);
|
||||
template <typename _T> friend void _1wire_i_match (_T& obj, _1wire_id_t& id, typename _T::Speed s);
|
||||
template <typename _T> friend void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id);
|
||||
template <typename _T> friend void _1wire_i_skip (_T& obj, typename _T::Speed s);
|
||||
template <typename _T> friend void _1wire_i_skip_n_ovdr (_T& obj);
|
||||
template <typename _T> friend _1wire_id_t _1wire_i_first (_T&, typename _T::Speed, bool);
|
||||
template <typename _T> friend _1wire_id_t _1wire_i_next (_T&, typename _T::Speed, bool);
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name User functionality provided by the interface
|
||||
*/
|
||||
//!@{
|
||||
public:
|
||||
/*!
|
||||
* \brief
|
||||
* Generate a 1-wire reset
|
||||
* \param s Bus speed
|
||||
* \return The status of the operation
|
||||
* \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<byte_t> 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<byte_t> data, Speed s) { return _1wire_i_tx (*this, data, s); }
|
||||
/*!
|
||||
* \brief
|
||||
* Write a byte to 1-Wire bus and read the response
|
||||
* \param b The byte to write
|
||||
* \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); }
|
||||
|
||||
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); }
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* 'first' operation, to search on the 1-Wire for the first device.
|
||||
* This is performed by setting dec_, pos_ and cur_ to zero and then doing the search.
|
||||
* \param s The bus speed
|
||||
* \param alarm If set, search for alarm devices
|
||||
* \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); }
|
||||
/*!
|
||||
* \brief
|
||||
* 'next' operation, to search on the 1-Wire for the next device.
|
||||
* This search is usually performed after a 'first' operation or another 'next' operation.
|
||||
* Based on maxim-ic application note 187.
|
||||
* \param s The bus speed
|
||||
* \param alarm If set, search for alarm devices
|
||||
* \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); }
|
||||
//!@}
|
||||
|
||||
|
||||
private:
|
||||
_1wire_id_t dec_ {_1wire_id_t::nullDev()}; /*!<
|
||||
* Hold the algorithm's select bit when a discrepancy
|
||||
* is detected. We use this variable to navigate to the
|
||||
* ROM tree as we store the path we take each time (0-1).
|
||||
* Each bit represent a bit position in the ROM ID.
|
||||
*/
|
||||
_1wire_id_t pos_ {_1wire_id_t::nullDev()}; /*!<
|
||||
* Hold the discrepancy position. We use this variable to
|
||||
* navigate to the ROM tree as we store the crossroads(1) we encounter.
|
||||
* Each bit represent a bit position in the ROM ID.
|
||||
*/
|
||||
_1wire_id_t cur_ {_1wire_id_t::nullDev()}; //! Current rom discrepancy state
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* \name Friend API to provide common functionality to all specializations
|
||||
*/
|
||||
//!@{
|
||||
|
||||
/*!
|
||||
* \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 <typename _T>
|
||||
bool _1wire_i_reset (_T& obj, typename _T::Speed s) {
|
||||
if (obj.speed () != s)
|
||||
obj.speed (s);
|
||||
return obj._reset ();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Write a byte to 1-Wire bus and read the response
|
||||
* \param obj The object from which we call private members
|
||||
* \param b The byte to write
|
||||
* \param s Bus speed to use
|
||||
* \return The byte received.
|
||||
*/
|
||||
template <typename _T>
|
||||
byte_t _1wire_i_rw (_T& obj, byte_t b, typename _T::Speed s) {
|
||||
byte_t ret {0};
|
||||
|
||||
// Select speed once
|
||||
if (obj.speed () != s)
|
||||
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;
|
||||
/*^
|
||||
* 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
|
||||
*/
|
||||
}
|
||||
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 <typename _T>
|
||||
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 <typename _T>
|
||||
size_t _1wire_i_rx (_T& obj, span<byte_t> 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 <typename _T>
|
||||
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 <typename _T>
|
||||
size_t _1wire_i_tx (_T& obj, const span<byte_t> 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
|
||||
* \param obj The object from which we call private members
|
||||
* \param id The ID to select on the bus
|
||||
* \param s The speed to use for the command
|
||||
*/
|
||||
template <typename _T>
|
||||
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);
|
||||
for (uint8_t& b : id)
|
||||
_1wire_i_tx (obj, b, s);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Match and overdrive sequence
|
||||
* \param obj The object from which we call private members
|
||||
* \param id The ID to select on the bus
|
||||
*/
|
||||
template <typename _T>
|
||||
void _1wire_i_match_n_ovdr (_T& obj, _1wire_id_t& id) {
|
||||
_1wire_i_tx (obj, _T::CMD_MATCH, _T::Speed::STD);
|
||||
for (uint8_t& b : id)
|
||||
_1wire_i_tx (obj, b, _T::Speed::OVDR);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Send skip command to the bus
|
||||
* \param obj The object from which we call private members
|
||||
* \param id The ID to select on the bus
|
||||
*/
|
||||
template <typename _T>
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Send the Skip and Overdrive sequence
|
||||
* \param obj The object from which we call private members
|
||||
*/
|
||||
template <typename _T>
|
||||
void _1wire_i_skip_n_ovdr (_T& obj) {
|
||||
_1wire_i_tx (obj, _T::CMD_OVDR_SKIP, _T::Speed::STD);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* 'first' operation, to search on the 1-Wire for the first device.
|
||||
* This is performed by setting dec_, pos_ and cur_ to zero and then doing the search.
|
||||
* \param obj The object from which we call private members
|
||||
* \param s The bus speed
|
||||
* \return ID The romID
|
||||
* \arg nullDev Indicate no [more] device[s]
|
||||
*/
|
||||
template <typename _T>
|
||||
_1wire_id_t _1wire_i_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);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* 'next' operation, to search on the 1-Wire for the next device.
|
||||
* This search is usually performed after a 'first' operation or another 'next' operation.
|
||||
* Based on maxim-ic application note 187.
|
||||
* \param obj The object from which we call private members
|
||||
* \param s The bus speed
|
||||
* \return The romID
|
||||
* \arg nullDev Indicate no [more] device[s]
|
||||
*/
|
||||
template <typename _T>
|
||||
_1wire_id_t _1wire_i_next (_T& obj, typename _T::Speed s, bool alarm) {
|
||||
uint8_t b, bxx; // bit helper vars
|
||||
uint8_t i;
|
||||
_1wire_id_t ID;
|
||||
|
||||
do {
|
||||
if ((obj.pos_ != _1wire_id_t::nullDev()) && (obj.dec_ >= obj.pos_)) {
|
||||
// dec_ == pos_: We have found all the leafs, already
|
||||
// dec_ > pos_ : Error
|
||||
ID = _1wire_id_t::nullDev();
|
||||
break;
|
||||
}
|
||||
if (!obj.reset (s)) {
|
||||
ID = _1wire_id_t::nullDev();
|
||||
break;
|
||||
}
|
||||
// Issue search command
|
||||
if (alarm) obj.write (_T::CMD_ALARM_SEARCH, s);
|
||||
else obj.write (_T::CMD_SEARCH_ROM, s);
|
||||
|
||||
// traverse entire RomID from LSB to MSB
|
||||
for (i =0 ; i<64 ; ++i) {
|
||||
// Get response pair bits
|
||||
bxx = obj.bit (); // bit
|
||||
bxx <<= 1;
|
||||
bxx |= obj.bit (); // complementary bit
|
||||
|
||||
if (bxx == 0x00) {
|
||||
// 00 - We have discrepancy
|
||||
obj.cur_.bit (i, 1);
|
||||
switch (_1wire_id_t::compare (obj.pos_, obj.cur_)) {
|
||||
default:
|
||||
case -1:
|
||||
// pos_ < cur_: This discrepancy is the most far for now. Mark position and select 0.
|
||||
b = 0;
|
||||
//dec_.bit (i, (b = 0)); //<-- Its already 0
|
||||
obj.pos_.bit (i, 1);
|
||||
break;
|
||||
case 0:
|
||||
// pos_ == cur_: This was the last discrepancy in the last pass.
|
||||
// Select the other branch this time (1)
|
||||
obj.dec_.bit (i, (b = 1));
|
||||
break;
|
||||
case 1:
|
||||
// pos_ > cur_: We had a discrepancy in a MSB than that, in a previous pass.
|
||||
// Continue with the last pass decision.
|
||||
b = obj.dec_.bit (i);
|
||||
break;
|
||||
}
|
||||
// Send selection and update romid
|
||||
obj.bit (b);
|
||||
ID.bit (i, b);
|
||||
}
|
||||
else if (bxx == 0x01) {
|
||||
// 01 - All bits of all ROMs are 0s
|
||||
obj.bit (0);
|
||||
ID.bit (i, 0);
|
||||
|
||||
}
|
||||
else if (bxx == 0x02) {
|
||||
// 10 - All bits of all ROMs are 1s
|
||||
obj.bit (1);
|
||||
ID.bit (i, 1);
|
||||
}
|
||||
else {
|
||||
// 11 - No device on the bus
|
||||
ID = _1wire_id_t::nullDev();
|
||||
break;
|
||||
}
|
||||
} // for
|
||||
|
||||
if (i == 64 && obj.pos_ == _1wire_id_t::nullDev()) {
|
||||
// Mark done with only one device
|
||||
obj.pos_.bit (0, 1);
|
||||
obj.dec_.bit (0, 1);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return ID;
|
||||
}
|
||||
//!@}
|
||||
|
||||
|
||||
#if defined _utl_have_concepts
|
||||
/*!
|
||||
* \name 1-wire type interface concept
|
||||
*/
|
||||
template <typename T>
|
||||
concept bool _1wire_c = requires (T t, typename T::Speed s, _1wire_id_t id) {
|
||||
// Object type
|
||||
requires not_<std::is_copy_constructible<T>::value>::value;
|
||||
requires not_<std::is_copy_assignable<T>::value>::value;
|
||||
// Members
|
||||
// typename T::Speed;
|
||||
// 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.match(id, s);
|
||||
t.match_n_ovdr(id);
|
||||
t.skip(s);
|
||||
t.skip_n_ovdr();
|
||||
{t.first(s)} -> _1wire_id_t;
|
||||
{t.next(s)} -> _1wire_id_t;
|
||||
};
|
||||
#else
|
||||
namespace _1wire_i_cnpt {
|
||||
using std::declval;
|
||||
|
||||
template <class _Tp> using try_reset_t = decltype (declval<_Tp>().reset (declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_rw_t = decltype (declval<_Tp>().rw (declval<byte_t>(), declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_rx1_t = decltype (declval<_Tp>().read (declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_rx2_t = decltype (declval<_Tp>().read (declval<span<byte_t>>(), declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_tx1_t = decltype (declval<_Tp>().write (declval<byte_t>(), declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_tx2_t = decltype (declval<_Tp>().write (declval<const span<byte_t>>(), declval<typename _Tp::Speed>()));
|
||||
|
||||
|
||||
template <class _Tp> using try_match_t = decltype (declval<_Tp>().match (declval<_1wire_id_t&>(), declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_match_n_ovdr_t = decltype (declval<_Tp>().match_n_ovdr (declval<_1wire_id_t&>()));
|
||||
template <class _Tp> using try_skip_t = decltype (declval<_Tp>().skip (declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_skip_n_ovdr_t = decltype (declval<_Tp>().skip_n_ovdr ());
|
||||
template <class _Tp> using try_first_t = decltype (declval<_Tp>().first (declval<typename _Tp::Speed>()));
|
||||
template <class _Tp> using try_next_t = decltype (declval<_Tp>().next (declval<typename _Tp::Speed>()));
|
||||
|
||||
//! Primary template to catch any non 1-wire interface types
|
||||
template <typename _Tp, typename =void>
|
||||
struct is_1wire_ : false_ {};
|
||||
|
||||
//! template to catch a proper 1-wire interface type
|
||||
template <typename _Tp>
|
||||
struct is_1wire_ <_Tp,
|
||||
void_t <
|
||||
// typename _Tp::Speed,
|
||||
// typename _Tp::Command,
|
||||
use_if_same_t <try_reset_t <_Tp>, bool>,
|
||||
use_if_same_t <try_rw_t <_Tp>, byte_t>,
|
||||
use_if_same_t <try_rx1_t <_Tp>, byte_t>,
|
||||
use_if_same_t <try_rx2_t <_Tp>, size_t>,
|
||||
use_if_same_t <try_tx1_t <_Tp>, size_t>,
|
||||
use_if_same_t <try_tx2_t <_Tp>, size_t>,
|
||||
use_if_same_t <try_match_t<_Tp>, void>,
|
||||
use_if_same_t <try_match_n_ovdr_t<_Tp>, void>,
|
||||
use_if_same_t <try_skip_t<_Tp>, void>,
|
||||
use_if_same_t <try_skip_n_ovdr_t<_Tp>, void>,
|
||||
use_if_same_t <try_first_t <_Tp>, _1wire_id_t>,
|
||||
use_if_same_t <try_next_t <_Tp>, _1wire_id_t>
|
||||
> //!^ SFINAE may apply
|
||||
> : true_ {};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Value meta-programming function for 1-wire interface checking
|
||||
* \param _Tp Type to check
|
||||
* \return True if _Tp is a 1-wire interface
|
||||
*/
|
||||
template <typename _Tp>
|
||||
constexpr bool _1wire_c = _1wire_i_cnpt::is_1wire_<_Tp>::value;
|
||||
#endif
|
||||
|
||||
//!@}
|
||||
} //namespace utl
|
||||
|
||||
#endif /* __utl_com_1wire_h__ */
|
412
include/utl/com/_1wire_uart.h
Normal file
412
include/utl/com/_1wire_uart.h
Normal file
@ -0,0 +1,412 @@
|
||||
/*!
|
||||
* \file utl/com/_1wire_uart.h
|
||||
* \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
|
||||
* connected to the 1-wire bus wire
|
||||
* 2) A Transmit/receive function even in blocking/polling mode
|
||||
* 3) A baudrate set function
|
||||
*
|
||||
* Copyright (C) 2018 Christos Choutouridis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __utl_com_1wire_uart_h__
|
||||
#define __utl_com_1wire_uart_h__
|
||||
|
||||
#include <utl/impl/impl.h>
|
||||
#include <utl/helper/crtp.h>
|
||||
#include <utl/com/_1wire.h>
|
||||
|
||||
namespace utl {
|
||||
/*!
|
||||
* \ingroup Communication
|
||||
* A 1-wire implementation using a microprocessor's uart for bit timing
|
||||
* inherited from \ref _1wire_i base class.
|
||||
* \sa _1wire_i
|
||||
*/
|
||||
//!@{
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* 1-wire UART interface template class using CRTP
|
||||
* Using the private virtual interface we provide the interface from
|
||||
* _1wire_i<>
|
||||
*/
|
||||
template <typename Impl_t>
|
||||
class _1wire_uart_i : public _1wire_i<_1wire_uart_i<Impl_t>> {
|
||||
_CRTP_IMPL(Impl_t); //! \brief Syntactic sugar to CRTP casting
|
||||
friend _1wire_i <_1wire_uart_i<Impl_t>>;
|
||||
public:
|
||||
using type = _1wire_uart_i<Impl_t>; //!< Export type as identity meta-function
|
||||
using Speed = typename _1wire_i<type>::Speed; //!< Bring bus speed
|
||||
|
||||
/*!
|
||||
* \name Object lifetime
|
||||
*/
|
||||
//!@{
|
||||
protected:
|
||||
_1wire_uart_i () = default; //!< Allow constructor from derived only
|
||||
~_1wire_uart_i () = default; //!< Allow destructor from derived only
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Implementation requirements
|
||||
* \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<Foo> {
|
||||
* friend _1wire_uart<Foo>;
|
||||
* 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.
|
||||
* - Word Length = 8 Bits
|
||||
* - Stop Bit = One Stop bit
|
||||
* - Parity = No parity
|
||||
* \param The byte to send
|
||||
* \return The byte received.
|
||||
* \note
|
||||
* Due to the nature of the technique, the received byte is the actual bus
|
||||
* condition during the communication frame (time slot)
|
||||
*/
|
||||
byte_t UART_RW (byte_t byte) { return impl().UART_RW (byte); }
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Implementers's (driver) baudrate function.
|
||||
* \param The desired Baudrate
|
||||
*/
|
||||
void UART_BR (uint32_t br) { impl().UART_BR (br); }
|
||||
//!@}
|
||||
|
||||
//! \name Implementation of base requirements
|
||||
//!@{
|
||||
private:
|
||||
//! 1-wire UART baudrates
|
||||
enum BR {
|
||||
BR_STD_RST =9600,
|
||||
BR_OVR_RST =57600,
|
||||
BR_STD =115200,
|
||||
BR_OVR =921600
|
||||
};
|
||||
Speed _speed {Speed::STD};
|
||||
|
||||
Speed speed () { 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.
|
||||
*
|
||||
* --- - - - - - - - - - - - - - - - - ------
|
||||
* 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 \ /
|
||||
* ----
|
||||
* RS: | | | | | | | | | | |
|
||||
* bit: ST 0 1 2 3 4 5 6 7 SP
|
||||
* TX: 0xFF RX: 0xFF
|
||||
*
|
||||
* --- ------
|
||||
* Write 0 \ /
|
||||
* -------------------------------------
|
||||
* RS: | | | | | | | | | | |
|
||||
* bit: ST 0 1 2 3 4 5 6 7 SP
|
||||
* < ------------- 87/11 usec ------------->
|
||||
* TX: 0x00 RX: 0x00
|
||||
*
|
||||
* \param b The bit to send
|
||||
* \return Status of the operation
|
||||
* \arg 0 Fail
|
||||
* \arg 1 Success
|
||||
*/
|
||||
bool bit (bool b) {
|
||||
uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send
|
||||
return (w == impl().UART_RW (w)); // Return status
|
||||
}
|
||||
bool _reset ();
|
||||
//!@}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Set the 1-wire bus speed for normal operation only
|
||||
* \note
|
||||
* We have moved the BR set functionality here to reduce the code inside bit().
|
||||
* This is OK as long as the _1wire_i<> always check speed.
|
||||
* \param s The desired speed
|
||||
*/
|
||||
template <typename Impl_t>
|
||||
void _1wire_uart_i<Impl_t>::speed (Speed s) {
|
||||
switch (_speed = s) {
|
||||
case Speed::STD: impl().UART_BR (BR_STD); break;
|
||||
case Speed::OVDR: impl().UART_BR (BR_OVR); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Generate a 1-wire reset
|
||||
*
|
||||
* --- ---- - - - -------
|
||||
* Reset \ / \ X X X /
|
||||
* -------------------- - - - -
|
||||
* RS: | | | | | | | | | | |
|
||||
* 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
|
||||
*
|
||||
* \param t Timing
|
||||
* \return The status of the operation
|
||||
* \arg 0 Fail
|
||||
* \arg 1 Success
|
||||
*/
|
||||
template <typename Impl_t>
|
||||
bool _1wire_uart_i<Impl_t>::_reset () {
|
||||
// Select frame to send
|
||||
uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8;
|
||||
// Select baudrate
|
||||
impl().UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
|
||||
// Send frame and check the result
|
||||
return (impl().UART_RW (w) < w);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* A virtual base class interface implementation.
|
||||
* Using the private virtual interface we provide the interface from
|
||||
* _1wire_i<virtual_tag>
|
||||
* \param impl_t = virtual_tag
|
||||
*/
|
||||
template <>
|
||||
class _1wire_uart_i<virtual_tag> : public _1wire_i<virtual_tag> {
|
||||
public:
|
||||
using type = _1wire_uart_i<virtual_tag>; //!< Export type as identity meta-function
|
||||
using Speed = typename _1wire_i<virtual_tag>::Speed; //!< Bring bus speed
|
||||
|
||||
/*!
|
||||
* \name Object lifetime
|
||||
*/
|
||||
//!@{
|
||||
protected:
|
||||
_1wire_uart_i () = default; //!< Allow constructor from derived only
|
||||
~_1wire_uart_i () = default; //!< Allow destructor from derived only
|
||||
//!@}
|
||||
|
||||
/*!
|
||||
* \name Implementation requirements
|
||||
*/
|
||||
//!@{
|
||||
private:
|
||||
/*!
|
||||
* \brief
|
||||
* Implementers's (driver) read-write function. We use the following USART configuration.
|
||||
* - Word Length = 8 Bits
|
||||
* - Stop Bit = One Stop bit
|
||||
* - Parity = No parity
|
||||
* \param The byte to send
|
||||
* \return The byte received.
|
||||
* \note
|
||||
* Due to the nature of the technique, the received byte is the actual bus
|
||||
* condition during the communication frame (time slot)
|
||||
*/
|
||||
virtual byte_t UART_RW (byte_t byte) =0;
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
* Implementers's (driver) baudrate function.
|
||||
* \param The desired Baudrate
|
||||
*/
|
||||
virtual void UART_BR (uint32_t br) =0;
|
||||
//!@}
|
||||
|
||||
//! \name Implementation of base requirements
|
||||
//!@{
|
||||
private:
|
||||
//! 1-wire UART baudrates
|
||||
enum BR {
|
||||
BR_STD_RST =9600,
|
||||
BR_OVR_RST =57600,
|
||||
BR_STD =115200,
|
||||
BR_OVR =921600
|
||||
};
|
||||
Speed _speed {Speed::STD};
|
||||
|
||||
Speed speed () { 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.
|
||||
*
|
||||
* --- - - - - - - - - - - - - - - - - ------
|
||||
* 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 \ /
|
||||
* ----
|
||||
* RS: | | | | | | | | | | |
|
||||
* bit: ST 0 1 2 3 4 5 6 7 SP
|
||||
* TX: 0xFF RX: 0xFF
|
||||
*
|
||||
* --- ------
|
||||
* Write 0 \ /
|
||||
* -------------------------------------
|
||||
* RS: | | | | | | | | | | |
|
||||
* bit: ST 0 1 2 3 4 5 6 7 SP
|
||||
* < ------------- 87/11 usec ------------->
|
||||
* TX: 0x00 RX: 0x00
|
||||
*
|
||||
* \param b The bit to send
|
||||
* \return Status of the operation
|
||||
* \arg 0 Fail
|
||||
* \arg 1 Success
|
||||
*/
|
||||
bool bit (bool b) {
|
||||
uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send
|
||||
return (w == UART_RW (w)); // Return status
|
||||
}
|
||||
bool _reset ();
|
||||
//!@}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Set the 1-wire bus speed for normal operation only
|
||||
* \note
|
||||
* We have moved the BR set functionality here to reduce the code inside bit().
|
||||
* This is OK as long as the _1wire_i<> always check speed.
|
||||
* \param s The desired speed
|
||||
*/
|
||||
void _1wire_uart_i<virtual_tag>::speed (Speed s) {
|
||||
switch (_speed = s) {
|
||||
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 /
|
||||
* -------------------- - - - -
|
||||
* RS: | | | | | | | | | | |
|
||||
* 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
|
||||
*
|
||||
* \param t Timing
|
||||
* \return The status of the operation
|
||||
* \arg 0 Fail
|
||||
* \arg 1 Success
|
||||
*/
|
||||
bool _1wire_uart_i<virtual_tag>::_reset () {
|
||||
// Select frame to send
|
||||
uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8;
|
||||
// Select baudrate
|
||||
UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
|
||||
// Send frame and check the result
|
||||
return (UART_RW (w) < w);
|
||||
}
|
||||
|
||||
//!@}
|
||||
|
||||
} // namespace utl
|
||||
|
||||
#endif /* __utl_com_1wire_uart_h__ */
|
Loading…
x
Reference in New Issue
Block a user