mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
Reverted to better old copy
This commit is contained in:
2
vimlac/.gitignore
vendored
2
vimlac/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
test_memory
|
||||
test_cpu
|
||||
13
vimlac/Makefile
Normal file → Executable file
13
vimlac/Makefile
Normal file → Executable file
@@ -1,20 +1,15 @@
|
||||
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
|
||||
OFILES = vimlac.o cpu.o dcpu.o ptr.o ptp.o memory.o kb.o ttyin.o ttyout.o trace.o
|
||||
|
||||
CFLAGS=-shared -fPIC -O2 -Wall -ansi -pedantic -std=c99 -g
|
||||
|
||||
#test: vimlac.py vimlac
|
||||
# #python vimlac.py -ptr test_add.ptp -r 040 -r 0100
|
||||
# vimlac
|
||||
test: vimlac.py vimlac
|
||||
#python vimlac.py -ptr test_add.ptp -r 040 -r 0100
|
||||
./vimlac
|
||||
|
||||
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
|
||||
|
||||
|
||||
32
vimlac/cpu.c
32
vimlac/cpu.c
@@ -6,11 +6,11 @@
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.h"
|
||||
#include "cpu.h"
|
||||
#include "dcpu.h"
|
||||
#include "memory.h"
|
||||
#include "kbd.h"
|
||||
#include "kb.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_running())
|
||||
if (dcpu_on())
|
||||
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_running())
|
||||
if (!dcpu_on())
|
||||
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)
|
||||
{
|
||||
kbd_clear_flag();
|
||||
kb_clear_flag();
|
||||
|
||||
trace("KCF\t");
|
||||
|
||||
@@ -602,7 +602,7 @@ Description : Emulate the IMLAC KRB instruction.
|
||||
static int
|
||||
i_KRB(void)
|
||||
{
|
||||
r_AC |= kbd_get_char();
|
||||
r_AC |= kb_get_char();
|
||||
|
||||
trace("KRB\t");
|
||||
|
||||
@@ -619,8 +619,8 @@ Description : Emulate the IMLAC KRC instruction.
|
||||
static int
|
||||
i_KRC(void)
|
||||
{
|
||||
r_AC |= kbd_get_char();
|
||||
kbd_clear_flag();
|
||||
r_AC |= kb_get_char();
|
||||
kb_clear_flag();
|
||||
|
||||
trace("KRC\t");
|
||||
|
||||
@@ -637,7 +637,7 @@ Description : Emulate the IMLAC KSF instruction.
|
||||
static int
|
||||
i_KSF(void)
|
||||
{
|
||||
if (kbd_ready())
|
||||
if (kb_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 (!kbd_ready())
|
||||
if (!kb_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("KSN\t");
|
||||
@@ -673,9 +673,7 @@ Description : Emulate the IMLAC PUN instruction.
|
||||
static int
|
||||
i_PUN(void)
|
||||
{
|
||||
char value = r_AC & 0xff;
|
||||
|
||||
ptp_punch(value);
|
||||
ptp_punch(r_AC & 0xff);
|
||||
|
||||
trace("PUN\t");
|
||||
|
||||
@@ -939,9 +937,7 @@ Description : Emulate the IMLAC TPC instruction.
|
||||
static int
|
||||
i_TPC(void)
|
||||
{
|
||||
BYTE value = r_AC & 0xff;
|
||||
|
||||
ttyout_send(value);
|
||||
ttyout_send(r_AC & 0xff);
|
||||
ttyout_clear_flag();
|
||||
|
||||
trace("TPC\t");
|
||||
@@ -1120,7 +1116,7 @@ Description : Emulate the IMLAC DLA instruction.
|
||||
static int
|
||||
i_DLA(void)
|
||||
{
|
||||
dcpu_set_DPC(r_AC);
|
||||
dcpu_set_PC(r_AC);
|
||||
|
||||
trace("DLA\t");
|
||||
|
||||
@@ -1489,7 +1485,7 @@ page00(WORD instruction)
|
||||
/******************************************************************************
|
||||
Description : Function to execute one main processor instruction.
|
||||
Parameters :
|
||||
Returns : The number of cycles the instruction took.
|
||||
Returns :
|
||||
Comments : Perform initial decode of 5 bit opcode and either call
|
||||
: appropriate emulating function or call further decode function.
|
||||
******************************************************************************/
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/******************************************************************************\
|
||||
* cpu.h *
|
||||
* ------- *
|
||||
* *
|
||||
* Implements all main CPU instructions. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
|
||||
182
vimlac/dcpu.c
182
vimlac/dcpu.c
@@ -1,105 +1,56 @@
|
||||
/******************************************************************************\
|
||||
* dcpu.c *
|
||||
* -------- *
|
||||
* dcpu.c *
|
||||
* ------- *
|
||||
* *
|
||||
* This file is used to decode and execute a display processor instruction. *
|
||||
* *
|
||||
\******************************************************************************/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.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;
|
||||
static WORD r_PC;
|
||||
static WORD Prev_r_PC;
|
||||
static int r_DRSindex;
|
||||
|
||||
/* 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 */
|
||||
static bool cpu_is_on; /* true if display processor is running */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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.
|
||||
Description : Functions to get/set various registers.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
WORD
|
||||
dcpu_get_DPC(void)
|
||||
dcpu_get_PC(void)
|
||||
{
|
||||
return r_DPC;
|
||||
}
|
||||
|
||||
|
||||
WORD
|
||||
dcpu_get_prev_DPC(void)
|
||||
{
|
||||
return Prev_r_DPC;
|
||||
return r_PC;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dcpu_set_DPC(WORD new_dpc)
|
||||
dcpu_set_PC(WORD value)
|
||||
{
|
||||
r_DPC = new_dpc;
|
||||
r_PC = value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dcpu_set_DRSindex(WORD drsindex)
|
||||
dcpu_set_DRSindex(int value)
|
||||
{
|
||||
DRSindex = drsindex;
|
||||
r_DRSindex = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,55 +63,44 @@ Description : Function to handle unrecognized instruction.
|
||||
static void
|
||||
illegal(void)
|
||||
{
|
||||
WORD oldDPC = Prev_r_DPC & MEMMASK;
|
||||
WORD oldPC = Prev_r_PC & MEMMASK;
|
||||
|
||||
/* memdump(LogOut, oldPC - 8, 16); */
|
||||
|
||||
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;
|
||||
"unexpected main processor opcode %06.6o at address %06.6o",
|
||||
mem_get(oldPC, false), oldPC);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to execute one display processor instruction.
|
||||
Parameters :
|
||||
Returns : The number of cycles the instruction took.
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int
|
||||
dcpu_execute_one(void)
|
||||
{
|
||||
WORD instruction;
|
||||
WORD opcode;
|
||||
WORD address;
|
||||
bool indirect;
|
||||
WORD instruction = 0;
|
||||
bool indirect = false;
|
||||
WORD opcode = 0;
|
||||
WORD address = 0;
|
||||
|
||||
/******
|
||||
* If main processor not running, return immediately.
|
||||
* If processor not running, return immediately.
|
||||
******/
|
||||
|
||||
if (!dcpu_on)
|
||||
if (!cpu_is_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;
|
||||
Prev_r_PC = r_PC;
|
||||
instruction = mem_get(r_PC++, false);
|
||||
r_PC = r_PC & MEMMASK;
|
||||
|
||||
indirect = (bool) (instruction & 0100000); /* high bit set? */
|
||||
opcode = (instruction >> 11) & 017; /* high 5 bits */
|
||||
@@ -170,12 +110,70 @@ dcpu_execute_one(void)
|
||||
* Now decode it.
|
||||
******/
|
||||
|
||||
#ifdef JUNK
|
||||
switch (opcode)
|
||||
{
|
||||
default: illegal();
|
||||
}
|
||||
#endif
|
||||
++instruction;
|
||||
indirect = !indirect;
|
||||
++opcode;
|
||||
++address;
|
||||
illegal();
|
||||
|
||||
return 0; /* CAN'T REACH */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to get CPU state.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool
|
||||
dcpu_on(void)
|
||||
{
|
||||
return cpu_is_on;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to start the CPU.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
dcpu_start(void)
|
||||
{
|
||||
cpu_is_on = true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to stop the CPU.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
dcpu_stop(void)
|
||||
{
|
||||
cpu_is_on = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to stop the CPU.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
dcpu_set_drsindex(int index)
|
||||
{
|
||||
r_DRSindex = index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
/******************************************************************************\
|
||||
* dcpu.h *
|
||||
* -------- *
|
||||
* *
|
||||
* Implements all display CPU instructions. *
|
||||
* *
|
||||
* dcpu.h *
|
||||
* -------- *
|
||||
\******************************************************************************/
|
||||
|
||||
#ifndef DCPU_H
|
||||
#define DCPU_H
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.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);
|
||||
WORD dcpu_get_PC(void);
|
||||
void dcpu_set_PC(WORD value);
|
||||
void dcpu_set_DRSindex(int index);
|
||||
bool dcpu_on(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Error routines for the imlac simulation.
|
||||
*/
|
||||
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
void error(char *fmt, ...);
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Global definitions for the imlac simulator.
|
||||
*/
|
||||
|
||||
#ifndef IMLAC_H
|
||||
#define IMLAC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef unsigned int WORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
#define CPU_HERZ 1800000
|
||||
#define MEMMASK 0xffff
|
||||
#define HIGHBITMASK 0x8000
|
||||
#define WORD_MASK 0xffff
|
||||
#define OVERFLOWMASK 0x10000
|
||||
#define LOWBITMASK 0x1
|
||||
|
||||
|
||||
void error(char *msg, ...);
|
||||
|
||||
#endif
|
||||
58
vimlac/kbd.c
58
vimlac/kbd.c
@@ -1,58 +0,0 @@
|
||||
/******************************************************************************\
|
||||
* 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
24
vimlac/kbd.h
@@ -1,24 +0,0 @@
|
||||
/******************************************************************************\
|
||||
* 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
|
||||
54
vimlac/memory.c
Normal file → Executable file
54
vimlac/memory.c
Normal file → Executable file
@@ -1,14 +1,13 @@
|
||||
/*
|
||||
* Implementation of memory for the imlac simulator.
|
||||
* Implementation of vimlac memory.
|
||||
*
|
||||
* Memory size is a compile-time constant.
|
||||
* The code here handles indirect memory references as well
|
||||
* The code here handles indirect memory references as will
|
||||
* as the 8 auto-index registers at 010-017 in every 2K block.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "imlac.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
@@ -44,14 +43,6 @@ static WORD memory[MEM_SIZE];
|
||||
#define AUTO_INDEX(a) (((a & INDEX_MASK) >= LOWER_INDEX) && ((a & INDEX_MASK) <= HIGHER_INDEX))
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Get a word value from memory.
|
||||
Parameters : address - the address to fetch from
|
||||
: indirect - TRUE if the fetch is to be indirect
|
||||
Returns : The word from memory.
|
||||
Comments : If 'indirect' is TRUE 'address' is the address of a pointer to
|
||||
: the word to fetch.
|
||||
******************************************************************************/
|
||||
WORD
|
||||
mem_get(WORD address, bool indirect)
|
||||
{
|
||||
@@ -68,15 +59,6 @@ mem_get(WORD address, bool indirect)
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Put a word value into memory.
|
||||
Parameters : address - the address to store to
|
||||
: indirect - TRUE if the store is to be indirect
|
||||
: value - the word value to place into memory
|
||||
Returns :
|
||||
Comments : If 'indirect' is TRUE 'address' is the address of a pointer to
|
||||
: the word to store into.
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_put(WORD address, bool indirect, WORD value)
|
||||
{
|
||||
@@ -91,17 +73,11 @@ mem_put(WORD address, bool indirect, WORD value)
|
||||
memory[a & ADDR_MASK] = value;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Clear memory to zero words.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : If the ROM addresses are read-only, don't clear them.
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_clear(void)
|
||||
{
|
||||
if (rom_readonly)
|
||||
{ /* save the ROM contents and restore after clear */
|
||||
{ /* save the ROM contents */
|
||||
WORD rom[ROM_SIZE];
|
||||
|
||||
memcpy(rom, &memory[ROM_START], sizeof(WORD)*ROM_SIZE);
|
||||
@@ -112,12 +88,6 @@ mem_clear(void)
|
||||
memset(memory, 0, sizeof(WORD)*MEM_SIZE);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Set the ROM addresses to a particular ROM setting.
|
||||
Parameters : rom - pointer to ROM_SIZE words of OM values
|
||||
Returns :
|
||||
Comments : Sets the ROM area as read-only.
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_set_rom(WORD *rom)
|
||||
{
|
||||
@@ -125,24 +95,12 @@ mem_set_rom(WORD *rom)
|
||||
memcpy(&memory[ROM_START], rom, sizeof(WORD)*ROM_SIZE);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Sets the ROM area to be protected or not.
|
||||
Parameters : readonly - if TRUE the ROM area is protected
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_set_rom_readonly(bool readonly)
|
||||
{
|
||||
rom_readonly = readonly;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Load memory from a core save file.
|
||||
Parameters : filename - pathname of file to load
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_load_core(char *filename)
|
||||
{
|
||||
@@ -164,12 +122,6 @@ mem_load_core(char *filename)
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Save memory to a core save file.
|
||||
Parameters : filename - pathname of file to save to
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
mem_save_core(char *filename)
|
||||
{
|
||||
|
||||
4
vimlac/memory.h
Normal file → Executable file
4
vimlac/memory.h
Normal file → Executable file
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Interface to the imlac memory routines.
|
||||
* Interface for the vimlac memory.
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.h"
|
||||
|
||||
#define MEM_SIZE 0x4000
|
||||
|
||||
|
||||
88
vimlac/ptp.c
Normal file → Executable file
88
vimlac/ptp.c
Normal file → Executable file
@@ -1,25 +1,23 @@
|
||||
/*
|
||||
* Implementation for the imlac PTP (papertape punch) device.
|
||||
* Implementation for the vimlac PTP (papertape punch).
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.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.
|
||||
* The device punches at 300 chars/second, so we work out how many
|
||||
* machine cycles device is not ready after punch starts.
|
||||
******/
|
||||
|
||||
#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)
|
||||
#define CHARS_PER_SECOND 300
|
||||
#define NOT_READY_CYCLES (int) (CPU_HERZ / CHARS_PER_SECOND)
|
||||
|
||||
/*****
|
||||
* State variables for the PTP device
|
||||
* State variables for the PTR device
|
||||
******/
|
||||
|
||||
static bool motor_on = false;
|
||||
@@ -27,16 +25,8 @@ 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;
|
||||
@@ -54,12 +44,6 @@ int ptp_mount(char *fname)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ptp_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
@@ -67,16 +51,10 @@ void ptp_dismount(void)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
motor_on = false;
|
||||
device_ready = false;
|
||||
device_ready = true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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;
|
||||
@@ -85,50 +63,29 @@ void ptp_start(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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)
|
||||
void ptp_punch(BYTE value)
|
||||
{
|
||||
return value;
|
||||
if (motor_on && open_file != NULL)
|
||||
{
|
||||
putc(value, open_file);
|
||||
cycle_count = NOT_READY_CYCLES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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 */
|
||||
@@ -139,21 +96,8 @@ void ptp_tick(long cycles)
|
||||
cycle_count -= cycles;
|
||||
if (cycle_count <= 0L)
|
||||
{
|
||||
if (device_ready)
|
||||
{
|
||||
device_ready = false;
|
||||
cycle_count += NOT_READY_CYCLES;
|
||||
value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!device_ready)
|
||||
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;
|
||||
}
|
||||
}
|
||||
cycle_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
6
vimlac/ptp.h
Normal file → Executable file
6
vimlac/ptp.h
Normal file → Executable file
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Interface for the imlac PTP (papertape punch).
|
||||
* Interface for the vimlac PTP (papertape punch).
|
||||
*/
|
||||
|
||||
#ifndef PTP_H
|
||||
@@ -9,8 +9,8 @@ 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_punch(BYTE byte);
|
||||
void ptp_tick(long cycles);
|
||||
bool ptp_ready(void);
|
||||
|
||||
#endif
|
||||
|
||||
49
vimlac/ptr.c
Normal file → Executable file
49
vimlac/ptr.c
Normal file → Executable file
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Implementation for the imlac PTR (papertape reader) device.
|
||||
* Implementation for the vimlac PTR (papertape reader).
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.h"
|
||||
#include "ptr.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the PTR device
|
||||
*
|
||||
* The device reads at 300 chars/second, so we work out how many imlac
|
||||
* The device reads at 300 chars/second, so we work out how many
|
||||
* machine cycles data is ready/notready at a 30%/70% ready cycle.
|
||||
******/
|
||||
|
||||
@@ -33,13 +33,6 @@ 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;
|
||||
@@ -59,12 +52,6 @@ int ptr_mount(char *fname)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ptr_dismount(void)
|
||||
{
|
||||
if (open_file)
|
||||
@@ -78,12 +65,6 @@ 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;
|
||||
@@ -92,12 +73,6 @@ void ptr_start(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Turn the papertape device motor off.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ptr_stop(void)
|
||||
{
|
||||
motor_on = false;
|
||||
@@ -105,36 +80,18 @@ 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 */
|
||||
|
||||
2
vimlac/ptr.h
Normal file → Executable file
2
vimlac/ptr.h
Normal file → Executable file
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Interface for the imlac PTR (papertape reader).
|
||||
* Interface for the vimlac PTR (papertape reader).
|
||||
*/
|
||||
|
||||
#ifndef PTR_H
|
||||
|
||||
35
vimlac/test_memory.c
Normal file → Executable file
35
vimlac/test_memory.c
Normal file → Executable file
@@ -5,7 +5,7 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ main(int argc, char *argv[])
|
||||
WORD addr;
|
||||
WORD result;
|
||||
FILE *fd;
|
||||
int errors = 0;
|
||||
|
||||
// test the "memory clear" function
|
||||
mem_clear();
|
||||
@@ -31,7 +30,7 @@ main(int argc, char *argv[])
|
||||
{
|
||||
printf("A: mem_get(0x%04x) was 0x%04x, should be 0x%04x\n",
|
||||
addr, mem_get(addr, false), addr);
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ main(int argc, char *argv[])
|
||||
{
|
||||
printf("B: mem_get(0x%04x) was 0x%04x, should be 0x%04x\n",
|
||||
addr, mem_get(addr, false), addr);
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,26 +57,26 @@ main(int argc, char *argv[])
|
||||
if (result != 1)
|
||||
{
|
||||
printf("C: auto-index at address 010 not indirectly addressing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
result = mem_get(010, false);
|
||||
if (result != 1)
|
||||
{
|
||||
printf("D: auto-index at address 010 not incrementing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
mem_put(010, false, 0xffff);
|
||||
result = mem_get(010, true);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("E: auto-index at address 010 not indirectly addressing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
result = mem_get(010, false);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("F: auto-index at address 010 not incrementing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check 017, make sure address wrap-around works
|
||||
@@ -89,26 +88,26 @@ main(int argc, char *argv[])
|
||||
if (result != 0)
|
||||
{
|
||||
printf("G: auto-index at address 017 not indirectly addressing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
result = mem_get(017, false);
|
||||
if (result != 2)
|
||||
{
|
||||
printf("H: auto-index at address 017 not incrementing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
mem_put(017, false, 0x3fff);
|
||||
result = mem_get(017, true);
|
||||
if (result != 2)
|
||||
{
|
||||
printf("I: auto-index at address 017 not indirectly addressing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
result = mem_get(017, false);
|
||||
if (result != 0x4000)
|
||||
{
|
||||
printf("J: auto-index at address 017 not incrementing\n");
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// now save memory to a file
|
||||
@@ -116,22 +115,24 @@ main(int argc, char *argv[])
|
||||
mem_clear();
|
||||
for (addr = 0; addr < MEM_SIZE; ++addr)
|
||||
mem_put(addr, false, addr);
|
||||
mem_save_core("imlac.core");
|
||||
fd = fopen("imlac.core", "wb");
|
||||
mem_save_core(fd);
|
||||
fclose(fd);
|
||||
|
||||
// clear memory and read core file back in
|
||||
mem_clear();
|
||||
mem_load_core("imlac.core");
|
||||
fd = fopen("imlac.core", "rb");
|
||||
mem_load_core(fd);
|
||||
fclose(fd);
|
||||
for (addr = 0; addr < MEM_SIZE; ++addr)
|
||||
{
|
||||
if (mem_get(addr, false) != addr)
|
||||
{
|
||||
printf("K: mem_get(0x%04x) was 0x%04x, should be 0x%04x\n",
|
||||
addr, mem_get(addr, false), addr);
|
||||
errors += 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d errors found\n", errors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
0
vimlac/test_ptr.c
Normal file → Executable file
0
vimlac/test_ptr.c
Normal file → Executable file
84
vimlac/trace.c
Normal file → Executable file
84
vimlac/trace.c
Normal file → Executable file
@@ -1,27 +1,89 @@
|
||||
/*
|
||||
* Trace routines for the imlac simulator.
|
||||
* Trace routines for vimlac.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
bool TraceFlag = false;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Description : printf()-style output routine to RAW screen.
|
||||
* Parameters : like printf()
|
||||
* Returns :
|
||||
* Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
Emit(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[512];
|
||||
char *chptr;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
for (chptr = buff; *chptr != '\0'; ++chptr)
|
||||
fprintf(stdout, "%c", *chptr);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DumpRegs(char *buff)
|
||||
{
|
||||
sprintf(buff, "AC=0%6.6o\tL=%1.1o", cpu_get_AC(), cpu_get_L());
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine to dump registers.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
traceRegs(void)
|
||||
{
|
||||
static char outbuff[512];
|
||||
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
char emitbuff[512];
|
||||
|
||||
DumpRegs(outbuff);
|
||||
sprintf(emitbuff, "\t;%s", outbuff);
|
||||
Emit(emitbuff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine.
|
||||
Parameters : like printf()
|
||||
Returns :
|
||||
Comments :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[1024];
|
||||
static char outbuff[512];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
fprintf(stdout, "%s\n", buff);
|
||||
va_end(ap);
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(outbuff, fmt, ap);
|
||||
va_end(ap);
|
||||
Emit("0%6.6o\t%s", cpu_get_prev_PC(), outbuff);
|
||||
traceRegs();
|
||||
Emit("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
2
vimlac/trace.h
Normal file → Executable file
2
vimlac/trace.h
Normal file → Executable file
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Interface for the imlac TRACE routine(s).
|
||||
* Interface for the vimlac trace routines.
|
||||
*/
|
||||
|
||||
#ifndef TRACE_H
|
||||
|
||||
132
vimlac/ttyin.c
Normal file → Executable file
132
vimlac/ttyin.c
Normal file → Executable file
@@ -1,149 +1,41 @@
|
||||
/*
|
||||
* Implementation for the imlac TTYIN (TTY input) device.
|
||||
* Implementation for the vimlac TTY input device.
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.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;
|
||||
static bool flag; /* true if char ready to read */
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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)
|
||||
void
|
||||
ttyin_clear_flag(void)
|
||||
{
|
||||
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;
|
||||
flag = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ttyin_dismount(void)
|
||||
BYTE
|
||||
ttyin_get_char(void)
|
||||
{
|
||||
if (open_file)
|
||||
if (fclose(open_file) != 0)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
device_ready = true;
|
||||
at_eof = true;
|
||||
value = TTYIN_EOF;
|
||||
return ' ';
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Read the current value of the papertape device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int ttyin_get_char(void)
|
||||
bool
|
||||
ttyin_ready(void)
|
||||
{
|
||||
return value;
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
vimlac/ttyin.h
Normal file → Executable file
9
vimlac/ttyin.h
Normal file → Executable file
@@ -1,15 +1,12 @@
|
||||
/*
|
||||
* Interface for the imlac TTYIN (TTY input).
|
||||
* Interface for the vimlac TTY input device.
|
||||
*/
|
||||
|
||||
#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);
|
||||
BYTE ttyin_get_char(void);
|
||||
bool ttyin_ready(void);
|
||||
|
||||
#endif
|
||||
|
||||
119
vimlac/ttyout.c
Normal file → Executable file
119
vimlac/ttyout.c
Normal file → Executable file
@@ -1,136 +1,41 @@
|
||||
/*
|
||||
* Implementation for the imlac TTYOUT (TTY output) device.
|
||||
* Implementation for the vimlac TTY output device.
|
||||
*/
|
||||
|
||||
#include "imlac.h"
|
||||
#include "vimlac.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;
|
||||
static bool flag; /* true if char ready to read */
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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)
|
||||
void
|
||||
ttyout_clear_flag(void)
|
||||
{
|
||||
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;
|
||||
flag = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Dismount papertape file from device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments : Turns motor off.
|
||||
******************************************************************************/
|
||||
void ttyout_dismount(void)
|
||||
void
|
||||
ttyout_send(BYTE ch)
|
||||
{
|
||||
if (open_file)
|
||||
if (fclose(open_file) != 0)
|
||||
filename = NULL;
|
||||
open_file = NULL;
|
||||
device_ready = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Write a byte value to the device.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void ttyout_send(BYTE value)
|
||||
bool
|
||||
ttyout_ready(void)
|
||||
{
|
||||
if (device_ready)
|
||||
fwrite(&value, 1, 1, open_file);
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
vimlac/ttyout.h
Normal file → Executable file
9
vimlac/ttyout.h
Normal file → Executable file
@@ -1,17 +1,12 @@
|
||||
/*
|
||||
* Interface for the imlac TTYOUT (TTY input).
|
||||
* Interface for the vimlac TTY output device.
|
||||
*/
|
||||
|
||||
#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);
|
||||
void ttyout_send(BYTE);
|
||||
bool ttyout_ready(void);
|
||||
void ttyout_tick(long cycles);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user