Project

General

Profile

Revision 1563

View differences:

branches/ir_lookup/rangefinder.c
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file rangefinder.c
29
 * @brief Rangefinders
30
 *
31
 * Implementation of functions for rangefinder use.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
/*
37
  Authors: James Kong and Greg Tress
38

  
39
  Last Modified: 4/30/06 by James
40
  -Started log_distance conversion function !!!NOT COMPLETE!!!
41
  -Cleaning up comments
42

  
43
  -----------------
44
  rangefinder.c
45
  Using Sharp GP2D02 IR Rangefinder
46

  
47
  Vin is the input to the rangefinder, designated RANGE_CTRL.
48
  Vout is the output from the rangefinder, designated RANGE_IN# where # is the rangefinder you are reading from
49

  
50
  Expected Initial Conditions:
51
  Vin is high and Vout should read high.
52

  
53
  Usage:
54
  1.) Set Vin low. Vout should read low.
55
  2.) Wait for high on Vout.
56
  3.) Begin clocking Vin and reading 8 bits from Vout (MSB first).
57
  4.) Set Vin high for 2ms or more to turn off rangefinder
58

  
59
*/
60
#include <avr/pgmspace.h>
61

  
62
#include "rangefinder.h"
63
#include "analog.h"
64
#include "dio.h"
65

  
66
/*
67
  read_distance returns the 8-bit reading from the rangefinder
68
  parameters:
69
  range_id - dio pin set as the rangefinder Vout [i.e. RANGE_IN0]
70

  
71
  NOTE:
72
  The Sharp GD2D02 returns values on a decreasing logrithmic scale.
73
  So higher values correspond to closer distances.  Use linearize_distance to convert to normal centimeter scale.
74
  Also, when reading distances closer than 8cm, the Sharp GD2D02 will return lower values than the values at 8cm.
75
  At this point, we are only reading from one rangefinder [RANGE_IN0].
76
*/
77

  
78
// constants
79
/* Nasty IR approximation table
80
   I'm using this for the heck of it.  We can do whatever.
81

  
82
   Note the minimum value is .4V (20), and the maximum is 2.6V (133).
83
   Gives distance in mm.
84

  
85
   excel formula(valid for inputs 20-133):  ROUND(2353.6*(E2^(-1.1146))*10,0)
86

  
87
   This is only valid for the GP2D12, with objects directly ahead and more than
88
   10cm from the detector.  See the datasheet for more information.
89
*/
90

  
91
static int IR_dist_conversion[72] PROGMEM = {
92
	327,315,303,291,281,271,262,253,245,238,231,224,218,212,206,200,
93
	195,190,185,181,177,173,168,165,161,158,155,151,148,145,143,140,
94
	137,134,132,130,127,125,123,121,119,117,115,114,111,110,108,106,
95
	105,104,102,100,99,98,97,95,94,93,91,90,89,88,87,86,84,83,83,82,
96
	81,80,79,78
97
};
98

  
99
/**
100
 * @defgroup rangefinder Rangefinder
101
 * @brief Functions for using the IR rangefinders
102
 * 
103
 * Functions for using the IR rangefinders.
104
 *
105
 * @{
106
 **/
107

  
108
/**
109
 * Initializes the rangefinders. This must be called before
110
 * range_read_distance.
111
 *
112
 * @see range_read_distance
113
 **/
114
void range_init(void)
115
{
116
  digital_output(_PIN_B4,0);
117
}
118

  
119
/**
120
 * Reads the distance measured by one of the rangefinders.
121
 * This distance is in arbitrary units.
122
 *
123
 * @param range_id the rangefinder to use. This should be one
124
 * of the constants IR1 - IR5.
125
 *
126
 * @return the distance measured by the rangefinder
127
 *
128
 * @see range_init
129
 **/
130
int range_read_distance(int range_id) {
131
  return linearize_distance(analog8(range_id));
132
}
133

  
134
/**
135
 * Transforms distance readings from logarithmic to linear scale.
136
 * This probably isn't the function you are looking for.
137
 *
138
 * Note: pgm_read_word() needs additional testing
139
 *
140
 * @param value the 8-bit analog value from rangefinder
141
 *
142
 * @return linearized distance reading from rangefinder (integer in [101,800])
143
 **/
144
int linearize_distance(int value) {
145
  if(value < MIN_IR_ADC8) {
146
    return -1;
147
  } else if(value > MAX_IR_ADC8) {
148
    return -1;
149
  } else {
150
    return pgm_read_word(&(IR_dist_conversion[value - MIN_IR_ADC8]));
151
  }
152
}
153

  
154
/** @} **/ //end defgroup
branches/ir_lookup/rangefinder.h
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file rangefinder.h
29
 * @brief Contains rangefinder declarations and functions
30
 * 
31
 * Contains functions and definitions for the use of
32
 * IR rangefinders.
33
 *
34
 * @author Colony Project, CMU Robotics Club
35
 **/
36

  
37
#ifndef _RANGEFINDER_H_
38
#define _RANGEFINDER_H_
39

  
40
/**
41
 * @addtogroup rangefinder
42
 * @{
43
 **/
