Project

General

Profile

Revision 277

more cleanup

View differences:

lights.c
42 42

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

  
47 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.
48
  Modified sort_buffer() to prune for repeats.  PWM now uses orb_buf_size for the number of orb values in
49
  orb_time_arr[].
50
  Changed sorting algorithm used in sort_buffer() to selection sort (faster). And it works now.
50 51

  
51 52
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

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

  
58 58
#include "lights.h"
......
79 79
#define ORB2_BLUE       0x06
80 80

  
81 81

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

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

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

  
96 96
// the status of an orb
97 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

  
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;
105 104
} ORB_STATUS;
106 105

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

  
110 109
SIGNAL (SIG_OUTPUT_COMPARE3C){
110
  //pull the correct ones down
111
  ORBPORT &= (~ORBMASK)|(ORB_STATUS.changes[ORB_STATUS.current_orb].port_val);
111 112

  
112
		//pull the correct ones down
113
      ORBPORT &= (~ORBMASK)|(ORB_STATUS.changes[ORB_STATUS.current_orb].port_val);
113
  ++ORB_STATUS.current_orb; //now look at next orb transition
114 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

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

  
129

  
130 123
//sets a channel to a value
131 124
void orb_set_angle(int orb, int angle) {
132
	uint8_t mysreg;
125
  uint8_t mysreg;
133 126

  
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
   }
127
  orb=orb&0x07; //only have 8
128
  angle=angle&0xff; //only accept 0-255
129
  angle=255-angle; //inverse intensity
130
  angle=angle<<2; //scale up so that we dont run it too often
131
  angle+=3; //0 values dont really work
132

  
133
  if (ORB_STATUS.orb_angles[orb] != angle) { //if the angle has changed
134
    mysreg=SREG;
135
    cli(); //disable interrupts
136
    ORB_STATUS.orb_angles[orb] = angle; //update angle
137
    ORB_STATUS.new_angles = 1;
138
    SREG=mysreg; //put interrupt status back
139
  }
146 140
}
147 141

  
148

  
149 142
void orb_sort(void) {
150
   int done = 0, i;
143
  int done = 0, i;
151 144

  
152
   while (! done) {
153
      done = 1;
145
  while (! done) {
146
    done = 1;
154 147

  
155
      for (i = 0; i < ORB_COUNT - 1; ++i) {  //loop through all
148
    for (i = 0; i < ORB_COUNT - 1; ++i) {  //loop through all
149
      //if they are out of order, swap them
150
      if (ORB_STATUS.orbs[i].angle > ORB_STATUS.orbs[i+1].angle) {
151
        ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
152
        ORB_STATUS.orbs[i+1].angle ^= ORB_STATUS.orbs[i].angle;
153
        ORB_STATUS.orbs[i].angle ^= ORB_STATUS.orbs[i+1].angle;
156 154

  
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;
155
        ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
156
        ORB_STATUS.orbs[i+1].num ^= ORB_STATUS.orbs[i].num;
157
        ORB_STATUS.orbs[i].num ^= ORB_STATUS.orbs[i+1].num;
162 158

  
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
         }
159
        done = 0;
169 160
      }
170
   }
161
    }
162
  }
171 163
}
172 164

  
173 165
//calculate the split times
174 166
void orb_setup_pulse(void) {
175
   int i;
176
   uint16_t my_port;
177
   uint16_t sum = 0;
178
   uint16_t split_time;
167
  int i;
168
  uint16_t my_port;
169
  uint16_t sum = 0;
170
  uint16_t split_time;
179 171

  
180
   my_port = 0xff; //all on
172
  my_port = 0xff; //all on
181 173

  
182
   if (ORB_STATUS.new_angles) {
174
  if (ORB_STATUS.new_angles) {
175
    ORB_STATUS.change_count = 0;
183 176

  
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
      }
177
    for (i = 0; i < ORB_COUNT; ++i) { //get the new values
178
      ORB_STATUS.orbs[i].angle = ORB_STATUS.orb_angles[ORB_STATUS.orbs[i].num];
179
    }
188 180

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

  
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);
184
    for (i = 0; i < ORB_COUNT; ++i) { //calculate split times
185
      split_time = ORB_STATUS.orbs[i].angle - sum;
186
      my_port &= ~_BV(ORB_STATUS.orbs[i].num);
195 187

  
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;
188
      for (; i < ORB_COUNT - 1 && ORB_STATUS.orbs[i].angle == ORB_STATUS.orbs[i+1].angle; ++i) {
189
        my_port &= ~_BV(ORB_STATUS.orbs[i+1].num); //look for doups
206 190
      }
207 191

  
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
192
      ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port; //which pins are low
193
      ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = split_time;
210 194

  
211 195
      ++ORB_STATUS.change_count;
212 196

  
213
   }
197
      sum += split_time;
198
    }
