PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

342 line
8.1KB

  1. /*
  2. TwoWire.cpp - TWI/I2C library for Wiring & Arduino
  3. Copyright (c) 2006 Nicholas Zambetti. All right reserved.
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
  16. */
  17. #include <Arduino.h>
  18. #if defined(__AVR__)
  19. #include "Wire.h"
  20. extern "C" {
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <inttypes.h>
  24. #include "twi.h"
  25. }
  26. // Initialize Class Variables //////////////////////////////////////////////////
  27. uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
  28. uint8_t TwoWire::rxBufferIndex = 0;
  29. uint8_t TwoWire::rxBufferLength = 0;
  30. uint8_t TwoWire::txAddress = 0;
  31. uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
  32. uint8_t TwoWire::txBufferIndex = 0;
  33. uint8_t TwoWire::txBufferLength = 0;
  34. uint8_t TwoWire::transmitting = 0;
  35. void (*TwoWire::user_onRequest)(void);
  36. void (*TwoWire::user_onReceive)(int);
  37. // Constructors ////////////////////////////////////////////////////////////////
  38. TwoWire::TwoWire()
  39. {
  40. }
  41. // Public Methods //////////////////////////////////////////////////////////////
  42. void TwoWire::begin(void)
  43. {
  44. rxBufferIndex = 0;
  45. rxBufferLength = 0;
  46. txBufferIndex = 0;
  47. txBufferLength = 0;
  48. twi_init();
  49. }
  50. void TwoWire::begin(uint8_t address)
  51. {
  52. twi_setAddress(address);
  53. twi_attachSlaveTxEvent(onRequestService);
  54. twi_attachSlaveRxEvent(onReceiveService);
  55. begin();
  56. }
  57. void TwoWire::begin(int address)
  58. {
  59. begin((uint8_t)address);
  60. }
  61. void TwoWire::end()
  62. {
  63. TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
  64. digitalWrite(SDA, 0);
  65. digitalWrite(SCL, 0);
  66. }
  67. void TwoWire::setClock(uint32_t frequency)
  68. {
  69. TWBR = ((F_CPU / frequency) - 16) / 2;
  70. }
  71. void TwoWire::setSDA(uint8_t pin)
  72. {
  73. }
  74. void TwoWire::setSCL(uint8_t pin)
  75. {
  76. }
  77. uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
  78. {
  79. // clamp to buffer length
  80. if(quantity > BUFFER_LENGTH){
  81. quantity = BUFFER_LENGTH;
  82. }
  83. // perform blocking read into buffer
  84. uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
  85. // set rx buffer iterator vars
  86. rxBufferIndex = 0;
  87. rxBufferLength = read;
  88. return read;
  89. }
  90. uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
  91. {
  92. return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
  93. }
  94. uint8_t TwoWire::requestFrom(int address, int quantity)
  95. {
  96. return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
  97. }
  98. uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
  99. {
  100. return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
  101. }
  102. uint8_t TwoWire::requestFrom(uint8_t addr, uint8_t qty, uint32_t iaddr, uint8_t n, uint8_t stop)
  103. {
  104. if (n > 0) {
  105. union { uint32_t ul; uint8_t b[4]; } iaddress;
  106. iaddress.ul = iaddr;
  107. beginTransmission(addr);
  108. if (n > 3) n = 3;
  109. do {
  110. n = n - 1;
  111. write(iaddress.b[n]);
  112. } while (n > 0);
  113. endTransmission(false);
  114. }
  115. if (qty > BUFFER_LENGTH) qty = BUFFER_LENGTH;
  116. return requestFrom(addr, qty, stop);
  117. }
  118. void TwoWire::beginTransmission(uint8_t address)
  119. {
  120. // indicate that we are transmitting
  121. transmitting = 1;
  122. // set address of targeted slave
  123. txAddress = address;
  124. // reset tx buffer iterator vars
  125. txBufferIndex = 0;
  126. txBufferLength = 0;
  127. }
  128. void TwoWire::beginTransmission(int address)
  129. {
  130. beginTransmission((uint8_t)address);
  131. }
  132. //
  133. // Originally, 'endTransmission' was an f(void) function.
  134. // It has been modified to take one parameter indicating
  135. // whether or not a STOP should be performed on the bus.
  136. // Calling endTransmission(false) allows a sketch to
  137. // perform a repeated start.
  138. //
  139. // WARNING: Nothing in the library keeps track of whether
  140. // the bus tenure has been properly ended with a STOP. It
  141. // is very possible to leave the bus in a hung state if
  142. // no call to endTransmission(true) is made. Some I2C
  143. // devices will behave oddly if they do not see a STOP.
  144. //
  145. uint8_t TwoWire::endTransmission(uint8_t sendStop)
  146. {
  147. // transmit buffer (blocking)
  148. int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
  149. // reset tx buffer iterator vars
  150. txBufferIndex = 0;
  151. txBufferLength = 0;
  152. // indicate that we are done transmitting
  153. transmitting = 0;
  154. return ret;
  155. }
  156. // This provides backwards compatibility with the original
  157. // definition, and expected behaviour, of endTransmission
  158. //
  159. uint8_t TwoWire::endTransmission(void)
  160. {
  161. return endTransmission(true);
  162. }
  163. // must be called in:
  164. // slave tx event callback
  165. // or after beginTransmission(address)
  166. size_t TwoWire::write(uint8_t data)
  167. {
  168. if(transmitting){
  169. // in master transmitter mode
  170. // don't bother if buffer is full
  171. if(txBufferLength >= BUFFER_LENGTH){
  172. setWriteError();
  173. return 0;
  174. }
  175. // put byte in tx buffer
  176. txBuffer[txBufferIndex] = data;
  177. ++txBufferIndex;
  178. // update amount in buffer
  179. txBufferLength = txBufferIndex;
  180. }else{
  181. // in slave send mode
  182. // reply to master
  183. twi_transmit(&data, 1);
  184. }
  185. return 1;
  186. }
  187. // must be called in:
  188. // slave tx event callback
  189. // or after beginTransmission(address)
  190. size_t TwoWire::write(const uint8_t *data, size_t quantity)
  191. {
  192. if(transmitting){
  193. // in master transmitter mode
  194. for(size_t i = 0; i < quantity; ++i){
  195. write(data[i]);
  196. }
  197. }else{
  198. // in slave send mode
  199. // reply to master
  200. twi_transmit(data, quantity);
  201. }
  202. return quantity;
  203. }
  204. // must be called in:
  205. // slave rx event callback
  206. // or after requestFrom(address, numBytes)
  207. int TwoWire::available(void)
  208. {
  209. return rxBufferLength - rxBufferIndex;
  210. }
  211. // must be called in:
  212. // slave rx event callback
  213. // or after requestFrom(address, numBytes)
  214. int TwoWire::read(void)
  215. {
  216. int value = -1;
  217. // get each successive byte on each call
  218. if(rxBufferIndex < rxBufferLength){
  219. value = rxBuffer[rxBufferIndex];
  220. ++rxBufferIndex;
  221. }
  222. return value;
  223. }
  224. // must be called in:
  225. // slave rx event callback
  226. // or after requestFrom(address, numBytes)
  227. int TwoWire::peek(void)
  228. {
  229. int value = -1;
  230. if(rxBufferIndex < rxBufferLength){
  231. value = rxBuffer[rxBufferIndex];
  232. }
  233. return value;
  234. }
  235. void TwoWire::flush(void)
  236. {
  237. // XXX: to be implemented.
  238. }
  239. // behind the scenes function that is called when data is received
  240. void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
  241. {
  242. // don't bother if user hasn't registered a callback
  243. if(!user_onReceive){
  244. return;
  245. }
  246. // don't bother if rx buffer is in use by a master requestFrom() op
  247. // i know this drops data, but it allows for slight stupidity
  248. // meaning, they may not have read all the master requestFrom() data yet
  249. if(rxBufferIndex < rxBufferLength){
  250. return;
  251. }
  252. // copy twi rx buffer into local read buffer
  253. // this enables new reads to happen in parallel
  254. for(uint8_t i = 0; i < numBytes; ++i){
  255. rxBuffer[i] = inBytes[i];
  256. }
  257. // set rx iterator vars
  258. rxBufferIndex = 0;
  259. rxBufferLength = numBytes;
  260. // alert user program
  261. user_onReceive(numBytes);
  262. }
  263. // behind the scenes function that is called when data is requested
  264. void TwoWire::onRequestService(void)
  265. {
  266. // don't bother if user hasn't registered a callback
  267. if(!user_onRequest){
  268. return;
  269. }
  270. // reset tx buffer iterator vars
  271. // !!! this will kill any pending pre-master sendTo() activity
  272. txBufferIndex = 0;
  273. txBufferLength = 0;
  274. // alert user program
  275. user_onRequest();
  276. }
  277. // sets function called on slave write
  278. void TwoWire::onReceive( void (*function)(int) )
  279. {
  280. user_onReceive = function;
  281. }
  282. // sets function called on slave read
  283. void TwoWire::onRequest( void (*function)(void) )
  284. {
  285. user_onRequest = function;
  286. }
  287. // Preinstantiate Objects //////////////////////////////////////////////////////
  288. TwoWire Wire = TwoWire();
  289. #endif // __AVR__