aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Modules/IDS/IDS_maint.c
blob: 400eab33eec83227ce2a167b0a3faf11dbf10f5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.BL.Entities;

namespace Tango.MachineStudio.Developer.Converters
{
    public class BrushStopToOffsetValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                BrushStop stop = values[0] as BrushStop;
                Segment segment = values[1] as Segment;

                if (stop != null && segment != null)
                {
                    if (stop.IsLast)
                    {
                        return 100d;
                    }
                    else if (stop.IsFirst)
                    {
                        return 0d;
                    }
                    else
                    {
                        return stop.OffsetPercent;
                    }
                }
                else
                {
                    return 0d;
                }
            }
            catch
            {
                return 0d;
            }
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
'#n467'>467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
/************************************************************************************************************************
 * Ids_maint.c
 * Printing module is responsible for :
 * operating the dispensers according to predefined dispensing rate from the UI
 **************************************************************************************************************************/
#include "include.h"
#include "ids.h"
#include "ids_ex.h"
#include "../control/control.h"
#include "../control/pidalgo.h"
#include "../thread/thread.h"
#include "PMR/Hardware/Hardwaremotor.pb-c.h"
#include "PMR/Hardware/HardwareDispenser.pb-c.h"
#include "StateMachines/Printing/printingSTM.h"

#include "drivers/I2C_Communication/ADC_MUX/ADC_MUX.h"
#include "drivers/I2C_Communication/Dispenser_Card/IO_Ports/Dispenser_IO.h"

#include "drivers/FPGA/FPGA_GPIO/FPGA_GPIO.h"
#include "drivers/FPGA/FPGA_SPI_Comm.h"
#include "drivers/Motors/Motor.h"
#include "drivers/Valves/Valve.h"
#include "Modules/AlarmHandling/AlarmHandling.h"


FPGA_GPI_ENUM     Dispenser_Id_to_LS_Id[MAX_SYSTEM_DISPENSERS] = {
      GPI_LS_DISPENSER_DOWN_1, //MOTO_DISPENSER_1 = 6,
      GPI_LS_DISPENSER_DOWN_2, //MOTO_DISPENSER_2 = 7,
      GPI_LS_DISPENSER_DOWN_3, //MOTO_DISPENSER_3 = 8,
      GPI_LS_DISPENSER_DOWN_4, //MOTO_DISPENSER_4 = 9,
      GPI_LS_DISPENSER_DOWN_5, //MOTO_DISPENSER_5 = 10,
      GPI_LS_DISPENSER_DOWN_6, //MOTO_DISPENSER_6 = 11,
      GPI_LS_DISPENSER_DOWN_7, //MOTO_DISPENSER_7 = 12,
      GPI_LS_DISPENSER_DOWN_8, //MOTO_DISPENSER_8 = 13,
};
FPGA_GPI_ENUM     Dispenser_Id_to_LS_Empty_Id[MAX_SYSTEM_DISPENSERS] = {
      GPI_LS_DISPENSER_UP_1, //MOTO_DISPENSER_1 = 6,
      GPI_LS_DISPENSER_UP_2, //MOTO_DISPENSER_2 = 7,
      GPI_LS_DISPENSER_UP_3, //MOTO_DISPENSER_3 = 8,
      GPI_LS_DISPENSER_UP_4, //MOTO_DISPENSER_4 = 9,
      GPI_LS_DISPENSER_UP_5, //MOTO_DISPENSER_5 = 10,
      GPI_LS_DISPENSER_UP_6, //MOTO_DISPENSER_6 = 11,
      GPI_LS_DISPENSER_UP_7, //MOTO_DISPENSER_7 = 12,
      GPI_LS_DISPENSER_UP_8, //MOTO_DISPENSER_8 = 13,
};
FPGA_GPI_ENUM     Dispenser_Id_to_Alarm_LS_Id[MAX_SYSTEM_DISPENSERS*2] = {
      GPI_LS_DISPENSER_UP_1, //MOTO_DISPENSER_1 = 6,
      GPI_LS_DISPENSER_UP_2, //MOTO_DISPENSER_2 = 7,
      GPI_LS_DISPENSER_UP_3, //MOTO_DISPENSER_3 = 8,
      GPI_LS_DISPENSER_UP_4, //MOTO_DISPENSER_4 = 9,
      GPI_LS_DISPENSER_UP_5, //MOTO_DISPENSER_5 = 10,
      GPI_LS_DISPENSER_UP_6, //MOTO_DISPENSER_6 = 11,
      GPI_LS_DISPENSER_UP_7, //MOTO_DISPENSER_7 = 12,
      GPI_LS_DISPENSER_UP_8, //MOTO_DISPENSER_8 = 13,
      GPI_LS_DISPENSER_25_1, //MOTO_DISPENSER_1 = 6,
      GPI_LS_DISPENSER_25_2, //MOTO_DISPENSER_2 = 7,
      GPI_LS_DISPENSER_25_3, //MOTO_DISPENSER_3 = 8,
      GPI_LS_DISPENSER_25_4, //MOTO_DISPENSER_4 = 9,
      GPI_LS_DISPENSER_25_5, //MOTO_DISPENSER_5 = 10,
      GPI_LS_DISPENSER_25_6, //MOTO_DISPENSER_6 = 11,
      GPI_LS_DISPENSER_25_7, //MOTO_DISPENSER_7 = 12,
      GPI_LS_DISPENSER_25_8, //MOTO_DISPENSER_8 = 13,
};
callback_fptr HomingRequestCallback[MAX_SYSTEM_DISPENSERS]={0,0,0,0,0,0,0,0};
callback_fptr HomingBacklashCallback[MAX_SYSTEM_DISPENSERS]={0,0,0,0,0,0,0,0};
uint32_t HomingBacklashTimeout[MAX_SYSTEM_DISPENSERS];
uint32_t HomingBacklashTime[MAX_SYSTEM_DISPENSERS];

