Project

General

Profile

Revision 544

Added by ibrin about 16 years ago

worked on lights driver, set up everything except a sort and a time-split calculating method

View differences:

branches/lights/projects/libdragonfly/lights_old.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 ligths.c
29
 * @brief Orbs
30
 *
31
 * Implemenation for the orbs (tri-colored LEDs)
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 * @bug Colors are incorrect, seems to not work with wireless library
35
 **/
36

  
37
/*
38
lights.c
39
Controls orb1 and orb2. Also contains the framework for a software PWM that may be used for servos in the future.
40

  
41
author: CMU Robotics Club, Colony Project
42

  
43
Change Log:
44
2.4.07 - Aaron
45
	Revamped orb code so it works.  Need to check interaction with rtc, and tweak some colors.
46

  
47
2.1.07 - James
48
	Modified sort_buffer() to prune for repeats.  PWM now uses orb_buf_size for the number of orb values in orb_time_arr[].
49
		Changed sorting algorithm used in sort_buffer() to selection sort (faster). And it works now.
50

  
51
1.25.07 - KWoo
52
	Deleted old FF+ code to make it cleaner. Commented code. This all works. Note however that if you ever plan to use the
53
		software PWM (which is this) you will need to change the implementation of orb_enable() and orb_disable() to not
54
		shutdown the PWM.
55

  
56
*/
57

  
58
#include "lights.h"
59
#include "dragonfly_lib.h"
60
#include <avr/interrupt.h>
61

  
62
#define ORB_RESET 1025
63
#define ORBPORT PORTC
64
#define ORBDDR DDRC
65
#define ORBMASK 0x77
66

  
67
/***** Port and Pin Definitions ****/
68

  
69
//Orb Ports and Registers
70
#define ORB_PORT        PORTC
71
#define ORB_DDR         DDRC
72

  
73
//Orb Pins
74
#define ORB1_RED        0x00
75
#define ORB1_GREEN      0x01
76
#define ORB1_BLUE       0x02
77
#define ORB2_RED        0x04
78
#define ORB2_GREEN      0x05
79
#define ORB2_BLUE       0x06
80

  
81

  
82
#define ORB_COUNT 8	//please dont change this, or bad things might happen
83

  
84
// an orb node
85
struct ORB_NODE {
86
   uint8_t num;
87
   uint16_t angle;
88
};
89

  
90
//the change in an orb
91
struct ORB_CHANGE {
92
   uint16_t port_val;
93
   uint16_t split_time_period;
94
};
95

  
96
// the status of an orb
97
struct ORB_STATUS_STRUCT {
98
   struct ORB_NODE orbs[ORB_COUNT];
99
   uint16_t orb_angles[ORB_COUNT];
100
   struct ORB_CHANGE changes[ORB_COUNT+1];
101
   uint8_t change_count;
102
   uint8_t new_angles;
103
   uint8_t current_orb;
104

  
105
} ORB_STATUS;
106

  
107
void orb_sort(void);
108
void orb_setup_pulse(void);
109

  
110
SIGNAL (SIG_OUTPUT_COMPARE3C){
111

  
112
		//pull the correct ones down
113
      ORBPORT &= (~ORBMASK)|(ORB_STATUS.changes[ORB_STATUS.current_orb].port_val);
114

  
115
      ++ORB_STATUS.current_orb; //now look at next orb transition
116

  
117
      if (ORB_STATUS.current_orb < ORB_STATUS.change_count) { //if it isnt the end...
118
	  
119
			//setup timer for next pull down
120
         OCR3C = TCNT3+ORB_STATUS.changes[ORB_STATUS.current_orb].split_time_period;
121
		 
122
     }
123
      else { //we are done with these pulses
124
		orb_setup_pulse();
125
      }
126

  
127
}
128

  
129

  
130
//sets a channel to a value
131
void orb_set_angle(int orb, int angle) {
132
	uint8_t mysreg;
133
	
134
	orb=orb&0x07; //only have 8
135
	angle=angle&0xff; //only accept 0-255
136
	angle=255-angle; //inverse intensity
137
	angle=angle<<2; //scale up so that we dont run it too often
138
	angle+=3; //0 values dont really work
139
   if (ORB_STATUS.orb_angles[orb] != angle) { //if the angle has changed
140
	  mysreg=SREG; 
141
	  cli(); //disable interrupts
142
      ORB_STATUS.orb_angles[orb] = angle; //update angle
143
      ORB_STATUS.new_angles = 1;
144
	  SREG=mysreg; //put interrupt status back
145
   }
146
}
147

  
148

  
149
void orb_sort(void) {
150
   int done = 0, i;
151
   
152
   while (! done) {
153
      done = 1;
154

  
155
      for (i = 0; i < ORB_COUNT - 1; ++i) {  //loop through all
156
	  
157
			//if they are out of order, swap them
158
         if (ORB_STATUS.orbs[i].angle > ORB_STATUS.orbs[i+1].angle) {
159
            ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
160
            ORB_STATUS.orbs[i+1].angle ^= ORB_STATUS.orbs[i].angle;
161
            ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
162

  
163
            ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
164
            ORB_STATUS.orbs[i+1].num ^= ORB_STATUS.orbs[i].num;
165
            ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
166

  
167
            done = 0;
168
         }
169
      }
170
   }
171
}
172

  
173
//calculate the split times
174
void orb_setup_pulse(void) {
175
   int i;
176
   uint16_t my_port;
177
   uint16_t sum = 0;
178
   uint16_t split_time;
179

  
180
   my_port = 0xff; //all on
181

  
182
   if (ORB_STATUS.new_angles) {
183

  
184
      ORB_STATUS.change_count = 0;
185
	  for (i = 0; i < ORB_COUNT; ++i) { //get the new values
186
         ORB_STATUS.orbs[i].angle = ORB_STATUS.orb_angles[ORB_STATUS.orbs[i].num];
187
      }
188

  
189
      orb_sort(); //sort them
190
      ORB_STATUS.new_angles = 0;
191

  
192
      for (i = 0; i < ORB_COUNT; ++i) { //calculate split times
193
         split_time = ORB_STATUS.orbs[i].angle - sum;
194
         my_port &= ~_BV(ORB_STATUS.orbs[i].num);
195
		 
196
         for (; i < ORB_COUNT - 1 && ORB_STATUS.orbs[i].angle == ORB_STATUS.orbs[i+1].angle; ++i) {
197
            my_port &= ~_BV(ORB_STATUS.orbs[i+1].num); //look for doups
198
         }
199
		 
200
         ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port; //which pins are low
201
         ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = split_time;
202
         
203
		 ++ORB_STATUS.change_count;
204
		 
205
         sum += split_time;
206
      }
207

  
208
      ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port;
209
      ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = ORB_RESET - sum; //get a constant period
210

  
211
      ++ORB_STATUS.change_count;
212

  
213
   }
214

  
215

  
216

  
217
   ORB_STATUS.current_orb = 0;
218

  
219
    ORBPORT |= ORBMASK; //start with all high
220
	OCR3C = TCNT3 + ORB_STATUS.changes[0].split_time_period; //wait for first split
221

  
222
}
223

  
224
/**
225
 * @defgroup orbs Orbs
226
 * @brief Functions for controlling the color of the orbs.
227
 * 
228
 * Functions for controlling the color and lighting of the orbs.
229
 *
230
 * @{
231
 **/