44

  
45
/** @brief IR Rangefinder 1 **/
46
#define IR1 6
47
/** @brief IR Rangefinder 2 **/
48
#define IR2 5
49
/** @brief IR Rangefinder 3 **/
50
#define IR3 4
51
/** @brief IR Rangefinder 4 **/
52
#define IR4 3
53
/** @brief IR Rangefinder 5 **/
54
#define IR5 2
55
/** @brief smallest meaningful rangefinder reading (logarithmic scale) **/
56
#define MIN_IR_ADC8 27
57
/** @brief largest meaningful rangefinder reading (logarithmic scale) **/
58
#define MAX_IR_ADC8 98
59

  
60
/** @brief Initialize the rangefinders **/
61
void range_init(void);
62
/** @brief Read the distance from a rangefinder **/
63
int range_read_distance(int range_id);
64
/** @brief Convert logarithmic-scale distance readings to a linear scale **/
65
int linearize_distance(int value);
66

  
67
/** @} **/ //end addtogroup
68

  
69
#endif
70

  
branches/ir_lookup/bom.c
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file bom.c
29
 * @brief Implementation for using the BOM
30
 *
31
 * Contains functions for using the Bearing and Orientation Module (BOM)
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
#include "bom.h"
37
#include "dio.h"
38
#include "serial.h"
39
#include "analog.h"
40

  
41
//On the original BOM1.0, the emmitter angular order does not match the analog mux order
42
//so you need to iterate through the mux index in the following order if you want to get
43
//the detector readings in order:
44
static const char lookup[16] = {7,6,5,0xe,1,4,3,2,0xf,0,0xd,8,0xc,0xb,9,0xa};
45

  
46

  
47
/* *****************************
48
 * BOM Vector Component Tables *
49
 **************************** **/
50

  
51
/*
52
 * The x component of each BOM detector (indexed from 0 to 15)
53
 * was calculated using the following formula:
54
 *
55
 *		x_comp[i] = fix(25 * cos ( 2 * pi / 16 * i) )
56
 *
57
 * where "fix" rounds towards 0. If the BOM detectors were superimposed
58
 * onto a 2 dimensional Cartesian space, this effectively calculates the
59
 * x component of the emitter vector where emitter 0 corresponds to an
60
 * angle of 0 radians, 4 -> pi/2, 8 -> pi, ect.
61
 */
62
static const signed int x_comp[16] = {
63
	25,
64
	23,
65
	17,
66
	9,
67
	0,
68
	-9,
69
	-17,
70
	-23,
71
	-25,
72
	-23,
73
	-17,
74
	-9,
75
	0,
76
	9,
77
	17,
78
	23
79
};
80

  
81

  
82
/*
83
 * The y component of each BOM detector (indexed from 0 to 15)
84
 * was calculated using the following formula:
85
 *
86
 *		y_comp[i] = fix(25 * sin ( 2 * pi / 16 * i) )
87
 *
88
 * where "fix" rounds towards 0. If the BOM detectors were superimposed
89
 * onto a 2 dimensional Cartesian space, this effectively calculates the
90
 * x component of the emitter vector where emitter 0 corresponds to an
91
 * angle of 0 radians, 4 -> pi/2, 8 -> pi, ect.
92
 */
93
static signed int y_comp[16] = {
94
	0,
95
	9,
96
	17,
97
	23,
98
	25,
99
	23,
100
	17,
101
	9,
102
	0,
103
	-9,
104
	-17,
105
	-23,
106
	-25,
107
	-23,
108
	-17,
109
	-9
110
};
111

  
112
// internal function prototypes
113
static void bom_select(char which);
114

  
115
/*
116
 Bk R Y (Analog)
117
---------
118
 Green
119
 Blue
120
 White
121
---------
122
 Blue
123
 White
124
*/
125

  
126

  
127
/*
128
the analog pin definitions from dio.h DO NOT work here,
129
so we must use PF0 from avrgcc (as opposed to _PIN_F0).
130
BUT the dio pin definitions from dio.h must be used (no PE...).
131

  
132
also, _PIN_E2 is initialized to high for some reason,
133
which turns the BOM on when the robot is turned on.
134
WORK-AROUND: call digital_output(_PIN_E2,0) at some point.
135

  
136
*/
137

  
138
#define MONKI PF0         //analog (yellow)
139
//------------------------//
140
#define MONKL _PIN_E2     //green
141
#define MONK1 _PIN_E3     //blue
142
#define MONK0 _PIN_E4     //white
143
//------------------------//
144
#define MONK3 _PIN_E6     //blue
145
#define MONK2 _PIN_E7     //white
146

  
147
#define BOM_VALUE_THRESHOLD 150 //200
148
#define NUM_BOM_LEDS 16
149

  
150
/*
151
  *The following pin definitions are for the BOM v1.5
152
  */
153

  
154
#define BOM_MODE	_PIN_E2	//dio0
155
#define BOM_STROBE	_PIN_E3	//dio1
156

  
157
#define BOM_DATA	_PIN_A0 //servo0
158
#define BOM_CLOCK	_PIN_A1	//servo1
159

  
160
#define BOM_S0		_PIN_E5	//dio3
161
#define BOM_S1		_PIN_E4	//dio2
162
#define BOM_S2		_PIN_E7	//dio4
163
#define BOM_S3		_PIN_E6	//dio5
164
#define BOM_OUT		PF0		//analog(yellow)
165

  
166
/**
167
 * @defgroup bom BOM (Bearing and Orientation Module)
168
 * @brief Functions for dealing with the BOM.
169
 *
170
 * The Bearing and Orientation Module / Barrel of Monkeys / BOM
171
 * is a custom sensor designed and built by the Colony Project.
172
 * It consists of a ring of 16 IR emitters and 16 IR detectors.
173
 * The BOM is most often use to determine the direction of other
174
 * robots. This module contains functions for controlling the BOM.
175
 *
176
 * Include bom.h to access these functions.
177
 *
178
 * @{
179
 **/
