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