int32_t KeepMicrostep[MAX_SYSTEM_DISPENSERS];

bool HomingActive[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false};
bool PrimingActive[MAX_SYSTEM_DISPENSERS] = {false,false,false,false,false,false,false,false};
uint32_t DispenserHomingControlId[MAX_SYSTEM_DISPENSERS] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint32_t DispenserBacklashControlId[MAX_SYSTEM_DISPENSERS] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint32_t DispenserHomingTime[MAX_SYSTEM_DISPENSERS] = {0,0,0,0,0,0,0,0};
#define INITIAL_DISPENSER_PRESSURE 3.85
#define INITIAL_DISPENSER_TIMEOUT_LIMIT 120000
#define INITIAL_DISPENSER_TIMEOUT 100
#define INITIAL_DISPENSER_SPEED 1000

double   InitialDispenserPressure = INITIAL_DISPENSER_PRESSURE;
uint32_t InitialDispenserTimeout = INITIAL_DISPENSER_TIMEOUT_LIMIT;
uint32_t InitialDispenserTimeLag = INITIAL_DISPENSER_TIMEOUT;
uint32_t InitialDispenserSpeed = INITIAL_DISPENSER_SPEED;

uint32_t    ControlIdtoInactiveDispenserId [MAX_SYSTEM_DISPENSERS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

//uint32_t IDS_StopHomeDispenserBuildPressure (uint32_t deviceID);

AutoHoming_Config_enum AutoHoming_Config = AutoHoming_off;
void IDS_Dispenser_SetAutoHoming_Config(AutoHoming_Config_enum Config)
{
    ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_SetAutoHoming_Config ",__FILE__,__LINE__,Config,RpWarning,AutoHoming_Config,0);
    if (Special_Dispensers == false)
    {
        AutoHoming_Config = Config;
    }
    else
    {
        AutoHoming_Config = AutoHoming_off;
    }
#ifdef DISPESER_TEST
    AutoHoming_Config = AutoHoming_off;
#endif
}

void IDS_Dispenser_SetBackLashValues(double   initialdispenserpressure,   uint32_t initialdispensertimeout,   uint32_t initialdispensertimelag,   uint32_t initialdispenserspeed)
{
    //if (initialdispenserpressure>2)
        InitialDispenserPressure = initialdispenserpressure;
    //if (initialdispensertimeout>70000)
        InitialDispenserTimeout = initialdispensertimeout;
    InitialDispenserTimeLag = initialdispensertimelag;
    InitialDispenserSpeed = initialdispenserspeed;

    ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_SetBackLashValues ",__FILE__,InitialDispenserPressure*100,InitialDispenserTimeout,RpWarning,(int)InitialDispenserTimeLag,0);
}
uint32_t IDS_HomeDispenserWaitForHomingEndCallback(uint32_t DispenserId, uint32_t ReadValue)
{
    HomingBacklashTime[DispenserId]+=eOneSecond;
    if (( HomingActive[DispenserId]== false) ||((HomingBacklashTime[DispenserId]>=HomingBacklashTimeout[DispenserId])&&(HomingBacklashTimeout[DispenserId]>0)))
       {
           //stop this control loop
           SafeRemoveControlCallback(DispenserBacklashControlId[DispenserId], IDS_HomeDispenserWaitForHomingEndCallback );
           DispenserBacklashControlId[DispenserId] = 0xFF;

           if (HomingBacklashCallback[DispenserId])
           {
               if ( HomingActive[DispenserId]== false)
                   HomingBacklashCallback[DispenserId](DispenserId,OK);
               else
                   HomingBacklashCallback[DispenserId](DispenserId,ERROR);
           }
           HomingBacklashCallback[DispenserId] = 0;
       }
    return OK;
}
uint32_t IDS_HomeDispenserWaitForHomingEnd(uint32_t DispenserId,  uint32_t timeout , callback_fptr callback)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);

    if (HomingBacklashCallback[DispenserId]!=NULL)
        return ERROR;
    HomingBacklashCallback[DispenserId] = callback;
    HomingBacklashTimeout[DispenserId] = timeout;
    HomingBacklashTime[DispenserId] = 0;

    if (DispenserBacklashControlId[DispenserId] != 0xFF)
    {
        RemoveControlCallback(DispenserBacklashControlId[DispenserId], IDS_HomeDispenserWaitForHomingEndCallback );
        DispenserBacklashControlId[DispenserId] = 0xFF;
        //return ERROR;
    }
    DispenserBacklashControlId[DispenserId] = AddControlCallback("Wait for Homing", IDS_HomeDispenserWaitForHomingEnd,eOneSecond , TemplateDataReadCBFunction,DispenserId,0, 0 );
    if ( DispenserBacklashControlId[DispenserId] == 0xFF)
        return ERROR;

    return OK;
}

