Project

General

Profile

Revision 1131

Cleaned up lights.h
Implemented predefined color setting
Implemented binary/PWM mode switching

View differences:

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