📄 logicev.pas
字号:
if (vName = 'W') then
if (Value = 1) then W.Brush.Color := clRed
else W.Brush.Color := clWhite;
if (vName = 'X') then
if (Value = 1) then X.Brush.Color := clRed
else X.Brush.Color := clWhite;
if (vName = 'Y') then
if (Value = 1) then Y.Brush.Color := clRed
else Y.Brush.Color := clWhite;
if (vName = 'Z') then
if (Value = 1) then Z.Brush.Color := clRed
else Z.Brush.Color := clWhite;
end;
end;
{ The following function evaluates the system of logic equations. }
procedure Eval;
var
i :integer;
funcCount :integer;
CurVar :char;
prevVals :variables;
{ CmpVars- Compares two arrays of type "variables" and returns }
{ true if they are equal. }
function CmpVars(var v1, v2:Variables):boolean;
assembler;
asm
push ds
les di, v2
lds si, v1
mov cx, 27
repe cmpsw
mov ax, 1
cmp cx, 0
je @@0
mov ax, 0
@@0:
pop ds
end;
{ EvalOnce- Evaluates all the active logic equations one time each. }
{ This function returns the number of active logic equa- }
{ tions in the system. Note that for a complete logic }
{ system evaluation, that is, to allow values to propogate}
{ throughout the system of equations, you must evaluate }
{ the set of equations at least n times where "n" is the }
{ number of logic equations in the system. }
function EvalOnce:integer;
var
funcName: char;
val: integer;
begin
Result := 0;
{ The following loop, in conjunction with the IF stmt, executes once }
{ for each active equation in the system. }
for funcName := 'A' to 'Z' do
if funcName in EqnSet then
begin
{ The following case statement handles the case where the current }
{ equation has zero, one, two, three, or four variables. It com- }
{ putes the new value by using a lookup based on the current vari-}
{ able values. }
case TruthTbls[funcName].NumVars of
0: val := TruthTbls[funcName].tt[Values['@'],0,0,0,0];
1: val := TruthTbls[funcName].tt[Values['@'],0,0,0,
Values[TruthTbls[funcName].theVars[0]]];
2: val := TruthTbls[funcName].tt[Values['@'],0,0,
Values[TruthTbls[funcName].theVars[1]],
Values[TruthTbls[funcName].theVars[0]]];
3: val := TruthTbls[funcName].tt[Values['@'],0,
Values[TruthTbls[funcName].theVars[2]],
Values[TruthTbls[funcName].theVars[1]],
Values[TruthTbls[funcName].theVars[0]]];
4: val := TruthTbls[funcName].tt[Values['@'],
Values[TruthTbls[funcName].theVars[3]],
Values[TruthTbls[funcName].theVars[2]],
Values[TruthTbls[funcName].theVars[1]],
Values[TruthTbls[funcName].theVars[0]]];
end;
{ Update the current function's variable with the value obtained above. }
Values[funcName] := val;
{ Count the number of functions we've processed down here. }
inc(Result);
end;
end;
begin {Eval}
{ Call EvalOnce to obtain the number of functions in the system. }
{ Bump this value by one since we've got the clock variable to worry}
{ about, as well. }
funcCount := EvalOnce + 1;
{ Evaluate the system of equations "funcCount" times. This gives }
{ us a total of "n+2" evaluations where "n" is the number of funcs. }
{ The first extra execution is for the clock variable, the second }
{ extra execution provides a safety margin. }
for i := 1 to funcCount do EvalOnce;
{ Now let's check for instability. Save the current set of values }
{ and execute the set of equations one more time. If the system is }
{ stable, we should obtain the exact same set of values. If the }
{ system is unstable, they will differ. }
prevVals := Values;
EvalOnce;
{ If the system is unstable, turn on the Instability annunciator. }
{ If the system is stable, turn the annunciator off. }
if CmpVars(prevVals,Values) then
LogicEval.InstabilityAnnunc.Color := clGray
else LogicEval.InstabilityAnnunc.Color := clRed;
{ Throughout the operations above, EvalOnce stored results directly }
{ into the Values array rather than (correctly) calling SetVar. The }
{ reason is because EvalOnce would call SetVar a tremendous number }
{ of times and SetVar is rather slow. Therefore, we need to call }
{ SetVar once for each variable to ensure that all LEDs, display }
{ values, etc., are properly updated. }
for CurVar := '@' to 'Z' do
SetVar(CurVar,Values[CurVar]);
end;
{ The following procedures handle button toggle events. Whenever the }
{ user toggles one of the four input values (A..D) the following pro- }
{ cedures adjust the values of the corresponding variables and then }
{ they evaluate the system of logic equations. }
procedure TLogicEval.AOff(Sender: TObject);
begin
SetVar('A',0);
Eval;
end;
procedure TLogicEval.AOn(Sender: TObject);
begin
SetVar('A',1);
Eval;
end;
procedure TLogicEval.BOff(Sender: TObject);
begin
SetVar('B',0);
Eval;
end;
procedure TLogicEval.BOn(Sender: TObject);
begin
SetVar('B',1);
Eval;
end;
procedure TLogicEval.COn(Sender: TObject);
begin
SetVar('C',1);
Eval;
end;
procedure TLogicEval.COff(Sender: TObject);
begin
SetVar('C',0);
Eval;
end;
procedure TLogicEval.DOff(Sender: TObject);
begin
SetVar('D',0);
Eval;
end;
procedure TLogicEval.DOn(Sender: TObject);
begin
SetVar('D',1);
Eval;
end;
{ If the user hits the "Pulse" button, set the clock to zero and eval- }
{ uate the system, set the clock to one and evaluate the system, and }
{ then set the clock back to zero and reevaluate the equations. }
procedure TLogicEval.PulseBtnClick(Sender: TObject);
begin
Values['@'] := 0;
Eval;
Values['@'] := 1;
Eval;
Values['@'] := 0;
Eval;
end;
{ The system calls the following functions whenever the user clicks on }
{ one of the buttons on the initialization page. This code figures }
{ out which button was pressed and toggles its value. The InitClick }
{ procedure runs whenever the user clicks on the panel (button), the }
{ ValueClick procedure runs if the users clicks on the actual value }
{ within the panel. }
procedure TLogicEval.InitClick(Sender: TObject);
var name:char;
begin
{The first character of the Box's Caption is the variable's name. }
name := (Sender as TGroupBox).Caption[1];
{ Fetch that variable's value, invert it, and write it back. }
SetVar(Name, Values[name] xor 1);
end;
procedure TLogicEval.ValueClick(Sender: TObject);
var name:char;
begin
name := ((Sender as TLabel).Parent as TGroupBox).Caption[1];
SetVar(Name, Values[name] xor 1);
end;
{ If the user presses the "ADD" button, bring up the equation dialog }
{ box and let them add a new equation to the system. }
procedure TLogicEval.AddEqnBtnClick(Sender: TObject);
begin
EqnDlg.InputEqn.SelectAll; {Select equation inside dialog box. }
EqnDlg.Show; {Open the equation dialog box. }
end;
{ If the user clicks on an equation in the equation list box, update }
{ the truth table on the create page to display the truth table for }
{ the selected equation. }
procedure TLogicEval.EqnListClick(Sender: TObject);
var ch:char;
begin
if (EqnList.ItemIndex <> -1) then {Make sure there is a selection. }
begin
ch := EqnList.Items[EqnList.ItemIndex][1]; {Get function name. }
DrawTruths(TruthTbls[ch]); {Draw that function's truth table. }
end;
end;
{ If the user double-clicks on an equation in the equation list box, }
{ then bring up the equation editor dialog box and let them edit this }
{ equation. }
procedure TLogicEval.EqnListDblClick(Sender: TObject);
begin
if (EqnList.ItemIndex <> -1) then {Is there a selection? }
begin
{ Grab the equation the user just selected and make it the }
{ default equation in the equation dialog box. }
EqnDlg.InputEqn.Text := EqnList.Items[EqnList.ItemIndex];
{ Select the equation. }
EqnDlg.InputEqn.SelectAll;
{ Bring up the equation editor dialog box. }
EqnDlg.Show;
end;
end;
{ If the user presses the edit button and there is a selected equation }
{ in the equation list box, open up the equation editor dialog box and }
{ let the user edit that equation. }
procedure TLogicEval.EditBtnClick(Sender: TObject);
begin
{ If there is a selected equation, copy it to the default }
{ equation in the equation editor dialog box. If there is no }
{ such equation available, just use the current default equa- }
{ tion when it opens the equation editor dialog box. }
if (EqnList.Items.Count <> 0) then {Are there any equations? }
if (EqnList.ItemIndex <> -1) then {Is an equation selected? }
EqnDlg.InputEqn.Text := EqnList.Items[EqnList.ItemIndex];
{ Select the equation and open up the dialog box. }
EqnDlg.InputEqn.SelectAll;
EqnDlg.Show;
end;
{ If the user has selected and equation and presses the delete button, }
{ the following procedure deletes that equation from the list and re- }
{ moves that function definition from the EqnSet. }
procedure TLogicEval.DeleteBtnClick(Sender: TObject);
var ch: char;
dummy: TruthType;
begin
if (EqnList.ItemIndex <> -1) then {Is there an equation selected? }
begin
{ Make sure the user really wants to do this. }
if MessageDlg('Okay to delete ' +
EqnList.Items[EqnList.ItemIndex] + '?',
mtWarning, [mbYes, mbNo], 0) = mrYes then
begin
{ Remove the equation from our equation set. }
EqnSet := EqnSet - [EqnList.Items[EqnList.ItemIndex][1]];
{ Remove the equation from the list of equations. }
EqnList.Items.Delete(EqnList.ItemIndex);
{ Since there is no longer a selected equation in the }
{ equation list, clear the truth tables. }
dummy.NumVars := 0;
DrawTruths(dummy);
end;
end;
end;
{ Miscellaneous procedures to handle the PRINT, ABOUT, and EXIT buttons }
{ found on each page of the form. }
procedure TLogicEval.PrintBtnClick(Sender: TObject);
begin
if (PrintDialog.Execute) then
begin
LogicEval.Print;
end;
end;
procedure TLogicEval.ExitBtnClick(Sender: TObject);
begin
Halt;
end;
procedure TLogicEval.AboutBtn2Click(Sender: TObject);
begin
AboutBox.Show;
end;
procedure TLogicEval.ScreensChange( Sender: TObject;
NewTab: Integer;
var AllowChange: Boolean);
var
i: integer;
begin
AllowChange := true;
if NewTab = 2 then
begin
ExecEqns.Clear;
for i := 0 to EqnList.Items.Count - 1 do
ExecEqns.Lines.Add(EqnList.Items[i]);
Eval;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -