From 89b992d468e5691dd7601a22d87477280e5c1dda Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 8 Dec 2025 12:45:09 -1000 Subject: [PATCH] linc: Change line endings to simh CRLF standard These file got missed when the linc simulator was original added --- linc/linc_dpy.c | 80 ++-- linc/linc_kbd.c | 534 +++++++++++++-------------- linc/linc_tape.c | 940 +++++++++++++++++++++++------------------------ linc/linc_tty.c | 248 ++++++------- 4 files changed, 901 insertions(+), 901 deletions(-) diff --git a/linc/linc_dpy.c b/linc/linc_dpy.c index 861873c8..2faadcf3 100644 --- a/linc/linc_dpy.c +++ b/linc/linc_dpy.c @@ -1,40 +1,40 @@ -#include "linc_defs.h" - -/* Debug */ -#define DBG 0001 - -static DEBTAB dpy_deb[] = { - { "DBG", DBG }, - { NULL, 0 } -}; - -DEVICE dpy_dev = { - "DPY", NULL, NULL, NULL, - 0, 8, 12, 1, 8, 12, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, DEV_DEBUG, 0, dpy_deb, - NULL, NULL, NULL, NULL, NULL, NULL -}; - -void dpy_dis(uint16 h, uint16 x, uint16 y) -{ - sim_debug(DBG, &dpy_dev, "DIS %u;%03o, A=%03o\n", h, x, y); - /* Y coordinate +0 and -0 both refer to the same vertical position. */ - if (y < 256) - y += 255; - else - y -= 256; - crt_point(x, y); -} - -/* Called from display library to get data switches. */ -void -cpu_get_switches (unsigned long *p1, unsigned long *p2) -{ -} - -/* Called from display library to set data switches. */ -void -cpu_set_switches (unsigned long p1, unsigned long p2) -{ -} +#include "linc_defs.h" + +/* Debug */ +#define DBG 0001 + +static DEBTAB dpy_deb[] = { + { "DBG", DBG }, + { NULL, 0 } +}; + +DEVICE dpy_dev = { + "DPY", NULL, NULL, NULL, + 0, 8, 12, 1, 8, 12, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, dpy_deb, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +void dpy_dis(uint16 h, uint16 x, uint16 y) +{ + sim_debug(DBG, &dpy_dev, "DIS %u;%03o, A=%03o\n", h, x, y); + /* Y coordinate +0 and -0 both refer to the same vertical position. */ + if (y < 256) + y += 255; + else + y -= 256; + crt_point(x, y); +} + +/* Called from display library to get data switches. */ +void +cpu_get_switches (unsigned long *p1, unsigned long *p2) +{ +} + +/* Called from display library to set data switches. */ +void +cpu_set_switches (unsigned long p1, unsigned long p2) +{ +} diff --git a/linc/linc_kbd.c b/linc/linc_kbd.c index 6a6ae1f8..53b4b03c 100644 --- a/linc/linc_kbd.c +++ b/linc/linc_kbd.c @@ -1,267 +1,267 @@ -#include "linc_defs.h" -#include "sim_video.h" - -/* Debug */ -#define DBG 0001 - -#define A (*(uint16 *)cpu_reg[2].loc) -#define paused (*(int *)cpu_reg[11].loc) - -static t_stat kbd_reset(DEVICE *dptr); - -static DEBTAB kbd_deb[] = { - { "DBG", DBG }, - { NULL, 0 } -}; - -DEVICE kbd_dev = { - "KBD", NULL, NULL, NULL, - 0, 8, 12, 1, 8, 12, - NULL, NULL, &kbd_reset, - NULL, NULL, NULL, NULL, DEV_DEBUG, 0, kbd_deb, - NULL, NULL, NULL, NULL, NULL, NULL -}; - -/* -CASE 0 1 2 3 4 5 6 7 8 9 DEL - 23 00 01 02 03 04 05 06 07 10 11 13 - - Q W E R T Y U I O P i= - 44 52 30 45 47 54 50 34 42 43 15 - - A S D F G H J K L +. -, - 24 46 27 31 32 33 35 36 37 10 17 - - #[ Z X C V B N M pu |⊟ META/EOL - 22 55 53 26 51 25 41 40 16 21 12 - - SPACE - 14 -*/ - -static int kbd_pressed = 0; -static uint16 kbd_code; - -int kbd_struck(void) -{ - if (kbd_pressed) - sim_debug(DBG, &kbd_dev, "KST\n"); - return kbd_pressed; -} - -uint16 kbd_key(uint16 wait) -{ - if (kbd_pressed) { - sim_debug(DBG, &kbd_dev, "KEY %02o\n", kbd_code); - kbd_pressed = 0; - return kbd_code; - } else if (wait) { - sim_debug(DBG, &kbd_dev, "KEY paused\n"); - paused = 1; - } - return 0; -} - -static void kbd_convert(uint32 key) -{ - switch (key) { - case SIM_KEY_0: /* 0 Q */ - case SIM_KEY_BACKQUOTE: - kbd_code = 000; - break; - case SIM_KEY_1: /* 1 R */ - kbd_code = 001; - break; - case SIM_KEY_2: /* 2 S */ - kbd_code = 002; - break; - case SIM_KEY_3: /* 3 T */ - kbd_code = 003; - break; - case SIM_KEY_4: /* 4 U */ - kbd_code = 004; - break; - case SIM_KEY_5: /* 5 V */ - kbd_code = 005; - break; - case SIM_KEY_6: /* 6 W */ - kbd_code = 006; - break; - case SIM_KEY_7: /* 7 X */ - kbd_code = 007; - break; - case SIM_KEY_8: /* 8 Y */ - kbd_code = 010; - break; - case SIM_KEY_9: /* 9 Z */ - kbd_code = 011; - break; - case SIM_KEY_ENTER: - kbd_code = 012; - break; - case SIM_KEY_BACKSPACE: - case SIM_KEY_DELETE: - kbd_code = 013; - break; - case SIM_KEY_SPACE: /* Space ? */ - case SIM_KEY_SLASH: - kbd_code = 014; - break; - case SIM_KEY_EQUALS: /* i = */ - kbd_code = 015; - break; - case SIM_KEY_F1: /* p u */ - kbd_code = 016; - break; - case SIM_KEY_MINUS: /* - , */ - case SIM_KEY_COMMA: - kbd_code = 017; - break; - case SIM_KEY_PERIOD: /* + . */ - kbd_code = 020; - break; - case SIM_KEY_BACKSLASH: /* | ⊟ */ - kbd_code = 021; - break; - case SIM_KEY_LEFT_BRACKET: /* # [ */ - case SIM_KEY_LEFT_BACKSLASH: - kbd_code = 022; - break; - case SIM_KEY_SHIFT_L: /* CASE _ */ - case SIM_KEY_SHIFT_R: - kbd_code = 023; - break; - case SIM_KEY_A: /* A " */ - case SIM_KEY_SINGLE_QUOTE: - kbd_code = 024; - break; - case SIM_KEY_B: /* B „ */ - kbd_code = 025; - break; - case SIM_KEY_C: /* C < */ - kbd_code = 026; - break; - case SIM_KEY_D: /* D > */ - kbd_code = 027; - break; - case SIM_KEY_E: /* E ] */ - case SIM_KEY_RIGHT_BRACKET: - kbd_code = 030; - break; - case SIM_KEY_F: /* F ˣ */ - kbd_code = 031; - break; - case SIM_KEY_G: /* G : */ - case SIM_KEY_SEMICOLON: - kbd_code = 032; - break; - case SIM_KEY_H: /* H */ - kbd_code = 033; - break; - case SIM_KEY_I: /* I */ - kbd_code = 034; - break; - case SIM_KEY_J: /* J */ - kbd_code = 035; - break; - case SIM_KEY_K: /* K */ - kbd_code = 036; - break; - case SIM_KEY_L: /* L */ - kbd_code = 037; - break; - case SIM_KEY_M: /* M */ - kbd_code = 040; - break; - case SIM_KEY_N: /* N */ - kbd_code = 041; - break; - case SIM_KEY_O: /* O */ - kbd_code = 042; - break; - case SIM_KEY_P: /* P */ - kbd_code = 043; - break; - case SIM_KEY_Q: /* Q */ - kbd_code = 044; - break; - case SIM_KEY_R: /* R */ - kbd_code = 045; - break; - case SIM_KEY_S: /* S */ - kbd_code = 046; - break; - case SIM_KEY_T: /* T */ - kbd_code = 047; - break; - case SIM_KEY_U: /* U */ - kbd_code = 050; - break; - case SIM_KEY_V: /* V */ - kbd_code = 051; - break; - case SIM_KEY_W: /* W */ - kbd_code = 052; - break; - case SIM_KEY_X: /* X */ - kbd_code = 053; - break; - case SIM_KEY_Y: /* Y */ - kbd_code = 054; - break; - case SIM_KEY_Z: /* Z */ - kbd_code = 055; - break; - case SIM_KEY_ALT_L: /* META? */ - case SIM_KEY_ALT_R: - kbd_code = 056; - break; - // → 57 - // ? 60 - // = 61 - // u 62 - // , 63 - // . 64 - // ⊟ 65 - // [ 66 - // _ 67 - // " 70 - // „ 71 - // < 72 - // > 73 - // ] 74 - // ˣ 75 - // : 76 - // ʸ 77 - case SIM_KEY_F11: - crt_toggle_fullscreen(); - return; - default: - return; - } - sim_debug(DBG, &kbd_dev, "Key struck %s -> %02o\n", - vid_key_name(key), kbd_code); - if (paused) - A = kbd_code; - else - kbd_pressed = 1; - paused = 0; -} - -static int -kbd_event(SIM_KEY_EVENT *ev) -{ - if (ev->state == SIM_KEYPRESS_DOWN) - kbd_convert(ev->key); - return 0; -} - -static t_stat -kbd_reset(DEVICE *dptr) -{ -#ifdef USE_DISPLAY - vid_display_kb_event_process = kbd_event; -#endif - - return SCPE_OK; -} +#include "linc_defs.h" +#include "sim_video.h" + +/* Debug */ +#define DBG 0001 + +#define A (*(uint16 *)cpu_reg[2].loc) +#define paused (*(int *)cpu_reg[11].loc) + +static t_stat kbd_reset(DEVICE *dptr); + +static DEBTAB kbd_deb[] = { + { "DBG", DBG }, + { NULL, 0 } +}; + +DEVICE kbd_dev = { + "KBD", NULL, NULL, NULL, + 0, 8, 12, 1, 8, 12, + NULL, NULL, &kbd_reset, + NULL, NULL, NULL, NULL, DEV_DEBUG, 0, kbd_deb, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* +CASE 0 1 2 3 4 5 6 7 8 9 DEL + 23 00 01 02 03 04 05 06 07 10 11 13 + + Q W E R T Y U I O P i= + 44 52 30 45 47 54 50 34 42 43 15 + + A S D F G H J K L +. -, + 24 46 27 31 32 33 35 36 37 10 17 + + #[ Z X C V B N M pu |⊟ META/EOL + 22 55 53 26 51 25 41 40 16 21 12 + + SPACE + 14 +*/ + +static int kbd_pressed = 0; +static uint16 kbd_code; + +int kbd_struck(void) +{ + if (kbd_pressed) + sim_debug(DBG, &kbd_dev, "KST\n"); + return kbd_pressed; +} + +uint16 kbd_key(uint16 wait) +{ + if (kbd_pressed) { + sim_debug(DBG, &kbd_dev, "KEY %02o\n", kbd_code); + kbd_pressed = 0; + return kbd_code; + } else if (wait) { + sim_debug(DBG, &kbd_dev, "KEY paused\n"); + paused = 1; + } + return 0; +} + +static void kbd_convert(uint32 key) +{ + switch (key) { + case SIM_KEY_0: /* 0 Q */ + case SIM_KEY_BACKQUOTE: + kbd_code = 000; + break; + case SIM_KEY_1: /* 1 R */ + kbd_code = 001; + break; + case SIM_KEY_2: /* 2 S */ + kbd_code = 002; + break; + case SIM_KEY_3: /* 3 T */ + kbd_code = 003; + break; + case SIM_KEY_4: /* 4 U */ + kbd_code = 004; + break; + case SIM_KEY_5: /* 5 V */ + kbd_code = 005; + break; + case SIM_KEY_6: /* 6 W */ + kbd_code = 006; + break; + case SIM_KEY_7: /* 7 X */ + kbd_code = 007; + break; + case SIM_KEY_8: /* 8 Y */ + kbd_code = 010; + break; + case SIM_KEY_9: /* 9 Z */ + kbd_code = 011; + break; + case SIM_KEY_ENTER: + kbd_code = 012; + break; + case SIM_KEY_BACKSPACE: + case SIM_KEY_DELETE: + kbd_code = 013; + break; + case SIM_KEY_SPACE: /* Space ? */ + case SIM_KEY_SLASH: + kbd_code = 014; + break; + case SIM_KEY_EQUALS: /* i = */ + kbd_code = 015; + break; + case SIM_KEY_F1: /* p u */ + kbd_code = 016; + break; + case SIM_KEY_MINUS: /* - , */ + case SIM_KEY_COMMA: + kbd_code = 017; + break; + case SIM_KEY_PERIOD: /* + . */ + kbd_code = 020; + break; + case SIM_KEY_BACKSLASH: /* | ⊟ */ + kbd_code = 021; + break; + case SIM_KEY_LEFT_BRACKET: /* # [ */ + case SIM_KEY_LEFT_BACKSLASH: + kbd_code = 022; + break; + case SIM_KEY_SHIFT_L: /* CASE _ */ + case SIM_KEY_SHIFT_R: + kbd_code = 023; + break; + case SIM_KEY_A: /* A " */ + case SIM_KEY_SINGLE_QUOTE: + kbd_code = 024; + break; + case SIM_KEY_B: /* B „ */ + kbd_code = 025; + break; + case SIM_KEY_C: /* C < */ + kbd_code = 026; + break; + case SIM_KEY_D: /* D > */ + kbd_code = 027; + break; + case SIM_KEY_E: /* E ] */ + case SIM_KEY_RIGHT_BRACKET: + kbd_code = 030; + break; + case SIM_KEY_F: /* F ˣ */ + kbd_code = 031; + break; + case SIM_KEY_G: /* G : */ + case SIM_KEY_SEMICOLON: + kbd_code = 032; + break; + case SIM_KEY_H: /* H */ + kbd_code = 033; + break; + case SIM_KEY_I: /* I */ + kbd_code = 034; + break; + case SIM_KEY_J: /* J */ + kbd_code = 035; + break; + case SIM_KEY_K: /* K */ + kbd_code = 036; + break; + case SIM_KEY_L: /* L */ + kbd_code = 037; + break; + case SIM_KEY_M: /* M */ + kbd_code = 040; + break; + case SIM_KEY_N: /* N */ + kbd_code = 041; + break; + case SIM_KEY_O: /* O */ + kbd_code = 042; + break; + case SIM_KEY_P: /* P */ + kbd_code = 043; + break; + case SIM_KEY_Q: /* Q */ + kbd_code = 044; + break; + case SIM_KEY_R: /* R */ + kbd_code = 045; + break; + case SIM_KEY_S: /* S */ + kbd_code = 046; + break; + case SIM_KEY_T: /* T */ + kbd_code = 047; + break; + case SIM_KEY_U: /* U */ + kbd_code = 050; + break; + case SIM_KEY_V: /* V */ + kbd_code = 051; + break; + case SIM_KEY_W: /* W */ + kbd_code = 052; + break; + case SIM_KEY_X: /* X */ + kbd_code = 053; + break; + case SIM_KEY_Y: /* Y */ + kbd_code = 054; + break; + case SIM_KEY_Z: /* Z */ + kbd_code = 055; + break; + case SIM_KEY_ALT_L: /* META? */ + case SIM_KEY_ALT_R: + kbd_code = 056; + break; + // → 57 + // ? 60 + // = 61 + // u 62 + // , 63 + // . 64 + // ⊟ 65 + // [ 66 + // _ 67 + // " 70 + // „ 71 + // < 72 + // > 73 + // ] 74 + // ˣ 75 + // : 76 + // ʸ 77 + case SIM_KEY_F11: + crt_toggle_fullscreen(); + return; + default: + return; + } + sim_debug(DBG, &kbd_dev, "Key struck %s -> %02o\n", + vid_key_name(key), kbd_code); + if (paused) + A = kbd_code; + else + kbd_pressed = 1; + paused = 0; +} + +static int +kbd_event(SIM_KEY_EVENT *ev) +{ + if (ev->state == SIM_KEYPRESS_DOWN) + kbd_convert(ev->key); + return 0; +} + +static t_stat +kbd_reset(DEVICE *dptr) +{ +#ifdef USE_DISPLAY + vid_display_kb_event_process = kbd_event; +#endif + + return SCPE_OK; +} diff --git a/linc/linc_tape.c b/linc/linc_tape.c index f5014769..daf5d32c 100644 --- a/linc/linc_tape.c +++ b/linc/linc_tape.c @@ -1,470 +1,470 @@ -#include "linc_defs.h" - -#define POS u3 -#define SPEED u4 -#define ACC u5 -#define OFFSET u6 - -#define P (*(uint16 *)cpu_reg[0].loc) -#define C (*(uint16 *)cpu_reg[1].loc) -#define A (*(uint16 *)cpu_reg[2].loc) -#define S (*(uint16 *)cpu_reg[6].loc) -#define B (*(uint16 *)cpu_reg[7].loc) -#define LSW (*(uint16 *)cpu_reg[8].loc) -#define RSW (*(uint16 *)cpu_reg[9].loc) -#define paused (*(int *)cpu_reg[11].loc) -#define IBZ (*(int *)cpu_reg[12].loc) - -#define ACC_START 3 -#define ACC_REVERSE 6 -#define ACC_STOP 1 -#define MAX_SPEED (ACC_START * 625) /* 0.1s / 160µs */ -#define IBZ_WORDS 5 -#define DATA_WORDS 256 -#define OTHER_WORDS 7 -#define BLOCK_WORDS (IBZ_WORDS + DATA_WORDS + OTHER_WORDS) -#define START_POS (ACC_START * (625 + (625 * 625))/2) -#define MAX_BLOCKS 512 -#define MAX_POS ((BLOCK_WORDS * MAX_BLOCKS + IBZ_WORDS) * MAX_SPEED) - -#define GOOD_CHECKSUM 07777 - -#define RDC 0 /* read tape and check */ -#define RCG 1 /* read tape group */ -#define RDE 2 /* read tape */ -#define MTB 3 /* move toward block */ -#define WRC 4 /* write tape and check */ -#define WCG 5 /* write tape group */ -#define WRI 6 /* write tape */ -#define CHK 7 /* check tape */ - -#define DBG 0001 -#define DBG_SEEK 0002 -#define DBG_READ 0004 -#define DBG_WRITE 0010 -#define DBG_POS 0020 - -static uint16 GROUP; -static int16 CURRENT_BLOCK; -static int16 WANTED_BLOCK; - -static t_stat tape_svc(UNIT *uptr); -static t_stat tape_reset(DEVICE *dptr); -static t_stat tape_boot(int32 u, DEVICE *dptr); -static t_stat tape_attach(UNIT *uptr, CONST char *cptr); -static t_stat tape_detach(UNIT *uptr); - -#define UNIT_FLAGS (UNIT_IDLE|UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE) -#define CAPACITY (MAX_BLOCKS * DATA_WORDS) - -static UNIT tape_unit[] = { - { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, - { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, - { UDATA(&tape_svc, UNIT_DIS, 0) }, - { UDATA(&tape_svc, UNIT_DIS, 0) }, - { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, - { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) } -}; - -static DEBTAB tape_deb[] = { - { "DBG", DBG }, - { "SEEK", DBG_SEEK }, - { "READ", DBG_READ }, - { "WRITE", DBG_WRITE }, - { "POSITION", DBG_POS }, - { NULL, 0 } -}; - -DEVICE tape_dev = { - "TAPE", tape_unit, NULL, NULL, - 6, 8, 12, 1, 8, 12, - NULL, NULL, &tape_reset, - &tape_boot, &tape_attach, &tape_detach, - NULL, DEV_DEBUG, 0, tape_deb, - NULL, NULL, NULL, NULL, NULL, NULL -}; - -void tape_op(void) -{ - uint16 u = (C & 050) >> 3; - UNIT *uptr = &tape_unit[u]; - - if ((uptr->flags & UNIT_ATT) == 0) - return; - - if (uptr->SPEED < 0) { - if ((C & 7) != MTB) { - sim_debug(DBG_SEEK, &tape_dev, "Reverse to forward\n"); - uptr->ACC = ACC_REVERSE; - } - } else if (uptr->POS >= MAX_POS) { - sim_debug(DBG_SEEK, &tape_dev, "End zone; reverse\n"); - uptr->ACC = ACC_REVERSE; - } else if (uptr->SPEED < MAX_SPEED || uptr->ACC < 0) { - sim_debug(DBG_SEEK, &tape_dev, "Speed up\n"); - uptr->ACC = ACC_START; - } - if (!sim_is_active(uptr)) - sim_activate(uptr, 20); - paused = 1; - A = 0; - WANTED_BLOCK = B & TMASK; - - switch (C & 7) { - case RDC: case RDE: case WRC: case WRI: case CHK: - S = 256 * (B >> 9); - GROUP = 0; - sim_debug(DBG, &tape_dev, "Single tranfer: S=%04o, BN=%03o\n", - S, WANTED_BLOCK); - break; - case RCG: case WCG: - S = 256 * (B & 7); - GROUP = B >> 9; - sim_debug(DBG, &tape_dev, "Group transfer: S=%04o, BN=%03o/%o\n", - S, WANTED_BLOCK, GROUP+1); - break; - case MTB: - sim_debug(DBG, &tape_dev, "Move towards block %03o\n", WANTED_BLOCK); - break; - } -} - -static t_stat tape_seek(FILE *fileref, t_addr block, t_addr offset) -{ - offset = DATA_WORDS * block + offset; - offset *= 2; - if (sim_fseek(fileref, offset, SEEK_SET) == -1) - return SCPE_IOERR; - return SCPE_OK; -} - -static uint16 read_word(FILE *fileref, t_addr block, t_addr offset) -{ - t_stat stat; - uint8 data[2]; - uint16 word; - - stat = tape_seek(fileref, block, offset); - if (stat != SCPE_OK) - ; - if (sim_fread(data, 1, 2, fileref) != 2) - ; - if (data[1] & 0xF0) - ; - word = data[1]; - word <<= 8; - word |= data[0]; - return word; -} - -static void write_word(FILE *fileref, t_addr block, t_addr offset, uint16 word) -{ - t_stat stat; - uint8 data[2]; - - stat = tape_seek(fileref, block, offset); - if (stat != SCPE_OK) - ; - data[0] = word & 0xFF; - data[1] = word >> 8; - if (sim_fwrite(data, 1, 2, fileref) != 2) - ; -} - -/* - IBZ BN G block CS C C G BN IBZ - 5 1 1 256 1 1 1 1 1 5 - --------------------- - 263 - -------------------------- - 268 - - - start - 100 ms - stop - 300 ms - reverse - 100 ms - BN to BN at 60 ips - 43 ms - block length = 43 ms * 60 inch/s = 2.58 inch - - per word - 160 µs - word length = 0.0096 inch - words per inch = 104 - words per second = 6250 - end zone to end zone - 23 s - tape length = 23 * 60 = 1380 inch = 115 feet - end zone length = 5 feet - - */ - -static void tape_done(UNIT *uptr) -{ - sim_debug(DBG, &tape_dev, "Done with block\n"); - - switch (C & 7) { - case RDC: case RCG: case RDE: case CHK: - A = GOOD_CHECKSUM; - break; - case WRI: - A = (A ^ 07777) + 1; - A &= WMASK; - break; - case MTB: - A = (WANTED_BLOCK + ~CURRENT_BLOCK); - A += A >> 12; - A &= WMASK; - break; - } - - switch (C & 7) { - case RDC: - if (A != GOOD_CHECKSUM) { - sim_debug(DBG, &tape_dev, "Check failed; read again\n"); - S &= ~0377; - } else { - sim_debug(DBG, &tape_dev, "Check passed\n"); - paused = 0; - } - break; - case WRC: - sim_debug(DBG, &tape_dev, "Block written, go back and check\n"); - // For now, done. - A = GOOD_CHECKSUM; - paused = 0; - break; - case RCG: case WCG: - if (GROUP == 0) { - sim_debug(DBG, &tape_dev, "Done with group\n"); - paused = 0; - } else { - sim_debug(DBG, &tape_dev, "Blocks left in group: %d\n", GROUP); - GROUP--; - } - WANTED_BLOCK = (WANTED_BLOCK + 1) & TMASK; - break; - case RDE: case WRI: - sim_debug(DBG, &tape_dev, "Transfer done\n"); - paused = 0; - break; - case MTB: - sim_debug(DBG, &tape_dev, "Move towards block done, result %04o\n", A); - paused = 0; - break; - case CHK: - sim_debug(DBG, &tape_dev, "Check done\n"); - paused = 0; - break; - } - - if (paused) - ; - else if ((C & IMASK) == 0) { - sim_debug(DBG_SEEK, &tape_dev, "Instruction done, stop tape\n"); - uptr->ACC = uptr->SPEED > 0 ? -ACC_STOP : ACC_STOP; - } else { - sim_debug(DBG_SEEK, &tape_dev, "Instruction done, keep moving\n"); - } -} - -static void tape_word(UNIT *uptr, uint16 block, uint16 offset) -{ - switch (C & 7) { - case RDC: case RCG: case RDE: case CHK: - B = read_word(uptr->fileref, block, offset); - sim_debug(DBG_READ, &tape_dev, - "Read block %03o offset %03o data %04o address %04o\n", - block, offset, B, S); - if ((C & 7) != CHK) - M[S] = B; - break; - case WRC: case WCG: case WRI: - B = M[S]; - sim_debug(DBG_WRITE, &tape_dev, - "Write block %03o offset %03o data %04o address %04o\n", - block, offset, B, S); - write_word(uptr->fileref, block, offset, B); - break; - } - S = (S+1) & AMASK; - A += B; - A &= WMASK; -} - -static t_stat tape_svc(UNIT *uptr) -{ - long pos, block, offset; - - uptr->SPEED += uptr->ACC; - if (uptr->SPEED >= MAX_SPEED) { - uptr->SPEED = MAX_SPEED; - uptr->ACC = 0; - } - else if (uptr->SPEED <= -MAX_SPEED) { - uptr->SPEED = -MAX_SPEED; - uptr->ACC = 0; - } else if (uptr->SPEED == 0 && (uptr->ACC == ACC_STOP || uptr->ACC == -ACC_STOP)) - uptr->ACC = 0; - uptr->POS += uptr->SPEED; - sim_debug(DBG_POS, &tape_dev, "Speed %d, position %d (block %03o)\n", - uptr->SPEED, uptr->POS, uptr->POS / MAX_SPEED / BLOCK_WORDS); - - if (uptr->POS < 0 && uptr->ACC <= 0) { - sim_debug(DBG_SEEK, &tape_dev, "End zone; stop tape\n"); - uptr->ACC = ACC_STOP; - } else if(uptr->POS >= MAX_POS && uptr->ACC >= 0) { - sim_debug(DBG_SEEK, &tape_dev, "End zone; stop tape\n"); - uptr->ACC = -ACC_STOP; - } - - if (uptr->SPEED != 0) - /* The tape takes 160 microseconds between words. This is - approximately 20 memory cycles, 8 microseconds each. */ - sim_activate(uptr, 20); - - pos = uptr->POS / MAX_SPEED; - if (pos < 0) - return SCPE_OK; - - block = pos / BLOCK_WORDS; - offset = pos % BLOCK_WORDS; - if (block >= MAX_BLOCKS) - return SCPE_OK; - - IBZ = offset < IBZ_WORDS; - if (IBZ) - sim_debug(DBG, &tape_dev, "Interblock zone\n"); - - if (uptr->SPEED > -MAX_SPEED && uptr->SPEED < MAX_SPEED) - return SCPE_OK; - - if (!paused) - return SCPE_OK; - - if (uptr->SPEED > 0) { - if (offset == 5) { - /* Forward block number. */ - CURRENT_BLOCK = (uint16)(block + uptr->OFFSET); - sim_debug(DBG_SEEK, &tape_dev, - "Found block number %03o; looking for %03o\n", - CURRENT_BLOCK, WANTED_BLOCK); - if (CURRENT_BLOCK > WANTED_BLOCK) { - sim_debug(DBG_SEEK, &tape_dev, "Reverse to find lower block numbers\n"); - uptr->ACC = -ACC_REVERSE; - } - if ((C & 7) == MTB) - tape_done(uptr); - /* Word 6 is a guard. */ - } else if (offset >= 7 && offset < 263) { - if (CURRENT_BLOCK == WANTED_BLOCK) - tape_word(uptr, (uint16)block, (uint16)(offset - 7)); - } - else if (offset == 263 && CURRENT_BLOCK == WANTED_BLOCK) - /* Checksum here. */ - tape_done(uptr); - } - /* Word 264-265 are "C". */ - /* Word 266 is a guard. */ - else if (offset == 267 && uptr->SPEED < 0) { - /* Reverse block number. */ - CURRENT_BLOCK = (uint16)(block + uptr->OFFSET); - sim_debug(DBG_SEEK, &tape_dev, - "Found reverse block number %03o; looking for %03o\n", - CURRENT_BLOCK, WANTED_BLOCK); - if (CURRENT_BLOCK <= WANTED_BLOCK) { - sim_debug(DBG_SEEK, &tape_dev, "Reverse to find higher block numbers\n"); - uptr->ACC = ACC_REVERSE; - uptr->POS -= MAX_SPEED * BLOCK_WORDS; - } - if ((C & 7) == MTB) - tape_done(uptr); - } - - return SCPE_OK; -} - -static t_stat tape_reset(DEVICE *dptr) -{ - return SCPE_OK; -} - -static t_stat tape_boot(int32 unit_num, DEVICE *dptr) -{ - uint16 block = 0300; - uint16 blocks = 8; - uint16 quarter = 0; - t_stat stat; - - if (unit_num >= 2 && unit_num <= 3) - return SCPE_ARG; - if (blocks == 0) - return SCPE_ARG; - - if (blocks == 1) - LSW = RDC; - else - LSW = RCG, quarter = blocks - 1; - LSW |= 0700 | (unit_num << 3); - RSW = (quarter << 9) | block; - stat = cpu_do(); - if (stat != SCPE_OK) - return stat; - P = 020; - return SCPE_OK; -} - -t_stat tape_metadata(FILE *fileref, uint16 *block_size, int16 *forward_offset, int16 *reverse_offset) -{ - t_offset size = sim_fsize(fileref); - if (size == MAX_BLOCKS * DATA_WORDS * 2) { - /* Plain image. */ - *block_size = DATA_WORDS; - *forward_offset = 0; - *reverse_offset = 0; - } else if ((size % (2 * DATA_WORDS)) == 6) { - /* Extended image with additional meta data. */ - uint16 metadata = (uint16)(size / (2 * DATA_WORDS)); - *block_size = read_word(fileref, metadata, 0); - *forward_offset = (int16)read_word(fileref, metadata, 1); - *reverse_offset = (int16)read_word(fileref, metadata, 2); - } else - return SCPE_FMT; - return SCPE_OK; -} - -static t_stat tape_attach(UNIT *uptr, CONST char *cptr) -{ - t_stat stat; - uint16 block_size; - int16 forward_offset, reverse_offset; - - if (uptr - tape_unit >= 2 && uptr - tape_unit <= 3) - return SCPE_ARG; - stat = attach_unit(uptr, cptr); - if (stat != SCPE_OK) - return stat; - stat = tape_metadata(uptr->fileref, &block_size, &forward_offset, &reverse_offset); - if (stat != SCPE_OK) - return stat; - sim_debug(DBG, &tape_dev, - "Tape image with block size %o, block offset %d/%d\r\n", - block_size, forward_offset, reverse_offset); - if (block_size != DATA_WORDS) - return SCPE_FMT; - if (forward_offset != reverse_offset) - return SCPE_FMT; - uptr->OFFSET = forward_offset; - - uptr->POS = -2 * START_POS; - uptr->SPEED = 0; - return SCPE_OK; -} - -static t_stat tape_detach(UNIT *uptr) -{ - if (uptr - tape_unit >= 2 && uptr - tape_unit <= 3) - return SCPE_ARG; - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_OK; - if (sim_is_active(uptr)) - sim_cancel(uptr); - return detach_unit(uptr); -} +#include "linc_defs.h" + +#define POS u3 +#define SPEED u4 +#define ACC u5 +#define OFFSET u6 + +#define P (*(uint16 *)cpu_reg[0].loc) +#define C (*(uint16 *)cpu_reg[1].loc) +#define A (*(uint16 *)cpu_reg[2].loc) +#define S (*(uint16 *)cpu_reg[6].loc) +#define B (*(uint16 *)cpu_reg[7].loc) +#define LSW (*(uint16 *)cpu_reg[8].loc) +#define RSW (*(uint16 *)cpu_reg[9].loc) +#define paused (*(int *)cpu_reg[11].loc) +#define IBZ (*(int *)cpu_reg[12].loc) + +#define ACC_START 3 +#define ACC_REVERSE 6 +#define ACC_STOP 1 +#define MAX_SPEED (ACC_START * 625) /* 0.1s / 160µs */ +#define IBZ_WORDS 5 +#define DATA_WORDS 256 +#define OTHER_WORDS 7 +#define BLOCK_WORDS (IBZ_WORDS + DATA_WORDS + OTHER_WORDS) +#define START_POS (ACC_START * (625 + (625 * 625))/2) +#define MAX_BLOCKS 512 +#define MAX_POS ((BLOCK_WORDS * MAX_BLOCKS + IBZ_WORDS) * MAX_SPEED) + +#define GOOD_CHECKSUM 07777 + +#define RDC 0 /* read tape and check */ +#define RCG 1 /* read tape group */ +#define RDE 2 /* read tape */ +#define MTB 3 /* move toward block */ +#define WRC 4 /* write tape and check */ +#define WCG 5 /* write tape group */ +#define WRI 6 /* write tape */ +#define CHK 7 /* check tape */ + +#define DBG 0001 +#define DBG_SEEK 0002 +#define DBG_READ 0004 +#define DBG_WRITE 0010 +#define DBG_POS 0020 + +static uint16 GROUP; +static int16 CURRENT_BLOCK; +static int16 WANTED_BLOCK; + +static t_stat tape_svc(UNIT *uptr); +static t_stat tape_reset(DEVICE *dptr); +static t_stat tape_boot(int32 u, DEVICE *dptr); +static t_stat tape_attach(UNIT *uptr, CONST char *cptr); +static t_stat tape_detach(UNIT *uptr); + +#define UNIT_FLAGS (UNIT_IDLE|UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE) +#define CAPACITY (MAX_BLOCKS * DATA_WORDS) + +static UNIT tape_unit[] = { + { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, + { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, + { UDATA(&tape_svc, UNIT_DIS, 0) }, + { UDATA(&tape_svc, UNIT_DIS, 0) }, + { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) }, + { UDATA(&tape_svc, UNIT_FLAGS, CAPACITY) } +}; + +static DEBTAB tape_deb[] = { + { "DBG", DBG }, + { "SEEK", DBG_SEEK }, + { "READ", DBG_READ }, + { "WRITE", DBG_WRITE }, + { "POSITION", DBG_POS }, + { NULL, 0 } +}; + +DEVICE tape_dev = { + "TAPE", tape_unit, NULL, NULL, + 6, 8, 12, 1, 8, 12, + NULL, NULL, &tape_reset, + &tape_boot, &tape_attach, &tape_detach, + NULL, DEV_DEBUG, 0, tape_deb, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +void tape_op(void) +{ + uint16 u = (C & 050) >> 3; + UNIT *uptr = &tape_unit[u]; + + if ((uptr->flags & UNIT_ATT) == 0) + return; + + if (uptr->SPEED < 0) { + if ((C & 7) != MTB) { + sim_debug(DBG_SEEK, &tape_dev, "Reverse to forward\n"); + uptr->ACC = ACC_REVERSE; + } + } else if (uptr->POS >= MAX_POS) { + sim_debug(DBG_SEEK, &tape_dev, "End zone; reverse\n"); + uptr->ACC = ACC_REVERSE; + } else if (uptr->SPEED < MAX_SPEED || uptr->ACC < 0) { + sim_debug(DBG_SEEK, &tape_dev, "Speed up\n"); + uptr->ACC = ACC_START; + } + if (!sim_is_active(uptr)) + sim_activate(uptr, 20); + paused = 1; + A = 0; + WANTED_BLOCK = B & TMASK; + + switch (C & 7) { + case RDC: case RDE: case WRC: case WRI: case CHK: + S = 256 * (B >> 9); + GROUP = 0; + sim_debug(DBG, &tape_dev, "Single tranfer: S=%04o, BN=%03o\n", + S, WANTED_BLOCK); + break; + case RCG: case WCG: + S = 256 * (B & 7); + GROUP = B >> 9; + sim_debug(DBG, &tape_dev, "Group transfer: S=%04o, BN=%03o/%o\n", + S, WANTED_BLOCK, GROUP+1); + break; + case MTB: + sim_debug(DBG, &tape_dev, "Move towards block %03o\n", WANTED_BLOCK); + break; + } +} + +static t_stat tape_seek(FILE *fileref, t_addr block, t_addr offset) +{ + offset = DATA_WORDS * block + offset; + offset *= 2; + if (sim_fseek(fileref, offset, SEEK_SET) == -1) + return SCPE_IOERR; + return SCPE_OK; +} + +static uint16 read_word(FILE *fileref, t_addr block, t_addr offset) +{ + t_stat stat; + uint8 data[2]; + uint16 word; + + stat = tape_seek(fileref, block, offset); + if (stat != SCPE_OK) + ; + if (sim_fread(data, 1, 2, fileref) != 2) + ; + if (data[1] & 0xF0) + ; + word = data[1]; + word <<= 8; + word |= data[0]; + return word; +} + +static void write_word(FILE *fileref, t_addr block, t_addr offset, uint16 word) +{ + t_stat stat; + uint8 data[2]; + + stat = tape_seek(fileref, block, offset); + if (stat != SCPE_OK) + ; + data[0] = word & 0xFF; + data[1] = word >> 8; + if (sim_fwrite(data, 1, 2, fileref) != 2) + ; +} + +/* + IBZ BN G block CS C C G BN IBZ + 5 1 1 256 1 1 1 1 1 5 + --------------------- + 263 + -------------------------- + 268 + + + start - 100 ms + stop - 300 ms + reverse - 100 ms + BN to BN at 60 ips - 43 ms + block length = 43 ms * 60 inch/s = 2.58 inch + + per word - 160 µs + word length = 0.0096 inch + words per inch = 104 + words per second = 6250 + end zone to end zone - 23 s + tape length = 23 * 60 = 1380 inch = 115 feet + end zone length = 5 feet + + */ + +static void tape_done(UNIT *uptr) +{ + sim_debug(DBG, &tape_dev, "Done with block\n"); + + switch (C & 7) { + case RDC: case RCG: case RDE: case CHK: + A = GOOD_CHECKSUM; + break; + case WRI: + A = (A ^ 07777) + 1; + A &= WMASK; + break; + case MTB: + A = (WANTED_BLOCK + ~CURRENT_BLOCK); + A += A >> 12; + A &= WMASK; + break; + } + + switch (C & 7) { + case RDC: + if (A != GOOD_CHECKSUM) { + sim_debug(DBG, &tape_dev, "Check failed; read again\n"); + S &= ~0377; + } else { + sim_debug(DBG, &tape_dev, "Check passed\n"); + paused = 0; + } + break; + case WRC: + sim_debug(DBG, &tape_dev, "Block written, go back and check\n"); + // For now, done. + A = GOOD_CHECKSUM; + paused = 0; + break; + case RCG: case WCG: + if (GROUP == 0) { + sim_debug(DBG, &tape_dev, "Done with group\n"); + paused = 0; + } else { + sim_debug(DBG, &tape_dev, "Blocks left in group: %d\n", GROUP); + GROUP--; + } + WANTED_BLOCK = (WANTED_BLOCK + 1) & TMASK; + break; + case RDE: case WRI: + sim_debug(DBG, &tape_dev, "Transfer done\n"); + paused = 0; + break; + case MTB: + sim_debug(DBG, &tape_dev, "Move towards block done, result %04o\n", A); + paused = 0; + break; + case CHK: + sim_debug(DBG, &tape_dev, "Check done\n"); + paused = 0; + break; + } + + if (paused) + ; + else if ((C & IMASK) == 0) { + sim_debug(DBG_SEEK, &tape_dev, "Instruction done, stop tape\n"); + uptr->ACC = uptr->SPEED > 0 ? -ACC_STOP : ACC_STOP; + } else { + sim_debug(DBG_SEEK, &tape_dev, "Instruction done, keep moving\n"); + } +} + +static void tape_word(UNIT *uptr, uint16 block, uint16 offset) +{ + switch (C & 7) { + case RDC: case RCG: case RDE: case CHK: + B = read_word(uptr->fileref, block, offset); + sim_debug(DBG_READ, &tape_dev, + "Read block %03o offset %03o data %04o address %04o\n", + block, offset, B, S); + if ((C & 7) != CHK) + M[S] = B; + break; + case WRC: case WCG: case WRI: + B = M[S]; + sim_debug(DBG_WRITE, &tape_dev, + "Write block %03o offset %03o data %04o address %04o\n", + block, offset, B, S); + write_word(uptr->fileref, block, offset, B); + break; + } + S = (S+1) & AMASK; + A += B; + A &= WMASK; +} + +static t_stat tape_svc(UNIT *uptr) +{ + long pos, block, offset; + + uptr->SPEED += uptr->ACC; + if (uptr->SPEED >= MAX_SPEED) { + uptr->SPEED = MAX_SPEED; + uptr->ACC = 0; + } + else if (uptr->SPEED <= -MAX_SPEED) { + uptr->SPEED = -MAX_SPEED; + uptr->ACC = 0; + } else if (uptr->SPEED == 0 && (uptr->ACC == ACC_STOP || uptr->ACC == -ACC_STOP)) + uptr->ACC = 0; + uptr->POS += uptr->SPEED; + sim_debug(DBG_POS, &tape_dev, "Speed %d, position %d (block %03o)\n", + uptr->SPEED, uptr->POS, uptr->POS / MAX_SPEED / BLOCK_WORDS); + + if (uptr->POS < 0 && uptr->ACC <= 0) { + sim_debug(DBG_SEEK, &tape_dev, "End zone; stop tape\n"); + uptr->ACC = ACC_STOP; + } else if(uptr->POS >= MAX_POS && uptr->ACC >= 0) { + sim_debug(DBG_SEEK, &tape_dev, "End zone; stop tape\n"); + uptr->ACC = -ACC_STOP; + } + + if (uptr->SPEED != 0) + /* The tape takes 160 microseconds between words. This is + approximately 20 memory cycles, 8 microseconds each. */ + sim_activate(uptr, 20); + + pos = uptr->POS / MAX_SPEED; + if (pos < 0) + return SCPE_OK; + + block = pos / BLOCK_WORDS; + offset = pos % BLOCK_WORDS; + if (block >= MAX_BLOCKS) + return SCPE_OK; + + IBZ = offset < IBZ_WORDS; + if (IBZ) + sim_debug(DBG, &tape_dev, "Interblock zone\n"); + + if (uptr->SPEED > -MAX_SPEED && uptr->SPEED < MAX_SPEED) + return SCPE_OK; + + if (!paused) + return SCPE_OK; + + if (uptr->SPEED > 0) { + if (offset == 5) { + /* Forward block number. */ + CURRENT_BLOCK = (uint16)(block + uptr->OFFSET); + sim_debug(DBG_SEEK, &tape_dev, + "Found block number %03o; looking for %03o\n", + CURRENT_BLOCK, WANTED_BLOCK); + if (CURRENT_BLOCK > WANTED_BLOCK) { + sim_debug(DBG_SEEK, &tape_dev, "Reverse to find lower block numbers\n"); + uptr->ACC = -ACC_REVERSE; + } + if ((C & 7) == MTB) + tape_done(uptr); + /* Word 6 is a guard. */ + } else if (offset >= 7 && offset < 263) { + if (CURRENT_BLOCK == WANTED_BLOCK) + tape_word(uptr, (uint16)block, (uint16)(offset - 7)); + } + else if (offset == 263 && CURRENT_BLOCK == WANTED_BLOCK) + /* Checksum here. */ + tape_done(uptr); + } + /* Word 264-265 are "C". */ + /* Word 266 is a guard. */ + else if (offset == 267 && uptr->SPEED < 0) { + /* Reverse block number. */ + CURRENT_BLOCK = (uint16)(block + uptr->OFFSET); + sim_debug(DBG_SEEK, &tape_dev, + "Found reverse block number %03o; looking for %03o\n", + CURRENT_BLOCK, WANTED_BLOCK); + if (CURRENT_BLOCK <= WANTED_BLOCK) { + sim_debug(DBG_SEEK, &tape_dev, "Reverse to find higher block numbers\n"); + uptr->ACC = ACC_REVERSE; + uptr->POS -= MAX_SPEED * BLOCK_WORDS; + } + if ((C & 7) == MTB) + tape_done(uptr); + } + + return SCPE_OK; +} + +static t_stat tape_reset(DEVICE *dptr) +{ + return SCPE_OK; +} + +static t_stat tape_boot(int32 unit_num, DEVICE *dptr) +{ + uint16 block = 0300; + uint16 blocks = 8; + uint16 quarter = 0; + t_stat stat; + + if (unit_num >= 2 && unit_num <= 3) + return SCPE_ARG; + if (blocks == 0) + return SCPE_ARG; + + if (blocks == 1) + LSW = RDC; + else + LSW = RCG, quarter = blocks - 1; + LSW |= 0700 | (unit_num << 3); + RSW = (quarter << 9) | block; + stat = cpu_do(); + if (stat != SCPE_OK) + return stat; + P = 020; + return SCPE_OK; +} + +t_stat tape_metadata(FILE *fileref, uint16 *block_size, int16 *forward_offset, int16 *reverse_offset) +{ + t_offset size = sim_fsize(fileref); + if (size == MAX_BLOCKS * DATA_WORDS * 2) { + /* Plain image. */ + *block_size = DATA_WORDS; + *forward_offset = 0; + *reverse_offset = 0; + } else if ((size % (2 * DATA_WORDS)) == 6) { + /* Extended image with additional meta data. */ + uint16 metadata = (uint16)(size / (2 * DATA_WORDS)); + *block_size = read_word(fileref, metadata, 0); + *forward_offset = (int16)read_word(fileref, metadata, 1); + *reverse_offset = (int16)read_word(fileref, metadata, 2); + } else + return SCPE_FMT; + return SCPE_OK; +} + +static t_stat tape_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat stat; + uint16 block_size; + int16 forward_offset, reverse_offset; + + if (uptr - tape_unit >= 2 && uptr - tape_unit <= 3) + return SCPE_ARG; + stat = attach_unit(uptr, cptr); + if (stat != SCPE_OK) + return stat; + stat = tape_metadata(uptr->fileref, &block_size, &forward_offset, &reverse_offset); + if (stat != SCPE_OK) + return stat; + sim_debug(DBG, &tape_dev, + "Tape image with block size %o, block offset %d/%d\r\n", + block_size, forward_offset, reverse_offset); + if (block_size != DATA_WORDS) + return SCPE_FMT; + if (forward_offset != reverse_offset) + return SCPE_FMT; + uptr->OFFSET = forward_offset; + + uptr->POS = -2 * START_POS; + uptr->SPEED = 0; + return SCPE_OK; +} + +static t_stat tape_detach(UNIT *uptr) +{ + if (uptr - tape_unit >= 2 && uptr - tape_unit <= 3) + return SCPE_ARG; + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_OK; + if (sim_is_active(uptr)) + sim_cancel(uptr); + return detach_unit(uptr); +} diff --git a/linc/linc_tty.c b/linc/linc_tty.c index 89044e8c..6207b6d7 100644 --- a/linc/linc_tty.c +++ b/linc/linc_tty.c @@ -1,124 +1,124 @@ -#include "linc_defs.h" - - -/* Data bits, 110 baud rate. */ -#define BIT_TIME 1120 -/* Sample rate to find the start bit edge. */ -#define START_TIME (BIT_TIME / 5) -/* After finding the edge, wait until the middle of the first data bit. */ -#define FIRST_TIME (BIT_TIME + (BIT_TIME - START_TIME) / 2) - -#define R (*(uint16 *)cpu_reg[5].loc) - -/* Debug */ -#define DBG 0001 -#define DBG_BIT 0002 - -#define DATA u3 /* Character being assembled. */ -#define STATE u4 /* 0 for start bit, 1 for stop bit, otherwise data. */ -#define PREVIOUS u5 /* Previous level seen. */ - -/* When a start bit is found, the state is set to 10 and then - decremented for each bit that is processed. */ -#define STATE_START 0 -#define STATE_STOP 1 -/* STATE_DATA 2-9 */ -#define STATE_FIRST 10 - -/* Function declaration. */ -static t_stat tty_svc(UNIT *uptr); -static t_stat tty_attach(UNIT *uptr, CONST char *cptr); -static t_stat tty_detach(UNIT *uptr); - -static UNIT tty_unit = { - UDATA(&tty_svc, UNIT_IDLE | UNIT_ATTABLE, 0) -}; - -static DEBTAB tty_deb[] = { - { "DBG", DBG }, - { "BIT", DBG_BIT }, - { NULL, 0 } -}; - -DEVICE tty_dev = { - "TTY", &tty_unit, NULL, NULL, - 1, 8, 12, 1, 8, 12, - NULL, NULL, NULL, - NULL, &tty_attach, &tty_detach, - NULL, DEV_DISABLE | DEV_DEBUG, 0, tty_deb, - NULL, NULL, NULL, NULL, NULL, NULL -}; - -static void tty_output(UNIT *uptr) -{ - uint8 ch = uptr->DATA; - sim_debug(DBG, &tty_dev, "Character %03o '%c'\n", ch, ch & 0177); - fputc(ch & 0177, uptr->fileref); - fflush(uptr->fileref); -} - -static t_stat tty_svc(UNIT *uptr) -{ - switch (uptr->STATE) { - case STATE_START: - if (uptr->PREVIOUS == 0 || (R & 1) == 1) { - /* Keep looking for start bit. */ - uptr->PREVIOUS = R & 1; - sim_activate(uptr, START_TIME); - return SCPE_OK; - } - - sim_debug(DBG_BIT, &tty_dev, "Start bit edge found.\n"); - uptr->STATE = STATE_FIRST; - uptr->DATA = 0; - /* Wait until the middle of the first data bit. Since the edge - was just seen, this is a little longer than the time between - data bits. */ - sim_activate(uptr, FIRST_TIME); - break; - - default: - sim_debug(DBG_BIT, &tty_dev, "Data bit %d is %d\n", - STATE_FIRST - 1 - uptr->STATE, R & 1); - uptr->DATA >>= 1; - uptr->DATA |= (R & 1) << 7; - sim_activate(uptr, BIT_TIME); - break; - - case STATE_STOP: - sim_debug(DBG_BIT, &tty_dev, "Stop bit is %d\n", R & 1); - if (R & 1) - tty_output(uptr); - else - sim_debug(DBG, &tty_dev, "Framing error.\n"); - uptr->PREVIOUS = R & 1; - /* Look for next start bit. */ - sim_activate(uptr, START_TIME); - break; - } - - /* Decrease the state counter, first through the data bits, then - the stop bit, and finally the start bit. */ - uptr->STATE--; - return SCPE_OK; -} - -static t_stat tty_attach(UNIT *uptr, CONST char *cptr) -{ - t_stat stat = attach_unit(uptr, cptr); - if (stat != SCPE_OK) - return stat; - uptr->STATE = 0; - uptr->PREVIOUS = 0; - sim_activate(uptr, 1); - return SCPE_OK; -} - -static t_stat tty_detach(UNIT *uptr) -{ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_OK; - if (sim_is_active(uptr)) - sim_cancel(uptr); - return detach_unit(uptr); -} +#include "linc_defs.h" + + +/* Data bits, 110 baud rate. */ +#define BIT_TIME 1120 +/* Sample rate to find the start bit edge. */ +#define START_TIME (BIT_TIME / 5) +/* After finding the edge, wait until the middle of the first data bit. */ +#define FIRST_TIME (BIT_TIME + (BIT_TIME - START_TIME) / 2) + +#define R (*(uint16 *)cpu_reg[5].loc) + +/* Debug */ +#define DBG 0001 +#define DBG_BIT 0002 + +#define DATA u3 /* Character being assembled. */ +#define STATE u4 /* 0 for start bit, 1 for stop bit, otherwise data. */ +#define PREVIOUS u5 /* Previous level seen. */ + +/* When a start bit is found, the state is set to 10 and then + decremented for each bit that is processed. */ +#define STATE_START 0 +#define STATE_STOP 1 +/* STATE_DATA 2-9 */ +#define STATE_FIRST 10 + +/* Function declaration. */ +static t_stat tty_svc(UNIT *uptr); +static t_stat tty_attach(UNIT *uptr, CONST char *cptr); +static t_stat tty_detach(UNIT *uptr); + +static UNIT tty_unit = { + UDATA(&tty_svc, UNIT_IDLE | UNIT_ATTABLE, 0) +}; + +static DEBTAB tty_deb[] = { + { "DBG", DBG }, + { "BIT", DBG_BIT }, + { NULL, 0 } +}; + +DEVICE tty_dev = { + "TTY", &tty_unit, NULL, NULL, + 1, 8, 12, 1, 8, 12, + NULL, NULL, NULL, + NULL, &tty_attach, &tty_detach, + NULL, DEV_DISABLE | DEV_DEBUG, 0, tty_deb, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +static void tty_output(UNIT *uptr) +{ + uint8 ch = uptr->DATA; + sim_debug(DBG, &tty_dev, "Character %03o '%c'\n", ch, ch & 0177); + fputc(ch & 0177, uptr->fileref); + fflush(uptr->fileref); +} + +static t_stat tty_svc(UNIT *uptr) +{ + switch (uptr->STATE) { + case STATE_START: + if (uptr->PREVIOUS == 0 || (R & 1) == 1) { + /* Keep looking for start bit. */ + uptr->PREVIOUS = R & 1; + sim_activate(uptr, START_TIME); + return SCPE_OK; + } + + sim_debug(DBG_BIT, &tty_dev, "Start bit edge found.\n"); + uptr->STATE = STATE_FIRST; + uptr->DATA = 0; + /* Wait until the middle of the first data bit. Since the edge + was just seen, this is a little longer than the time between + data bits. */ + sim_activate(uptr, FIRST_TIME); + break; + + default: + sim_debug(DBG_BIT, &tty_dev, "Data bit %d is %d\n", + STATE_FIRST - 1 - uptr->STATE, R & 1); + uptr->DATA >>= 1; + uptr->DATA |= (R & 1) << 7; + sim_activate(uptr, BIT_TIME); + break; + + case STATE_STOP: + sim_debug(DBG_BIT, &tty_dev, "Stop bit is %d\n", R & 1); + if (R & 1) + tty_output(uptr); + else + sim_debug(DBG, &tty_dev, "Framing error.\n"); + uptr->PREVIOUS = R & 1; + /* Look for next start bit. */ + sim_activate(uptr, START_TIME); + break; + } + + /* Decrease the state counter, first through the data bits, then + the stop bit, and finally the start bit. */ + uptr->STATE--; + return SCPE_OK; +} + +static t_stat tty_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat stat = attach_unit(uptr, cptr); + if (stat != SCPE_OK) + return stat; + uptr->STATE = 0; + uptr->PREVIOUS = 0; + sim_activate(uptr, 1); + return SCPE_OK; +} + +static t_stat tty_detach(UNIT *uptr) +{ + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_OK; + if (sim_is_active(uptr)) + sim_cancel(uptr); + return detach_unit(uptr); +}