Arduino Automotive Light Sequencer

This is my first attempt at any Arduino (Seeeduino) programming. I'm a Delphi programmer, but I've worked in C
in the distant past. Don't be terribly surprised if my coding style doesn't look like what you're used to seeing.
 


 
Here's what it's going into
 


 
The circuit
 



 
The code (commented)
 

/*  ZX Light Sequencer ver 1.1  -  2009-04-04  -  Ray Andrews  -  SteelToad Software, Inc.  
    My first program on the Arduino platform, and my first dive back into C in a long time.
    The circuit is intended to drive the tail-lights and marker-lights on a car I'm rebuilding.
    The led's will be replaced with mosfet's to drive the auto voltages and switch the lights.  
    There are three (T)ail-lights on each side of the car, and a single (m)arker light
     
    Vehicle lights   (m)   (T) (T) (T)         (T) (T) (T)   (m)
                      |     |   |   |           |   |   |     |
    Arduino pins      13    12  11  10          9   8   7     6
    ------------------------------------------------------------
    Profile bits     128    64  32  16          8   4   2     1
    
    This program stores the sequences as profiles, each profile has four step sequence for 
    each of six possible values to be read from the available inputs. Each byte in the profile
    drives a light with each corresponding bit as shown above. The program does one step in the 
    sequence each time through the loop in order to maximize responsiveness to inputs. I dont 
    want to be waiting to finish a turn singal sequence when I'm already standing on the brakes. 
    
    Another reason I've designed it this way rather than coding individual digitalWrite commands
    is that I can add new profiles, or extend the number of steps in a sequence without having 
    to change the actual code. With the current four steps per sequence, each new profile only 
    adds an additional 24 bytes to the program.
    
    ver 1.0 (1844 bytes / Ardunio 0015)
    
    ver 1.1 (1780 bytes / Ardunio 0015)
    - removed setup line that set all digital pins to input, controller does that automatically 
    - hazard lights only come on if no other signal is present  
    - removed unused const profile_size
 
/**********************************************************************************************/

const int first_light_pin = 6;          // starting point for led output pins

const int speed_pin = 2;                // analog pin (potentiometer speed adjustment)

const int right_turn_pin = 1;           // digital input pins for control signals
const int left_turn_pin = 2;            //
const int brakes_pin = 3;               //
const int hazard_pin = 4;               //
const int profile_selector_pin = 5;     //

const int no_activity = -2;             // these constants are possible values for the 
const int brakes_only = 0;              // signal_type variable and indicate which of 
const int left_turn = 1;                // the controls are active
const int right_turn = 2;               //
const int left_turn_brakes = 3;         //
const int right_turn_brakes = 4;        //
const int hazard_lights = 5;            //

const int profile_max = 2;              // number of profiles
const int signal_type_max = 6;          // how many types of signals can there be
const int step_max = 4;                 // number of steps in each sequence

/**********************************************************************************************/

// different profiles for light settings, the first group are the standard sequence,
// the second are settings that are more "inspection time" friendly. Other profiles
// could easily be added later.
                        
byte profiles[profile_max][signal_type_max][step_max] = 
//                    1 = Light On   0 = Light Off
//             step 1      step 2      step 3      step 4
//                           Basic Profile
            {B11111111,  B11111111,  B11111111,  B11111111,   // 0  brakes
             B11110000,  B00000000,  B11110000,  B00000000,   // 1  left turn
             B00001111,  B00000000,  B00001111,  B00000000,   // 2  right turn
             B00111111,  B11111111,  B00111111,  B11111111,   // 3  left turn with brakes
             B11111100,  B11111111,  B11111100,  B11111111,   // 4  right turn with brakes
             B11111111,  B00100100,  B11111111,  B00100100,   // 5  hazard lights
             
//                      Sequenced Lights Profile   
             B11111111,  B11111111,  B11111111,  B11111111,   // 0  brakes
             B00010000,  B10100000,  B01000000,  B10000000,   // 1  left turn 
             B00001000,  B00000101,  B00000010,  B00000001,   // 2  right turn 
             B11101111,  B01011111,  B10111111,  B01111111,   // 3  left turn with brakes  
             B11110111,  B11111010,  B11111101,  B11111110,   // 4  right turn with brakes 
             B10100101,  B01011010,  B10100101,  B01011010};  // 5  hazard lights 
                           
int cycle_delay;                        // analog reading from the speed_pin
int profile_id = 0;                     // the currently selected profile
int previous_signal_type = no_activity; // the previous signal reading (for later comparison)
int signal_type = no_activity;          // the current input signal reading
int step_counter = 0;                   // where in the four step sequence:  0 - (step_max-1)
int x = 0;                              // counter varaible for small for loops

/**********************************************************************************************/

void setup()                    
  {
  // set led pins for output starting at first_light_pin
  for (x = 0; x < 8; x++)    pinMode(first_light_pin + x, OUTPUT);
  }
  

void loop()                     
  {
  // find out what switches are pressed, the speed, which profile to use
  read_controls();    
  
  // if the signal has changed, start at the beginning of the new sequence
  if (signal_type != previous_signal_type)  step_counter = 0;
  
  if (signal_type == no_activity)
    {
    // turn all of the lights off, but only if we're changing to no_activity
    // theres no need to turn them off every time through the loop if nothing has changed
    // restart the loop to make looking for the next signal faster, we dont need the delay
    if (previous_signal_type != no_activity)
      for (x = 0; x < 8; x++)  digitalWrite(first_light_pin + x, LOW);
    return;
    }
    
  // look-up the byte to use according to the profile, signal_type, and step_counter
  // set each let based on the corresponding bit in the profile byte
  for (x = 0; x < 8; x++)
    digitalWrite(first_light_pin + x, profiles[profile_id][signal_type][step_counter] & (1<<x)); 
 
  // increment the step_counter and reset back to 0 to start the sequence over
  if (++step_counter >= step_max)  step_counter = 0;
    
  // wait time is set by the potentiomenter on speed_pin
  delay(cycle_delay);  
  }


