https://github.com/virtualagc/virtualagc
Tip revision: a4a63bc20b80eae78970dbffa2ff02cebc6b61d7 authored by Mike Stewart on 24 December 2020, 18:51:12 UTC
Manche45R2: incorporated the R-2 potential model, which makes all checksums correct.
Manche45R2: incorporated the R-2 potential model, which makes all checksums correct.
Tip revision: a4a63bc
yaDSKY2.cpp
// -*- C++ -*- generated by wxGlade 0.6.3 on Fri Mar 6 23:28:00 2009
/*
* Copyright 2009,2016,2017 Ronald S. Burkey <info@sandroid.org>
*
* This file is part of yaAGC.
*
* yaAGC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* yaAGC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with yaAGC; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Filename: yaDSKY2.cpp
* Contact: Ron Burkey <info@sandroid.org>
* Reference: http://www.ibiblio.org/apollo/index.html
* Mods: 2009-03-06 RSB Began adapting from yaDSKY.
* 2009-03-12 RSB First working version.
* 2009-03-14 RSB Added a workaround for a funky socket
* error which was showing up in Windows
* for the yaTelemetry program (which uses
* identical socket-management code) but
* which wasn't showing up here for some
* reason ... yet. Eliminated some
* compiler warnings due to now-deprecated
* initializers for char *.
* 2009-03-27 RSB Added hotkeys. They don't work, but I
* added them.
* 2009-06-13 RSB Added stuff for mapping verb-noun patterns
* to optional commands to be executed on the
* PC running the simulation. This is all the
* stuff with names like *MATCH* or *Match*.
* 2009-06-14 RSB Added the "startup" pattern.
* 2009-06-17 RSB On Windows XP, a pop-up box appears at
* startup when DSKY2.matches doesn't exist.
* Silly me! Why didn't I notice that?
* A separate check of the file's existence
* is now performed to eliminate that.
* 2009-11-12 RSB Changed the flashing duty cycle from 1:1
* to 3:1 (high:low) to match what Christian
* Bucher has found on the Apollo 11 TV
* transmissions. Increased the flashing
* frequency as well, by about 20%. It's
* still not accurate.
* 2016-10-01 MAS Converted several signals over to the new
* fictitious channel 163, driven by the AGC.
* The flashing timing is now driven by the
* AGC itself, as was the actual DSKY, and the
* timing should be very accurate. RESTART and
* STANDBY lights should now work. PROCEED has
* been changed such that it can be held down,
* so it's possible to go to standby.
* 2016-10-05 MAS Re-implemented PROCEED logic to be compatible
* with older wxwidgets.
* 2016-11-02 MAS Made + higher priority than - when both sign
* bits are set, based on newly discovered
* diagrams of DSKY relay wiring. This fixes
* the Aurora12/Sunburst 120 DSKY relay test.
* 2016-12-05 RSB Changed EVT_CHAR to EVT_CHAR_HOOK to make
* hotkeys work. Thanks to Chris Beecham for
* sending in this fix! It still doesn't work
* quite right (for me, at least), in that the
* hotkeys aren't recognized until at least
* one click of the virtual buttons, but it's
* a lot better than not working at all.
* 2017-01-15 MAS Set sane defaults for the indicators when
* no config is present.
* 2017-08-24 RSB Eliminated a clang warning.
* 2017-12-11 RSB Added ability to click PROG indicator
* (for playback of pre-canned scripts).
* 2017-12-12 RSB Prevented from returning keystrokes to
* AGC during script playback. Added keypad
* indications for logged keystrokes during
* playback. Added ability to record, from
* TRACKER.
*
* The yaDSKY2 program is intended to be a completely identical drop-in
* replacement for the yaDSKY program as it exists at 2009-03-06.
* yaDSKY works well, but it suffers from the basic problem that GTK+
* support for Mac OS X (and even to some extent for Win32) is not
* where I want it to be. Furthermore, newer GUI programs for yaAGC
* are based on wxWidgets, where I have been having better luck with
* Win32/Mac support. So in other words, yaDSKY2 is a wxWidgets port
* of the GTK+ based yaDSKY program.
*/
#include "yaDSKY2.h"
#define VER(x) #x
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
using namespace std;
#include "wx/filefn.h"
#include <wx/stdpaths.h>
#include "../yaAGC/yaAGC.h"
#include "../yaAGC/agc_engine.h"
#ifdef __clang__
extern "C" FILE *rfopen (const char *Filename, const char *mode);
#else
FILE *
rfopen (const char *Filename, const char *mode);
#endif
static MainFrame* MainWindow;
int HalfSize = 0;
#define PULSE_INTERVAL 80
static char DefaultHostname[] = "localhost";
char *Hostname = DefaultHostname;
static char NonDefaultHostname[129];
#ifdef WIN32
static int StartupDelay = 500;
#else
static int StartupDelay = 0;
#endif
static int DebugCounterMode = 0;
static int DebugCounterReg = 032, DebugCounterInc = 1, DebugCounterWhich = 1;
// TestUplink is set when we want to test the digital uplink by emitting
// keycodes on the digital uplink rather than on the DSKY channels.
static int TestUplink = 0;
static int ServerSocket = -1;
static bool ProceedPressed = false;
static const char SevenSeg0[] = "7Seg-0.jpg";
// Here are the defaults used for indicator lamps in the absence of a configuration file.
// In cases where we don't know that channel/bit corresponds to the lamp, we use
// channel -1.
static const char UplinkActyOnJpeg[] = "UplinkActyOn.jpg", UplinkActyOffJpeg[] =
"UplinkActyOff.jpg", NoAttOnJpeg[] = "NoAttOn.jpg", NoAttOffJpeg[] =
"NoAttOff.jpg", StbyOnJpeg[] = "StbyOn.jpg", StbyOffJpeg[] = "StbyOff.jpg",
KeyRelOnJpeg[] = "KeyRelOn.jpg", KeyRelOffJpeg[] = "KeyRelOff.jpg",
OprErrOnJpeg[] = "OprErrOn.jpg", OprErrOffJpeg[] = "OprErrOff.jpg",
PrioDispOnJpeg[] = "PrioDispOn.jpg", PrioDispOffJpeg[] = "PrioDispOff.jpg",
NoDapOnJpeg[] = "NoDapOn.jpg", NoDapOffJpeg[] = "NoDapOff.jpg",
TempOnJpeg[] = "TempOn.jpg", TempOffJpeg[] = "TempOff.jpg",
GimbalLockOnJpeg[] = "GimbalLockOn.jpg", GimbalLockOffJpeg[] =
"GimbalLockOff.jpg", ProgOnJpeg[] = "ProgOn.jpg", ProgOffJpeg[] =
"ProgOff.jpg", RestartOnJpeg[] = "RestartOn.jpg", RestartOffJpeg[] =
"RestartOff.jpg", TrackerOnJpeg[] = "TrackerOn.jpg", TrackerOffJpeg[] =
"TrackerOff.jpg", AltOnJpeg[] = "AltOn.jpg",
AltOffJpeg[] = "AltOff.jpg", VelOnJpeg[] = "VelOn.jpg", VelOffJpeg[] =
"VelOff.jpg";
static Ind_t Inds[14] =
{
{ // 11
UplinkActyOnJpeg, UplinkActyOffJpeg, 011, 04, 0, 0, 0, 0, 0, 0 },
{ // 12
NoAttOnJpeg, NoAttOffJpeg, 010, 010, 0, 0, 0, 1, 074000, 060000 },
{ // 13
StbyOnJpeg, StbyOffJpeg, 0163, 0400, 0, 0, 0, 0, 0, 0 },
{ // 14
KeyRelOnJpeg, KeyRelOffJpeg, 0163, 020, 0, 0, 0, 0, 0, 0 },
{ // 15
OprErrOnJpeg, OprErrOffJpeg, 0163, 0100, 0, 0, 0, 0, 0, 0 },
{ // 16
PrioDispOnJpeg, PrioDispOffJpeg, 010, 01, 0, 0, 0, 1, 074000, 060000 },
{ // 17
NoDapOnJpeg, NoDapOffJpeg, 010, 02, 0, 0, 0, 1, 074000, 060000 },
{ // 21
TempOnJpeg, TempOffJpeg, 011, 010, 0, 0, 0, 0, 0, 0 },
{ // 22
GimbalLockOnJpeg, GimbalLockOffJpeg, 010, 040, 0, 0, 0, 1, 074000,
060000 },
{ // 23
ProgOnJpeg, ProgOffJpeg, 010, 0400, 0, 0, 0, 1, 074000, 060000 },
{ // 24
RestartOnJpeg, RestartOffJpeg, 0163, 0200, 0, 0, 0, 0, 0, 0 },
{ // 25
TrackerOnJpeg, TrackerOffJpeg, 010, 0200, 0, 0, 0, 1, 074000, 060000 },
{ // 26
AltOnJpeg, AltOffJpeg, 010, 020, 0, 0, 0, 1, 074000, 060000 },
{ // 27
VelOnJpeg, VelOffJpeg, 010, 04, 0, 0, 0, 1, 074000, 060000 } };
#define DEBUG(x)
// The following stuff relates to a feature used for giving presentations,
// in which patterns of DSKY keystrokes can be used to trigger commands on
// the computer running the simulation. All keystroke patterns begin with
// VERB, and contain at most one VERB. The array of possible mappings is
// filled up at boot time from the file DSKY2.matches, if it exists, and is
// empty otherwise. The buffer of actual keystrokes is, of course, filled
// at runtime. The syntax in DSKY2.matches (which is an ASCII file) is that
// there is a separate line for each mapping, of the form:
// pattern command
// The pattern consists of any string of the characters VN+-0123456788EPCRK
// followed by whitespace, followed by any string until the end-of-line is
// reached.
#define MAX_MATCHES 100
typedef struct
{
wxString *Pattern;
wxString *Command;
} Match_t;
static wxString Match = wxT (" ");
static Match_t Matches[MAX_MATCHES] =
{ NULL };
static int NumMatches = 0;
// begin wxGlade: ::extracode
// end wxGlade
MainFrame::MainFrame (wxWindow* parent, int id, const wxString& title,
const wxPoint& pos, const wxSize& size, long style) :
wxFrame (parent, id, title, pos, size,
wxCLOSE_BOX | wxMINIMIZE_BOX | wxCAPTION | wxSYSTEM_MENU)
{
// begin wxGlade: MainFrame::MainFrame
panel_1 = new wxPanel (this, wxID_ANY);
bitmap_5 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("FrameVertical.jpg"), wxBITMAP_TYPE_ANY));
bitmap_6_copy = new wxStaticBitmap (
this, wxID_ANY,
wxBitmap (wxT ("FrameHorizontal.jpg"), wxBITMAP_TYPE_ANY));
Annunciator11 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator21 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator12 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator22 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator13 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator23 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator14 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator24 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator15 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator25 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator16 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator26 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator17 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
Annunciator27 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("UplinkActyOff.jpg"), wxBITMAP_TYPE_ANY));
bitmap_6 = new wxStaticBitmap (
this, wxID_ANY,
wxBitmap (wxT ("FrameHorizontal.jpg"), wxBITMAP_TYPE_ANY));
bitmap_5_copy = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("FrameVertical.jpg"), wxBITMAP_TYPE_ANY));
bitmap_5_copy_1 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("FrameVertical.jpg"), wxBITMAP_TYPE_ANY));
bitmap_6_copy_copy = new wxStaticBitmap (
this, wxID_ANY,
wxBitmap (wxT ("FrameHorizontal.jpg"), wxBITMAP_TYPE_ANY));
CompActyAnnunciator = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("CompActyOff.jpg"), wxBITMAP_TYPE_ANY));
ModeAnnunciator = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("rProgOn.jpg"), wxBITMAP_TYPE_ANY));
MD1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
MD2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
VerbAnnunciator = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("VerbOn.jpg"), wxBITMAP_TYPE_ANY));
VD1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
VD2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
NounAnnunciator = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("NounOn.jpg"), wxBITMAP_TYPE_ANY));
ND1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
ND2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
bitmap_2_copy_1 = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("SeparatorOn.jpg"), wxBITMAP_TYPE_ANY));
R1PlusMinus = new wxStaticBitmap (
panel_1, wxID_ANY,
wxBitmap (wxT ("PlusMinusOff.jpg"), wxBITMAP_TYPE_ANY));
R1D1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R1D2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R1D3Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R1D4Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R1D5Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
bitmap_2_copy = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("SeparatorOn.jpg"), wxBITMAP_TYPE_ANY));
R2PlusMinus = new wxStaticBitmap (
panel_1, wxID_ANY,
wxBitmap (wxT ("PlusMinusOff.jpg"), wxBITMAP_TYPE_ANY));
R2D1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R2D2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R2D3Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R2D4Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R2D5Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
bitmap_2 = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("SeparatorOn.jpg"), wxBITMAP_TYPE_ANY));
R3PlusMinus = new wxStaticBitmap (
panel_1, wxID_ANY,
wxBitmap (wxT ("PlusMinusOff.jpg"), wxBITMAP_TYPE_ANY));
R3D1Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R3D2Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R3D3Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R3D4Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
R3D5Digit = new wxStaticBitmap (
panel_1, wxID_ANY, wxBitmap (wxT ("7Seg-0.jpg"), wxBITMAP_TYPE_ANY));
bitmap_6_copy_copy_copy = new wxStaticBitmap (
this, wxID_ANY,
wxBitmap (wxT ("FrameHorizontal.jpg"), wxBITMAP_TYPE_ANY));
bitmap_5_copy_2 = new wxStaticBitmap (
this, wxID_ANY, wxBitmap (wxT ("FrameVertical.jpg"), wxBITMAP_TYPE_ANY));
VerbBitmap = wxBitmap (wxT ("VerbUp.jpg"), wxBITMAP_TYPE_ANY);
NounBitmap = wxBitmap (wxT ("NounUp.jpg"), wxBITMAP_TYPE_ANY);
PlusBitmap = wxBitmap (wxT ("PlusUp.jpg"), wxBITMAP_TYPE_ANY);
MinusBitmap = wxBitmap (wxT ("MinusUp.jpg"), wxBITMAP_TYPE_ANY);
ZeroBitmap = wxBitmap (wxT ("0Up.jpg"), wxBITMAP_TYPE_ANY);
SevenBitmap = wxBitmap (wxT ("7Up.jpg"), wxBITMAP_TYPE_ANY);
FourBitmap = wxBitmap (wxT ("4Up.jpg"), wxBITMAP_TYPE_ANY);
OneBitmap = wxBitmap (wxT ("1Up.jpg"), wxBITMAP_TYPE_ANY);
EightBitmap = wxBitmap (wxT ("8Up.jpg"), wxBITMAP_TYPE_ANY);
FiveBitmap = wxBitmap (wxT ("5Up.jpg"), wxBITMAP_TYPE_ANY);
TwoBitmap = wxBitmap (wxT ("2Up.jpg"), wxBITMAP_TYPE_ANY);
NineBitmap = wxBitmap (wxT ("9Up.jpg"), wxBITMAP_TYPE_ANY);
SixBitmap = wxBitmap (wxT ("6Up.jpg"), wxBITMAP_TYPE_ANY);
ThreeBitmap = wxBitmap (wxT ("3Up.jpg"), wxBITMAP_TYPE_ANY);
ClrBitmap = wxBitmap (wxT ("ClrUp.jpg"), wxBITMAP_TYPE_ANY);
ProBitmap = wxBitmap (wxT ("ProUp.jpg"), wxBITMAP_TYPE_ANY);
KeyRelBitmap = wxBitmap (wxT ("KeyRelUp.jpg"), wxBITMAP_TYPE_ANY);
EntrBitmap = wxBitmap (wxT ("EntrUp.jpg"), wxBITMAP_TYPE_ANY);
RsetBitmap = wxBitmap (wxT ("RsetUp.jpg"), wxBITMAP_TYPE_ANY);
VerbButton = new wxBitmapButton (this, ID_VERBBUTTON, VerbBitmap);
NounButton = new wxBitmapButton (this, ID_NOUNBUTTON, NounBitmap);
PlusButton = new wxBitmapButton (this, ID_PLUSBUTTON, PlusBitmap);
MinusButton = new wxBitmapButton (this, ID_MINUSBUTTON, MinusBitmap);
ZeroButton = new wxBitmapButton (this, ID_ZEROBUTTON, ZeroBitmap);
SevenButton = new wxBitmapButton (this, ID_SEVENBUTTON, SevenBitmap);
FourButton = new wxBitmapButton (this, ID_FOURBUTTON, FourBitmap);
OneButton = new wxBitmapButton (this, ID_ONEBUTTON, OneBitmap);
EightButton = new wxBitmapButton (this, ID_EIGHTBUTTON, EightBitmap);
FiveButton = new wxBitmapButton (this, ID_FIVEBUTTON, FiveBitmap);
TwoButton = new wxBitmapButton (this, ID_TWOBUTTON, TwoBitmap);
NineButton = new wxBitmapButton (this, ID_NINEBUTTON, NineBitmap);
SixButton = new wxBitmapButton (this, ID_SIXBUTTON, SixBitmap);
ThreeButton = new wxBitmapButton (this, ID_THREEBUTTON, ThreeBitmap);
ClrButton = new wxBitmapButton (this, ID_CLRBUTTON, ClrBitmap);
ProButton = new wxBitmapButton (this, ID_PROBUTTON, ProBitmap);
KeyRelButton = new wxBitmapButton (this, ID_KEYRELBUTTON, KeyRelBitmap);
EntrButton = new wxBitmapButton (this, ID_ENTRBUTTON, EntrBitmap);
RsetButton = new wxBitmapButton (this, ID_RSETBUTTON, RsetBitmap);
ProButton->Connect (wxEVT_LEFT_DOWN,
wxMouseEventHandler (MainFrame::on_ProButton_pressed),
NULL,
this);
Annunciator23->Connect (
wxEVT_LEFT_DOWN,
wxMouseEventHandler (MainFrame::on_Annunciator23_clicked), NULL, this);
Annunciator25->Connect (
wxEVT_LEFT_DOWN,
wxMouseEventHandler (MainFrame::on_Annunciator25_clicked), NULL, this);
scriptFileOpen = false;
numScriptKeysPressed = 0;
last11 = last13 = last163 = 0;
for (int i = 0; i < 16; last10[i++] = 0)
;
set_properties ();
do_layout ();
// end wxGlade
}
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
// begin wxGlade: MainFrame::event_table
EVT_BUTTON(ID_VERBBUTTON, MainFrame::on_VerbButton_pressed)
EVT_BUTTON(ID_NOUNBUTTON, MainFrame::on_NounButton_pressed)
EVT_BUTTON(ID_PLUSBUTTON, MainFrame::on_PlusButton_pressed)
EVT_BUTTON(ID_MINUSBUTTON, MainFrame::on_MinusButton_pressed)
EVT_BUTTON(ID_ZEROBUTTON, MainFrame::on_ZeroButton_pressed)
EVT_BUTTON(ID_SEVENBUTTON, MainFrame::on_SevenButton_pressed)
EVT_BUTTON(ID_FOURBUTTON, MainFrame::on_FourButton_pressed)
EVT_BUTTON(ID_ONEBUTTON, MainFrame::on_OneButton_pressed)
EVT_BUTTON(ID_EIGHTBUTTON, MainFrame::on_EightButton_pressed)
EVT_BUTTON(ID_FIVEBUTTON, MainFrame::on_FiveButton_pressed)
EVT_BUTTON(ID_TWOBUTTON, MainFrame::on_TwoButton_pressed)
EVT_BUTTON(ID_NINEBUTTON, MainFrame::on_NineButton_pressed)
EVT_BUTTON(ID_SIXBUTTON, MainFrame::on_SixButton_pressed)
EVT_BUTTON(ID_THREEBUTTON, MainFrame::on_ThreeButton_pressed)
EVT_BUTTON(ID_CLRBUTTON, MainFrame::on_ClrButton_pressed)
EVT_BUTTON(ID_KEYRELBUTTON, MainFrame::on_KeyRelButton_pressed)
EVT_BUTTON(ID_ENTRBUTTON, MainFrame::on_EntrButton_pressed)
EVT_BUTTON(ID_RSETBUTTON, MainFrame::on_RsetButton_pressed)
EVT_BUTTON(ID_PROBUTTON, MainFrame::on_ProButton_released)
// end wxGlade
EVT_CHAR_HOOK(MainFrame::HotkeyEvent)
END_EVENT_TABLE();
void
MainFrame::HotkeyEvent (wxKeyEvent &KeyEvent)
{
wxCommandEvent event;
int k = KeyEvent.GetKeyCode ();
//wxMessageBox ((char) k, wxT ("Info"));
switch (k)
{
case '0':
on_ZeroButton_pressed (event);
break;
case '1':
on_OneButton_pressed (event);
break;
case '2':
on_TwoButton_pressed (event);
break;
case '3':
on_ThreeButton_pressed (event);
break;
case '4':
on_FourButton_pressed (event);
break;
case '5':
on_FiveButton_pressed (event);
break;
case '6':
on_SixButton_pressed (event);
break;
case '7':
on_SevenButton_pressed (event);
break;
case '8':
on_EightButton_pressed (event);
break;
case '9':
on_NineButton_pressed (event);
break;
case '+':
on_PlusButton_pressed (event);
break;
case '-':
on_MinusButton_pressed (event);
break;
case 'v':
case 'V':
on_VerbButton_pressed (event);
break;
case 'n':
case 'N':
on_NounButton_pressed (event);
break;
case 'e':
case 'E':
on_EntrButton_pressed (event);
break;
default:
event.Skip ();
break;
}
}
void
MainFrame::on_VerbButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
DebugCounterWhich = 1;
DebugCounterInc = 0;
}
else
OutputKeycode (17);
if (NumMatches)
{
Match = wxT ("V");
MatchCheck ();
}
}
void
MainFrame::on_NounButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
DebugCounterWhich = 0;
DebugCounterReg = 0;
}
else
OutputKeycode (31);
if (NumMatches)
{
Match += wxT ("N");
MatchCheck ();
}
}
void
MainFrame::on_PlusButton_pressed (wxCommandEvent &event)
{
OutputKeycode (26);
if (NumMatches)
{
Match += wxT ("+");
MatchCheck ();
}
}
void
MainFrame::on_MinusButton_pressed (wxCommandEvent &event)
{
OutputKeycode (27);
if (NumMatches)
{
Match += wxT ("-");
MatchCheck ();
}
}
void
MainFrame::on_ZeroButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 0;
else
DebugCounterReg = (DebugCounterReg * 8) + 0;
}
else
OutputKeycode (16);
if (NumMatches)
{
Match += wxT ("0");
MatchCheck ();
}
}
void
MainFrame::on_SevenButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 7;
else
DebugCounterReg = (DebugCounterReg * 8) + 7;
}
else
OutputKeycode (7);
if (NumMatches)
{
Match += wxT ("7");
MatchCheck ();
}
}
void
MainFrame::on_FourButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 4;
else
DebugCounterReg = (DebugCounterReg * 8) + 4;
}
else
OutputKeycode (4);
if (NumMatches)
{
Match += wxT ("4");
MatchCheck ();
}
}
void
MainFrame::on_OneButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 1;
else
DebugCounterReg = (DebugCounterReg * 8) + 1;
}
else
OutputKeycode (1);
if (NumMatches)
{
Match += wxT ("1");
MatchCheck ();
}
}
void
MainFrame::on_EightButton_pressed (wxCommandEvent &event)
{
OutputKeycode (8);
if (NumMatches)
{
Match += wxT ("8");
MatchCheck ();
}
}
void
MainFrame::on_FiveButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 5;
else
DebugCounterReg = (DebugCounterReg * 8) + 5;
}
else
OutputKeycode (5);
if (NumMatches)
{
Match += wxT ("5");
MatchCheck ();
}
}
void
MainFrame::on_ThreeButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 3;
else
DebugCounterReg = (DebugCounterReg * 8) + 3;
}
else
OutputKeycode (3);
if (NumMatches)
{
Match += wxT ("3");
MatchCheck ();
}
}
void
MainFrame::on_TwoButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 2;
else
DebugCounterReg = (DebugCounterReg * 8) + 2;
}
else
OutputKeycode (2);
if (NumMatches)
{
Match += wxT ("2");
MatchCheck ();
}
}
void
MainFrame::on_NineButton_pressed (wxCommandEvent &event)
{
OutputKeycode (9);
if (NumMatches)
{
Match += wxT ("9");
MatchCheck ();
}
}
void
MainFrame::on_SixButton_pressed (wxCommandEvent &event)
{
if (DebugCounterMode)
{
if (DebugCounterWhich)
DebugCounterInc = 6;
else
DebugCounterReg = (DebugCounterReg * 8) + 6;
}
else
OutputKeycode (6);
if (NumMatches)
{
Match += wxT ("6");
MatchCheck ();
}
}
void
MainFrame::on_ClrButton_pressed (wxCommandEvent &event)
{
OutputKeycode (30);
if (NumMatches)
{
Match += wxT ("C");
MatchCheck ();
}
}
void
MainFrame::on_ProButton_pressed (wxMouseEvent &event)
{
if (DebugCounterMode)
{
int j;
unsigned char Packet[4];
if (DebugCounterReg < 032 || DebugCounterReg > 060)
return;
if (DebugCounterInc < 0 || DebugCounterInc > 6)
return;
Packet[0] = 0x10 | ((DebugCounterReg >> 3) & 0x0f);
Packet[1] = 0x40 | ((DebugCounterReg & 7) << 3);
Packet[2] = 0x80;
Packet[3] = 0xC0 | (DebugCounterInc & 7);
//printf ("Reg=%02o Inc=%o Packet=%02x %02x %02x %02x\n",
// DebugCounterReg, DebugCounterInc,
// Packet[0], Packet[1], Packet[2], Packet[3]);
if (ServerSocket != -1)
{
j = send (ServerSocket, (const char *) Packet, 4, MSG_NOSIGNAL);
if (j == SOCKET_ERROR && SOCKET_BROKEN)
{
if (!DebugMode)
printf ("Removing socket %d\n", ServerSocket);
#ifdef unix
close (ServerSocket);
#else
closesocket (ServerSocket);
#endif
ServerSocket = -1;
}
}
}
else
{
// Press.
OutputPro (0);
ProceedPressed = true;
}
if (NumMatches)
{
Match += wxT ("P");
MatchCheck ();
}
event.ResumePropagation (INT_MAX);
event.Skip ();
}
void
MainFrame::scriptFileProcessLine (void)
{
if (scriptFileCurrentLine >= scriptFileCount)
return;
wxString line = scriptFile.GetLine (scriptFileCurrentLine);
if (3
!= wxSscanf (line, wxT ("%lf %o %o"), &scriptFileDifferentialTime,
&scriptFileChannelNumber, &scriptFileChannelValue))
{
scriptFileDifferentialTime = 0;
scriptFileChannelNumber = 0;
scriptFileChannelValue = 0;
}
}
void
MainFrame::restoreToPrescript (void)
{
scriptFileChannelNumber = 011;
scriptFileChannelValue = last11;
Timer->ActOnIncomingIO ((unsigned char *) NULL);
scriptFileChannelNumber = 013;
scriptFileChannelValue = last13;
Timer->ActOnIncomingIO ((unsigned char *) NULL);
scriptFileChannelNumber = 0163;
scriptFileChannelValue = last163;
Timer->ActOnIncomingIO ((unsigned char *) NULL);
scriptFileChannelNumber = 010;
for (int i = 1; i < 13; i++)
{
scriptFileChannelValue = (i << 11) + last10[i];
Timer->ActOnIncomingIO ((unsigned char *) NULL);
}
numScriptKeysPressed = 0;
// Note that when the script indicates a keypress, we Disable() that
// key briefly and then reenable it. This is done solely because it
// was the only relatively-efficient way I could think to make a
// visual indication of the button press ... yes, not very good in
// terms of understandability, I know. At any rate, we have to
// make sure that the keys all get enabled at the end of the script.
ProButton->Enable ();
VerbButton->Enable ();
NounButton->Enable ();
ZeroButton->Enable ();
OneButton->Enable ();
TwoButton->Enable ();
ThreeButton->Enable ();
FourButton->Enable ();
FiveButton->Enable ();
SixButton->Enable ();
SevenButton->Enable ();
EightButton->Enable ();
NineButton->Enable ();
PlusButton->Enable ();
MinusButton->Enable ();
EntrButton->Enable ();
ClrButton->Enable ();
RsetButton->Enable ();
KeyRelButton->Enable ();
}
void
MainFrame::on_Annunciator23_clicked (wxMouseEvent &event)
{
// When you click on the PROG lamp, we want to:
// Save the current display settings (they're always already saved).
// Show a file-dialog to select a pre-canned script of i/o channel changes.
// Start playback of the pre-canned script, ignoring AGC commands
// After completion of playback,
// Show a message box.
// Restore the original display settings
// Quickly run through all of the pending commands from AGC.
// Start taking commands from the AGC again.
if (recordingFileOpen)
return;
if (scriptFileOpen)
{
wxMessageBox (wxT ("Script aborted by user."));
scriptFile.Close ();
scriptFileOpen = false;
restoreToPrescript ();
return;
}
wxFileDialog* OpenDialog = new wxFileDialog (
this, wxT ("Choose a pre-recorded i/o-channel script"), wxT ("."),
wxEmptyString, wxT ("Scripts (*.canned)|*.canned"), wxFD_OPEN,
wxDefaultPosition);
if (OpenDialog->ShowModal () == wxID_OK) // if the user click "Open" instead of "Cancel"
{
wxString scriptPath = OpenDialog->GetPath ();
scriptFile.Open (scriptPath);
scriptFileCount = scriptFile.GetLineCount ();
scriptFileCurrentLine = 0;
scriptFileProcessLine ();
scriptFileWaitUntil = scriptFileDifferentialTime;
wxMessageBox (
wxT ("Script (") + wxString::Format (wxT ("%i"), scriptFileCount)
+ wxT (" records) will start when this box closes."));
scriptFileStopWatch.Start ();
scriptFileOpen = true;
}
// Clean up after ourselves
OpenDialog->Destroy ();
event.ResumePropagation (INT_MAX);
event.Skip ();
}
void
MainFrame::on_Annunciator25_clicked (wxMouseEvent &event)
{
// When you first click on the TRACKER, we want to:
// Show a message box to say we're starting to record a canned script of i/o channel changes.
// Start recording.
// When you subsequently click TRACKER, we want to:
// Stop recording
if (scriptFileOpen)
return;
if (recordingFileOpen)
{
recordingFile.Write();
recordingFile.Close ();
recordingFileOpen = false;
wxMessageBox (wxT ("Recording completed by user."));
}
else
{
wxMessageBox (wxT ("Recording will commence when this box is closed."));
wxString documents = wxStandardPaths::Get().GetDocumentsDir();
recordingFile.Create (documents + wxT("/yaDSKY2-recorded.canned"));
recordingFileOpen = true;
scriptFileStopWatch.Start ();
recordingLastTime = 0;
}
event.ResumePropagation (INT_MAX);
event.Skip ();
}
void
MainFrame::on_KeyRelButton_pressed (wxCommandEvent &event)
{
OutputKeycode (25);
if (NumMatches)
{
Match += wxT ("K");
MatchCheck ();
}
}
void
MainFrame::on_EntrButton_pressed (wxCommandEvent &event)
{
OutputKeycode (28);
if (NumMatches)
{
Match += wxT ("E");
MatchCheck ();
}
}
void
MainFrame::on_RsetButton_pressed (wxCommandEvent &event)
{
OutputKeycode (18);
if (NumMatches)
{
Match += wxT ("R");
MatchCheck ();
}
}
// wxGlade: add MainFrame event handlers
void
MainFrame::on_ProButton_released (wxCommandEvent &event)
{
if (ProceedPressed)
{
OutputPro (1);
ProceedPressed = false;
}
}
void
MainFrame::set_properties ()
{
// begin wxGlade: MainFrame::set_properties
SetTitle (wxT ("yaDSKY2 by Ron Burkey"));
wxIcon _icon;
_icon.CopyFromBitmap (wxBitmap (wxT ("ApolloPatch2.png"), wxBITMAP_TYPE_ANY));
SetIcon (_icon);
panel_1->SetBackgroundColour (wxColour (160, 160, 160));
VerbButton->SetMinSize (wxSize (75, 75));
NounButton->SetMinSize (wxSize (75, 75));
PlusButton->SetMinSize (wxSize (75, 75));
MinusButton->SetMinSize (wxSize (75, 75));
ZeroButton->SetMinSize (wxSize (75, 75));
SevenButton->SetMinSize (wxSize (75, 75));
FourButton->SetMinSize (wxSize (75, 75));
OneButton->SetMinSize (wxSize (75, 75));
EightButton->SetMinSize (wxSize (75, 75));
FiveButton->SetMinSize (wxSize (75, 75));
TwoButton->SetMinSize (wxSize (75, 75));
NineButton->SetMinSize (wxSize (75, 75));
SixButton->SetMinSize (wxSize (75, 75));
ThreeButton->SetMinSize (wxSize (75, 75));
ClrButton->SetMinSize (wxSize (75, 75));
ProButton->SetMinSize (wxSize (75, 75));
KeyRelButton->SetMinSize (wxSize (75, 75));
EntrButton->SetMinSize (wxSize (75, 75));
RsetButton->SetMinSize (wxSize (75, 75));
// end wxGlade
}
void
MainFrame::do_layout ()
{
// begin wxGlade: MainFrame::do_layout
wxBoxSizer* sizer_1 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_3 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_4_copy = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_5_copy_3 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_5_copy_2 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_5_copy_1 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_5_copy = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_5 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_4 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_2 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_14 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_15 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_6 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_7 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_7_copy = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_7_copy_1 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_8 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_10_copy_1 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_11_copy_1 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_10_copy = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_11_copy = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_9 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_10 = new wxBoxSizer (wxVERTICAL);
wxBoxSizer* sizer_11 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_12 = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* sizer_13 = new wxBoxSizer (wxVERTICAL);
wxGridSizer* grid_sizer_1_copy = new wxGridSizer (7, 2, 9, 10);
sizer_1->Add (20, 15, 0, 0, 0);
sizer_2->Add (20, 20, 2, wxEXPAND, 0);
sizer_12->Add (bitmap_5, 0, 0, 0);
sizer_13->Add (bitmap_6_copy, 0, 0, 0);
sizer_13->Add (20, 5, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator11, 0,
wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL,
0);
grid_sizer_1_copy->Add (Annunciator21, 0,
wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL,
0);
grid_sizer_1_copy->Add (Annunciator12, 0,
wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL,
0);
grid_sizer_1_copy->Add (Annunciator22, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator13, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator23, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator14, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator24, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator15, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator25, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator16, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator26, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator17, 0, 0, 0);
grid_sizer_1_copy->Add (Annunciator27, 0, 0, 0);
sizer_13->Add (grid_sizer_1_copy, 0,
wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 0);
sizer_13->Add (20, 5, 0, 0, 0);
sizer_13->Add (bitmap_6, 0, 0, 0);
sizer_12->Add (sizer_13, 0, 0, 0);
sizer_12->Add (bitmap_5_copy, 0, 0, 0);
sizer_2->Add (sizer_12, 0, 0, 0);
sizer_2->Add (20, 20, 3, wxEXPAND, 0);
sizer_14->Add (bitmap_5_copy_1, 0, 0, 0);
sizer_15->Add (bitmap_6_copy_copy, 0, 0, 0);
sizer_9->Add (CompActyAnnunciator, 0, wxALIGN_CENTER_VERTICAL, 0);
sizer_9->Add (20, 20, 1, 0, 0);
sizer_10->Add (ModeAnnunciator, 0, 0, 0);
sizer_11->Add (MD1Digit, 0, 0, 0);
sizer_11->Add (MD2Digit, 0, 0, 0);
sizer_10->Add (sizer_11, 1, wxEXPAND, 0);
sizer_9->Add (sizer_10, 1, wxEXPAND, 0);
sizer_6->Add (sizer_9, 0, wxEXPAND, 0);
sizer_6->Add (20, 14, 0, 0, 0);
sizer_10_copy->Add (VerbAnnunciator, 0, 0, 0);
sizer_11_copy->Add (VD1Digit, 0, 0, 0);
sizer_11_copy->Add (VD2Digit, 0, 0, 0);
sizer_10_copy->Add (sizer_11_copy, 0, wxEXPAND, 0);
sizer_8->Add (sizer_10_copy, 1, wxEXPAND, 0);
sizer_8->Add (20, 20, 1, 0, 0);
sizer_10_copy_1->Add (NounAnnunciator, 0, 0, 0);
sizer_11_copy_1->Add (ND1Digit, 0, 0, 0);
sizer_11_copy_1->Add (ND2Digit, 0, 0, 0);
sizer_10_copy_1->Add (sizer_11_copy_1, 1, wxEXPAND, 0);
sizer_8->Add (sizer_10_copy_1, 1, wxEXPAND, 0);
sizer_6->Add (sizer_8, 1, wxEXPAND, 0);
sizer_6->Add (bitmap_2_copy_1, 0, wxALIGN_CENTER_HORIZONTAL, 0);
sizer_7_copy_1->Add (R1PlusMinus, 0, 0, 0);
sizer_7_copy_1->Add (R1D1Digit, 0, 0, 0);
sizer_7_copy_1->Add (R1D2Digit, 0, 0, 0);
sizer_7_copy_1->Add (R1D3Digit, 0, 0, 0);
sizer_7_copy_1->Add (R1D4Digit, 0, 0, 0);
sizer_7_copy_1->Add (R1D5Digit, 0, 0, 0);
sizer_6->Add (sizer_7_copy_1, 0, wxEXPAND, 0);
sizer_6->Add (bitmap_2_copy, 0, wxALIGN_CENTER_HORIZONTAL, 0);
sizer_7_copy->Add (R2PlusMinus, 0, 0, 0);
sizer_7_copy->Add (R2D1Digit, 0, 0, 0);
sizer_7_copy->Add (R2D2Digit, 0, 0, 0);
sizer_7_copy->Add (R2D3Digit, 0, 0, 0);
sizer_7_copy->Add (R2D4Digit, 0, 0, 0);
sizer_7_copy->Add (R2D5Digit, 0, 0, 0);
sizer_6->Add (sizer_7_copy, 0, wxEXPAND, 0);
sizer_6->Add (bitmap_2, 0, wxALIGN_CENTER_HORIZONTAL, 0);
sizer_7->Add (R3PlusMinus, 0, 0, 0);
sizer_7->Add (R3D1Digit, 0, 0, 0);
sizer_7->Add (R3D2Digit, 0, 0, 0);
sizer_7->Add (R3D3Digit, 0, 0, 0);
sizer_7->Add (R3D4Digit, 0, 0, 0);
sizer_7->Add (R3D5Digit, 0, 0, 0);
sizer_6->Add (sizer_7, 0, wxEXPAND, 0);
panel_1->SetSizer (sizer_6);
sizer_15->Add (panel_1, 1, wxEXPAND, 0);
sizer_15->Add (bitmap_6_copy_copy_copy, 0, 0, 0);
sizer_14->Add (sizer_15, 0, 0, 0);
sizer_14->Add (bitmap_5_copy_2, 0, 0, 0);
sizer_2->Add (sizer_14, 0, 0, 0);
sizer_2->Add (20, 20, 2, wxEXPAND, 0);
sizer_1->Add (sizer_2, 0, wxEXPAND, 0);
sizer_1->Add (20, 15, 0, 0, 0);
sizer_3->Add (8, 20, 0, 0, 0);
sizer_4->Add (20, 20, 1, 0, 0);
sizer_4->Add (VerbButton, 0, 0, 0);
sizer_4->Add (20, 5, 0, 0, 0);
sizer_4->Add (NounButton, 0, 0, 0);
sizer_4->Add (20, 20, 1, 0, 0);
sizer_3->Add (sizer_4, 0, wxEXPAND, 0);
sizer_3->Add (8, 20, 0, 0, 0);
sizer_5->Add (PlusButton, 0, 0, 0);
sizer_5->Add (20, 5, 0, 0, 0);
sizer_5->Add (MinusButton, 0, 0, 0);
sizer_5->Add (20, 5, 0, 0, 0);
sizer_5->Add (ZeroButton, 0, 0, 0);
sizer_3->Add (sizer_5, 0, 0, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_5_copy->Add (SevenButton, 0, 0, 0);
sizer_5_copy->Add (20, 5, 0, 0, 0);
sizer_5_copy->Add (FourButton, 0, 0, 0);
sizer_5_copy->Add (20, 5, 0, 0, 0);
sizer_5_copy->Add (OneButton, 0, 0, 0);
sizer_3->Add (sizer_5_copy, 0, 0, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_5_copy_1->Add (EightButton, 0, 0, 0);
sizer_5_copy_1->Add (20, 5, 0, 0, 0);
sizer_5_copy_1->Add (FiveButton, 0, 0, 0);
sizer_5_copy_1->Add (20, 5, 0, 0, 0);
sizer_5_copy_1->Add (TwoButton, 0, 0, 0);
sizer_3->Add (sizer_5_copy_1, 0, 0, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_5_copy_2->Add (NineButton, 0, 0, 0);
sizer_5_copy_2->Add (20, 5, 0, 0, 0);
sizer_5_copy_2->Add (SixButton, 0, 0, 0);
sizer_5_copy_2->Add (20, 5, 0, 0, 0);
sizer_5_copy_2->Add (ThreeButton, 0, 0, 0);
sizer_3->Add (sizer_5_copy_2, 0, 0, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_5_copy_3->Add (ClrButton, 0, 0, 0);
sizer_5_copy_3->Add (20, 5, 0, 0, 0);
sizer_5_copy_3->Add (ProButton, 0, 0, 0);
sizer_5_copy_3->Add (20, 5, 0, 0, 0);
sizer_5_copy_3->Add (KeyRelButton, 0, 0, 0);
sizer_3->Add (sizer_5_copy_3, 0, 0, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_4_copy->Add (20, 20, 1, 0, 0);
sizer_4_copy->Add (EntrButton, 0, 0, 0);
sizer_4_copy->Add (20, 5, 0, 0, 0);
sizer_4_copy->Add (RsetButton, 0, 0, 0);
sizer_4_copy->Add (20, 20, 1, 0, 0);
sizer_3->Add (sizer_4_copy, 0, wxEXPAND, 0);
sizer_3->Add (5, 20, 0, 0, 0);
sizer_1->Add (sizer_3, 1, 0, 0);
sizer_1->Add (20, 15, 0, 0, 0);
SetSizer (sizer_1);
sizer_1->Fit (this);
Layout ();
// end wxGlade
}
class yaDskyApp : public wxApp
{
public:
bool
OnInit ();
};
IMPLEMENT_APP (yaDskyApp)
bool
yaDskyApp::OnInit ()
{
int i, j, UsedCfg = 0;
wxInitAllImageHandlers ();
MainWindow = new MainFrame (NULL, wxID_ANY, wxEmptyString);
MainWindow->iLastButton = MainWindow->ProButton;
MainWindow->CurrentBlank = wxString::FromAscii (SevenSeg0);
MainWindow->CurrentVD1 = wxString::FromAscii (SevenSeg0);
MainWindow->CurrentVD2 = wxString::FromAscii (SevenSeg0);
MainWindow->CurrentND1 = wxString::FromAscii (SevenSeg0);
MainWindow->CurrentND2 = wxString::FromAscii (SevenSeg0);
SetTopWindow (MainWindow);
// Put pointers to all of the indicator lamps into an array for
// more-convenient access.
Inds[0].Widget = MainWindow->Annunciator11;
Inds[1].Widget = MainWindow->Annunciator12;
Inds[2].Widget = MainWindow->Annunciator13;
Inds[3].Widget = MainWindow->Annunciator14;
Inds[4].Widget = MainWindow->Annunciator15;
Inds[5].Widget = MainWindow->Annunciator16;
Inds[6].Widget = MainWindow->Annunciator17;
Inds[7].Widget = MainWindow->Annunciator21;
Inds[8].Widget = MainWindow->Annunciator22;
Inds[9].Widget = MainWindow->Annunciator23;
Inds[10].Widget = MainWindow->Annunciator24;
Inds[11].Widget = MainWindow->Annunciator25;
Inds[12].Widget = MainWindow->Annunciator26;
Inds[13].Widget = MainWindow->Annunciator27;
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
cout
<< string (
"yaDSKY2 Apollo DSKY simulation, ver " VER(NVER) ", built " __DATE__ " " __TIME__ "\n");
cout << string ("Copyright 2009,2017 by Ronald S. Burkey\n");
cout
<< string (
"Refer to http://www.ibiblio.org/apollo/index.html for more information.\n");
DEBUG (-1);
Portnum = 19697;
for (i = 1; i < argc; i++)
{
wxString Arg = argv[i];
wxString ArgStart = Arg.BeforeFirst ('=');
wxString ArgEnd = Arg.AfterFirst ('=');
cout << string ("Arg ");
cout << i;
cout << string (" = \"");
cout << string (Arg.mb_str ());
cout << string ("\"\n");
if (Arg.IsSameAs (wxT ("--relative-pixmaps")))
{
// Does nothing. Legacy from yaDSKY.
}
else if (Arg.IsSameAs (wxT ("--test-uplink")))
TestUplink = 1;
else if (Arg.IsSameAs (wxT ("--test-downlink")))
{
// Does nothing. Legacy from yaDSKY.
}
else if (ArgStart.IsSameAs (wxT ("--ip")))
{
strcpy (NonDefaultHostname, ArgEnd.char_str ());
Hostname = NonDefaultHostname;
}
else if (ArgStart.IsSameAs (wxT ("--port")))
{
long lPortnum;
ArgEnd.ToLong (&lPortnum);
Portnum = lPortnum;
if (Portnum <= 0 || Portnum >= 0x10000)
{
printf ("The --port switch is out of range. Must be 1-64K.\n");
goto Help;
}
}
else if (ArgStart.IsSameAs (wxT ("--cfg")))
{
if (MainWindow->ParseCfg (ArgEnd))
{
printf ("Aborting due to --cfg errors.\n");
goto Help;
}
UsedCfg = 1;
}
else if (Arg.IsSameAs (wxT ("--half-size")))
{
if (UsedCfg)
{
printf (
"The --half-size switch must precede the --cfg switch.\n");
goto Help;
}
HalfSize = 1;
MainWindow->HalveTheWindow ();
}
else if (ArgStart.IsSameAs (wxT ("--delay")))
{
long lj;
ArgEnd.ToLong (&lj);
StartupDelay = lj;
}
else if (Arg.IsSameAs (wxT ("--debug-counter-mode")))
DebugCounterMode = 1;
else
{
Help: printf ("USAGE:\n");
printf ("\tyaDSKY2 [OPTIONS]\n");
printf ("The available options are:\n");
printf ("--ip=Hostname\n");
printf (
"\tThe yaDSKY2 program and the yaAGC Apollo Guidance Computer simulation\n");
printf (
"\texist in a \"client/server\" relationship, in which the yaDSKY2 program\n");
printf (
"\tneeds to be aware of the IP address or symbolic name of the host \n");
printf (
"\tcomputer running the yaAGC program. By default, this is \"localhost\",\n");
printf (
"\tmeaning that both yaDSKY2 and yaAGC are running on the same computer.\n");
printf ("--port=Portnumber\n");
printf (
"\tBy default, yaDSKY2 attempts to connect to the yaAGC program using port\n");
printf (
"\tnumber %d. However, if more than one instance of yaDSKY2 is being\n",
Portnum);
printf (
"\trun, or if yaAGC has been configured to listen on different ports, then\n");
printf (
"\tdifferent port settings for yaDSKY2 are needed. Note that by default,\n");
printf ("\tyaAGC listens for new connections on ports %d-%d.\n",
Portnum, Portnum + 10 - 1);
printf ("--cfg=ConfigFilename\n");
printf (
"\tSelects a configuration file to be used, to allow different yaDSKY\n");
printf (
"\tsettings for LM vs. CM, or for different Apollo missions. The \n");
printf (
"\tconfiguration files presently known are LM0.ini, LM.ini, LM1.ini, and CM.ini. \n");
printf (
"\tBy default (no --cfg switch) LM settings are used, but not the LM.ini\n");
printf ("\tfile itself.\n");
printf ("--half-size\n");
printf (
"\tUses a half-size version of yaDSKY2, suitable for smaller graphical\n");
printf ("\tdisplays. If present, must precede --cfg.\n");
printf ("--delay=N\n");
printf (
"\t\"Start-up delay\", in ms. Defaults to %d. What the start-up\n",
StartupDelay);
printf (
"\tdelay does is to prevent yaDSKY2 from attempting to communicate with\n");
printf (
"\tyaAGC for a brief time after power-up. This option is really only\n");
printf (
"\tuseful in Win32, to work around a problem with race-conditions in\n");
printf (
"\tthe start-up scripts like SimLuminary131. When the race problem is\n");
printf (
"\tfixed correctly, this option will probably no longer be useful.\n");
printf ("--debug-counter-mode\n");
printf (
"\tThis is present only for debugging yaAGC\'s \"unprogrammed\"\n");
printf (
"\tcounter-increments, and has no useful purpose otherwise. In this\n");
printf (
"\tthe simulated DSKY\'s do not have their normal interpretations and\n");
printf (
"\tcannot be used to affect the AGC CPU in any normal way. Instead,\n");
printf (
"\tthe combination NOUN-digit-digit is used to specify an (octal)\n");
printf (
"\tCPU register number, and the combination VERB-digit is used\n");
printf (
"\tto select a counter-increment type as defined on the Virtual AGC\n");
printf (
"\twebsite\'s developer page. The PRO key is used to send the selected\n");
printf (
"\tcounter-increment command to the AGC. Note that there are no\n");
printf (
"\tvisual displays associated with this, since the AGC is still\n");
printf (
"\tcommanding the DSKY visual display in its usual way. This mode\n");
printf (
"\tis terminated only by restarting yaDSKY2. Only counter registers\n");
printf (
"\tin the range 32-60 (octal, default 32) are accepted, and only \n");
printf (
"\tincrement-types in the range 0-6 (default 1) are accepted.\n");
printf ("--test-uplink\n");
printf (
"\tIf this switch is used, keypresses are communicated to yaAGC\n");
printf ("\tas digital-uplink date instead of regular DSKY data.\n");
printf ("--test-downlink\n");
printf (
"\tDoes nothing. This switch is accepted only for backward compatibility.\n");
printf (
"\tIts former functionality has been replaced with the yaTelemetry program.\n");
printf ("--relative-pixmaps\n");
printf (
"\tDoes nothing. This switch is accepted only for backward compatibility.\n");
exit (1);
}
}DEBUG (0);
cout << string ("Hostname=");
cout << string (Hostname);
cout << string (", port=");
cout << Portnum;
cout << string ("\n");
// The following is sort of an abbreviated form of some stuff that
// ParseCfg does, and is called in case --cfg didn't appear on the
// command-line.
if (!UsedCfg)
{
Ind_t *Indptr;
// Update all of the indicator legends.
for (Indptr = Inds, i = 0; i < 14; Indptr++, i++)
MainWindow->ImageSet (Indptr->Widget, Indptr->GraphicOff);
MainWindow->ImageSet (MainWindow->iLastButton, "ProUp.jpg");
MainWindow->KeyRelAnnunciator = Inds[3].Widget;
MainWindow->CurrentKeyRel = MainWindow->BlankKeyRel =
wxString::FromAscii (Inds[3].GraphicOff);
MainWindow->ImageSet (MainWindow->KeyRelAnnunciator,
MainWindow->CurrentKeyRel);
MainWindow->OprErrAnnunciator = Inds[4].Widget;
MainWindow->CurrentOprErr = MainWindow->BlankOprErr =
wxString::FromAscii (Inds[4].GraphicOff);
MainWindow->ImageSet (MainWindow->OprErrAnnunciator,
MainWindow->CurrentOprErr);
}
// Read the optional DSKY2.matches file.
wxTextFile Fin;
if (wxFileExists (wxT ("DSKY2.matches")))
{
if (Fin.Open (wxT ("DSKY2.matches")))
{
int i;
NumMatches = Fin.GetLineCount ();
for (i = 0; i < NumMatches; i++)
{
wxString Line;
Line = Fin.GetLine (i);
Matches[i].Pattern = new wxString (Line.BeforeFirst (' '));
Matches[i].Command = new wxString (Line.AfterFirst (' '));
if (Matches[i].Pattern->IsSameAs (wxT ("startup")))
wxExecute (*Matches[i].Command, wxEXEC_ASYNC);
}
Fin.Close ();
}
}
MainWindow->Timer = new TimerClass ();
MainWindow->Timer->Start (PULSE_INTERVAL);
// With wxWidgets 3.0, the --half-size option inevitably creates a main
// window thats too short (vertically), and I haven't been able to figure
// out how to coax it into calculating the window size properly.
// (Works fine with wxWidgets 2.8 or with the full-size DSKY.) At any
// rate, the following is a lame attempt to prevent that from happening,
// though in theory it could force windows that are too big on some
// platforms, alas!
MainWindow->SetMinSize (wxSize(330, 392));
MainWindow->Show ();
return true;
}
//-------------------------------------------------------------------------
// This function is called every PULSE_INTERVAL milliseconds. It manages
// the server connection, and causes display-updates based on input from
// yaAGC.
void
TimerClass::Notify ()
{
static unsigned char Packet[4];
static int PacketSize = 0;
int i;
unsigned char c;
static unsigned long pulseCount = 0;
pulseCount++;
#if 0
// Just a preliminary debugging thing, to check out how well bitmap
// replacement works.
static int j = 0, k = 0;
k++;
if (k >= 10)
{
k = 0;
j = !j;
if (j)
MainWindow->ImageSet (MainWindow->Annunciator11, "OprErrOnO.jpg");
else
MainWindow->ImageSet (MainWindow->Annunciator11, "OprErrOff.jpg");
}
#endif
if (StartupDelay > 0)
{
StartupDelay -= PULSE_INTERVAL;
return;
}
// Process canned script, if any, rather than actual packets from yaAGC.
if (MainWindow->scriptFileOpen)
{
int i, j;
// If any buttons that have been pressed (and hence are Disabled) have
// timed out (and hence need to be Enabled), then fix them.
for (j = 0; j < MainWindow->numScriptKeysPressed; j++)
if (pulseCount >= MainWindow->scriptKeysPressed[j].whenPressed + 4)
MainWindow->scriptKeysPressed[j].button->Enable ();
else
break;
if (j > 0)
{
MainWindow->numScriptKeysPressed -= j;
for (i = 0; i < MainWindow->numScriptKeysPressed; i++, j++)
{
MainWindow->scriptKeysPressed[i].whenPressed =
MainWindow->scriptKeysPressed[j].whenPressed;
MainWindow->scriptKeysPressed[i].button =
MainWindow->scriptKeysPressed[j].button;
}
}
// Now check the script for new records.
while (true)
{
if (MainWindow->scriptFileCurrentLine >= MainWindow->scriptFileCount)
{
MainWindow->scriptFile.Close ();
MainWindow->scriptFileOpen = false;
wxMessageBox (
wxT ("Script completed, time ")
+ wxString::Format (
wxT("%.2f"),
MainWindow->scriptFileStopWatch.Time () / 1000.0)
+ wxT (" seconds."));
MainWindow->restoreToPrescript ();
break;
}
else if (MainWindow->scriptFileStopWatch.Time ()
>= MainWindow->scriptFileWaitUntil)
{
MainWindow->scriptFileCurrentLine++;
MainWindow->scriptFileProcessLine ();
if (MainWindow->scriptFileChannelNumber == 015)
{
// These are actually AGC input ports, and hence are
// outputs from the DSKY rather than inputs. The
// only thing we do with this info is to temporarily
// Disable() the key widget, so as to give it a slightly
// different appearance.
int keycode = MainWindow->scriptFileChannelValue & 0x1F;
int i;
wxBitmapButton *button;
switch (keycode)
{
case 16:
button = MainWindow->ZeroButton;
break;
case 1:
button = MainWindow->OneButton;
break;
case 2:
button = MainWindow->TwoButton;
break;
case 3:
button = MainWindow->ThreeButton;
break;
case 4:
button = MainWindow->FourButton;
break;
case 5:
button = MainWindow->FiveButton;
break;
case 6:
button = MainWindow->SixButton;
break;
case 7:
button = MainWindow->SevenButton;
break;
case 8:
button = MainWindow->EightButton;
break;
case 9:
button = MainWindow->NineButton;
break;
case 17:
button = MainWindow->VerbButton;
break;
case 18:
button = MainWindow->RsetButton;
break;
case 25:
button = MainWindow->KeyRelButton;
break;
case 26:
button = MainWindow->PlusButton;
break;
case 27:
button = MainWindow->MinusButton;
break;
case 28:
button = MainWindow->EntrButton;
break;
case 30:
button = MainWindow->ClrButton;
break;
case 31:
button = MainWindow->NounButton;
break;
default:
button = NULL;
break;
}
if (button != NULL)
{
for (i = 0; i < MainWindow->numScriptKeysPressed; i++)
if (MainWindow->scriptKeysPressed[i].button == button)
break;
if (i < MainWindow->numScriptKeysPressed)
{
// Already on the list, so remove it.
MainWindow->numScriptKeysPressed--;
for (int j = i; j < MainWindow->numScriptKeysPressed;
j++)
{
MainWindow->scriptKeysPressed[j].whenPressed =
MainWindow->scriptKeysPressed[j + 1].whenPressed;
MainWindow->scriptKeysPressed[j].button =
MainWindow->scriptKeysPressed[j + 1].button;
}
}
MainWindow->scriptKeysPressed[MainWindow->numScriptKeysPressed].whenPressed =
pulseCount;
MainWindow->scriptKeysPressed[MainWindow->numScriptKeysPressed].button =
button;
MainWindow->numScriptKeysPressed++;
button->Disable ();
}
}
else if (MainWindow->scriptFileChannelNumber == 032)
{
if ((MainWindow->scriptFileChannelValue & 020000) != 0)
MainWindow->ProButton->Enable ();
else
MainWindow->ProButton->Disable ();
}
else
ActOnIncomingIO ((unsigned char *) NULL);
MainWindow->scriptFileWaitUntil +=
MainWindow->scriptFileDifferentialTime;
}
else
return;
}
}
// Try to connect to the server (yaAGC) if not already connected.
if (ServerSocket == -1)
{
ServerSocket = CallSocket (Hostname, Portnum);
if (ServerSocket != -1)
printf ("yaDSKY is connected.\n");
}
if (ServerSocket != -1)
{
for (;;)
{
i = recv (ServerSocket, (char *) &c, 1, MSG_NOSIGNAL);
if (i == -1)
{
// The conditions i==-1,errno==0 or 9 occur only on Win32,
// and I'm not sure exactly what they corresponds to---but
// empirically I find that ignoring them makes no difference
// to the operation of the program.
if (errno == EAGAIN || errno == 0 || errno == 9)
i = 0;
else
{
printf ("yaDSKY reports server error %d\n", errno);
close (ServerSocket);
ServerSocket = -1;
break;
}
}
if (i == 0)
break;
// This (newer) code will accept any packet signature of the form
// 00 XX XX XX.
if (0 == (0xc0 & c))
PacketSize = 0;
if (PacketSize != 0 || (0xc0 & c) == 0)
{
Packet[PacketSize++] = c;
if (PacketSize >= 4)
{
ActOnIncomingIO (Packet);
PacketSize = 0;
}
}
}
}
}
// A function to overwrite one of the static bitmaps in the display, such as an
// annunciator, with a replacement from a file.
void
MainFrame::ImageSet (wxStaticBitmap *StaticBitmap, wxString &Filename)
{
wxString Dummy;
wxBitmap Bitmap;
if (HalfSize)
Dummy = wxT ("h") + Filename;
else
Dummy = Filename;
Bitmap = StaticBitmap->GetBitmap ();
Bitmap.LoadFile (Dummy, wxBITMAP_TYPE_JPEG);
StaticBitmap->SetBitmap (Bitmap);
}
void
MainFrame::ImageSet (wxStaticBitmap *StaticBitmap, char *Filename)
{
wxString Dummy;
Dummy = wxString::FromAscii (Filename);
ImageSet (StaticBitmap, Dummy);
}
void
MainFrame::ImageSet (wxStaticBitmap *StaticBitmap, const char *Filename)
{
ImageSet (StaticBitmap, (char *) Filename);
}
void
MainFrame::ImageSet (wxBitmapButton *BitmapButton, wxString &Filename)
{
wxString Dummy;
wxBitmap Bitmap;
if (HalfSize)
Dummy = wxT ("h") + Filename;
else
Dummy = Filename;
Bitmap = BitmapButton->GetBitmapLabel ();
Bitmap.LoadFile (Dummy, wxBITMAP_TYPE_JPEG);
BitmapButton->SetBitmapLabel (Bitmap);
}
void
MainFrame::ImageSet (wxBitmapButton *BitmapButton, char *Filename)
{
wxString Dummy;
Dummy = wxString::FromAscii (Filename);
ImageSet (BitmapButton, Dummy);
}
void
MainFrame::ImageSet (wxBitmapButton *BitmapButton, const char *Filename)
{
ImageSet (BitmapButton, (char *) Filename);
}
//--------------------------------------------------------------------------------
// Function for acting on incoming channel i/o from yaAGC, and change any affected
// DSKY annunciators or 7-segment displays. The Packet parameter
// is a string of 4 bytes, representing a channel i/o packet. Refer to the
// Virtual AGC Technical Manual, "I/O Specifics" subheading of the "Developer
// Details" chapter. (The widget parameter can be ANY widget.)
// Matches image widget filenames to channel 010 CCCCC and DDDDD fields.
static const char *SevenSegmentFilenames[32] =
{ "7Seg-0.jpg",
NULL, NULL, "7Seg-3.jpg",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"7Seg-15.jpg",
NULL, NULL, NULL, "7Seg-19.jpg",
NULL, "7Seg-21.jpg",
NULL, NULL, NULL, "7Seg-25.jpg",
NULL, "7Seg-27.jpg", "7Seg-28.jpg", "7Seg-29.jpg", "7Seg-30.jpg",
"7Seg-31.jpg" };
static int IoErrorCount = 0, Last11 = 0;
static int R1Sign = 0, R2Sign = 0, R3Sign = 0;
void
TimerClass::ActOnIncomingIO (unsigned char *Packet)
{
Ind_t *Indptr;
int Channel, Value, uBit, i;
if (Packet != NULL)
{
// Check to see if the message has a yaAGC signature. If not,
// ignore it. The yaAGC signature is 00 01 10 11 in the
// 2 most-significant bits of the packet's bytes. We are
// guaranteed that the first byte is signed 00, so we don't
// need to check it.
if (0x40 != (Packet[1] & 0xc0) || 0x80 != (Packet[2] & 0xc0)
|| 0xc0 != (Packet[3] & 0xc0))
return;
if (ParseIoPacket (Packet, &Channel, &Value, &uBit))
goto Error;
// Save, in case we need to run a canned script and
// restore the values afterward.
if (uBit == 0)
{
switch (Channel)
{
case 010:
int relay, relayValue;
relay = (Value >> 11) & 0x0F;
relayValue = Value & 03777;
if (MainWindow->last10[relay] != relayValue)
{
MainWindow->last10[relay] = relayValue;
MainWindow->record (Channel, Value);
}
break;
case 011:
if (MainWindow->last11 != Value)
{
MainWindow->last11 = Value;
MainWindow->record (Channel, Value);
}
break;
case 013:
if (MainWindow->last13 != Value)
{
MainWindow->last13 = Value;
MainWindow->record (Channel, Value);
}
break;
case 0163:
if (MainWindow->last163 != Value)
{
MainWindow->last163 = Value;
MainWindow->record (Channel, Value);
}
break;
default:
break;
}
}
}
else
{
Channel = MainWindow->scriptFileChannelNumber;
Value = MainWindow->scriptFileChannelValue;
uBit = 0;
}
// Take care of all of the indicator lights.
for (Indptr = Inds, i = 0; i < 14; Indptr++, i++)
if (Indptr->Channel == Channel
&& (!Indptr->Latched || ((Value & Indptr->RowMask) == Indptr->Row))
&& Indptr->State != (Indptr->Bitmask & (Value ^ Indptr->Polarity)))
{
Indptr->State = (Indptr->Bitmask & (Value ^ Indptr->Polarity));
if (Indptr->State == 0)
{
MainWindow->ImageSet (Indptr->Widget, Indptr->GraphicOff);
if (Indptr->Widget == MainWindow->OprErrAnnunciator)
MainWindow->CurrentOprErr = wxString::FromAscii (
Indptr->GraphicOff);
if (Indptr->Widget == MainWindow->KeyRelAnnunciator)
MainWindow->CurrentKeyRel = wxString::FromAscii (
Indptr->GraphicOff);
}
else
{
MainWindow->ImageSet (Indptr->Widget, Indptr->GraphicOn);
if (Indptr->Widget == MainWindow->OprErrAnnunciator)
MainWindow->CurrentOprErr = wxString::FromAscii (
Indptr->GraphicOn);
if (Indptr->Widget == MainWindow->KeyRelAnnunciator)
MainWindow->CurrentKeyRel = wxString::FromAscii (
Indptr->GraphicOn);
}
}
// Now take care of everything that's left. Only a few channels are of interest to the
// DSKY as far as input is concerned.
if (Channel == 010)
{
// 7-segment display management.
wxStaticBitmap *Sign = NULL, *Left = NULL, *Right = NULL;
int RSign = 0;
// Set up the pointers to the widgets associated with this channel.
switch (Value & 0x7800)
{
case 0x5800: // AAAA=11D
Left = MainWindow->MD1Digit;
Right = MainWindow->MD2Digit;
break;
case 0x5000: // AAAA=10D
Left = MainWindow->VD1Digit;
Right = MainWindow->VD2Digit;
break;
case 0x4800: // AAAA=9
Left = MainWindow->ND1Digit;
Right = MainWindow->ND2Digit;
break;
case 0x4000: // AAAA=8
Right = MainWindow->R1D1Digit;
break;
case 0x3800: // AAAA=7
Sign = MainWindow->R1PlusMinus;
if (0 != (Value & 0x0400))
R1Sign |= 2;
else
R1Sign &= ~2;
RSign = R1Sign;
Left = MainWindow->R1D2Digit;
Right = MainWindow->R1D3Digit;
break;
case 0x3000: // AAAA=6
Sign = MainWindow->R1PlusMinus;
if (0 != (Value & 0x0400))
R1Sign |= 1;
else
R1Sign &= ~1;
RSign = R1Sign;
Left = MainWindow->R1D4Digit;
Right = MainWindow->R1D5Digit;
break;
case 0x2800: // AAAA=5
Sign = MainWindow->R2PlusMinus;
if (0 != (Value & 0x0400))
R2Sign |= 2;
else
R2Sign &= ~2;
RSign = R2Sign;
Left = MainWindow->R2D1Digit;
Right = MainWindow->R2D2Digit;
break;
case 0x2000: // AAAA=4
Sign = MainWindow->R2PlusMinus;
if (0 != (Value & 0x0400))
R2Sign |= 1;
else
R2Sign &= ~1;
RSign = R2Sign;
Left = MainWindow->R2D3Digit;
Right = MainWindow->R2D4Digit;
break;
case 0x1800: // AAAA=3
Left = MainWindow->R2D5Digit;
Right = MainWindow->R3D1Digit;
break;
case 0x1000: // AAAA=2
Sign = MainWindow->R3PlusMinus;
if (0 != (Value & 0x0400))
R3Sign |= 2;
else
R3Sign &= ~2;
RSign = R3Sign;
Left = MainWindow->R3D2Digit;
Right = MainWindow->R3D3Digit;
break;
case 0x0800: // AAAA=1
Sign = MainWindow->R3PlusMinus;
if (0 != (Value & 0x0400))
R3Sign |= 1;
else
R3Sign &= ~1;
RSign = R3Sign;
Left = MainWindow->R3D4Digit;
Right = MainWindow->R3D5Digit;
break;
default:
goto Error;
}
// Write the sign.
if (Sign != NULL)
{
// + has priority if both are set
if (0 != (RSign & 2))
MainWindow->ImageSet (Sign, "PlusOn.jpg");
else if (0 != (RSign & 1))
MainWindow->ImageSet (Sign, "MinusOn.jpg");
else
MainWindow->ImageSet (Sign, "PlusMinusOff.jpg");
}
// Write the left digit.
if (Left != NULL)
{
int i;
i = (Value >> 5) & 0x1F;
if (SevenSegmentFilenames[i] == NULL)
goto Error;
if (Left == MainWindow->VD1Digit)
MainWindow->CurrentVD1 = wxString::FromAscii (
SevenSegmentFilenames[i]);
else if (Left == MainWindow->ND1Digit)
MainWindow->CurrentND1 = wxString::FromAscii (
SevenSegmentFilenames[i]);
MainWindow->ImageSet (Left, SevenSegmentFilenames[i]);
}
// Write the right digit.
if (Right != NULL)
{
int i;
i = Value & 0x1F;
if (SevenSegmentFilenames[i] == NULL)
goto Error;
if (Right == MainWindow->VD2Digit)
MainWindow->CurrentVD2 = wxString::FromAscii (
SevenSegmentFilenames[i]);
else if (Right == MainWindow->ND2Digit)
MainWindow->CurrentND2 = wxString::FromAscii (
SevenSegmentFilenames[i]);
MainWindow->ImageSet (Right, SevenSegmentFilenames[i]);
}
}
else if (Channel == 011)
{
int i;
// Here are appropriate Luminary 131 actions for various discrete
// annunciations.
if ((Value & 2) != (Last11 & 2))
{
if (0 == (Value & 2))
MainWindow->ImageSet (MainWindow->CompActyAnnunciator,
"CompActyOff.jpg");
else
MainWindow->ImageSet (MainWindow->CompActyAnnunciator,
"CompActyOn.jpg");
}
Last11 = Value;
}
else if (Channel == 0163)
{
// Handle Verb/Noun flashing via the fake V/N flash channel 163
if (Value & DSKY_VN_FLASH)
{
MainWindow->ImageSet (MainWindow->VD1Digit, MainWindow->CurrentBlank);
MainWindow->ImageSet (MainWindow->VD2Digit, MainWindow->CurrentBlank);
MainWindow->ImageSet (MainWindow->ND1Digit, MainWindow->CurrentBlank);
MainWindow->ImageSet (MainWindow->ND2Digit, MainWindow->CurrentBlank);
}
else
{
MainWindow->ImageSet (MainWindow->VD1Digit, MainWindow->CurrentVD1);
MainWindow->ImageSet (MainWindow->VD2Digit, MainWindow->CurrentVD2);
MainWindow->ImageSet (MainWindow->ND1Digit, MainWindow->CurrentND1);
MainWindow->ImageSet (MainWindow->ND2Digit, MainWindow->CurrentND2);
}
}
return;
Error: IoErrorCount++;
}
//--------------------------------------------------------------------------------
// A nice little function to output a keycode (except PRO) to yaAGC.
void
MainFrame::OutputKeycode (int Keycode)
{
unsigned char Packet[4];
int j;
if (scriptFileOpen)
return;
record (015, Keycode);
if (ServerSocket != -1)
{
if (TestUplink)
{
// In this case, we communicate keycodes to the AGC via the digital
// uplink rather than through the normal DSKY input channel.
Keycode &= 037;
Keycode |= ((Keycode << 10) | ((Keycode ^ 037) << 5));
FormIoPacket (0173, Keycode, Packet);
}
else
FormIoPacket (015, Keycode, Packet);
j = send (ServerSocket, (const char *) Packet, 4, MSG_NOSIGNAL);
if (j == SOCKET_ERROR && SOCKET_BROKEN)
{
close (ServerSocket);
ServerSocket = -1;
}
}
}
void
MainFrame::record (int channel, int value)
{
if (recordingFileOpen)
{
long now = scriptFileStopWatch.Time ();
recordingFile.AddLine (
wxString::Format (wxT ("%ld %o %o"), now - recordingLastTime,
channel, value));
recordingFile.Write();
recordingLastTime = now;
}
}
//--------------------------------------------------------------------------------
// ... and a similar function for outputting the PRO-key status to yaAGC.
void
MainFrame::OutputPro (int OffOn)
{
unsigned char Packet[8];
int j;
if (scriptFileOpen)
return;
record (032, OffOn ? 020000 : 0);
if (ServerSocket != -1)
{
// First, create the mask which will tell the CPU to only pay attention to
// bit 14 of the channel (032).
FormIoPacket (0432, 020000, Packet);
// Next, generate the data itself.
if (OffOn)
OffOn = 020000;
FormIoPacket (032, OffOn, &Packet[4]);
// And, send it all.
j = send (ServerSocket, (const char *) Packet, 8, MSG_NOSIGNAL);
if (j == SOCKET_ERROR && SOCKET_BROKEN)
{
close (ServerSocket);
ServerSocket = -1;
}
}
}
//--------------------------------------------------------------------------------
// Parses the configuration file.
void
xpm2jpg (char *s)
{
char *ss;
while (NULL != (ss = strstr (s, ".xpm")))
{
ss[1] = 'j';
ss[2] = 'p';
ss[3] = 'g';
}
}
int
MainFrame::ParseCfg (wxString &Filename)
{
Ind_t *Indptr;
char s[129], *ss, s1[1024], s2[129], s3[129];
int i, RetVal = 1, IndNum, BitNum, Polarity, Channel, Latched, RowMask, Row;
FILE *Cfg = NULL;
strcpy (s, Filename.char_str ());
Cfg = rfopen (s, "r");
if (Cfg == NULL)
{
printf ("The specified --cfg file does not exist.\n");
goto Error;
}
s[sizeof(s) - 1] = 0;
while (NULL != fgets (s, sizeof(s) - 1, Cfg))
{
// Trim off the trailing \n to make it easier to print error messages.
for (ss = s; *ss; ss++)
if (*ss == '\n' || *ss == '\r')
{
*ss = 0;
break;
}
if (!strncmp (s, "DEBUG ", 6))
continue;
if (!strcmp (s, "LMSIM"))
{
CmOrLm = 0;
continue;
}
if (!strcmp (s, "CMSIM"))
{
CmOrLm = 1;
continue;
}
if (1 == sscanf (s, "PROKEY %s", s2))
{
xpm2jpg (s2);
// Look up the widget for the PRO key, and change its graphic.
sprintf (s1, "%s%s", "", s2);
ImageSet (iLastButton, s1);
continue;
}
if (3 == sscanf (s, "IND %o %s %s", &IndNum, s2, s3))
{
xpm2jpg (s2);
xpm2jpg (s3);
if (IndNum >= 011 && IndNum <= 017)
IndNum -= 011;
else if (IndNum >= 021 && IndNum <= 027)
IndNum += 7 - 021;
else
{
printf ("Indicator must be 11-17 or 21-27 in \"%s\".\n", s);
goto Error;
}
// Need a better way (or SOME way) to check here for string overflow.
sprintf (s1, "%s%s", "", s2);
Inds[IndNum].GraphicOn = (char *) malloc (strlen (s1) + 1);
if (Inds[IndNum].GraphicOn == NULL)
{
printf ("Out of memory.\n");
goto Error;
}
strcpy ((char *) Inds[IndNum].GraphicOn, s1);
sprintf (s1, "%s%s", "", s3);
Inds[IndNum].GraphicOff = (char *) malloc (strlen (s1) + 1);
if (Inds[IndNum].GraphicOff == NULL)
{
printf ("Out of memory.\n");
goto Error;
}
strcpy ((char *) Inds[IndNum].GraphicOff, s1);
if (NULL != strstr (s2, "KeyRel") || NULL != strstr (s3, "KeyRel"))
{
KeyRelAnnunciator = Inds[IndNum].Widget;
CurrentKeyRel = BlankKeyRel = wxString::FromAscii (
Inds[IndNum].GraphicOff);
}
if (NULL != strstr (s2, "OprErr") || NULL != strstr (s3, "OprErr"))
{
OprErrAnnunciator = Inds[IndNum].Widget;
CurrentOprErr = BlankOprErr = wxString::FromAscii (
Inds[IndNum].GraphicOff);
}
continue;
}
i = sscanf (s, "CHAN %o %o %d %d %o %o", &IndNum, &Channel, &BitNum,
&Polarity, &RowMask, &Row);
if (i == 4 || i == 6)
{
if (i == 4)
Latched = Row = RowMask = 0;
else
Latched = 1;
if (IndNum >= 011 && IndNum <= 017)
IndNum -= 011;
else if (IndNum >= 021 && IndNum <= 027)
IndNum += 7 - 021;
else
{
printf ("Indicator must be 11-17 or 21-27 in \"%s\".\n", s);
goto Error;
}
if (Channel < 0 || Channel > 255)
{
printf (
"The channel-number must be in the range 0-255 in \"%s\".\n",
s);
goto Error;
}
if (BitNum < 1 || BitNum > 15)
{
printf ("The bit-number must be in the range 1-15 in \"%s\".\n",
s);
goto Error;
}
if (Polarity != 0 && Polarity != 1)
{
printf ("Polarity must be 0 or 1 in \"%s\".\n", s);
goto Error;
}
BitNum--;
Inds[IndNum].Channel = Channel;
Inds[IndNum].Bitmask = (1 << BitNum);
Inds[IndNum].Polarity = (Polarity << BitNum);
Inds[IndNum].Latched = Latched;
Inds[IndNum].RowMask = RowMask;
Inds[IndNum].Row = Row;
continue;
}
for (ss = s; isspace (*ss); ss++)
;
if (*ss != 0 && *ss != '#')
{
printf ("Input line not recognized: \"%s\".\n", s);
goto Error;
}
}
// Update all of the indicator legends.
for (Indptr = Inds, i = 0; i < 14; Indptr++, i++)
ImageSet (Indptr->Widget, Indptr->GraphicOff);
RetVal = 0;
Error: if (Cfg != NULL)
fclose (Cfg);
return (RetVal);
}
// The following function was adapted from the normal constructor. It is called only at the point in the
// startup sequence where it has noted that the --half-size switch has been used, and it is called to
// replace the already-created but not-yet-displayed main window to use smaller graphics.
void
MainFrame::HalveTheWindow (void)
{
int ButtonSize;
if (HalfSize)
ButtonSize = 40;
else
ButtonSize = 75;
ImageSet (bitmap_5, "FrameVerticalL.jpg");
ImageSet (bitmap_6_copy, "FrameHorizontal.jpg");
ImageSet (Annunciator11, "UplinkActyOff.jpg");
ImageSet (Annunciator21, "UplinkActyOff.jpg");
ImageSet (Annunciator12, "UplinkActyOff.jpg");
ImageSet (Annunciator22, "UplinkActyOff.jpg");
ImageSet (Annunciator13, "UplinkActyOff.jpg");
ImageSet (Annunciator23, "UplinkActyOff.jpg");
ImageSet (Annunciator14, "UplinkActyOff.jpg");
ImageSet (Annunciator24, "UplinkActyOff.jpg");
ImageSet (Annunciator15, "UplinkActyOff.jpg");
ImageSet (Annunciator25, "UplinkActyOff.jpg");
ImageSet (Annunciator16, "UplinkActyOff.jpg");
ImageSet (Annunciator26, "UplinkActyOff.jpg");
ImageSet (Annunciator17, "UplinkActyOff.jpg");
ImageSet (Annunciator27, "UplinkActyOff.jpg");
ImageSet (bitmap_6, "FrameHorizontal.jpg");
ImageSet (bitmap_5_copy, "FrameVerticalL.jpg");
ImageSet (bitmap_5_copy_1, "FrameVerticalR.jpg");
ImageSet (bitmap_6_copy_copy, "FrameHorizontal.jpg");
ImageSet (CompActyAnnunciator, "CompActyOff.jpg");
ImageSet (ModeAnnunciator, "rProgOn.jpg");
ImageSet (MD1Digit, "7Seg-0.jpg");
ImageSet (MD2Digit, "7Seg-0.jpg");
ImageSet (VerbAnnunciator, "VerbOn.jpg");
ImageSet (VD1Digit, "7Seg-0.jpg");
ImageSet (VD2Digit, "7Seg-0.jpg");
ImageSet (NounAnnunciator, "NounOn.jpg");
ImageSet (ND1Digit, "7Seg-0.jpg");
ImageSet (ND2Digit, "7Seg-0.jpg");
ImageSet (bitmap_2_copy_1, "SeparatorOn.jpg");
ImageSet (R1PlusMinus, "PlusMinusOff.jpg");
ImageSet (R1D1Digit, "7Seg-0.jpg");
ImageSet (R1D2Digit, "7Seg-0.jpg");
ImageSet (R1D3Digit, "7Seg-0.jpg");
ImageSet (R1D4Digit, "7Seg-0.jpg");
ImageSet (R1D5Digit, "7Seg-0.jpg");
ImageSet (bitmap_2_copy, "SeparatorOn.jpg");
ImageSet (R2PlusMinus, "PlusMinusOff.jpg");
ImageSet (R2D1Digit, "7Seg-0.jpg");
ImageSet (R2D2Digit, "7Seg-0.jpg");
ImageSet (R2D3Digit, "7Seg-0.jpg");
ImageSet (R2D4Digit, "7Seg-0.jpg");
ImageSet (R2D5Digit, "7Seg-0.jpg");
ImageSet (bitmap_2, "SeparatorOn.jpg");
ImageSet (R3PlusMinus, "PlusMinusOff.jpg");
ImageSet (R3D1Digit, "7Seg-0.jpg");
ImageSet (R3D2Digit, "7Seg-0.jpg");
ImageSet (R3D3Digit, "7Seg-0.jpg");
ImageSet (R3D4Digit, "7Seg-0.jpg");
ImageSet (R3D5Digit, "7Seg-0.jpg");
ImageSet (bitmap_6_copy_copy_copy, "FrameHorizontal.jpg");
ImageSet (bitmap_5_copy_2, "FrameVerticalR.jpg");
ImageSet (VerbButton, "VerbUp.jpg");
ImageSet (NounButton, "NounUp.jpg");
ImageSet (PlusButton, "PlusUp.jpg");
ImageSet (MinusButton, "MinusUp.jpg");
ImageSet (ZeroButton, "0Up.jpg");
ImageSet (SevenButton, "7Up.jpg");
ImageSet (FourButton, "4Up.jpg");
ImageSet (OneButton, "1Up.jpg");
ImageSet (EightButton, "8Up.jpg");
ImageSet (FiveButton, "5Up.jpg");
ImageSet (TwoButton, "2Up.jpg");
ImageSet (NineButton, "9Up.jpg");
ImageSet (SixButton, "6Up.jpg");
ImageSet (ThreeButton, "3Up.jpg");
ImageSet (ClrButton, "ClrUp.jpg");
ImageSet (ProButton, "ProUp.jpg");
ImageSet (KeyRelButton, "KeyRelUp.jpg");
ImageSet (EntrButton, "EntrUp.jpg");
ImageSet (RsetButton, "RsetUp.jpg");
VerbButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
NounButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
PlusButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
MinusButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
ZeroButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
SevenButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
FourButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
OneButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
EightButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
FiveButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
TwoButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
NineButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
SixButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
ThreeButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
ClrButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
ProButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
KeyRelButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
EntrButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
RsetButton->SetMinSize (wxSize (ButtonSize, ButtonSize));
Fit ();
}
// this is for the "presentation" feature: the function checks the buffer
// being accumulated from the keypad against the set of patterns read at
// power-up from the optional DSKY2.matches file. If there is a match, then
// the associated command (in the PC's native operating system) is performed.
void
MainFrame::MatchCheck (void)
{
int i;
for (i = 0; i < NumMatches; i++)
if (Match.IsSameAs (*Matches[i].Pattern))
wxExecute (*Matches[i].Command, wxEXEC_ASYNC);
}