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.
 
 
 
 

413 lignes
14 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 io functionality. In order
  7. * to work it needs:
  8. * 1) A Open drain tx and 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. * for ex:
  69. * class Foo : public _1wire_uart<Foo> {
  70. * friend _1wire_uart<Foo>;
  71. * byte_t UART_RW (byte_t byte);
  72. * void UART_BR (uint32_t br);
  73. * // ...
  74. * };
  75. */
  76. //!@{
  77. private:
  78. /*!
  79. * \brief
  80. * Implementers's (driver) read-write function. We use the following USART configuration.
  81. * - Word Length = 8 Bits
  82. * - Stop Bit = One Stop bit
  83. * - Parity = No parity
  84. * \param The byte to send
  85. * \return The byte received.
  86. * \note
  87. * Due to the nature of the technique, the received byte is the actual bus
  88. * condition during the communication frame (time slot)
  89. */
  90. byte_t UART_RW (byte_t byte) { return impl().UART_RW (byte); }
  91. /*!
  92. * \brief
  93. * Implementers's (driver) baudrate function.
  94. * \param The desired Baudrate
  95. */
  96. void UART_BR (uint32_t br) { impl().UART_BR (br); }
  97. //!@}
  98. //! \name Implementation of base requirements
  99. //!@{
  100. private:
  101. //! 1-wire UART baudrates
  102. enum BR {
  103. BR_STD_RST =9600,
  104. BR_OVR_RST =57600,
  105. BR_STD =115200,
  106. BR_OVR =921600
  107. };
  108. Speed _speed {Speed::STD};
  109. Speed speed () { return _speed; } //!< Get the 1-wire bus speed
  110. void speed (Speed s); //!< Set the 1-wire bus speed
  111. /*!
  112. * \brief
  113. * Read a bit from the 1-Wire bus, return it and provide
  114. * the recovery time.
  115. *
  116. * --- - - - - - - - - - - - - - - - - ------
  117. * Read \ / X X X X X X X X X X X X X X X /
  118. * ---- - - - - - - - - - - - - - - - -
  119. * RS: | | | | | | | | | | |
  120. * bit: ST 0 1 2 3 4 5 6 7 SP
  121. * < ------------- 87/11 usec ------------->
  122. * ^
  123. * |
  124. * Master sample
  125. *
  126. * 8 bits, no parity, 1 stop
  127. * standard: BR: 115200
  128. * Overdrive: BR: 921600
  129. * TX: 0xFF
  130. * RX: {1 - 0xFF, 0 - [0x00 - 0xFE] }
  131. *
  132. * \return The answer
  133. * \arg 0 Read 0
  134. * \arg 1 Read 1 (This is also returned on transition error).
  135. */
  136. bool bit () {
  137. return (impl().UART_RW (0xFF) < 0xFF);
  138. }
  139. /*!
  140. * \brief
  141. * Send a 1-Wire write bit
  142. * 8 bits, no parity, 1 stop
  143. * standard: BR: 115200
  144. * Overdrive: BR: 921600
  145. *
  146. * --- --------------------------------------
  147. * Write 1 \ /
  148. * ----
  149. * RS: | | | | | | | | | | |
  150. * bit: ST 0 1 2 3 4 5 6 7 SP
  151. * TX: 0xFF RX: 0xFF
  152. *
  153. * --- ------
  154. * Write 0 \ /
  155. * -------------------------------------
  156. * RS: | | | | | | | | | | |
  157. * bit: ST 0 1 2 3 4 5 6 7 SP
  158. * < ------------- 87/11 usec ------------->
  159. * TX: 0x00 RX: 0x00
  160. *
  161. * \param b The bit to send
  162. * \return Status of the operation
  163. * \arg 0 Fail
  164. * \arg 1 Success
  165. */
  166. bool bit (bool b) {
  167. uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send
  168. return (w == impl().UART_RW (w)); // Return status
  169. }
  170. bool _reset ();
  171. //!@}
  172. };
  173. /*!
  174. * Set the 1-wire bus speed for normal operation only
  175. * \note
  176. * We have moved the BR set functionality here to reduce the code inside bit().
  177. * This is OK as long as the _1wire_i<> always check speed.
  178. * \param s The desired speed
  179. */
  180. template <typename Impl_t>
  181. void _1wire_uart_i<Impl_t>::speed (Speed s) {
  182. switch (_speed = s) {
  183. case Speed::STD: impl().UART_BR (BR_STD); break;
  184. case Speed::OVDR: impl().UART_BR (BR_OVR); break;
  185. }
  186. }
  187. /*!
  188. * \brief
  189. * Generate a 1-wire reset
  190. *
  191. * --- ---- - - - -------
  192. * Reset \ / \ X X X /
  193. * -------------------- - - - -
  194. * RS: | | | | | | | | | | |
  195. * bit: ST 0 1 2 3 4 5 6 7 SP
  196. * < ---------- 1024/174 usec ------------->
  197. *
  198. * 8 bits, no parity, 1 stop
  199. * Standard: Overdrive :
  200. * BR: 9600, BR: 57600
  201. * TX: 0xF0, TX: 0xF8
  202. * RX: 0xF0 not present RX: 0xF8 not present
  203. * less if present less if present
  204. *
  205. * \param t Timing
  206. * \return The status of the operation
  207. * \arg 0 Fail
  208. * \arg 1 Success
  209. */
  210. template <typename Impl_t>
  211. bool _1wire_uart_i<Impl_t>::_reset () {
  212. // Select frame to send
  213. uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8;
  214. // Select baudrate
  215. impl().UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
  216. // Send frame and check the result
  217. return (impl().UART_RW (w) < w);
  218. }
  219. /*!
  220. * \brief
  221. * A virtual base class interface implementation.
  222. * Using the private virtual interface we provide the interface from
  223. * _1wire_i<virtual_tag>
  224. * \param impl_t = virtual_tag
  225. */
  226. template <>
  227. class _1wire_uart_i<virtual_tag> : public _1wire_i<virtual_tag> {
  228. public:
  229. using type = _1wire_uart_i<virtual_tag>; //!< Export type as identity meta-function
  230. using Speed = typename _1wire_i<virtual_tag>::Speed; //!< Bring bus speed
  231. /*!
  232. * \name Object lifetime
  233. */
  234. //!@{
  235. protected:
  236. _1wire_uart_i () = default; //!< Allow constructor from derived only
  237. ~_1wire_uart_i () = default; //!< Allow destructor from derived only
  238. //!@}
  239. /*!
  240. * \name Implementation requirements
  241. */
  242. //!@{
  243. private:
  244. /*!
  245. * \brief
  246. * Implementers's (driver) read-write function. We use the following USART configuration.
  247. * - Word Length = 8 Bits
  248. * - Stop Bit = One Stop bit
  249. * - Parity = No parity
  250. * \param The byte to send
  251. * \return The byte received.
  252. * \note
  253. * Due to the nature of the technique, the received byte is the actual bus
  254. * condition during the communication frame (time slot)
  255. */
  256. virtual byte_t UART_RW (byte_t byte) =0;
  257. /*!
  258. * \brief
  259. * Implementers's (driver) baudrate function.
  260. * \param The desired Baudrate
  261. */
  262. virtual void UART_BR (uint32_t br) =0;
  263. //!@}
  264. //! \name Implementation of base requirements
  265. //!@{
  266. private:
  267. //! 1-wire UART baudrates
  268. enum BR {
  269. BR_STD_RST =9600,
  270. BR_OVR_RST =57600,
  271. BR_STD =115200,
  272. BR_OVR =921600
  273. };
  274. Speed _speed {Speed::STD};
  275. Speed speed () { return _speed; } //!< Get the 1-wire bus speed
  276. void speed (Speed s); //!< Set the 1-wire bus speed
  277. /*!
  278. * \brief
  279. * Read a bit from the 1-Wire bus, return it and provide
  280. * the recovery time.
  281. *
  282. * --- - - - - - - - - - - - - - - - - ------
  283. * Read \ / X X X X X X X X X X X X X X X /
  284. * ---- - - - - - - - - - - - - - - - -
  285. * RS: | | | | | | | | | | |
  286. * bit: ST 0 1 2 3 4 5 6 7 SP
  287. * < ------------- 87/11 usec ------------->
  288. * ^
  289. * |
  290. * Master sample
  291. *
  292. * 8 bits, no parity, 1 stop
  293. * standard: BR: 115200
  294. * Overdrive: BR: 921600
  295. * TX: 0xFF
  296. * RX: {1 - 0xFF, 0 - [0x00 - 0xFE] }
  297. *
  298. * \return The answer
  299. * \arg 0 Read 0
  300. * \arg 1 Read 1 (This is also returned on transition error).
  301. */
  302. bool bit () {
  303. return (UART_RW (0xFF) < 0xFF);
  304. }
  305. /*!
  306. * \brief
  307. * Send a 1-Wire write bit
  308. * 8 bits, no parity, 1 stop
  309. * standard: BR: 115200
  310. * Overdrive: BR: 921600
  311. *
  312. * --- --------------------------------------
  313. * Write 1 \ /
  314. * ----
  315. * RS: | | | | | | | | | | |
  316. * bit: ST 0 1 2 3 4 5 6 7 SP
  317. * TX: 0xFF RX: 0xFF
  318. *
  319. * --- ------
  320. * Write 0 \ /
  321. * -------------------------------------
  322. * RS: | | | | | | | | | | |
  323. * bit: ST 0 1 2 3 4 5 6 7 SP
  324. * < ------------- 87/11 usec ------------->
  325. * TX: 0x00 RX: 0x00
  326. *
  327. * \param b The bit to send
  328. * \return Status of the operation
  329. * \arg 0 Fail
  330. * \arg 1 Success
  331. */
  332. bool bit (bool b) {
  333. uint8_t w = (b) ? 0xFF : 0x00; // Select write frame to send
  334. return (w == UART_RW (w)); // Return status
  335. }
  336. bool _reset ();
  337. //!@}
  338. };
  339. /*!
  340. * Set the 1-wire bus speed for normal operation only
  341. * \note
  342. * We have moved the BR set functionality here to reduce the code inside bit().
  343. * This is OK as long as the _1wire_i<> always check speed.
  344. * \param s The desired speed
  345. */
  346. void _1wire_uart_i<virtual_tag>::speed (Speed s) {
  347. switch (_speed = s) {
  348. case Speed::STD: UART_BR (BR_STD); break;
  349. case Speed::OVDR: UART_BR (BR_OVR); break;
  350. }
  351. }
  352. /*!
  353. * \brief
  354. * Generate a 1-wire reset
  355. *
  356. * --- ---- - - - -------
  357. * Reset \ / \ X X X /
  358. * -------------------- - - - -
  359. * RS: | | | | | | | | | | |
  360. * bit: ST 0 1 2 3 4 5 6 7 SP
  361. * < ---------- 1024/174 usec ------------->
  362. *
  363. * 8 bits, no parity, 1 stop
  364. * Standard: Overdrive :
  365. * BR: 9600, BR: 57600
  366. * TX: 0xF0, TX: 0xF8
  367. * RX: 0xF0 not present RX: 0xF8 not present
  368. * less if present less if present
  369. *
  370. * \param t Timing
  371. * \return The status of the operation
  372. * \arg 0 Fail
  373. * \arg 1 Success
  374. */
  375. bool _1wire_uart_i<virtual_tag>::_reset () {
  376. // Select frame to send
  377. uint8_t w = (_speed == Speed::STD) ? 0xF0 : 0xF8;
  378. // Select baudrate
  379. UART_BR ((_speed == Speed::STD) ? BR_STD_RST : BR_OVR_RST);
  380. // Send frame and check the result
  381. return (UART_RW (w) < w);
  382. }
  383. //!@}
  384. } // namespace utl
  385. #endif /* __utl_com_1wire_uart_h__ */