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.
 
 
 
 

408 lines
12 KiB

  1. /*!
  2. * \file utl/com/i2c_bb.h
  3. * \brief A bit banking implementation of i2c bus inherited from
  4. * i2c_i base class.
  5. *
  6. * Copyright (C) 2018 Christos Choutouridis
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as
  10. * published by the Free Software Foundation, either version 3
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #ifndef __utl_com_i2c_bb_h__
  23. #define __utl_com_i2c_bb_h__
  24. #include <utl/impl/impl.h>
  25. #include <utl/helper/crtp.h>
  26. #include <utl/com/i2c.h>
  27. namespace utl {
  28. /*!
  29. * \ingroup Communication
  30. * \brief A bit banking implementation of i2c bus
  31. * inherited from \ref i2c_i base class.
  32. * \sa i2c_i
  33. */
  34. //!@{
  35. /*!
  36. * \brief
  37. * I2C bit banking interface template class providing
  38. * an I2C using bit banking using CRTP.
  39. * \param impl_t The CRTP type (the derived/implementation class typename).
  40. */
  41. template <typename impl_t>
  42. class i2c_bb_i : public i2c_i<i2c_bb_i<impl_t>> {
  43. _CRTP_IMPL(impl_t);
  44. friend i2c_i<i2c_bb_i<impl_t>>;
  45. public:
  46. using type = i2c_bb_i<impl_t>; //!< Export type as identity meta-function
  47. using Sequence = typename i2c_i<type>::Sequence;
  48. //! SDA pin direction enumerator
  49. enum class SDAMode {
  50. INPUT =0,
  51. OUTPUT
  52. };
  53. /*!
  54. * \name Object lifetime
  55. */
  56. //!@{
  57. protected:
  58. //! \brief A default destructor, allow destructor from derived only
  59. ~i2c_bb_i () noexcept = default;
  60. //! \brief A default constructor
  61. i2c_bb_i (uint32_t frequency =100000) noexcept
  62. : usec_ {1000000/(2*frequency)} { }
  63. //!@}
  64. /*!
  65. * \name Implementation requirements
  66. * \note
  67. * In order for the implementation to have the following as private members
  68. * it also need to declare this class as friend
  69. * bool SDA (SDAMode mode, bool st);
  70. * void SCL (uint8_t st);
  71. * void delay (uint32_t usec);
  72. */
  73. //!@{
  74. private:
  75. /*!
  76. * Implementers's sda pin function
  77. * \param st In SDA_OUTPUT mode, selects the pin output state
  78. * \return In SDA_INPUT mode return the pin input state
  79. */
  80. bool SDA (SDAMode mode, bool st) { return impl().SDA (mode, st); }
  81. void SCL (uint8_t st) { impl().SCL (st); } //!< Implementers's scl pin function
  82. void delay (uint32_t usec) { impl().delay(usec); } //!< Implementers's usec delay function
  83. //!@}
  84. /*!
  85. * \name Implementation of base requirements
  86. */
  87. //!@{
  88. private:
  89. uint32_t _frequency () const { return 1000000/(2*usec_); }
  90. void _frequency (uint32_t f) { usec_ = 1000000/(2*f); }
  91. void _start (); //!< Send start functionality
  92. void _stop (); //!< Send stop functionality
  93. byte_t _read (bool ack, Sequence seq);
  94. bool _write (byte_t byte, Sequence seq);
  95. uint32_t usec_; //!< half period of I2C nus
  96. //!@}
  97. };
  98. /*
  99. * ============= User functions ================
  100. */
  101. /*!
  102. * \brief
  103. * Send a START bit to the bus
  104. * \return none
  105. */
  106. template <typename impl_t>
  107. void i2c_bb_i<impl_t>::_start (void) {
  108. //Initially set pins
  109. SDA (SDAMode::OUTPUT, 1);
  110. SCL (1);
  111. delay (usec_);
  112. SDA (SDAMode::OUTPUT, 0);
  113. delay (usec_);
  114. SCL (0); //Clear Clock
  115. }
  116. /*!
  117. * \brief
  118. * Send a START bit to the bus
  119. * \return none
  120. */
  121. template <typename impl_t>
  122. void i2c_bb_i<impl_t>::_stop (void) {
  123. //Stop bit Operation
  124. SDA (SDAMode::OUTPUT, 0);
  125. SCL (0);
  126. SCL (1);
  127. delay (usec_);
  128. SDA (SDAMode::OUTPUT, 1);
  129. delay (usec_);
  130. }
  131. /*!
  132. * \brief
  133. * Receive a byte from the i2c bus.
  134. * \param ack Optional ack bit.
  135. * \arg 1 ACK the reception
  136. * \arg 0 Don't ACK the reception.
  137. * \param seq The operation sequence to execute
  138. * \arg Sequence::BYTE Receive only the byte, do not send ack clock
  139. * \arg Sequence::ACK Send only the ack bit
  140. * \arg Sequence::BYTEnACK Receive the byte and send the ack bit
  141. * \return The byte received.
  142. */
  143. template <typename impl_t>
  144. byte_t i2c_bb_i<impl_t>::_read (bool ack, Sequence seq) {
  145. byte_t byte {0};
  146. //Initial conditions
  147. SCL (0);
  148. SDA (SDAMode::INPUT, 0);
  149. if (seq == Sequence::BYTE || seq == Sequence::BYTEnACK) {
  150. // read 8 data bits
  151. for (int i=8 ; i!=0 ; --i) {
  152. byte <<= 1;
  153. SCL (1);
  154. delay (usec_);
  155. byte |= SDA (SDAMode::INPUT, 0);
  156. SCL (0);
  157. delay (usec_);
  158. }
  159. }
  160. if (seq == Sequence::ACK || seq == Sequence::BYTEnACK) {
  161. SDA (SDAMode::OUTPUT, !ack); //Send (or not) ACK bit
  162. SCL (1);
  163. delay (usec_);
  164. SCL (0); // Keep the bus busy
  165. SDA (SDAMode::OUTPUT, 0);
  166. }
  167. return byte;
  168. }
  169. /*!
  170. * \brief
  171. * Transmit a byte to the i2c bus.
  172. * \param byte The byte to send.
  173. * \param seq The operation sequence to execute
  174. * \arg Sequence::BYTE Transmit only the byte, do not read ack bit
  175. * \arg Sequence::ACK Read only the ack bit
  176. * \arg Sequence::BYTEnACK Transmit the byte and read the ack bit
  177. * \return Slave's ACK bit
  178. * \arg false Slave didn't ACK
  179. * \arg true Slave did ACK
  180. */
  181. template <typename impl_t>
  182. bool i2c_bb_i<impl_t>::_write (byte_t byte, Sequence seq) {
  183. bool ack {false};
  184. //Initial conditions
  185. SCL (0);
  186. SDA (SDAMode::OUTPUT, 0);
  187. if (seq == Sequence::BYTE || seq == Sequence::BYTEnACK) {
  188. //Send 8 bit data
  189. for (int i=8 ; i!=0 ; --i) {
  190. //Send MSB
  191. SDA (SDAMode::OUTPUT, byte & 0x80);
  192. byte <<= 1;
  193. SCL (1);
  194. delay (usec_);
  195. SCL (0);
  196. delay (usec_);
  197. }
  198. }
  199. if (seq == Sequence::ACK || seq == Sequence::BYTEnACK) {
  200. // Get ACK
  201. SDA (SDAMode::INPUT, 0);
  202. SCL (1);
  203. delay (usec_);
  204. ack = !SDA (SDAMode::INPUT, 0);
  205. SCL (0); // Keep the bus busy
  206. delay (usec_);
  207. SDA (SDAMode::OUTPUT, 0);
  208. }
  209. return ack;
  210. }
  211. /*!
  212. * \brief
  213. * A virtual base class interface specialization.
  214. * Using the private virtual interface we provide the interface from
  215. * i2c_i<virtual_tag>
  216. * \param impl_t = virtual_tag
  217. */
  218. template<>
  219. class i2c_bb_i<virtual_tag> : public i2c_i<virtual_tag> {
  220. public:
  221. using type = i2c_bb_i<virtual_tag>; //!< Export type as identity meta-function
  222. using Sequence = typename i2c_i<virtual_tag>::Sequence;
  223. //! SDA pin direction enumerator
  224. enum class SDAMode {
  225. INPUT =0,
  226. OUTPUT
  227. };
  228. /*!
  229. * \name Object lifetime
  230. */
  231. //!@{
  232. protected:
  233. //! \brief Constructor
  234. i2c_bb_i (uint32_t frequency =100000) noexcept
  235. : usec_ {1000000/(2*frequency)} { }
  236. //! \brief Virtual destructor
  237. virtual ~i2c_bb_i () noexcept = default;
  238. //!@}
  239. /*!
  240. * \name Implementation requirements
  241. */
  242. //!@{
  243. private:
  244. /*!
  245. * Implementers's sda pin function
  246. * \param st In SDA_OUTPUT mode, selects the pin output state
  247. * \return In SDA_INPUT mode return the pin input state
  248. */
  249. virtual bool SDA (SDAMode mode, bool st) =0;
  250. virtual void SCL (bool st) =0; //!< Implementers's scl pin function
  251. virtual void delay (uint32_t usec) =0; //!< Implementers's usec delay function
  252. //!@}
  253. /*!
  254. * \name Implementation of base requirements
  255. */
  256. //!@{
  257. private:
  258. uint32_t _frequency () const final { return 1000000/(2*usec_); }
  259. void _frequency (uint32_t f) final { usec_ = 1000000/(2*f); }
  260. void _start () final;
  261. void _stop () final;
  262. byte_t _read (bool ack, Sequence seq) final;
  263. bool _write (byte_t byte, Sequence seq) final;
  264. //!< half period of I2C bus
  265. uint32_t usec_;
  266. //!@}
  267. };
  268. /*!
  269. * \brief
  270. * Send a START bit to the bus
  271. * \return none
  272. */
  273. void i2c_bb_i<virtual_tag>::_start (void) {
  274. //Initially set pins
  275. SDA (SDAMode::OUTPUT, 1);
  276. SCL (1);
  277. delay (usec_);
  278. SDA (SDAMode::OUTPUT, 0);
  279. delay (usec_);
  280. SCL (0); //Clear Clock
  281. }
  282. /*!
  283. * \brief
  284. * Send a START bit to the bus
  285. * \return none
  286. */
  287. void i2c_bb_i<virtual_tag>::_stop (void) {
  288. //Stop bit Operation
  289. SDA (SDAMode::OUTPUT, 0);
  290. SCL (0);
  291. SCL (1);
  292. delay (usec_);
  293. SDA (SDAMode::OUTPUT, 1);
  294. delay (usec_);
  295. }
  296. /*!
  297. * \brief
  298. * Receive a byte from the i2c bus.
  299. * \param ack Optional ack bit.
  300. * \arg 1 ACK the reception
  301. * \arg 0 Don't ACK the reception.
  302. * \param seq The operation sequence to execute
  303. * \arg Sequence::BYTE Receive only the byte, do not send ack clock
  304. * \arg Sequence::ACK Send only the ack bit
  305. * \arg Sequence::BYTEnACK Receive the byte and send the ack bit
  306. * \return The byte received.
  307. */
  308. byte_t i2c_bb_i<virtual_tag>::_read (bool ack, Sequence seq) {
  309. byte_t byte {0};
  310. //Initial conditions
  311. SCL (0);
  312. SDA (SDAMode::INPUT, 0);
  313. if (seq == Sequence::BYTE || seq == Sequence::BYTEnACK) {
  314. // read 8 data bits
  315. for (int i=8 ; i!=0 ; --i) {
  316. byte <<= 1;
  317. SCL (1);
  318. delay (usec_);
  319. byte |= SDA (SDAMode::INPUT, 0);
  320. SCL (0);
  321. delay (usec_);
  322. }
  323. }
  324. if (seq == Sequence::ACK || seq == Sequence::BYTEnACK) {
  325. SDA (SDAMode::OUTPUT, !ack); //Send (or not) ACK bit
  326. SCL (1);
  327. delay (usec_);
  328. SCL (0); // Keep the bus busy
  329. SDA (SDAMode::OUTPUT, 0);
  330. }
  331. return byte;
  332. }
  333. /*!
  334. * \brief
  335. * Transmit a byte to the i2c bus.
  336. * \param byte The byte to send.
  337. * \param seq The operation sequence to execute
  338. * \arg Sequence::BYTE Transmit only the byte, do not read ack bit
  339. * \arg Sequence::ACK Read only the ack bit
  340. * \arg Sequence::BYTEnACK Transmit the byte and read the ack bit
  341. * \return Slave's ACK bit
  342. * \arg false Slave didn't ACK
  343. * \arg true Slave did ACK
  344. */
  345. bool i2c_bb_i<virtual_tag>::_write (byte_t byte, Sequence seq) {
  346. bool ack {false};
  347. //Initial conditions
  348. SCL (0);
  349. SDA (SDAMode::OUTPUT, 0);
  350. if (seq == Sequence::BYTE || seq == Sequence::BYTEnACK) {
  351. //Send 8 bit data
  352. for (int i=8 ; i!=0 ; --i) {
  353. //Send MSB
  354. SDA (SDAMode::OUTPUT, byte & 0x80);
  355. byte <<= 1;
  356. SCL (1);
  357. delay (usec_);
  358. SCL (0);
  359. delay (usec_);
  360. }
  361. }
  362. if (seq == Sequence::ACK || seq == Sequence::BYTEnACK) {
  363. // Get ACK
  364. SDA (SDAMode::INPUT, 0);
  365. SCL (1);
  366. delay (usec_);
  367. ack = !SDA (SDAMode::INPUT, 0);
  368. SCL (0); // Keep the bus busy
  369. delay (usec_);
  370. SDA (SDAMode::OUTPUT, 0);
  371. }
  372. return ack;
  373. }
  374. //!@}
  375. } // namspace utl
  376. #endif // #ifndef __utl_com_i2c_bb_h__