#include <SPI.h>
#include "sr595.h"

#define DIV 5
#define SIZE_OF(a) (sizeof(a) / sizeof(a[0]))
const byte PIN_CS   =  4;  
SR59532 sr32(PIN_CS);

struct OutTime {
    uint32_t dataOut;
    uint32_t time;
};

struct SCycle {
    OutTime *outTimes;
    OutTime *ot = nullptr;
    uint8_t idx;
    uint8_t nMaxIdx;
    uint32_t greenTimeRef;
    uint32_t saveMillis;
    uint8_t phaseCnt;
    uint8_t pSplit;
};

SCycle vehicleCycle;
SCycle vehicleCycle1;

SCycle *ptrCycle = &vehicleCycle;

OutTime outTimeList[] = {
    { 0x864921, 30000UL / DIV },    // green
    { 0x864922, 3000UL / DIV },     // yellow
    { 0x864924, 1000UL / DIV },     // red
    { 0x86130C, 25000UL / DIV },    // green
    { 0x861514, 3000UL / DIV },
    { 0x861924, 1000UL / DIV },
    { 0x249924, 15000UL / DIV },
    { 0x491924, 3000UL / DIV },
    { 0x921924, 1000UL / DIV },
    { 0x921864, 30000UL / DIV },
    { 0x9228A4, 3000UL / DIV },
    { 0x924924, 1000UL / DIV }      // red
};
OutTime outTimeList1[] = {
    { 0x864921, 30000UL / DIV },    // green
    { 0x864922, 3000UL / DIV },     // yellow
    { 0x864924, 1000UL / DIV },     // red
    { 0x86130C, 10000UL / DIV },    // green
    { 0x861514, 3000UL / DIV },
    { 0x861924, 1000UL / DIV },
    { 0x249924, 15000UL / DIV },
    { 0x491924, 3000UL / DIV },
    { 0x921924, 1000UL / DIV },
    { 0x921864, 30000UL / DIV },
    { 0x9228A4, 3000UL / DIV },
    { 0x924924, 1000UL / DIV }      // red
};

// attr_lss4 
// verde 10000 / DIV
// fase_time = 10000 + 3000 + 1000 + 3000 + 1000 = 18000
// verde_lss0 = outTimeList[0].time(30000)
// verde_init_end = (verde_lss0 - fase_time) / 2
// verde_init_end = 30000 - 18000 = 12000 / 2 = 6000
uint32_t greenTimeRef;


//OutTime *outPtr = outTimeList;
OutTime *outPtr = nullptr;
uint8_t nMaxIdx = SIZE_OF(outTimeList);
OutTime *sot = nullptr;
uint8_t idx = 0;
uint32_t saveMillis; 
uint8_t phaseCnt = 1;
uint8_t pSplit;

// for develop
uint8_t pSplitOld = 4;
uint8_t phaseCntOld = 255;

OutTime g_ot;

void exec(OutTime *ot, uint8_t nMax) {
    
    if (sot == nullptr) {
        sot = &ot[idx];
        //sr32.write(sot->dataOut);
        //Serial.println(sot->time);
        g_ot = ot[idx];
        sr32.write(g_ot.dataOut);

        saveMillis = millis();
        if (idx % 3 == 0) {
            // si entra qui ad inizio di ogni fase
            // greenTimeRef segna l'istante in cui 
            // commuta il verde per ogni fase.
            greenTimeRef = saveMillis;
            
            if (idx != 0) {
                //Serial.print("phase: ");
                //Serial.println(phaseCnt);
                phaseCnt++;
            }
            
        }
        //Serial.println(sot->time);
        
    //} else if (millis() - saveMillis >= sot->time) {
    } else if (millis() - saveMillis >= g_ot.time) {
        sot = nullptr;
        idx++;
        if (idx == nMaxIdx) {
            Serial.println("ciclo completato");
            phaseCnt = 1;
        }
        idx = idx % nMax; 
        pSplit = (pSplit + 1) % 3;
        //Serial.println(pSplit);
        
    } else if (1) {
        sot = nullptr;
        idx++;
    }
} 


void setup() {
 
    Serial.begin(115200);
    Serial.println(sizeof(outTimeList));
    outPtr = (OutTime*)malloc(sizeof(outTimeList));
    memcpy(outPtr, outTimeList, sizeof(outTimeList));
    vehicleCycle.outTimes = outPtr;
    vehicleCycle.idx = 0;
    vehicleCycle.nMaxIdx = 12;

    OutTime lot;
    lot = outPtr[1];
    Serial.println(lot.time);
    pinMode(PIN_CS, OUTPUT);

    digitalWrite(PIN_CS, HIGH);
    SPI.begin();
    
    sr32.write(0x924924);
    delay(2000);
        
}
uint8_t oldIdx = 13;
uint8_t oldPc = 4;
void loop() {
    //exec(outPtr, nMaxIdx);
    selectPhase(ptrCycle);
    exec1(ptrCycle);
    if (ptrCycle->phaseCnt != oldPc) {
        oldPc = ptrCycle->phaseCnt;
        Serial.println(ptrCycle->phaseCnt);
    }


    
}

