The Rusty Spike

A Railroad Fan's Website

By

Police Lightbar Sim for Launchpad – Rev 3



Last round of modifications to this project for a while. Rev 2 was pretty good, but the memory limitations of the MSP430G2553 chip posed a challenge: 512 bytes of ram! I was only able to get three flashing sequences plus the logic loops into that little memory. So another rework was needed.

Instead of using a byte broken down into 1bit/7bit status/time chunks, for Rev 3 I went with a hardcoded 50ms time chunk constant and used every bit in each byte as a status flag. Example: 00111100 would tell the logic loop that the first two 50ms steps are ‘OFF’, the next 4 steps are ‘ON’ and the last 2 are ‘OFF’. This allows me to compress 8 steps into one byte… an initial 8x memory efficiency increase.

The trade off to this is that counters like ‘CurrentStep’ are now moved out of the flashing sequence. Which, when you think about it, the notion of which step a sequence is on is not necessarily an attribute of the sequence itself, but rather a bookkeeping value by the logic loop. This increases memory usage however, stealing the thunder of my previous 8x decrease in memory use.

The overall effect is still a large reduction in memory use. Rev 3 ups the number of LEDs controlled from 8 to 11 (3 red, 3 blue, 2 yellow, 1 white takedown light, and 2 headlights.) as well as increasing the flashing sequences from 3 to 10 (Technically 15). The LEDs are also now grouped into 3 groups which allows for changing of the flash sequence on one group without interrupting the sequence of the other groups. Rev 2 had a ‘jitter’ problem when the sequences changed. Barely noticable, I think, but the power of my OCD compelled me to fix it.

The final feature enhancement is the concept of ‘Modes’. Currently, there are only two modes installed: Demo and Random. Demo will iterate through each sequence, spending about 8 seconds on each sequence. Random will pick a sequence at random and spend 2-6 seconds on that sequence. (Note: There is some room for improvement on the random chooser)

Anyways, code and how-to are posted below, so for now here’s a video of what Rev 3 can do:

 


CSS Project Stuff

ZIP-ed project available here: PoliceLightbar-Rev3.1.zip

Instructions for importing into CCS are here: http://therustyspike.com/?p=330

Uploading a CCS project to a Launchpad info is here: http://therustyspike.com/?p=354

 


Code

The code contains for basic files, two of which (lp4mrr.h, lp4mrr.c) are the beginnings of a simple LP4MRR library that I am slowly evolving. The other two are the actual Light Bar sim code. There is LOTS of room for improvement in both code functionality and readability. I am sure my OCD will compel me to clean up the code, optimize and properly document… eventually. For now, here’s the hack:

 

lp4mrr.h

/*
 * Launchpad for Model Railroaders (LP4MRR) Library
 * COPYRIGHT 2013 Dave Loman
 *
 * Provided  under a Creative Commons Attribution, Non-Commercial
 * Share-Alike, 3.0 Unported License
 *
 * TARGETED TO MSP430 LANUCHPAD W/MSP430G2553 PROCESSOR
 *
 */
 
#ifndef LP4MRR_H
#define LP4MRR_H
 
typedef char byte;
 
#define OUTPUT 0x00
#define INPUT  0x01
 
#define ON     0x00
#define OFF    0x01
#define TOGGLE 0x02
 
#define PORT01 1
#define PORT02 2
 
void setPinMode(int port, int pin, int mode);
void setP1PinMode(int pin, int mode);
void setP2PinMode(int pin, int mode);
 
void setPinState(int port, int pin, int mode);
void setP1PinState(int pin, int state);
void setP2PinState(int pin, int state);
 
void waitabit(volatile unsigned int cycles);
 
 
#endif //LP4MRR_H

 

lp4mrr.c

/*
 * Launchpad for Model Railroaders (LP4MRR) Library
 * COPYRIGHT 2012 Dave Loman
 *
 * Provided  under a Creative Commons Attribution, Non-Commercial
 * Share-Alike,3.0 Unported License
 *
 * TARGETED TO MSP430 LANUCHPAD W/MSP430G2553 PROCESSOR
 *
 */
 
