diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c
index 43681ad1..7ae54a04 100644
--- a/PDP18B/pdp18b_cpu.c
+++ b/PDP18B/pdp18b_cpu.c
@@ -1390,6 +1390,18 @@ while (reason == 0) { /* loop until halted */
700042 ION ION ION ION
700024 undefined undefined undefined LDMM (XVM)
700062 undefined ITON undefined undefined
+ 700501 undefined IDVE undefined undefined
+ 700601 undefined IDSI undefined undefined
+ 700701 undefined IDSP undefined undefined
+ 701001 undefined IDHE undefined undefined
+ 700504 undefined IDRS undefined undefined
+ 700512 undefined IDRA undefined undefined
+ 700606 undefined IDLA undefined undefined
+ 700614 undefined IDRD undefined undefined
+ 700704 undefined IDCF undefined undefined
+ 700712 undefined IDRC undefined undefined
+ 701012 undefined IDSC undefined undefined
+ 701014 undefined IDRP undefined undefined
701701 undefined undefined MPSK MPSK
701741 undefined undefined MPSNE MPSNE
701702 undefined undefined MPCV MPCV
diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h
index a95d28e4..1122860b 100644
--- a/PDP18B/pdp18b_defs.h
+++ b/PDP18B/pdp18b_defs.h
@@ -149,6 +149,9 @@
#define DRM 0 /* drum */
#define RB 0 /* fixed head disk */
#define GRAPHICS2 0 /* BTL display */
+#ifdef USE_DISPLAY
+#define TYPE340 0 /* Type 340 display */
+#endif
#elif defined (PDP9)
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
@@ -284,6 +287,7 @@ typedef struct {
#define DEV_PTP 002 /* paper tape punch */
#define DEV_TTI 003 /* console input */
#define DEV_TTO 004 /* console output */
+#define DEV_DPY 005 /* Type 340 */
#define DEV_TTI1 041 /* extra terminals */
#define DEV_TTO1 040
#define DEV_DRM 060 /* drum */
diff --git a/PDP18B/pdp18b_dpy.c b/PDP18B/pdp18b_dpy.c
new file mode 100644
index 00000000..2f52a3b1
--- /dev/null
+++ b/PDP18B/pdp18b_dpy.c
@@ -0,0 +1,217 @@
+/* pdp18b_dpy.c: PDP-7 Type 340 interface
+
+ Copyright (c) 2019, Lars Brinkhoff
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ LARS BRINKHOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of Lars Brinkhoff shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from Lars Brinkhoff.
+
+ dpy (PDP-7) Type 340 Precision Incremental CRT Display, with
+ Type 341 Interface, Type 347 Subroutine Interface,
+ and Type 342 Symbol Generator.
+*/
+
+
+#include "pdp18b_defs.h"
+
+#if defined(TYPE340)
+#include "display/type340.h"
+#include "display/display.h"
+
+#define DBG_IOT 001 /* IOT instructions. */
+#define DBG_IRQ 002 /* Interrupts. */
+#define DBG_INS 004 /* 340 instructions. */
+
+/*
+ * Number of microseconds between svc calls. Used to age display and
+ * poll for WS events.
+ */
+#define DPY_CYCLE_US 100
+
+int32 dpy05 (int32 dev, int32 pulse, int32 dat);
+int32 dpy06 (int32 dev, int32 pulse, int32 dat);
+int32 dpy07 (int32 dev, int32 pulse, int32 dat);
+int32 dpy10 (int32 dev, int32 pulse, int32 dat);
+int32 dpy_iors (void);
+t_stat dpy_svc (UNIT *uptr);
+t_stat dpy_reset (DEVICE *dptr);
+
+DIB dpy_dib = { DEV_DPY, 4, &dpy_iors, { &dpy05, &dpy06, &dpy07, &dpy10 } };
+
+UNIT dpy_unit[] = {
+ { UDATA (&dpy_svc, 0, 0) },
+};
+
+DEBTAB dpy_deb[] = {
+ { "IOT", DBG_IOT },
+ { "IRQ", DBG_IRQ },
+ { "INS", DBG_INS },
+ { NULL, 0 }
+ };
+
+DEVICE dpy_dev = {
+ "DPY", dpy_unit, NULL, NULL,
+ 1, 8, 12, 1, 8, 18,
+ NULL, NULL, &dpy_reset,
+ NULL, NULL, NULL,
+ &dpy_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0,
+ dpy_deb, NULL, NULL
+ };
+
+t_stat dpy_svc (UNIT *uptr)
+{
+ sim_activate_after(uptr, DPY_CYCLE_US);
+ display_age(DPY_CYCLE_US, 0);
+ ty340_cycle();
+ return SCPE_OK;
+}
+
+ty340word ty340_fetch(ty340word addr)
+{
+ extern int32 *M;
+ return (ty340word)M[addr];
+}
+
+t_stat dpy_reset (DEVICE *dptr)
+{
+ if (!(dptr->flags & DEV_DIS)) {
+ display_reset();
+ ty340_reset(dptr);
+ }
+ sim_cancel (&dpy_unit[0]);
+ return SCPE_OK;
+}
+
+void
+cpu_get_switches(unsigned long *p1, unsigned long *p2)
+{
+}
+
+void
+cpu_set_switches(unsigned long w1, unsigned long w2)
+{
+}
+
+void
+ty340_lp_int(ty340word x, ty340word y)
+{
+}
+
+void
+ty340_rfd(void)
+{
+}
+
+int32 dpy_iors (void)
+{
+#if defined IOS_LPEN
+ return IOS_LPEN;
+#else
+ return 0;
+#endif
+}
+
+int32 dpy05 (int32 dev, int32 pulse, int32 dat)
+{
+ sim_debug(DBG_IOT, &dpy_dev, "7005%02o, %06o\n", pulse, dat);
+
+ if (pulse & 001) {
+ if (ty340_sense(ST340_VEDGE))
+ dat |= IOT_SKP;
+ }
+
+ if (pulse & 002) {
+ dat |= ty340_get_dac();
+ }
+
+ if (pulse & 004) {
+ ty340_clear (ST340_LPHIT);
+ sim_activate_abs (dpy_unit, 0);
+ }
+
+ return dat;
+}
+
+int32 dpy06 (int32 dev, int32 pulse, int32 dat)
+{
+ sim_debug(DBG_IOT, &dpy_dev, "7006%02o, %06o\n", pulse, dat);
+
+ if (pulse & 001) {
+ if (ty340_sense(ST340_STOPPED))
+ dat |= IOT_SKP;
+ }
+
+ if (pulse & 002) {
+ ty340_set_dac (0);
+ }
+
+ if (pulse & 004) {
+ if ((pulse & 010) == 0)
+ ty340_set_dac (dat & 07777);
+ ty340_clear (ST340_STOPPED|ST340_STOP_INT);
+ sim_activate_abs (dpy_unit, 0);
+ }
+
+ return dat;
+}
+
+int32 dpy07 (int32 dev, int32 pulse, int32 dat)
+{
+ sim_debug(DBG_IOT, &dpy_dev, "7007%02o, %06o\n", pulse, dat);
+
+ if (pulse & 001) {
+ if (ty340_sense(ST340_LPHIT))
+ dat |= IOT_SKP;
+ }
+
+ if (pulse & 002) {
+ dat |= 0; // X, Y
+ }
+
+ if (pulse & 004) {
+ ty340_clear(~0);
+ }
+
+ return dat;
+}
+
+int32 dpy10 (int32 dev, int32 pulse, int32 dat)
+{
+ sim_debug(DBG_IOT, &dpy_dev, "7010%02o, %06o\n", pulse, dat);
+
+ if (pulse & 001) {
+ if (ty340_sense(ST340_HEDGE))
+ dat |= IOT_SKP;
+ }
+
+ if (pulse & 002) {
+ dat |= ty340_get_asr();
+ }
+
+ if (pulse & 004) {
+ dat |= 0; // Light pen.
+ }
+
+ return dat;
+}
+
+#else /* !TYPE340 */
+char pdp18b_dpy_unused; /* sometimes empty object modules cause problems */
+#endif /* !TYPE340 */
diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c
index b611843d..a4b01321 100644
--- a/PDP18B/pdp18b_sys.c
+++ b/PDP18B/pdp18b_sys.c
@@ -108,6 +108,9 @@ extern DEVICE dr15_dev;
#if defined (GRAPHICS2)
extern DEVICE g2out_dev, g2in_dev;
#endif
+#if defined (TYPE340)
+extern DEVICE dpy_dev;
+#endif
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern int32 *M;
@@ -184,6 +187,9 @@ DEVICE *sim_devices[] = {
#endif
#if defined (GRAPHICS2)
&g2out_dev, &g2in_dev,
+#endif
+#if defined (TYPE340)
+ &dpy_dev,
#endif
NULL
};
@@ -460,6 +466,10 @@ static const char *opcode[] = {
"PSF", "PCF", "PSA", "PSB", "PLS",
"KSF", "KRB", "KCF", "IORS", "IOOS",
"TSF", "TCF", "TPC", "TLS",
+ "IDVE", "IDRA", "IDRS", "IDRA",
+ "IDSI", "IDCA", "IDRD", "IDLA", "IDRD",
+ "IDSP", "IDRC", "IDCF", "IDRC",
+ "IDHE", "IDSC", "IDRP", "IDSC", "IDRP",
#if defined (TYPE62) /* Type 62 */
"LPSF", "LPCF", "LPLD", "LPSE",
"LSSF", "LSCF", "LSPR",
@@ -699,6 +709,10 @@ static const int32 opc_val[] = {
0700201+I_NPI, 0700202+I_NPI, 0700204+I_NPI, 0700244+I_NPI, 0700206+I_NPI,
0700301+I_NPI, 0700312+I_NPN, 0700302+I_NPI, 0700314+I_NPN, 0700304+I_NPI,
0700401+I_NPI, 0700402+I_NPI, 0700404+I_NPI, 0700406+I_NPI,
+ 0700501+I_NPI, 0700502+I_NPI, 0700504+I_NPI, 0700512+I_NPI,
+ 0700601+I_NPI, 0700602+I_NPI, 0700604+I_NPI, 0700606+I_NPI, 0700614+I_NPI,
+ 0700701+I_NPI, 0700702+I_NPI, 0700704+I_NPI, 0700712+I_NPI,
+ 0701001+I_NPI, 0701002+I_NPI, 0701004+I_NPI, 0701012+I_NPI, 0701014+I_NPI,
#if defined (TYPE62)
0706501+I_NPI, 0706502+I_NPI, 0706542+I_NPI, 0706506+I_NPI,
0706601+I_NPI, 0706602+I_NPI, 0706606+I_NPI,
diff --git a/PDP18B/tests/test340.simh b/PDP18B/tests/test340.simh
new file mode 100644
index 00000000..55e1ff90
--- /dev/null
+++ b/PDP18B/tests/test340.simh
@@ -0,0 +1,27 @@
+set g2out disabled
+
+set debug stdout
+set dpy enabled
+set dpy debug
+
+# Small test program.
+dep -m 100 law 1000
+dep -m 101 idla
+dep -m 102 idsi
+dep -m 103 jmp 102
+dep -m 104 jmp 100
+
+# Small display list.
+#Go to point mode, set scale, set intensity.
+dep 1000 020117
+#Stay in point mode, set x=1000.
+dep 1001 021000
+#Go to vector mode, set y=1000.
+dep 1002 301000
+#Escape, intensify, delta x=100.
+dep 1003 600100
+#Stop.
+dep 1004 003000
+
+dep pc 100
+# Ready to go or single step.
diff --git a/Visual Studio Projects/PDP7.vcproj b/Visual Studio Projects/PDP7.vcproj
index b809f8d5..84ce040f 100644
--- a/Visual Studio Projects/PDP7.vcproj
+++ b/Visual Studio Projects/PDP7.vcproj
@@ -41,7 +41,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../PDP18B/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="PDP7;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC"
+ PreprocessorDefinitions="PDP7;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
@@ -125,7 +125,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../PDP18B/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="PDP7;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC"
+ PreprocessorDefinitions="PDP7;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -191,10 +191,18 @@
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
+
+
+
+
@@ -287,11 +295,23 @@
RelativePath="..\sim_video.c"
>
+
+
+
+
+
+
@@ -348,6 +368,10 @@
RelativePath="..\sim_video.h"
>
+
+
status = 0; /* XXX just clear stopped? */
ty340_rfd(); /* ready for data */
}
+
+void
+ty340_cycle(void)
+{
+ struct type340 *u = UNIT(0);
+
+ if (u->status == 0) {
+ ty340word insn = ty340_fetch(u->DAC);
+ u->status = ty340_instruction (insn);
+ u->DAC = (u->DAC + 1) & 07777;
+ }
+}
+
+ty340word
+ty340_get_dac(void)
+{
+ struct type340 *u = UNIT(0);
+ return u->DAC;
+}
+
+ty340word
+ty340_get_asr(void)
+{
+#if TYPE347
+ struct type340 *u = UNIT(0);
+ return u->ASR;
+#else
+ return 0;
#endif
+}
+
+ty340word
+ty340_sense(ty340word flags)
+{
+ struct type340 *u = UNIT(0);
+ return u->status & flags;
+}
+
+void
+ty340_clear(ty340word flags)
+{
+ struct type340 *u = UNIT(0);
+ u->status &= ~flags;
+}
ty340word
ty340_reset(void *dptr)
diff --git a/display/type340.h b/display/type340.h
index 1c39dc1a..5caf06d6 100644
--- a/display/type340.h
+++ b/display/type340.h
@@ -49,7 +49,13 @@ typedef unsigned int ty340word;
ty340word ty340_reset(void *);
ty340word ty340_status(void);
ty340word ty340_instruction(ty340word inst);
+ty340word ty340_get_dac(void);
+ty340word ty340_get_asr(void);
+ty340word ty340_sense(ty340word);
void ty340_set_dac(ty340word addr);
+void ty340_clear(ty340word addr);
+void ty340_cycle(void);
+void ty340_set_status(ty340word);
void ty342_set_grid(int, int);
/*
diff --git a/makefile b/makefile
index 8b30f740..18a890f2 100644
--- a/makefile
+++ b/makefile
@@ -114,6 +114,10 @@ endif
ifneq (,$(or $(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS))))
NETWORK_USEFUL = true
endif
+# building the PDP-7 needs video support
+ifneq (,$(findstring pdp7,$(MAKECMDGOALS)))
+ VIDEO_USEFUL = true
+endif
# building the pdp11, pdp10, or any vax simulator could use networking support
ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring pdp10,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring 3b2,$(MAKECMDGOALS))$(findstring all,$(MAKECMDGOALS))))
NETWORK_USEFUL = true
@@ -1283,8 +1287,12 @@ PDP18B = ${PDP18BD}/pdp18b_dt.c ${PDP18BD}/pdp18b_drm.c ${PDP18BD}/pdp18b_cpu.c
${PDP18BD}/pdp18b_rb.c ${PDP18BD}/pdp18b_tt1.c ${PDP18BD}/pdp18b_fpp.c \
${PDP18BD}/pdp18b_g2tty.c ${PDP18BD}/pdp18b_dr15.c
+ifneq (,$(DISPLAY_OPT))
+ PDP7_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF
+endif
+
PDP4_OPT = -DPDP4 -I ${PDP18BD}
-PDP7_OPT = -DPDP7 -I ${PDP18BD}
+PDP7_OPT = -DPDP7 -I ${PDP18BD} $(DISPLAY_OPT) $(PDP7_DISPLAY_OPT)
PDP9_OPT = -DPDP9 -I ${PDP18BD}
PDP15_OPT = -DPDP15 -I ${PDP18BD}
@@ -2062,9 +2070,9 @@ endif
pdp7 : ${BIN}pdp7${EXE}
-${BIN}pdp7${EXE} : ${PDP18B} ${SIM}
+${BIN}pdp7${EXE} : ${PDP18B} ${PDP18BD}/pdp18b_dpy.c ${DISPLAYL} $(DISPLAY340) ${SIM}
${MKDIRBIN}
- ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} $(CC_OUTSPEC) ${LDFLAGS}
+ ${CC} ${PDP18B} ${PDP18BD}/pdp18b_dpy.c ${DISPLAYL} $(DISPLAY340) ${SIM} ${PDP7_OPT} $(CC_OUTSPEC) ${LDFLAGS}
ifneq (,$(call find_test,${PDP18BD},pdp7))
$@ $(call find_test,${PDP18BD},pdp7) $(TEST_ARG)
endif