/*uint32_t IDS_HomeDispenserBackMoveCallback(uint32_t motorId, uint32_t ReadValue)
{
    uint8_t DispenserId = motorId-HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1;
    if ((GetDispenserPressure(DispenserId)>=InitialDispenserPressure)||(DispenserHomingTime[DispenserId]>InitialDispenserTimeout))
    {
        MotorStop(motorId,Hard_Hiz);
        CurrentDispenserSpeed[DispenserId] = 0;
        if (Extended_Motor_Param == true)
            Power_Step_01_Dispenser_Mode(DispenserId,Voltage);
        //MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
        HomingActive[DispenserId]= false;
        PrimingActive[DispenserId]= false;
        Control_TCA9534ByPass(DispenserId,DISABLE);// use ENABLE or DISABLE

        //close dry air valve in the dispenser
        Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
        Disable_MidTank_Pressure_Reading(DispenserId);

        ReportWithPackageFilter(IDSFilter,"End backlash",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)DispenserHomingTime[DispenserId],0);
        if (SafeRemoveControlCallback(DispenserHomingControlId[DispenserId], IDS_HomeDispenserBackMoveCallback )==OK)
            DispenserHomingControlId[DispenserId] = 0xFF;
        else
            ReportWithPackageFilter(IDSFilter,"Remove control callback failed",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)DispenserHomingControlId[DispenserId],0);
        DispenserHomingTime[DispenserId]=0;
    }
    else
    {
        DispenserHomingTime[DispenserId]+=InitialDispenserTimeLag;
    }
    return OK;
}*/
uint32_t IDS_HomeDispenserCallback(uint32_t motorId, uint32_t ReadValue)
{
    uint8_t DispenserId = motorId-HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1;

    Read_MidTank_Pressure_Sensor(DispenserId);
    //close dry air valve in the dispenser
    //Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    //Disable_MidTank_Pressure_Reading(DispenserId);
    //    MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
    if (HomingRequestCallback[DispenserId])
    {
        HomingRequestCallback[DispenserId](DispenserId,0);
        HomingRequestCallback[DispenserId] = NULL;
    }
//    HomingActive[DispenserId]= false;
    IDS_Dispenser_RefillEnded ( DispenserId, MotorsCfg[motorId].microstep);
    ReportWithPackageFilter(IDSFilter,"Homing ended",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)DispenserHomingTime[DispenserId],0);