232

  
233
/**
234
 * Initializes the PWM for Orb control. This must be called before 
235
 * the orbs are used for them to function.
236
 **/
237
void orb_init() 
238
{	
239
   int i;
240
   uint8_t mysreg;
241
   
242
   ORBDDR |= ORBMASK;	//all outputs
243
   
244
	mysreg=SREG;
245
	cli(); //turn off interrupts for now
246

  
247
	//init everything
248

  
249
   for (i = 0; i < ORB_COUNT; ++i) {
250
      ORB_STATUS.orbs[i].num = i;
251
      ORB_STATUS.orbs[i].angle = 1023;	//127 is a pretty stupid start angle, but oh well
252
      ORB_STATUS.orb_angles[i] = 1023;
253
   }
254

  
255
   ORB_STATUS.new_angles = 1;
256
   ORB_STATUS.change_count = 0;
257

  
258
	//init timer3
259
	TCCR3A = 0; 
260
	TCCR3B = _BV(CS31); //prescale = 8
261
	TCCR3C = 0;
262
	ETIMSK |= _BV(OCIE3C); //turn on oc3c interrupt
263
	OCR3C = TCNT3+ORB_RESET;
264

  
265
	SREG=mysreg;
266
}
267

  
268
/**
269
 * Set both orbs to the color specified. orb_init must
270
 * be called before this function may be used.
271
 *
272
 * @param red_led the red component of the color
273
 * @param green_led the green component of the color
274
 * @param blue_led the blue component of the color
275
 *
276
 * @see orb_init
277
 **/
