#include "CAN_FW.h"
#include "Can.h"
#include "IO.h"
#include "Utils.h"
#include "myfunc/VinReq.h"
#include "myfunc/_MFM3.h"

void Init (TCanFwMem * vars)
{
    static const TCanInit can1_init =
    {
        CCan::CanBaudrate500,
        1,
        {
            CCan::Filter::List11 (0x010, 0x020),
            CCan::Filter::List11 (0x040, 0x0E0),
            CCan::Filter::List11 (0x095, 0x100),
            CCan::Filter::List11 (0x300, 0x310),
            CCan::Filter::List11 (0x334, 0x355),

            CCan::Filter::List11 (0x380),

            CCan::Filter::List11 (0x0C3, 0x210),
        }
    };
    CoreFunc->CanInit (CANch1, &can1_init);
//---------------------------------------------------------
    static const TCanInit can2_init =
    {
        CCan::CanBaudrate500,
        1,
        {
            CCan::Filter::List11 (0x04B, 0x050),
            CCan::Filter::List11 (0x111, 0x138),
            CCan::Filter::Mask11 (0x7E0, 0x7F0),
        }
    };
    CoreFunc->CanInit (CANch2, &can2_init);
//---------------------------------------------------------
    vars->PeriodicTask.AddTask    (PELightButton, ELight_Button2);
}

void Can1Received (TCanFwMem * vars, TCanPkt *apPkt)
{
    // int32_t temp;   // знаковое!
    // int16_t tmp;    // знаковое!
    uint8_t * buf = apPkt->data;
    TCanPkt pkt;
    TCanPkt pktm;

    switch (apPkt->id)
    {
        case 0x010:
            CoreFunc->InputState (CIO::iLock,    (Rx_D & 0x0C)==0x08);
            break;

        case 0x040:
            CoreFunc->InputState (CIO::iDoorDrv, (Rx_G & 0xC0)==0x40);
            CoreFunc->InputState (CIO::iDoorRL,  (Rx_F & 0x0C)==0x04);

            if (vars->cmf)
            {
                pkt = *apPkt;
                pkt.data[4] |= 0x0A;
                CoreFunc->CanSend (CANch1, &pkt, 7);
                CoreFunc->CanSend (CANch1, &pkt, 17);
                vars->cmf = false;
            }
            break;

        case 0x0E0:
            CoreFunc->InputState (CIO::iDoorFP,  (Rx_D & 0xC0)==0x40);
            CoreFunc->InputState (CIO::iDoorRR,  (Rx_B & 0x30)==0x10);
            CoreFunc->InputState (CIO::iTrunk,   (Rx_F & 0xC0)==0x40);
            break;

        case 0x095:
            if (Rx_A == 0x52)   CoreFunc->Command (CoreCmdTrunkOpened, 0x04);   // Br-Hf
            break;

        case 0x100:

                 if (Rx_B == 0x1F || Rx_B == 0x2F || Rx_B == 0x9F)   CoreFunc->Command (CoreCmdArm, 0x04);       // Br,  HF-L,R
            else if (Rx_B == 0x17 || Rx_B == 0x27 || Rx_B == 0x97)   CoreFunc->Command (CoreCmdDisarm, 0x04);    // Br, HF-L,R
/*
            if (vars->mirror) не закрывается и зеркала зависают
            {
                pktm = *apPkt;
                pktm.data[1] == 0x1F;
 // попробовать это !!!               pktm.data[7] |= 0x08;
                for (int i=0; i<30; i++)     CoreFunc->CanSend (CANch1, &pktm, 30);
                vars->mirror = false;
            }
             */
            break;
        case 0x210:
            CoreFunc->DataValue (CanData_CoolantTemp, Rx_C - 10);
            break;

        //case 0x270: XC90
            //CoreFunc->DataValue (CanData_FuelLevel, buf[6]*100/256);//
        //    break;

        case 0x300:
            CoreFunc->DataValue  (CanData_RPM, (Rx_C << 8 | Rx_D) >> 1);
            break;
        case 0x310:
            CoreFunc->DataValue (CanData_Odometer, ((Rx_A & 0x0F) <<16 | buf[1]<<8 | buf[2]) * 10);
            break;

        case 0x334:
            CoreFunc->InputState (CIO::iLeftTurnLight,  Rx_H & BIT(4));
            CoreFunc->InputState (CIO::iRightTurnLight, Rx_H & BIT(2));
            CoreFunc->InputState (CIO::iEmergency,     (Rx_H & 0x14) == 0x14);
            break;
        case 0x355:
            CoreFunc->InputState (CIO::iLauncher,   Rx_F & 0x03);
            break;

        case 0x000:
            // CoreFunc->InputState (CIO::iLamp,  Rx_B & BIT(2));               // от XC90 не подходит ID0C3
            // CoreFunc->DataValue  (CanData_Speed, (Rx_B << 8 | Rx_C)>>4);
            // CoreFunc->DataValue  (CanData_FuelLevel, Rx_H);                  // от XC90 не подходит ID310
            // CoreFunc->DataValue  (CanData_FuelConsumption, Rx_C);
            break;
    }
}
void Can2Received (TCanFwMem * vars, TCanPkt *apPkt)
{
    // int32_t temp;   // знаковое!
    // int16_t tmp;    // знаковое!
    uint8_t * buf = apPkt->data;

    switch (apPkt->id)
    {

        case 0x04B:
            CoreFunc->InputState (CIO::iPark,        (Rx_D & 0x0E) == 0x00);
            break;
        case 0x050:
            Rx_C = Rx_C/2;
            if (Rx_C > 100) Rx_C = 100;
            CoreFunc->DataValue  (CanData_Accelerator, Rx_C);
            break;
        case 0x111:
            CoreFunc->InputState (CIO::iIgn,          Rx_C & BIT(7));
            break;
        case 0x138:
            //CoreFunc->InputState (CIO::iHBrake,      (Rx_A & 0x0C)==0x04); // ID144
            CoreFunc->DataValue  (CanData_BrakeForce,(Rx_E << 8 | Rx_F)/20);
            CoreFunc->InputState (CIO::iBrake,        Rx_E );
            break;

        case 0x2B0:
            //tmp = Rx_D << 8 | Rx_E ;
            //CoreFunc->DataValue (CanData_WheelAngle, tmp);
            break;
    }

}

void InputChanged (TCanFwMem * vars, uint32_t aInputNum, bool aSwitchedOn)
{
// TCanPkt pkt;

    if ((aInputNum == CIO::iIgn) && ! aSwitchedOn)
    {
        CoreFunc->InputState (CIO::iBrake, false);
        CoreFunc->DataValue (CanData_Invalid | CanData_RPM, 0);
    }

    if (aInputNum == CIO::iIgn)        vars->ign = aSwitchedOn;

    if (aInputNum == CIO::iEmergency)
    {
        vars->ELight.hazlamp = aSwitchedOn;

        if (!vars->ELight.seized) vars->ELight.tmr.Restart ();            // при собственных моргках таймер не перезапускаем
        //tt(aSwitchedOn);
    }
}

void GuardEvent (TCanFwMem * vars, TGuardEvents aEvent)
{
    if (aEvent == geARM)    vars->arm = true;
    if (aEvent == geDISARM) vars->arm = false;
}