#include "lp4mrr.h"
#include <msp430.h>
 
void setPinMode(int port, int pin, int mode) {
	if (port == PORT01 )
		setP1PinMode(pin, mode);
	else
		setP2PinMode(pin, mode);
}
void setP1PinMode(int pin, int mode) {
	if (mode == INPUT )
		P1DIR &= ~(0x01 << pin);
	else
		P1DIR |= (0x01 << pin);
}
void setP2PinMode(int pin, int mode) {
	if (mode == INPUT )
		P2DIR &= ~(0x01 << pin);
	else
		P2DIR |= (0x01 << pin);
}
 
 
void setPinState(int port, int pin, int state) {
	if (port == PORT01 )
		setP1PinState(pin, state);
	else
		setP2PinState(pin, state);
}
void setP1PinState(int pin, int state) {
	if (state == OFF )
		P1OUT &= ~(0x01 << pin);
	else if (state == ON )
		P1OUT |= (0x01 << pin);
	else
		P1OUT ^= (0x01 << pin);
}
void setP2PinState(int pin, int state) {
	if (state == OFF )
		P2OUT &= ~(0x01 << pin);
	else if (state == ON )
		P2OUT |= (0x01 << pin);
	else
		P2OUT ^= (0x01 << pin);
}
 
void waitabit(volatile unsigned int cycles) {
	do cycles--;
	while(cycles != 0);
}
 
 
 
int main(void) {
	setup();
 
	for(;;) {
		//TODO: calc elapsed time and pass to loop
		loop();
		waitabit(4000);
	}
 
	return 0;
}

The lp4Mrr library provides basic pin control and implements the main function. The User of the library is responsible for implementation of the setup() and loop() functions.

 

main.c

/*
 * Police Lightbar Flasher v3.1
 * COPYRIGHT 2012 Dave Loman
 *
 * Provided  under a Creative Commons Attribution, Non-Commercial
 * Share-Alike,3.0 Unported License
 *
 * TARGETED TO MSP430 LANUCHPAD W/MSP430G2553 PROCESSOR
 *
 */
 
#include <msp430.h>
#include <stdlib.h>
 
#include "lp4mrr.h"
#include "flashSequences.h"
 
#define NUMBER_OF_LIGHTS 10
 
#define LAMP_CHECK
 
byte curButtonState = 0x00;
byte lastButtonState = 0x00;
 
const byte allSeqsLen = 10;
const Sequence* allSeqs[10] = {
		&patrol,
		&solid_slow,
		&solid_med,
		&solid_fast,
		&strobe_3x,
		&strobe_2x,
		&strobe_1x,
		&strobe_multi,
		&traffic_left,
		&traffic_right
};
 
const byte randomSeqsLen = 5;
const Sequence* randomSeqs[5] = {
		&solid_fast,
		&strobe_3x,
		&strobe_2x,
		&strobe_1x,
		&strobe_multi,
};
 
byte curSeq = 0;
 
byte simulationMode = 0;
short totalTime = 0;
 
void initAllPins() {
	volatile byte i = 0;
	// Setup Pins
	for (i = 0; i < 6; ++i ) {
		setPinMode(redBluePorts[i], redBluePins[i], OUTPUT);
		setPinState(redBluePorts[i], redBluePins[i], OFF);
		redBlueCurStep[i] = 0;
	}
	for (i = 0; i < 2; ++i ) {
		setPinMode(yellowPorts[i], yellowPins[i], OUTPUT);
		setPinState(yellowPorts[i], yellowPins[i], OFF);
		yellowCurStep[i] = 0;
	}
	for (i = 0; i < 2; ++i ) {
		setPinMode(headlightPorts[i], headlightPins[i], OUTPUT);
		setPinState(headlightPorts[i], headlightPins[i], OFF);
		headlightCurStep[i] = 0;
	}
 
	setPinMode(2, 2, OUTPUT);
}
 