278
void orb_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {
279
	orb1_set(red_led,green_led,blue_led);
280
	orb2_set(red_led,green_led,blue_led);
281

  
282
}
283

  
284
/**
285
 * Set orb1 to the color specified. orb_init must
286
 * be called before this function may be used.
287
 *
288
 * @param red_led the red component of the color
289
 * @param green_led the green component of the color
290
 * @param blue_led the blue component of the color
291
 *
292
 * @see orb_init
293
 **/
294
void orb1_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {
295
	orb_set_angle(0,red_led);
296
	orb_set_angle(1,green_led);
297
	orb_set_angle(2,blue_led);
298
}
299

  
300
/**
301
 * Set orb2 to the color specified. orb_init must
302
 * be called before this function may be used.
303
 *
304
 * @param red_led the red component of the color
305
 * @param green_led the green component of the color
306
 * @param blue_led the blue component of the color
307
 *
308
 * @see orb_init
309
 **/
310
void orb2_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {	
311
	orb_set_angle(4,red_led);
312
	orb_set_angle(5,green_led);
313
	orb_set_angle(6,blue_led);
314
}
315

  
316
/**
317
 * Set both orbs to the specified color. This function
318
 * is intended to be used with the predefined
319
 * colors. orb_init must be called before this
320
 * function may be used.
321
 *
322
 * @param col the color to set the orbs to
323
 *
324
 * @see orb_init
325
 **/
326
void orb_set_color(int col)
327
{
328
 int red, green, blue;
329

  
330
 red = ((col & 0xE0) >> 5) * 36;
331
 green = ((col & 0x1C) >> 2) * 36;
332
 blue = (col & 0x03) * 85;
333

  
334
 orb_set(red, green, blue);
335
}
336

  
337
/**
338
 * Set orb1 to the specified color. This function
339
 * is intended to be used with the predefined
340
 * colors. orb_init must be called before this
341
 * function may be used.
342
 *
343
 * @param col the color to set the orbs to
344
 *
345
 * @see orb_init
346
 **/
347
void orb1_set_color(int col)
348
{
349
 int red, green, blue;
350

  
351
 red = ((col & 0xE0) >> 5) * 36;
352
 green = ((col & 0x1C) >> 2) * 36;
353
 blue = (col & 0x03) * 85;
354

  
355
 orb1_set(red, green, blue);
356
}
357

  
358
/**
359
 * Set orb2 to the specified color. This function
360
 * is intended to be used with the predefined
361
 * colors. orb_init must be called before this
362
 * function may be used.
363
 *
364
 * @param col the color to set the orbs to
365
 *
366
 * @see orb_init
367
 **/
368
void orb2_set_color(int col)
369
{
370
 int red, green, blue;
371

  
372
 red = ((col & 0xE0) >> 5) * 36;
373
 green = ((col & 0x1C) >> 2) * 36;
374
 blue = (col & 0x03) * 85;
375

  
376
 orb2_set(red, green, blue);
377
}
378

  
379
//DOES THIS WORK?
380
// Disables the timer1 interrupt, disabling the Orb's color fading capabilities
381
// You can still turn the red, green, and blue leds on and off with set_orb_dio
382
/* If we use the PWM for anything else besides the ORB, this implementation needs to be done better */
383
/**
384
 * Disables the orb color fading capabilities
385
 * by disabling the timer1 interrupt.
386
 *
387
 * @see orb_init
388
 **/
