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.

300 lines
8.1 KiB

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