void checkForIncrPattern() {
	//Demo Mode
	if (simulationMode == 0) {
		// After preset, constant time, Simply incr mode and range check
		if (totalTime > 8000) {
			totalTime = 0;
			if (++redBlueSeqSelect >= 10){
				redBlueSeqSelect = 0;
				++simulationMode;
			}
			initAllPins();
			//hack
			if (redBlueSeqSelect == 8 || redBlueSeqSelect == 9) {
				setPinState(2, 2, ON);
			} else {
				setPinState(2, 2, OFF);
			}
		}
 
	//random Mode
	} else if ( simulationMode == 1 ) {
		// After random time, set random mode.
		if (totalTime > ((rand() % 4 + 2) * 1000)) {
			totalTime = 0;
			redBlueSeqSelect = (rand() % 5) + 3;
			initAllPins();
		}
	}
}
 
void setup() {
	WDTCTL = WDTPW | WDTHOLD;		// Stop watchdog timer
	initAllPins();
 
#ifdef LAMP_CHECK
	// LAMP CHECK
	volatile byte i = 0;
	for (i = 0; i < 6; ++i )
		setPinState(redBluePorts[i], redBluePins[i], ON);
	for (i = 0; i < 2; ++i )
		setPinState(yellowPorts[i], yellowPins[i], ON);
	for (i = 0; i < 2; ++i )
		setPinState(headlightPorts[i], headlightPins[i], ON);
	setPinState(2, 2, ON);
 
	for (i = 0; i < 200; ++i) waitabit(2 * 1000);
 
	for (i = 0; i < 6; ++i )
		setPinState(redBluePorts[i], redBluePins[i], OFF);
	for (i = 0; i < 2; ++i )
		setPinState(yellowPorts[i], yellowPins[i], OFF);
	for (i = 0; i < 2; ++i )
		setPinState(headlightPorts[i], headlightPins[i], OFF);
	setPinState(2, 2, OFF);
 
	for (i = 0; i < 200; ++i) waitabit(1 * 1000);
#endif
}
 
 
void processLightGrouping(
	const byte *pData,
	const byte dataLen,
	byte *pCurStep,
	const byte *pPorts,
	const byte *pPins
) {
 
	volatile byte portPin = 0;
	volatile byte stepCount = 0;
	volatile byte curByte = 0, curBit = 0;
	volatile byte dataByte = 0;
	volatile byte i = 0;
 
	for (i = 0; i< dataLen; ++i) {
		// get step count from 'header' of subsequence
		stepCount = pData[i++];
 
		// pull current step from currentStepArray
		curBit = *pCurStep; //Copy to local variable
 
		// loop and reduce curStep to bit index and byte index
		while (curBit > 7) {
			curBit -= 8;
			curByte++;
		}
		//curBit is now < 7 and represents the bit
 
		// Get the data byte from data array
		dataByte = pData[i + curByte];
 
		// shift the bit we are interested in all the way to the right.
		dataByte = dataByte >> (7-curBit);
 
		// check to see if the bit is 1 or 0
		setPinState(*pPorts, *pPins, (dataByte & 0x01 == 0x01)?ON:OFF );
 
		// figure out how to get to next light.
		i += (stepCount / 8) - 1;
		if (stepCount % 8 != 0) i++;
 
		// incr Current step, range check
		*pCurStep = *pCurStep + 1;
		if (*pCurStep > stepCount)
			*pCurStep = 0;
 
		//Reset for next pass
		stepCount = 0;
		curByte = 0;
		curBit = 0;
		dataByte = 0;
 
		//Incr pointers
		pCurStep++;
		pPorts++;
		pPins++;
	}
 
	i = 0;
}
 