389
void orb_disable()
390
{
391
	TCCR3B &= 0;  	//Turn off everything
392
	ORB_PORT |= _BV(ORB1_RED);
393
	ORB_PORT |= _BV(ORB1_GREEN);
394
	ORB_PORT |= _BV(ORB1_BLUE);
395
	ORB_PORT |= _BV(ORB2_RED);
396
	ORB_PORT |= _BV(ORB2_GREEN);
397
	ORB_PORT |= _BV(ORB2_BLUE);
398
}
399

  
400
//DOES THIS WORK?
401
// Enables the timer1 interrupt, enabling the Orb's color fading capabilities
402
/**
403
 * Enables the orb's color fading capabilities.
404
 *
405
 * @see orb_init
406
 **/
407
void orb_enable()
408
{
409
//	TCCR0 |= _BV(COM01) | _BV(COM00)  | _BV(WGM00) | _BV(CS01);	//Toggle OC Pin on match, FAST PWM Mode, clock/8
410
	TCCR3B =_BV(CS31);
411
}
412

  
413
/** @} **/ //end group
414

  
branches/lights/projects/libdragonfly/lights.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 ligths.c
29
 * @brief Orbs
30
 *
31
 * Implemenation for the orbs (tri-colored LEDs)
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 * @bug Colors are incorrect, seems to not work with wireless library
35
 **/
36

  
37
/*
38
lights.c
39
Controls orb1 and orb2. Also contains the framework for a software PWM that may be used for servos in the future.
40

  
41
author: CMU Robotics Club, Colony Project
42

  
43
Change Log:
44
2.4.07 - Aaron
45
	Revamped orb code so it works.  Need to check interaction with rtc, and tweak some colors.
46

  
47
2.1.07 - James
48
	Modified sort_buffer() to prune for repeats.  PWM now uses orb_buf_size for the number of orb values in orb_time_arr[].
49
		Changed sorting algorithm used in sort_buffer() to selection sort (faster). And it works now.
50

  
51
1.25.07 - KWoo
52
	Deleted old FF+ code to make it cleaner. Commented code. This all works. Note however that if you ever plan to use the
53
		software PWM (which is this) you will need to change the implementation of orb_enable() and orb_disable() to not
54
		shutdown the PWM.
55

  
56
*/
57

  
58 1
#include "lights.h"
59 2
#include "dragonfly_lib.h"
60 3
#include <avr/interrupt.h>
......
71 14
#define ORB_DDR         DDRC
72 15

  
73 16
//Orb Pins
74
#define ORB1_RED        0x00
75
#define ORB1_GREEN      0x01
76
#define ORB1_BLUE       0x02
77
#define ORB2_RED        0x04
78
#define ORB2_GREEN      0x05
79
#define ORB2_BLUE       0x06
17
#define ORB1_RED        0x01
18
#define ORB1_GREEN      0x02
19
#define ORB1_BLUE       0x04
20
#define ORB2_RED        0x10
21
#define ORB2_GREEN      0x20
22
#define ORB2_BLUE       0x40
80 23

  
24
//this used to be 8 but i changed it. i suspect it was 8 cuz of the led pins + 2 enc pins, but not sure
25
#define ORB_COUNT 6	//please dont change this, or bad things might happen, number of orb pins off port, this should more accurately be called LED_COUNT i think
81 26

  
82
#define ORB_COUNT 8	//please dont change this, or bad things might happen
83

  
84 27
// an orb node
85 28
struct ORB_NODE {
86 29
   uint8_t num;
87 30
   uint16_t angle;
88
};
89

  
90
//the change in an orb
91
struct ORB_CHANGE {
92 31
   uint16_t port_val;
93
   uint16_t split_time_period;
94
};
32
   int time_split; // this will store the amount of time the timer needs to be set to from previous pin