214 199

  
200
    ORB_STATUS.changes[ORB_STATUS.change_count].port_val = my_port;
201
    ORB_STATUS.changes[ORB_STATUS.change_count].split_time_period = ORB_RESET - sum; //get a constant period
215 202

  
203
    ++ORB_STATUS.change_count;
204
  }
216 205

  
217
   ORB_STATUS.current_orb = 0;
206
  ORB_STATUS.current_orb = 0;
218 207

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

  
208
  ORBPORT |= ORBMASK; //start with all high
209
  OCR3C = TCNT3 + ORB_STATUS.changes[0].split_time_period; //wait for first split
222 210
}
223 211

  
224 212
/**
......
236 224
 **/
237 225
void orb_init()
238 226
{
239
   int i;
240
   uint8_t mysreg;
227
  int i;
228
  uint8_t mysreg;
241 229

  
242
   ORBDDR |= ORBMASK;	//all outputs
230
  ORBDDR |= ORBMASK; //all outputs
243 231

  
244
	mysreg=SREG;
245
	cli(); //turn off interrupts for now
232
  mysreg=SREG;
233
  cli(); //turn off interrupts for now
246 234

  
247
	//init everything
235
  //init everything
248 236

  
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
   }
237
  for (i = 0; i < ORB_COUNT; ++i) {
238
    ORB_STATUS.orbs[i].num = i;
239
    ORB_STATUS.orbs[i].angle = 1023;  //127 is a pretty stupid start angle, but oh well
240
    ORB_STATUS.orb_angles[i] = 1023;
241
  }
254 242

  
255
   ORB_STATUS.new_angles = 1;
256
   ORB_STATUS.change_count = 0;
243
  ORB_STATUS.new_angles = 1;
244
  ORB_STATUS.change_count = 0;
257 245

  
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;
246
  //init timer3
247
  TCCR3A = 0;
248
  TCCR3B = _BV(CS31); //prescale = 8
249
  TCCR3C = 0;
250
  ETIMSK |= _BV(OCIE3C); //turn on oc3c interrupt
251
  OCR3C = TCNT3+ORB_RESET;
264 252

  
265
	SREG=mysreg;
253
  SREG=mysreg;
266 254
}
267 255

  
268 256
/**
......
276 264
 * @see orb_init
277 265
 **/
278 266
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

  
267
  orb1_set(red_led,green_led,blue_led);
268
  orb2_set(red_led,green_led,blue_led);
282 269
}
283 270

  
284 271
/**
......
292 279
 * @see orb_init
293 280
 **/
294 281
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);
282
  orb_set_angle(0,red_led);
283
  orb_set_angle(1,green_led);
284
  orb_set_angle(2,blue_led);
298 285
}
299 286

  
300 287
/**
......
308 295
 * @see orb_init
309 296
 **/
310 297
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);
298
  orb_set_angle(4,red_led);
299
  orb_set_angle(5,green_led);
300
  orb_set_angle(6,blue_led);
314 301
}
315 302

  
316 303
/**
......
325 312
 **/
326 313
void orb_set_color(int col)
327 314
{
328
 int red, green, blue;
315
  int red, green, blue;
329 316

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

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

  
337 324
/**
......
346 333
 **/
347 334
void orb1_set_color(int col)
348 335
{
349
 int red, green, blue;
336
  int red, green, blue;
350 337

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

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

  
358 345
/**
......
367 354
 **/
368 355
void orb2_set_color(int col)
369 356
{
370
 int red, green, blue;
357
  int red, green, blue;
371 358

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

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

  
379 366
//DOES THIS WORK?
......
388 375
 **/
389 376
void orb_disable()
390 377
{
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);
378
  TCCR3B &= 0;    //Turn off everything
379
  ORB_PORT |= _BV(ORB1_RED);
380
  ORB_PORT |= _BV(ORB1_GREEN);
381
  ORB_PORT |= _BV(ORB1_BLUE);
382
  ORB_PORT |= _BV(ORB2_RED);
383
  ORB_PORT |= _BV(ORB2_GREEN);
384
  ORB_PORT |= _BV(ORB2_BLUE);
398 385
}
399 386

  
400 387
//DOES THIS WORK?
......
406 393
 **/
407 394
void orb_enable()
408 395
{
409
//	TCCR0 |= _BV(COM01) | _BV(COM00)  | _BV(WGM00) | _BV(CS01);	//Toggle OC Pin on match, FAST PWM Mode, clock/8
410
	TCCR3B =_BV(CS31);
396
//  TCCR0 |= _BV(COM01) | _BV(COM00)  | _BV(WGM00) | _BV(CS01); //Toggle OC Pin on match, FAST PWM Mode, clock/8
397
  TCCR3B =_BV(CS31);
411 398
}
412 399

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

  

Also available in: Unified diff