Project

General

Profile

Revision a52b0259

IDa52b02596e5eb5ed5d700afff96567bfdc55f159

Added by Thomas Mullins over 6 years ago

Added code for forklift AVR

twi.c and twi.h were taken from Arduino's library. forklift.c currently
implements i2c slave communication, but no motor control or sensor input
yet.

View differences:

forklift/code/Makefile
1
forklift: forklift.hex
2
	@
3

  
4
%.hex: %.elf
5
	avr-objcopy -j .text -j .data -O ihex $< $@
6

  
7
forklift.elf: forklift.c twi.c twi.h
8
	avr-gcc -mmcu=atmega168 -DF_CPU=8000000L forklift.c twi.c -o forklift.elf -Os
9

  
10
download: forklift.hex
11
	avrdude -c avrispmkII -p m328p forklift.hex
12

  
13
clean:
14
	rm -f forklift.elf forklift.hex
forklift/code/forklift.c
1
/*
2
 * ARM -> us
3
 * -height setpoint
4
 *
5
 * us -> ARM
6
 * -tracking ID (same for all forklifts)
7
 * -serial number (unique to each forklift)
8
 * -current height
9
 * -current height setpoint
10
 * -payload weight
11
 *
12
 */
13
 
14
#include "twi.h"
15

  
16
#define TRACKING_ID 0x41
17
#define SERIAL_NUMBER 0x12
18

  
19
// indicies for forklift internal data
20
#define FORKLIFT_TRACKING_ID     0
21
#define FORKLIFT_SERIAL_NUMBER   1
22
#define FORKLIFT_HEIGHT          2
23
#define FORKLIFT_HEIGHT_SETPOINT 3 // only one that's r/w
24
#define FORKLIFT_FORCE           4
25

  
26
#define FORKLIFT_DATA_LEN        5
27

  
28
uint8_t internal_index = 0;
29
uint8_t internal_data[] = {
30
  TRACKING_ID,
31
  SERIAL_NUMBER,
32
  0,
33
  0,
34
  0
35
};
36

  
37
void slave_rx(uint8_t* data, int len)
38
{
39
  if (len > 0 && data[0] < FORKLIFT_DATA_LEN)
40
  {
41
    internal_index = data[0];
42
    if (len > 1 && internal_index == FORKLIFT_HEIGHT_SETPOINT)
43
      internal_data[internal_index] = data[1];
44
  }
45
}
46

  
47
void slave_tx(void)
48
{
49
  twi_transmit(&internal_data[internal_index], 1);
50
  internal_index++;
51
  if (internal_index >= FORKLIFT_DATA_LEN)
52
    internal_index = 0;
53
}
54

  
55
int main()
56
{
57
  twi_init();
58
  twi_setAddress(TRACKING_ID);
59
  twi_attachSlaveRxEvent(slave_rx);
60
  twi_attachSlaveTxEvent(slave_tx);
61
  while (1)
62
  {
63
    // do motor stuff
64
  }
65
  return 0;
66
}
forklift/code/twi.c
1
/*
2
  twi.c - TWI/I2C library for Wiring & Arduino
3
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
4

  
5
  This library is free software; you can redistribute it and/or
6
  modify it under the terms of the GNU Lesser General Public
7
  License as published by the Free Software Foundation; either
8
  version 2.1 of the License, or (at your option) any later version.
9

  
10
  This library is distributed in the hope that it will be useful,
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
  Lesser General Public License for more details.
14

  
15
  You should have received a copy of the GNU Lesser General Public
16
  License along with this library; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
*/
19

  
20
#include <math.h>
21
#include <stdlib.h>
22
#include <inttypes.h>
23
#include <avr/io.h>
24
#include <avr/interrupt.h>
25
#include <compat/twi.h>
26

  
27
#ifndef cbi
28
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
29
#endif
30

  
31
#ifndef sbi
32
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
33
#endif
34

  
35
#include "twi.h"
36

  
37
static volatile uint8_t twi_state;
38
static uint8_t twi_slarw;
39

  
40
static void (*twi_onSlaveTransmit)(void);
41
static void (*twi_onSlaveReceive)(uint8_t*, int);
42

  
43
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
44
static volatile uint8_t twi_masterBufferIndex;
45
static uint8_t twi_masterBufferLength;
46

  
47
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
48
static volatile uint8_t twi_txBufferIndex;
49
static volatile uint8_t twi_txBufferLength;
50

  
51
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
52
static volatile uint8_t twi_rxBufferIndex;
53

  
54
static volatile uint8_t twi_error;
55

  
56
/* 
57
 * Function twi_init
58
 * Desc     readys twi pins and sets twi bitrate
59
 * Input    none
60
 * Output   none
61
 */
