eBoard ๐Ÿ‰  โ‘ โ‘งโ‘จ
Written for SIA 2017/2018
eagle_Twi.h
Go to the documentation of this file.
1 #ifndef EAGLE_EBOARD_HELPLIB_TWI
2  #define EAGLE_EBOARD_HELPLIB_TWI
3 
12 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
13 // Undocumented
14 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15 
16  #ifndef TWI_FREQ
17  #define TWI_FREQ 100000L
18  #endif
19 
20  #include <inttypes.h>
21 
22  //#define ATMEGA8
23 
24  #ifndef TWI_FREQ
25  #define TWI_FREQ 100000L
26  #endif
27 
28  #ifndef TWI_BUFFER_LENGTH
29  #define TWI_BUFFER_LENGTH 32
30  #endif
31 
32  #define TWI_READY 0
33  #define TWI_MRX 1
34  #define TWI_MTX 2
35  #define TWI_SRX 3
36  #define TWI_STX 4
37 
38  void twi_init(void);
39  void twi_disable(void);
40  void twi_setAddress(uint8_t);
41  void twi_setFrequency(uint32_t);
42  uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
43  uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
44  uint8_t twi_transmit(const uint8_t*, uint8_t);
45  void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
46  void twi_attachSlaveTxEvent( void (*)(void) );
47  void twi_reply(uint8_t);
48  void twi_stop(void);
49  void twi_releaseBus(void);
50 
52  #ifndef TWI_BUFFER_LENGTH
53  #define TWI_BUFFER_LENGTH 32
54  #endif
55 
56  #define TWI_READY 0
57  #define TWI_MRX 1
58  #define TWI_MTX 2
59  #define TWI_SRX 3
60  #define TWI_STX 4
61 
62  //#include <inttypes.h>
63  //#include <avr/io.h>
64  #include <avr/interrupt.h>
65  #include <compat/twi.h>
66 
67  #ifndef cbi
68  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
69  #endif
70 
71  #ifndef sbi
72  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
73  #endif
74 
75  #include "pins_arduino.h"
76 
77  static volatile uint8_t twi_state;
78  static volatile uint8_t twi_slarw;
79  static volatile uint8_t twi_sendStop;
80  static volatile uint8_t twi_inRepStart;
81 
82  static void (*twi_onSlaveTransmit)(void);
83  static void (*twi_onSlaveReceive)(uint8_t*, int);
84 
85  static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
86  static volatile uint8_t twi_masterBufferIndex;
87  static volatile uint8_t twi_masterBufferLength;
88 
89  static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
90  static volatile uint8_t twi_txBufferIndex;
91  static volatile uint8_t twi_txBufferLength;
92 
93  static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
94  static volatile uint8_t twi_rxBufferIndex;
95 
96  static volatile uint8_t twi_error;
97 
98 
99  inline void twi_setAddress(uint8_t address) {
100  TWAR = address << 1;
101  }
102 
103  void twi_init(void) {
104  twi_state = TWI_READY;
105  twi_sendStop = true;
106  twi_inRepStart = false;
107 
108  digitalWrite(SDA, 1);
109  digitalWrite(SCL, 1);
110 
111  cbi(TWSR, TWPS0);
112  cbi(TWSR, TWPS1);
113  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
114 
115  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
116  }
117 
118  uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) {
119  uint8_t i;
120 
121  if(TWI_BUFFER_LENGTH < length) return 0;
122 
123  while(TWI_READY != twi_state) continue;
124 
125  twi_state = TWI_MRX;
126  twi_sendStop = sendStop;
127 
128  twi_error = 0xFF;
129 
130  twi_masterBufferIndex = 0;
131  twi_masterBufferLength = length-1;
132  twi_slarw = TW_READ;
133  twi_slarw |= address << 1;
134 
135  if (true == twi_inRepStart) {
136  twi_inRepStart = false;
137  TWDR = twi_slarw;
138  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
139  }
140  else
141  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
142 
143  while(TWI_MRX == twi_state) continue;
144 
145  if (twi_masterBufferIndex < length)
146  length = twi_masterBufferIndex;
147 
148  for(i = 0; i < length; ++i) data[i] = twi_masterBuffer[i];
149 
150  return length;
151  }
152 
153  uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) {
154  uint8_t i;
155 
156  if(TWI_BUFFER_LENGTH < length) return 1;
157 
158  while(TWI_READY != twi_state) continue;
159 
160  twi_state = TWI_MTX;
161  twi_sendStop = sendStop;
162  twi_error = 0xFF;
163 
164  twi_masterBufferIndex = 0;
165  twi_masterBufferLength = length;
166 
167  for(i = 0; i < length; ++i) twi_masterBuffer[i] = data[i];
168 
169  twi_slarw = TW_WRITE;
170  twi_slarw |= address << 1;
171 
172  if (true == twi_inRepStart) {
173  twi_inRepStart = false;
174  TWDR = twi_slarw;
175  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
176  }
177  else
178  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
179 
180  while(wait && (TWI_MTX == twi_state)) continue;
181 
182  if (twi_error == 0xFF) return 0;
183  else if (twi_error == TW_MT_SLA_NACK) return 2;
184  else if (twi_error == TW_MT_DATA_NACK) return 3;
185  else return 4;
186  }
187 
188  uint8_t twi_transmit(const uint8_t* data, uint8_t length) {
189  uint8_t i;
190 
191  if(TWI_BUFFER_LENGTH < length) return 1;
192 
193  if(TWI_STX != twi_state) return 2;
194 
195  twi_txBufferLength = length;
196  for(i = 0; i < length; ++i) twi_txBuffer[i] = data[i];
197 
198  return 0;
199  }
200 
201  void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) {
202  twi_onSlaveReceive = function;
203  }
204 
205  void twi_attachSlaveTxEvent( void (*function)(void) ) {
206  twi_onSlaveTransmit = function;
207  }
208 
209  void twi_reply(uint8_t ack) {
210  if(ack){
211  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
212  }else{
213  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
214  }
215  }
216 
217 
218  void twi_stop(void) {
219  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
220 
221  while(TWCR & _BV(TWSTO)) continue;
222 
223  twi_state = TWI_READY;
224  }
225 
226  void twi_releaseBus(void){
227  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
228  twi_state = TWI_READY;
229  }
230 
231  ISR(TWI_vect) {
232  switch(TW_STATUS){
233  case TW_START:
234  case TW_REP_START:
235  TWDR = twi_slarw;
236  twi_reply(1);
237  break;
238 
239  case TW_MT_SLA_ACK:
240  case TW_MT_DATA_ACK:
241  if(twi_masterBufferIndex < twi_masterBufferLength){
242  TWDR = twi_masterBuffer[twi_masterBufferIndex++];
243  twi_reply(1);
244  }else{
245  if (twi_sendStop) twi_stop();
246  else {
247  twi_inRepStart = true;
248  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
249  twi_state = TWI_READY;
250  }
251  }
252  break;
253  case TW_MT_SLA_NACK:
254  twi_error = TW_MT_SLA_NACK;
255  twi_stop();
256  break;
257  case TW_MT_DATA_NACK:
258  twi_error = TW_MT_DATA_NACK;
259  twi_stop();
260  break;
261  case TW_MT_ARB_LOST:
262  twi_error = TW_MT_ARB_LOST;
263  twi_releaseBus();
264  break;
265  case TW_MR_DATA_ACK:
266  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
267  case TW_MR_SLA_ACK:
268  if(twi_masterBufferIndex < twi_masterBufferLength) twi_reply(1);
269  else twi_reply(0);
270  break;
271  case TW_MR_DATA_NACK:
272  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
273  if (twi_sendStop) twi_stop();
274  else {
275  twi_inRepStart = true;
276  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
277  twi_state = TWI_READY;
278  }
279  break;
280  case TW_MR_SLA_NACK:
281  twi_stop();
282  break;
283  case TW_SR_SLA_ACK:
284  case TW_SR_GCALL_ACK:
285  case TW_SR_ARB_LOST_SLA_ACK:
286  case TW_SR_ARB_LOST_GCALL_ACK:
287  twi_state = TWI_SRX;
288  twi_rxBufferIndex = 0;
289  twi_reply(1);
290  break;
291  case TW_SR_DATA_ACK:
292  case TW_SR_GCALL_DATA_ACK:
293  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
294  twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
295  twi_reply(1);
296  } else twi_reply(0);
297 
298  break;
299  case TW_SR_STOP:
300  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH) twi_rxBuffer[twi_rxBufferIndex] = '\0';
301  twi_stop();
302  twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
303  twi_rxBufferIndex = 0;
304  twi_releaseBus();
305  break;
306  case TW_SR_DATA_NACK:
307  case TW_SR_GCALL_DATA_NACK:
308  twi_reply(0);
309  break;
310  case TW_ST_SLA_ACK:
311  case TW_ST_ARB_LOST_SLA_ACK:
312  twi_state = TWI_STX;
313  twi_txBufferIndex = 0;
314  twi_txBufferLength = 0;
315  twi_onSlaveTransmit();
316  if(0 == twi_txBufferLength){
317  twi_txBufferLength = 1;
318  twi_txBuffer[0] = 0x00;
319  }
320  case TW_ST_DATA_ACK:
321  TWDR = twi_txBuffer[twi_txBufferIndex++];
322  if(twi_txBufferIndex < twi_txBufferLength) twi_reply(1);
323  else twi_reply(0);
324  break;
325  case TW_ST_DATA_NACK:
326  case TW_ST_LAST_DATA:
327  twi_reply(1);
328  twi_state = TWI_READY;
329  break;
330 
331  case TW_NO_INFO:
332  break;
333  case TW_BUS_ERROR:
334  twi_error = TW_BUS_ERROR;
335  twi_stop();
336  break;
337  }
338  }
339 
341 #endif
void twi_reply(uint8_t)
void twi_releaseBus(void)
void twi_setAddress(uint8_t)
#define TWI_SRX
Definition: eagle_Twi.h:35
void twi_stop(void)
uint8_t twi_transmit(const uint8_t *, uint8_t)
uint8_t twi_readFrom(uint8_t, uint8_t *, uint8_t, uint8_t)
#define TWI_MTX
Definition: eagle_Twi.h:34
void twi_setFrequency(uint32_t)
uint8_t twi_writeTo(uint8_t, uint8_t *, uint8_t, uint8_t, uint8_t)
void twi_disable(void)
#define TWI_BUFFER_LENGTH
Definition: eagle_Twi.h:29
#define TWI_READY
Definition: eagle_Twi.h:32
#define TWI_FREQ
Definition: eagle_Twi.h:17
void twi_attachSlaveRxEvent(void(*)(uint8_t *, int))
void twi_init(void)
#define TWI_MRX
Definition: eagle_Twi.h:33
#define TWI_STX
Definition: eagle_Twi.h:36
void twi_attachSlaveTxEvent(void(*)(void))