BESM6: Implemented punchcard output.
This commit is contained in:
parent
026d082950
commit
f46c048bb6
7 changed files with 541 additions and 16 deletions
|
@ -76,11 +76,7 @@ extern const char *scp_errors[];
|
|||
GRP_CHAN5_FREE | GRP_CHAN6_FREE |\
|
||||
GRP_CHAN7_FREE )
|
||||
|
||||
/* So far irrelevant as none of the devices -
|
||||
* punchcard I/O and punchtape output - had been implemented.
|
||||
*/
|
||||
#define PRP_WIRED_BITS (PRP_UVVK1_END | PRP_UVVK2_END |\
|
||||
PRP_PCARD1_CHECK | PRP_PCARD2_CHECK |\
|
||||
PRP_PCARD1_PUNCH | PRP_PCARD2_PUNCH |\
|
||||
PRP_PTAPE1_PUNCH | PRP_PTAPE2_PUNCH )
|
||||
|
||||
|
@ -285,6 +281,7 @@ DEVICE *sim_devices[] = {
|
|||
&clock_dev,
|
||||
&printer_dev,
|
||||
&fs_dev,
|
||||
&pi_dev,
|
||||
&tty_dev, /* терминалы - телетайпы, видеотоны, "Консулы" */
|
||||
0
|
||||
};
|
||||
|
@ -651,12 +648,16 @@ static void cmd_033 ()
|
|||
/* besm6_debug(">>> гашение АС: %08o", (uint32) ACC & BITS(24));*/
|
||||
break;
|
||||
case 0154: case 0155:
|
||||
/* TODO: управление выводом на перфокарты */
|
||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||
/*
|
||||
* Punchcard output: the two selected bits control the motor
|
||||
* and the culling mechanism.
|
||||
*/
|
||||
pi_control (Aex & 1, (uint32) ACC & 011);
|
||||
break;
|
||||
case 0160: case 0167:
|
||||
/* TODO: управление электромагнитами пробивки перфокарт */
|
||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||
case 0160: case 0161: case 0162: case 0163:
|
||||
case 0164: case 0165: case 0166: case 0167:
|
||||
/* Punchcard output: activating the punching solenoids, 20 at a time. */
|
||||
pi_write (Aex & 7, (uint32) ACC & BITS(20));
|
||||
break;
|
||||
case 0170: case 0171:
|
||||
/* TODO: пробивка строки на перфоленте */
|
||||
|
@ -742,6 +743,11 @@ static void cmd_033 ()
|
|||
* группами по 8 штук каждые несколько секунд. */
|
||||
ACC = 0;
|
||||
break;
|
||||
case 04160: case 04161: case 04162: case 04163:
|
||||
case 04164: case 04165: case 04166: case 04167:
|
||||
/* Punchcard output: reading a punched line for checking, 20 bit at a time */
|
||||
ACC = pi_read (Aex & 7);
|
||||
break;
|
||||
case 04170: case 04171: case 04172: case 04173:
|
||||
/* TODO: считывание контрольного кода
|
||||
* строки перфоленты */
|
||||
|
@ -764,9 +770,6 @@ static void cmd_033 ()
|
|||
} else if (04140 <= val && val <= 04157) {
|
||||
/* TODO: считывание строки перфокарты */
|
||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||
} else if (04160 <= val && val <= 04167) {
|
||||
/* TODO: контрольное считывание строки перфокарты */
|
||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||
} else {
|
||||
/* Неиспользуемые адреса */
|
||||
/* if (sim_deb && cpu_dev.dctrl)*/
|
||||
|
|
|
@ -146,6 +146,7 @@ extern DEVICE clock_dev;
|
|||
extern DEVICE printer_dev;
|
||||
extern DEVICE tty_dev;
|
||||
extern DEVICE fs_dev;
|
||||
extern DEVICE pi_dev;
|
||||
extern jmp_buf cpu_halt;
|
||||
|
||||
/*
|
||||
|
@ -310,6 +311,12 @@ extern void mmu_setup (void);
|
|||
extern void mmu_setprotection (int idx, t_value word);
|
||||
extern void mmu_print_brz (void);
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
extern void gost_putc(unsigned char, FILE *);
|
||||
extern int odd_parity(unsigned char);
|
||||
|
||||
/*
|
||||
* Выполнение обращения к барабану.
|
||||
*/
|
||||
|
@ -348,6 +355,13 @@ int vt_is_idle (void);
|
|||
void fs_control (int num, uint32 cmd);
|
||||
int fs_read (int num);
|
||||
|
||||
/*
|
||||
* Вывод на перфокарты.
|
||||
*/
|
||||
void pi_control (int num, uint32 cmd);
|
||||
void pi_write (int num, uint32 cmd);
|
||||
int pi_read (int num);
|
||||
|
||||
/*
|
||||
* Отладочная выдача.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* besm6_punch.c: BESM-6 punchcard/punchtape devices
|
||||
* besm6_punch.c: BESM-6 punchtape devices
|
||||
*
|
||||
* Copyright (c) 2009, Leonid Broukhis
|
||||
*
|
||||
|
@ -29,7 +29,6 @@
|
|||
#include "besm6_defs.h"
|
||||
|
||||
t_stat fs_event (UNIT *u);
|
||||
t_stat uvvk_event (UNIT *u);
|
||||
|
||||
UNIT fs_unit [] = {
|
||||
{ UDATA (fs_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||
|
|
505
BESM6/besm6_punchcard.c
Normal file
505
BESM6/besm6_punchcard.c
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* besm6_punchcard.c: BESM-6 punchcard devices
|
||||
*
|
||||
* Copyright (c) 2017, Leonid Broukhis
|
||||
*
|
||||
* 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
|
||||
* SERGE VAKULENKO OR LEONID BROUKHIS 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 Leonid Broukhis or
|
||||
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||
* the sale, use or other dealings in this Software without prior written
|
||||
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||
*/
|
||||
#include "besm6_defs.h"
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Punchcard input not yet implemented.
|
||||
*/
|
||||
t_stat uvvk_event (UNIT *u); /* punched card reader */
|
||||
UNIT uvvk_unit [] = {
|
||||
{ UDATA (uvvk_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||
{ UDATA (uvvk_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||
};
|
||||
#endif
|
||||
|
||||
t_stat pi_event (UNIT *u); /* punched card writer */
|
||||
UNIT pi_unit [] = {
|
||||
{ UDATA (pi_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||
{ UDATA (pi_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
/*
|
||||
* Each line has 3 phases:
|
||||
* - striking: the "PUNCH" interrupt line goes high,
|
||||
* puncher solenoids can be activated
|
||||
* - moving: solenoids are turned off, the "PUNCH" interrupt line goes low
|
||||
* - checking: the "CHECK" interrupt goes high,
|
||||
* querying of the check brushes can be done.
|
||||
*/
|
||||
typedef enum {
|
||||
PI_STRIKE,
|
||||
PI_MOVE,
|
||||
PI_CHECK,
|
||||
PI_LAST = PI_STRIKE + 3*12 - 1,
|
||||
PI_PAUSE,
|
||||
PI_IDLE
|
||||
} pi_state_t;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* A 3-card long tract, with 12 lines per card,
|
||||
* represented as 4 20-bit registers each.
|
||||
*/
|
||||
uint32 image[3][12][4];
|
||||
int cur; /* FIFO position */
|
||||
int running; /* continue with the next card */
|
||||
pi_state_t state;
|
||||
void (*punch_fn)(int, int);
|
||||
} pi_t;
|
||||
|
||||
/*
|
||||
* There are 2 card punchers */
|
||||
pi_t PI[2];
|
||||
|
||||
#define PI1_READY (1<<15)
|
||||
#define PI2_READY (1<<13)
|
||||
|
||||
#define PI1_START (1<<14)
|
||||
#define PI2_START (1<<12)
|
||||
|
||||
// #define NEGATIVE_RDY
|
||||
|
||||
#ifndef NEGATIVE_RDY
|
||||
# define ENB_RDY2 SET_RDY2
|
||||
# define DIS_RDY2 CLR_RDY2
|
||||
# define IS_RDY2 ISSET_RDY2
|
||||
#else
|
||||
# define ENB_RDY2 CLR_RDY2
|
||||
# define DIS_RDY2 SET_RDY2
|
||||
# define IS_RDY2 ISCLR_RDY2
|
||||
#endif
|
||||
|
||||
#define SET_RDY2(x) do READY2 |= x; while (0)
|
||||
#define CLR_RDY2(x) do READY2 &= ~(x); while (0)
|
||||
#define ISSET_RDY2(x) ((READY2 & (x)) != 0)
|
||||
#define ISCLR_RDY2(x) ((READY2 & (x)) == 0)
|
||||
|
||||
/*
|
||||
* Per one line of a punched card.
|
||||
*/
|
||||
#define PI_RATE (20*MSEC)
|
||||
|
||||
const uint32 pi_punch_mask[2] = { PRP_PCARD1_PUNCH, PRP_PCARD2_PUNCH };
|
||||
const uint32 pi_check_mask[2] = { PRP_PCARD1_CHECK, PRP_PCARD2_CHECK };
|
||||
const uint32 pi_ready_mask[2] = { PI1_READY, PI2_READY };
|
||||
const uint32 pi_start_mask[2] = { PI1_START, PI2_START };
|
||||
|
||||
REG pi_reg[] = {
|
||||
{ REGDATA ( "READY", READY2, 2, 4, 12, 1, NULL, NULL, 0, 0, 0) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MTAB pi_mod[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
t_stat pi_reset (DEVICE *dptr);
|
||||
t_stat pi_attach (UNIT *uptr, CONST char *cptr);
|
||||
t_stat pi_detach (UNIT *uptr);
|
||||
|
||||
DEVICE pi_dev = {
|
||||
"PI", pi_unit, pi_reg, pi_mod,
|
||||
2, 8, 19, 1, 8, 50,
|
||||
NULL, NULL, &pi_reset, NULL, &pi_attach, &pi_detach,
|
||||
NULL, DEV_DISABLE | DEV_DEBUG
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Outputs 12 lines of 80 characters plus an empty line.
|
||||
*/
|
||||
static void pi_punch_dots(int unit, int card) {
|
||||
UNIT *u = &pi_unit[unit];
|
||||
FILE * f = u->fileref;
|
||||
int l, p, c;
|
||||
for (l = 0; l < 12; ++l) {
|
||||
for (p = 0; p < 4; ++p)
|
||||
for (c = 19; c >= 0; --c)
|
||||
putc((PI[unit].image[card][l][p] >> c) & 1 ? 'O' : '.', f);
|
||||
putc('\n', f);
|
||||
}
|
||||
putc('\n', f);
|
||||
}
|
||||
|
||||
static void pi_to_bytes(int unit, int card, unsigned char buf[120]) {
|
||||
int byte = 0;
|
||||
int cnt = 0;
|
||||
int l, p, c;
|
||||
for (l = 0; l < 12; ++l) {
|
||||
for (p = 0; p < 4; ++p) {
|
||||
for (c = 19; c >= 0; --c) {
|
||||
int bit = (PI[unit].image[card][l][p] >> c) & 1 ? 1 : 0;
|
||||
buf[byte] <<= 1;
|
||||
buf[byte] |= bit;
|
||||
if (++cnt == 8) {
|
||||
cnt = 0;
|
||||
++byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Outputs 120 bytes, read linewise.
|
||||
*/
|
||||
static void pi_punch_binary(int unit, int card) {
|
||||
UNIT *u = &pi_unit[unit];
|
||||
FILE * f = u->fileref;
|
||||
unsigned char buf[120];
|
||||
pi_to_bytes(unit, card, buf);
|
||||
fwrite(buf, 120, 1, f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Outputs a visual representation of the card
|
||||
* using 3 lines of 40 Braille patterns, plus an empty line.
|
||||
*/
|
||||
static void pi_punch_visual(int unit, int card) {
|
||||
UNIT *u = &pi_unit[unit];
|
||||
FILE * f = u->fileref;
|
||||
// Print 3 lines of 40 Braille characters per line representing a punchcard.
|
||||
unsigned char bytes[3][40];
|
||||
int line, col, p, c;
|
||||
memset(bytes, 0, 120);
|
||||
for (line = 0; line < 12; ++line) {
|
||||
for (p = 0; p < 4; ++p)
|
||||
for (c = 19; c >= 0; --c) {
|
||||
int bit = (PI[unit].image[card][line][p] >> c) & 1 ? 1 : 0;
|
||||
int col = p*20 + 19-c;
|
||||
if (bit) {
|
||||
/*
|
||||
* Braille Unicode codepoints are U+2800 plus
|
||||
* an 8-bit mask of punches according to the map
|
||||
* 0 3
|
||||
* 1 4
|
||||
* 2 5
|
||||
* 6 7
|
||||
*/
|
||||
bytes[line/4][col/2] |=
|
||||
"\x01\x08\x02\x10\x04\x20\x40\x80"[line%4*2+col%2];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (line = 0; line < 3; ++line) {
|
||||
for (col = 0; col < 40; ++col) {
|
||||
fprintf(f, "\342%c%c",
|
||||
0240+(bytes[line][col] >> 6),
|
||||
0200 + (bytes[line][col] & 077));
|
||||
}
|
||||
putc('\n', f);
|
||||
}
|
||||
putc('\n', f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to interpret a card as GOST-10859 with odd parity;
|
||||
* if fails, dumps visual.
|
||||
*/
|
||||
static void pi_punch_gost(int unit, int card) {
|
||||
UNIT *u = &pi_unit[unit];
|
||||
FILE * f = u->fileref;
|
||||
unsigned char buf[120];
|
||||
int len;
|
||||
int cur;
|
||||
int zero_expected = 0;
|
||||
pi_to_bytes(unit, card, buf);
|
||||
/*
|
||||
* Bytes in the buffer must have odd parity, with the exception
|
||||
* of optional zero bytes at the end of lines and at the end of a card.
|
||||
* Trailing zeros are trimmed, intermediate zeros become blanks.
|
||||
* The first character in each line must be valid.
|
||||
*/
|
||||
for (len = 120; len && !buf[len-1]; --len);
|
||||
for (cur = 0; cur < len; ++cur) {
|
||||
if (cur % 10 == 0) {
|
||||
/* A new line */
|
||||
zero_expected = 0;
|
||||
}
|
||||
if (zero_expected) {
|
||||
if (buf[cur])
|
||||
break;
|
||||
} else if (!buf[cur]) {
|
||||
if (cur % 10 == 0) {
|
||||
/* The first char in a line is zero */
|
||||
break;
|
||||
}
|
||||
zero_expected = 1;
|
||||
} else if (!odd_parity(buf[cur]) || (buf[cur] & 0177) >= 0140) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cur != len) {
|
||||
/* Bad parity or invalid codepoint detected */
|
||||
pi_punch_visual(unit, card);
|
||||
} else {
|
||||
for (cur = 0; cur < len; ++cur) {
|
||||
if (buf[cur]) {
|
||||
gost_putc(buf[cur] & 0177, f);
|
||||
} else {
|
||||
putc(' ', f);
|
||||
}
|
||||
}
|
||||
putc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps the last card in the FIFO and advances the FIFO pointer
|
||||
* (this is equivalent to advancing the FIFO pointer and dumping
|
||||
* the "current" card).
|
||||
*/
|
||||
static void pi_output (int unit, int cull) {
|
||||
int card;
|
||||
|
||||
PI[unit].cur = card = (PI[unit].cur + 1) % 3;
|
||||
|
||||
if (cull) {
|
||||
besm6_debug("<<< PI-%d: Culling bad card", unit);
|
||||
} else {
|
||||
(*PI[unit].punch_fn)(unit, card);
|
||||
}
|
||||
pi_unit[unit].pos = ftell(pi_unit[unit].fileref);
|
||||
memset(PI[unit].image[card], 0, sizeof(PI[unit].image[card]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset routine
|
||||
*/
|
||||
t_stat pi_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&pi_unit[0]);
|
||||
sim_cancel (&pi_unit[1]);
|
||||
PI[0].state = PI[1].state = PI_IDLE;
|
||||
DIS_RDY2(PI1_READY | PI2_READY);
|
||||
if (pi_unit[0].flags & UNIT_ATT)
|
||||
ENB_RDY2(PI1_READY|PI1_START);
|
||||
if (pi_unit[1].flags & UNIT_ATT)
|
||||
ENB_RDY2(PI2_READY|PI2_START);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Punching mode switches:
|
||||
* -b - raw binary, line-wise, 120 bytes per p/c;
|
||||
* -v - a visual form using Unicode Braille patterns;
|
||||
* -d - a visual form using dots and Os;
|
||||
* -g or -u - attempts to interpret the card as GOST/UPP text.
|
||||
* The default is -v.
|
||||
*/
|
||||
t_stat pi_attach (UNIT *u, CONST char *cptr)
|
||||
{
|
||||
t_stat s;
|
||||
int unit = u - pi_unit;
|
||||
PI[unit].punch_fn = NULL;
|
||||
while (sim_switches &
|
||||
(SWMASK('B')|SWMASK('V')|SWMASK('D')|SWMASK('G')|SWMASK('U'))) {
|
||||
if (PI[unit].punch_fn) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if (sim_switches & SWMASK('B')) {
|
||||
PI[unit].punch_fn = pi_punch_binary;
|
||||
sim_switches &= ~SWMASK('B');
|
||||
} else if (sim_switches & SWMASK('V')) {
|
||||
PI[unit].punch_fn = pi_punch_visual;
|
||||
sim_switches &= ~SWMASK('V');
|
||||
} else if (sim_switches & SWMASK('D')) {
|
||||
PI[unit].punch_fn = pi_punch_dots;
|
||||
sim_switches &= ~SWMASK('D');
|
||||
} else if (sim_switches & SWMASK('G')) {
|
||||
PI[unit].punch_fn = pi_punch_gost;
|
||||
sim_switches &= ~SWMASK('G');
|
||||
} else if (sim_switches & SWMASK('U')) {
|
||||
PI[unit].punch_fn = pi_punch_gost;
|
||||
sim_switches &= ~SWMASK('U');
|
||||
}
|
||||
}
|
||||
if (PI[unit].punch_fn == NULL) {
|
||||
PI[unit].punch_fn = pi_punch_visual;
|
||||
}
|
||||
s = attach_unit (u, cptr);
|
||||
if (s != SCPE_OK)
|
||||
return s;
|
||||
ENB_RDY2(pi_ready_mask[unit]);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat pi_detach (UNIT *u)
|
||||
{
|
||||
int unit = u - pi_unit;
|
||||
DIS_RDY2(pi_ready_mask[unit]);
|
||||
return detach_unit (u);
|
||||
}
|
||||
|
||||
void pi_control (int num, uint32 cmd)
|
||||
{
|
||||
UNIT *u = &pi_unit[num];
|
||||
if (pi_dev.dctrl)
|
||||
besm6_debug("<<<PI-%d cmd %o, state %d", num, cmd, PI[num].state);
|
||||
cmd &= 011;
|
||||
if (! IS_RDY2(pi_ready_mask[num])) {
|
||||
if (pi_dev.dctrl)
|
||||
besm6_debug("<<< PI-%d not ready", num, cmd);
|
||||
return;
|
||||
}
|
||||
switch (cmd) {
|
||||
case 000: /* stop */
|
||||
case 010: /* stop with culling (doesn't make much sense) */
|
||||
if (PI[num].state == PI_LAST) {
|
||||
pi_output(num, cmd & 010);
|
||||
}
|
||||
sim_cancel (u);
|
||||
PI[num].state = PI_IDLE;
|
||||
ENB_RDY2(pi_start_mask[num]);
|
||||
break;
|
||||
case 001: /* start without culling */
|
||||
case 011: /* start with culling */
|
||||
switch (PI[num].state) {
|
||||
case PI_IDLE:
|
||||
sim_activate (u, PI_RATE);
|
||||
break;
|
||||
case PI_PAUSE:
|
||||
/* Switching on during pause ignored */
|
||||
besm6_debug("<<< PI-%d switching on during pause ignored", num);
|
||||
break;
|
||||
case PI_LAST:
|
||||
PI[num].running = 1;
|
||||
/* This is the only state when the cull bit is honored */
|
||||
pi_output(num, cmd & 010);
|
||||
break;
|
||||
default:
|
||||
PI[num].running = 1;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
t_stat pi_event (UNIT *u)
|
||||
{
|
||||
int unit = u - pi_unit;
|
||||
if (++PI[unit].state > PI_IDLE) {
|
||||
/* Starting a new card */
|
||||
PI[unit].state = PI_STRIKE;
|
||||
}
|
||||
switch (PI[unit].state) {
|
||||
case PI_LAST:
|
||||
/*
|
||||
* At the last check interrupt,
|
||||
* the "permission to start" flag is cleared.
|
||||
*/
|
||||
DIS_RDY2(pi_start_mask[unit]);
|
||||
break;
|
||||
case PI_PAUSE:
|
||||
/*
|
||||
* The permission to start is re-enabled.
|
||||
*/
|
||||
ENB_RDY2(pi_start_mask[unit]);
|
||||
PI[unit].state = PI_IDLE;
|
||||
if (PI[unit].running) {
|
||||
if (pi_dev.dctrl)
|
||||
besm6_debug ("<<< PI-%d re-enabled", unit);
|
||||
sim_activate(u, PI_RATE);
|
||||
PI[unit].running = 0;
|
||||
} else {
|
||||
/*
|
||||
* The unit is going idle without an explicit "stop" command:
|
||||
* The last card (the separator) falls into the "good" bin.
|
||||
*/
|
||||
pi_output(unit, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (pi_dev.dctrl)
|
||||
besm6_debug ("<<< PI-%d event, state %d", unit, PI[unit].state);
|
||||
if (PI[unit].state <= PI_LAST) {
|
||||
switch (PI[unit].state % 3) {
|
||||
case PI_STRIKE:
|
||||
/* Punch interrupt */
|
||||
PRP |= pi_punch_mask[unit];
|
||||
sim_activate(u, PI_RATE/3);
|
||||
break;
|
||||
case PI_MOVE:
|
||||
/* Punchers off */
|
||||
PRP &= ~pi_punch_mask[unit];
|
||||
sim_activate(u, 2*PI_RATE/3);
|
||||
break;
|
||||
case PI_CHECK:
|
||||
/* Check interrupt */
|
||||
PRP |= pi_check_mask[unit];
|
||||
sim_activate(u, PI_RATE);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writing to the register punches the current card.
|
||||
*/
|
||||
void pi_write (int num, uint32 val)
|
||||
{
|
||||
int unit = num >> 2;
|
||||
int card = PI[unit].cur;
|
||||
int pos = (num & 3) ^ 3;
|
||||
int line = PI[unit].state / 3;
|
||||
if (line > 11 || PI[unit].state % 3 != PI_STRIKE) {
|
||||
besm6_debug("<<< PI-%d, writing out of turn, useless", num);
|
||||
return;
|
||||
}
|
||||
if (pi_dev.dctrl) {
|
||||
besm6_debug("Card %d line %d pos %d <- val %05x",
|
||||
card, line, pos, val);
|
||||
}
|
||||
PI[unit].image[card][line][pos] = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reading from the register reads the previous card
|
||||
* and returns the inverted value.
|
||||
*/
|
||||
int pi_read (int num)
|
||||
{
|
||||
int unit = num >> 2;
|
||||
int pos = (num & 3) ^ 3;
|
||||
int line = PI[unit].state / 3;
|
||||
int card = (PI[unit].cur + 2) % 3;
|
||||
if (line > 11 || PI[unit].state % 3 != PI_CHECK) {
|
||||
/* Reading out of turn */
|
||||
return 0xFFFFF;
|
||||
} else {
|
||||
if (pi_dev.dctrl) {
|
||||
besm6_debug("Card %d line %d pos %d -> val %05x",
|
||||
card, line, pos, PI[unit].image[card][line][pos]);
|
||||
}
|
||||
return PI[unit].image[card][line][pos] ^ 0xFFFFF;
|
||||
}
|
||||
}
|
||||
|
|
@ -220,6 +220,10 @@
|
|||
RelativePath="..\BESM6\besm6_punch.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\BESM6\besm6_punchcard.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\BESM6\besm6_sys.c"
|
||||
>
|
||||
|
|
|
@ -664,7 +664,7 @@ BESM6_LIB = $(LIB_DIR)BESM6-$(ARCH).OLB
|
|||
BESM6_SOURCE = $(BESM6_DIR)BESM6_CPU.C,$(BESM6_DIR)BESM6_SYS.C,$(BESM6_DIR)BESM6_MMU.C,\
|
||||
$(BESM6_DIR)BESM6_ARITH.C,$(BESM6_DIR)BESM6_DISK.C,$(BESM6_DIR)BESM6_DRUM.C,\
|
||||
$(BESM6_DIR)BESM6_TTY.C,$(BESM6_DIR)BESM6_PANEL.C,$(BESM6_DIR)BESM6_PRINTER.C,\
|
||||
$(BESM6_DIR)BESM6_PUNCH.C
|
||||
$(BESM6_DIR)BESM6_PUNCHCARD.C,$(BESM6_DIR)BESM6_PUNCH.C
|
||||
BESM6_OPTIONS = /INCL=($(SIMH_DIR),$(BESM6_DIR))/DEF=($(CC_DEFS),"USE_INT64=1")
|
||||
|
||||
#
|
||||
|
|
2
makefile
2
makefile
|
@ -1438,7 +1438,7 @@ BESM6D = BESM6
|
|||
BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \
|
||||
${BESM6D}/besm6_arith.c ${BESM6D}/besm6_disk.c ${BESM6D}/besm6_drum.c \
|
||||
${BESM6D}/besm6_tty.c ${BESM6D}/besm6_panel.c ${BESM6D}/besm6_printer.c \
|
||||
${BESM6D}/besm6_punch.c
|
||||
${BESM6D}/besm6_punch.c ${BESM6D}/besm6_punchcard.c
|
||||
|
||||
ifneq (,$(BESM6_BUILD))
|
||||
ifneq (,$(and ${VIDEO_LDFLAGS}, $(or $(and $(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf)), $(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf)))))
|
||||
|
|
Loading…
Add table
Reference in a new issue