33
} ORB_NODE;
95 34

  
96
// the status of an orb
35
// the status of the orbs
97 36
struct ORB_STATUS_STRUCT {
98 37
   struct ORB_NODE orbs[ORB_COUNT];
99
   uint16_t orb_angles[ORB_COUNT];
100
   struct ORB_CHANGE changes[ORB_COUNT+1];
38
   int changes[ORB_COUNT]; // when an orb changes, its number will go from 0 to 1
101 39
   uint8_t change_count;
102 40
   uint8_t new_angles;
103 41
   uint8_t current_orb;
104

  
105 42
} ORB_STATUS;
106 43

  
107
void orb_sort(void);
108
void orb_setup_pulse(void);
44
struct ORB_CHANGED_ORBS {
45
	int orb_number;
46
	uint16_t new_angle;
47
} ORB_CHANGED_ORBS;
109 48

  
49
struct ORB_CHANGED_ORBS_STRUCT {
50
	struct ORB_CHANGED_ORBS changed_orbs[ORB_COUNT];
51
} ORB_CHANGED_ORBS_STRUCT;
52

  
53
struct ORB_ORDER { // 0 will store number of first orb to turn off, 1 of second, etc.
54
	int order[ORB_COUNT];
55
} ORB_ORDER;
56

  
57
void sort_orbs(void); // this function will copy new values into angle values
58
void calc_split_times(void); // this function will calculate split times and place them in the appropriate orbs
59

  
60
// use compare C to reset every pulse + check new times
110 61
SIGNAL (SIG_OUTPUT_COMPARE3C){
111 62

  
112
		//pull the correct ones down
113
      ORBPORT &= (~ORBMASK)|(ORB_STATUS.changes[ORB_STATUS.current_orb].port_val);
63
      ORB_STATUS.current_orb=0; // reset the orb we're looking at
114 64

  
115
      ++ORB_STATUS.current_orb; //now look at next orb transition
65
		if(ORB_STATUS.change_count>0)
66
		{
67
			sort_orbs();
68
			calc_split_times();
69
		}
70
	  
71
	  // now that we've done everything, turn on all the lights
72
	  ORB_PORT |= ORBMASK;
73
	  // reset the time
74
	  OCR3C = TCNT3+ORB_RESET;
75
	  // turn ocr3a back on and set the time for the lights off counter
76
	  ETIMSK |= _BV(OCIE3A); //turn on oc3a interrupt
77
	  OCR3A = TCNT3+ORB_STATUS.orbs[0].time_split; //set time
78
	  
79
}
116 80

  
117
      if (ORB_STATUS.current_orb < ORB_STATUS.change_count) { //if it isnt the end...
81
// use compare A for turning lights off
82
SIGNAL (SIG_OUTPUT_COMPARE3A){
83
		//pull the correct ones down
84
      ORBPORT &= ~(ORB_STATUS.orbs[ORB_ORDER.order[ORB_STATUS.current_orb]].port_val);
118 85
	  
86
	  int num_updated_orbs = 1;
87
		// HERE, YOU ALSO NEED TO CHECK IF ANY OTHER ORBS HAVE THE SAME TIME!!!!!!!!!!!!!!!!@#!#!@#!@#!@#, update num updated
88
      
89
	  ORB_STATUS.current_orb+=num_updated_orbs; //now look at next orb transition
90

  
91
      if (ORB_STATUS.current_orb < ORB_COUNT) { //if it isnt the end...
119 92
			//setup timer for next pull down
120
         OCR3C = TCNT3+ORB_STATUS.changes[ORB_STATUS.current_orb].split_time_period;
93
         OCR3C = TCNT3+ORB_STATUS.orbs[ORB_STATUS.current_orb].time_split;
121 94
		 
122 95
     }
123 96
      else { //we are done with these pulses
124
		orb_setup_pulse();
125
      }
97
		//turn off this timer until it is reset
98
		ETIMSK &= ~(_BV(OCIE3A)); 
99
	  }
126 100

  
127 101
}
128 102

  
103
void orb_init()
104
{
105
   uint8_t mysreg;
106
      int i;
107
	ORBDDR |= ORBMASK;	//make all the pins output ports
129 108

  
109
   
110
	mysreg=SREG;
111
	cli(); //turn off interrupts for now
112

  
113
	//we're looking at the 1st orb
114
	ORB_STATUS.current_orb=0;
115
	//store values
116
	for (i = 0; i < ORB_COUNT; ++i) {
117
      ORB_STATUS.orbs[i].num = i;
118
	  //i'm not sure why he starts at 1023, so i'm making it 0 for now
119
      ORB_STATUS.orbs[i].angle = 0; //1023;	//127 is a pretty stupid start angle, but oh well
120
	  ORB_STATUS.changes[i]=1; // each orb has been "changed"
121
	}
122
	ORB_STATUS.orbs[0].port_val=ORB1_RED;
123
	ORB_STATUS.orbs[1].port_val=ORB1_GREEN;
124
	ORB_STATUS.orbs[2].port_val=ORB1_BLUE;
125
	ORB_STATUS.orbs[3].port_val=ORB2_RED;
126
	ORB_STATUS.orbs[4].port_val=ORB2_GREEN;
127
	ORB_STATUS.orbs[5].port_val=ORB2_BLUE;
128
	
129
	//init timer3
130
	TCCR3A = 0; // sets normal operation
131
	TCCR3B = _BV(CS31); //set a prescale of 8
132
	TCCR3C = 0; // sets normal operation
133
	ETIMSK |= _BV(OCIE3C); //turn on oc3c interrupt
134
	ETIMSK |= _BV(OCIE3A); //turn on oc3a interrupt
135
	OCR3C = TCNT3+ORB_RESET; // WHAT HAPPENS IF THE TIMER IS ON FOR A VERY LONG TIME; OVERFLOW?
136
	OCR3A = TCNT3+ORB_RESET;
137
	
138
	SREG=mysreg;
139
}
140

  
130 141
//sets a channel to a value
131 142
void orb_set_angle(int orb, int angle) {
132 143
	uint8_t mysreg;
......
134 145
	orb=orb&0x07; //only have 8
135 146
	angle=angle&0xff; //only accept 0-255
136 147
	angle=255-angle; //inverse intensity
148

  
149
/*
137 150
	angle=angle<<2; //scale up so that we dont run it too often
138 151
	angle+=3; //0 values dont really work
139
   if (ORB_STATUS.orb_angles[orb] != angle) { //if the angle has changed
152
  */
153
  
154
	// check if the angle is different, if it is, update our status
155
	if(angle!=ORB_STATUS.orbs[orb].angle)
156
	{
157
		ORB_STATUS.new_angles++;
158
		ORB_STATUS.changes[orb]=1;
159
	}
160
  
161
	mysreg=SREG;
162
	cli();
163
  ORB_CHANGED_ORBS_STRUCT.changed_orbs[orb].new_angle=angle;
164
//    ORB_STATUS.orbs[orb].angle = angle; //update angle
165
	SREG = mysreg;
166

  
167
  // dont see why you need to track changes, so might as well just change it
168
  /*
169
	mysreg=SREG;
170
	cli();
171
    ORB_STATUS.orb_angles[orb] = angle; //update angle
172
	SREG = mysreg;
173
	*/
174
/*
175
	if (ORB_STATUS.orb_angles[orb] != angle) { //if the angle has changed
140 176
	  mysreg=SREG; 
141 177
	  cli(); //disable interrupts
142 178
      ORB_STATUS.orb_angles[orb] = angle; //update angle
143 179
      ORB_STATUS.new_angles = 1;
144 180
	  SREG=mysreg; //put interrupt status back
145 181
   }
182
   */
146 183
}
147 184

  
148

  
149
void orb_sort(void) {
150
   int done = 0, i;
151
   
152
   while (! done) {
153
      done = 1;
154

  
155
      for (i = 0; i < ORB_COUNT - 1; ++i) {  //loop through all
156
	  
157
			//if they are out of order, swap them
158
         if (ORB_STATUS.orbs[i].angle > ORB_STATUS.orbs[i+1].angle) {
159
            ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
160
            ORB_STATUS.orbs[i+1].angle ^= ORB_STATUS.orbs[i].angle;
161
            ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
162

  
163
            ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
164
            ORB_STATUS.orbs[i+1].num ^= ORB_STATUS.orbs[i].num;
165
            ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
166

  
167
            done = 0;
168
         }
169
      }
170
   }
171
}
172

  
173
//calculate the split times
174
void orb_setup_pulse(void) {
175
   int i;
176
   uint16_t my_port;
177
   uint16_t sum = 0;
178
   uint16_t split_time;
179

  
180
   my_port = 0xff; //all on
181

  
182
   if (ORB_STATUS.new_angles) {
183

  
184
      ORB_STATUS.change_count = 0;
185
	  for (i = 0; i < ORB_COUNT; ++i) { //get the new values
186
         ORB_STATUS.orbs[i].angle = ORB_STATUS.orb_angles[ORB_STATUS.orbs[i].num];
187
      }
188

  
189
      orb_sort(); //sort them
190
      ORB_STATUS.new_angles = 0;
191

  
192
      for (i = 0; i < ORB_COUNT; ++i) { //calculate split times
193
         split_time = ORB_STATUS.orbs[i].angle - sum;
194
         my_port &= ~_BV(ORB_STATUS.orbs[i].num);
195
		 
196
         for (; i < ORB_COUNT - 1 && ORB_STATUS.orbs[i].angle == ORB_STATUS.orbs[i+1].angle; ++i) {
197
            my_port &= ~_BV(ORB_STATUS.orbs[i+1].num); //look for doups
198
         }
199
		 
200
         ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port; //which pins are low
201
         ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = split_time;
202
         
203
		 ++ORB_STATUS.change_count;
204
		 
205
         sum += split_time;
206
      }
207

  
208
      ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port;
209
      ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = ORB_RESET - sum; //get a constant period
210

  
211
      ++ORB_STATUS.change_count;
212

  
213
   }
214

  
215

  
216

  
217
   ORB_STATUS.current_orb = 0;
218

  
219
    ORBPORT |= ORBMASK; //start with all high
220
	OCR3C = TCNT3 + ORB_STATUS.changes[0].split_time_period; //wait for first split
221

  
222
}
223

  
224
/**
225
 * @defgroup orbs Orbs
226
 * @brief Functions for controlling the color of the orbs.
227
 * 
228
 * Functions for controlling the color and lighting of the orbs.
229
 *
230
 * @{
231
 **/