void selectPhase(SCycle *sc) {
    if (sc->ot == nullptr) {
        sc->ot = &sc->outTimes[sc->idx];
        sr32.write(sc->ot->dataOut);
        //Serial.println(sot->time);
        sc->saveMillis = millis();
        if (sc->idx % 3 == 0) {
            // si entra qui ad inizio di ogni fase
            // greenTimeRef segna l'istante in cui 
            // commuta il verde per ogni fase.
            sc->greenTimeRef = saveMillis;
            
            if (sc->idx != 0) {
                //Serial.print("phase: ");
                //Serial.println(phaseCnt);
                sc->phaseCnt++;
            }
            
        }
    }   //Serial.println(sot->time);
        
}

void exec1(SCycle *sc) {
    
    /*if (sc->ot == nullptr) {
        sc->ot = &sc->outTimes[sc->idx];
        sr32.write(sc->ot->dataOut);
        //Serial.println(sot->time);
        sc->saveMillis = millis();
        if (sc->idx % 3 == 0) {
            // si entra qui ad inizio di ogni fase
            // greenTimeRef segna l'istante in cui 
            // commuta il verde per ogni fase.
            sc->greenTimeRef = saveMillis;
            
            if (sc->idx != 0) {
                //Serial.print("phase: ");
                //Serial.println(phaseCnt);
                sc->phaseCnt++;
            }
            
        }
        //Serial.println(sot->time);
        
    } else */
    if (sc->ot) {
        if (millis() - sc->saveMillis >= sc->ot->time) {
            sc->ot = nullptr;
            sc->idx++;
            if (sc->idx == sc->nMaxIdx) {
                Serial.println("ciclo completato");
                sc->phaseCnt = 0;
                sc->idx = 0;
            }
            //idx = idx % nMax; 
            sc->pSplit = (sc->pSplit + 1) % 3;
            //Serial.println(pSplit);
            
        }
    }
} 


uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
74HC595
sr1:Q1
sr1:Q2
sr1:Q3
sr1:Q4
sr1:Q5
sr1:Q6
sr1:Q7
sr1:GND
sr1:Q7S
sr1:MR
sr1:SHCP
sr1:STCP
sr1:OE
sr1:DS
sr1:Q0
sr1:VCC
led3:A
led3:C
led4:A
led4:C
led5:A
led5:C
led6:A
led6:C
led7:A
led7:C
led8:A
led8:C
74HC595
sr2:Q1
sr2:Q2
sr2:Q3
sr2:Q4
sr2:Q5
sr2:Q6
sr2:Q7
sr2:GND
sr2:Q7S
sr2:MR
sr2:SHCP
sr2:STCP
sr2:OE
sr2:DS
sr2:Q0
sr2:VCC
led11:A
led11:C
led12:A
led12:C
led13:A
led13:C
led14:A
led14:C
led15:A
led15:C
led16:A
led16:C
lss0 id=0
lss1 id=1
lss3 id=3
lss2 id=2
sw1:1a
sw1:2a
sw1:3a
sw1:4a
sw1:5a
sw1:6a
sw1:7a
sw1:8a
sw1:8b
sw1:7b
sw1:6b
sw1:5b
sw1:4b
sw1:3b
sw1:2b
sw1:1b
sw2:1a
sw2:2a
sw2:3a
sw2:4a
sw2:5a
sw2:6a
sw2:7a
sw2:8a
sw2:8b
sw2:7b
sw2:6b
sw2:5b
sw2:4b
sw2:3b
sw2:2b
sw2:1b
sw3:1a
sw3:2a
sw3:3a
sw3:4a
sw3:5a
sw3:6a
sw3:7a
sw3:8a
sw3:8b
sw3:7b
sw3:6b
sw3:5b
sw3:4b
sw3:3b
sw3:2b
sw3:1b
74HC595
sr3:Q1
sr3:Q2
sr3:Q3
sr3:Q4
sr3:Q5
sr3:Q6
sr3:Q7
sr3:GND
sr3:Q7S
sr3:MR
sr3:SHCP
sr3:STCP
sr3:OE
sr3:DS
sr3:Q0
sr3:VCC
74HC595
sr4:Q1
sr4:Q2
sr4:Q3
sr4:Q4
sr4:Q5
sr4:Q6
sr4:Q7
sr4:GND
sr4:Q7S
sr4:MR
sr4:SHCP
sr4:STCP
sr4:OE
sr4:DS
sr4:Q0
sr4:VCC
LS0
LS1
LS2
LS3
LS4
LS5
LS6
LS7
LS8
LS9
led1:A
led1:C
led2:A
led2:C
led9:A
led9:C
lss4
led10:A
led10:C
led17:A
led17:C
led18:A
led18:C
lss5
and1:A
and1:B
and1:OUT
not1:IN
not1:OUT
led19:A
led19:C
led20:A
led20:C
led21:A
led21:C
led22:A
led22:C
led23:A
led23:C
led24:A
led24:C
lss7
lss6
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
______________
--------------------------------------------
--------------------------------------------
____________________________________
--------------------------------------------
--------------------------------------------
- - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -
p5
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
p4
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
p6
p7
____________________________________
____________________________________
____________________________________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
______________
gnd1:GND
gnd2:GND
gnd3:GND