62
void twi_init(void)
63
{
64
  // initialize state
65
  twi_state = TWI_READY;
66
  
67
  // activate internal pullups for twi.
68
  //digitalWrite(SDA, 1);
69
  //digitalWrite(SCL, 1);
70

  
71
  // initialize twi prescaler and bit rate
72
  cbi(TWSR, TWPS0);
73
  cbi(TWSR, TWPS1);
74
  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
75

  
76
  /* twi bit rate formula from atmega128 manual pg 204
77
  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
78
  note: TWBR should be 10 or higher for master mode
79
  It is 72 for a 16mhz Wiring board with 100kHz TWI */
80

  
81
  // enable twi module, acks, and twi interrupt
82
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
83
}
84

  
85
/* 
86
 * Function twi_slaveInit
87
 * Desc     sets slave address and enables interrupt
88
 * Input    none
89
 * Output   none
90
 */
91
void twi_setAddress(uint8_t address)
92
{
93
  // set twi slave address (skip over TWGCE bit)
94
  TWAR = address << 1;
95
}
96

  
97
/* 
98
 * Function twi_readFrom
99
 * Desc     attempts to become twi bus master and read a
100
 *          series of bytes from a device on the bus
101
 * Input    address: 7bit i2c device address
102
 *          data: pointer to byte array
103
 *          length: number of bytes to read into array
104
 * Output   number of bytes read
105
 */
106
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
107
{
108
  uint8_t i;
109

  
110
  // ensure data will fit into buffer
111
  if(TWI_BUFFER_LENGTH < length){
112
    return 0;
113
  }
114

  
115
  // wait until twi is ready, become master receiver
116
  while(TWI_READY != twi_state){
117
    continue;
118
  }
119
  twi_state = TWI_MRX;
120
  // reset error state (0xFF.. no error occured)
121
  twi_error = 0xFF;
122

  
123
  // initialize buffer iteration vars
124
  twi_masterBufferIndex = 0;
125
  twi_masterBufferLength = length-1;  // This is not intuitive, read on...
126
  // On receive, the previously configured ACK/NACK setting is transmitted in
127
  // response to the received byte before the interrupt is signalled. 
128
  // Therefor we must actually set NACK when the _next_ to last byte is
129
  // received, causing that NACK to be sent in response to receiving the last
130
  // expected byte of data.
131

  
132
  // build sla+w, slave device address + w bit
133
  twi_slarw = TW_READ;
134
  twi_slarw |= address << 1;
135

  
136
  // send start condition
137
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
138

  
139
  // wait for read operation to complete
140
  while(TWI_MRX == twi_state){
141
    continue;
142
  }
143

  
144
  if (twi_masterBufferIndex < length)
145
    length = twi_masterBufferIndex;
146

  
147
  // copy twi buffer to data
148
  for(i = 0; i < length; ++i){
149
    data[i] = twi_masterBuffer[i];
150
  }
151
	
152
  return length;
153
}
154

  
155
/* 
156
 * Function twi_writeTo
157
 * Desc     attempts to become twi bus master and write a
158
 *          series of bytes to a device on the bus
159
 * Input    address: 7bit i2c device address
160
 *          data: pointer to byte array
161
 *          length: number of bytes in array
162
 *          wait: boolean indicating to wait for write or not
163
 * Output   0 .. success
164
 *          1 .. length to long for buffer
165
 *          2 .. address send, NACK received
166
 *          3 .. data send, NACK received
167
 *          4 .. other twi error (lost bus arbitration, bus error, ..)
168
 */