180

  
181
static unsigned int bom_val[NUM_BOM_LEDS];
182
static volatile char bom_type = BOM10;
183
static int select_pins[4];
184
static int analog_pin;
185

  
186
/**
187
 * Initializes the BOM.
188
 * Call bom_init before reading bom values or turning bom leds.
189
 *
190
 * @bugs INCOMPLETE - No utilization of BOM1.5 RSSI capability. Probably leave this out
191
 * until Cornell and Pras return
192
 * 
193
 * @see bom_refresh, bom_leds_on, bom_leds_off
194
 **/
195
void bom_init(char type) {
196
    bom_type = type;
197
    
198
    switch(bom_type) {
199
    case BOM10:
200
		select_pins[0] = MONK0; 
201
		select_pins[1] = MONK1;
202
		select_pins[2] = MONK2;
203
		select_pins[3] = MONK3;
204
		analog_pin = MONKI;
205
        break;
206
    case BOM15:
207
        //Sets BOM1.5 to normal [BOM] mode
208
        digital_output(BOM_MODE, 0);
209
		select_pins[0] = BOM_S0; 
210
		select_pins[1] = BOM_S1;
211
		select_pins[2] = BOM_S2;
212
		select_pins[3] = BOM_S3;
213
		bom_set_leds(BOM_ALL);
214
		analog_pin = BOM_OUT;
215
        break;
216
    case RBOM:
217
        break;
218
    //default:
219
    }
220
}
221

  
222
/**
223
 * Iterates through each bit in the bit_field. For each set bit, sets the corresponding bom select bits
224
 *    and updates the corresponding bom value with an analog_get8 reading.  analog_init and bom_init
225
 *    must be called for this to work. Must call this before reading BOM values!
226
 *
227
 *
228
 * @param bit_field specifies which elements in bom_val[] should be updated. Use BOM_ALL to refresh all values.
229
 *    Ex. if 0x0003 is passed, bom_val[0] and bom_val[1] will be updated.
230
 *
231
 * @see bom_get
232
 **/
233
void bom_refresh(int bit_field) {
234
    int i;
235
	int loop_was_running = 0;
236
    
237
	//Check analog loop status
238
    if(analog_loop_status() == ADC_LOOP_RUNNING) {
239
		loop_was_running = 1;
240
		analog_stop_loop();
241
	}
242
    
243
	//Read BOM values
244
    for(i = 0; i < NUM_BOM_LEDS; i++) {
245
        if(bit_field & 0x1) {
246
            bom_select(i);
247
            bom_val[i] = analog_get8(analog_pin);
248
        }
249
        bit_field = bit_field >> 1;
250
    }
251
    
252
	//Restore analog loop status
253
	if(loop_was_running)
254
		analog_start_loop();
255
}
256

  
257
/**
258
 * Gets the bom reading from bom_val[which].  Call bom_refresh beforehand to read new bom values.
259
 *
260
 * @pre must call bom refresh first
261
 *
262
 * @param which which bom value to return
263
 *
264
 * @return the bom value
265
 *
266
 * see bom_refresh
267
 **/
268
int bom_get(int which) {
269
    return bom_val[which];
270
}
271

  
272
/** 
273
 * Compares all the values in bom_val[] and returns the index to the lowest (max) value element.
274
 *
275
 * @pre must call bom refresh
276
 * @return index to the lowest (max) bom value element.  -1 if no value is lower than
277
 *    BOM_VALUE_THRESHOLD
278
 **/
279
int bom_get_max(void) {
280
    int i, lowest_val, lowest_i;
281
    lowest_i = -1;
282
    lowest_val = 255;
283
    for(i = 0; i < NUM_BOM_LEDS; i++) {
284
        if(bom_val[i] < lowest_val) {
285
            lowest_val = bom_val[i];
286
            lowest_i = i;
287
        }
288
    }
289
    
290
    if(lowest_val < BOM_VALUE_THRESHOLD)
291
        return lowest_i;
292
    else
293
        return -1;
294
}
295

  
296
/** 
297
 * Compute the net resultant BOM IR vector by scaling each IR unit vector by its intensity
298
 *		and summing over all IR LEDs.
299
 *
300
 * @param v  Pointer to Vector struct to be filled by this function with an x and y net vector
301
 *		component.
302
 *
303
 * @param usrBOMvals  Pointer to array which holds 16 raw BOM readings which can be used if user
304
 *		has already collected BOM information instead of collecting a new data set from the BOM.
305
 *
306
 * @return  Exit status - Zero for success; negative on error.
307
 **/