232

  
233
/**
234
 * Initializes the PWM for Orb control. This must be called before 
235
 * the orbs are used for them to function.
236
 **/
237
void orb_init() 
238
{	
239
   int i;
240
   uint8_t mysreg;
241
   
242
   ORBDDR |= ORBMASK;	//all outputs
243
   
244
	mysreg=SREG;
245
	cli(); //turn off interrupts for now
246

  
247
	//init everything
248

  
249
   for (i = 0; i < ORB_COUNT; ++i) {
250
      ORB_STATUS.orbs[i].num = i;
251
      ORB_STATUS.orbs[i].angle = 1023;	//127 is a pretty stupid start angle, but oh well
252
      ORB_STATUS.orb_angles[i] = 1023;
253
   }
254

  
255
   ORB_STATUS.new_angles = 1;
256
   ORB_STATUS.change_count = 0;
257

  
258
	//init timer3
259
	TCCR3A = 0; 
260
	TCCR3B = _BV(CS31); //prescale = 8
261
	TCCR3C = 0;
262
	ETIMSK |= _BV(OCIE3C); //turn on oc3c interrupt
263
	OCR3C = TCNT3+ORB_RESET;
264

  
265
	SREG=mysreg;
266
}
267

  
268
/**
269
 * Set both orbs to the color specified. orb_init must
270
 * be called before this function may be used.
271
 *
272
 * @param red_led the red component of the color
273
 * @param green_led the green component of the color
274
 * @param blue_led the blue component of the color
275
 *
276
 * @see orb_init
277
 **/