Sequence *seq = 0x00;
Sequence *newSeq = 0x00;
void loop() {
 
	totalTime += 35;
 
	//Check Modes
	if (simulationMode == 0) { //DEMO
		//Null check (for app start)
		if (seq == 0x00)
			newSeq = (Sequence*)allSeqs[curSeq];
 
		// After preset, constant time, Simply incr mode and range check
		if (totalTime > 8000) {
			//Reset accumulated time
			totalTime = 0;
 
			//incr and range check
			if (++curSeq >= allSeqsLen) {
				curSeq = 0;
				++simulationMode;
			}
 
			//set sequence pointer
			newSeq = (Sequence*)allSeqs[curSeq];
		}
 
	//random Mode
	} else if ( simulationMode == 1 ) {
		//Null check (for app start)
		if (seq == 0x00)
			newSeq = (Sequence*)randomSeqs[curSeq];
 
		// After random time, set random sequence.
		if (totalTime > ((rand() % 4 + 2) * 1000)) {
			totalTime = 0;
			newSeq = (Sequence*)randomSeqs[rand() % randomSeqsLen];
		}
	}
 
	//Check for sequence transition
	if (seq == 0x00) { //Case: App start, pointers arent all set yet
		seq = newSeq;
		initAllPins();
 
	} else if (seq != 0x00 && newSeq != 0x00 && seq != newSeq) { //Case: seq transition
		//Reset redblue pins
		int i = 0;
		for (i = 0; i < 6; ++i )
			redBlueCurStep[i] = 0;
		i = 0;
		seq = newSeq;
	}
 
	// Process the Sequence
 
	//Do redBlue
	processLightGrouping(
		redBlueSequences[seq->redBlueIndex],
		redBlueSequencesLen[seq->redBlueIndex],
		redBlueCurStep,
		redBluePorts,
		redBluePins
	);
 
 
	//Do yellow
	processLightGrouping(
		yellowSequences[seq->yellowIndex],
		yellowSequencesLen[seq->yellowIndex],
		yellowCurStep,
		yellowPorts,
		yellowPins
	);
 
	//Do Headlights
	processLightGrouping(
		headlightSequences[seq->headlightIndex],
		headlightSequencesLen[seq->headlightIndex],
		headlightCurStep,
		headlightPorts,
		headlightPins
	);
 
	//Do Takedown
	if (seq->takeDown == TAKEDOWN_ON)
		setPinState(2, 2, ON);
	else
		setPinState(2, 2, OFF);
}

 

flashSequences.h

/*
 * Police Lightbar Flasher v3.1
 * COPYRIGHT 2012 Dave Loman
 *
 * Provided  under a Creative Commons Attribution, Non-Commercial
 * Share-Alike,3.0 Unported License
 *
 * TARGETED TO MSP430 LANUCHPAD W/MSP430G2553 PROCESSOR
 *
 */
 
#ifndef FLASHSEQUENCES_H
#define FLASHSEQUENCES_H
 
//XXX Bookmark
// Yellow Alternate
static byte yellow_alternate[] =
{
//YEL_00
	32,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
//YEL_01
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
};
 
//XXX Bookmark
// Yellow slow flash same
static byte yellow_slow_flash[] =
{
//YEL_00
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
//YEL_01
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
};
 
//XXX Bookmark
// Yellow OFF
static byte yellow_off[] =
{
//YEL_00
	7,  // stepCount;
	0x00,	// 00000000
//YEL_01
	7,  // stepCount;
	0x00,	// 00000000
};
 
byte  yellowCurStep[2]     = {0,0};
const byte yellowPorts[2] = {2,2};
const byte yellowPins[2]  = {3,4};
const byte *yellowSequences[3] = {
	yellow_off,
	yellow_slow_flash,
	yellow_alternate
};
const byte  yellowSequencesLen[3] = {
	sizeof(yellow_off),
	sizeof(yellow_slow_flash),
	sizeof(yellow_alternate)
};
byte  yellowSeqSelect = 0;
#define YELLOW_OFF        0
#define YELLOW_SLOW_FLASH 1
#define YELLOW_ALTERNATE  2
 
 
 
 
//XXX Bookmark
// headlight strobe
static byte headlight_strobe[] =
{
//WHT_00
	16,  // stepCount;
	0x24,	// 00100100
	0x00,	// 00000000
//WHT_01
	16,  // stepCount;
	0x00,	// 00000000
	0x24,	// 00100100
};
 
