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