169
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait)
170
{
171
  uint8_t i;
172

  
173
  // ensure data will fit into buffer
174
  if(TWI_BUFFER_LENGTH < length){
175
    return 1;
176
  }
177

  
178
  // wait until twi is ready, become master transmitter
179
  while(TWI_READY != twi_state){
180
    continue;
181
  }
182
  twi_state = TWI_MTX;
183
  // reset error state (0xFF.. no error occured)
184
  twi_error = 0xFF;
185

  
186
  // initialize buffer iteration vars
187
  twi_masterBufferIndex = 0;
188
  twi_masterBufferLength = length;
189
  
190
  // copy data to twi buffer
191
  for(i = 0; i < length; ++i){
192
    twi_masterBuffer[i] = data[i];
193
  }
194
  
195
  // build sla+w, slave device address + w bit
196
  twi_slarw = TW_WRITE;
197
  twi_slarw |= address << 1;
198
  
199
  // send start condition
200
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
201

  
202
  // wait for write operation to complete
203
  while(wait && (TWI_MTX == twi_state)){
204
    continue;
205
  }
206
  
207
  if (twi_error == 0xFF)
208
    return 0;	// success
209
  else if (twi_error == TW_MT_SLA_NACK)
210
    return 2;	// error: address send, nack received
211
  else if (twi_error == TW_MT_DATA_NACK)
212
    return 3;	// error: data send, nack received
213
  else
214
    return 4;	// other twi error
215
}
216

  
217
/* 
218
 * Function twi_transmit
219
 * Desc     fills slave tx buffer with data
220
 *          must be called in slave tx event callback
221
 * Input    data: pointer to byte array
222
 *          length: number of bytes in array
223
 * Output   1 length too long for buffer
224
 *          2 not slave transmitter
225
 *          0 ok
226
 */
227
uint8_t twi_transmit(const uint8_t* data, uint8_t length)
228
{
229
  uint8_t i;
230

  
231
  // ensure data will fit into buffer
232
  if(TWI_BUFFER_LENGTH < length){
233
    return 1;
234
  }
235
  
236
  // ensure we are currently a slave transmitter
237
  if(TWI_STX != twi_state){
238
    return 2;
239
  }
240
  
241
  // set length and copy data into tx buffer
242
  twi_txBufferLength = length;
243
  for(i = 0; i < length; ++i){
244
    twi_txBuffer[i] = data[i];
245
  }
246
  
247
  return 0;
248
}
249

  
250
/* 
251
 * Function twi_attachSlaveRxEvent
252
 * Desc     sets function called before a slave read operation
253
 * Input    function: callback function to use
254
 * Output   none
255
 */
256
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) )
257
{
258
  twi_onSlaveReceive = function;
259
}
260

  
261
/* 
262
 * Function twi_attachSlaveTxEvent
263
 * Desc     sets function called before a slave write operation
264
 * Input    function: callback function to use
265
 * Output   none
266
 */
267
void twi_attachSlaveTxEvent( void (*function)(void) )
268
{
269
  twi_onSlaveTransmit = function;
270
}
271

  
272
/* 
273
 * Function twi_reply
274
 * Desc     sends byte or readys receive line
275
 * Input    ack: byte indicating to ack or to nack
276
 * Output   none
277
 */
278
void twi_reply(uint8_t ack)
279
{
280
  // transmit master read ready signal, with or without ack
281
  if(ack){
282
    TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
283
  }else{
284
	  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
285
  }
286
}
287

  
288
/* 
289
 * Function twi_stop
290
 * Desc     relinquishes bus master status
291
 * Input    none
292
 * Output   none
293
 */
