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