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.

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