TWIlib.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * TWIlib.c
  3. *
  4. * Created: 6/01/2014 10:41:33 PM
  5. * Author: Chris Herring
  6. */
  7. #include <avr/io.h>
  8. #include <avr/interrupt.h>
  9. #include "TWIlib.h"
  10. #include "util/delay.h"
  11. #include "print.h"
  12. void TWIInit()
  13. {
  14. TWIInfo.mode = Ready;
  15. TWIInfo.errorCode = 0xFF;
  16. TWIInfo.repStart = 0;
  17. // Set pre-scalers (no pre-scaling)
  18. TWSR = 0;
  19. // Set bit rate
  20. TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
  21. // Enable TWI and interrupt
  22. TWCR = (1 << TWIE) | (1 << TWEN);
  23. }
  24. uint8_t isTWIReady()
  25. {
  26. if ( (TWIInfo.mode == Ready) | (TWIInfo.mode == RepeatedStartSent) )
  27. {
  28. // xprintf("i2c ready\n");
  29. return 1;
  30. }
  31. else
  32. {
  33. if(TWIInfo.mode == Initializing){
  34. switch(TWIInfo.errorCode){
  35. case TWI_SUCCESS:
  36. break;
  37. case TWI_NO_RELEVANT_INFO:
  38. break;
  39. case TWI_LOST_ARBIT:
  40. case TWI_MT_DATA_NACK:
  41. // Some kind of I2C error, reset and re-init
  42. xprintf("I2C init error: %d\n", TWIInfo.errorCode);
  43. TWCR = (1 << TWINT)|(1 << TWSTO);
  44. TWIInit();
  45. break;
  46. default:
  47. xprintf("Other i2c init error: %d\n", TWIInfo.errorCode);
  48. }
  49. }
  50. return 0;
  51. }
  52. }
  53. void TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart, uint8_t blocking)
  54. {
  55. // Wait until ready
  56. while (!isTWIReady()) {_delay_us(1);}
  57. // Reset the I2C stuff
  58. TWCR = (1 << TWINT)|(1 << TWSTO);
  59. TWIInit();
  60. // Set repeated start mode
  61. TWIInfo.repStart = repStart;
  62. // Copy transmit info to global variables
  63. TWITransmitBuffer = (uint8_t *)TXdata;
  64. TXBuffLen = dataLen;
  65. TXBuffIndex = 0;
  66. // If a repeated start has been sent, then devices are already listening for an address
  67. // and another start does not need to be sent.
  68. if (TWIInfo.mode == RepeatedStartSent)
  69. {
  70. TWIInfo.mode = Initializing;
  71. TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
  72. TWISendTransmit(); // Send the data
  73. }
  74. else // Otherwise, just send the normal start signal to begin transmission.
  75. {
  76. TWIInfo.mode = Initializing;
  77. TWISendStart();
  78. }
  79. if(blocking){
  80. // Wait until ready
  81. while (!isTWIReady()){_delay_us(1);}
  82. }
  83. }
  84. // uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart)
  85. // {
  86. // if (dataLen <= TXMAXBUFLEN)
  87. // {
  88. // // Wait until ready
  89. // while (!isTWIReady()) {_delay_us(1);}
  90. // // Set repeated start mode
  91. // TWIInfo.repStart = repStart;
  92. // // Copy data into the transmit buffer
  93. // uint8_t *data = (uint8_t *)TXdata;
  94. // for (int i = 0; i < dataLen; i++)
  95. // {
  96. // TWITransmitBuffer[i] = data[i];
  97. // }
  98. // // Copy transmit info to global variables
  99. // TXBuffLen = dataLen;
  100. // TXBuffIndex = 0;
  101. // // If a repeated start has been sent, then devices are already listening for an address
  102. // // and another start does not need to be sent.
  103. // if (TWIInfo.mode == RepeatedStartSent)
  104. // {
  105. // TWIInfo.mode = Initializing;
  106. // TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
  107. // TWISendTransmit(); // Send the data
  108. // }
  109. // else // Otherwise, just send the normal start signal to begin transmission.
  110. // {
  111. // TWIInfo.mode = Initializing;
  112. // TWISendStart();
  113. // }
  114. // }
  115. // else
  116. // {
  117. // return 1; // return an error if data length is longer than buffer
  118. // }
  119. // return 0;
  120. // }
  121. uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart)
  122. {
  123. // Check if number of bytes to read can fit in the RXbuffer
  124. if (bytesToRead < RXMAXBUFLEN)
  125. {
  126. // Reset buffer index and set RXBuffLen to the number of bytes to read
  127. RXBuffIndex = 0;
  128. RXBuffLen = bytesToRead;
  129. // Create the one value array for the address to be transmitted
  130. uint8_t TXdata[1];
  131. // Shift the address and AND a 1 into the read write bit (set to write mode)
  132. TXdata[0] = (TWIaddr << 1) | 0x01;
  133. // Use the TWITransmitData function to initialize the transfer and address the slave
  134. TWITransmitData(TXdata, 1, repStart, 0);
  135. }
  136. else
  137. {
  138. return 0;
  139. }
  140. return 1;
  141. }
  142. ISR (TWI_vect)
  143. {
  144. switch (TWI_STATUS)
  145. {
  146. // ----\/ ---- MASTER TRANSMITTER OR WRITING ADDRESS ----\/ ---- //
  147. case TWI_MT_SLAW_ACK: // SLA+W transmitted and ACK received
  148. // Set mode to Master Transmitter
  149. TWIInfo.mode = MasterTransmitter;
  150. case TWI_START_SENT: // Start condition has been transmitted
  151. case TWI_MT_DATA_ACK: // Data byte has been transmitted, ACK received
  152. if (TXBuffIndex < TXBuffLen) // If there is more data to send
  153. {
  154. TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
  155. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  156. TWISendTransmit(); // Send the data
  157. }
  158. // This transmission is complete however do not release bus yet
  159. else if (TWIInfo.repStart)
  160. {
  161. TWIInfo.errorCode = 0xFF;
  162. TWISendStart();
  163. }
  164. // All transmissions are complete, exit
  165. else
  166. {
  167. TWIInfo.mode = Ready;
  168. TWIInfo.errorCode = 0xFF;
  169. TWISendStop();
  170. }
  171. break;
  172. // ----\/ ---- MASTER RECEIVER ----\/ ---- //
  173. case TWI_MR_SLAR_ACK: // SLA+R has been transmitted, ACK has been received
  174. // Switch to Master Receiver mode
  175. TWIInfo.mode = MasterReceiver;
  176. // If there is more than one byte to be read, receive data byte and return an ACK
  177. if (RXBuffIndex < RXBuffLen-1)
  178. {
  179. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  180. TWISendACK();
  181. }
  182. // Otherwise when a data byte (the only data byte) is received, return NACK
  183. else
  184. {
  185. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  186. TWISendNACK();
  187. }
  188. break;
  189. case TWI_MR_DATA_ACK: // Data has been received, ACK has been transmitted.
  190. /// -- HANDLE DATA BYTE --- ///
  191. TWIReceiveBuffer[RXBuffIndex++] = TWDR;
  192. // If there is more than one byte to be read, receive data byte and return an ACK
  193. if (RXBuffIndex < RXBuffLen-1)
  194. {
  195. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  196. TWISendACK();
  197. }
  198. // Otherwise when a data byte (the only data byte) is received, return NACK
  199. else
  200. {
  201. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  202. TWISendNACK();
  203. }
  204. break;
  205. case TWI_MR_DATA_NACK: // Data byte has been received, NACK has been transmitted. End of transmission.
  206. /// -- HANDLE DATA BYTE --- ///
  207. TWIReceiveBuffer[RXBuffIndex++] = TWDR;
  208. // This transmission is complete however do not release bus yet
  209. if (TWIInfo.repStart)
  210. {
  211. TWIInfo.errorCode = 0xFF;
  212. TWISendStart();
  213. }
  214. // All transmissions are complete, exit
  215. else
  216. {
  217. TWIInfo.mode = Ready;
  218. TWIInfo.errorCode = 0xFF;
  219. TWISendStop();
  220. }
  221. break;
  222. // ----\/ ---- MT and MR common ----\/ ---- //
  223. case TWI_MR_SLAR_NACK: // SLA+R transmitted, NACK received
  224. case TWI_MT_SLAW_NACK: // SLA+W transmitted, NACK received
  225. case TWI_MT_DATA_NACK: // Data byte has been transmitted, NACK received
  226. case TWI_LOST_ARBIT: // Arbitration has been lost
  227. // Return error and send stop and set mode to ready
  228. if (TWIInfo.repStart)
  229. {
  230. TWIInfo.errorCode = TWI_STATUS;
  231. TWISendStart();
  232. }
  233. // All transmissions are complete, exit
  234. else
  235. {
  236. TWIInfo.mode = Ready;
  237. TWIInfo.errorCode = TWI_STATUS;
  238. TWISendStop();
  239. }
  240. break;
  241. case TWI_REP_START_SENT: // Repeated start has been transmitted
  242. // Set the mode but DO NOT clear TWINT as the next data is not yet ready
  243. TWIInfo.mode = RepeatedStartSent;
  244. break;
  245. // ----\/ ---- SLAVE RECEIVER ----\/ ---- //
  246. // TODO IMPLEMENT SLAVE RECEIVER FUNCTIONALITY
  247. // ----\/ ---- SLAVE TRANSMITTER ----\/ ---- //
  248. // TODO IMPLEMENT SLAVE TRANSMITTER FUNCTIONALITY
  249. // ----\/ ---- MISCELLANEOUS STATES ----\/ ---- //
  250. case TWI_NO_RELEVANT_INFO: // It is not really possible to get into this ISR on this condition
  251. // Rather, it is there to be manually set between operations
  252. break;
  253. case TWI_ILLEGAL_START_STOP: // Illegal START/STOP, abort and return error
  254. TWIInfo.errorCode = TWI_ILLEGAL_START_STOP;
  255. TWIInfo.mode = Ready;
  256. TWISendStop();
  257. break;
  258. }
  259. }