#include <Wire.h>
#include <SparkFunSX1509.h> // Include SX1509 library
const int SX_RESET = 16; // reset pins of SX1509s
const int RAILWAY_SOUND = 6; // control pin of relay for mp3 power
const int PCF_INT = 2; // interrupt from PCF8575
// D4 & D5 = software serial for level shifter / ESP8266; not implemented yet
// SX1509 I2C address (set by ADDR1 and ADDR0 (00 by default):
const byte SX1509_0 = 0x3E; // SX1509 I2C address
const byte SX1509_1 = 0x70; // SX1509 I2C address
SX1509 io0; // Create an SX1509 object to be used throughout
SX1509 io1; // Create an SX1509 object to be used throughout
// SX1509_0 Pin definition:
const byte SX1509_0_RWL0 = 6; // rail red left
const byte SX1509_0_RWR0 = 5; // rail red right
const byte SX1509_0_RWW0 = 7; // rail white
const byte SX1509_0_RWL1 = 14; // rail red left
const byte SX1509_0_RWR1 = 15; // rail red right
const byte SX1509_0_RWW1 = 13; // rail white
const byte SX1509_0_PEDR0 = 10; //pedestrian red #3a
const byte SX1509_0_PEDG0 = 11; //pedestrian green #3a
const byte SX1509_0_PEDR1 = 9; //pedestrian red #3b
const byte SX1509_0_PEDG1 = 8; //pedestrian green #3b
const byte SX1509_0_PEDR2 = 1; //pedestrian red #4a
const byte SX1509_0_PEDG2 = 0; //pedestrian green #4a
const byte SX1509_0_PEDR3 = 2; //pedestrian red #4b
const byte SX1509_0_PEDG3 = 3; //pedestrian green #4b
// SX1509_1 Pin definition:
const byte SX1509_1_RWL0 = 6; // rail red left
const byte SX1509_1_RWR0 = 5; // rail red right
const byte SX1509_1_RWW0 = 7; // rail white
const byte SX1509_1_RWL1 = 14; // rail red left
const byte SX1509_1_RWR1 = 13; // rail red right
const byte SX1509_1_RWW1 = 15; // rail white
const byte SX1509_1_PEDR0 = 8; //pedestrian red #1a
const byte SX1509_1_PEDG0 = 9; //pedestrian green #1a
const byte SX1509_1_PEDR1 = 10; //pedestrian red #1b
const byte SX1509_1_PEDG1 = 11; //pedestrian green #1b
const byte SX1509_1_PEDR2 = 0; //pedestrian red #2a
const byte SX1509_1_PEDG2 = 1; //pedestrian green #2a
const byte SX1509_1_PEDR3 = 3; //pedestrian red #2b
const byte SX1509_1_PEDG3 = 2; //pedestrian green #2b
// addresses of PCF8574 IC
const byte PCF8574[] = {0x39, 0x3b, 0x3d, 0x3f};
#define PCF8575 (0x20) //address of PCF8575 (button input, illuminated buttons LED output)
const byte RED = 10;
const byte YLW = 20;
const byte GRN = 30;
unsigned long previousMillis = 0;
const long interval = 20;
byte blink_int = 0;
byte sec20 = 0;
boolean blink_state = false;
const byte numChars = 64;
char recChars[numChars]; // an array to store the received data
boolean newData = false;
byte cur_light = 0;
byte b;
String s;
boolean pcf_int_trigger = false;
byte dbnc = 0;
boolean sound = false;
boolean red_btn = false; // LED of red button
boolean grn_btn = false; // LED of green button
boolean blu_btn = false; // LED of blue button
byte mode = 1; // 0 = orange lights blink, 1 - program, 2 - test
byte rail_mode = 1; // 0 = off, 1 - white, 2 - red
byte prog_step = 0;
byte next_step = 1;
void setup()
{
pinMode(RAILWAY_SOUND, OUTPUT);
digitalWrite(RAILWAY_SOUND, LOW);
pinMode(SX_RESET, OUTPUT);
digitalWrite(SX_RESET, HIGH);
pinMode(PCF_INT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PCF_INT), PCF_INT_ISR, FALLING); //interrupt when any of buttons is pressed
Wire.begin();
pcf8575_write(word(B11111111,B11111111)); //set all IOs as inputs
Serial.begin(9600);
while (!Serial);
Serial.println("\nI2C Scanner");
if (!io0.begin(SX1509_0, SX_RESET)) {
Serial.println("SX1509_0 not found");
}
if (!io1.begin(SX1509_1, SX_RESET)) {
Serial.println("SX1509_1 not found");
}
sx_init();
set_rail();
}
void sx_init() {
// Use the internal 2MHz oscillator.
// Set LED clock with divider (2MHz / (2^(divider-1)):
// divider = 2 means 1MHz LED clock (2MHz / (2^(2-1))
// divider = 3 means 500kHz LED clock (2MHz / (2^(3-1))
// divider = 4 means 250kHz LED clock (2MHz / (2^(4-1))
// 0x1-0xE: fOSCout = Fosc / 2 ^ (outputFreq - 1) Hz
const byte divider = 4;
io0.init();
io1.init();
io0.clock(INTERNAL_CLOCK_2MHZ, divider, INPUT, 1); //250kHz clock
io1.clock(INTERNAL_CLOCK_2MHZ, divider, INPUT, 1); //250kHz clock
//set IOs for pedestrian lights as digital outputs
//IOs for railway lights will be set as analogue outputs with breath funcion later
io0.pinMode(SX1509_0_PEDR0, OUTPUT);
io0.pinMode(SX1509_0_PEDG0, OUTPUT);
io0.pinMode(SX1509_0_PEDR1, OUTPUT);
io0.pinMode(SX1509_0_PEDG1, OUTPUT);
io0.pinMode(SX1509_0_PEDR2, OUTPUT);
io0.pinMode(SX1509_0_PEDG2, OUTPUT);
io0.pinMode(SX1509_0_PEDR3, OUTPUT);
io0.pinMode(SX1509_0_PEDG3, OUTPUT);
io1.pinMode(SX1509_1_PEDR0, OUTPUT);
io1.pinMode(SX1509_1_PEDG0, OUTPUT);
io1.pinMode(SX1509_1_PEDR1, OUTPUT);
io1.pinMode(SX1509_1_PEDG1, OUTPUT);
io1.pinMode(SX1509_1_PEDR2, OUTPUT);
io1.pinMode(SX1509_1_PEDG2, OUTPUT);
io1.pinMode(SX1509_1_PEDR3, OUTPUT);
io1.pinMode(SX1509_1_PEDG3, OUTPUT);
}
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {//every 20ms / 50x sec
previousMillis = currentMillis;
sec20++;
if (dbnc > 0) {
dbnc --;
}
if (sec20 == 50) { // 50 x 20 miliseconds elapsed, i.e. new second
// **************************** NEW SECOND ****************************
sec20 = 0;
if (next_step > 0) {next_step--;} //counter for traffic lights program
if (next_step == 0 || mode == 0 || mode == 2) { //when counter reaches zero, it's time for next program step. In mode=0 and mode=2 it's every second.
program_step();
}
}
blink_int++;
if (blink_int == 34) {
blink_state = true;
if (mode == 0) { // mode = 0 means only orange lights are flashing with cca. 700ms ON / 700ms OFF interval
set_leds(0, 5*32 + 5*4);
set_leds(1, 5*32 + 5*4);
set_leds(2, 5*32 + 5*4);
set_leds(3, 5*32 + 5*4);
}
}
if (blink_int == 69) {
blink_state = false;
blink_int = 0;
if (mode == 0) {
set_leds(0, 5*32 + 5*4);
set_leds(1, 5*32 + 5*4);
set_leds(2, 5*32 + 5*4);
set_leds(3, 5*32 + 5*4);
}
}
if (blink_int == 1) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
}
//check if any of buttons was pressed
if (pcf_int_trigger) {
pcf_int_trigger = false;
b = pcf8575_read();
b = b | B11101010; // mask only for the buttons
if (b != 255 && dbnc == 0) { //some button was pressed
Serial.println(b, BIN);
dbnc = 8; //set debounce period
//blue.0
//red.4
//grn.2
if (bitRead(b, 4) == 0) { //RED button pressed, change railway lights mode
rail_mode++;
if (rail_mode > 2) {
rail_mode = 1;
}
set_rail();
} else if (bitRead(b, 2) == 0) {//GREEN button pressed, change traffic lights mode
mode++;
next_step = 1;
prog_step = 0;
if (mode > 2) {
mode = 0;
}
Serial.print("Mode changed: ");
Serial.println(mode);
} else if (bitRead(b, 0) == 0) {//BLUE button pressed, it does nothing so far
//nothing yet
}
}
}
//check serial port input buffer
CheckSerial();
}
void button_lights() {
//sets illuminated buttons LEDs according to variables red_btn, grn_btn and blu_btn
byte lights;
lights = pcf8575_read();
if (red_btn) {
bitClear(lights, 3);
} else {
bitSet(lights, 3);
}
if (grn_btn) {
bitClear(lights, 5);
} else {
bitSet(lights, 5);
}
if (blu_btn) {
bitClear(lights, 1);
} else {
bitSet(lights, 1);
}
lights = lights | B00010101; //set button input IOs always as inputs
pcf8575_write(word(0xFF,lights));
}
void set_ped_group(byte group, byte color) {
//there are 4 groups of LEDs for pedestrian signals
//in every group the signals change simultaneously
boolean rval;
boolean gval;
if (color == RED) {
rval = 0; // RED lights on
gval = 1; // GRN lights off
} else {
rval = 1;
gval = 0;
}
if (group == 0) {
io1.digitalWrite(SX1509_1_PEDR1, rval);
io1.digitalWrite(SX1509_1_PEDG1, gval);
io1.digitalWrite(SX1509_1_PEDR2, rval);
io1.digitalWrite(SX1509_1_PEDG2, gval);
} else if (group == 1) {
io1.digitalWrite(SX1509_1_PEDR3, rval);
io1.digitalWrite(SX1509_1_PEDG3, gval);
io0.digitalWrite(SX1509_0_PEDR0, rval);
io0.digitalWrite(SX1509_0_PEDG0, gval);
} else if (group == 2) {
io0.digitalWrite(SX1509_0_PEDR1, rval);
io0.digitalWrite(SX1509_0_PEDG1, gval);
io0.digitalWrite(SX1509_0_PEDR2, rval);
io0.digitalWrite(SX1509_0_PEDG2, gval);
} else if (group == 3) {
io0.digitalWrite(SX1509_0_PEDR3, rval);
io0.digitalWrite(SX1509_0_PEDG3, gval);
io1.digitalWrite(SX1509_1_PEDR0, rval);
io1.digitalWrite(SX1509_1_PEDG0, gval);
}
}
void ped_off() {
//turn off all pedestrian signals
io0.digitalWrite(SX1509_0_PEDR0, 1);
io0.digitalWrite(SX1509_0_PEDG0, 1);
io0.digitalWrite(SX1509_0_PEDR1, 1);
io0.digitalWrite(SX1509_0_PEDG1, 1);
io0.digitalWrite(SX1509_0_PEDR2, 1);
io0.digitalWrite(SX1509_0_PEDG2, 1);
io0.digitalWrite(SX1509_0_PEDR3, 1);
io0.digitalWrite(SX1509_0_PEDG3, 1);
io1.digitalWrite(SX1509_1_PEDR0, 1);
io1.digitalWrite(SX1509_1_PEDG0, 1);
io1.digitalWrite(SX1509_1_PEDR1, 1);
io1.digitalWrite(SX1509_1_PEDG1, 1);
io1.digitalWrite(SX1509_1_PEDR2, 1);
io1.digitalWrite(SX1509_1_PEDG2, 1);
io1.digitalWrite(SX1509_1_PEDR3, 1);
io1.digitalWrite(SX1509_1_PEDG3, 1);
}
void CheckSerial() {
//serial port input routine, used only for debugging
static byte ndx = 0;
char endMarker = '\n';
char endMarker2 = '\r';
char rc;
byte pgroup, pcolor;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (rc != endMarker && rc != endMarker2) {
recChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
recChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
if (newData == true) {
int slen = strlen(recChars);
if (slen > 1) {
String usbreply = recChars;
usbreply.trim();
slen = usbreply.length();
if (usbreply == "TRED") {
rail_mode = 2;
set_rail();
} else if (usbreply == "TREDB") {
rail_mode = 3;
set_rail();
} else if (usbreply == "WHITE") {
rail_mode = 1;
set_rail();
} else if (usbreply == "RED") {
set_leds(cur_light, 32 + 4);
} else if (usbreply == "YLW") {
set_leds(cur_light, 4*32 + 4*4 + 0);
} else if (usbreply == "GRN") {
set_leds(cur_light, 3*32 + 3*4 + 1);
} else if (usbreply == "REDYLW") {
set_leds(cur_light, 2*32 + 2*4 + 0);
} else if (usbreply.startsWith("CL")) {
usbreply = usbreply.substring(2);
cur_light = usbreply.toInt();
Serial.println("CURRENT LIGHT: " + String(cur_light));
} else if (usbreply == "SXRST") {
digitalWrite(SX_RESET, LOW);
delay(2); //2ms RESET
digitalWrite(SX_RESET, HIGH);
sx_init();
Serial.println("SXs were RESET");
} else if (usbreply == "SX0READ") {
SX1509_print_regs(SX1509_0);
} else if (usbreply == "SX1READ") {
SX1509_print_regs(SX1509_1);
} else if (usbreply.startsWith("PG")) {
s = usbreply.substring(2,3);
pgroup = s.toInt();
s = usbreply.substring(3,4);
pcolor = s.toInt();
pcolor = pcolor * 10;
Serial.println("PED GROUP: " + String(pgroup) + ", color: " + String(pcolor));
set_ped_group(pgroup, pcolor);
}
}
newData = false;
}
}
void set_rail() {
if (rail_mode == 0) {
//nothing yet
} else if (rail_mode == 1) {
//set railway lights as GO - white lights blinking/breathing, red lights off
red_btn = false;
button_lights();
digitalWrite(RAILWAY_SOUND, LOW);
io0.pinMode(SX1509_0_RWL0, OUTPUT);
io0.pinMode(SX1509_0_RWR0, OUTPUT);
io0.digitalWrite(SX1509_0_RWL0, HIGH);
io0.digitalWrite(SX1509_0_RWR0, HIGH);
io0.pinMode(SX1509_0_RWL1, OUTPUT);
io0.pinMode(SX1509_0_RWR1, OUTPUT);
io0.digitalWrite(SX1509_0_RWL1, HIGH);
io0.digitalWrite(SX1509_0_RWR1, HIGH);
io0.pinMode(SX1509_0_RWW0, ANALOG_OUTPUT);
io0.breathe(SX1509_0_RWW0, 600, 700, 5, 5); // Breathe interval: 600ms LOW, 700ms HIGH, 5ms to rise from low to high, 5ms to fall from high to low
io0.pinMode(SX1509_0_RWW1, ANALOG_OUTPUT);
io0.breathe(SX1509_0_RWW1, 600, 700, 5, 5);
io1.pinMode(SX1509_1_RWL0, OUTPUT);
io1.pinMode(SX1509_1_RWR0, OUTPUT);
io1.digitalWrite(SX1509_1_RWL0, HIGH);
io1.digitalWrite(SX1509_1_RWR0, HIGH);
io1.pinMode(SX1509_1_RWL1, OUTPUT);
io1.pinMode(SX1509_1_RWR1, OUTPUT);
io1.digitalWrite(SX1509_1_RWL1, HIGH);
io1.digitalWrite(SX1509_1_RWR1, HIGH);
io1.pinMode(SX1509_1_RWW0, ANALOG_OUTPUT);
io1.breathe(SX1509_1_RWW0, 600, 700, 5, 5);
io1.pinMode(SX1509_1_RWW1, ANALOG_OUTPUT);
io1.breathe(SX1509_1_RWW1, 600, 700, 5, 5);
} else if (rail_mode == 2) {
//set railway lights as STOP - white lights off, red lights blinking/breathing
red_btn = true;
button_lights();
io0.sync();
io1.sync();
digitalWrite(RAILWAY_SOUND, HIGH);
io0.pinMode(SX1509_0_RWW0, OUTPUT);
io0.digitalWrite(SX1509_0_RWW0, HIGH);
io0.pinMode(SX1509_0_RWW1, OUTPUT);
io0.digitalWrite(SX1509_0_RWW1, HIGH);
io0.pinMode(SX1509_0_RWL0, ANALOG_OUTPUT);
io0.breathe(SX1509_0_RWL0, 500, 500, 40, 40); // Breathe interval: 500ms LOW, 500ms HIGH, 40ms to rise from low to high, 40ms to fall from high to low
io0.pinMode(SX1509_0_RWL1, ANALOG_OUTPUT);
io0.breathe(SX1509_0_RWL1, 500, 500, 40, 40);
io1.pinMode(SX1509_1_RWW0, OUTPUT);
io1.digitalWrite(SX1509_1_RWW0, HIGH);
io1.pinMode(SX1509_1_RWW1, OUTPUT);
io1.digitalWrite(SX1509_1_RWW1, HIGH);
io1.pinMode(SX1509_1_RWL0, ANALOG_OUTPUT);
io1.breathe(SX1509_1_RWL0, 500, 500, 40, 40);
io1.pinMode(SX1509_1_RWL1, ANALOG_OUTPUT);
io1.breathe(SX1509_1_RWL1, 500, 500, 40, 40);
delay(650);
io0.pinMode(SX1509_0_RWR0, ANALOG_OUTPUT);
io0.pinMode(SX1509_0_RWR1, ANALOG_OUTPUT);
io1.pinMode(SX1509_1_RWR0, ANALOG_OUTPUT);
io1.pinMode(SX1509_1_RWR1, ANALOG_OUTPUT);
io0.breathe(SX1509_0_RWR0, 500, 500, 40, 40);
io0.breathe(SX1509_0_RWR1, 500, 500, 40, 40);
io1.breathe(SX1509_1_RWR0, 500, 500, 40, 40);
io1.breathe(SX1509_1_RWR1, 500, 500, 40, 40);
} else if (rail_mode == 3) {
//test mode, just to show how lights work without breathe function
red_btn = true;
button_lights();
io0.sync();
io1.sync();
io0.pinMode(SX1509_0_RWW0, OUTPUT);
io0.digitalWrite(SX1509_0_RWW0, HIGH);
io0.pinMode(SX1509_0_RWW1, OUTPUT);
io0.digitalWrite(SX1509_0_RWW1, HIGH);
io1.pinMode(SX1509_1_RWW0, OUTPUT);
io1.digitalWrite(SX1509_1_RWW0, HIGH);
io1.pinMode(SX1509_1_RWW1, OUTPUT);
io1.digitalWrite(SX1509_1_RWW1, HIGH);
io0.pinMode(SX1509_0_RWL0, OUTPUT);
io0.pinMode(SX1509_0_RWL1, OUTPUT);
io1.pinMode(SX1509_1_RWL0, OUTPUT);
io1.pinMode(SX1509_1_RWL1, OUTPUT);
io0.pinMode(SX1509_0_RWR0, OUTPUT);
io0.pinMode(SX1509_0_RWR1, OUTPUT);
io1.pinMode(SX1509_1_RWR0, OUTPUT);
io1.pinMode(SX1509_1_RWR1, OUTPUT);
io0.blink(SX1509_0_RWL0, 600, 600);
io0.blink(SX1509_0_RWL1, 600, 600);
io1.blink(SX1509_1_RWL0, 600, 600);
io1.blink(SX1509_1_RWL1, 600, 600);
delay(600);
io0.blink(SX1509_0_RWR0, 600, 600);
io0.blink(SX1509_0_RWR1, 600, 600);
io1.blink(SX1509_1_RWR0, 600, 600);
io1.blink(SX1509_1_RWR1, 600, 600);
}
}
void program_step() {
if (rail_mode == 2) { //whaen railway lights are red, all car traffic in every direction is set to RED signals, all pedestrian signals are GREEN
set_leds(0, 1*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 1*32 + 1*4);
set_ped_group(0, GRN);
set_ped_group(1, GRN);
set_ped_group(2, GRN);
set_ped_group(3, GRN);
return;
}
if (mode == 1) {
if (prog_step == 0) {
set_leds(0, 4*32 + 4*4);
set_leds(1, 4*32 + 4*4);
set_leds(2, 4*32 + 4*4);
set_leds(3, 4*32 + 4*4);
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
next_step = 5;
} else if (prog_step == 1) {
set_leds(0, 1*32 + 2*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 2*4);
set_leds(3, 1*32 + 1*4);
next_step = 3;
} else if (prog_step == 2) {
set_leds(0, 1*32 + 3*4 + 1);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 3*4 + 1);
set_leds(3, 1*32 + 1*4);
set_ped_group(0, GRN);
set_ped_group(1, RED);
set_ped_group(2, GRN);
set_ped_group(3, RED);
next_step = 12;
} else if (prog_step == 3) {
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
next_step = 8;
} else if (prog_step == 4) {
set_leds(0, 1*32 + 4*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 4*4);
set_leds(3, 1*32 + 1*4);
next_step = 3;
} else if (prog_step == 5) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 2*32 + 1*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 2*32 + 1*4);
next_step = 3;
} else if (prog_step == 6) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 3*32 + 1*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 3*32 + 1*4);
next_step = 15;
} else if (prog_step == 7) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 4*32 + 2*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 4*32 + 2*4);
next_step = 3;
} else if (prog_step == 8) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 1*32 + 3*4 + 1);
set_leds(2, 1*32 + 1*4);
set_leds(3, 1*32 + 3*4 + 1);
set_ped_group(0, RED);
set_ped_group(1, GRN);
set_ped_group(2, RED);
set_ped_group(3, GRN);
next_step = 12;
} else if (prog_step == 9) {
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
next_step = 8;
} else if (prog_step == 10) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 1*32 + 4*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 1*32 + 4*4);
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
next_step = 3;
} else if (prog_step == 11) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 1*32 + 1*4);
next_step = 3;
} else if (prog_step == 12) {
set_leds(0, 2*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 2*32 + 1*4);
set_leds(3, 1*32 + 1*4);
next_step = 3;
} else if (prog_step == 13) {
set_leds(0, 3*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 3*32 + 1*4);
set_leds(3, 1*32 + 1*4);
next_step = 15;
} else if (prog_step == 14) {
set_leds(0, 4*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 4*32 + 1*4);
set_leds(3, 1*32 + 1*4);
next_step = 3;
}
prog_step++;
if (prog_step > 14) {
prog_step = 1;
}
} else if (mode == 2) {
if (prog_step == 1) {
set_leds(0, 0);
set_leds(1, 0);
set_leds(2, 0);
set_leds(3, 0);
ped_off();
} else if (prog_step == 2) {
set_leds(0, 1*32 + 1*4);
set_leds(1, 1*32 + 1*4);
set_leds(2, 1*32 + 1*4);
set_leds(3, 1*32 + 1*4);
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
} else if (prog_step == 3) {
set_leds(0, 4*32 + 4*4);
set_leds(1, 4*32 + 4*4);
set_leds(2, 4*32 + 4*4);
set_leds(3, 4*32 + 4*4);
set_ped_group(0, GRN);
set_ped_group(1, GRN);
set_ped_group(2, GRN);
set_ped_group(3, GRN);
} else if (prog_step == 4) {
set_leds(0, 3*32 + 3*4);
set_leds(1, 3*32 + 3*4);
set_leds(2, 3*32 + 3*4);
set_leds(3, 3*32 + 3*4);
set_ped_group(0, RED);
set_ped_group(1, RED);
set_ped_group(2, RED);
set_ped_group(3, RED);
} else if (prog_step == 5) {
set_leds(0, 1);
set_leds(1, 1);
set_leds(2, 1);
set_leds(3, 1);
set_ped_group(0, GRN);
set_ped_group(1, GRN);
set_ped_group(2, GRN);
set_ped_group(3, GRN);
}
prog_step++;
if (prog_step > 5) {
prog_step = 1;
}
} else { // mode = 0, orng blinking
ped_off();
set_leds(0, 5*32 + 5*4);
set_leds(1, 5*32 + 5*4);
set_leds(2, 5*32 + 5*4);
set_leds(3, 5*32 + 5*4);
next_step = 10;
}
}
void SX1509_print_regs(byte devAdd) {
//only for debug
b = SX1509_readB(devAdd, 0x1e);
Serial.print("RegClock (1E): ");
print_val(b);
b = SX1509_readB(devAdd, 0x1f);
Serial.print("RegMisc (1F): ");
print_val(b);
b = SX1509_readB(devAdd, 0x21);
Serial.print("RegLEDDriverEnableA (21): ");
print_val(b);
b = SX1509_readB(devAdd, 0x20);
Serial.print("RegLEDDriverEnableB (20): ");
print_val(b);
b = SX1509_readB(devAdd, 0x44);
Serial.print("REG_T_ON_7 (44): ");
print_val(b);
b = SX1509_readB(devAdd, 0x45);
Serial.print("REG_I_ON_7 (45): ");
print_val(b);
b = SX1509_readB(devAdd, 0x46);
Serial.print("REG_OFF_7 (46): ");
print_val(b);
b = SX1509_readB(devAdd, 0x47);
Serial.print("REG_T_RISE_7 (47): ");
print_val(b);
b = SX1509_readB(devAdd, 0x48);
Serial.print("REG_T_FALL_7 (48): ");
print_val(b);
}
void print_val(byte b) {
Serial.println(b);
Serial.println(b, HEX);
Serial.println(b, BIN);
}
void set_leds(byte pole, byte pattern) {
byte Pleds;
/*
LEFT:
0 - off
1 - RED
2 - RED+ORNG
3 - GRN
4 - ORNG
5 - ORNG blink
RIGHT:
0 - off
1 - RED
2 - RED+ORNG
3 - GRN
4 - ORNG
5 - ORNG blink
PEDESTRIAN CROSSING WARNING ORANGE LIGHT:
0 - off
1 - on
2 - blink
LLLRRRPP
LLLx32 + RRRx4 + PP
*/
//Left
b = pattern & B11100000;
b = b >> 5;
if (b == 0) {
Pleds = 0;
} else if (b == 1) {
Pleds = 16; //red
} else if (b == 2) {
Pleds = 16+64; // red+orng
} else if (b == 3) {
Pleds = 32; //grn
} else if (b == 4) {
Pleds = 64;
} else if (b == 5) {
if (blink_state) {
Pleds = 64;
} else {
Pleds = 0;
}
}
//Right
b = pattern & B00011100;
b = b >> 2;
if (b == 0) {
//Pleds += 0;
} else if (b == 1) {
Pleds += 8; //red
} else if (b == 2) {
Pleds += 8+1; // red+orng
} else if (b == 3) {
Pleds += 2; //grn
} else if (b == 4) {
Pleds += 1;
} else if (b == 5) {
if (blink_state) {
Pleds += 1;
} else {
//Pleds += 0;
}
}
//Pedestrian warning orng
b = pattern & B00000011;
if (b == 0) {
//Pleds += 0;
} else if (b == 1) {
Pleds += 4; //pedestrian
} else if (b == 2) {// blink
if (blink_state) {
Pleds += 4;
}
}
Pleds = ~Pleds;
pole = constrain(pole, 0, 3);
Wire.beginTransmission(PCF8574[pole]);
Wire.write(Pleds);
Wire.endTransmission();
}
// Function for writing two Bytes to the I2C expander device
void pcf8575_write(uint16_t data)
{
Wire.beginTransmission(PCF8575);
Wire.write(lowByte(data));
Wire.write(highByte(data));
Wire.endTransmission();
}
//uint16_t pcf8575_read()
byte pcf8575_read()
{
byte dataReceived[2]; //a two byte array to hold our data
uint16_t dat_rec;
Wire.beginTransmission(PCF8575);
Wire.endTransmission();
Wire.requestFrom(PCF8575, 2); //request two bytes of data
if (Wire.available()){
dataReceived[0] = Wire.read(); //read byte 1
dataReceived[1] = Wire.read(); //read byte 2
}
dat_rec = word(dataReceived[0], dataReceived[1]);
//return dat_rec;
return dataReceived[0]; //we use only one half of PCF8575, so only first byte is enough
}
byte SX1509_readB(byte devAdd, byte regAdd)
{
byte readValue;
unsigned int timeout = 1000;
Wire.beginTransmission(devAdd);
Wire.write(regAdd);
Wire.endTransmission();
Wire.requestFrom(devAdd, (byte) 1);
while ((Wire.available() < 1) && (timeout != 0))
timeout--;
if (timeout == 0)
return 0x55;
readValue = Wire.read();
return readValue;
}
void SX1509_writeB(byte devAdd, byte regAdd, byte writeVal)
{
Wire.beginTransmission(devAdd);
Wire.write(regAdd);
Wire.write(writeVal);
Wire.endTransmission();
}
//IO interrupt routine
void PCF_INT_ISR() {
pcf_int_trigger = true;
}
Comments