Revision 1131
Cleaned up lights.h
Implemented predefined color setting
Implemented binary/PWM mode switching
lights.c | ||
---|---|---|
74 | 74 |
TODO: |
75 | 75 |
- Find out the interrupt time |
76 | 76 |
- Optimize the OC interrupt |
77 |
- enable_orb_pwm use everywhere, add methods to switch on/off, add init |
|
78 |
function |
|
79 | 77 |
- test old code: continuously setting the orbs |
80 | 78 |
- fix sync/volatile |
79 |
- make functions static |
|
81 | 80 |
*/ |
82 | 81 |
|
83 | 82 |
/* |
... | ... | |
160 | 159 |
#define orb2_blue_mask _BV (ORB2_BLUE ) |
161 | 160 |
|
162 | 161 |
// Mask for all LEDs |
163 |
const uint8_t all_orbs_mask=
|
|
164 |
orb1_red_mask | orb1_green_mask | orb1_blue_mask | |
|
162 |
#define all_orbs_mask \
|
|
163 |
orb1_red_mask | orb1_green_mask | orb1_blue_mask | \
|
|
165 | 164 |
orb2_red_mask | orb2_green_mask | orb2_blue_mask; |
166 | 165 |
|
167 | 166 |
// Mask for the individual LEDs, organized as an array for programmatic access. |
... | ... | |
318 | 317 |
struct pwm_channel_t *a, *b; |
319 | 318 |
|
320 | 319 |
// The actual sorting |
321 |
|
|
322 | 320 |
a=first; b=a+1; done=true; |
323 | 321 |
bubble next bubble next bubble next bubble next bubble |
324 | 322 |
if (done) return; |
... | ... | |
413 | 411 |
else |
414 | 412 |
{ |
415 | 413 |
// Binary mode. |
416 |
// Don't do anything, the orbs pins are set in orb_n_set. |
|
417 |
// It would be more consistent to set them here (because you could |
|
418 |
// update them independently and then apply the changes at once), but it |
|
419 |
// is faster this way, and being fast is the whole point of using the |
|
420 |
// binary orb mode anyway. |
|
414 |
// The outputs are inverted. |
|
415 |
uint8_t on=0; |
|
416 |
|
|
417 |
if (orb_values[0][0]) on |= orb_mask[0][0]; |
|
418 |
if (orb_values[0][1]) on |= orb_mask[0][1]; |
|
419 |
if (orb_values[0][2]) on |= orb_mask[0][2]; |
|
420 |
if (orb_values[1][0]) on |= orb_mask[1][0]; |
|
421 |
if (orb_values[1][1]) on |= orb_mask[1][1]; |
|
422 |
if (orb_values[1][2]) on |= orb_mask[1][2]; |
|
423 |
|
|
424 |
ORBPORT |= all_orbs_mask; // All orbs off |
|
425 |
ORBPORT &= ~on; // Selected orbs on |
|
421 | 426 |
} |
422 | 427 |
} |
423 | 428 |
|
424 |
// TODO: make a public version of this one, but keep a private one which does |
|
425 |
// not sort them so you can update both sides and update only once. |
|
426 |
|
|
427 |
static void orb_n_set (uint8_t num, uint8_t red, uint8_t green, uint8_t blue) |
|
429 |
static void set_orb_values (uint8_t num, uint8_t red, uint8_t green, uint8_t blue) |
|
428 | 430 |
{ |
429 |
if (enable_orb_pwm) |
|
430 |
{ |
|
431 |
// PWM mode |
|
432 |
orb_values[num][0]=red; |
|
433 |
orb_values[num][1]=green; |
|
434 |
orb_values[num][2]=blue; |
|
435 |
} |
|
436 |
else |
|
437 |
{ |
|
438 |
// Binary mode |
|
439 |
// The outputs are inverted. |
|
440 |
if (!red) ORBPORT|=orb_mask[num][0]; else ORBPORT&=~orb_mask[num][0]; |
|
441 |
if (!green) ORBPORT|=orb_mask[num][1]; else ORBPORT&=~orb_mask[num][1]; |
|
442 |
if (!blue) ORBPORT|=orb_mask[num][2]; else ORBPORT&=~orb_mask[num][2]; |
|
443 |
} |
|
431 |
// PWM mode |
|
432 |
orb_values[num][0]=red; |
|
433 |
orb_values[num][1]=green; |
|
434 |
orb_values[num][2]=blue; |
|
444 | 435 |
} |
445 | 436 |
|
446 |
// ************************************ |
|
447 |
// ** Frontend orb setting functions ** |
|
448 |
// ************************************ |
|
449 | 437 |
|
450 |
// All of these functions use orb_n_set to set the actual values, and then call |
|
451 |
// apply_orbs() to apply the changes. orb_n_set should be used (although it |
|
452 |
// would be faster to set the array directly) because the binary/pwm mode has |
|
453 |
// to be handled. |
|
438 |
// *********************** |
|
439 |
// ** RGB color setting ** |
|
440 |
// *********************** |
|
454 | 441 |
|
442 |
// All of these functions use set_orb_values to set the actual values, and then call apply_orbs() to apply the changes. |
|
443 |
// set_orb_values should be used (even though it would be faster to set the array directly) because the binary/pwm mode |
|
444 |
// has to be handled. |
|
445 |
|
|
455 | 446 |
/** |
447 |
* @param num the number of the orb to set (0 or 1) |
|
448 |
*/ |
|
449 |
void orb_n_set (uint8_t num, uint8_t red, uint8_t green, uint8_t blue) |
|
450 |
{ |
|
451 |
set_orb_values (num, red, green, blue); |
|
452 |
apply_orbs (); |
|
453 |
} |
|
454 |
|
|
455 |
/** |
|
456 | 456 |
* Set orb1 to the color specified. orb_init must be called before this function |
457 | 457 |
* may be used. |
458 | 458 |
* |
... | ... | |
464 | 464 |
**/ |
465 | 465 |
void orb1_set (uint8_t red, uint8_t green, uint8_t blue) |
466 | 466 |
{ |
467 |
orb_n_set (0, red, green, blue);
|
|
467 |
set_orb_values (0, red, green, blue);
|
|
468 | 468 |
apply_orbs (); |
469 | 469 |
} |
470 | 470 |
|
... | ... | |
480 | 480 |
**/ |
481 | 481 |
void orb2_set (uint8_t red, uint8_t green, uint8_t blue) |
482 | 482 |
{ |
483 |
orb_n_set (1, red, green, blue);
|
|
483 |
set_orb_values (1, red, green, blue);
|
|
484 | 484 |
apply_orbs (); |
485 | 485 |
} |
486 | 486 |
|
... | ... | |
496 | 496 |
**/ |
497 | 497 |
void orb_set (uint8_t red, uint8_t green, uint8_t blue) |
498 | 498 |
{ |
499 |
orb_n_set (0, red, green, blue);
|
|
500 |
orb_n_set (1, red, green, blue);
|
|
499 |
set_orb_values (0, red, green, blue);
|
|
500 |
set_orb_values (1, red, green, blue);
|
|
501 | 501 |
apply_orbs (); |
502 | 502 |
} |
503 | 503 |
|
... | ... | |
505 | 505 |
uint8_t red1, uint8_t green1, uint8_t blue1, |
506 | 506 |
uint8_t red2, uint8_t green2, uint8_t blue2) |
507 | 507 |
{ |
508 |
orb_n_set (0, red1, green1, blue1);
|
|
509 |
orb_n_set (1, red2, green2, blue2);
|
|
508 |
set_orb_values (0, red1, green1, blue1);
|
|
509 |
set_orb_values (1, red2, green2, blue2);
|
|
510 | 510 |
apply_orbs (); |
511 | 511 |
} |
512 | 512 |
|
513 | 513 |
|
514 |
// ****************************** |
|
515 |
// ** Predefined color setting ** |
|
516 |
// ****************************** |
|
514 | 517 |
|
518 |
// Macros for extracting a color. |
|
519 |
#define C_RED(col) (((col & 0xE0) >> 5) * 36) |
|
520 |
#define C_GREEN(col) (((col & 0x1C) >> 2) * 36) |
|
521 |
#define C_BLUE(col) (((col & 0x03) ) * 85) |
|
515 | 522 |
|
516 | 523 |
/** |
517 |
* Set both orbs to the specified color. This function |
|
518 |
* is intended to be used with the predefined |
|
519 |
* colors. orb_init must be called before this |
|
520 |
* function may be used. |
|
524 |
* Set both orbs to the specified color. This function is intended to be used with the predefined colors. |
|
521 | 525 |
* |
522 | 526 |
* @param col the color to set the orbs to |
523 |
* |
|
524 |
* @see orb_init |
|
525 | 527 |
**/ |
526 | 528 |
void orb_set_color(uint8_t col) |
527 | 529 |
{ |
528 |
// uint16_t red, green, blue; |
|
529 |
// |
|
530 |
// red = ((col & 0xE0) >> 5) * 36; |
|
531 |
// green = ((col & 0x1C) >> 2) * 36; |
|
532 |
// blue = (col & 0x03) * 85; |
|
533 |
// |
|
534 |
// orb_set(red, green, blue); |
|
530 |
orb_set (C_RED(col), C_GREEN(col), C_BLUE(col)); |
|
535 | 531 |
} |
536 | 532 |
|
537 | 533 |
/** |
538 |
* Set orb1 to the specified color. This function |
|
539 |
* is intended to be used with the predefined |
|
540 |
* colors. orb_init must be called before this |
|
541 |
* function may be used. |
|
534 |
* Set orb1 to the specified color. This function is intended to be used with the predefined colors. |
|
542 | 535 |
* |
543 | 536 |
* @param col the color to set the orbs to |
544 |
* |
|
545 |
* @see orb_init |
|
546 | 537 |
**/ |
547 |
void orb1_set_color(uint8_t col)
|
|
538 |
void orb1_set_color(uint8_t col) |
|
548 | 539 |
{ |
549 |
// uint16_t red, green, blue; |
|
550 |
// |
|
551 |
// red = ((col & 0xE0) >> 5) * 36; |
|
552 |
// green = ((col & 0x1C) >> 2) * 36; |
|
553 |
// blue = (col & 0x03) * 85; |
|
554 |
// |
|
555 |
// orb1_set(red, green, blue); |
|
540 |
orb1_set (C_RED(col), C_GREEN(col), C_BLUE(col)); |
|
556 | 541 |
} |
557 | 542 |
|
558 | 543 |
/** |
559 |
* Set orb2 to the specified color. This function |
|
560 |
* is intended to be used with the predefined |
|
561 |
* colors. orb_init must be called before this |
|
562 |
* function may be used. |
|
544 |
* Set orb2 to the specified color. This function is intended to be used with the predefined colors. |
|
563 | 545 |
* |
564 | 546 |
* @param col the color to set the orbs to |
565 |
* |
|
566 |
* @see orb_init |
|
567 | 547 |
**/ |
568 |
void orb2_set_color(uint8_t col)
|
|
548 |
void orb2_set_color(uint8_t col) |
|
569 | 549 |
{ |
570 |
// uint16_t red, green, blue; |
|
571 |
// |
|
572 |
// red = ((col & 0xE0) >> 5) * 36; |
|
573 |
// green = ((col & 0x1C) >> 2) * 36; |
|
574 |
// blue = (col & 0x03) * 85; |
|
575 |
// |
|
576 |
// orb2_set(red, green, blue); |
|
550 |
orb2_set(C_RED(col), C_GREEN(col), C_BLUE(col)); |
|
577 | 551 |
} |
578 | 552 |
|
579 |
//DOES THIS WORK? |
|
580 |
// Disables the timer1 interrupt, disabling the Orb's color fading capabilities |
|
581 |
// You can still turn the red, green, and blue leds on and off with set_orb_dio |
|
582 |
/* If we use the PWM for anything else besides the ORB, this implementation needs to be done better */ |
|
583 | 553 |
/** |
584 |
* Disables the orb color fading capabilities |
|
585 |
* by disabling the timer1 interrupt. |
|
554 |
* Set the specified orb to the specified color. This function is intended to be used with the predefined colors. |
|
586 | 555 |
* |
587 |
* @see orb_init |
|
556 |
* @param num the number of the orb to set (0 or 1) |
|
557 |
* @param col the color to set the orbs to |
|
588 | 558 |
**/ |
589 |
void orb_disable()
|
|
559 |
void orb_n_set_color(uint8_t num, uint8_t col)
|
|
590 | 560 |
{ |
591 |
// TCCR3B &= 0; //Turn off everything |
|
592 |
// ORB_PORT |= _BV(ORB1_RED); |
|
593 |
// ORB_PORT |= _BV(ORB1_GREEN); |
|
594 |
// ORB_PORT |= _BV(ORB1_BLUE); |
|
595 |
// ORB_PORT |= _BV(ORB2_RED); |
|
596 |
// ORB_PORT |= _BV(ORB2_GREEN); |
|
597 |
// ORB_PORT |= _BV(ORB2_BLUE); |
|
561 |
orb_n_set(num, C_RED(col), C_GREEN(col), C_BLUE(col)); |
|
598 | 562 |
} |
599 | 563 |
|
600 |
//DOES THIS WORK? |
|
601 |
// Enables the timer1 interrupt, enabling the Orb's color fading capabilities |
|
602 | 564 |
/** |
603 |
* Enables the orb's color fading capabilities.
|
|
565 |
* Set the orbs to the respecitve color. This function is intended to be used with the predefined colors.
|
|
604 | 566 |
* |
605 |
* @see orb_init |
|
567 |
* @param col1 the color to set orb 1 to |
|
568 |
* @param col2 the color to set orb 2 to |
|
606 | 569 |
**/ |
607 |
void orb_enable()
|
|
570 |
void orbs_set_color(uint8_t col1, uint8_t col2)
|
|
608 | 571 |
{ |
609 |
//// TCCR0 |= _BV(COM01) | _BV(COM00) | _BV(WGM00) | _BV(CS01); //Toggle OC Pin on match, FAST PWM Mode, clock/8 |
|
610 |
// TCCR3B =_BV(CS31); |
|
572 |
orbs_set (C_RED(col1), C_GREEN(col1), C_BLUE(col1), C_RED(col2), C_GREEN(col2), C_BLUE(col2)); |
|
611 | 573 |
} |
612 | 574 |
|
613 |
/** @} **/ //end group |
|
575 |
#undef C_BLUE |
|
576 |
#undef C_GREEN |
|
577 |
#undef C_RED2 |
|
614 | 578 |
|
615 | 579 |
|
616 |
// ********************
|
|
617 |
// ** Initialization **
|
|
618 |
// ********************
|
|
580 |
// ****************** |
|
581 |
// ** Mode setting **
|
|
582 |
// ****************** |
|
619 | 583 |
|
620 |
void orb_disable_timer (void) |
|
621 |
{ |
|
622 |
TIMSK&=~( _BV(OCIE0) | _BV(TOIE0)); |
|
623 |
} |
|
624 |
|
|
625 |
|
|
626 | 584 |
void orb_enable_timer (void) |
627 | 585 |
{ |
628 |
TIMSK|= _BV(OCIE0) | _BV(TOIE0); |
|
629 |
} |
|
630 |
|
|
631 |
/** |
|
632 |
* Initializes the PWM for Orb control. This must be called before |
|
633 |
* the orbs are used for them to function. |
|
634 |
**/ |
|
635 |
void orb_init () |
|
636 |
{ |
|
637 | 586 |
// Use 8 bit TC0. Timer mode: |
638 | 587 |
// We cannot use CTC mode because it can only clear on OCR0 (in contrast |
639 | 588 |
// to the 16 bit timers which can also use the ICR for that) and OCR0 is |
... | ... | |
653 | 602 |
// Using and 8 bit timer has the added advantage that all the comparisons |
654 | 603 |
// are faster. |
655 | 604 |
|
605 |
|
|
606 |
// Normal mode, Compare match output off, Prescaler |
|
607 |
TCCR0=_BV(CS02) | _BV(CS01) | _BV(CS00); // 1024, 30 Hz |
|
608 |
TCCR0=_BV(CS02) | _BV(CS01); // 1024, 30 Hz |
|
609 |
|
|
610 |
TIMSK|= _BV(OCIE0) | _BV(TOIE0); |
|
611 |
} |
|
612 |
|
|
613 |
void orb_disable_timer (void) |
|
614 |
{ |
|
615 |
TIMSK&=~( _BV(OCIE0) | _BV(TOIE0)); |
|
616 |
} |
|
617 |
|
|
618 |
|
|
619 |
void orb_set_mode (orb_mode_t mode) |
|
620 |
{ |
|
621 |
if (mode==orb_mode_binary) |
|
622 |
{ |
|
623 |
enable_orb_pwm=false; |
|
624 |
orb_disable_timer (); |
|
625 |
} |
|
626 |
else // orb_mode_pwm |
|
627 |
{ |
|
628 |
enable_orb_pwm=true; |
|
629 |
orb_enable_timer (); |
|
630 |
} |
|
631 |
|
|
632 |
apply_orbs (); |
|
633 |
} |
|
634 |
|
|
635 |
|
|
636 |
// ******************** |
|
637 |
// ** Initialization ** |
|
638 |
// ******************** |
|
639 |
|
|
640 |
// Orb initialization code common to all modes. |
|
641 |
static void orb_init_common (void) |
|
642 |
{ |
|
656 | 643 |
// Enable the output ports and turn off the LEDs |
657 | 644 |
ORBDDR |= all_orbs_mask; |
658 | 645 |
ORBPORT |= all_orbs_mask; |
659 | 646 |
|
660 | 647 |
// Set all orbs to "off" |
661 | 648 |
orb_set (0, 0, 0); |
649 |
|
|
650 |
// Debug |
|
651 |
DDRF=6; // TODO remove |
|
652 |
} |
|
662 | 653 |
|
663 |
// *** Set up the timer |
|
654 |
/** |
|
655 |
* Initializes the orbs in PWM mode. One of the orb_init* functions must be called before the orbs can be used. |
|
656 |
* |
|
657 |
* @see orb_init_pwm |
|
658 |
**/ |
|
659 |
void orb_init_binary (void) |
|
660 |
{ |
|
661 |
orb_init_common (); |
|
662 |
orb_set_mode (orb_mode_binary); |
|
663 |
} |
|
664 | 664 |
|
665 |
// Normal mode, Compare match output off, Prescaler |
|
666 |
TCCR0=_BV(CS02) | _BV(CS01) | _BV(CS00); // 1024, 30 Hz |
|
667 |
TCCR0=_BV(CS02) | _BV(CS01); // 1024, 30 Hz |
|
665 |
/** |
|
666 |
* Initializes the orbs in PWM mode. One of the orb_init* functions must be called before the orbs can be used. |
|
667 |
* |
|
668 |
* @see orb_init_binary |
|
669 |
**/ |
|
670 |
void orb_init_pwm (void) |
|
671 |
{ |
|
672 |
orb_init_common (); |
|
673 |
orb_set_mode (orb_mode_pwm); |
|
674 |
} |
|
668 | 675 |
|
669 |
// Enable compare match and overflow interrupts |
|
670 |
orb_enable_timer (); |
|
676 |
/** |
|
677 |
* A synonym for orb_init_pwm |
|
678 |
* |
|
679 |
* @see orb_init_pwm |
|
680 |
**/ |
|
681 |
void orb_init () |
|
682 |
{ |
|
683 |
orb_init_pwm (); |
|
684 |
} |
|
671 | 685 |
|
672 |
// Debug |
|
673 |
DDRF=6; |
|
674 | 686 |
|
687 |
|
|
688 |
|
|
689 |
|
|
690 |
|
|
691 |
|
|
692 |
|
|
693 |
// *************** |
|
694 |
// ** Debugging ** |
|
695 |
// *************** |
|
696 |
|
|
697 |
void orb_test (void) |
|
698 |
{ |
|
675 | 699 |
|
676 | 700 |
// The output compare flag (and interrupt) is set at the next timer clock |
677 | 701 |
// cycle after compare match. So time=pwm_value-1 (for pwm_value==0: don't |
... | ... | |
703 | 727 |
// delay_ms (10); |
704 | 728 |
// } |
705 | 729 |
} |
706 |
|
Also available in: Unified diff