//XXX Bookmark
// headlight OFF
static byte headlight_off[] =
{
//WHT_00
	7,  // stepCount;
	0x00,	// 00000000
//WHT_01
	7,  // stepCount;
	0x00,	// 00000000
};
 
 
byte headlightCurStep[2]     = {0,0};
const byte headlightPorts[2] = {1,1};
const byte headlightPins[2]  = {6,7};
const byte *headlightSequences[2] = {
	headlight_off,
	headlight_strobe
};
const byte  headlightSequencesLen[2] = {
	sizeof(headlight_off),
	sizeof(headlight_strobe)
};
byte  headlightSeqSelect = 0;
 
#define HEADLIGHT_OFF    0
#define HEADLIGHT_STROBE 1
 
 
 
 
 
 
 
 
//XXX Bookmark
// Cruise
static byte seq_cruise[] =
{
//RED_00
	2,  // stepCount;
	0xFF,	// 11111111
//RED_01
	2,  // stepCount;
	0x00,	// 00000000
//RED_02
	2,  // stepCount;
	0x00,	// 00000000
 
//BLU_00
	2,  // stepCount;
	0xFF,	// 00000000
//BLU_01
	2,  // stepCount;
	0x00,	// 00000000
//BLU_02
	2,  // stepCount;
	0x00,	// 11111111
};
 
//XXX Bookmark
// SOLID Slow
static byte seq_solid_slow[] =
{
//RED_00
	48,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_01
	48,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_02
	48,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
 
//BLU_00
	48,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
//BLU_01
	48,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
//BLU_02
	48,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
};
 
//XXX Bookmark
// SOLID Medium
static byte seq_solid_medium[] =
{
//RED_00
	32,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_01
	32,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_02
	32,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
 
//BLU_00
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
//BLU_01
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
//BLU_02
	32,  // stepCount;
	0xFF,	// 11111111
	0xFF,	// 11111111
	0x00,	// 00000000
	0x00,	// 00000000
};
 
//XXX Bookmark
// SOLID fast
static byte seq_solid_fast[] =
{
//RED_00
	16,  // stepCount;
	0x00,	// 00000000
	0xFF,	// 11111111
//RED_01
	16,  // stepCount;
	0x00,	// 00000000
	0xFF,	// 11111111
//RED_02
	16,  // stepCount;
	0x00,	// 00000000
	0xFF,	// 11111111
 
//BLU_00
	16,  // stepCount;
	0xFF,	// 11111111
	0x00,	// 00000000
//BLU_01
	16,  // stepCount;
	0xFF,	// 11111111
	0x00,	// 00000000
//BLU_02
	16,  // stepCount;
	0xFF,	// 11111111
	0x00,	// 00000000
};
 
 
//XXX Bookmark
// 3x Strobe
static byte seq_3x_strobe[] = {
//RED_00
	18,  // stepCount;
	0x24,	// 00100100
	0x80,	// 10000000
	0x00,	// 00 000000
//RED_01
	18,  // stepCount;
	0x24,	// 00100100
	0x80,	// 10000000
	0x00,	// 00 000000
//RED_02
	18,  // stepCount;
	0x24,	// 00100100
	0x80,	// 10000000
	0x00,	// 00 000000
 
//BLU_00
	18,  // stepCount;
	0x00,	// 00000000
	0x12,	// 00010010
	0x40,	// 01 000000
//BLU_01
	18,  // stepCount;
	0x00,	// 00000000
	0x12,	// 00010010
	0x40,	// 01 000000
//BLU_02
	18,  // stepCount;
	0x00,	// 00000000
	0x12,	// 00010010
	0x40,	// 01 000000
};
 
 
//XXX Bookmark
// 2x Strobe
static byte seq_2x_strobe[] = {
//RED_00
	12,  // stepCount;
	0x24,	// 00100100
	0x00,	// 000000 00
//RED_01
	12,  // stepCount;
	0x24,	// 00100100
	0x00,	// 000000 00
//RED_02
	12,  // stepCount;
	0x24,	// 00100100
	0x00,	// 000000 00
 
//BLU_00
	12,  // stepCount;
	0x00,	// 00000000
	0x90,	// 100100 00
//BLU_01
	12,  // stepCount;
	0x00,	// 00000000
	0x90,	// 100100 00
//BLU_02
	12,  // stepCount;
	0x00,	// 00000000
	0x90,	// 100100 00
};
 
 
 