294
void twi_stop(void)
295
{
296
  // send stop condition
297
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
298

  
299
  // wait for stop condition to be exectued on bus
300
  // TWINT is not set after a stop condition!
301
  while(TWCR & _BV(TWSTO)){
302
    continue;
303
  }
304

  
305
  // update twi state
306
  twi_state = TWI_READY;
307
}
308

  
309
/* 
310
 * Function twi_releaseBus
311
 * Desc     releases bus control
312
 * Input    none
313
 * Output   none
314
 */
315
void twi_releaseBus(void)
316
{
317
  // release bus
318
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
319

  
320
  // update twi state
321
  twi_state = TWI_READY;
322
}
323

  
324
SIGNAL(TWI_vect)
325
{
326
  switch(TW_STATUS){
327
    // All Master
328
    case TW_START:     // sent start condition
329
    case TW_REP_START: // sent repeated start condition
330
      // copy device address and r/w bit to output register and ack
331
      TWDR = twi_slarw;
332
      twi_reply(1);
333
      break;
334

  
335
    // Master Transmitter
336
    case TW_MT_SLA_ACK:  // slave receiver acked address
337
    case TW_MT_DATA_ACK: // slave receiver acked data
338
      // if there is data to send, send it, otherwise stop 
339
      if(twi_masterBufferIndex < twi_masterBufferLength){
340
        // copy data to output register and ack
341
        TWDR = twi_masterBuffer[twi_masterBufferIndex++];
342
        twi_reply(1);
343
      }else{
344
        twi_stop();
345
      }
346
      break;
347
    case TW_MT_SLA_NACK:  // address sent, nack received
348
      twi_error = TW_MT_SLA_NACK;
349
      twi_stop();
350
      break;
351
    case TW_MT_DATA_NACK: // data sent, nack received
352
      twi_error = TW_MT_DATA_NACK;
353
      twi_stop();
354
      break;
355
    case TW_MT_ARB_LOST: // lost bus arbitration
356
      twi_error = TW_MT_ARB_LOST;
357
      twi_releaseBus();
358
      break;
359

  
360
    // Master Receiver
361
    case TW_MR_DATA_ACK: // data received, ack sent
362
      // put byte into buffer
363
      twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
364
    case TW_MR_SLA_ACK:  // address sent, ack received
365
      // ack if more bytes are expected, otherwise nack
366
      if(twi_masterBufferIndex < twi_masterBufferLength){
367
        twi_reply(1);
368
      }else{
369
        twi_reply(0);
370
      }
371
      break;
372
    case TW_MR_DATA_NACK: // data received, nack sent
373
      // put final byte into buffer
374
      twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
375
    case TW_MR_SLA_NACK: // address sent, nack received
376
      twi_stop();
377
      break;
378
    // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case
379

  
380
    // Slave Receiver
381
    case TW_SR_SLA_ACK:   // addressed, returned ack
382
    case TW_SR_GCALL_ACK: // addressed generally, returned ack
383
    case TW_SR_ARB_LOST_SLA_ACK:   // lost arbitration, returned ack
384
    case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
385
      // enter slave receiver mode
386
      twi_state = TWI_SRX;
387
      // indicate that rx buffer can be overwritten and ack
388
      twi_rxBufferIndex = 0;
389
      twi_reply(1);
390
      break;
391
    case TW_SR_DATA_ACK:       // data received, returned ack
392
    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
393
      // if there is still room in the rx buffer
394
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
395
        // put byte in buffer and ack
396
        twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
397
        twi_reply(1);
398
      }else{
399
        // otherwise nack
400
        twi_reply(0);
401
      }
402
      break;
403
    case TW_SR_STOP: // stop or repeated start condition received
404
      // put a null char after data if there's room
405
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
406
        twi_rxBuffer[twi_rxBufferIndex] = '\0';
407
      }
