mirror of
https://github.com/aap/pdp6.git
synced 2026-01-13 15:27:46 +00:00
183 lines
3.2 KiB
C
183 lines
3.2 KiB
C
#include "common.h"
|
|
#include "pdp6.h"
|
|
|
|
#define IOB pdp->iob
|
|
|
|
static void calc_dc_req(PDP6 *pdp, Dc136 *dc);
|
|
|
|
static void
|
|
dbda_swap(Dc136 *dc)
|
|
{
|
|
dc->dbda_move = 0;
|
|
dc->darq = 0;
|
|
dc->dbrq = 1;
|
|
if(dc->inout) // out
|
|
dc->da = dc->db;
|
|
else {
|
|
dc->db = dc->da;
|
|
dc->da = 0;
|
|
}
|
|
//printf("DB req %012llo\n", dc->db);
|
|
}
|
|
|
|
/*
|
|
* bits per char ch mode shifts per char chars per word
|
|
* 6 0 0 0 6
|
|
* 12 1 0 2 3
|
|
* 18 1 1 3 2
|
|
* 36 0 1 0 1
|
|
*/
|
|
#define NSHIFT ((0xE0 >> (dc->ch_mode*2)) & 3)
|
|
#define NCHARS ((02316 >> (dc->ch_mode*3)) & 7)
|
|
#define DC_SCT_DONE (dc->sct == NSHIFT)
|
|
#define DC_CCT_DONE (dc->cct == NCHARS-1)
|
|
|
|
static void
|
|
dashcp0(Dc136 *dc, Word inp)
|
|
{
|
|
cp0:
|
|
// DASH CP0
|
|
if(dc->darq)
|
|
dc->data_clbd = 1;
|
|
|
|
// 1μs dly
|
|
|
|
// DASH CP1
|
|
if(DC_CCT_DONE) {
|
|
dc->cct = 0;
|
|
if(dc->dbda_move && !dc->darq)
|
|
dbda_swap(dc);
|
|
else
|
|
dc->darq = 1;
|
|
} else if(DC_SCT_DONE) {
|
|
// CCT CONT
|
|
dc->sct = 0;
|
|
dc->cct = (dc->cct+1) & 7;
|
|
} else {
|
|
// SCT CONT
|
|
dc->sct = (dc->sct+1) & 3;
|
|
|
|
// DASH LT
|
|
dc->da = dc->da<<6 | inp;
|
|
goto cp0;
|
|
}
|
|
}
|
|
|
|
int
|
|
dctkgv(Dc136 *dc, int dev, int ch, int rt)
|
|
{
|
|
int ret;
|
|
if(dc->device != dev)
|
|
return 0;
|
|
|
|
switch(dev) {
|
|
case 1: case 2:
|
|
if(rt) {
|
|
ret = dc->da & 077;
|
|
ret = (ret<<3 | ret>>3) & 077;
|
|
ch = (ch<<3 | ch>>3) & 077;
|
|
dc->da = dc->da>>6 | (Word)ch<<30;
|
|
} else {
|
|
case 3: case 4:
|
|
ret = (dc->da>>30) & 077;
|
|
ch &= 077;
|
|
dc->da = dc->da<<6 | ch;
|
|
}
|
|
break;
|
|
default: // shouldn't happen
|
|
return 0;
|
|
}
|
|
dc->da &= FW;
|
|
dashcp0(dc, ch);
|
|
calc_dc_req(dc->pdp, dc);
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
handle_dc(PDP6 *pdp, IOdev *dev, int cmd)
|
|
{
|
|
Dc136 *dc = (Dc136*)dev->dev;
|
|
|
|
bool s0 = dc->darq && dc->dbda_move;
|
|
switch(cmd) {
|
|
case IOB_RESET:
|
|
dc->db = 0;
|
|
dc->da = 0; // hack so DB isn't overwritten again
|
|
case IOB_CONO_CLR:
|
|
dc->sct = 0;
|
|
dc->cct = 0;
|
|
dc->data_clbd = 0;
|
|
dc->dbda_move = 0;
|
|
dc->darq = 0;
|
|
dc->dbrq = 0;
|
|
dc->inout = 0;
|
|
dc->ch_mode = 0;
|
|
dc->device = 0;
|
|
dc->pia = 0;
|
|
|
|
dc->db = dc->da;
|
|
dc->da = 0;
|
|
break;
|
|
|
|
case IOB_CONO_SET:
|
|
if(IOB & F23) dc->data_clbd = 1;
|
|
if(IOB & F24) dc->dbda_move = 1;
|
|
if(IOB & F25) dc->darq = 1;
|
|
if(IOB & F26) dc->dbrq = 1;
|
|
if(IOB & F27) dc->inout = 1;
|
|
dc->ch_mode |= (IOB>>6)&3;
|
|
dc->device |= (IOB>>3)&7;
|
|
dc->pia |= IOB&7;
|
|
break;
|
|
|
|
case IOB_DATAO_CLR:
|
|
dc->db = 0;
|
|
dc->dbrq = 0;
|
|
break;
|
|
case IOB_DATAO_SET:
|
|
dc->db |= IOB;
|
|
dc->dbda_move = 1;
|
|
break;
|
|
|
|
case IOB_DATAI:
|
|
IOB |= dc->db;
|
|
dc->dbrq = 0;
|
|
dc->dbda_move = 1;
|
|
break;
|
|
|
|
case IOB_STATUS:
|
|
IOB |= dc->cct<<13;
|
|
if(dc->data_clbd) IOB |= F23;
|
|
if(dc->dbda_move) IOB |= F24;
|
|
if(dc->darq) IOB |= F25;
|
|
if(dc->dbrq) IOB |= F26;
|
|
if(dc->inout) IOB |= F27;
|
|
IOB |= dc->ch_mode<<6;
|
|
IOB |= dc->device<<3;
|
|
IOB |= dc->pia;
|
|
break;
|
|
}
|
|
bool s1 = dc->darq && dc->dbda_move;
|
|
if(s1 && !s0)
|
|
dbda_swap(dc);
|
|
calc_dc_req(pdp, dc);
|
|
}
|
|
|
|
static Dc136 dc;
|
|
static IOdev dc_dev = { 0, 0200, &dc, handle_dc, nil };
|
|
|
|
static void
|
|
calc_dc_req(PDP6 *pdp, Dc136 *dc)
|
|
{
|
|
setreq(pdp, &dc_dev, dc->pia && dc->dbrq ? 0200>>dc->pia : 0);
|
|
}
|
|
|
|
Dc136*
|
|
attach_dc(PDP6 *pdp)
|
|
{
|
|
dc.pdp = pdp;
|
|
installdev(pdp, &dc_dev);
|
|
|
|
return &dc;
|
|
}
|