//XXX Bookmark
// 1x Strobe
static byte seq_1x_strobe[] = {
//RED_00
	6,  // stepCount;
	0x20,	// 001000 00
//RED_01
	6,  // stepCount;
	0x20,	// 001000 00
//RED_02
	6,  // stepCount;
	0x20,	// 001000 00
 
//BLU_00
	6,  // stepCount;
	0x04,	// 000001 00
//BLU_01
	6,  // stepCount;
	0x04,	// 000001 00
//BLU_02
	6,  // stepCount;
	0x04,	// 000001 00
};
 
 
//XXX Bookmark
// multi Strobe
static byte seq_multi_strobe[] = {
//RED_00
	18,  // stepCount;
	0x24,	// 00100100
	0x80,	// 10000000
	0x00,	// 00 000000
//RED_01
	12,  // stepCount;
	0x24,	// 00100100
	0x00,	// 000000 00
//RED_02
	6,  // stepCount;
	0x20,	// 001000 00
 
//BLU_00
	18,  // stepCount;
	0x00,	// 00000000
	0x12,	// 00010010
	0x40,	// 01 000000
//BLU_01
	12,  // stepCount;
	0x00,	// 00000000
	0x90,	// 100100 00
//BLU_02
	6,  // stepCount;
	0x04,	// 000001 00
};
 
 
//XXX Bookmark
// Traffic Director, Left
static byte seq_traffic_director_left[] =
{
//RED_00
	40,  // stepCount;
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_01
	40,  // stepCount;
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_02
	40,  // stepCount;
	0x00,	// 00000000
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
 
//BLU_00
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
//BLU_01
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
//BLU_02
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
};
 
//XXX Bookmark
// Traffic Director, Left
static byte seq_traffic_director_right[] =
{
//RED_00
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_01
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
//RED_02
	40,  // stepCount;
	0x00,	// 00000000
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
 
//BLU_00
	40,  // stepCount;
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//BLU_01
	40,  // stepCount;
	0x00,	// 00000000
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
//BLU_02
	40,  // stepCount;
	0x00,	// 00000000
	0x0F,	// 00001111
	0xFF,	// 11111111
	0xFF,	// 11111111
	0xFF,	// 11111111
};
 
 
byte redBlueCurStep[6]     = {0,0,0,0,0,0};
const byte redBluePorts[6] = {1,1,1,1,1,2};
const byte redBluePins[6]  = {0,1,2,4,5,0};
const byte *redBlueSequences[10] = {
		seq_cruise,
		seq_solid_slow,
		seq_solid_medium,
		seq_solid_fast,
		seq_3x_strobe,
		seq_2x_strobe,
		seq_1x_strobe,
		seq_multi_strobe,
		seq_traffic_director_left,
		seq_traffic_director_right
};
const byte  redBlueSequencesLen[10] = {
		sizeof(seq_cruise),
		sizeof(seq_solid_slow),
		sizeof(seq_solid_medium),
		sizeof(seq_solid_fast),
		sizeof(seq_3x_strobe),
		sizeof(seq_2x_strobe),
		sizeof(seq_1x_strobe),
		sizeof(seq_multi_strobe),
		sizeof(seq_traffic_director_left),
		sizeof(seq_traffic_director_right)
};
byte  redBlueSeqSelect = 0;
#define REDBLUE_PATROL       0
#define REDBLUE_SOLID_SLOW   1
#define REDBLUE_SOLID_MED    2
#define REDBLUE_SOLID_FAST   3
#define REDBLUE_3X_STROBE    4
#define REDBLUE_2X_STROBE    5
#define REDBLUE_1X_STROBE    6
#define REDBLUE_MULTI_STROBE 7
#define REDBLUE_TRAFFIC_DIRECTOR_LEFT  8
#define REDBLUE_TRAFFIC_DIRECTOR_RIGHT 9
 
 
#define TAKEDOWN_OFF  0
#define TAKEDOWN_ON   1
 
 
typedef struct Sequence {
	const byte redBlueIndex;
	const byte yellowIndex;
	const byte headlightIndex;
	const byte takeDown;
} Sequence ;
 
 
const Sequence patrol = {
	REDBLUE_PATROL,
	YELLOW_OFF,
	HEADLIGHT_OFF,
	TAKEDOWN_OFF
};
 
