Micro template library A library for building device drivers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

413 lines
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__ */