void read_controls()
  {
  // reading the cycle_delay and profile_id could be moved to the setup function
  // but for testing, it's easier to just leave them here to get called by loop
    
  // save the previous signal_type to help detect changes
  previous_signal_type = signal_type;
  
  // assume no activity, and then adjust accordingly based on input pin values
  signal_type = no_activity;
  if (digitalRead(left_turn_pin))    signal_type = left_turn;
  if (digitalRead(right_turn_pin))   signal_type = right_turn;
  if (digitalRead(brakes_pin))
    {
    if (signal_type == left_turn)    signal_type = left_turn_brakes;
    if (signal_type == right_turn)   signal_type = right_turn_brakes;
    if (signal_type == no_activity)  signal_type = brakes_only;
    }
  if (digitalRead(hazard_pin) && signal_type == no_activity)
    signal_type = hazard_lights;
  
  // read the delay to put between steps
  cycle_delay = analogRead(speed_pin) + 10;
  
  // determine which profile to use, right now it's by input pin selection, but
  // it could be software derived, from a rotary switch, or other method later
  if (digitalRead(profile_selector_pin) == HIGH)   
    profile_id = 1;  
  else  
    profile_id = 0;
    
  // make sure whatever profile_id is selected is within the profile table range
  if (profile_id >= profile_max || profile_id < 0)  profile_id = 0;
  }


 
The code (with minimal comments)
 

const int first_light_pin = 6;         

const int speed_pin = 2;              

const int right_turn_pin = 1;          
const int left_turn_pin = 2;           
const int brakes_pin = 3;              
const int hazard_pin = 4;            
const int profile_selector_pin = 5;  

const int no_activity = -2;            
const int brakes_only = 0;             
const int left_turn = 1;              
const int right_turn = 2;              
const int left_turn_brakes = 3;       
const int right_turn_brakes = 4;      
const int hazard_lights = 5;           

const int profile_max = 2;            
const int signal_type_max = 6;         
const int step_max = 4;                
                       
byte profiles[profile_max][signal_type_max][step_max] = 
//             step 1      step 2      step 3      step 4
//                           Basic Profile
            {B11111111,  B11111111,  B11111111,  B11111111,   // 0  brakes
             B11110000,  B00000000,  B11110000,  B00000000,   // 1  left turn
             B00001111,  B00000000,  B00001111,  B00000000,   // 2  right turn
             B00111111,  B11111111,  B00111111,  B11111111,   // 3  left turn with brakes
             B11111100,  B11111111,  B11111100,  B11111111,   // 4  right turn with brakes
             B11111111,  B00100100,  B11111111,  B00100100,   // 5  hazard lights
             
//                      Sequenced Lights Profile   
             B11111111,  B11111111,  B11111111,  B11111111,   // 0  brakes
             B00010000,  B10100000,  B01000000,  B10000000,   // 1  left turn 
             B00001000,  B00000101,  B00000010,  B00000001,   // 2  right turn 
             B11101111,  B01011111,  B10111111,  B01111111,   // 3  left turn with brakes  
             B11110111,  B11111010,  B11111101,  B11111110,   // 4  right turn with brakes 
             B10100101,  B01011010,  B10100101,  B01011010};  // 5  hazard lights 
                           
int cycle_delay;                        
int profile_id = 0;                     
int previous_signal_type = no_activity; 
int signal_type = no_activity;          
int step_counter = 0;                   
int x = 0;                            


void setup()                    
  {
  for (x = 0; x < 8; x++)    pinMode(first_light_pin + x, OUTPUT);
  }
  

void loop()                     
  {
  read_controls();    
  
  if (signal_type != previous_signal_type)  step_counter = 0;
  
  if (signal_type == no_activity)
    {
    if (previous_signal_type != no_activity)
      for (x = 0; x < 8; x++)  digitalWrite(first_light_pin + x, LOW);
    return;
    }
    
  for (x = 0; x < 8; x++)
    digitalWrite(first_light_pin + x, profiles[profile_id][signal_type][step_counter] & (1<<x)); 
 
  if (++step_counter >= step_max)  step_counter = 0;
    
  delay(cycle_delay);  
  }


void read_controls()
  {
  previous_signal_type = signal_type;
  
  signal_type = no_activity;
  if (digitalRead(left_turn_pin))    signal_type = left_turn;
  if (digitalRead(right_turn_pin))   signal_type = right_turn;
  if (digitalRead(brakes_pin))
    {
    if (signal_type == left_turn)    signal_type = left_turn_brakes;
    if (signal_type == right_turn)   signal_type = right_turn_brakes;
    if (signal_type == no_activity)  signal_type = brakes_only;
    }
  if (digitalRead(hazard_pin) && signal_type == no_activity)
    signal_type = hazard_lights;
  
  cycle_delay = analogRead(speed_pin) + 10;
  
  if (digitalRead(profile_selector_pin) == HIGH)   
    profile_id = 1;  
  else  
    profile_id = 0;
    
  if (profile_id >= profile_max || profile_id < 0)  profile_id = 0;
  }