Click here to Skip to main content
15,897,273 members
Articles / Internet of Things / Arduino

Simulating and controlling GE Color Effects Lights with Arduino

Rate me:
Please Sign up or sign in to vote.
4.80/5 (13 votes)
27 Nov 2012CPOL13 min read 138.4K   1.4K   25  
Simulating and Controlling GE Color Effects Lights with Arduino
// Errors are 9.x

#include "global.h"
#include "Processor.h"

extern short cycleinterval; // access a variable declared in GEColorEffects.cpp

void Processor::ParallelDisplay()
{
	#ifdef PARALLELDISPLAY
		#ifdef FASTPARALLELDISPLAY
			// this routine is faster because it displays in parallel changed bulbs from multiple strings even if they are not at the same address
			// only downside is its extra complexity may make it slightly slower when every bulb has changed

			byte currentbulb[MAXSTRINGS]; // counter of which bulb we are up to on each string
			Bulb* bulbs[MAXSTRINGS]; // allocate memory for our bulbs
			bool done = false; // flag to indicate we are done with all strings

			// initialise the counters to the bulb count
			for (byte j = 0; j < MAXSTRINGS; j++)
			{
				currentbulb[j] = _strings[j]->BulbCount() -1;
			}

			// while we still have bulbs to check
			while(!done)
			{
				done = true; // assume we are done

				// check each string
				for (byte j = 0; j < MAXSTRINGS; j++)
				{
					// assume there will be no bulb
					bulbs[j] = NULL;

					// loop back through the bulbs looking for the next changed bulb
					while (currentbulb[j] != 255 && _strings[j]->GetBulb(currentbulb[j]) != NULL && !_strings[j]->GetBulb(currentbulb[j])->IsChanged())
					{
						(currentbulb[j])--;
					}

					// if we have a bulb
					if (_strings[j]->GetBulb(currentbulb[j]) != NULL)
					{
						// add it to our bulbs to display
						bulbs[j] = _strings[j]->GetBulb(currentbulb[j]);

						// we are obviously not done
						done = false;
					}
				}

				// now we have the bulbs to display ... display them
				Bulb::DisplayParallel(bulbs);
			}
		#else
			// now display each of the bulbs
			for (byte i = 0; i <= _maxbulbs; i++)
			{
				// get the bulbs to display in parallel
				Bulb* bulbs[MAXSTRINGS];
				for (byte j = 0; j < MAXSTRINGS; j++)
				{
					bulbs[j] = _strings[j]->GetBulb(i);
				}

				// display them
				Bulb::DisplayParallel(bulbs);
			}
		#endif
	#endif
}

// set all the bulbs on all the strings to the nominated colour
void Processor::SetAllColour(short colour)
{
	// do it for each string
	for (byte i = 0; i < MAXSTRINGS; i++)
	{
		// if there is a program there
		if (_strings[i]->IsValid())
		{
			// execute a step
			_strings[i]->SetAllColour(colour);
		}
	}

	#ifdef PARALLELDISPLAY
		ParallelDisplay();
	#endif
}

