COSA
An Object-Oriented Platform for Arduino Programming
TWI.hh
Go to the documentation of this file.
1 
21 #ifndef COSA_TWI_HH
22 #define COSA_TWI_HH
23 
24 #include "Cosa/Types.h"
25 #if defined(BOARD_ATTINY)
26 #include "Cosa/USI/TWI.hh"
27 #else
28 #include "Cosa/Event.hh"
29 #include <avr/power.h>
30 
51 class TWI {
52 public:
54  static const uint32_t DEFAULT_FREQ = 100000L;
55 
57  static const uint32_t MAX_FREQ = (F_CPU / (16 + 2*2));
58 
64  class Driver {
65  public:
70  Driver(uint8_t addr) :
71  m_addr(addr << 1),
72  m_async(false)
73  {}
74 
78  bool is_async() const
79  {
80  return (m_async);
81  }
82 
86  void sync_request()
87  {
88  m_async = false;
89  }
90 
95  {
96  m_async = true;
97  }
98 
106  virtual void on_completion(uint8_t type, int count)
107  {
108  UNUSED(type);
109  UNUSED(count);
110  }
111 
112  protected:
114  uint8_t m_addr;
115 
117  bool m_async;
118 
120  friend class TWI;
121  friend void TWI_vect(void);
122  };
123 
129  class Slave : public Driver, public Event::Handler {
130  public:
135  Slave(uint8_t addr) : Driver(addr), Event::Handler() {}
136 
142  void read_buf(void* buf, size_t size);
143 
149  void write_buf(void* buf, size_t size);
150 
154  void begin();
155 
163  virtual void on_completion(uint8_t type, int count)
164  {
165  Event::push(type, this, count);
166  }
167 
177  virtual void on_request(void* buf, size_t size) = 0;
178 
179  protected:
183  static const uint8_t WRITE_IX = 0;
184  static const uint8_t READ_IX = 1;
185 
195  virtual void on_event(uint8_t type, uint16_t value);
196 
198  friend class TWI;
199  friend void TWI_vect(void);
200  };
201 
206  TWI() :
207  m_state(IDLE_STATE),
208  m_status(NO_INFO),
209  m_ix(0),
210  m_next(NULL),
211  m_last(NULL),
212  m_count(0),
213  m_dev(NULL),
214  m_freq(((F_CPU / DEFAULT_FREQ) - 16) / 2),
215  m_busy(false)
216  {
217  for (uint8_t ix = 0; ix < VEC_MAX; ix++) {
218  m_vec[ix].buf = 0;
219  m_vec[ix].size = 0;
220  }
221  }
222 
229  void acquire(TWI::Driver* dev);
230 
234  void release();
235 
243  bool write_request(void* buf, size_t size);
244 
254  bool write_request(uint8_t header, void* buf, size_t size);
255 
264  bool write_request(uint16_t header, void* buf, size_t size);
265 
273  bool read_request(void* buf, size_t size);
274 
282  int write(void* buf, size_t size)
283  __attribute__((always_inline))
284  {
285  if (UNLIKELY(!write_request(buf, size))) return (EIO);
286  return (await_completed());
287  }
288 
297  int write(uint8_t header, void* buf = 0, size_t size = 0)
298  __attribute__((always_inline))
299  {
300  if (UNLIKELY(!write_request(header, buf, size))) return (EIO);
301  return (await_completed());
302  }
303 
312  int write(uint16_t header, void* buf = 0, size_t size = 0)
313  __attribute__((always_inline))
314  {
315  if (UNLIKELY(!write_request(header, buf, size))) return (EIO);
316  return (await_completed());
317  }
318 
326  int read(void* buf, size_t size)
327  __attribute__((always_inline))
328  {
329  if (UNLIKELY(!read_request(buf, size))) return (EIO);
330  return (await_completed());
331  }
332 
338  int await_completed();
339 
345  void set_freq(uint32_t hz)
346  __attribute__((always_inline))
347  {
348  m_freq = (hz < MAX_FREQ) ? (((F_CPU / hz) - 16) / 2) : 2;
349  }
350 
354  void powerup()
355  {
356  power_twi_enable();
357  }
358 
362  void powerdown()
363  {
364  power_twi_disable();
365  }
366 
367 private:
371  enum State {
372  ERROR_STATE,
373  IDLE_STATE,
374  MT_STATE,
375  MR_STATE,
376  ST_STATE,
377  SR_STATE
378  } __attribute__((packed));
379 
384 # define TWI_STATUS(x) ((x) >> 3)
385 
390  enum {
392  START = TWI_STATUS(0x08),
393  REP_START = TWI_STATUS(0x10),
394  ARB_LOST = TWI_STATUS(0x38),
395 
397  MT_SLA_ACK = TWI_STATUS(0x18),
398  MT_SLA_NACK = TWI_STATUS(0x20),
399  MT_DATA_ACK = TWI_STATUS(0x28),
400  MT_DATA_NACK = TWI_STATUS(0x30),
401 
403  MR_SLA_ACK = TWI_STATUS(0x40),
404  MR_SLA_NACK = TWI_STATUS(0x48),
405  MR_DATA_ACK = TWI_STATUS(0x50),
406  MR_DATA_NACK = TWI_STATUS(0x58),
407 
409  ST_SLA_ACK = TWI_STATUS(0xA8),
410  ST_ARB_LOST_SLA_ACK = TWI_STATUS(0xB0),
411  ST_DATA_ACK = TWI_STATUS(0xB8),
412  ST_DATA_NACK = TWI_STATUS(0xC0),
413  ST_LAST_DATA = TWI_STATUS(0xC8),
414 
416  SR_SLA_ACK = TWI_STATUS(0x60),
417  SR_ARB_LOST_SLA_ACK = TWI_STATUS(0x68),
418  SR_GCALL_ACK = TWI_STATUS(0x70),
419  SR_ARB_LOST_GCALL_ACK = TWI_STATUS(0x78),
420  SR_DATA_ACK = TWI_STATUS(0x80),
421  SR_DATA_NACK = TWI_STATUS(0x88),
422  SR_GCALL_DATA_ACK = TWI_STATUS(0x90),
423  SR_GCALL_DATA_NACK = TWI_STATUS(0x98),
424  SR_STOP = TWI_STATUS(0xA0),
425 
427  NO_INFO = TWI_STATUS(0xF8),
428  BUS_ERROR = TWI_STATUS(0x00)
429  } __attribute__((packed));
430 
434  enum {
435  WRITE_OP = 0x00,
436  READ_OP = 0x01,
437  ADDR_MASK = 0xfe
438  } __attribute__((packed));
439 
441  static const uint8_t NEXT_IX = 255;
442 
446  enum Command {
447  NULL_CMD = 0,
448  IDLE_CMD = _BV(TWEA) | _BV(TWEN) | _BV(TWIE),
449  START_CMD = _BV(TWINT) | _BV(TWEA) | _BV(TWSTA) | _BV(TWEN) | _BV(TWIE),
450  DATA_CMD = _BV(TWINT) | _BV(TWEN) | _BV(TWIE),
451  ACK_CMD = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE),
452  NACK_CMD = _BV(TWINT) | _BV(TWEN) | _BV(TWIE),
453  STOP_CMD = _BV(TWINT) | _BV(TWEA) | _BV(TWSTO) | _BV(TWEN) | _BV(TWIE)
454  } __attribute__((packed));
455 
459  static const uint8_t HEADER_MAX = 4;
460  static const uint8_t VEC_MAX = 4;
461  uint8_t m_header[HEADER_MAX];
462  iovec_t m_vec[VEC_MAX];
463  volatile State m_state;
464  volatile uint8_t m_status;
465  volatile uint8_t m_ix;
466  volatile uint8_t* m_next;
467  volatile uint8_t* m_last;
468  volatile int m_count;
469  uint8_t m_addr;
470  Driver* m_dev;
471  uint8_t m_freq;
472  volatile bool m_busy;
473 
480  void isr_start(State state, uint8_t ix);
481 
488  bool isr_write(Command cmd);
489 
497  bool isr_read(Command cmd = NULL_CMD);
498 
505  void isr_stop(State state, uint8_t type = Event::NULL_TYPE);
506 
513  bool request(uint8_t op);
514 
516  friend void TWI_vect(void);
517 };
518 #endif
519 
523 extern TWI twi;
524 #endif
#define EIO
Definition: Errno.h:32
TWI()
Definition: TWI.hh:206
Definition: TWI.hh:51
void powerdown()
Definition: TWI.hh:362
void async_request()
Definition: TWI.hh:94
virtual void on_completion(uint8_t type, int count)
Definition: TWI.hh:163
int write(uint16_t header, void *buf=0, size_t size=0)
Definition: TWI.hh:312
void set_freq(uint32_t hz)
Definition: TWI.hh:345
#define NULL
Definition: Types.h:101
Definition: Types.h:391
int write(uint8_t header, void *buf=0, size_t size=0)
Definition: TWI.hh:297
bool m_async
Definition: TWI.hh:117
#define TWI_STATUS(x)
Definition: TWI.hh:384
void release()
Definition: TWI.cpp:58
bool is_async() const
Definition: TWI.hh:78
TWI twi
Definition: TWI.cpp:27
Slave(uint8_t addr)
Definition: TWI.hh:135
uint8_t m_addr
Definition: TWI.hh:114
static const uint32_t DEFAULT_FREQ
Definition: TWI.hh:54
int read(void *buf, size_t size)
Definition: TWI.hh:326
friend void TWI_vect(void)
static const uint32_t MAX_FREQ
Definition: TWI.hh:57
int write(void *buf, size_t size)
Definition: TWI.hh:282
#define UNUSED(x)
Definition: ATmega328P.hh:31
Driver(uint8_t addr)
Definition: TWI.hh:70
void acquire(TWI::Driver *dev)
Definition: TWI.cpp:36
void powerup()
Definition: TWI.hh:354
Definition: Event.hh:39
virtual void on_completion(uint8_t type, int count)
Definition: TWI.hh:106
void sync_request()
Definition: TWI.hh:86
bool read_request(void *buf, size_t size)
Definition: TWI.cpp:124
#define UNLIKELY(x)
Definition: Types.h:153
static bool push(uint8_t type, Handler *target, uint16_t value=0)
Definition: Event.hh:180
bool write_request(void *buf, size_t size)
Definition: TWI.cpp:92
int await_completed()
Definition: TWI.cpp:133