//    DispenserHomingControlId[DispenserId] = AddControlCallback( IDS_HomeDispenserBackMoveCallback, InitialDispenserTimeLag, GetDispenserPressure,motorId, motorId, 0 );
    MotorSetDirection(motorId,MotorsCfg[motorId].directionthreadwize);
    Task_sleep(10);
//    MotorSetSpeed(motorId, InitialDispenserSpeed);
    CurrentDispenserSpeed[DispenserId] = 0;
/////////////////////////////////////////////////////////////
    if (Extended_Motor_Param[motorId] == true)
        Power_Step_01_Dispenser_Mode(DispenserId,Voltage);
    //MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
    HomingActive[DispenserId]= false;
    PrimingActive[DispenserId]= false;
    Control_TCA9534ByPass(DispenserId,DISABLE);// use ENABLE or DISABLE
#ifdef DISPENSER_VALVES_OPEN
    if (JobIsActive()==false)
        Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
#endif

    //close dry air valve in the dispenser
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    Disable_MidTank_Pressure_Reading(DispenserId);

    ////////////////////////////////////////////////////////
    return OK;
}
bool     IDS_IsHomingActive(uint32_t DispenserId)
{
    return HomingActive[DispenserId];
}
uint32_t IDS_HomeDispenser (uint32_t DispenserId, uint32_t speed , callback_fptr callback)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);
    TimerMotors_t MotorId = HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1 + DispenserId;
    //if (DispensersAlarmState[DispenserId] == true)
    //    return ERROR;

    double midTankContent = 0.0;
    if (isMotorConfigured(MotorId)==false)
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Disp not in config",__FILE__,Dispenser_Id_to_LS_Id[DispenserId],(int)DispenserId,RpWarning,LIMIT,0);
        return ERROR;
    }
    if (FPGA_Read_limit_Switches(Dispenser_Id_to_LS_Id[DispenserId]) == LIMIT)
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Disp is full",__FILE__,Dispenser_Id_to_LS_Id[DispenserId],(int)DispenserId,RpWarning,LIMIT,0);
        return ERROR;
    }
    if (Get_MidTank_Pressure_Sensor(DispenserId)<0.2)
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Midtank is empty",__FILE__,Get_MidTank_Int1000_Sensor(DispenserId),(int)DispenserId,RpWarning,LIMIT,0);
        return ERROR;
    }
    midTankContent = Read_MidTank_Pressure_Sensor(DispenserId);
    if (midTankContent < 0.2) //midtank is empty - abort!!!!
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Mid Tank Empty!!! ",__FILE__,__LINE__,(int)(midTankContent * 1000),RpWarning,DispenserId,0);
        return ERROR;
    }
    //if Safety is active
        //if safety is upper position or
    if ((HomingActive[DispenserId] == true)||(PrimingActive[DispenserId] == true))
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Homing/priming already active",__FILE__,HomingActive[DispenserId],(int)DispenserId,RpWarning,PrimingActive[DispenserId],0);
        return ERROR;
    }

    if (Check_Disp_Safety_Stop_Indication(DispenserId) == true)
    {
        if ((Get_Notification_Disp_UP(DispenserId) == false)||(Get_Notification_Over_Press(DispenserId) == false))
        {
            ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Bypassing safety",__FILE__,HomingActive[DispenserId],(int)DispenserId,RpWarning,PrimingActive[DispenserId],0);
            Control_TCA9534ByPass(DispenserId,ENABLE);// use ENABLE or DISABLE
        }
    }
    HomingRequestCallback[DispenserId] = callback;

    if ( Dispenser_Id_to_LS_Id[DispenserId] != MAX_GPI)
    {
        HomingActive[DispenserId] = true;
        //open dispenser valve dispenser to midtank direction
        Control3WayValvesWithCallback ((Valves_t)DispenserId, MidTank_Dispenser, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
        if (Extended_Motor_Param[MotorId] == true)
            Power_Step_01_Dispenser_Mode(DispenserId,Current);
        KeepMicrostep[DispenserId] = MotorsCfg[MotorId].microstep;
        //MotorSetMicroStep(MotorId, 1);
        //open dry air valve in the dispenser
        Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_ON);
        Enable_MidTank_Pressure_Reading(DispenserId);

        IDS_Dispenser_RefillStarted(DispenserId,1);
        if (DispenserId== LUBRICANT_DISPENSER)
        {
            MotorMovetoLimitSwitch (MotorId,1-MotorsCfg[MotorId].directionthreadwize, speed/4,  Dispenser_Id_to_LS_Id[DispenserId], IDS_HomeDispenserCallback,0);
            CurrentDispenserSpeed[DispenserId] = speed/4;
            ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser ",__FILE__,(int)(midTankContent*1000),(int)DispenserId,RpWarning,speed/4,0);
        }
        else
        {
            MotorMovetoLimitSwitch (MotorId,1-MotorsCfg[MotorId].directionthreadwize, speed,  Dispenser_Id_to_LS_Id[DispenserId], IDS_HomeDispenserCallback,0);
            CurrentDispenserSpeed[DispenserId] = speed;
            ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser ",__FILE__,(int)(midTankContent*1000),(int)DispenserId,RpWarning,speed,0);
        }
        CurrentDispenserSpeed[DispenserId] = (-1*CurrentDispenserSpeed[DispenserId]);
        DispenserLastMovementDown[DispenserId] = true;

        return OK;
    }
    return ERROR;
}
uint32_t IDS_StopHomeDispenser (uint32_t DispenserId)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);

    ReportWithPackageFilter(IDSFilter,"IDS_StopHomeDispenser",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)HomingActive[DispenserId],0);
    if ((HomingActive[DispenserId] == false)&&( PrimingActive[DispenserId] == false))
    {
        ReportWithPackageFilter(IDSFilter,"Homing not active",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)HomingActive[DispenserId],0);
        return OK;
    }

    TimerMotors_t MotorId = (DispenserId)+HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1;
    MotorAbortMovetoLimitSwitch(MotorId);
    //close dry air valve in the dispenser
    Disable_MidTank_Pressure_Reading(DispenserId);
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    Control3WayValvesWithCallback ((Valves_t)DispenserId, MidTank_Dispenser, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer

/*    if (HomingActive[DispenserId] == true)
    {
        IDS_StopHomeDispenserBuildPressure(DispenserId);
    }*/
    if (HomingActive[DispenserId] == true)
    {
        if (DispenserId == LUBRICANT_DISPENSER)
        {
            Lubricant_2Way_Valve (STOP);
        }
    }
    HomingActive[DispenserId] = false;
    PrimingActive[DispenserId] = false;
    Control_TCA9534ByPass(DispenserId,DISABLE);// use ENABLE or DISABLE
#ifdef DISPENSER_VALVES_OPEN
    if (JobIsActive()==false)
        Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
#endif
    if (Extended_Motor_Param[MotorId] == true)
        Power_Step_01_Dispenser_Mode(DispenserId,Voltage);
    //MotorSetMicroStep(MotorId, KeepMicrostep[DispenserId]);
    CurrentDispenserSpeed[DispenserId] = 0;
    return OK;
}
/*
uint32_t IDS_StopHomeDispenserBuildPressure (uint32_t DispenserId)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);

    ReportWithPackageFilter(IDSFilter,"IDS_StopHomeDispenser and build pressure",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)HomingActive[DispenserId],0);
    if (HomingActive[DispenserId] != true)
    {
        ReportWithPackageFilter(IDSFilter,"Homing not active",__FILE__,__LINE__,(int)DispenserId,RpWarning,(int)HomingActive[DispenserId],0);
        return ERROR;
    }
    else
        HomingActive[DispenserId] = false;
    Control_TCA9534ByPass(DispenserId,DISABLE);// use ENABLE or DISABLE

    TimerMotors_t motorId = (DispenserId)+HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1;
    MotorAbortMovetoLimitSwitch(motorId);
    //close dry air valve in the dispenser
//////////////////////////////////////////////////
    Read_MidTank_Pressure_Sensor(DispenserId);
    //close dry air valve in the dispenser
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    Disable_MidTank_Pressure_Reading(DispenserId);
    //    MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
    if (HomingRequestCallback[DispenserId])
    {
        HomingRequestCallback[DispenserId](DispenserId,0);
        HomingRequestCallback[DispenserId] = NULL;
    }
//    HomingActive[DispenserId]= false;
      ReportWithPackageFilter(IDSFilter,"End homing for job start",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)DispenserHomingTime[DispenserId],0);
  /`*  else
    {
        ReportWithPackageFilter(IDSFilter,"homing aborted,start backlash",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)DispenserHomingTime[DispenserId],0);
        DispenserHomingControlId[DispenserId] = AddControlCallback( IDS_HomeDispenserBackMoveCallback, InitialDispenserTimeLag, GetDispenserPressure,motorId, motorId, 0 );
        Task_sleep(10);
        MotorSetDirection(motorId,MotorsCfg[motorId].directionthreadwize);
        Task_sleep(10);
        MotorSetSpeed(motorId, 1000);
        CurrentDispenserSpeed[DispenserId] = 1000;
    }*`/
    //IDS_Dispenser_RefillEnded ( DispenserId, MotorsCfg[motorId].microstep);

    return OK;
}
*/
uint32_t IDS_CheckDispenserLimitSwitch (LimitSwitchAlarms LS_Id)
{
    int DispenserId;
    if (LS_Id <= LimitSwitchAlarmEmpty_8)
    {
        DispenserId = LS_Id;
    }
    else
    {
        DispenserId = LS_Id-LimitSwitchAlarmEmpty_8;
    }
    if (isMotorConfigured(DispenserId + HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1)==false)
        return true;  //false is the alarm value
    else
        return FPGA_Read_limit_Switches(Dispenser_Id_to_Alarm_LS_Id[LS_Id]);
}
uint32_t IDS_EmptyDispenserCallback(uint32_t motorId, uint32_t ReadValue)
{
    uint8_t DispenserId = motorId-HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1;

    Read_MidTank_Pressure_Sensor(DispenserId);
    //close dry air valve in the dispenser
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    Disable_MidTank_Pressure_Reading(DispenserId);

    MotorStop(motorId,Hard_Hiz);
    CurrentDispenserSpeed[DispenserId] = 0;
    if (Extended_Motor_Param[motorId] == true)
        Power_Step_01_Dispenser_Mode(DispenserId,Voltage);
    //MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
    PrimingActive[DispenserId]= false;
    Control_TCA9534ByPass(DispenserId,DISABLE);// use ENABLE or DISABLE
    if (DispenserId == LUBRICANT_DISPENSER)
    {
        Lubricant_2Way_Valve (STOP);
    }
    ReportWithPackageFilter(IDSFilter,"End Priming",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,(int)DispenserHomingTime[DispenserId],0);
    //    MotorSetMicroStep(motorId, KeepMicrostep[DispenserId]);
    if (HomingRequestCallback[DispenserId])
    {
        HomingRequestCallback[DispenserId](DispenserId,0);
        HomingRequestCallback[DispenserId] = NULL;
    }
    return OK;
}