// Run the program
void Processor::Run()
{
	#if defined(PC) || defined(RASPBERRY)
		int cycle = 0;
	#endif

	byte exec = 0;

	// forever
	while(true)
	{
		#if defined(PC) || defined(RASPBERRY)
			cycle++;
			#ifdef INCLUDE_MSG_DETAIL
				#ifdef MINMEMORY
					_platform->WriteMessage("9.1");
				#else
					_platform->WriteMessage("Cycle %d\n", cycle);
				#endif
			#endif
		#endif

		// flash the 13 pin
		_platform->WritePin(PROGRESSPIN, exec);
		_platform->SendToEmulator(PROGRESSPIN, exec);
		exec++;
		if (exec > 1)
		{
			exec = 0;
		}

		// go through all the strings
		for (byte i = 0; i < MAXSTRINGS; i++)
		{
			#ifdef INCLUDE_PARAM_CHECK
				if (_strings[i] == NULL)
				{
					_platform->Error(9);
				}
			#endif

			// if there is a program there
			if (_strings[i]->IsValid())
			{
				// if there are no instructions in the queue to execute or at least all the donothings are done
				if (_strings[i]->Executing()->IsEmpty() || _strings[i]->AllDone())
				{
					// load some instructions
					_strings[i]->LoadInstructions();
				}
			}
		}

		#ifdef INCLUDE_MSG_DETAIL
			_platform->WriteMessage("\n");
		#endif

		// go through all the strings to calculate the new light states
		for (byte i = 0; i < MAXSTRINGS; i++)
		{
			// if there is a program there
			if (_strings[i]->IsValid())
			{
				// execute a step
				_strings[i]->Execute();
			}
		}

		#ifdef PARALLELDISPLAY
			ParallelDisplay();
		#endif

		#ifdef INCLUDE_MSG_DETAIL
			#ifdef MINMEMORY
				_platform->WriteMessage("9.2");
			#else
				// debug progress statements
				_platform->WriteMessage("End of cycle.\n");
				_platform->WriteMessage("Sleeping for %d\n", cycleinterval);
			#endif
		#endif

		// sleep for our cycle interval
		#if defined(PC) || defined(RASPBERRY)
			if (_break)
			{
				#ifdef PC
					MessageBox(NULL, L"Debug Break", L"Debug Break", MB_OK);
				#elif defined(RASPBERRY)
					printf("Debug Break ... press enter to continue\n");
					int i = 0;
					scanf("%d", &i);
				#endif
				_break = false;
			}
			else
			{
				_platform->Delay(cycleinterval);
			}
		#else
			_platform->Delay(cycleinterval);
		#endif
	}
}

// Dont need this as the processor is never destroyed
//Processor::~Processor()
//{
//	for (short i = 0; i < MAXSTRINGS; i++)
//	{
//		delete _string[i];
//	}
//}

// add a string of lights with a program
#if defined(PC) || defined(RASPBERRY)
	void Processor::AddString(const byte pin, short* program, byte stringlen, short* subroutinestable)
#else
	void Processor::AddString(const byte pin, prog_int16_t* program, prog_int8_t* stringlen, prog_int16_t* subroutinestable)
#endif
	{
		#ifdef INCLUDE_PARAM_CHECK
			if (_strings[pin] == NULL)
			{
				_platform->Error(9);
			}
		#endif

		// keep track of the longest string of bulbs be have seen
		#if defined(PC) || defined(RASPBERRY)
			if (stringlen > _maxbulbs)
			{
				_maxbulbs = stringlen;
			}
		#else
			if (pgm_read_byte_near(stringlen) > _maxbulbs)
			{
				_maxbulbs = pgm_read_byte_near(stringlen);
			}
		#endif

		// create the lights string
		_strings[pin]->Construct(pin, program, stringlen, subroutinestable);
	}

// Create a processor
void Processor::Construct()
{
#ifdef PC
	_break = false;
#endif

	_maxbulbs = 0;

	// create the strings but set them to invalid
	for (byte i = 0; i < MAXSTRINGS; i++)
	{
		#if defined(PC) || defined(RASPBERRY)
			_strings[i] = new LightsString(this);
		#else
			_strings[i] = new LightsString();
		#endif

		#ifdef INCLUDE_PARAM_CHECK
		if (_strings[i] == NULL)
		{
			_platform->Error(9);
		}
		#endif

		_strings[i]->SetInvalid();
	}
}

#ifdef INCLUDE_DEBUG_PATTERNS
		void Processor::SetStringBulb(byte string, byte bulb, short colour, short brightness)
		{
			if (_strings[string] != NULL)
			{
				if (_strings[string]->GetBulb(bulb) != NULL)
				{
					_strings[string]->GetBulb(bulb)->SetColour(colour);
					_strings[string]->GetBulb(bulb)->SetBrightness(brightness);
					_strings[string]->GetBulb(bulb)->Display();
				}
			}
		}
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions