Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

334 lignes
11 KiB

  1. /*!
  2. * \file utl/com/_1wire_uart.h
  3. * \brief
  4. * A 1-wire implementation using a microprocessor's uart for bit timing
  5. * \note
  6. * This 1-wire implementation is based on MCU UART functionality. The implementation
  7. * expects:
  8. * 1) An Open drain tx and a floating(or pull-up) rx UART pin configuration with both pins
  9. * connected to the 1-wire bus wire
  10. * 2) A Transmit/receive function even in blocking/polling mode
  11. * 3) A baudrate set function
  12. *
  13. * Copyright (C) 2018 Christos Choutouridis
  14. *
  15. * This program is free software: you can redistribute it and/or modify
  16. * it under the terms of the GNU Lesser General Public License as
  17. * published by the Free Software Foundation, either version 3
  18. * of the License, or (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU Lesser General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Lesser General Public License
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  27. *
  28. */
  29. #ifndef __utl_com_1wire_uart_h__
  30. #define __utl_com_1wire_uart_h__
  31. #include <utl/impl/impl.h>
  32. #include <utl/helper/crtp.h>
  33. #include <utl/com/_1wire.h>
  34. namespace utl {
  35. /*!
  36. * \ingroup Communication
  37. * A 1-wire implementation using a microprocessor's uart for bit timing
  38. * inherited from \ref _1wire_i base class.
  39. * \sa _1wire_i
  40. */
  41. //!@{
  42. /*!
  43. * \brief
  44. * 1-wire UART interface template class using CRTP
  45. * Using the private virtual interface we provide the interface from
  46. * _1wire_i<>
  47. */
  48. template <typename Impl_t>
  49. class _1wire_uart_i : public _1wire_i<_1wire_uart_i<Impl_t>> {
  50. _CRTP_IMPL(Impl_t); //! \brief Syntactic sugar to CRTP casting
  51. friend _1wire_i <_1wire_uart_i<Impl_t>>;
  52. public:
  53. using type = _1wire_uart_i<Impl_t>; //!< Export type as identity meta-function
  54. using Speed = typename _1wire_i<type>::Speed; //!< Bring bus speed
  55. /*!
  56. * \name Object lifetime
  57. */
  58. //!@{
  59. protected:
  60. _1wire_uart_i () = default; //!< Allow constructor from derived only
  61. ~_1wire_uart_i () = default; //!< Allow destructor from derived only
  62. //!@}
  63. /*!
  64. * \name Implementation requirements
  65. * \note
  66. * In order for the implementation to have the following as private members
  67. * it also need to declare this class as friend
  68. */
  69. //!@{
  70. private:
  71. /*!
  72. * \brief
  73. * Implementers's (driver) read-write function. We expect the following
  74. * USART configuration:
  75. * - Word Length = 8 Bits
  76. * - Stop Bit = One Stop bit
  77. * - Parity = No parity
  78. * \param The byte to send
  79. * \return The byte received.
  80. * \note
  81. * Due to the nature of the technique, the received byte is the actual bus
  82. * condition during the communication frame (time slot)
  83. */
  84. byte_t UART_RW (byte_t byte) { return impl().UART_RW (byte); }
  85. /*!
  86. * \brief
  87. * Implementers's (driver) baudrate function.
  88. * \param The desired Baudrate
  89. */
  90. void UART_BR (uint32_t br) { impl().UART_BR (br); }
  91. //!@}
  92. //! \name Implementation of base requirements
  93. //!@{
  94. private:
  95. //! 1-wire UART baudrates
  96. enum BR {
  97. BR_STD_RST =9600,
  98. BR_OVR_RST =57600,
  99. BR_STD =115200,
  100. BR_OVR =921600
  101. };
  102. Speed _speed {Speed::STD};
  103. Speed speed () const { return _speed; } //!< Get the 1-wire bus speed
  104. void speed (Speed s); //!< Set the 1-wire bus speed
  105. /*!
  106. * \brief
  107. * Send a 1-Wire write bit and read the response
  108. *
  109. * Write 1 --- --------------------------------------
  110. * Read 0/1 \ /
  111. * ----
  112. * RS: | | | | | | | | | | |
  113. * bit: ST 0 1 2 3 4 5 6 7 SP
  114. * TX: 0xFF RX: 0xFF->1, less->0
  115. *
  116. * Write 0 --- ------
  117. * Read 0 \ /
  118. * -------------------------------------
  119. * RS: | | | | | | | | | | |
  120. * bit: ST 0 1 2 3 4 5 6 7 SP
  121. * < ------------- 87/11 usec ------------->
  122. * TX: 0x00 RX: 0x00
  123. *
  124. * \param b The bit to send
  125. * \return The response
  126. */
  127. bool bit (bool b) {
  128. if (b)
  129. return (UART_RW (0xFF) < 0xFF) ? 0 : 1;
  130. else {
  131. UART_RW (0x00);
  132. return 0;
  133. }
  134. }
  135. bool _reset (Speed s);
  136. //!@}
  137. };
  138. /*!
  139. * Set the 1-wire bus speed for normal operation only
  140. * \note
  141. * We have moved the BR set functionality here to reduce the code inside bit().
  142. * This is OK as long as the _1wire_i<> always check speed.
  143. * \param s The desired speed
  144. */
  145. template <typename Impl_t>
  146. void _1wire_uart_i<Impl_t>::speed (Speed s) {
  147. switch (_speed = s) {
  148. case Speed::STD: UART_BR (BR_STD); break;
  149. case Speed::OVDR: UART_BR (BR_OVR); break;
  150. }
  151. }
  152. /*!
  153. * \brief
  154. * Generate a 1-wire reset
  155. * --- ---- - - - -------
  156. * Reset \ / \ X X X /
  157. * -------------------- - - - -
  158. * RS: | | | | | | | | | | |
  159. * bit: ST 0 1 2 3 4 5 6 7 SP
  160. * < ---------- 1024/174 usec ------------->
  161. *
  162. * TX: (STD)0xF0, (OVDR)0xF8 RX: less if present
  163. *
  164. * \param t Timing
  165. * \return The status of the operation
  166. * \arg 0 Fail
  167. * \arg 1 Success
  168. */
  169. template <typename Impl_t>
  170. bool _1wire_uart_i<Impl_t>::_reset (Speed s) {
  171. // Select frame to send
  172. uint8_t w = ((_speed = s) == Speed::STD) ? 0xF0 : 0xF8;
  173. // Select baudrate
  174. impl().UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
  175. // Send frame and check the result
  176. return (impl().UART_RW (w) < w);
  177. }
  178. /*!
  179. * \brief
  180. * A virtual base class interface implementation.
  181. * Using the private virtual interface we provide the interface from
  182. * _1wire_i<virtual_tag>
  183. * \param impl_t = virtual_tag
  184. */
  185. template <>
  186. class _1wire_uart_i<virtual_tag> : public _1wire_i<virtual_tag> {
  187. public:
  188. using type = _1wire_uart_i<virtual_tag>; //!< Export type as identity meta-function
  189. using Speed = typename _1wire_i<virtual_tag>::Speed; //!< Bring bus speed
  190. /*!
  191. * \name Object lifetime
  192. */
  193. //!@{
  194. protected:
  195. _1wire_uart_i () = default; //!< Allow constructor from derived only
  196. ~_1wire_uart_i () = default; //!< Allow destructor from derived only
  197. //!@}
  198. /*!
  199. * \name Implementation requirements
  200. */
  201. //!@{
  202. private:
  203. /*!
  204. * \brief
  205. * Implementers's (driver) read-write function. We use the following
  206. * USART configuration:
  207. * - Word Length = 8 Bits
  208. * - Stop Bit = One Stop bit
  209. * - Parity = No parity
  210. * \param The byte to send
  211. * \return The byte received.
  212. * \note
  213. * Due to the nature of the technique, the received byte is the actual bus
  214. * condition during the communication frame (time slot)
  215. */
  216. virtual byte_t UART_RW (byte_t byte) =0;
  217. /*!
  218. * \brief
  219. * Implementers's (driver) baudrate function.
  220. * \param The desired Baudrate
  221. */
  222. virtual void UART_BR (uint32_t br) =0;
  223. //!@}
  224. //! \name Implementation of base requirements
  225. //!@{
  226. private:
  227. //! 1-wire UART baudrates
  228. enum BR {
  229. BR_STD_RST =9600,
  230. BR_OVR_RST =57600,
  231. BR_STD =115200,
  232. BR_OVR =921600
  233. };
  234. Speed _speed {Speed::STD};
  235. Speed speed () const { return _speed; } //!< Get the 1-wire bus speed
  236. void speed (Speed s); //!< Set the 1-wire bus speed
  237. /*!
  238. * \brief
  239. * Send a 1-Wire write bit and read the response
  240. *
  241. * Write 1 --- --------------------------------------
  242. * Read 0/1 \ /
  243. * ----
  244. * RS: | | | | | | | | | | |
  245. * bit: ST 0 1 2 3 4 5 6 7 SP
  246. * TX: 0xFF RX: 0xFF->1, less->0
  247. *
  248. * Write 0 --- ------
  249. * Read 0 \ /
  250. * -------------------------------------
  251. * RS: | | | | | | | | | | |
  252. * bit: ST 0 1 2 3 4 5 6 7 SP
  253. * < ------------- 87/11 usec ------------->
  254. * TX: 0x00 RX: 0x00
  255. *
  256. * \param b The bit to send
  257. * \return The response
  258. */
  259. bool bit (bool b) {
  260. if (b)
  261. return (UART_RW (0xFF) < 0xFF) ? 0 : 1;
  262. else {
  263. UART_RW (0x00);
  264. return 0;
  265. }
  266. }
  267. bool _reset (Speed s);
  268. //!@}
  269. };
  270. /*!
  271. * Set the 1-wire bus speed for normal operation only
  272. * \note
  273. * We have moved the BR set functionality here to reduce the code inside bit().
  274. * This is OK as long as the _1wire_i<> always check speed.
  275. * \param s The desired speed
  276. */
  277. void _1wire_uart_i<virtual_tag>::speed (Speed s) {
  278. switch (_speed = s) {
  279. case Speed::STD: UART_BR (BR_STD); break;
  280. case Speed::OVDR: UART_BR (BR_OVR); break;
  281. }
  282. }
  283. /*!
  284. * \brief
  285. * Generate a 1-wire reset
  286. * --- ---- - - - -------
  287. * Reset \ / \ X X X /
  288. * -------------------- - - - -
  289. * RS: | | | | | | | | | | |
  290. * bit: ST 0 1 2 3 4 5 6 7 SP
  291. * < ---------- 1024/174 usec ------------->
  292. *
  293. * TX: (STD)0xF0, (OVDR)0xF8 RX: less if present
  294. *
  295. * \param t Timing
  296. * \return The status of the operation
  297. * \arg 0 Fail
  298. * \arg 1 Success
  299. */
  300. bool _1wire_uart_i<virtual_tag>::_reset (Speed s) {
  301. // Select frame to send
  302. uint8_t w = ((_speed = s) == Speed::STD) ? 0xF0 : 0xF8;
  303. // Select baudrate
  304. UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
  305. // Send frame and check the result
  306. return (UART_RW (w) < w);
  307. }
  308. //!@}
  309. } // namespace utl
  310. #endif /* __utl_com_1wire_uart_h__ */