uint32_t IDS_EmptyDispenser (uint32_t DispenserId, uint32_t speed , callback_fptr callback)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);

    //if (DispensersAlarmState[DispenserId] == true)
    //    return ERROR;
    if ((HomingActive[DispenserId] == true)||(PrimingActive[DispenserId] == true))
    {
        ReportWithPackageFilter(IDSFilter,"IDS_HomeDispenser - Homing/priming already active",__FILE__,HomingActive[DispenserId],(int)DispenserId,RpWarning,PrimingActive[DispenserId],0);
        return ERROR;
    }
    if (Check_Disp_Safety_Stop_Indication(DispenserId) == true)
    {
        if ((Get_Notification_Disp_Down(DispenserId) == false)||(Get_Notification_Over_Press(DispenserId) == false))
        {
            ReportWithPackageFilter(IDSFilter,"IDS_EmptyDispenser - Bypassing safety",__FILE__,HomingActive[DispenserId],(int)DispenserId,RpWarning,PrimingActive[DispenserId],0);
            Control_TCA9534ByPass(DispenserId,ENABLE);// use ENABLE or DISABLE
        }
    }
    TimerMotors_t MotorId = HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1 + DispenserId;
    if ( Dispenser_Id_to_LS_Empty_Id[DispenserId] != MAX_GPI)
    {
        PrimingActive[DispenserId] = true;
        HomingRequestCallback[DispenserId] = callback;
        //open dispenser valve dispenser to midtank direction
        Control3WayValvesWithCallback ((Valves_t)DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
        if (Extended_Motor_Param[MotorId] == true)
            Power_Step_01_Dispenser_Mode(DispenserId,Current);
        //Valve_Set((Valves_t) request->index, Dispenser_Mixer);
        KeepMicrostep[DispenserId] = MotorsCfg[MotorId].microstep;
        //MotorSetMicroStep(MotorId, 1);
        Task_sleep(100);
        //open dry air valve in the dispenser
        //Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_ON);
        if (DispenserId == LUBRICANT_DISPENSER)
        {
            Lubricant_2Way_Valve (START);
        }
        MotorMovetoLimitSwitch (MotorId,MotorsCfg[MotorId].directionthreadwize, speed,  Dispenser_Id_to_LS_Empty_Id[DispenserId], IDS_EmptyDispenserCallback,0);
        CurrentDispenserSpeed[DispenserId] = speed;
        return OK;
    }
    return ERROR;
}
uint32_t IDS_Dispenser_Alarm_On (uint8_t DispenserId)
{
    uint32_t status = OK;
    ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_Alarm_On",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,0,0);
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);
    DispensersAlarmState[DispenserId] = true;
    TimerMotors_t MotorId = HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1 + DispenserId;
    status |= MotorAbortMovetoLimitSwitch(MotorId);
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
    Disable_MidTank_Pressure_Reading(DispenserId);
    if (Extended_Motor_Param[MotorId] == true)
        Power_Step_01_Dispenser_Mode(DispenserId,Voltage);
    //status |= MotorSetMicroStep(MotorId, KeepMicrostep[DispenserId]);
    status |= MotorStop(MotorId, Hard_Hiz);
    IDS_Dispenser_Init(DispenserId);
    JobEndReason = JOB_OUT_OF_DYE;
    usnprintf(AlarmReasonStr, 100, "IDS_Dispenser_Alarm_On %d ",DispenserId);
    return status;
}
uint32_t IDS_Dispenser_Alarm_Off (uint8_t DispenserId)
{
    uint32_t status = OK;
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);
    DispensersAlarmState[DispenserId] = false;
    ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_Alarm_Off",__FILE__,millisecondCounter,(int)DispenserId,RpWarning,0,0);
    return status;
}
uint32_t IDS_ReCheck_Pressure_Callback(uint32_t DispenserId, uint32_t ReadValue)
{
    ReportWithPackageFilter(IDSFilter,"Pulling dispenser down result",__FILE__,DispenserId,(int)(GetDispenserPressure(DispenserId)*100),RpWarning,200,0);
    SafeRemoveControlCallback(GetControlLowDevice_i(), IDS_ReCheck_Pressure_Callback );

    return OK;
}
bool Check_Pressure_Bypass = false;
bool Set_Check_Pressure_Bypass (int value)
{
    if (value == 0)
        Check_Pressure_Bypass = false;
    else
        Check_Pressure_Bypass = true;
    return Check_Pressure_Bypass;
}
uint32_t IDS_Check_Pressure_Callback(uint32_t DispenserId, uint32_t ReadValue)
{
    TimerMotors_t  HW_Motor_Id = DispenserIdToMotorId[DispenserId];
    if (JobIsActive())
    {
        if (DispenserUsedInJob[DispenserId] == true)
        {
            return ERROR;
        }
    }
    if (Check_Pressure_Bypass == true)
        return OK;

    if (GetDispenserPressure(DispenserId)>3.0)
    {
        //10/8/2020 pulling down 2000 steps
        ReportWithPackageFilter(IDSFilter,"Pulling dispenser down to reduce pressure",__FILE__,DispenserId,(int)(GetDispenserPressure(DispenserId)*100),RpWarning,2000,0);
        if ((HomingActive[DispenserId] == true)||(PrimingActive[DispenserId] == true))
        {
            ReportWithPackageFilter(IDSFilter,"Dispenser in pressure but homing active",__FILE__,DispenserId,(int)HomingActive[DispenserId],RpWarning,PrimingActive[DispenserId],0);
            return ERROR;
        }
        if (GetDispenserPressure(DispenserId)>5.5)
        {
            //stop job on pressure rise above 5.5 bar
            IDS_Dispenser_Alarm_On(DispenserId);
            //open valve toward mixer on pressure rise above 5.5 bar
            Task_sleep(100);
            Control3WayValvesWithCallback ((Valves_t)DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
        }
        MotorMove(HW_Motor_Id,1-MotorsCfg[HW_Motor_Id].directionthreadwize,2000*MotorsCfg[HW_Motor_Id].microstep);
        AddControlCallback("IDS_ReCheck_Pressure", IDS_ReCheck_Pressure_Callback, eOneSecond*4,TemplateDataReadCBFunction ,DispenserId, 0, 0 );
    }
    return OK;
}


void IDS_Dispenser_Init(uint8_t DispenserId)
{
    assert(DispenserId < MAX_SYSTEM_DISPENSERS);
    ReportWithPackageFilter(IDSFilter,"IDS_Dispenser_Init",__FILE__,DispenserId,HomingActive[DispenserId],RpWarning,PrimingActive[DispenserId],0);
    CurrentDispenserSpeed[DispenserId] = 0;
    HomingActive[DispenserId]= false;
    PrimingActive[DispenserId]= false;
    Valve_Set(IDS_Id_to_AirValve[DispenserId], Atm_MidTank_OFF);
/*#ifdef DISPENSER_VALVES_OPEN
    Control3WayValvesWithCallback (DispenserId, Dispenser_Mixer, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
#else
    Control3WayValvesWithCallback ((Valves_t)DispenserId, MidTank_Dispenser, NULL); //direction: MidTank_Dispenser or Dispenser_Mixer
#endif*/
    //if (Special_Dispensers == true)
    {
        if (ControlIdtoInactiveDispenserId[DispenserId] == 0xFF)
            ControlIdtoInactiveDispenserId[DispenserId] = AddControlCallback("IDS_Check_Pressure", IDS_Check_Pressure_Callback, eOneMinute,TemplateDataReadCBFunction ,DispenserId, 0, 0 );
    }
}