diff --git a/ldmicro/Makefile b/ldmicro/Makefile index 03d533b..3bc6257 100644 --- a/ldmicro/Makefile +++ b/ldmicro/Makefile @@ -44,8 +44,10 @@ LDOBJS = $(OBJDIR)\ldmicro.obj \ COMPOBJS = $(OBJDIR)\components.obj \ $(OBJDIR)\switch.obj \ - $(OBJDIR)\relay.obj - + $(OBJDIR)\relay.obj \ + $(OBJDIR)\spdt.obj \ + $(OBJDIR)\dpst.obj \ + $(OBJDIR)\dpdt.obj HELPOBJ = $(OBJDIR)\helptext.obj @@ -76,7 +78,7 @@ all: $(OBJDIR)/ldmicro.exe $(OBJDIR)/ldinterpret.exe clean: rm -rf $(LDOBJS) $(COMPOBJS) $(CLEANOBJ) - rmdir reg\results + rmdir reg\results lang.cpp: $(OBJDIR)/lang-tables.h diff --git a/ldmicro/components/componentfunctions.h b/ldmicro/components/componentfunctions.h index 9da4bfb..916bf00 100644 --- a/ldmicro/components/componentfunctions.h +++ b/ldmicro/components/componentfunctions.h @@ -23,22 +23,40 @@ BOOL ProcessDialogWindow(void); /*Initialization Functions*/ int InitSwitch(void* ComponentAddress); int InitRelay(void* ComponentAddress); +int InitSpdt(void* ComponentAddress); +int InitDpst(void* ComponentAddress); +int InitDpdt(void* ComponentAddress); /*Event Handlers*/ void HandleSwitchEvent(void* ComponentAddress, int Event, BOOL SimulationStarted, void* ImageLocation, UINT ImageId, HWND* h); void HandleRelayEvent(void* ComponentAddress, int Event, BOOL SimulationStarted, void* ImageLocation, UINT ImageId, HWND* h); +void HandleSpdtEvent(void* ComponentAddress, int Event, BOOL SimulationStarted, + void* ImageLocation, UINT ImageId, HWND* h); +void HandleDpstEvent(void* ComponentAddress, int Event, BOOL SimulationStarted, + void* ImageLocation, UINT ImageId, HWND* h); +void HandleDpdtEvent(void* ComponentAddress, int Event, BOOL SimulationStarted, + void* ImageLocation, UINT ImageId, HWND* h); /*Request Handlers*/ double SwitchVoltChanged(void* ComponentAddress, BOOL SimulationStarted, int index, double Volt, int Source, void* ImageLocation); double RelayVoltChanged(void* ComponentAddress, BOOL SimulationStarted, int index, double Volt, int Source, void* ImageLocation); +double SpdtVoltChanged(void* ComponentAddress, BOOL SimulationStarted, int index, + double Volt, int Source, void* ImageLocation); +double DpstVoltChanged(void* ComponentAddress, BOOL SimulationStarted, int index, + double Volt, int Source, void* ImageLocation); +double DpdtVoltChanged(void* ComponentAddress, BOOL SimulationStarted, int index, + double Volt, int Source, void* ImageLocation); /*Program Reference Functions*/ void SetSwitchIds(int*, void*); void SetRelayIds(int*, void*); +void SetSpdtIds(int*, void*); +void SetDpstIds(int*, void*); +void SetDpdtIds(int*, void*); // Relay Functions diff --git a/ldmicro/components/componentimages.h b/ldmicro/components/componentimages.h index 5c71ae6..27ef6ce 100644 --- a/ldmicro/components/componentimages.h +++ b/ldmicro/components/componentimages.h @@ -5,16 +5,27 @@ #define SWITCH_DISCONNECTED 8001 #define RELAY_NC 8002 #define RELAY_NO 8003 +#define SPDT_1 8004 +#define SPDT_2 8005 +#define DPST_1 8006 +#define DPST_2 8007 +#define DPDT_1 8008 +#define DPDT_2 8009 + + #ifndef RC_INVOKED //Used to hide code from resource file(Guess) -#define TOTAL_COMPONENTS 2 +#define TOTAL_COMPONENTS 5 #define COMPONENT_NAME_MAX_LENGTH 50 // Try to keep ComponentID's between 6000 - 6999 #define COMPONENT_SWITCH 6000 #define COMPONENT_RELAY 6001 +#define COMPONENT_SPDT 6002 +#define COMPONENT_DPST 6003 +#define COMPONENT_DPDT 6004 #define MAX_PIN_COUNT 10 @@ -32,7 +43,10 @@ void SetImage(int Component, void *il); static ComponentData rgCompData[TOTAL_COMPONENTS] = { {0, COMPONENT_SWITCH, TEXT("Switch"), 2, {"Input:", "Output:"}}, - {1, COMPONENT_RELAY, TEXT("Relay"), 5, {"Coil1:", "Coil2:", "NO:", "COM:", "NC:"}} + {1, COMPONENT_RELAY, TEXT("Relay"), 5, {"Coil1:", "Coil2:", "NO:", "COM:", "NC:"}}, + {2, COMPONENT_SPDT, TEXT("SPDT"), 3, {"Input:", "Output1:", "Output2:"}}, + {3, COMPONENT_DPST, TEXT("DPST"), 4, {"Input1:", "Input2:", "Output1:", "Output2:"}}, + {4, COMPONENT_DPDT, TEXT("DPDT"), 6, {"Input1:", "Input2:", "Output11:", "Output12:", "Output21:", "Output22:"}} }; #endif diff --git a/ldmicro/components/components.cpp b/ldmicro/components/components.cpp index 7a27823..632f136 100644 --- a/ldmicro/components/components.cpp +++ b/ldmicro/components/components.cpp @@ -48,7 +48,16 @@ size_t GetStructSize(int ComponentId) break; case COMPONENT_RELAY: return sizeof(RelayStruct); + break; + case COMPONENT_SPDT: + return sizeof(SpdtStruct); break; + case COMPONENT_DPST: + return sizeof(DpstStruct); + break; + case COMPONENT_DPDT: + return sizeof(DpdtStruct); + break; } return (size_t)-1; } @@ -64,6 +73,15 @@ int InitializeComponentProperties(void *ComponentAddress, int ComponentId) case COMPONENT_RELAY: return InitRelay(ComponentAddress); break; + case COMPONENT_SPDT: + return InitSpdt(ComponentAddress); + break; + case COMPONENT_DPST: + return InitDpst(ComponentAddress); + break; + case COMPONENT_DPDT: + return InitDpdt(ComponentAddress); + break; } return 0; } @@ -81,6 +99,16 @@ double VoltSet(void* ComponentAddress, BOOL SimulationStarted, int ImageType, in break; case COMPONENT_RELAY: return RelayVoltChanged(ComponentAddress, SimulationStarted, Index, Volt, Source, ImageLocation); + break; + case COMPONENT_SPDT: + return SpdtVoltChanged(ComponentAddress, SimulationStarted, Index, Volt, Source, ImageLocation); + break; + case COMPONENT_DPST: + return DpstVoltChanged(ComponentAddress, SimulationStarted, Index, Volt, Source, ImageLocation); + break; + case COMPONENT_DPDT: + return DpdtVoltChanged(ComponentAddress, SimulationStarted, Index, Volt, Source, ImageLocation); + break; } return Volt; } @@ -97,6 +125,16 @@ void SetPinIds(int Index, void *PinName,int ComponentId, void *ComponentAddres break; case COMPONENT_RELAY: SetRelayIds(PinIds,ComponentAddress); + break; + case COMPONENT_SPDT: + SetSpdtIds(PinIds, ComponentAddress); + break; + case COMPONENT_DPST: + SetDpstIds(PinIds, ComponentAddress); + break; + case COMPONENT_DPDT: + SetDpdtIds(PinIds, ComponentAddress); + break; } } } @@ -125,6 +163,15 @@ int NotifyComponent(void *ComponentAddress, void *PinName, int ComponentId, HandleRelayEvent(ComponentAddress, Event, SimulationStarted, ImageLocation, ImageId, h); // return InitRelay(ComponentAddress); break; + case COMPONENT_SPDT: + HandleSpdtEvent(ComponentAddress, Event, SimulationStarted, ImageLocation, ImageId, h); + break; + case COMPONENT_DPST: + HandleDpstEvent(ComponentAddress, Event, SimulationStarted, ImageLocation, ImageId, h); + break; + case COMPONENT_DPDT: + HandleDpdtEvent(ComponentAddress, Event, SimulationStarted, ImageLocation, ImageId, h); + break; } // return voltage return 0; diff --git a/ldmicro/components/componentstructs.h b/ldmicro/components/componentstructs.h index a7baca5..76dadda 100644 --- a/ldmicro/components/componentstructs.h +++ b/ldmicro/components/componentstructs.h @@ -24,9 +24,39 @@ typedef struct RelayStructTag double CoilVolt2; //Voltage at input pin double COMVolt; //Voltage at COM pin double NOVolt; //Voltage at NO pin - double NCVolt; - int PinId[5]; //Voltage at NC pin + double NCVolt; //Voltage at NC pin + int PinId[5]; }RelayStruct; +typedef struct SpdtStructTag +{ + int id; + int image; + BOOL latched; //Whether the swetch is in latch mode or not + BOOL NO1; //Whether Output 1 is connected + double Volt[3]; //Voltage at Input, Output1, Output2 respectively + int PinId[3]; +}SpdtStruct; + +typedef struct DpstStructTag +{ + int id; + int image; + BOOL latched; //Whether the swetch is in latch mode or not + BOOL NO; //Whether the inputs and outputs are disconnected (Open) + double Volt[4]; // Voltage at Input1, Input2, Output1, Output2 respectively + int PinId[4]; +}DpstStruct; + +typedef struct DpdtStructTag +{ + int id; + int image; + BOOL latched; //Whether the swetch is in latch mode or not + BOOL NS1; //Whether the inputs and outputs are connected in state 1 + double Volt[6]; // Voltage at Input1, Input2, Output11, Output12, Output21, Output22 respectively + int PinId[6]; +}DpdtStruct; + #endif diff --git a/ldmicro/components/dpdt.cpp b/ldmicro/components/dpdt.cpp new file mode 100644 index 0000000..c04c901 --- /dev/null +++ b/ldmicro/components/dpdt.cpp @@ -0,0 +1,539 @@ +/* DPDT component file +* Code version: 2.0 +* Version description: Adds latching functionality to component +* Version steability: +* GUI -> Stable +* Functionality -> No known bugs. +* Bugs: +* 1. - +* +*/ + +///Includes +#include +#include +//#include +#include +#include + +#include "componentstructs.h" +#include "componentfunctions.h" +#include "componentimages.h" +#include "components.h" + +///Window handles +static HWND DPDTState1; +static HWND DPDTState2; +static HWND ModeLatchedDPDT; +static HWND ModeTempDPDT; +HWND* SettingsDialogDPDT; + +///Global variables +enum DPDT_Pins { in1 = 0, in2, out11, out12, out21, out22 }; + +///Function definitions +int InitDpdt(void * ComponentAddress) +{ + DpdtStruct* d = (DpdtStruct*)ComponentAddress; + d->image = DPDT_1; + d->NS1 = TRUE; + d->latched = TRUE; + d->Volt[in1] = V_OPEN; + d->Volt[in2] = V_OPEN; + d->Volt[out11] = V_OPEN; + d->Volt[out12] = V_OPEN; + d->Volt[out21] = V_OPEN; + d->Volt[out22] = V_OPEN; + + return DPDT_1; +} + +void SetDpdtIds(int* id, void* ComponentAddress) +{ + DpdtStruct* d = (DpdtStruct*)ComponentAddress; + d->PinId[in1] = *id++; + d->PinId[in2] = *id++; + d->PinId[out11] = *id++; + d->PinId[out12] = *id++; + d->PinId[out21] = *id++; + d->PinId[out22] = *id++; +} + +void MakeSettingsDialogDPDT() +{ + ///Switch action mode + HWND InitLatched = CreateWindowEx(0, WC_BUTTON, ("Action mode"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 7, 3, 120, 65, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(InitLatched); + + ModeLatchedDPDT = CreateWindowEx(0, WC_BUTTON, ("Latched"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 16, 21, 100, 20, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(ModeLatchedDPDT); + + ModeTempDPDT = CreateWindowEx(0, WC_BUTTON, ("Temporary"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 16, 41, 100, 20, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(ModeTempDPDT); + + ///Switch initial status + HWND InitOut = CreateWindowEx(0, WC_BUTTON, ("Initial output state"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 140, 3, 120, 65, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(InitOut); + + DPDTState1 = CreateWindowEx(0, WC_BUTTON, ("State 1"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 149, 21, 100, 20, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(DPDTState1); + + DPDTState2 = CreateWindowEx(0, WC_BUTTON, ("State 2"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 149, 41, 100, 20, *SettingsDialogDPDT, NULL, NULL, NULL); + FontNice(DPDTState2); +} + +void LoadSettings(DpdtStruct* d) +{ + if (d->latched) + Button_SetCheck(ModeLatchedDPDT, BST_CHECKED); + else + Button_SetCheck(ModeTempDPDT, BST_CHECKED); + if (d->NS1) + Button_SetCheck(DPDTState1, BST_CHECKED); + else + Button_SetCheck(DPDTState2, BST_CHECKED); +} + +BOOL SaveSettings(DpdtStruct* d, void* ImageLocation) +{ + if (Button_GetState(ModeLatchedDPDT) == BST_CHECKED) + d->latched = TRUE; + else + d->latched = FALSE; + + if (Button_GetState(DPDTState1) == BST_CHECKED) + d->NS1 = TRUE; + else if (Button_GetState(DPDTState2) == BST_CHECKED) + d->NS1 = FALSE; + else + { + MessageBox(*SettingsDialogDPDT, + ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); + return FALSE; + } + + if (d->NS1) + d->image = DPDT_1; + else + d->image = DPDT_2; + + SetImage(d->image, ImageLocation); + RefreshImages(); + + return TRUE; +} + +void DpdtSettingsDialog(void* ComponentAddress, void* ImageLocation) +{ + DpdtStruct* d = (DpdtStruct*)ComponentAddress; + BOOL exitStatus; + + //Create dialog window instance + SettingsDialogDPDT = CreateDialogWindow("SPDT Settings Dialog", 100, 100, 263, 145, STYLE_VERTICAL); + + //Make the settings dialog + MakeSettingsDialogDPDT(); + + //Load settings + LoadSettings(d); + + //Show dialog window + ShowDialogWindow(); + + exitStatus = ProcessDialogWindow(); + while (exitStatus == FALSE) + { + exitStatus = SaveSettings(d, ImageLocation); + if (exitStatus == TRUE) + break; + else + { + exitStatus = TRUE; + exitStatus = ProcessDialogWindow(); + } + } + + DestroyWindow(*SettingsDialogDPDT); +} + +//Dynamically check and equalise the voltage on all pins that are connected to DPST at runtime +double EqualiseRuntimeVoltageDPDT(void* ComponentAdderss, int index, double volt) +{ + DpdtStruct* d = (DpdtStruct*)ComponentAdderss; + + ///Check if DPDT switch is in state 1; i.e Input 1 is connected to output11, Input 2 is connected to output21 + if (d->NS1) + { + ///If DPDT switch is in state 1 then output12 and output22 will be floating/open + if (index == out12) + { + d->Volt[out12] = V_OPEN; + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, V_OPEN); + } + else if (index == out22) + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, V_OPEN); + d->Volt[out22] = V_OPEN; + } + else + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, V_OPEN); + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, V_OPEN); + } + + double Vin; + double Vout; + + ///Get voltages at the connected pins + if (index == in1) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out11], ComponentAdderss); + } + else if (index == out11) + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = VoltRequest(d->PinId[out11], ComponentAdderss); + } + + ///Set 1: input 1, output11, output12 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + ///Get voltages at the connected pins + if (index == in2) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out21], ComponentAdderss); + } + else if (index == out21) + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out21], ComponentAdderss); + } + + ///Set 2: input 2, output21, output22 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } + ///Check if DPDT switch is in state 2; i.e Input 1 is connected to output12, Input 2 is connected to output22 + else + { + ///If DPDT switch is in state 2 then output11 and output21 will be floating/open + if (index == out11) + { + d->Volt[out11] = V_OPEN; + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, V_OPEN); + } + else if (index == out21) + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, V_OPEN); + d->Volt[out21] = V_OPEN; + } + else + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, V_OPEN); + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, V_OPEN); + } + + double Vin; + double Vout; + + ///Get voltages at the connected pins + if (index == in1) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out12], ComponentAdderss); + } + else if (index == out12) + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = VoltRequest(d->PinId[out12], ComponentAdderss); + } + + ///Set 1: input 1, output11, output12 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + ///Get voltages at the connected pins + if (index == in2) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out22], ComponentAdderss); + } + else if (index == out22) + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out22], ComponentAdderss); + } + + ///Set 2: input 2, output21, output22 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } + + return d->Volt[index]; +} + +//Perform a static check and equalise the voltage on all pins that are connected to DPST at runtime +void EqualiseStaticVoltageDPDT(void* ComponentAdderss) +{ + DpdtStruct* d = (DpdtStruct*)ComponentAdderss; + + ///Check if DPDT switch is in state 1; i.e Input 1 is connected to output11, Input 2 is connected to output21 + if (d->NS1) + { + ///If DPDT switch is in state 1 then output12 and output22 will be floating/open + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, V_OPEN); + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, V_OPEN); + + ///Get voltages at the connected pins + double Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + double Vout = VoltRequest(d->PinId[out11], ComponentAdderss); + + ///Set 1: input 1, output11, output12 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out21], ComponentAdderss); + ///Set 2: input 2, output21, output22 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } + ///Check if DPDT switch is in state 2; i.e Input 1 is connected to output12, Input 2 is connected to output22 + else + { + ///If DPDT switch is in state 2 then output11 and output21 will be floating/open + d->Volt[out11] = VoltChange(d->PinId[out11], out11, ComponentAdderss, V_OPEN); + d->Volt[out21] = VoltChange(d->PinId[out21], out21, ComponentAdderss, V_OPEN); + + ///Get voltages at the connected pins + double Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + double Vout = VoltRequest(d->PinId[out12], ComponentAdderss); + + ///Set 1: input 1, output11, output12 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out12] = VoltChange(d->PinId[out12], out12, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out22], ComponentAdderss); + ///Set 2: input 2, output21, output22 + ///If either pin is grounded then all pins are set to GND + if (Vin == GND || Vout == GND) + { + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + d->Volt[out22] = VoltChange(d->PinId[out22], out22, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } +} + +void ToggleState(DpdtStruct* d, void* ImageLocation) +{ + d->image = (d->image == DPDT_1) ? DPDT_2 : DPDT_1; + d->NS1 = (d->NS1 == TRUE) ? FALSE : TRUE; + SetImage(d->image, ImageLocation); + RefreshImages(); +} + +void HandleDpdtEvent(void * ComponentAddress, int Event, BOOL SimulationStarted, void * ImageLocation, UINT ImageId, HWND * h) +{ + + DpdtStruct* d = (DpdtStruct*)ComponentAddress; + + if (SimulationStarted) + { + switch (Event) + { + case EVENT_MOUSE_DOWN: + ToggleState(d, ImageLocation); + EqualiseStaticVoltageDPDT(ComponentAddress); + break; + case EVENT_MOUSE_UP: + if (!d->latched) + { + ToggleState(d, ImageLocation); + EqualiseStaticVoltageDPDT(ComponentAddress); + } + break; + default: + break; + } + } + else + { + switch (Event) + { + case EVENT_MOUSE_DBLCLICK: + DpdtSettingsDialog(ComponentAddress, ImageLocation); + break; + default: + break; + } + } +} + +double DpdtVoltChanged(void * ComponentAddress, BOOL SimulationStarted, int index, double Volt, int Source, void * ImageLocation) +{ + + if (SimulationStarted) + return EqualiseRuntimeVoltageDPDT(ComponentAddress, index, Volt); + + return Volt; +} \ No newline at end of file diff --git a/ldmicro/components/dpst.cpp b/ldmicro/components/dpst.cpp new file mode 100644 index 0000000..d806dbb --- /dev/null +++ b/ldmicro/components/dpst.cpp @@ -0,0 +1,417 @@ +/* DPST component file +* Code version: 2.1 +* Version description: Fixes minor bugs in v2.0 +* Version steability: +* GUI -> Stable +* Functionality -> Bugs found. +* Bugs: +* 1. Voltages dont load properly during simulation when the "Switch" component controls input pin of the DPST component. +* +*/ + +///Includes +#include +#include +//#include +#include +#include + +#include "componentstructs.h" +#include "componentfunctions.h" +#include "componentimages.h" +#include "components.h" + +///Window handles +static HWND State1; +static HWND State2; +static HWND ModeLatchedDPST; +static HWND ModeTempDPST; +HWND* SettingsDialogDPST; + +///Global variables +enum DPST_Pins { in1 = 0, in2, out1, out2 }; + +///Function definitions +int InitDpst(void * ComponentAddress) +{ + DpstStruct* d = (DpstStruct*)ComponentAddress; + d->image = DPST_1; + d->NO = FALSE; + d->latched = TRUE; + d->Volt[in1] = V_OPEN; + d->Volt[in2] = V_OPEN; + d->Volt[out1] = V_OPEN; + d->Volt[out2] = V_OPEN; + + return DPST_1; +} + +void SetDpstIds(int* id, void* ComponentAddress) +{ + DpstStruct* d = (DpstStruct*)ComponentAddress; + d->PinId[in1] = *id++; + d->PinId[in2] = *id++; + d->PinId[out1] = *id++; + d->PinId[out2] = *id++; +} + +void MakeSettingsDialogDPST() +{ + ///Switch action mode + HWND InitLatched = CreateWindowEx(0, WC_BUTTON, ("Action mode"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 7, 3, 120, 65, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(InitLatched); + + ModeLatchedDPST = CreateWindowEx(0, WC_BUTTON, ("Latched"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 16, 21, 100, 20, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(ModeLatchedDPST); + + ModeTempDPST = CreateWindowEx(0, WC_BUTTON, ("Temporary"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 16, 41, 100, 20, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(ModeTempDPST); + + ///Switch initial status + HWND InitOut = CreateWindowEx(0, WC_BUTTON, ("Initial output state"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 140, 3, 120, 65, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(InitOut); + + State1 = CreateWindowEx(0, WC_BUTTON, ("State 1"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 149, 21, 100, 20, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(State1); + + State2 = CreateWindowEx(0, WC_BUTTON, ("State 2"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 149, 41, 100, 20, *SettingsDialogDPST, NULL, NULL, NULL); + FontNice(State2); +} + +void LoadSettings(DpstStruct* d) +{ + + if (d->latched) + Button_SetCheck(ModeLatchedDPST, BST_CHECKED); + else + Button_SetCheck(ModeTempDPST, BST_CHECKED); + + if (!d->NO) + Button_SetCheck(State1, BST_CHECKED); + else + Button_SetCheck(State2, BST_CHECKED); +} + +BOOL SaveSettings(DpstStruct* d, void* ImageLocation) +{ + if (Button_GetState(ModeLatchedDPST) == BST_CHECKED) + d->latched = TRUE; + else if (Button_GetState(ModeTempDPST) == BST_CHECKED) + d->latched = FALSE; + else + { + MessageBox(*SettingsDialogDPST, + ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); + return FALSE; + } + + if (Button_GetState(State1) == BST_CHECKED) + d->NO = FALSE; + else if (Button_GetState(State2) == BST_CHECKED) + d->NO = TRUE; + else + { + MessageBox(*SettingsDialogDPST, + ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); + return FALSE; + } + + if (!d->NO) + d->image = DPST_1; + else + d->image = DPST_2; + + SetImage(d->image, ImageLocation); + RefreshImages(); + + return TRUE; +} + +void DpstSettingsDialog(void* ComponentAddress, void* ImageLocation) +{ + DpstStruct* d = (DpstStruct*)ComponentAddress; + BOOL exitStatus; + + //Create dialog window instance + SettingsDialogDPST = CreateDialogWindow("SPDT Settings Dialog", 100, 100, 263, 145, STYLE_VERTICAL); + + //Make the settings dialog + MakeSettingsDialogDPST(); + + //Load settings + LoadSettings(d); + + //Show dialog window + ShowDialogWindow(); + + exitStatus = ProcessDialogWindow(); + while (exitStatus == FALSE) + { + exitStatus = SaveSettings(d, ImageLocation); + if (exitStatus == TRUE) + break; + else + { + exitStatus = TRUE; + exitStatus = ProcessDialogWindow(); + } + } + + DestroyWindow(*SettingsDialogDPST); +} + +//Dynamically check and equalise the voltage on all pins that are connected to DPST at runtime +double EqualiseRuntimeVoltageDPST(void* ComponentAdderss, int index, double volt) +{ + DpstStruct* d = (DpstStruct*)ComponentAdderss; + + ///Check if the switch is open + if (d->NO) + { + ///If switch is open then all terminals will be floating/open + switch (index) + { + case in1: + d->Volt[in1] = V_OPEN; + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, V_OPEN); + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, V_OPEN); + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, V_OPEN); + break; + case in2: + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, V_OPEN); + d->Volt[in2] = V_OPEN; + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, V_OPEN); + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, V_OPEN); + case out1: + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, V_OPEN); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, V_OPEN); + d->Volt[out1] = V_OPEN; + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, V_OPEN); + break; + case out2: + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, V_OPEN); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, V_OPEN); + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, V_OPEN); + d->Volt[out2] = V_OPEN; + break; + default: + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, V_OPEN); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, V_OPEN); + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, V_OPEN); + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, V_OPEN); + break; + } + } + ///If the switch is connected + else + { + double Vin; + double Vout; + + ///Get voltages at the connected pins + if (index == in1) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out1], ComponentAdderss); + } + else if (index == out1) + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + Vout = VoltRequest(d->PinId[out1], ComponentAdderss); + } + + ///Equalise voltage for input 1 output 1 pair + ///If either pin is grounded then all pins are set to GND (Static event) + if (Vin == GND || Vout == GND) + { + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + ///Get voltages at the connected pins + if (index == in2) + { + Vin = volt; + Vout = VoltRequest(d->PinId[out2], ComponentAdderss); + } + else if (index == out2) + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = volt; + } + else + { + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out2], ComponentAdderss); + } + + ///Equalise voltage for input 2 output 2 pair + ///If either pin is grounded then all pins are set to GND (Static event) + if (Vin == GND || Vout == GND) + { + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } + + return d->Volt[index]; +} + +//Perform a static check and equalise the voltage on all pins that are connected to DPST at runtime +void EqualiseStaticVoltageDPST(void* ComponentAdderss) +{ + DpstStruct* d = (DpstStruct*)ComponentAdderss; + + ///Check if the switch is open + if (d->NO) + { + ///If switch is open then all terminals will be floating/open + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, V_OPEN); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, V_OPEN); + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, V_OPEN); + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, V_OPEN); + + } + ///If the switch is connected + else + { + double Vin = VoltRequest(d->PinId[in1], ComponentAdderss); + double Vout = VoltRequest(d->PinId[out1], ComponentAdderss); + + ///Equalise voltage for input 1 output 1 pair + ///If either pin is grounded then all pins are set to GND (Static event) + if (Vin == GND || Vout == GND) + { + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, GND); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + d->Volt[out1] = VoltChange(d->PinId[out1], out1, ComponentAdderss, max(Vin, Vout)); + d->Volt[in1] = VoltChange(d->PinId[in1], in1, ComponentAdderss, max(Vin, Vout)); + } + + Vin = VoltRequest(d->PinId[in2], ComponentAdderss); + Vout = VoltRequest(d->PinId[out2], ComponentAdderss); + + ///Equalise voltage for input 2 output 2 pair + ///If either pin is grounded then all pins are set to GND (Static event) + if (Vin == GND || Vout == GND) + { + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, GND); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, GND); + } + ///If Vin is set as open + else if (Vin == V_OPEN) + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, Vout); + ///If Vout is set as open + else if (Vout == V_OPEN) + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, Vin); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + d->Volt[out2] = VoltChange(d->PinId[out2], out2, ComponentAdderss, max(Vin, Vout)); + d->Volt[in2] = VoltChange(d->PinId[in2], in2, ComponentAdderss, max(Vin, Vout)); + } + } +} + +void ToggleState(DpstStruct* d, void* ImageLocation) +{ + d->image = (d->image == DPST_1) ? DPST_2 : DPST_1; + d->NO = (d->NO == TRUE) ? FALSE : TRUE; + SetImage(d->image, ImageLocation); + RefreshImages(); +} + +void HandleDpstEvent(void * ComponentAddress, int Event, BOOL SimulationStarted, void * ImageLocation, UINT ImageId, HWND * h) +{ + DpstStruct* d = (DpstStruct*)ComponentAddress; + + if (SimulationStarted) + { + switch (Event) + { + case EVENT_MOUSE_DOWN: + ToggleState(d, ImageLocation); + EqualiseStaticVoltageDPST(ComponentAddress); + break; + case EVENT_MOUSE_UP: + if (!d->latched) + { + ToggleState(d, ImageLocation); + EqualiseStaticVoltageDPST(ComponentAddress); + } + break; + default: + break; + } + } + else + { + switch (Event) + { + case EVENT_MOUSE_DBLCLICK: + DpstSettingsDialog(ComponentAddress, ImageLocation); + break; + default: + break; + } + } +} + +double DpstVoltChanged(void * ComponentAddress, BOOL SimulationStarted, int index, double Volt, int Source, void * ImageLocation) +{ + if (SimulationStarted) + return EqualiseRuntimeVoltageDPST(ComponentAddress, index, Volt); + + return Volt; +} \ No newline at end of file diff --git a/ldmicro/components/spdt.cpp b/ldmicro/components/spdt.cpp new file mode 100644 index 0000000..e30a732 --- /dev/null +++ b/ldmicro/components/spdt.cpp @@ -0,0 +1,390 @@ +/* SPDT component file +* Code version: 2.0 +* Version description: Adds latching functionality to component +* Version steability: +* GUI -> Stable +* Functionality -> No known bugs. +* Bugs: +* 1. - +* +*/ + +///Includes +#include +#include +//#include +#include +#include + +#include "componentstructs.h" +#include "componentfunctions.h" +#include "componentimages.h" +#include "components.h" + +///Window handles +static HWND StateOut1; +static HWND StateOut2; +static HWND ModeLatched; +static HWND ModeTemp; +HWND* SettingsDialogSPDT; + +///Global variables +enum SPDT_Pins {in = 0, out1, out2}; + +///Function definitions +void SetSpdtIds(int* id, void* ComponentAddress) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAddress; + s->PinId[in] = *id++; + s->PinId[out1] = *id++; + s->PinId[out2] = *id++; +} + +int InitSpdt(void * ComponentAddress) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAddress; + s->image = SPDT_1; + s->latched = TRUE; + s->NO1 = TRUE; + s->Volt[in] = V_OPEN; + s->Volt[out1] = V_OPEN; + s->Volt[out2] = V_OPEN; + + return SPDT_1; +} + +void MakeSettingsDialogSPDT() +{ + ///Switch action mode + HWND InitLatched = CreateWindowEx(0, WC_BUTTON, ("Action mode"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 7, 3, 120, 65, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(InitLatched); + + ModeLatched = CreateWindowEx(0, WC_BUTTON, ("Latched"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 16, 21, 100, 20, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(ModeLatched); + + ModeTemp = CreateWindowEx(0, WC_BUTTON, ("Temporary"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 16, 41, 100, 20, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(ModeTemp); + + ///Switch initial status + HWND InitOut = CreateWindowEx(0, WC_BUTTON, ("Initial output"), + WS_CHILD | BS_GROUPBOX | WS_VISIBLE | WS_TABSTOP, + 140, 3, 120, 65, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(InitOut); + + StateOut1 = CreateWindowEx(0, WC_BUTTON, ("Output 1"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP, + 149, 21, 100, 20, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(StateOut1); + + StateOut2 = CreateWindowEx(0, WC_BUTTON, ("Output 2"), + WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE, + 149, 41, 100, 20, *SettingsDialogSPDT, NULL, NULL, NULL); + FontNice(StateOut2); +} + +void LoadSettings(SpdtStruct* s) +{ + if (s->latched) + Button_SetCheck(ModeLatched, BST_CHECKED); + else + Button_SetCheck(ModeTemp, BST_CHECKED); + if (s->NO1) + Button_SetCheck(StateOut1, BST_CHECKED); + else + Button_SetCheck(StateOut2, BST_CHECKED); +} + +BOOL SaveSettings(SpdtStruct* s, void* ImageLocation) +{ + if (Button_GetState(ModeLatched) == BST_CHECKED) + s->latched = TRUE; + else if (Button_GetState(ModeTemp) == BST_CHECKED) + s->latched = FALSE; + else + { + MessageBox(*SettingsDialogSPDT, + ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); + return FALSE; + } + + if (Button_GetState(StateOut1) == BST_CHECKED) + s->NO1 = TRUE; + else if (Button_GetState(StateOut2) == BST_CHECKED) + s->NO1 = FALSE; + else + { + MessageBox(*SettingsDialogSPDT, + ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); + return FALSE; + } + + + if (s->NO1) + s->image = SPDT_1; + else + s->image = SPDT_2; + + SetImage(s->image, ImageLocation); + RefreshImages(); + + return TRUE; +} + +void SpdtSettingsDialog(void* ComponentAddress, void* ImageLocation) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAddress; + BOOL exitStatus; + + //Create dialog window instance + SettingsDialogSPDT = CreateDialogWindow("SPDT Settings Dialog", 100, 100, 263, 145, STYLE_VERTICAL); + + //Make the settings dialog + MakeSettingsDialogSPDT(); + + //Load settings + LoadSettings(s); + + //Show dialog window + ShowDialogWindow(); + + exitStatus = ProcessDialogWindow(); + while (exitStatus == FALSE) + { + exitStatus = SaveSettings(s, ImageLocation); + if (exitStatus == TRUE) + break; + else + { + exitStatus = TRUE; + exitStatus = ProcessDialogWindow(); + } + } + + DestroyWindow(*SettingsDialogSPDT); + +} + +//Perform a static check and equalise the voltage on all pins that are connected to SPDT at runtime +void EqualiseStaticVoltageSPDT(void* ComponentAdderss) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAdderss; + + ///Check if input and output 1 are connected + if (s->NO1) + { + ///If the input pin is connected to output 1 then output 2 will be open + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, V_OPEN); + + ///Get voltages at the connected pins + double volt1 = VoltRequest(s->PinId[in], ComponentAdderss); + double volt2 = VoltRequest(s->PinId[out1], ComponentAdderss); + + ///If either pin is grounded then all pins are set to GND + if (volt1 == GND || volt2 == GND) + { + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, GND); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, GND); + } + ///If volt1 is set as open + else if (volt1 == V_OPEN) + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, volt2); + ///If volt2 is set as open + else if (volt2 == V_OPEN) + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, volt1); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, max(volt1, volt2)); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, max(volt1, volt2)); + } + } + ///If input and output 2 are connected + else + { + ///If the input pin is connected to output 2 then output 1 will be open + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, V_OPEN); + + ///Get voltages at the connected pins + double volt1 = VoltRequest(s->PinId[0], ComponentAdderss); + double volt2 = VoltRequest(s->PinId[out2], ComponentAdderss); + + ///If either pin is grounded then all pins are set to GND (Static event) + if (volt1 == GND || volt2 == GND) + { + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, GND); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, GND); + } + ///If volt1 is set as open + else if (volt1 == V_OPEN) + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, volt2); + ///If volt2 is set as open + else if (volt2 == V_OPEN) + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, volt1); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, max(volt1, volt2)); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, max(volt1, volt2)); + } + } +} + +//Dynamically check and equalise the voltage on all pins that are connected to SPDT at runtime +double EqualiseRuntimeVoltageSPDT(void* ComponentAdderss, int index, double volt) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAdderss; + + ///Check if input and output 1 are connected + if (s->NO1) + { + ///If the input pin is connected to output 1 then output 2 will be open + if (index == out2) + s->Volt[out2] = V_OPEN; + else + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, V_OPEN); + + double volt1; + double volt2; + + ///Get voltages at the connected pins + if (index == in) + { + volt1 = volt; + volt2 = VoltRequest(s->PinId[out1], ComponentAdderss); + } + else if (index == out1) + { + volt1 = VoltRequest(s->PinId[in], ComponentAdderss); + volt2 = volt; + } + else + { + volt1 = VoltRequest(s->PinId[in], ComponentAdderss); + volt2 = VoltRequest(s->PinId[out1], ComponentAdderss); + } + + ///If either pin is grounded then all pins are set to GND + if (volt1 == GND || volt2 == GND) + { + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, GND); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, GND); + } + ///If volt1 is set as open + else if (volt1 == V_OPEN) + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, volt2); + ///If volt2 is set as open + else if (volt2 == V_OPEN) + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, volt1); + ///If no pin is grounded then all pins are set to the max voltage of the pins + else + { + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, max(volt1, volt2)); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, max(volt1, volt2)); + } + } + ///If input and output 2 are connected + else + { + ///If the input pin is connected to output 2 then output 1 will be open + s->Volt[out1] = VoltChange(s->PinId[out1], out1, ComponentAdderss, V_OPEN); + + double volt1; + double volt2; + + ///Get voltages at the connected pins + if (index == in) + { + volt1 = volt; + volt2 = VoltRequest(s->PinId[out2], ComponentAdderss); + } + else if (index == out1) + { + volt1 = VoltRequest(s->PinId[in], ComponentAdderss); + volt2 = volt; + } + else + { + volt1 = VoltRequest(s->PinId[in], ComponentAdderss); + volt2 = VoltRequest(s->PinId[out2], ComponentAdderss); + } + + ///If either pin is grounded then all pins are set to GND (Static event) + if (volt1 == GND || volt2 == GND) + { + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, GND); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, GND); + } + ///If volt1 is set as open + else if (volt1 == V_OPEN) + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, volt2); + ///If volt2 is set as open + else if (volt2 == V_OPEN) + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, volt1); + ///If no pin is grounded then all pins are set to the max voltage of the pins (Dynamic event) + else + { + s->Volt[out2] = VoltChange(s->PinId[out2], out2, ComponentAdderss, max(volt1, volt2)); + s->Volt[in] = VoltChange(s->PinId[in], in, ComponentAdderss, max(volt1, volt2)); + } + } + + return s->Volt[index]; +} + +double SpdtVoltChanged(void * ComponentAddress, BOOL SimulationStarted, int index, double Volt, int Source, void * ImageLocation) +{ + if (SimulationStarted) + return EqualiseRuntimeVoltageSPDT(ComponentAddress, index, Volt); + + return Volt; +} + +void ToggleState(SpdtStruct* s, void* ImageLocation) +{ + s->image = (s->image == SPDT_1) ? SPDT_2 : SPDT_1; + s->NO1 = (s->NO1 == TRUE) ? FALSE : TRUE; + SetImage(s->image, ImageLocation); + RefreshImages(); +} + +void HandleSpdtEvent(void * ComponentAddress, int Event, BOOL SimulationStarted, void * ImageLocation, UINT ImageId, HWND * h) +{ + SpdtStruct* s = (SpdtStruct*)ComponentAddress; + + if (SimulationStarted) + { + switch (Event) + { + case EVENT_MOUSE_DOWN: + ToggleState(s, ImageLocation); + EqualiseStaticVoltageSPDT(ComponentAddress); + break; + case EVENT_MOUSE_UP: + if (!s->latched) + { + ToggleState(s, ImageLocation); + EqualiseStaticVoltageSPDT(ComponentAddress); + } + break; + default: + break; + } + } + else + { + switch (Event) + { + case EVENT_MOUSE_DBLCLICK: + SpdtSettingsDialog(ComponentAddress, ImageLocation); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/ldmicro/components/switch.cpp b/ldmicro/components/switch.cpp index 7e1bf57..ea74076 100644 --- a/ldmicro/components/switch.cpp +++ b/ldmicro/components/switch.cpp @@ -126,6 +126,7 @@ BOOL SaveSwitchDialog(SwitchStruct* Data) ("Incomplete"), ("Warning"), MB_OK | MB_ICONWARNING); return FALSE; } + if(Edit_GetText(NameTextbox, (LPSTR)&temp, 15) < 1) { MessageBox(*SwitchDialog, @@ -185,7 +186,7 @@ int InitSwitch(void* ComponentAddress) temp->Volt[0] = V_OPEN; temp->Volt[1] = V_OPEN; - return SWITCH_DISCONNECTED; + return SWITCH_DISCONNECTED; } void UpdateValues(SwitchStruct* Switch, void* ComponentAddress) diff --git a/ldmicro/img/dpdt_switch_2.png b/ldmicro/img/dpdt_1.png similarity index 100% rename from ldmicro/img/dpdt_switch_2.png rename to ldmicro/img/dpdt_1.png diff --git a/ldmicro/img/dpdt_switch_1.png b/ldmicro/img/dpdt_2.png similarity index 100% rename from ldmicro/img/dpdt_switch_1.png rename to ldmicro/img/dpdt_2.png diff --git a/ldmicro/img/dpst_switch_1.png b/ldmicro/img/dpst_1.png similarity index 100% rename from ldmicro/img/dpst_switch_1.png rename to ldmicro/img/dpst_1.png diff --git a/ldmicro/img/dpst_switch_2.png b/ldmicro/img/dpst_2.png similarity index 100% rename from ldmicro/img/dpst_switch_2.png rename to ldmicro/img/dpst_2.png diff --git a/ldmicro/img/spdt_switch_1.png b/ldmicro/img/spdt_1.png similarity index 100% rename from ldmicro/img/spdt_switch_1.png rename to ldmicro/img/spdt_1.png diff --git a/ldmicro/img/spdt_switch_2.png b/ldmicro/img/spdt_2.png similarity index 100% rename from ldmicro/img/spdt_switch_2.png rename to ldmicro/img/spdt_2.png diff --git a/ldmicro/ldmicro.rc b/ldmicro/ldmicro.rc index 46c3de1..952b087 100644 --- a/ldmicro/ldmicro.rc +++ b/ldmicro/ldmicro.rc @@ -10,4 +10,10 @@ RELAY_NC PNG "img\\relay_nc.png" RELAY_NO PNG "img\\relay_no.png" SWITCH_CONNECTED PNG "img\\switch_connected.png" -SWITCH_DISCONNECTED PNG "img\\switch_disconnected.png" \ No newline at end of file +SWITCH_DISCONNECTED PNG "img\\switch_disconnected.png" +SPDT_1 PNG "img\\spdt_1.png" +SPDT_2 PNG "img\\spdt_2.png" +DPST_1 PNG "img\\dpst_1.png" +DPST_2 PNG "img\\dpst_2.png" +DPDT_1 PNG "img\\dpdt_1.png" +DPDT_2 PNG "img\\dpdt_2.png"