308
int bom_get_vector(Vector* v, int* usrBOMvals) {
309

  
310
	/* Store current BOM readings and use them as a weighting factor */
311
	int intensity[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
312

  
313
	/* Arrays for storing the weighted x ("Rightness") and y ("Forwardness")
314
	 * components. Calculated by multiplying the intensity by the x and y
315
	 * component respectively (x and y components are stored in the tables
316
	 * above). */
317
	int weighted_x_comp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
318
	int weighted_y_comp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
319
	
320
	/* Accumulators to sum up the net x ("Rightness") and y ("Forwardness")
321
	 * components for the entire robot. */
322
	long net_x_comp = 0;
323
	long net_y_comp = 0;
324

  
325
	int i = 0;
326

  
327
	/* BOM intensity is actually measured as more intense = closer to 0 */
328
	if (usrBOMvals) {
329
		/* Use BOM values collected by user */
330
		for (i = 0; i < 16; i++) {
331
			intensity[i] = 255 - usrBOMvals[i];
332
		}
333
	} else {
334
		/* Collect new set of BOM data */
335
		bom_refresh(BOM_ALL);
336
		for (i = 0; i < 16; i++) {
337
			intensity[i] = 255 - bom_get(i);
338
		}
339
	}
340

  
341
	/* Calculate weighted vector components and accumulate vector sum */
342
	for (i = 0; i < 16; i++) {
343
		weighted_x_comp[i] = intensity[i] * x_comp[i];
344
		weighted_y_comp[i] = intensity[i] * y_comp[i];
345
		net_x_comp += weighted_x_comp[i];
346
		net_y_comp += weighted_y_comp[i];
347
	}
348

  
349
	/* Fill the Vector struct */
350
	v->x = net_x_comp;
351
	v->y = net_y_comp;
352

  
353
	return 0;
354

  
355
}
356

  
357
/** 
358
 * Compute the normalized net resultant BOM IR vector by scaling each IR unit vector by its
359
 *		intensity and summing over all IR LEDs.
360
 *
361
 * @param v  Pointer to Vector struct to be filled by this function with an x and y net vector
362
 *		component.
363
 *
364
 * @param usrBOMvals  Pointer to array which holds 16 raw BOM readings which can be used if user
365
 *		has already collected BOM information instead of collecting a new data set from the BOM.
366
 *
367
 * @return  Exit status - Zero for success; negative on error.
368
 **/
369
int bom_get_norm_vector(Vector* v, int* usrBOMvals) {
370

  
371
	/* Store current BOM readings and use them as a weighting factor */
372
	int intensity[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
373

  
374
	/* Arrays for storing the weighted x ("Rightness") and y ("Forwardness")
375
	 * components. Calculated by multiplying the intensity by the x and y
376
	 * component respectively (x and y components are stored in the tables
377
	 * above). */
378
	int weighted_x_comp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
379
	int weighted_y_comp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
380
	
381
	/* Accumulators to sum up the net x ("Rightness") and y ("Forwardness")
382
	 * components for the entire robot. */
383
	long net_x_comp = 0;
384
	long net_y_comp = 0;
385

  
386
	/* Variables used to normalize the net component values */
387
	int total_intensity = 0;
388
	int normalized_net_x_comp = 0;
389
	int normalized_net_y_comp = 0;
390

  
391
	int i = 0;
392

  
393
	/* BOM intensity is actually measured as more intense = closer to 0 */
394
	if (usrBOMvals) {
395
		/* Use BOM values collected by user */
396
		for (i = 0; i < 16; i++) {
397
			intensity[i] = 255 - usrBOMvals[i];
398
		}
399
	} else {
400
		/* Collect new set of BOM data */
401
		bom_refresh(BOM_ALL);
402
		for (i = 0; i < 16; i++) {
403
			intensity[i] = 255 - bom_get(i);
404
		}
405
	}
406

  
407
	/* Calculate weighted vector components and accumulate vector sum */
408
	for (i = 0; i < 16; i++) {
409
		weighted_x_comp[i] = intensity[i] * x_comp[i];
410
		weighted_y_comp[i] = intensity[i] * y_comp[i];
411
		net_x_comp += weighted_x_comp[i];
412
		net_y_comp += weighted_y_comp[i];
413
		total_intensity += intensity[i];
414
	}
415

  
416
	/* Normalize the resultant vector components by the total intensity */
417
	if (total_intensity > 0) {
418
		normalized_net_x_comp = net_x_comp / total_intensity;
419
		normalized_net_y_comp = net_y_comp / total_intensity;
420
	}
421

  
422
	/* Fill the Vector struct */
423
	v->x = normalized_net_x_comp;
424
	v->y = normalized_net_y_comp;
425

  
426
	return 0;
427

  
428
}
429

  
430
/** 
431
 * Print a histogram which shows the current BOM intensity values for each of the 16 BOM IR
432
 *		sensors. The function will attempt to send the histogram data over USB.
433
 *
434
 * @param curBOMvals  Pointer to an array of the current BOM values (the array must have
435
 *		length 16). Use this to print values you have already collected. Otherwise pass in NULL
436
 *		and bom_refresh() will be called and the current BOM intensity values will be collected.
437
 * @return  Exit status - Zero for success; negative on error.
438
 **/
439
int bom_print_usb(int* usrBOMvals) {
440

  
441
	int i, j, max = -1;
442
	int curVals[16];
443
	int* prtValPtr;
444

  
445
	if (usrBOMvals) {
446
		/* Use BOM values collected by user */
447
		prtValPtr = usrBOMvals;
448

  
449
		/* Find max BOM value from users values */
450
		for (i = 0; i < 16; i++) {
451
			if (max < prtValPtr[i])
452
				max = prtValPtr[i];
453
		}
454
	} else {
455
		/* Refresh and make sure the table is updated */
456
		bom_refresh(BOM_ALL);
457

  
458
		/* Record values into an array */
459
		for (i = 0; i < 16; i++) {
460
			curVals[i] = bom_get(i);
461
			if (max < curVals[i])
462
				max = curVals[i];
463
		}
464

  
465
		/* Use the current set of collected values */
466
		prtValPtr = curVals;
467
	}
468

  
469
	/* Display results */
470
	for (i = 0; i < 16; i++) {
471
		
472
		usb_puti(i);
473
		usb_puts(": ");
474
		usb_puti(prtValPtr[i]);
475
		usb_putc('\t');
476

  
477
		for (j = 0; j < (int)((max - prtValPtr[i]) / 5); j++) {
478
			usb_putc('#');
479
		}
480
		usb_puts("\r\n");
481
	}
482
	usb_puts("\r\n");
483

  
484
	return 0;
485

  
486
}
487

  
488
/** 
489
 * Computes the weighted average of all the bom readings to estimate the position (and distance) of another robot.
490
 *
491
 * @pre must call bom refresh
492
 * @param dist  pointer to int in which to return the estimated distance to the other robot
493
 * @return estimated position of the max bom value element as a fixed point value analogous to 10 times the
494
 *        index of the max bom value.  -1 if no value is lower than BOM_VALUE_THRESHOLD.
495
 **/
496
int bom_get_max10(int *dist) {
497
    int i, max;
498
    long long mean = 0, sum = 0;
499

  
500
    max = bom_get_max();
501
    if (max < 0)
502
    {
503
        if (dist)
504
        {
505
            *dist = -1;
506
        }
507
        return -1;
508
    }
509
    /* Record values into an array */
510
    for (i = 0; i < NUM_BOM_LEDS; i++) {
511
        int idx = ((i + (NUM_BOM_LEDS/2 - max) + NUM_BOM_LEDS) % NUM_BOM_LEDS) - (NUM_BOM_LEDS/2 - max);
512
        int val = 255 - bom_val[i];
513
        mean += idx * val;
514
        sum += val;
515
    }
516
    mean = (mean * 10) / sum;
517
    mean = (mean + NUM_BOM_LEDS*10) % (NUM_BOM_LEDS*10);
518

  
519
    if (dist)
520
    {
521
        *dist = 50 - sum/48;
522
    }
523

  
524
    return mean;
525
}
526

  
527
/**
528
 * Iterates through each bit in the bit_field. If the bit is set, the corresponding emitter will
529
 *    be enabled to turn on when bom_on() is called.
530
 *    bom_init must be called for this to work. Does nothing if a BOM1.0 is installed
531
 *
532
 * @param bit_field specifies which leds should be turned on when bom_on is called.  Use BOM_ALL to turn on all bom leds.
533
 *    Ex. if 0x0005 is passed, leds 0 and 2 will be turned on.
534
 **/
535
void bom_set_leds(int bit_field) {
536
    int i;
537
	unsigned int mask = 1<<(NUM_BOM_LEDS-1);
538
	switch(bom_type) {
539
    case BOM10:
540
        //TODO: put an assert here to alert the user that this should not be called
541
        break;
542
		
543
    case BOM15:
544
	    for(i=NUM_BOM_LEDS; i>0; i--)
545
	    {
546
		    //set the current bit, sending MSB first
547
		    digital_output(BOM_DATA, bit_field&mask);
548
		    //then pulse the clock
549
		    digital_output(BOM_CLOCK, 1);
550
		    digital_output(BOM_CLOCK, 0);
551
			mask = mask>>1;
552
	    }
553
        break;
554
		
555
    case RBOM:
556
        //add rbom code here
557
        break;
558
    }
559
}
560

  
561

  
562
/**
563
 * (DEPRECATED) Returns the direction of the maximum BOM reading,
564
 * as an integer in the range 0-15. 0 indicates to the
565
 * robot's right, while the rest of the sensors are
566
 * numbered counterclockwise. This is useful for determining
567
 * the direction of a robot flashing its BOM, of only one
568
 * robot is currently doing so. analog_init must be called
569
 * before this function can be used.
570
 *
571
 * @return the direction of the maximum BOM reading
572
 *
573
 * @see analog_init
574
 **/
575
int get_max_bom(void) {
576
    bom_refresh(BOM_ALL);
577
    return bom_get_max();
578
}
579

  
580
/**
581
 * Flashes the BOM.  If using a BOM1.5, only the emitters that have been enabled using
582
 * bom_set_leds will turn on.
583
 * 
584
 * @see bom_off, bom_set_leds
585
 **/
586
void bom_on(void)
587
{
588
  switch(bom_type) {
589
  case BOM10:
590
	digital_output(MONKL, 1);
591
	break;
592
  case BOM15:
593
	digital_output(BOM_STROBE, 1);
594
	break;
595
  case RBOM:
596
	break;
597
  }
598
}
599

  
600
/**
601
 * Turns off all bom leds.
602
 * 
603
 * @see bom_on
604
 **/
605
void bom_off(void)
606
{
607
  switch(bom_type) {
608
  case BOM10:
609
	digital_output(MONKL, 0);
610
	break;
611
  case BOM15:
612
	digital_output(BOM_STROBE, 0);
613
	break;
614
  case RBOM:
615
	break;
616
  }
617
}
618

  
619
/** @} **/ //end group
620

  
621
//select a detector to read
622
static void bom_select(char which) {
623
	if(bom_type == BOM10)
624
	  which = lookup[(int)which];
625
	
626
    if (which&8)
627
      digital_output(select_pins[3], 1);
628
    else
629
      digital_output(select_pins[3], 0);
630

  
631
    if (which&4)
632
      digital_output(select_pins[2], 1);
633
    else
634
      digital_output(select_pins[2], 0);
635

  
636
    if (which&2)
637
      digital_output(select_pins[1], 1);
638
    else
639
      digital_output(select_pins[1], 0);
640

  
641
    if (which&1)
642
      digital_output(select_pins[0], 1);
643
    else
644
      digital_output(select_pins[0], 0);
645
	
646
}
branches/ir_lookup/bom.h
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file bom.h
29
 * @brief Definitions for using the BOM
30
 * 
31
 * This file contains definitions for using the Bearing and 
32
 * Orientation Module (BOM).
33
 *
34
 * @author Colony Project, CMU Robotics Club
35
 *
36
 **/
37

  
38
#ifndef _BOM_H
39
#define _BOM_H
40

  
41
/**
42
 * @addtogroup bom
43
 * @{
44
 **/
45
 
46
/** @brief Include all elements in the 16-bit bitfield **/
47
#define BOM_ALL 0xFFFF
48

  
49
/** @brief Original BOM - No Range, No Individual LED control **/
50
#define BOM10     0
51

  
52
/** @brief BOM 1.5 - No Range, Individual LED control **/
53
#define BOM15   1
54

  
55
/** @brief RBOM - Range, Individual LED control **/
56
#define RBOM    2
57

  
58

  
59
/** @brief Struct for storing vector data. Used by bom_get_vector() functions **/
60
typedef struct vector {
61
	int x;
62
	int y;
63
} Vector;
64

  
65

  
66
/** @brief Initialize the bom according to bom type **/
67
void bom_init(char type);
68

  
69
/** @brief Refresh bom_val[] with new values from analog8.  analog_init and bom_init must be called for this to work. **/
70
void bom_refresh(int bit_field);
71

  
72
/** @brief Gets the bom reading from bom_val[which].  Call bom_refresh beforehand to read new bom values. **/
73
int bom_get(int which);
74

  
75
/** @brief Compares all the values in bom_val[] and returns the index to the highest value element. **/
76
int bom_get_max(void);
77

  
78
/** @brief Computes the net resultant BOM IR vector. **/
79
int bom_get_vector(Vector*, int*);
80

  
81
/** @brief Computes the normalized net resultant BOM IR vector. **/
82
int bom_get_norm_vector(Vector*, int*);
83

  
84
/** @brief Print snapshot of BOM intensity histogram over USB connection **/
85
int bom_print_usb(int*);
86

  
87
/** @brief Computes the weighted average of all the bom readings to estimate the position and distance of another robot. **/
88
int bom_get_max10(int *dist);
89

  
90
/** @brief Enables the selected bom leds on a BOM1.5 **/
91
void bom_set_leds(int bit_field);
92

  
93
/** @brief (DEPRECATED) Gets and compares all bom values.  Returns the index to the highest value element since last refresh. **/
94
int get_max_bom(void);
95

  
96
/** @brief Turns on all BOM leds, or turns on enabled leds on a BOM1.5. **/
97
void bom_on(void);
98

  
99
/** @brief Turns off all bom leds. **/
100
void bom_off(void);
101

  
102
/** @} **/
103

  
104
#endif
105

  
branches/ir_lookup/motor.c
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file motor.c
29
 * @brief Motors
30
 *
31
 * Implementation of functions for controlling the motors.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 * Much of this is taken from FWR's library, author: Tom Lauwers
35
 **/
36

  
37
#include "motor.h"
38

  
39
/**
40
 * @defgroup motors Motors
41
 * @brief Functions for controlling the motors.
42
 * Functions for controlling the motors. Found in motor.h.
43
 * @{
44
 **/
45

  
46
/**
47
 * Initializes both motors so that they can be used with future
48
 * calls to motor1_set and motor2_set.
49
 *
50
 * @see motors_off, motor1_set, motor2_set
51
 **/
52
void motors_init( void ) {
53
  // Configure counter such that we use phase correct
54
  // PWM with 8-bit resolution
55
  PORTA &= 0x0F;
56
  DDRA |= 0xF0;
57
  DDRB |= 0x60;
58

  
59
  //timer 1A and 1B
60
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);
61
  TCCR1B = _BV(WGM12) | _BV(CS10);
62
  //	TCCR1A = 0xA1;
63
  //	TCCR1B = 0x04;
64
  OCR1AH=0;
65
  OCR1AL=0;
66
  OCR1BH=0;
67
  OCR1BL=0;
68
}
69

  
70
/**
71
 * Sets the speed and direction of the left motor.
72
 * motors_init must be called before this function can be used.
73
 *
74
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
75
 * @param speed The speed the motor will run at, in the range 0-255.
76
 * 
77
 * @see motor_r_set, motors_init
78
 **/
79
void motor_l_set(int direction, int speed) {
80

  
81
  if(direction == 0) {
82
    // turn off PWM first if switching directions
83
    if((PORTA & 0x30) != 0x10) {
84
      OCR1A = 0;
85
    }	
86
    PORTA = (PORTA & 0xCF) | 0x10;
87
    //		PORTD |= 0x10;
88
    //		PORTD &= 0xBF;
89
  } else {
90
    // turn off PWM first if switching directions
91
    if((PORTA & 0x30) != 0x20) {
92
      OCR1A = 0;
93
    }
94
    PORTA = (PORTA & 0xCF) | 0x20;
95
    //		PORTD |= 0x40;
96
    //		PORTD &= 0xEF;
97
  }
98
	
99
  // Set the timer to count up to speed, an 8-bit value
100
  OCR1AL = speed;
101
}
102

  
103
/**
104
 * Sets the speed and direction of the right motor.
105
 * motors_init must be called before this function can be used.
106
 *
107
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
108
 * @param speed The speed the motor will run at, in the range 0-255.
109
 *
110
 * @see motor_l_set, motors_init
111
 **/
112
void motor_r_set(int direction, int speed) {
113
  if(direction == 0) {
114
    //		PORTD |= 0x20;
115
    //		PORTD &= 0x7F;
116
    // turn off PWM first if switching directions
117
    if((PORTA & 0xC0) != 0x80) {
118
      OCR1B = 0;
119
    }		
120
		
121
    PORTA = (PORTA & 0x3F) | 0x80;
122
  } else {
123
    //		PORTD |= 0x80;
124
    //		PORTD &= 0xDF;
125

  
126
    // turn off PWM first if switching directions
127
    if((PORTA & 0xC0) != 0x40) {
128
      OCR1B = 0;
129
    }		
130
		
131
    PORTA = (PORTA & 0x3F) | 0x40;
132
  }
133
  OCR1BL = speed;
134
}
135

  
136
/**
137
 * Sets the speed and direction of motor1.
138
 * motors_init must be called before this function can be used.
139
 *
140
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
141
 * @param speed The speed the motor will run at, in the range 0-255.
142
 *
143
 * @see motor2_set, motors_init
144
 **/
145
void motor1_set(int direction, int speed) {
146
	motor_l_set(direction, speed);
147
}
148

  
149
/**
150
 * Sets the speed and direction of motor2.
151
 * motors_init must be called before this function can be used.
152
 *
153
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
154
 * @param speed The speed the motor will run at, in the range 0-255.
155
 *
156
 * @see motor2_set, motors_init
157
 **/
158
void motor2_set(int direction, int speed) {
159
	motor_r_set(direction, speed);
160
}
161

  
162

  
163
/**
164
 * Turns off both motors.
165
 *
166
 * @see motors_init
167
 **/
168
void motors_off( void ) {
169
  OCR1AL = 0x0;
170
  OCR1BL = 0x0;
171
}
172

  
173
/**@}**///end defgroup
174

  
branches/ir_lookup/motor.h
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file motor.h
29
 * @brief Contains definitions for controlling the motors
30
 *
31
 * Contains definitions and functions for controlling
32
 * the motors.
33
 *
34
 * @author Colony Project, CMU Robotics Club
35
 * Based on Tom Lauwer's Firefly Library
36
 **/
37

  
38
#ifndef _MOTOR_H
39
#define _MOTOR_H
40

  
41
#include <avr/io.h>
42
/**
43
 * @addtogroup motors
44
 * @{
45
 **/
46

  
47
/** @brief make the motors go forwards **/
48
#define FORWARD 1
49
/** @brief make the motors go backwards **/
50
#define BACKWARD 0
51

  
52
/** @brief Initialize the motors **/
53
void motors_init(void);
54
/** @brief Set speed and direction of motor1 
55
 *  @deprecated use the left motor function instead. it's more intuitive and easier to read.**/
56
void motor1_set(int direction, int speed);
57
/** @brief Set speed and direction of motor2 
58
 *  @deprecated use the right motor function instead. it's more intuitive and easier to read.**/
59
void motor2_set(int direction, int speed);
60
/** @brief Set speed and direction of left motor **/
61
void motor_l_set(int direction, int speed);
62
/** @brief Set speed and direction of right motor **/
63
void motor_r_set(int direction, int speed);
64
/** @brief Turn the motors off **/
65
void motors_off(void);
66

  
67
/**@}**/ // end addtogroup
68

  
69
#endif
70

  
branches/ir_lookup/i2c.c
1
/**
2
 * Copyright (c) 2007 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26

  
27
/**
28
 * @file i2c.c
29
 * @brief Implemenation of I2C communications protocol
30
 * 
31
 * In the case where you have master sends and then a master request to the same
32
 * address, you will not give up control of the line because the send and
33
 * request addresses are seen as different addresses. In between it will send a
34
 * restart but will not give up the line.
35
 *
36
 * @author CMU Robotics Club, Kevin Woo, Sursh Nidhiry
37
 * @bug Not tested.
38
 */
39

  
40
#include <avr/interrupt.h>
41
#include <util/twi.h>
42

  
43
#include "i2c.h"
44
#include "ring_buffer.h"
45

  
46
/**
47
 * @defgroup i2c I2C 
48
 *
49
 * @brief Provides Inter-Interconnected-Communications (I2C)
50
 * 
51
 * Initiates I2C functions on an ATMega128 which has a fully hardware Two Wire 
52
 * Interface (TWI) module. Any Atmel chip with this hardware should be able to
53
 * use the software.
54
 *
55
 * This code will operate in a multi-master enviornment and can be either a
56
 * slave or a master at any time (as long as they are not one or the other at
57
 * the moment. You can queue up multiple transmission modes in the buffer up to 
58
 * the buffer size. The buffer is implemented as a ring buffer.
59
 *
60
 * It is implemented using callback functions. Whenever you want to send a packet
61
 * you can call the built in send function (as a master) and it will send an array
62
 * of bytes. Master recieve and slave send/receive are all handled by the call back
63
 * functions. It is up to the end user to create functions that will handle the
64
 * receiving of packets. Their functions will be called with every byte recieved
65
 * so you must either buffer the inputs or handle each one separately.
66
 *
67
 * On errors we will simply flush the entire buffer.
68
 * 
69
 * For information on how I2C operates, read the wikipedia article
70
 * http://en.wikipedia.org/wiki/I2c
71
 * for a good explanation of how it works.
72
 * @{
73
 */
74

  
75
/** 
76
 * @brief Set bit rate 12 = 100kbit/s (max speed setting is 10 for an
77
 *  8 MHz clock). It is a divider, so the lower the number the faster the speed.
78
 */
79
#define I2C_BIT_RATE_DIVIDER 0x0C
80

  
81
static int start_flag;
82

  
83
static fun_mrecv_t master_recv_function;
84
static fun_srecv_t slave_recv_function;
85
static fun_send_t slave_send_function;
86

  
87
RING_BUFFER_NEW(i2c_buffer, 128, char, i2c_write_buff, i2c_addr_buff);
88

  
89

  
90
/**
91
 * @brief Initializes the i2c module.
92
 *
93
 * Initializes the I2C module to start listening on the i2c lines. If the callback functions
94
 * are not set to null they will be called when that transmission mode is called. The address
95
 * is your address that you will listen to when you are not the master.
96
 *
97
 * @param addr 			Your address on the I2C bus.
98
 * @param master_recv 	The address of the function to call when you receive a byte when you are a
99
 *                    	master.
100
 * @param slave_recv 	The address of the function to call when you are a slave you receive data
101
 *								from the master
102
 * @param slave_send		The address of the function to call when you are a slave and the master
103
 *								requests data from you.
104
 *
105
 * @return 0 for success, nonzero for failure
106
 **/
107
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) {
108
    master_recv_function = master_recv;
109
    slave_recv_function = slave_recv;
110
    slave_send_function = slave_send;
111

  
112
    RING_BUFFER_CLEAR(i2c_write_buff);
113
    RING_BUFFER_CLEAR(i2c_addr_buff);
114
  
115
    /* enables twi interrupt, automatic ack sending, and all twi hardware */
116
    TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
117

  
118
    /* sets the bit rate of data transmission */
119
    TWBR = I2C_BIT_RATE_DIVIDER;
120

  
121
    /* sets the address (it is stored in the 7 most significant bits) and allows
122
     * global messages to be accepted */
123
    TWAR = (addr << 1) | 1;
124
  
125
    return 0;
126
}
127

  
128
/**
129
 * @brief Sends a byte array over I2C as a master
130
 *
131
 * Will perform a send over I2C to the destination from data for the ammount of
132
 * bytes that bytes is.
133
 *
134
 * @param dest		Destination address of the data on the I2C bus.
135
 * @param data 	The pointer to the byte array of data
136
 * @param bytes	The amount of bytes long that the byte array is. This is how
137
 *						many bytes from the array that the function will send.
138
 *
139
 * @return zero for success, nonzero for failure
140
 **/
