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.

232 lines
6.2 KiB

  1. /*
  2. * TWIlib.c
  3. *
  4. * Created: 6/01/2014 10:41:33 PM
  5. * Author: Chris Herring
  6. * http://www.chrisherring.net/all/tutorial-interrupt-driven-twi-interface-for-avr-part1/
  7. */
  8. #include <avr/io.h>
  9. #include <avr/interrupt.h>
  10. #include "TWIlib.h"
  11. #include "util/delay.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. return 0;
  33. }
  34. }
  35. uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart)
  36. {
  37. if (dataLen <= TXMAXBUFLEN)
  38. {
  39. // Wait until ready
  40. while (!isTWIReady()) {_delay_us(1);}
  41. // Set repeated start mode
  42. TWIInfo.repStart = repStart;
  43. // Copy data into the transmit buffer
  44. uint8_t *data = (uint8_t *)TXdata;
  45. for (int i = 0; i < dataLen; i++)
  46. {
  47. TWITransmitBuffer[i] = data[i];
  48. }
  49. // Copy transmit info to global variables
  50. TXBuffLen = dataLen;
  51. TXBuffIndex = 0;
  52. // If a repeated start has been sent, then devices are already listening for an address
  53. // and another start does not need to be sent.
  54. if (TWIInfo.mode == RepeatedStartSent)
  55. {
  56. TWIInfo.mode = Initializing;
  57. TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
  58. TWISendTransmit(); // Send the data
  59. }
  60. else // Otherwise, just send the normal start signal to begin transmission.
  61. {
  62. TWIInfo.mode = Initializing;
  63. TWISendStart();
  64. }
  65. }
  66. else
  67. {
  68. return 1; // return an error if data length is longer than buffer
  69. }
  70. return 0;
  71. }
  72. uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart)
  73. {
  74. // Check if number of bytes to read can fit in the RXbuffer
  75. if (bytesToRead < RXMAXBUFLEN)
  76. {
  77. // Reset buffer index and set RXBuffLen to the number of bytes to read
  78. RXBuffIndex = 0;
  79. RXBuffLen = bytesToRead;
  80. // Create the one value array for the address to be transmitted
  81. uint8_t TXdata[1];
  82. // Shift the address and AND a 1 into the read write bit (set to write mode)
  83. TXdata[0] = (TWIaddr << 1) | 0x01;
  84. // Use the TWITransmitData function to initialize the transfer and address the slave
  85. TWITransmitData(TXdata, 1, repStart);
  86. }
  87. else
  88. {
  89. return 0;
  90. }
  91. return 1;
  92. }
  93. ISR (TWI_vect)
  94. {
  95. switch (TWI_STATUS)
  96. {
  97. // ----\/ ---- MASTER TRANSMITTER OR WRITING ADDRESS ----\/ ---- //
  98. case TWI_MT_SLAW_ACK: // SLA+W transmitted and ACK received
  99. // Set mode to Master Transmitter
  100. TWIInfo.mode = MasterTransmitter;
  101. case TWI_START_SENT: // Start condition has been transmitted
  102. case TWI_MT_DATA_ACK: // Data byte has been transmitted, ACK received
  103. if (TXBuffIndex < TXBuffLen) // If there is more data to send
  104. {
  105. TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer
  106. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  107. TWISendTransmit(); // Send the data
  108. }
  109. // This transmission is complete however do not release bus yet
  110. else if (TWIInfo.repStart)
  111. {
  112. TWIInfo.errorCode = 0xFF;
  113. TWISendStart();
  114. }
  115. // All transmissions are complete, exit
  116. else
  117. {
  118. TWIInfo.mode = Ready;
  119. TWIInfo.errorCode = 0xFF;
  120. TWISendStop();
  121. }
  122. break;
  123. // ----\/ ---- MASTER RECEIVER ----\/ ---- //
  124. case TWI_MR_SLAR_ACK: // SLA+R has been transmitted, ACK has been received
  125. // Switch to Master Receiver mode
  126. TWIInfo.mode = MasterReceiver;
  127. // If there is more than one byte to be read, receive data byte and return an ACK
  128. if (RXBuffIndex < RXBuffLen-1)
  129. {
  130. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  131. TWISendACK();
  132. }
  133. // Otherwise when a data byte (the only data byte) is received, return NACK
  134. else
  135. {
  136. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  137. TWISendNACK();
  138. }
  139. break;
  140. case TWI_MR_DATA_ACK: // Data has been received, ACK has been transmitted.
  141. /// -- HANDLE DATA BYTE --- ///
  142. TWIReceiveBuffer[RXBuffIndex++] = TWDR;
  143. // If there is more than one byte to be read, receive data byte and return an ACK
  144. if (RXBuffIndex < RXBuffLen-1)
  145. {
  146. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  147. TWISendACK();
  148. }
  149. // Otherwise when a data byte (the only data byte) is received, return NACK
  150. else
  151. {
  152. TWIInfo.errorCode = TWI_NO_RELEVANT_INFO;
  153. TWISendNACK();
  154. }
  155. break;
  156. case TWI_MR_DATA_NACK: // Data byte has been received, NACK has been transmitted. End of transmission.
  157. /// -- HANDLE DATA BYTE --- ///
  158. TWIReceiveBuffer[RXBuffIndex++] = TWDR;
  159. // This transmission is complete however do not release bus yet
  160. if (TWIInfo.repStart)
  161. {
  162. TWIInfo.errorCode = 0xFF;
  163. TWISendStart();
  164. }
  165. // All transmissions are complete, exit
  166. else
  167. {
  168. TWIInfo.mode = Ready;
  169. TWIInfo.errorCode = 0xFF;
  170. TWISendStop();
  171. }
  172. break;
  173. // ----\/ ---- MT and MR common ----\/ ---- //
  174. case TWI_MR_SLAR_NACK: // SLA+R transmitted, NACK received
  175. case TWI_MT_SLAW_NACK: // SLA+W transmitted, NACK received
  176. case TWI_MT_DATA_NACK: // Data byte has been transmitted, NACK received
  177. case TWI_LOST_ARBIT: // Arbitration has been lost
  178. // Return error and send stop and set mode to ready
  179. if (TWIInfo.repStart)
  180. {
  181. TWIInfo.errorCode = TWI_STATUS;
  182. TWISendStart();
  183. }
  184. // All transmissions are complete, exit
  185. else
  186. {
  187. TWIInfo.mode = Ready;
  188. TWIInfo.errorCode = TWI_STATUS;
  189. TWISendStop();
  190. }
  191. break;
  192. case TWI_REP_START_SENT: // Repeated start has been transmitted
  193. // Set the mode but DO NOT clear TWINT as the next data is not yet ready
  194. TWIInfo.mode = RepeatedStartSent;
  195. break;
  196. // ----\/ ---- SLAVE RECEIVER ----\/ ---- //
  197. // TODO IMPLEMENT SLAVE RECEIVER FUNCTIONALITY
  198. // ----\/ ---- SLAVE TRANSMITTER ----\/ ---- //
  199. // TODO IMPLEMENT SLAVE TRANSMITTER FUNCTIONALITY
  200. // ----\/ ---- MISCELLANEOUS STATES ----\/ ---- //
  201. case TWI_NO_RELEVANT_INFO: // It is not really possible to get into this ISR on this condition
  202. // Rather, it is there to be manually set between operations
  203. break;
  204. case TWI_ILLEGAL_START_STOP: // Illegal START/STOP, abort and return error
  205. TWIInfo.errorCode = TWI_ILLEGAL_START_STOP;
  206. TWIInfo.mode = Ready;
  207. TWISendStop();
  208. break;
  209. }
  210. }