278
void orb_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {
279
	orb1_set(red_led,green_led,blue_led);
280
	orb2_set(red_led,green_led,blue_led);
281

  
282
}
283

  
284
/**
285
 * Set orb1 to the color specified. orb_init must
286
 * be called before this function may be used.
287
 *
288
 * @param red_led the red component of the color
289
 * @param green_led the green component of the color
290
 * @param blue_led the blue component of the color
291
 *
292
 * @see orb_init
293
 **/
294
void orb1_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {
295
	orb_set_angle(0,red_led);
296
	orb_set_angle(1,green_led);
297
	orb_set_angle(2,blue_led);
298
}
299

  
300
/**
301
 * Set orb2 to the color specified. orb_init must
302
 * be called before this function may be used.
303
 *
304
 * @param red_led the red component of the color
305
 * @param green_led the green component of the color
306
 * @param blue_led the blue component of the color
307
 *
308
 * @see orb_init
309
 **/
310
void orb2_set(unsigned char red_led, unsigned char green_led, unsigned char blue_led) {	
311
	orb_set_angle(4,red_led);
312
	orb_set_angle(5,green_led);
313
	orb_set_angle(6,blue_led);
314
}
315

  
316
/**
317
 * Set both orbs to the specified color. This function
318
 * is intended to be used with the predefined
319
 * colors. orb_init must be called before this
320
 * function may be used.
321
 *
322
 * @param col the color to set the orbs to
323
 *
324
 * @see orb_init
325
 **/
