mirror of
https://github.com/aap/pdp6.git
synced 2026-01-20 01:54:24 +00:00
251 lines
4.5 KiB
C
251 lines
4.5 KiB
C
#include "pdp6.h"
|
|
|
|
char *dc_ident = DC_IDENT;
|
|
|
|
/* table from DC1:
|
|
* 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)) & 03)
|
|
#define NCHARS ((02316 >> (dc->ch_mode*3)) & 07)
|
|
#define DC_SCT_DONE (dc->sct == NSHIFT)
|
|
#define DC_CCT_DONE (dc->cct == NCHARS-1)
|
|
//#define DC_CCT_CONT (DC_SCT_DONE && !(DC_CCT_DONE))
|
|
//#define DC_SCT_CONT (!(DC_SCT_DONE) && !(DC_CCT_DONE))
|
|
|
|
#define DB_JM_DA (dc->db = dc->da), dc->da = 0
|
|
#define DA_JM_DB (dc->da = dc->db)
|
|
#define DB_CLR dc->db = dc->db_rq = 0
|
|
|
|
static void
|
|
recalc_dc_req(Dc136 *dc)
|
|
{
|
|
setreq(dc->bus, DC, dc->db_rq ? dc->pia : 0);
|
|
}
|
|
|
|
static void
|
|
db_da_swap(Dc136 *dc)
|
|
{
|
|
dc->da_rq = 0;
|
|
dc->dbda_move = 0;
|
|
dc->db_rq = 1;
|
|
|
|
if(dc->inout)
|
|
DA_JM_DB; // out
|
|
else
|
|
DB_JM_DA; // in
|
|
}
|
|
|
|
/* TODO: maybe make these two a bit nicer?? */
|
|
static void
|
|
set_da_rq(Dc136 *dc)
|
|
{
|
|
int prev;
|
|
|
|
prev = dc->da_rq && dc->dbda_move;
|
|
dc->da_rq = 1;
|
|
if(!prev && dc->da_rq && dc->dbda_move)
|
|
db_da_swap(dc);
|
|
}
|
|
static void
|
|
set_dbda_move(Dc136 *dc)
|
|
{
|
|
int prev;
|
|
|
|
prev = dc->da_rq && dc->dbda_move;
|
|
dc->dbda_move = 1;
|
|
if(!prev && dc->da_rq && dc->dbda_move)
|
|
db_da_swap(dc);
|
|
}
|
|
|
|
static void
|
|
dash_cp0(Dc136 *dc)
|
|
{
|
|
cp0:
|
|
// DASH CP0
|
|
if(dc->da_rq)
|
|
dc->data_clbd = 1;
|
|
|
|
// 1ms delay
|
|
|
|
// DASH CP1
|
|
if(DC_CCT_DONE){
|
|
//printf("Full DA: %012lo\n", dc->da);
|
|
dc->cct = 0;
|
|
set_da_rq(dc);
|
|
}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) & FW;
|
|
goto cp0;
|
|
}
|
|
}
|
|
|
|
/* Give TO DC, this is the TK signal in the DC.
|
|
* NB: for dev 5/6 give only the lower N bits. */
|
|
void
|
|
dcgv(Dc136 *dc, int n, word c, int rev)
|
|
{
|
|
//printf("DC Taking %06lo from dev %d\n", c, n);
|
|
|
|
if(n != dc->device)
|
|
return;
|
|
switch(dc->device){
|
|
case 1: case 2:
|
|
if(rev)
|
|
dc->da = (dc->da >> 6 | (c&077)<<30) & FW;
|
|
else
|
|
dc->da = (dc->da << 6 | c&077) & FW;
|
|
break;
|
|
case 3: case 4:
|
|
dc->da = (dc->da << 6 | c&077) & FW;
|
|
break;
|
|
case 5: case 6:
|
|
dc->da |= c & FW;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
dash_cp0(dc);
|
|
recalc_dc_req(dc);
|
|
}
|
|
|
|
/* Take FROM DC, this is the GV signal in the DC.
|
|
* NB: for dev 5/6 read only the upper N bits. */
|
|
word
|
|
dctk(Dc136 *dc, int n, int rev)
|
|
{
|
|
word c;
|
|
|
|
if(n != dc->device)
|
|
return 0;
|
|
switch(dc->device){
|
|
case 1: case 2:
|
|
if(rev){
|
|
c = dc->da & 077;
|
|
dc->da = (dc->da >> 6) & FW;
|
|
}else{
|
|
c = (dc->da >> 30) & 077;
|
|
dc->da = (dc->da << 6) & FW;
|
|
}
|
|
break;
|
|
case 3: case 4:
|
|
c = (dc->da >> 30) & 077;
|
|
dc->da = (dc->da << 6) & FW;
|
|
break;
|
|
case 5: case 6:
|
|
c = dc->da & FW;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
dash_cp0(dc);
|
|
recalc_dc_req(dc);
|
|
//printf("DC Giving %06lo to dev %d\n", c, n);
|
|
return c;
|
|
}
|
|
|
|
static void
|
|
ic_clr(Dc136 *dc)
|
|
{
|
|
DB_JM_DA;
|
|
|
|
dc->cct = 0;
|
|
dc->sct = 0;
|
|
dc->data_clbd = 0;
|
|
dc->dbda_move = 0;
|
|
dc->da_rq = 0;
|
|
dc->db_rq = 0;
|
|
dc->inout = 0;
|
|
dc->ch_mode = 0;
|
|
dc->device = 0;
|
|
dc->pia = 0;
|
|
}
|
|
|
|
static void
|
|
wake_dc(void *dev)
|
|
{
|
|
Dc136 *dc;
|
|
IOBus *bus;
|
|
|
|
dc = dev;
|
|
bus = dc->bus;
|
|
|
|
if(IOB_RESET){
|
|
ic_clr(dc);
|
|
DB_CLR;
|
|
}
|
|
|
|
if(bus->devcode == DC){
|
|
if(IOB_STATUS){
|
|
bus->c12 |= (dc->cct&7) << 13;
|
|
if(dc->data_clbd) bus->c12 |= F23;
|
|
if(dc->dbda_move) bus->c12 |= F24;
|
|
if(dc->da_rq) bus->c12 |= F25;
|
|
if(dc->db_rq) bus->c12 |= F26;
|
|
if(dc->inout) bus->c12 |= F27;
|
|
bus->c12 |= (dc->ch_mode & 3) << 6;
|
|
bus->c12 |= (dc->device & 7) << 3;
|
|
bus->c12 |= dc->pia & 7;
|
|
}
|
|
if(IOB_DATAI){
|
|
bus->c12 |= dc->db;
|
|
dc->db_rq = 0;
|
|
set_dbda_move(dc);
|
|
}
|
|
if(IOB_CONO_CLEAR)
|
|
ic_clr(dc);
|
|
if(IOB_CONO_SET){
|
|
if(bus->c12 & F23) dc->data_clbd = 1;
|
|
if(bus->c12 & F24) set_dbda_move(dc);
|
|
if(bus->c12 & F25) set_da_rq(dc);
|
|
if(bus->c12 & F26) dc->db_rq = 1;
|
|
if(bus->c12 & F27) dc->inout = 1;
|
|
dc->ch_mode |= bus->c12>>6 & 03;
|
|
dc->device |= bus->c12>>3 & 07;
|
|
dc->pia |= bus->c12 & 07;
|
|
}
|
|
if(IOB_DATAO_CLEAR)
|
|
DB_CLR;
|
|
if(IOB_DATAO_SET){
|
|
dc->db |= bus->c12;
|
|
set_dbda_move(dc);
|
|
}
|
|
|
|
recalc_dc_req(dc);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dcioconnect(Device *dev, IOBus *bus)
|
|
{
|
|
Dc136 *dc;
|
|
dc = (Dc136*)dev;
|
|
dc->bus = bus;
|
|
bus->dev[DC] = (Busdev){ dc, wake_dc, 0 };
|
|
}
|
|
|
|
Device*
|
|
makedc(int argc, char *argv[])
|
|
{
|
|
Dc136 *dc;
|
|
|
|
dc = malloc(sizeof(Dc136));
|
|
memset(dc, 0, sizeof(Dc136));
|
|
|
|
dc->dev.type = dc_ident;
|
|
dc->dev.name = "";
|
|
dc->dev.ioconnect = dcioconnect;
|
|
|
|
return &dc->dev;
|
|
}
|