poppy_com  0.1
Poppy2.0 communication library
 All Classes Files Functions Variables Enumerations Enumerator Pages
hal.c
1 #include <util/twi.h>
2 #include <avr/interrupt.h>
3 #include "poppy-com/hal/atmega64/hal.h"
4 #include "poppy-com/inc/i2c_slave.h"
5 
6 // I2C Master mode
7 
8 // Global variables
9 extern context_t ctx;
10 
11 void hal_init(void) {
12  // I2C
13  TWBR = ((MAINCLOCK / SCLFREQ) - 16) / 2;
14  TWSR &= ~(1<<TWPS1) & ~(1<<TWPS0); // SetPrescaler divisor to 1
15  TWAR = (0x0A << 1) | (1<<TWGCE); // I2C Address and enable general call
16  TWAMR = 0x00; // Not used
17  TWCR = ((1 << TWEA) | (1 << TWEN) | (1 << TWIE)); // Enable ACK system
18 }
19 
20 unsigned char i2c_transmit(com_state_t type) {
21  switch (type) {
22  case START:
23  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
24  break;
25  case DATA:
26  TWCR = (1 << TWINT) | (1 << TWEN) | (1<<TWEA);
27  break;
28  case DATA_NACK:
29  TWCR = (1 << TWINT) | (1 << TWEN);
30  break;
31  case STOP:
32  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
33  return 0;
34  }
35  // Wait for TWINT flag set in TWCR Register
36  while (!(TWCR & (1 << TWINT)));
37  // TODO(NR) Timeout
38  // Return TWI Status Register, mask the prescaler bits (TWPS1,TWPS0)
39  return (TWSR & 0xF8);
40 }
41 
42 
43 unsigned char i2cAddr(unsigned char addr, msg_dir_t dir) {
44  unsigned char status;
45  unsigned char n = 0;
46  if (dir)
47  addr = (addr << 1) | TW_READ;
48  else
49  addr = (addr << 1) | TW_WRITE;
50  i2c_retry:
51  if (n++ >= MAX_TRIES) return 1;
52  status = i2c_transmit(START);
53  if ((status != TW_START) & (status != TW_REP_START)) {
54  ctx.status.master_write = TRUE;
55  return 1;
56  }
57 
58  TWDR = addr;
59  switch (i2c_transmit(DATA)) {
60  case TW_MT_SLA_ACK:
61  case TW_MR_SLA_ACK:
62  // ACK received
63  return 0;
64  break;
65  case TW_MR_SLA_NACK:
66  case TW_MT_SLA_NACK:
67  // NACK received
68  case TW_MT_ARB_LOST:
69  // Arbitration lost
70  goto i2c_retry;
71  break;
72  default:
73  return 1;
74  break;
75  }
76 }
77 
78 unsigned char i2cWrite(unsigned char data) {
79  if (TWCR & (1<<TWINT)) {
80  TWDR = data;
81  if (i2c_transmit(DATA) != TW_MT_DATA_ACK) {
82  ctx.status.master_write = TRUE;
83  return 1;
84  }
85  } else {
86  ctx.status.master_write = TRUE;
87  return 1;
88  }
89  return 0;
90 }
91 
92 unsigned char i2cRead(unsigned char ack_enable, unsigned char *data) {
93  if (ack_enable) {
94  if (i2c_transmit(DATA) != TW_MR_DATA_ACK) {
95  ctx.status.master_read = TRUE;
96  return 1;
97  }
98  } else {
99  if (i2c_transmit(DATA_NACK) != TW_MR_DATA_NACK) {
100  ctx.status.master_read = TRUE;
101  return 1;
102  }
103  }
104  *data = TWDR;
105  return 0;
106 }
107 
108 // I2C Slave mode
109 ISR(TWI_vect) {
110  // Test if there is really an interrupt
111  if (TWCR&(1<<TWINT))
112  switch (TWSR) {
113  // SLAVE TRANSMITTER MODE
114  case TW_ST_SLA_ACK: // 0xA8: SLA+R received, ACK returned.
115  case TW_ST_DATA_ACK: // 0xB8: Data transmitted, ACK received.
116  // Slave TX callback
117  ctx.data_cb(TX, &TWDR);
118  TWCR |= (1<<TWINT);
119  break;
120 
121  // SLAVE RECEIVER MODE
122  // Previously addressed with own SLA+W; ACK has been returned.
123  case TW_SR_SLA_ACK:
124  // Previously addressed with general call; ACK has been returned.
125  case TW_SR_GCALL_ACK:
126  TWCR |= (1<<TWINT)|(1<<TWEA);
127  break;
128 
129  // Data has been received on SLA+W; ACK has been returned.
130  case TW_SR_DATA_ACK:
131  // Slave RX callback
132  ctx.data_cb(RX, &TWDR);
133  TWCR |= (1<<TWINT);
134  break;
135 
136  // Data has been received on general call;ACK has been returned.
137  case TW_SR_GCALL_DATA_ACK:
138  // Slave RX general call callback
139  ctx.data_cb(RXGC, &TWDR);
140  TWCR |= (1<<TWINT);
141  break;
142 
143  // OTHER
144  case TW_BUS_ERROR: // Error
145  case TW_NO_INFO: // Error
146  TWCR |= (1<<TWINT)|(1<<TWSTO);
147  ctx.status.unexpected_state = TRUE;
148  ctx.data_cb = idle;
149  break;
150  case TW_SR_STOP:
151  TWCR |= (1<<TWINT)|(1<<TWSTO);
152  ctx.data_cb = idle;
153  ctx.data_cb(END, &TWDR);
154  default:
155  TWCR |= (1<<TWINT);
156  break;
157  }
158 }
159 
160 void id_update(unsigned char id) {
161  ctx.id = id;
162  TWAR = (ctx.id << 1) | (1 << TWGCE);
163  /*
164  * TORO(NR) : Write this ID on EEPROM and use it as default at
165  * reboot (do this after debug)
166  */
167 }
168 
169 unsigned char crc(unsigned char* data, unsigned char size) {
170  unsigned char x;
171  unsigned int crc = 0xFFFF;
172 
173  while (size--) {
174  x = crc >> 8 ^ *data++;
175  x ^= x>>4;
176  crc = (crc << 8) ^ ((unsigned int)(x << 12))
177  ^ ((unsigned int)(x <<5))
178  ^ ((unsigned int)x);
179  }
180  return (unsigned char)crc;
181 }
unsigned char id
Definition: context.h:42
status_t status
Definition: context.h:46
DATA_CB data_cb
Definition: context.h:36
msg_dir_t
Message direction enum.
Definition: poppyNetwork.h:22