/* * Valve.c * * Created on: Apr 29, 2018 * Author: avi * The timing of the pulse to the relay is done by the FPGA. * In order to know when the pulse is done you have a set of registers/interrupts called F2_DISPENSER_VALVE_IN*. * The busy bit indicates that a pulse duration is in - duration */ #include #include "include.h" #include #include #include "drivers/FPGA/FPGA_Comm.h" #include #include "Drivers/I2C_Communication/Head_Card/IO_Ports/Head_IO.h" #include #include "Modules/IFS/ifs.h" #include "Modules/Control/Control.h" VALVE_GPO_REG Valve_GPO_Reg; extern F1_GPO_REG F1_GPO_Reg; DISPENSER_VALVE_GPO_REG Dispenser_Valve_GPO_Reg; extern F3_GPO_01_REG F3_GPO_01_Reg; Valves_t IDS_Id_to_AirValve[MAX_IDS_UNITS] = {VALVE_2W_MID_AIR_1,VALVE_2W_MID_AIR_2,VALVE_2W_MID_AIR_3,VALVE_2W_MID_AIR_4,VALVE_2W_MID_AIR_5,VALVE_2W_MID_AIR_6,VALVE_2W_MID_AIR_7,VALVE_2W_MID_AIR_8}; Valves_t IDS_Id_to_CartrideValve[MAX_IDS_UNITS] = {VALVE_2W_CART_MID_1,VALVE_2W_CART_MID_2,VALVE_2W_CART_MID_3,VALVE_2W_CART_MID_4,VALVE_2W_CART_MID_5,VALVE_2W_CART_MID_6,VALVE_2W_CART_MID_7,VALVE_2W_CART_MID_8}; typedef struct { //bool EnableDisable; //TODO - to check if needed bool Direction; bool Busy; }ValveRequestStruct; typedef struct { //bool Direction;//TODO - to check if needed bool Busy; bool OCD; //Over Current Detection }ValveResponseStruct; ValveRequestStruct ValveRequest[NUM_OF_VALVES]; ValveResponseStruct ValveRsponse[NUM_OF_VALVES]; typedef enum { IfValvesTypeNone, IfTypeMidTankToManif, IfTypeCartToMidTank, IfTypeWasteTank, IfTypeMixchipWastech, IfTypeDisopenser, MAX_INTERFACE_VALVES_TYPES }SYSTEM_INTERFACE_VALVES_TYPES_ID_ENUM; callback_fptr Valve3WayModuleCallback[MAX_SYSTEM_DISPENSERS] = {0, 0, 0, 0, 0, 0, 0, 0,}; uint32_t Valve3WayControlId[MAX_SYSTEM_DISPENSERS] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bool Validate_Valve(Valves_t Valve_Id) { int MidTankId; if (ValveRequest[Valve_Id].Direction == 1) //opening always allowed return true; if (Valve_Id > VALVE_2W_MID_AIR_1)//dispenser valves return true; if (Valve_Id < VALVE_2W_MID_AIR_8)//cartridge valves return true; if (IFS_MidTankFilling() == false) //no ongoing filling process return true; switch (Valve_Id) { case VALVE_2W_MID_AIR_1: MidTankId = 0; break; case VALVE_2W_MID_AIR_2: MidTankId = 1; break; case VALVE_2W_MID_AIR_3: MidTankId = 2; break; case VALVE_2W_MID_AIR_4: MidTankId = 3; break; case VALVE_2W_MID_AIR_5: MidTankId = 4; break; case VALVE_2W_MID_AIR_6: MidTankId = 5; break; case VALVE_2W_MID_AIR_7: MidTankId = 6; break; case VALVE_2W_MID_AIR_8: MidTankId = 7; break; default: return true; } if (MidTankId == IFS_MidTankIsActive()) { Report("Valve shutdown while ink filling is active - cancelled",__FILE__,__LINE__,(int)Valve_Id,RpWarning,(int)MidTankId,0); return false; } return true; } bool IgnoreMidTank = false; #ifdef MIDTANK_MITIGATION bool MidTankMitigation = false; int MidTankMitigationOn = 20,MidTankMitigationOff = 10; uint32_t MidtankMitigationControlId[NUM_OF_VALVES] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; uint16_t MidtankMitigationCounter[NUM_OF_VALVES]; uint32_t ValveCallback(uint32_t deviceID, uint32_t ReadValue) { int Valve_Id = deviceID; MidtankMitigationCounter[deviceID]++; if (MidtankMitigationCounter[deviceID] > MidTankMitigationOn ) { if (MidtankMitigationCounter[deviceID] > 1000 )//2 seconds { Report("ValveCallback truning off first time",__FILE__,MidtankMitigationCounter[deviceID],(int)Valve_Id,RpWarning,(int)deviceID,0); MidtankMitigationCounter[deviceID] = 0; ValveRequest[Valve_Id].Direction = false; Valve_Command( Valve_Id); } } else { if (MidtankMitigationCounter[deviceID] == MidTankMitigationOff ) { Report("ValveCallback truning on",__FILE__,MidtankMitigationCounter[deviceID],(int)Valve_Id,RpWarning,(int)deviceID,0); ValveRequest[Valve_Id].Direction = true; Valve_Command( Valve_Id); } if (MidtankMitigationCounter[deviceID] == MidTankMitigationOn ) { Report("ValveCallback truning off",__FILE__,MidtankMitigationCounter[deviceID],(int)Valve_Id,RpWarning,(int)deviceID,0); ValveRequest[Valve_Id].Direction = false; Valve_Command( Valve_Id); MidtankMitigationCounter[deviceID] = 0; } } return OK; } #endif void Valve_Command(Valves_t Valve_Id) //1 - OPEN, 0 - CLOSE { if (Validate_Valve(Valve_Id) == false) { Report("Valve shutdown while ink filling is active - cancelled",__FILE__,__LINE__,(int)Valve_Id,RpWarning,(int)ValveRequest[Valve_Id].Direction,0); return; } #ifdef EVALUATION_BOARD return ; #endif switch(Valve_Id) { //Dry air Valves case VALVE_2W_MID_AIR_8: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_8 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_4: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_4 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_7: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_7 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_3: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_3 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_6: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_6 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_2: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_2 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_5: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_5 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_MID_AIR_1: Valve_GPO_Reg.bits.VALVE_2W_MID_AIR_1 = ValveRequest[Valve_Id].Direction; break; //Dispenser Valves case VALVE_2W_CART_MID_8: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_8 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_4: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_4 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_7: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_7 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_3: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_3 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_6: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_6 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_2: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_2 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_5: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_5 = ValveRequest[Valve_Id].Direction; break; case VALVE_2W_CART_MID_1: Valve_GPO_Reg.bits.VALVE_2W_CART_MID_1 = ValveRequest[Valve_Id].Direction; break; // Waste Valves case VALVE_WASTE_TANK: F1_GPO_Reg.bits.F1_VALVE_WASTE_TANK = ValveRequest[Valve_Id].Direction; break; case VALVE_MIXCHIP_WASTECH: if(Head_Type > HEAD_TYPE_FLAT_WITHOUT_CARD) Trigger_Head_MixerValve(ValveRequest[Valve_Id].Direction); else F1_GPO_Reg.bits.F1_VALVE_MIXCHIP_WASTECH = ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_1: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_1_C2_1 = ValveRequest[Valve_Id].Direction; REPORT_MSG(ValveRequest[Valve_Id].Direction,"Dispenser 1 Set valve direction"); break; case VALVE_DISPENSER_2: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_2_C2_2= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_3: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_3_C2_3= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_4: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_4_C2_4= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_5: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_5_C2_5= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_6: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_6_C2_6= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_7: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_7_C2_7= ValveRequest[Valve_Id].Direction; break; case VALVE_DISPENSER_8: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_C1_8_C2_8= ValveRequest[Valve_Id].Direction; REPORT_MSG(ValveRequest[Valve_Id].Direction,"Dispenser 8 Set valve direction"); break; default: break; } if ((Valve_Id == VALVE_WASTE_TANK) | (Valve_Id == VALVE_MIXCHIP_WASTECH)) // Waste Valves { F1_gpo_01 = F1_GPO_Reg.ushort; } else if(/*(Valve_Id >= VALVE_DISPENSER_1) |*/ (Valve_Id <= VALVE_DISPENSER_8)) { F2_DISPENSER_VALVE_OUT = Dispenser_Valve_GPO_Reg.ushort; } else F3_VALVE_OUT = Valve_GPO_Reg.ushort; } void SetAllDispensersValves(bool Direction) { if(Direction == MIDTANK_DIRECTION) { //F3_VALVE_OUT = 0; F2_DISPENSER_VALVE_OUT &= ~MASK_LOW_BYTE_IN_WORD; } else // MIXER_DIRECTION { //F3_VALVE_OUT = 0xFFFF; F2_DISPENSER_VALVE_OUT |= MASK_LOW_BYTE_IN_WORD; } } uint32_t FPGA_GetDispenserValveBusyOCD(uint32_t ValveId, uint32_t dummy) // MillisecLoop { //Valves_t Valve = ValveId; if (ValveId > VALVE_DISPENSER_8) return ERROR; #ifdef EVALUATION_BOARD return OK; #endif VALVE_BUSY_REG Valve_Busy_Reg; Valve_Busy_Reg.ushort = F2_DISPENSER_VALVE_IN_Direct; switch(ValveId) { //Dispenser Valves case VALVE_DISPENSER_1: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_0; break; case VALVE_DISPENSER_2: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_1; break; case VALVE_DISPENSER_3: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_2; break; case VALVE_DISPENSER_4: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_3; break; case VALVE_DISPENSER_5: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_4; break; case VALVE_DISPENSER_6: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_5; break; case VALVE_DISPENSER_7: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_6; break; case VALVE_DISPENSER_8: ValveRsponse[ValveId].Busy = Valve_Busy_Reg.bits.Valve_busy_7; break; default: break; } return ValveRsponse[ValveId].Busy; } void FPGA_GetAllDispensersValveBusyOCD() // MillisecLoop { #ifndef EVALUATION_BOARD VALVE_BUSY_REG Valve_Busy_Reg; Valve_Busy_Reg.ushort = F2_DISPENSER_VALVE_IN_Direct; //Dispenser Valves ValveRsponse[VALVE_DISPENSER_1].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_1; ValveRsponse[VALVE_DISPENSER_1].Busy = Valve_Busy_Reg.bits.Valve_busy_0; ValveRsponse[VALVE_DISPENSER_2].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_2; ValveRsponse[VALVE_DISPENSER_2].Busy = Valve_Busy_Reg.bits.Valve_busy_1; ValveRsponse[VALVE_DISPENSER_3].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_3; ValveRsponse[VALVE_DISPENSER_3].Busy = Valve_Busy_Reg.bits.Valve_busy_2; ValveRsponse[VALVE_DISPENSER_4].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_4; ValveRsponse[VALVE_DISPENSER_4].Busy = Valve_Busy_Reg.bits.Valve_busy_3; ValveRsponse[VALVE_DISPENSER_5].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_5; ValveRsponse[VALVE_DISPENSER_5].Busy = Valve_Busy_Reg.bits.Valve_busy_4; ValveRsponse[VALVE_DISPENSER_6].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_6; ValveRsponse[VALVE_DISPENSER_6].Busy = Valve_Busy_Reg.bits.Valve_busy_5; ValveRsponse[VALVE_DISPENSER_7].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_7; ValveRsponse[VALVE_DISPENSER_7].Busy = Valve_Busy_Reg.bits.Valve_busy_6; ValveRsponse[VALVE_DISPENSER_8].OCD = Valve_Busy_Reg.bits.F2_DISPENSER_VALVE_OCD_8; ValveRsponse[VALVE_DISPENSER_8].Busy = Valve_Busy_Reg.bits.Valve_busy_7; #endif } void EnableDisableDispenserValve(Valves_t Valve_Id, bool EnableOrDisable ) { switch(Valve_Id) { case VALVE_DISPENSER_1: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_1 = EnableOrDisable; break; case VALVE_DISPENSER_2: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_2 = EnableOrDisable; break; case VALVE_DISPENSER_3: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_3 = EnableOrDisable; break; case VALVE_DISPENSER_4: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_4 = EnableOrDisable; break; case VALVE_DISPENSER_5: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_5 = EnableOrDisable; break; case VALVE_DISPENSER_6: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_6 = EnableOrDisable; break; case VALVE_DISPENSER_7: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_7 = EnableOrDisable; break; case VALVE_DISPENSER_8: Dispenser_Valve_GPO_Reg.bits.F2_DISPENSER_VALVE_EN_8 = EnableOrDisable; break; default: //TODO ERROR break; } #ifndef EVALUATION_BOARD F2_DISPENSER_VALVE_OUT = Dispenser_Valve_GPO_Reg.ushort; #endif } // void EnableDisableAllDispensersValves(bool EnableOrDisable ) { #ifndef EVALUATION_BOARD if(EnableOrDisable == ENABLE) { F2_DISPENSER_VALVE_OUT |= MASK_HIGH_BYTE_IN_WORD; } else { F2_DISPENSER_VALVE_OUT &= ~MASK_HIGH_BYTE_IN_WORD; } #endif } void Valve_Set(Valves_t Valve_Id, bool Direction) { #ifndef EVALUATION_BOARD if ((Valve_Id>=VALVE_2W_MID_AIR_8)&&(Valve_Id<=VALVE_2W_CART_MID_1)) { if (IgnoreMidTank == true) { Report("Mid Tank Valve command ignored - bypass",__FILE__,__LINE__,(int)Valve_Id,RpWarning,Direction,0); return; } #ifdef MIDTANK_MITIGATION if (MidTankMitigation == true) { Report("Mid Tank Valve command mitigation",__FILE__,Valve_Id,(int)Valve_Id,RpWarning,Direction,0); if (Direction == true) { //start s 2 seconds control, then according to the set values MidtankMitigationCounter[Valve_Id] = MidTankMitigationOn+1; MidtankMitigationControlId[Valve_Id] = AddControlCallback("Valve mitigation", ValveCallback, 2, TemplateDataReadCBFunction,Valve_Id, Direction, 0 ); } else { //cancel the control if (Valve3WayControlId[_ValveId] != 0xFF) if (RemoveControlCallback(MidtankMitigationControlId[Valve_Id], ValveCallback )!=OK) Report("Remove Control Failed.",__FILE__,__LINE__,(int)Valve_Id,RpError,(int)Direction,0); MidtankMitigationControlId[Valve_Id] = 0xFF; } } #endif } ValveRequest[Valve_Id].Direction = Direction; Valve_Command( Valve_Id); #endif } //------------------------------------------------------------------------------------------------------------------------ bool Valve3WayGetBusyState(uint32_t _ValveId, uint32_t parameter) { return ValveRsponse[_ValveId].Busy; } //Internal handling uint32_t Valve3WayCallBackFunction(uint32_t IfIndex, uint32_t BusyFlag) { bool Busy; uint32_t ValveId; if (IfIndex>>8 != IfTypeDisopenser) { LOG_ERROR (IfIndex, "Wrong 3Way Valve Interface type"); return 0xFFFFFFFF; } ValveId = IfIndex&0xFF; Busy = Valve3WayGetBusyState(ValveId, 0); if (Busy == NOTBUSY) { EnableDisableDispenserValve((Valves_t)ValveId, DISABLE); //stop this control loop if (SafeRemoveControlCallback(Valve3WayControlId[ValveId], Valve3WayCallBackFunction )==OK) Valve3WayControlId[ValveId] = 0xFF; else Report("Remove control callback failed",__FILE__,__LINE__,(int)ValveId,RpWarning,(int)Valve3WayControlId[ValveId],0); //call the module callback if (Valve3WayModuleCallback[ValveId]) Valve3WayModuleCallback[ValveId](ValveId,BusyFlag); Valve3WayModuleCallback[ValveId] = NULL; } //else // LOG_ERROR (ValveId, "Valve busy"); return OK; } //External call uint32_t Control3WayValvesWithCallback (Valves_t _ValveId, bool direction, callback_fptr callback) //direction: MidTank_Dispenser or Dispenser_Mixer { //uint32_t busy = false; //Report("Control3WayValvesWithCallback ",__FILE__,__LINE__,(int)_ValveId,RpWarning,(int)direction,0); if (Valve3WayControlId[_ValveId] != 0xFF) { Report("Control3WayValvesWithCallback called busy ",__FILE__,__LINE__,(int)_ValveId,RpWarning,(int)Valve3WayControlId[_ValveId],0); RemoveControlCallback(Valve3WayControlId[_ValveId], Valve3WayCallBackFunction ); } Valve3WayModuleCallback[_ValveId] = callback; Valve3WayControlId[_ValveId] = AddControlCallback("Valve3WayControlId", Valve3WayCallBackFunction, eOneSecond/*eHundredMillisecond*/, FPGA_GetDispenserValveBusyOCD,(IfTypeDisopenser*0x100+_ValveId), _ValveId, 0 ); if (Valve3WayControlId[_ValveId] == 0xFF) Report("Add control callback failed",__FILE__,__LINE__,(int)_ValveId,RpWarning,(int)Valve3WayControlId[_ValveId],0); // else // Report("Add control callback",__FILE__,__LINE__,(int)_ValveId,RpWarning,(int)Valve3WayControlId[_ValveId],0); /*busy = */FPGA_GetDispenserValveBusyOCD(_ValveId,0); //Report("Set valve id, dir, busy",__FILE__,_ValveId,(int)direction,RpWarning,(int)busy,0); EnableDisableDispenserValve(_ValveId, ENABLE); //SysCtlDelay(300);//Need Small delay (0.1-1)ms ROM_SysCtlDelay(24000); Valve_Set(_ValveId, direction); return Valve3WayControlId[_ValveId]; } bool LubricantState = false; uint8_t Lubricant_2Way_Valve(bool Direction) { uint8_t Status = OK; short Low_Reg; // short High_Reg; if(Direction == START) { //F3_GPO_01_Reg.bits.F3_LUBRICANT_VALVE = OPEN; Low_Reg = 0; LubricantState = true; } else //Direction = STOP { //F3_GPO_01_Reg.bits.F3_LUBRICANT_VALVE = CLOSE; Low_Reg = 100; LubricantState = false; } F3_low_var_LED4 = Low_Reg + 1 ; F3_high_var_LED4 = 101 - Low_Reg; //F3_GPO_01_bus = F3_GPO_01_Reg.ushort; return Status; } bool GetLubricantState(void) { return LubricantState; }