408
      // sends ack and stops interface for clock stretching
409
      twi_stop();
410
      // callback to user defined callback
411
      twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
412
      // since we submit rx buffer to "wire" library, we can reset it
413
      twi_rxBufferIndex = 0;
414
      // ack future responses and leave slave receiver state
415
      twi_releaseBus();
416
      break;
417
    case TW_SR_DATA_NACK:       // data received, returned nack
418
    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
419
      // nack back at master
420
      twi_reply(0);
421
      break;
422
    
423
    // Slave Transmitter
424
    case TW_ST_SLA_ACK:          // addressed, returned ack
425
    case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
426
      // enter slave transmitter mode
427
      twi_state = TWI_STX;
428
      // ready the tx buffer index for iteration
429
      twi_txBufferIndex = 0;
430
      // set tx buffer length to be zero, to verify if user changes it
431
      twi_txBufferLength = 0;
432
      // request for txBuffer to be filled and length to be set
433
      // note: user must call twi_transmit(bytes, length) to do this
434
      twi_onSlaveTransmit();
435
      // if they didn't change buffer & length, initialize it
436
      if(0 == twi_txBufferLength){
437
        twi_txBufferLength = 1;
438
        twi_txBuffer[0] = 0x00;
439
      }
440
      // transmit first byte from buffer, fall
441
    case TW_ST_DATA_ACK: // byte sent, ack returned
442
      // copy data to output register
443
      TWDR = twi_txBuffer[twi_txBufferIndex++];
444
      // if there is more to send, ack, otherwise nack
445
      if(twi_txBufferIndex < twi_txBufferLength){
446
        twi_reply(1);
447
      }else{
448
        twi_reply(0);
449
      }
450
      break;
451
    case TW_ST_DATA_NACK: // received nack, we are done 
452
    case TW_ST_LAST_DATA: // received ack, but we are done already!
453
      // ack future responses
454
      twi_reply(1);
455
      // leave slave receiver state
456
      twi_state = TWI_READY;
457
      break;
458

  
459
    // All
460
    case TW_NO_INFO:   // no state information
461
      break;
462
    case TW_BUS_ERROR: // bus error, illegal stop/start
463
      twi_error = TW_BUS_ERROR;
464
      twi_stop();
465
      break;
466
  }
467
}
468

  
forklift/code/twi.h
1
/*
2
  twi.h - TWI/I2C library for Wiring & Arduino
3
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
4

  
5
  This library is free software; you can redistribute it and/or
6
  modify it under the terms of the GNU Lesser General Public
7
  License as published by the Free Software Foundation; either
8
  version 2.1 of the License, or (at your option) any later version.
9

  
10
  This library is distributed in the hope that it will be useful,
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
  Lesser General Public License for more details.
14

  
15
  You should have received a copy of the GNU Lesser General Public
16
  License along with this library; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
*/
19

  
20
#ifndef twi_h
21
#define twi_h
22

  
23
  #include <inttypes.h>
24

  
25
  //#define ATMEGA8
26

  
27
  #ifndef TWI_FREQ
28
  #define TWI_FREQ 100000L
29
  #endif
30

  
31
  #ifndef TWI_BUFFER_LENGTH
32
  #define TWI_BUFFER_LENGTH 32
33
  #endif
34

  
35
  #define TWI_READY 0
36
  #define TWI_MRX   1
37
  #define TWI_MTX   2
38
  #define TWI_SRX   3
39
  #define TWI_STX   4
40
  
41
  void twi_init(void);
42
  void twi_setAddress(uint8_t);
43
  uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t);
44
  uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t);
45
  uint8_t twi_transmit(const uint8_t*, uint8_t);
46
  void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
47
  void twi_attachSlaveTxEvent( void (*)(void) );
48
  void twi_reply(uint8_t);
49
  void twi_stop(void);
50
  void twi_releaseBus(void);
51

  
52
#endif
53

  

Also available in: Unified diff