/** ****************************************************************************** * File Name : io.c * Description : This file provides code for the digital input/output. ****************************************************************************** * @attention * *

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include #include "io.h" #include "led.h" #include "relay.h" #include "dev_addr.h" #include "asutil.h" #include "device_param.h" #include "dflash_sf1.h" #include "log.h" #include "delay.h" #include "modbus.h" #include "buzzer.h" #include "alarm.h" #include "pwm.h" /* Private typedef -----------------------------------------------------------*/ typedef struct // Input PortNo 0..4 * 8 channels { // PORT Information s16 PortNo; u8 NormalOpen; // Normal state logic level (0 or 1) u8 Enabled; // Enable device? s16 RefPort; // Module disconnection reference Port u8 State; // Current state of device u8 OldState; // Previous state of device // Chattering u8 UsedChat; // Enable chattering filter // MultiChat; // If OCCUR Chatt = 100, NORMAL Chatt = ChatTime, ex) Cable Open u8 ChatState; u16 AlarmChatTime; // Chattering Time (1 = 1ms) u16 ReleaseChatTime; // Chattering Time (1 = 1ms) u16 ChatCount; // Chattering internal counter // Using Information u8 Changed; // Temp Var u8 BakEnabled; // Flag for screen display u8 StateFlag; // Flag for state storage } TDIDeviceRec, *PDIDeviceRec; /* Private define ------------------------------------------------------------*/ #define IO_TASK_TIME 5 // 50ms TASK #define IO_ALARM_TIME 500 // 3000ms Alarm Delay #define LED_ONOFF_TIME 200 // 500ms #define DIDCount 2 /*********************** Digital Input Define *********************************/ #define DI_DISCHA_RELAY 0 #define DI_CHARGE_RELAY 1 #define RON 1 #define ROFF 0 #define PUSH 1 #define PULL 0 #define High 1 /* USED INVENTORY */ #define Low 0 /* USED INVENTORY */ #define false 0 #define true 1 #define cNormalOpen 0 #define cNormalClose 1 #define cNORMAL 0 #define cINITVALUE 0xff #define cOCCUR 1 #define cUNKNOWN 2 #define cDISABLE 3 #define cCANCEL 0 #define DSG_RELAY_ID '0' #define CHG_RELAY_ID '1' #define PRE_CHG_RELAY_ID '2' /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ u8 device_addr = 0; TDIDeviceRec DID[DIDCount], BakDID[DIDCount]; TDEVICE_STATUS alarm_device_status; u8 AlarmLed = false; u8 AlarmLedFlag = false; u16 AlarmLedTick = 0; u8 BuzzerWarning = false; u8 BuzzerProtection = false; u8 AlarmBuzzerFlag = false; u16 AlarmBuzzerTick = 0; u8 RunLedFlag = false; u16 RunLedTick = 0; u8 SocLedFlag = false; u16 SocLedTick = 0; u8 SocLed[4] = { 0 }; u8 RemoteReset = false; /* Private function prototypes -----------------------------------------------*/ void IO_Relay_Control(void); void Buzzer_Process(void); void Led_Process(void); void InitDIO(s16 port, s16 ref_port, u8 io_type, u16 alarm_time, u16 release_time, u8 enable); void Check_DI(void); void AnalysisDI(PDIDeviceRec aDID); u8 DIDState(u16 i); void dec_led_time(u32 tick); void dec_buzzer_time(u32 tick); /* Private function ----------------------------------------------------------*/ void InitDIODevice(void) { Relay_Init(); DevAddrInit(); for (int i = 0; i < DIDCount; i++) { DID[i].Enabled = true; DID[i].PortNo = -1; // Undefine Port DID[i].RefPort = -1; // Not used ref Port DID[i].State = cNORMAL; DID[i].OldState = cNORMAL; DID[i].Changed = false; DID[i].UsedChat = true; DID[i].AlarmChatTime = 0; DID[i].ReleaseChatTime = 0; DID[i].ChatCount = 0; DID[i].ChatState = cINITVALUE; DID[i].BakEnabled = cINITVALUE; // Flag for screen display DID[i].StateFlag = cINITVALUE; // Flag for state storage DID[i].Enabled = true; } InitDIO(DI_DISCHA_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true); InitDIO(DI_CHARGE_RELAY , -1, cNormalClose, IO_ALARM_TIME, IO_ALARM_TIME, true); memset(&alarm_device_status, 0x00, sizeof(TDEVICE_STATUS)); } void InitDIO(s16 port, s16 ref_port, u8 io_type, u16 alarm_time, u16 release_time, u8 enable) { DID[port].Enabled = enable; DID[port].PortNo = port; DID[port].RefPort = ref_port; DID[port].NormalOpen = io_type; DID[port].AlarmChatTime = alarm_time; DID[port].ReleaseChatTime = release_time; } u8 GetDevAddrIO(void) { return device_addr; // return device_param.sbs.data.System_ID; } void SetRemoteReset(void) { RemoteReset = true; } void App_TaskIO(void) { InitDIODevice(); while (DEF_TRUE) { device_addr = GetDevAddr(); Check_DI(); ProcessAlarm(); IO_Relay_Control(); Led_Process(); // Buzzer_Process(); if (RemoteReset == true) { delay_os_ms(100); Sys_Soft_Reset(); } delay_os_ms(IO_TASK_TIME); } } void DecIOTaskTick(u32 tick) { dec_led_time(tick); dec_buzzer_time(tick); } void Check_DI(void) { s16 i; for (i = 0; i < DIDCount; i++) { DID[i].Changed = false; AnalysisDI(&DID[i]); } device_status.battery_status.bit.DSG_S = (DIDState(DI_DISCHA_RELAY) != cNORMAL) ? 1 : 0; device_status.battery_status.bit.CHG_S = (DIDState(DI_CHARGE_RELAY) != cNORMAL) ? 1 : 0; } u8 GetIOBit(u16 port) { u8 result = 0; switch (port) { case DI_DISCHA_RELAY : result = Relay_Status(DI_DISCHA_RELAY); break; case DI_CHARGE_RELAY : result = Relay_Status(DI_CHARGE_RELAY); break; default: break; } return result; } void AnalysisDI(PDIDeviceRec aDID) { u16 ChatTime; u8 BitState; if (aDID->PortNo == -1) return; /* Undefined DI PORT */ aDID->OldState = aDID->State; aDID->Changed = false; aDID->StateFlag = true; BitState = GetIOBit(aDID->PortNo); if (aDID->NormalOpen == cNormalClose) BitState ^= aDID->NormalOpen; if (aDID->UsedChat == true) { if (aDID->State == cNORMAL) ChatTime = aDID->AlarmChatTime; else ChatTime = aDID->ReleaseChatTime; if (aDID->ChatState == BitState) { if (aDID->ChatCount < 10000) aDID->ChatCount += IO_TASK_TIME; } else aDID->ChatCount = 0; aDID->ChatState = BitState; if (aDID->ChatCount < ChatTime) BitState = aDID->State; } if (aDID->RefPort != -1) /* CABLE OPEN or FAIL reference PORT */ { if (DID[aDID->RefPort].State == cOCCUR) { BitState = cUNKNOWN; aDID->Changed = DID[aDID->RefPort].Changed; } } if (BitState != aDID->OldState) /* State changed */ { aDID->Changed = true; aDID->OldState = BitState; aDID->State = BitState; aDID->StateFlag = true; /* Flag for state storage */ } } void DIDAlarmHistory(PDIDeviceRec aDID,u8 msg1,u8 msg2,u8 msg3,u8 msg4) { if (aDID->Enabled == true){ if (aDID->Changed) { // switch (aDID->State) { // case cNORMAL : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2); // break; // case cOCCUR : ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3); // break; // case cUNKNOWN: ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4); // break; // } } } } void DoorAlarmHistory(PDIDeviceRec aDID,u8 msg1,u8 msg2,u8 msg3,u8 msg4) { if (aDID->Enabled == true) { if (aDID->Changed) { switch (aDID->State) { case cNORMAL : // ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg2); break; case cOCCUR : // ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg3); break; case cUNKNOWN: // ADD_RUN_HISTORY(true,osENVIR,0,0,msg1,msg4); break; } } } } u8 DIDState(u16 i) // return cNORMAL, cDISABLE, cOCCUR, cUNKNOWN { u8 Alarmflag; Alarmflag = cNORMAL; if (DID[i].Enabled != true) Alarmflag = cDISABLE; // No Alarm else { if (DID[i].State == cOCCUR) Alarmflag = cOCCUR; if (DID[i].RefPort != -1) { if (DID[DID[i].RefPort].State == cOCCUR) { Alarmflag = cUNKNOWN; // fail } } } return(Alarmflag); } void IO_Relay_Control(void) { if (device_status.battery_status.bit.INIT) { if (device_status.battery_status.bit.CHG_C == RON) // Relay On Relay_On(CHG_RELAY_ID); else // Relay Off Relay_Off(CHG_RELAY_ID); if (device_status.battery_status.bit.DSG_C == RON) // Relay On Relay_On(DSG_RELAY_ID); else // Relay Off Relay_Off(DSG_RELAY_ID); if (device_status.battery_status.bit.ZVC_C == RON) // Relay On Relay_On(PRE_CHG_RELAY_ID); else // Relay Off Relay_Off(PRE_CHG_RELAY_ID); } } void dec_led_time(u32 tick) { if (AlarmLedTick > 0) { if (AlarmLedTick > tick) AlarmLedTick -= tick; else AlarmLedTick = 0; } if (RunLedTick > 0) { if (RunLedTick > tick) RunLedTick -= tick; else RunLedTick = 0; } if (SocLedTick > 0) { if (SocLedTick > tick) SocLedTick -= tick; else SocLedTick = 0; } } void Alarm_Led_Process(void) { switch (device_status.alarm_status) { case 0: // Normal ALM_LED = OFF; break; case 1: // Warning if (AlarmLedFlag == true) { if (AlarmLedTick == 0) { ALM_LED = ON; AlarmLedTick = 1000; AlarmLedFlag = false; } } else { if (AlarmLedTick == 0) { ALM_LED = OFF; AlarmLedTick = 1000; AlarmLedFlag = true; } } break; case 2: // Protection ALM_LED = ON; break; case 3: // WarmingUp ALM_LED = OFF; break; } } void RUN_LED_Process(void) { switch (device_status.op_status) { case 0: // Standby RUN_LED = ON; break; case 1: // Charging RUN_LED = ON; // if (RunLedFlag == true) // { // if (RunLedTick == 0) // { // BD_RUN_LED = ON; // RUN_LED = ON; // // RunLedTick = 1000; // RunLedFlag = false; // } // } // else // { // if (RunLedTick == 0) // { // BD_RUN_LED = OFF; // RUN_LED = OFF; // // RunLedTick = 1000; // RunLedFlag = true; // } // } break; case 2: // Discharging if (RunLedFlag == true) { if (RunLedTick == 0) { BD_RUN_LED = ON; RUN_LED = ON; RunLedTick = 1000; RunLedFlag = false; } } else { if (RunLedTick == 0) { BD_RUN_LED = OFF; RUN_LED = OFF; RunLedTick = 1000; RunLedFlag = true; } } break; case 3: // Floating RUN_LED = ON; break; } } void SOC_LED_Buf(u32 soc, u16 mode) { switch (mode) { case 0: // Standby for (int i = 0; i < 4; i++) { if (SocLed[i] == 2) SocLed[i] = 1; else if (SocLed[i] == 3) SocLed[i] = 0; } break; case 1: // Charging if (soc > 750) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 1; if (SocLed[3] == 1) SocLed[3] = 2; else if (SocLed[3] == 0) SocLed[3] = 3; } else if (soc > 500) { SocLed[0] = 1; SocLed[1] = 1; if (SocLed[2] == 1) SocLed[2] = 2; else if (SocLed[2] == 0) SocLed[2] = 3; SocLed[3] = 0; } else if (soc > 250) { SocLed[0] = 1; if (SocLed[1] == 1) SocLed[1] = 2; else if (SocLed[1] == 0) SocLed[1] = 3; SocLed[2] = 0; SocLed[3] = 0; } else if (soc > 0) { if (SocLed[0] == 1) SocLed[0] = 2; else if (SocLed[0] == 0) SocLed[0] = 3; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } else { SocLed[0] = 0; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } break; case 2: // Discharging if (soc > 750) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 1; if (SocLed[3] == 2) SocLed[3] = 1; else if (SocLed[3] == 3) SocLed[3] = 0; } else if (soc > 500) { SocLed[0] = 1; SocLed[1] = 1; if (SocLed[2] == 2) SocLed[2] = 1; else if (SocLed[2] == 3) SocLed[2] = 0; SocLed[3] = 0; } else if (soc > 250) { SocLed[0] = 1; if (SocLed[1] == 2) SocLed[1] = 1; else if (SocLed[1] == 3) SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } else if (soc > 0) { if (SocLed[0] == 2) SocLed[0] = 1; else if (SocLed[0] == 3) SocLed[0] = 0; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } else { SocLed[0] = 0; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } break; case 3: // Floating if (soc >= 1000) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 1; SocLed[3] = 1; } else { for (int i = 0; i < 4; i++) { if (SocLed[i] == 2) SocLed[i] = 1; else if (SocLed[i] == 3) SocLed[i] = 0; } } break; case 4: // WarmingUp if (soc > 750) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 1; SocLed[3] = 1; } else if (soc > 500) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 1; SocLed[3] = 0; } else if (soc > 250) { SocLed[0] = 1; SocLed[1] = 1; SocLed[2] = 0; SocLed[3] = 0; } else if (soc > 0) { SocLed[0] = 1; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } else { SocLed[0] = 0; SocLed[1] = 0; SocLed[2] = 0; SocLed[3] = 0; } break; } } void SOC_LED_Control(u8 no, u8 onoff) { switch (no) { case 0: SOC_0_LED = onoff; break; case 1: SOC_1_LED = onoff; break; case 2: SOC_2_LED = onoff; break; case 3: SOC_3_LED = onoff; break; } } void SOC_LED_Process(void) { SOC_LED_Buf(device_value.RelativeStateOfCharge, device_status.op_status); for (int i = 0; i < 4; i++) { switch (SocLed[i]) { case 0: // LED Off SOC_LED_Control(i, 0); break; case 1: // LED On SOC_LED_Control(i, 1); break; case 2: // LED Toggle case 3: // LED Toggle if (SocLedFlag == true) { if (SocLedTick == 0) { SOC_LED_Control(i, 1); // On SocLedTick = 1000; SocLedFlag = false; } } else { if (SocLedTick == 0) { SOC_LED_Control(i, 0); // Off SocLedTick = 1000; SocLedFlag = true; } } break; } } } void Led_Process(void) { if (GetSleepMode() == false) { Alarm_Led_Process(); RUN_LED_Process(); SOC_LED_Process(); } else { SOC_0_LED = OFF; SOC_1_LED = OFF; SOC_2_LED = OFF; SOC_3_LED = OFF; ALM_LED = OFF; RUN_LED = OFF; } } void Alarm_Buzzer_Update(void) { alarm_device_status.warning.value = device_status.warning.value; alarm_device_status.protection.value = device_status.protection.value; } void Alarm_Buzzer_Process(void) { u8 buzzer = false; if (alarm_device_status.warning.value < device_status.warning.value) { buzzer = true; } else { alarm_device_status.warning.value = device_status.warning.value; } BuzzerWarning = buzzer; buzzer = false; if (alarm_device_status.protection.value < device_status.protection.value) { buzzer = true; } else { alarm_device_status.protection.value = device_status.protection.value; } BuzzerProtection = buzzer; } void dec_buzzer_time(u32 tick) { if (AlarmBuzzerTick > 0) { if (AlarmBuzzerTick > 0) AlarmBuzzerTick -= tick; else AlarmBuzzerTick = 0; } } void Buzzer_Process(void) { Alarm_Buzzer_Process(); // Protection if (BuzzerProtection) { if (AlarmBuzzerFlag == true) { if (AlarmBuzzerTick == 0) { BUZZER = 0; AlarmBuzzerTick = 500; AlarmBuzzerFlag = false; } } else { if (AlarmBuzzerTick == 0) { BUZZER = 1; AlarmBuzzerTick = 500; AlarmBuzzerFlag = true; } } } // Warning else if (BuzzerWarning) { if (AlarmBuzzerFlag == true) { if (AlarmBuzzerTick == 0) { BUZZER = 0; AlarmBuzzerTick = 1000; AlarmBuzzerFlag = false; } } else { if (AlarmBuzzerTick == 0) { BUZZER = 1; AlarmBuzzerTick = 1000; AlarmBuzzerFlag = true; } } } else { BUZZER = 0; } }