Close

About adding complexity to simplify the code.

A project log for Dice badge

Put a bit of colorful randomness on your clothes !

pierre-loup-mPierre-Loup M. 02/23/2023 at 08:310 Comments

When I was coding the program for the badge, I started with simple things : led on, or led off. Then I added fade in and out. Then I tought a heartbeat pulsation (fast pulse, then a slower) would be nice. I was fast having the almost same chunk of code in several places, with just the delays changing.

And there was the case where the system is put to sleep. It's nicer if the leds takes their times to fade out before sleeping.

I ended up implementing a queue for all that. That may be a bit overkilled for that, but that simplifies the global handling.

struct wait_t{
	uint16_t delay;
	uint32_t start;
};

struct fade_t{
	int8_t direction;
	volatile uint16_t duration;
	uint8_t limit;
	bool comp;
};

struct sleep_t{
	int16_t delay;
	bool shortSleep;
};

struct state_t{
	state_t *next;
	volatile uint8_t state;
	union{
		fade_t fade;
		wait_t wait;
		sleep_t sleep;
		uint8_t value;
	};
};

 The state_t struct contains three things : the type of operation it represents, the parameters linked to this operation, and a pointer to the next operation. These operations can be of four type :

Each of this action has its own function in the code, which are called by a dispatcher. The Union in the state_t makes it easy to handle several kind of informations within the same structure.

It makes complex blink patterns easier to set. For example the dice throw (mode 1) is as follow :

void throwDice(){
	uint8_t limit = xorshift(4) + 3;
	uint8_t speed = 4;

	for(uint8_t i = 0; i < limit; ++i){
		queueFadeOut(speed);
		queueNumber(xorshift(6) + 1);
		queueFadeIn(speed);
		speed += xorshift(4);
	}
	queueDelay(5000);
	queueFadeOut(FADE_SLOW);
	queueSleep();
}

 It makes the leds blink between 4 and 7 times a random number with fade in and out, then display the last one for 5 seconds, then go to long sleep. Once this function has been called to queue all the steps at once, main loop calls the dispatcher that handles each step when needed.

Discussions