141
int i2c_send(char dest, char *data, unsigned int bytes) {
142
    int i;
143

  
144
    /* adding data to be sent to ring buffers is not atomic,
145
     * so disable interrupts */
146
    cli();
147
    for(i = 0; i < bytes; i++) {
148
        if(RING_BUFFER_FULL(i2c_write_buff)) {
149
            sei();
150
            return -1;
151
        }
152

  
153
        RING_BUFFER_ADD(i2c_write_buff, data[i]);
154
        RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
155
    }
156
    
157
    /* re-enable the interrupts */
158
    sei();
159
    
160
    /* send the start bit, only if this device is not currently master */
161
    if(!start_flag) {
162
        start_flag = 1;
163
        TWCR |= _BV(TWSTA);
164
        TWCR |= _BV(TWINT);
165
    }
166
  
167
    return 0;
168
}
169
 
170
/**
171
 * @brief Send a master request to the destination
172
 *
173
 * Sends a request of data from the target address and calls
174
 * the callback function to handle data as it comes in. This function will
175
 * not work if the slave has not informationt to send or has nothing implemented
176
 * to send it.
177
 *
178
 * @param dest		The destination that we want to receive information from.
179
 *
180
 * @return 0 for success, nonzero for failure
181
 **/ 
182
int i2c_request(char dest) {
183
    if(RING_BUFFER_FULL(i2c_write_buff))
184
        return -1;
185
  
186
    RING_BUFFER_ADD(i2c_write_buff, 0);
187
    RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
188
  
189
    if(!start_flag) {
190
        start_flag = 1;
191
        TWCR |= _BV(TWSTA);
192
        TWCR |= _BV(TWINT);
193
    }
194
  
195
    return 0;
196
}
197

  
198
/** @} **/
199
 
200
/**
201
 * @brief Interrupt to handle I2C interrupts from the I2C hardware.
202
 * 
203
 * Uses the status codes from the I2C register to handle the events
204
 * needed to advance in I2C stages. For instance, you will get a bit for
205
 * receiving a start ack, then a address ack, then a data ack, etc.
206
 * The events are handled in each switch case. The status codes are defined
207
 * by avr-gcc in /util/twi.h but are the same codes as the Atmel documentation.
208
 *
209
 * Bytes are sent by popping off the ring buffer. It also will keep track
210
 * of what modes the send is in.
211
 *
212
 * Errors are handled here as well.
213
 **/ 
214
ISR(TWI_vect) {
215
	static char data_to_send;
216
	static char addr_to_send = -1;
217
	char addr, statusCode;
218
  
219
	//Get status code (only upper 5 bits)
220
	statusCode = (TWSR & 0xF8);
221

  
222
    switch (statusCode) {
223
        //Start sent successfully
224
        case TW_START:
225
        case TW_REP_START:
226
            /* Send address and write
227
             * ring_buffer will not be empty */
228
            RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
229
            RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
230
            
231
            /* first send the address */
232
            TWDR = addr_to_send; 
233
            
234
            //Turn off start bits
235
            TWCR &= ~_BV(TWSTA);
236
            break;
237

  
238
        //Master Transmit - Address sent succesfully
239
        case TW_MT_SLA_ACK:
240
        //Send byte
241
            TWDR = data_to_send;
242
            PORTG &= ~_BV(PG2);
243
            break;
244
	 
245
        //Master Transmit - Data sent succesfully
246
        case TW_MT_DATA_ACK:    
247
            //If there is still data to send
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff