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.

308 lines
8.0KB

  1. // Copyright 2010 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // -----------------------------------------------------------------------------
  17. //
  18. // Implementation of the I2C protocol (Master mode only for now).
  19. //
  20. // Note that this file is not in the hal directory directly because I don't want
  21. // the interrupt handler code for TWI to be linked with every project.
  22. #ifndef AVRLIB_I2C_I2C_H_
  23. #define AVRLIB_I2C_I2C_H_
  24. #include <util/twi.h>
  25. #include "avrlib/gpio.h"
  26. #include "avrlib/avrlib.h"
  27. #include "avrlib/ring_buffer.h"
  28. namespace avrlib {
  29. IORegister(TWCR);
  30. IORegister(TWSR);
  31. typedef BitInRegister<TWSRRegister, TWPS0> Prescaler0;
  32. typedef BitInRegister<TWSRRegister, TWPS1> Prescaler1;
  33. typedef BitInRegister<TWCRRegister, TWEN> I2cEnable;
  34. typedef BitInRegister<TWCRRegister, TWIE> I2cInterrupt;
  35. typedef BitInRegister<TWCRRegister, TWEA> I2cAck;
  36. typedef BitInRegister<TWCRRegister, TWSTA> I2cStart;
  37. typedef BitInRegister<TWCRRegister, TWSTO> I2cStop;
  38. enum I2cState {
  39. I2C_STATE_READY,
  40. I2C_STATE_TRANSMITTING,
  41. I2C_STATE_RECEIVING,
  42. };
  43. enum I2cError {
  44. I2C_ERROR_NONE = 0xff,
  45. I2C_ERROR_NO_ACK_FOR_ADDRESS = 0x01,
  46. I2C_ERROR_NO_ACK_FOR_DATA = TW_MT_SLA_NACK,
  47. I2C_ERROR_ARBITRATION_LOST = TW_MT_DATA_NACK,
  48. I2C_ERROR_BUS_ERROR = 0xfe,
  49. I2C_ERROR_TIMEOUT = 0x02,
  50. };
  51. template<uint8_t output_buffer_size = 4>
  52. class I2cOutput {
  53. public:
  54. I2cOutput() { }
  55. enum {
  56. buffer_size = output_buffer_size,
  57. data_size = 8
  58. };
  59. typedef typename DataTypeForSize<data_size>::Type Value;
  60. };
  61. template<uint8_t input_buffer_size = 4>
  62. class I2cInput {
  63. public:
  64. I2cInput() { }
  65. enum {
  66. buffer_size = input_buffer_size,
  67. data_size = 8
  68. };
  69. typedef typename DataTypeForSize<data_size>::Type Value;
  70. };
  71. // I2C Handler.
  72. extern void (*i2c_handler_)();
  73. template<uint8_t input_buffer_size = 16,
  74. uint8_t output_buffer_size = 16,
  75. uint32_t frequency = 100000 /* Hz */>
  76. class I2cMaster {
  77. public:
  78. I2cMaster() { }
  79. typedef typename DataTypeForSize<I2cInput<0>::data_size>::Type Value;
  80. static void Init() {
  81. // Prescaler is set to a factor of 1.
  82. Prescaler0::clear();
  83. Prescaler1::clear();
  84. TWBR = (F_CPU / frequency - 16) / 2;
  85. I2cEnable::set();
  86. I2cInterrupt::set();
  87. I2cAck::set();
  88. state_ = I2C_STATE_READY;
  89. i2c_handler_ = &Handler;
  90. }
  91. static void Done() {
  92. I2cInterrupt::clear();
  93. I2cEnable::clear();
  94. I2cAck::clear();
  95. i2c_handler_ = NULL;
  96. }
  97. static uint8_t Wait() {
  98. while (state_ != I2C_STATE_READY) { }
  99. return error_;
  100. }
  101. static uint8_t Wait(uint16_t num_cycles) {
  102. while (state_ != I2C_STATE_READY && num_cycles) {
  103. --num_cycles;
  104. }
  105. if (!num_cycles) {
  106. error_ = I2C_ERROR_TIMEOUT;
  107. }
  108. return error_;
  109. }
  110. static uint8_t Send(uint8_t address) {
  111. // The output buffer is empty, no need to do anything.
  112. if (!Output::readable()) {
  113. return 0;
  114. }
  115. // Sorry, data can be sent only when the line is not busy.
  116. if (state_ != I2C_STATE_READY) {
  117. return 0;
  118. }
  119. error_ = I2C_ERROR_NONE;
  120. state_ = I2C_STATE_RECEIVING;
  121. slarw_ = (address << 1) | TW_WRITE;
  122. uint8_t size = Output::readable();
  123. I2cStart::set();
  124. return size;
  125. }
  126. static uint8_t Request(uint8_t address, uint8_t requested) {
  127. // Make sure that we don't request more than the buffer can hold.
  128. if (requested >= Input::writable()) {
  129. requested = Input::writable() - 1;
  130. }
  131. // Sorry, data can be requested only when the line is not busy.
  132. if (state_ != I2C_STATE_READY) {
  133. return 0;
  134. }
  135. error_ = I2C_ERROR_NONE;
  136. state_ = I2C_STATE_RECEIVING;
  137. slarw_ = (address << 1) | TW_READ;
  138. received_ = 0;
  139. requested_ = requested;
  140. I2cStart::set();
  141. return requested;
  142. }
  143. // All the read/write operations are done on the buffer, so they do not
  144. // block.
  145. static inline void Write(Value v) { Output::Write(v); }
  146. static inline uint8_t writable() { return Output::writable(); }
  147. static inline uint8_t NonBlockingWrite(Value v) {
  148. return Output::NonBlockingWrite(v);
  149. }
  150. static inline void Overwrite(Value v) { Output::Overwrite(v); }
  151. static inline Value Read() { return Input::Read(); }
  152. static inline uint8_t readable() { return Input::readable(); }
  153. static inline int16_t NonBlockingRead() { return Input::NonBlockingRead(); }
  154. static inline Value ImmediateRead() { return Input::ImmediateRead(); }
  155. static inline void FlushInputBuffer() { Input::Flush(); }
  156. static inline void FlushOutputBuffer() { Output::Flush(); }
  157. private:
  158. static inline void Continue(uint8_t ack) {
  159. if (ack) {
  160. TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
  161. } else {
  162. TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
  163. }
  164. }
  165. static inline void Stop() {
  166. I2cStop::set();
  167. while (I2cStop::value()) { }
  168. state_ = I2C_STATE_READY;
  169. }
  170. static inline void Abort() {
  171. TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
  172. state_ = I2C_STATE_READY;
  173. }
  174. static void Handler() {
  175. switch (TW_STATUS) {
  176. case TW_START:
  177. case TW_REP_START:
  178. TWDR = slarw_;
  179. Continue(1);
  180. break;
  181. case TW_MT_DATA_ACK:
  182. case TW_MT_SLA_ACK:
  183. if (Output::readable()) {
  184. TWDR = Output::ImmediateRead();
  185. Continue(1);
  186. } else {
  187. Stop();
  188. }
  189. break;
  190. case TW_MT_SLA_NACK:
  191. case TW_MT_DATA_NACK:
  192. error_ = TW_STATUS;
  193. Stop();
  194. break;
  195. case TW_MT_ARB_LOST:
  196. error_ = I2C_ERROR_ARBITRATION_LOST;
  197. Abort();
  198. break;
  199. case TW_MR_DATA_ACK:
  200. Input::Overwrite(TWDR);
  201. ++received_;
  202. case TW_MR_SLA_ACK:
  203. if (received_ < requested_) {
  204. Continue(1);
  205. } else {
  206. Continue(0);
  207. }
  208. break;
  209. case TW_MR_DATA_NACK:
  210. Input::Overwrite(TWDR);
  211. ++received_;
  212. case TW_MR_SLA_NACK:
  213. Stop();
  214. break;
  215. case TW_NO_INFO:
  216. break;
  217. case TW_BUS_ERROR:
  218. error_ = I2C_ERROR_BUS_ERROR;
  219. Stop();
  220. break;
  221. }
  222. }
  223. public:
  224. typedef RingBuffer<I2cInput<input_buffer_size> > Input;
  225. typedef RingBuffer<I2cOutput<output_buffer_size> > Output;
  226. private:
  227. static volatile uint8_t state_;
  228. static volatile uint8_t error_;
  229. static volatile uint8_t slarw_;
  230. static volatile uint8_t received_;
  231. static uint8_t requested_;
  232. DISALLOW_COPY_AND_ASSIGN(I2cMaster);
  233. };
  234. /* static */
  235. template<uint8_t input_buffer_size, uint8_t output_buffer_size,
  236. uint32_t frequency>
  237. volatile uint8_t I2cMaster<input_buffer_size, output_buffer_size,
  238. frequency>::state_;
  239. /* static */
  240. template<uint8_t input_buffer_size, uint8_t output_buffer_size,
  241. uint32_t frequency>
  242. volatile uint8_t I2cMaster<input_buffer_size, output_buffer_size,
  243. frequency>::error_;
  244. /* static */
  245. template<uint8_t input_buffer_size, uint8_t output_buffer_size,
  246. uint32_t frequency>
  247. volatile uint8_t I2cMaster<input_buffer_size, output_buffer_size,
  248. frequency>::slarw_;
  249. /* static */
  250. template<uint8_t input_buffer_size, uint8_t output_buffer_size,
  251. uint32_t frequency>
  252. volatile uint8_t I2cMaster<input_buffer_size, output_buffer_size, frequency>::received_;
  253. /* static */
  254. template<uint8_t input_buffer_size, uint8_t output_buffer_size,
  255. uint32_t frequency>
  256. uint8_t I2cMaster<input_buffer_size, output_buffer_size, frequency>::requested_;
  257. } // namespace avrlib
  258. #endif // AVRLIB_I2C_I2C_H_