326
void orb_set_color(int col)
185
void orb1_set(unsigned char red, unsigned char green, unsigned char blue)
327 186
{
328
 int red, green, blue;
329

  
330
 red = ((col & 0xE0) >> 5) * 36;
331
 green = ((col & 0x1C) >> 2) * 36;
332
 blue = (col & 0x03) * 85;
333

  
334
 orb_set(red, green, blue);
187
	orb_set_angle(0,red);
188
	orb_set_angle(1,green);
189
	orb_set_angle(2,blue);
335 190
}
336 191

  
337
/**
338
 * Set orb1 to the specified color. This function
339
 * is intended to be used with the predefined
340
 * colors. orb_init must be called before this
341
 * function may be used.
342
 *
343
 * @param col the color to set the orbs to
344
 *
345
 * @see orb_init
346
 **/
347
void orb1_set_color(int col)
192
void orb2_set(unsigned char red, unsigned char green, unsigned char blue)
348 193
{
349
 int red, green, blue;
350

  
351
 red = ((col & 0xE0) >> 5) * 36;
352
 green = ((col & 0x1C) >> 2) * 36;
353
 blue = (col & 0x03) * 85;
354

  
355
 orb1_set(red, green, blue);
194
	orb_set_angle(3,red);
195
	orb_set_angle(4,green);
196
	orb_set_angle(5,blue);
356 197
}
357 198

  
358
/**
359
 * Set orb2 to the specified color. This function
360
 * is intended to be used with the predefined
361
 * colors. orb_init must be called before this
362
 * function may be used.
363
 *
364
 * @param col the color to set the orbs to
365
 *
366
 * @see orb_init
367
 **/
368
void orb2_set_color(int col)
369
{
370
 int red, green, blue;
371 199

  
372
 red = ((col & 0xE0) >> 5) * 36;
373
 green = ((col & 0x1C) >> 2) * 36;
374
 blue = (col & 0x03) * 85;
375

  
376
 orb2_set(red, green, blue);
377
}
378

  
379
//DOES THIS WORK?
380
// Disables the timer1 interrupt, disabling the Orb's color fading capabilities
381
// You can still turn the red, green, and blue leds on and off with set_orb_dio
382
/* If we use the PWM for anything else besides the ORB, this implementation needs to be done better */
383
/**
384
 * Disables the orb color fading capabilities
385
 * by disabling the timer1 interrupt.
386
 *
387
 * @see orb_init
388
 **/
389
void orb_disable()
390
{
391
	TCCR3B &= 0;  	//Turn off everything
392
	ORB_PORT |= _BV(ORB1_RED);
393
	ORB_PORT |= _BV(ORB1_GREEN);
394
	ORB_PORT |= _BV(ORB1_BLUE);
395
	ORB_PORT |= _BV(ORB2_RED);
396
	ORB_PORT |= _BV(ORB2_GREEN);
397
	ORB_PORT |= _BV(ORB2_BLUE);
398
}
399

  
400
//DOES THIS WORK?
401
// Enables the timer1 interrupt, enabling the Orb's color fading capabilities
402
/**
403
 * Enables the orb's color fading capabilities.
404
 *
405
 * @see orb_init
406
 **/
407
void orb_enable()
408
{
409
//	TCCR0 |= _BV(COM01) | _BV(COM00)  | _BV(WGM00) | _BV(CS01);	//Toggle OC Pin on match, FAST PWM Mode, clock/8
410
	TCCR3B =_BV(CS31);
411
}
412

  
413
/** @} **/ //end group
414

  
200
/*
201
	PORTC = 0bFF; //turns on all lights
202
	PORTC &= ~0x08; //turns off light in 4th bit (enc_cs)
203
*/

Also available in: Unified diff