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.

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