mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
Readying test_cpu
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
OFILES = vimlac.o cpu.o dcpu.o ptr.o ptp.o memory.o kb.o ttyin.o ttyout.o trace.o
|
||||
OFILES=cpu.o dcpu.o ptr.o ptp.o memory.o kbd.o ttyin.o ttyout.o trace.o
|
||||
CFILES=cpu.c dcpu.c ptr.c ptp.c memory.c kbd.c ttyin.c ttyout.c trace.c error.c
|
||||
HFILES=cpu.h dcpu.h ptr.h ptp.h memory.h kbd.h ttyin.h ttyout.h trace.h error.h
|
||||
|
||||
CFLAGS=-shared -fPIC -O2 -Wall -ansi -pedantic -std=c99 -g
|
||||
|
||||
@@ -10,6 +12,9 @@ vimlac: ${OFILES} Makefile
|
||||
#gcc -o vimlac.so -shared -fPIC ${OFILES}
|
||||
gcc -o vimlac ${OFILES}
|
||||
|
||||
test_cpu: test_cpu.c $(CFILES) $(HFILES) Makefile
|
||||
gcc -o test_cpu test_cpu.c $(CFILES)
|
||||
|
||||
test_ptr: test_ptr.c ptr.c ptr.h Makefile
|
||||
gcc -o test_ptr ptr.c test_ptr.c
|
||||
|
||||
|
||||
30
vimlac/cpu.c
30
vimlac/cpu.c
@@ -6,11 +6,11 @@
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "imlac.h"
|
||||
#include "cpu.h"
|
||||
#include "dcpu.h"
|
||||
#include "memory.h"
|
||||
#include "kb.h"
|
||||
#include "kbd.h"
|
||||
#include "ptr.h"
|
||||
#include "ptp.h"
|
||||
#include "ttyin.h"
|
||||
@@ -492,7 +492,7 @@ Description : Emulate the DSF instruction.
|
||||
static int
|
||||
i_DSF(void)
|
||||
{
|
||||
if (dcpu_on())
|
||||
if (dcpu_running())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("DSF\t");
|
||||
@@ -529,7 +529,7 @@ Description : Emulate the DSN instruction.
|
||||
static int
|
||||
i_DSN(void)
|
||||
{
|
||||
if (!dcpu_on())
|
||||
if (!dcpu_running())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("DSN\t");
|
||||
@@ -585,7 +585,7 @@ Description : Emulate the IMLAC KCF instruction.
|
||||
static int
|
||||
i_KCF(void)
|
||||
{
|
||||
kb_clear_flag();
|
||||
kbd_clear_flag();
|
||||
|
||||
trace("KCF\t");
|
||||
|
||||
@@ -602,7 +602,7 @@ Description : Emulate the IMLAC KRB instruction.
|
||||
static int
|
||||
i_KRB(void)
|
||||
{
|
||||
r_AC |= kb_get_char();
|
||||
r_AC |= kbd_get_char();
|
||||
|
||||
trace("KRB\t");
|
||||
|
||||
@@ -619,8 +619,8 @@ Description : Emulate the IMLAC KRC instruction.
|
||||
static int
|
||||
i_KRC(void)
|
||||
{
|
||||
r_AC |= kb_get_char();
|
||||
kb_clear_flag();
|
||||
r_AC |= kbd_get_char();
|
||||
kbd_clear_flag();
|
||||
|
||||
trace("KRC\t");
|
||||
|
||||
@@ -637,7 +637,7 @@ Description : Emulate the IMLAC KSF instruction.
|
||||
static int
|
||||
i_KSF(void)
|
||||
{
|
||||
if (kb_ready())
|
||||
if (kbd_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("KSF\t");
|
||||
@@ -655,7 +655,7 @@ Description : Emulate the IMLAC KSN instruction.
|
||||
static int
|
||||
i_KSN(void)
|
||||
{
|
||||
if (!kb_ready())
|
||||
if (!kbd_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("KSN\t");
|
||||
@@ -673,7 +673,9 @@ Description : Emulate the IMLAC PUN instruction.
|
||||
static int
|
||||
i_PUN(void)
|
||||
{
|
||||
ptp_punch(r_AC & 0xff);
|
||||
char value = r_AC & 0xff;
|
||||
|
||||
ptp_punch(value);
|
||||
|
||||
trace("PUN\t");
|
||||
|
||||
@@ -937,7 +939,9 @@ Description : Emulate the IMLAC TPC instruction.
|
||||
static int
|
||||
i_TPC(void)
|
||||
{
|
||||
ttyout_send(r_AC & 0xff);
|
||||
BYTE value = r_AC & 0xff;
|
||||
|
||||
ttyout_send(value);
|
||||
ttyout_clear_flag();
|
||||
|
||||
trace("TPC\t");
|
||||
@@ -1116,7 +1120,7 @@ Description : Emulate the IMLAC DLA instruction.
|
||||
static int
|
||||
i_DLA(void)
|
||||
{
|
||||
dcpu_set_PC(r_AC);
|
||||
dcpu_set_DPC(r_AC);
|
||||
|
||||
trace("DLA\t");
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
/******************************************************************************\
|
||||
* cpu.h *
|
||||
* ------- *
|
||||
* *
|
||||
* Implements all main CPU instructions. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "imlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
|
||||
181
vimlac/dcpu.c
Executable file
181
vimlac/dcpu.c
Executable file
@@ -0,0 +1,181 @@
|
||||
/******************************************************************************\
|
||||
* dcpu.c *
|
||||
* -------- *
|
||||
* *
|
||||
* This file is used to decode and execute a display processor instruction. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "dcpu.h"
|
||||
#include "memory.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
/******
|
||||
* Emulated registers, state, memory, etc.
|
||||
******/
|
||||
|
||||
static WORD r_DPC;
|
||||
static WORD Prev_r_DPC;
|
||||
static WORD DRSindex = 0;
|
||||
|
||||
/* 40Hz sync stuff */
|
||||
static bool Sync40HzOn = false;
|
||||
|
||||
/******
|
||||
* Environment stuff. PTR and TTY in and out files, etc
|
||||
******/
|
||||
|
||||
static bool dcpu_on; /* true if display processor is running */
|
||||
static bool dcpu_sync_on; /* true if 40HZ flag set */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to get the display CPU status.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool
|
||||
dcpu_running(void)
|
||||
{
|
||||
return dcpu_on == true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to start the display CPU.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
dcpu_start(void)
|
||||
{
|
||||
dcpu_on = true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to stop the display CPU.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
dcpu_stop(void)
|
||||
{
|
||||
dcpu_on = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Functions to get various registers.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
WORD
|
||||
dcpu_get_DPC(void)
|
||||
{
|
||||
return r_DPC;
|
||||
}
|
||||
|
||||
|
||||
WORD
|
||||
dcpu_get_prev_DPC(void)
|
||||
{
|
||||
return Prev_r_DPC;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dcpu_set_DPC(WORD new_dpc)
|
||||
{
|
||||
r_DPC = new_dpc;
|
||||
}
|
||||
|
||||
void
|
||||
dcpu_set_DRSindex(WORD drsindex)
|
||||
{
|
||||
DRSindex = drsindex;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to handle unrecognized instruction.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
static void
|
||||
illegal(void)
|
||||
{
|
||||
WORD oldDPC = Prev_r_DPC & MEMMASK;
|
||||
|
||||
error("INTERNAL ERROR: "
|
||||
"unexpected display processor opcode %06.6o at address %06.6o",
|
||||
mem_get(oldDPC, false), oldDPC);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description :
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
static int
|
||||
i_LAW_LWC(bool indirect, WORD address)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to execute one display processor instruction.
|
||||
Parameters :
|
||||
Returns : The number of cycles the instruction took.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int
|
||||
dcpu_execute_one(void)
|
||||
{
|
||||
WORD instruction;
|
||||
WORD opcode;
|
||||
WORD address;
|
||||
bool indirect;
|
||||
|
||||
/******
|
||||
* If main processor not running, return immediately.
|
||||
******/
|
||||
|
||||
if (!dcpu_on)
|
||||
return 0;
|
||||
|
||||
/******
|
||||
* Fetch the instruction. Split into initial opcode and address.
|
||||
******/
|
||||
|
||||
Prev_r_DPC = r_DPC;
|
||||
instruction = mem_get(r_DPC++, false);
|
||||
r_DPC = r_DPC & MEMMASK;
|
||||
|
||||
indirect = (bool) (instruction & 0100000); /* high bit set? */
|
||||
opcode = (instruction >> 11) & 017; /* high 5 bits */
|
||||
address = instruction & 03777; /* low 11 bits */
|
||||
|
||||
/******
|
||||
* Now decode it.
|
||||
******/
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
default: illegal();
|
||||
}
|
||||
|
||||
return 0; /* CAN'T REACH */
|
||||
}
|
||||
|
||||
|
||||
28
vimlac/dcpu.h
Executable file
28
vimlac/dcpu.h
Executable file
@@ -0,0 +1,28 @@
|
||||
/******************************************************************************\
|
||||
* dcpu.h *
|
||||
* -------- *
|
||||
* *
|
||||
* Implements all display CPU instructions. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#ifndef DCPU_H
|
||||
#define DCPU_H
|
||||
|
||||
#include "imlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
******/
|
||||
|
||||
bool dcpu_running(void);
|
||||
void dcpu_start(void);
|
||||
void dcpu_stop(void);
|
||||
void dcpu_set_DRSindex(WORD);
|
||||
int dcpu_execute_one(void);
|
||||
WORD dcpu_get_AC(void);
|
||||
WORD dcpu_get_DPC(void);
|
||||
WORD dcpu_get_prev_DPC(void);
|
||||
void dcpu_set_DPC(WORD dpc);
|
||||
|
||||
#endif
|
||||
30
vimlac/error.c
Normal file
30
vimlac/error.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Error routines for the imlac simulator.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine.
|
||||
Parameters : like printf()
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
error(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
fprintf(stderr, "%s\n", buff);
|
||||
va_end(ap);
|
||||
|
||||
exit(10);
|
||||
}
|
||||
|
||||
|
||||
10
vimlac/error.h
Normal file
10
vimlac/error.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Error routines for the imlac simulation.
|
||||
*/
|
||||
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
void error(char *fmt, ...);
|
||||
|
||||
#endif
|
||||
58
vimlac/kbd.c
Executable file
58
vimlac/kbd.c
Executable file
@@ -0,0 +1,58 @@
|
||||
/******************************************************************************\
|
||||
* kbd.c *
|
||||
* ------- *
|
||||
* *
|
||||
* This file is used to implement a KBD device (keyboard). *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "kbd.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
/******
|
||||
* Emulated registers, state, memory, etc.
|
||||
******/
|
||||
|
||||
static WORD state_KBD;
|
||||
static bool clear = false;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Clear the KBD (keyboard) flag.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
kbd_clear_flag(void)
|
||||
{
|
||||
clear = false;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the character in the keyboard buffer.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
WORD
|
||||
kbd_get_char(void)
|
||||
{
|
||||
return 'a';
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Test if the keyboard is ready with the next character.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool
|
||||
kbd_ready(void)
|
||||
{
|
||||
return !clear;
|
||||
}
|
||||
|
||||
|
||||
24
vimlac/kbd.h
Executable file
24
vimlac/kbd.h
Executable file
@@ -0,0 +1,24 @@
|
||||
/******************************************************************************\
|
||||
* kbd.h *
|
||||
* ------- *
|
||||
* *
|
||||
* Implements all display CPU instructions. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#ifndef KBD_H
|
||||
#define KBD_H
|
||||
|
||||
#include "imlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
******/
|
||||
|
||||
|
||||
void kbd_clear_flag(void);
|
||||
WORD kbd_get_char(void);
|
||||
bool kbd_ready(void);
|
||||
|
||||
|
||||
#endif
|
||||
159
vimlac/ptp.c
Normal file
159
vimlac/ptp.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Implementation for the imlac PTP (papertape punch) device.
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "ptp.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the PTP device
|
||||
*
|
||||
* The device punches at 100 chars/second, so we work out how many imlac
|
||||
* machine cycles data is ready/notready at a 30%/70% ready cycle.
|
||||
******/
|
||||
|
||||
#define CHARS_PER_SECOND 100
|
||||
#define CYCLES_PER_CHAR (CPU_HERZ / CHARS_PER_SECOND)
|
||||
#define READY_CYCLES (int)((3 * CYCLES_PER_CHAR) / 10)
|
||||
#define NOT_READY_CYCLES (int)((7 * CYCLES_PER_CHAR) / 10)
|
||||
|
||||
/*****
|
||||
* State variables for the PTP device
|
||||
******/
|
||||
|
||||
static bool motor_on = false;
|
||||
static bool device_ready = false;
|
||||
static FILE *open_file;
|
||||
static char *filename = NULL;
|
||||
static long cycle_count = 0;
|
||||
static char value = 0;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Mount a papertape file on the PTP device
|
||||
Parameters : fname - pathname of the file to mount
|
||||
Returns : 0 if no error, else status code.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ptp_mount(char *fname)
|
||||
{
|
||||
filename = fname;
|
||||
open_file = fopen(fname, "wb");
|
||||
if (open_file == NULL)
|
||||
{
|
||||
ptp_dismount();
|
||||
return errno;
|
||||
}
|
||||
motor_on = false;
|
||||
device_ready = false;
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ptp_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
if (fclose(open_file) != 0)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
motor_on = false;
|
||||
device_ready = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Start the papertape device motor.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : We don't check if papertape mounted as the real imlac doesn't.
|
||||
******************************************************************************/
|
||||
void ptp_start(void)
|
||||
{
|
||||
motor_on = true;
|
||||
device_ready = false;
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Turn the papertape device motor off.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ptp_stop(void)
|
||||
{
|
||||
motor_on = false;
|
||||
device_ready = false;
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Write the current value to the papertape punch file.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ptp_punch(BYTE value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool ptp_ready(void)
|
||||
{
|
||||
return device_ready;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Tick the state machine along a bit.
|
||||
Parameters : cycles - number of imlac cycles that have elapsed
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ptp_tick(long cycles)
|
||||
{
|
||||
/* if no state change */
|
||||
if (!motor_on || open_file == NULL)
|
||||
return;
|
||||
|
||||
/* tape in, motor on */
|
||||
cycle_count -= cycles;
|
||||
if (cycle_count <= 0L)
|
||||
{
|
||||
if (device_ready)
|
||||
{
|
||||
device_ready = false;
|
||||
cycle_count += NOT_READY_CYCLES;
|
||||
value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
device_ready = true;
|
||||
cycle_count += READY_CYCLES;
|
||||
if (fread(&value, sizeof(BYTE), 1, open_file) != 1)
|
||||
{ /* assume EOF on file, dismount tape */
|
||||
fclose(open_file);
|
||||
open_file = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
vimlac/ptp.h
Normal file
16
vimlac/ptp.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Interface for the imlac PTP (papertape punch).
|
||||
*/
|
||||
|
||||
#ifndef PTP_H
|
||||
#define PTP_H
|
||||
|
||||
int ptp_mount(char *fname);
|
||||
void ptp_dismount(void);
|
||||
void ptp_start(void);
|
||||
void ptp_stop(void);
|
||||
int ptp_punch(BYTE value);
|
||||
bool ptp_ready(void);
|
||||
void ptp_tick(long cycles);
|
||||
|
||||
#endif
|
||||
49
vimlac/ptr.c
49
vimlac/ptr.c
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Implementation for the vimlac PTR (papertape reader).
|
||||
* Implementation for the imlac PTR (papertape reader) device.
|
||||
*/
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "imlac.h"
|
||||
#include "ptr.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the PTR device
|
||||
*
|
||||
* The device reads at 300 chars/second, so we work out how many
|
||||
* The device reads at 300 chars/second, so we work out how many imlac
|
||||
* machine cycles data is ready/notready at a 30%/70% ready cycle.
|
||||
******/
|
||||
|
||||
@@ -33,6 +33,13 @@ static BYTE value = PTR_EOF;
|
||||
static long cycle_count = 0;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Mount a papertape file on the PTR device
|
||||
Parameters : fname - pathname of the file to mount
|
||||
Returns : 0 if no error, else status code.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ptr_mount(char *fname)
|
||||
{
|
||||
filename = fname;
|
||||
@@ -52,6 +59,12 @@ int ptr_mount(char *fname)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ptr_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
@@ -65,6 +78,12 @@ void ptr_dismount(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Start the papertape device motor.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : We don't check if papertape mounted as the real imlac doesn't.
|
||||
******************************************************************************/
|
||||
void ptr_start(void)
|
||||
{
|
||||
motor_on = true;
|
||||
@@ -73,6 +92,12 @@ void ptr_start(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Turn the papertape device motor off.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ptr_stop(void)
|
||||
{
|
||||
motor_on = false;
|
||||
@@ -80,18 +105,36 @@ void ptr_stop(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Read the current value of the papertape device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ptr_read(void)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool ptr_ready(void)
|
||||
{
|
||||
return device_ready;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Tick the state machine along a bit.
|
||||
Parameters : cycles - number of imlac cycles that have elapsed
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ptr_tick(long cycles)
|
||||
{
|
||||
/* if no state change */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Interface for the vimlac PTR (papertape reader).
|
||||
* Interface for the imlac PTR (papertape reader).
|
||||
*/
|
||||
|
||||
#ifndef PTR_H
|
||||
|
||||
23
vimlac/test_cpu.c
Normal file
23
vimlac/test_cpu.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Test the CPU implementation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "imlac.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define trace(args) ;
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
printf("%d errors found\n", errors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
vimlac/trace.c
Normal file
27
vimlac/trace.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Trace routines for the imlac simulator.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine.
|
||||
Parameters : like printf()
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
fprintf(stdout, "%s\n", buff);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
10
vimlac/trace.h
Normal file
10
vimlac/trace.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Interface for the imlac TRACE routine(s).
|
||||
*/
|
||||
|
||||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
void trace(char *fmt, ...);
|
||||
|
||||
#endif
|
||||
149
vimlac/ttyin.c
Normal file
149
vimlac/ttyin.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Implementation for the imlac TTYIN (TTY input) device.
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "ttyin.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the TTYIN device
|
||||
*
|
||||
* The device reads at 4800 chars/second, so we work out how many imlac
|
||||
* machine cycles data is ready/notready at a 30%/70% ready cycle.
|
||||
******/
|
||||
|
||||
#define CHARS_PER_SECOND 4800
|
||||
#define CYCLES_PER_CHAR (CPU_HERZ / CHARS_PER_SECOND)
|
||||
#define READY_CYCLES (int)((3 * CYCLES_PER_CHAR) / 10)
|
||||
#define NOT_READY_CYCLES (int)((7 * CYCLES_PER_CHAR) / 10)
|
||||
|
||||
#define TTYIN_EOF 0377
|
||||
|
||||
/*****
|
||||
* State variables for the TTYIN device
|
||||
******/
|
||||
|
||||
static bool device_ready = false;
|
||||
static FILE *open_file;
|
||||
static char *filename = NULL;
|
||||
static bool at_eof = false;
|
||||
static BYTE value = TTYIN_EOF;
|
||||
static long cycle_count = 0;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Mount a papertape file on the TTYIN device
|
||||
Parameters : fname - pathname of the file to mount
|
||||
Returns : 0 if no error, else status code.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ttyin_mount(char *fname)
|
||||
{
|
||||
filename = fname;
|
||||
open_file = fopen(fname, "rb");
|
||||
if (open_file == NULL)
|
||||
{
|
||||
ttyin_dismount();
|
||||
return errno;
|
||||
}
|
||||
device_ready = false;
|
||||
at_eof = false;
|
||||
value = TTYIN_EOF;
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ttyin_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
if (fclose(open_file) != 0)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
device_ready = true;
|
||||
at_eof = true;
|
||||
value = TTYIN_EOF;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Read the current value of the papertape device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ttyin_get_char(void)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyin_clear_flag(void)
|
||||
{
|
||||
device_ready = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool ttyin_ready(void)
|
||||
{
|
||||
return device_ready;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Tick the state machine along a bit.
|
||||
Parameters : cycles - number of imlac cycles that have elapsed
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyin_tick(long cycles)
|
||||
{
|
||||
/* if no state change */
|
||||
if (at_eof || open_file == NULL)
|
||||
return;
|
||||
|
||||
/* tape in, motor on */
|
||||
cycle_count -= cycles;
|
||||
if (cycle_count <= 0L)
|
||||
{
|
||||
if (device_ready)
|
||||
{
|
||||
device_ready = false;
|
||||
cycle_count += NOT_READY_CYCLES;
|
||||
value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
device_ready = true;
|
||||
cycle_count += READY_CYCLES;
|
||||
if (fread(&value, sizeof(BYTE), 1, open_file) != 1)
|
||||
{ /* assume EOF on file, dismount tape */
|
||||
fclose(open_file);
|
||||
open_file = NULL;
|
||||
at_eof = true;
|
||||
value = TTYIN_EOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
vimlac/ttyin.h
Normal file
15
vimlac/ttyin.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Interface for the imlac TTYIN (TTY input).
|
||||
*/
|
||||
|
||||
#ifndef TTYIN_H
|
||||
#define TTYIN_H
|
||||
|
||||
int ttyin_mount(char *fname);
|
||||
void ttyin_dismount(void);
|
||||
int ttyin_get_char(void);
|
||||
void ttyin_tick(long cycles);
|
||||
bool ttyin_ready(void);
|
||||
void ttyin_clear_flag(void);
|
||||
|
||||
#endif
|
||||
136
vimlac/ttyout.c
Normal file
136
vimlac/ttyout.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Implementation for the imlac TTYOUT (TTY output) device.
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "ttyout.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the TTYOUT device
|
||||
*
|
||||
* The device reads at 4800 chars/second, so we work out how many imlac
|
||||
* machine cycles data is ready/notready at a 30%/70% ready cycle.
|
||||
******/
|
||||
|
||||
#define CHARS_PER_SECOND 4800
|
||||
#define CYCLES_PER_CHAR (CPU_HERZ / CHARS_PER_SECOND)
|
||||
#define READY_CYCLES (int)((3 * CYCLES_PER_CHAR) / 10)
|
||||
#define NOT_READY_CYCLES (int)((7 * CYCLES_PER_CHAR) / 10)
|
||||
|
||||
#define TTYOUT_EOF 0377
|
||||
|
||||
/*****
|
||||
* State variables for the TTYOUT device
|
||||
******/
|
||||
|
||||
static bool device_ready = false;
|
||||
static FILE *open_file;
|
||||
static char *filename = NULL;
|
||||
static long cycle_count = 0;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Mount a papertape file on the TTYOUT device
|
||||
Parameters : fname - pathname of the file to mount
|
||||
Returns : 0 if no error, else status code.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ttyout_mount(char *fname)
|
||||
{
|
||||
filename = fname;
|
||||
open_file = fopen(fname, "wb");
|
||||
if (open_file == NULL)
|
||||
{
|
||||
ttyout_dismount();
|
||||
return errno;
|
||||
}
|
||||
device_ready = false;
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ttyout_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
if (fclose(open_file) != 0)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
device_ready = true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Write a byte value to the device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyout_send(BYTE value)
|
||||
{
|
||||
if (device_ready)
|
||||
fwrite(&value, 1, 1, open_file);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyout_clear_flag(void)
|
||||
{
|
||||
device_ready = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get the papertape device status.
|
||||
Parameters :
|
||||
Returns : TRUE if device ready, else FALSE.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool ttyout_ready(void)
|
||||
{
|
||||
return device_ready;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Tick the state machine along a bit.
|
||||
Parameters : cycles - number of imlac cycles that have elapsed
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyout_tick(long cycles)
|
||||
{
|
||||
/* if not open, no state change */
|
||||
if (open_file == NULL)
|
||||
return;
|
||||
|
||||
/* file mounted */
|
||||
cycle_count -= cycles;
|
||||
if (cycle_count <= 0L)
|
||||
{
|
||||
if (device_ready)
|
||||
{
|
||||
device_ready = false;
|
||||
cycle_count += NOT_READY_CYCLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
device_ready = true;
|
||||
cycle_count += READY_CYCLES;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
vimlac/ttyout.h
Normal file
17
vimlac/ttyout.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Interface for the imlac TTYOUT (TTY input).
|
||||
*/
|
||||
|
||||
#ifndef TTYOUT_H
|
||||
#define TTYOUT_H
|
||||
|
||||
|
||||
int ttyout_mount(char *fname);
|
||||
void ttyout_dismount(void);
|
||||
void ttyout_send(BYTE value);
|
||||
void ttyout_clear_flag(void);
|
||||
bool ttyout_ready(void);
|
||||
void ttyout_tick(long cycles);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user