const  Sequence solid_slow = {
	REDBLUE_SOLID_SLOW,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence solid_med = {
	REDBLUE_SOLID_MED,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence solid_fast = {
	REDBLUE_SOLID_FAST,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence strobe_3x = {
	REDBLUE_3X_STROBE,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence strobe_2x = {
	REDBLUE_2X_STROBE,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence strobe_1x = {
	REDBLUE_1X_STROBE,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence strobe_multi = {
	REDBLUE_MULTI_STROBE,
	YELLOW_ALTERNATE,
	HEADLIGHT_STROBE,
	TAKEDOWN_OFF
};
 
const Sequence traffic_left = {
	REDBLUE_TRAFFIC_DIRECTOR_LEFT,
	YELLOW_SLOW_FLASH,
	HEADLIGHT_STROBE,
	TAKEDOWN_ON
};
 
const Sequence traffic_right = {
	REDBLUE_TRAFFIC_DIRECTOR_RIGHT,
	YELLOW_SLOW_FLASH,
	HEADLIGHT_STROBE,
	TAKEDOWN_ON
};
 
#endif // FLASHSEQUENCES_H
 
/*
 
 
Decimal	Binary		Hex
1		00000001	01
2		00000010	02
3		00000011	03
4		00000100	04
5		00000101	05
6		00000110	06
7		00000111	07
8		00001000	08
9		00001001	09
10		00001010	0A
11		00001011	0B
12		00001100	0C
13		00001101	0D
14		00001110	0E
15		00001111	0F
16		00010000	10
17		00010001	11
18		00010010	12
19		00010011	13
20		00010100	14
21		00010101	15
22		00010110	16
23		00010111	17
24		00011000	18
25		00011001	19
26		00011010	1A
27		00011011	1B
28		00011100	1C
29		00011101	1D
30		00011110	1E
31		00011111	1F
32		00100000	20
33		00100001	21
34		00100010	22
35		00100011	23
36		00100100	24
37		00100101	25
38		00100110	26
39		00100111	27
40		00101000	28
41		00101001	29
42		00101010	2A
43		00101011	2B
44		00101100	2C
45		00101101	2D
46		00101110	2E
47		00101111	2F
48		00110000	30
49		00110001	31
50		00110010	32
51		00110011	33
52		00110100	34
53		00110101	35
54		00110110	36
55		00110111	37
56		00111000	38
57		00111001	39
58		00111010	3A
59		00111011	3B
60		00111100	3C
61		00111101	3D
62		00111110	3E
63		00111111	3F
64		01000000	40
65		01000001	41
66		01000010	42
67		01000011	43
68		01000100	44
69		01000101	45
70		01000110	46
71		01000111	47
72		01001000	48
73		01001001	49
74		01001010	4A
75		01001011	4B
76		01001100	4C
77		01001101	4D
78		01001110	4E
79		01001111	4F
80		01010000	50
81		01010001	51
82		01010010	52
83		01010011	53
84		01010100	54
85		01010101	55
86		01010110	56
87		01010111	57
88		01011000	58
89		01011001	59
90		01011010	5A
91		01011011	5B
92		01011100	5C
93		01011101	5D
94		01011110	5E
95		01011111	5F
96		01100000	60
97		01100001	61
98		01100010	62
99		01100011	63
100		01100100	64
101		01100101	65
102		01100110	66
103		01100111	67
104		01101000	68
105		01101001	69
106		01101010	6A
107		01101011	6B
108		01101100	6C
109		01101101	6D
110		01101110	6E
111		01101111	6F
112		01110000	70
113		01110001	71
114		01110010	72
115		01110011	73
116		01110100	74
117		01110101	75
118		01110110	76
119		01110111	77
120		01111000	78
121		01111001	79
122		01111010	7A
123		01111011	7B
124		01111100	7C
125		01111101	7D
126		01111110	7E
127		01111111	7F
128		10000000	80
129		10000001	81
130		10000010	82
131		10000011	83
132		10000100	84
133		10000101	85
134		10000110	86
135		10000111	87
136		10001000	88
137		10001001	89
138		10001010	8A
139		10001011	8B
140		10001100	8C
141		10001101	8D
142		10001110	8E
143		10001111	8F
144		10010000	90
145		10010001	91
146		10010010	92
147		10010011	93
148		10010100	94
149		10010101	95
150		10010110	96
151		10010111	97
152		10011000	98
153		10011001	99
154		10011010	9A
155		10011011	9B
156		10011100	9C
157		10011101	9D
158		10011110	9E
159		10011111	9F
160		10100000	A0
161		10100001	A1
162		10100010	A2
163		10100011	A3
164		10100100	A4
165		10100101	A5
166		10100110	A6
167		10100111	A7
168		10101000	A8
169		10101001	A9
170		10101010	AA
171		10101011	AB
172		10101100	AC
173		10101101	AD
174		10101110	AE
175		10101111	AF
176		10110000	B0
177		10110001	B1
178		10110010	B2
179		10110011	B3
180		10110100	B4
181		10110101	B5
182		10110110	B6
183		10110111	B7
184		10111000	B8
185		10111001	B9
186		10111010	BA
187		10111011	BB
188		10111100	BC
189		10111101	BD
190		10111110	BE
191		10111111	BF
192		11000000	C0
193		11000001	C1
194		11000010	C2
195		11000011	C3
196		11000100	C4
197		11000101	C5
198		11000110	C6
199		11000111	C7
200		11001000	C8
201		11001001	C9
202		11001010	CA
203		11001011	CB
204		11001100	CC
205		11001101	CD
206		11001110	CE
207		11001111	CF
208		11010000	D0
209		11010001	D1
210		11010010	D2
211		11010011	D3
212		11010100	D4
213		11010101	D5
214		11010110	D6
215		11010111	D7
216		11011000	D8
217		11011001	D9
218		11011010	DA
219		11011011	DB
220		11011100	DC
221		11011101	DD
222		11011110	DE
223		11011111	DF
224		11100000	E0
225		11100001	E1
226		11100010	E2
227		11100011	E3
228		11100100	E4
229		11100101	E5
230		11100110	E6
231		11100111	E7
232		11101000	E8
233		11101001	E9
234		11101010	EA
235		11101011	EB
236		11101100	EC
237		11101101	ED
238		11101110	EE
239		11101111	EF
240		11110000	F0
241		11110001	F1
242		11110010	F2
243		11110011	F3
244		11110100	F4
245		11110101	F5
246		11110110	F6
247		11110111	F7
248		11111000	F8
249		11111001	F9
250		11111010	FA
251		11111011	FB
252		11111100	FC
253		11111101	FD
254		11111110	FE
255		11111111	FF
 
 
 */

2 Responses to Police Lightbar Sim for Launchpad – Rev 3

  1. Toni W Ryan says:

    UGH! Cannot watch your video as it is tagged as private! Looking forward to seeing how you coded the timing loops. I have been tinkering with the timers and interrupts on my launchpad trying to get my speedometer (speed trap) off the ground.

  2. Dave L Dave L says:

    My apologies for the video’s visibility settings. Could have sworn I clicked ‘save’ when I changed it to public. I’ll get the code posted soon! There’s nothing fancy about the timing loops. I simply used a hard coded ‘time elapsed last loop’ value. Since the CPU is a constant frequency and I did not need actual millisecond accuracy, I went with a relative time per loop approach.

Leave a Reply

Your email address will not be published. Required fields are marked *