https://github.com/virtualagc/virtualagc
Tip revision: a4a63bc20b80eae78970dbffa2ff02cebc6b61d7 authored by Mike Stewart on 24 December 2020, 18:51:12 UTC
Manche45R2: incorporated the R-2 potential model, which makes all checksums correct.
Manche45R2: incorporated the R-2 potential model, which makes all checksums correct.
Tip revision: a4a63bc
CTR.cpp
/****************************************************************************
* CTR - INVOLUNTARY PRIORITY COUNTER subsystem
*
* AUTHOR: John Pultorak
* DATE: 10/25/02
* FILE: CTR.cpp
*
* NOTES: see header file.
*
*****************************************************************************
*/
#include "CTR.h"
#include "INT.h"
#include "BUS.h"
#include "SEQ.h"
regUpCELL CTR::register_UpCELL; // latches the selected priority counter cell (0-7 (decimal))
regDnCELL CTR::register_DnCELL; // latches the selected priority counter cell (0-7 (decimal))
unsigned CTR::pcUp[8];
unsigned CTR::pcDn[8];
// PRIORITY COUNTERS
// ****************************************************
// The interrupt priorities are stored in RPCELL as 1-5, but
// the priority counter priorities are stored as 0-7; this
// inconsistency should be fixed, probably. Also, the method
// of address determination for the priority counters needs work
void
CTR::resetAllpc()
{
for (int i = 0; i < 8; i++)
{
pcUp[i] = 0;
pcDn[i] = 0;
}
}
// priority encoder; outputs 0-7; 0=highest priority (OVCTR), 1=TIME2, 2=TIME1, etc
static bool newPriority = true; // a simulator performance optimization; not in the hardware AGC
unsigned
getPriority()
{
// simulator optimization; don't recompute priority if the priority inputs haven't changed
static unsigned priority = 7; // default (lowest priority)
if (!newPriority)
return priority;
priority = 7; // default (lowest priority)
for (int i = 0; i < 8; i++)
{
if (CTR::register_UpCELL.readField(i + 1, i + 1)
| CTR::register_DnCELL.readField(i + 1, i + 1))
{
priority = i;
break;
}
}
newPriority = false;
return priority;
}
unsigned
CTR::getSubseq()
{
unsigned pc = getPriority();
unsigned upCell = CTR::register_UpCELL.readField(pc + 1, pc + 1);
unsigned dnCell = CTR::register_DnCELL.readField(pc + 1, pc + 1);
if (upCell == 1 && dnCell == 0)
return PINCSEL;
else if (upCell == 0 && dnCell == 1)
return MINCSEL;
else
return NOPSEL;
}
void
CTR::execWP_GENRST()
{
register_UpCELL.write(0);
register_DnCELL.write(0);
resetAllpc();
}
void
CTR::execWP_WPCTR()
{
// transfer cell data into up and down synch registers
for (int i = 0; i < 8; i++)
{
register_UpCELL.writeField(i + 1, i + 1, pcUp[i]);
register_DnCELL.writeField(i + 1, i + 1, pcDn[i]);
}
newPriority = true; // a simulator performance optimization; not in hardware AGC
}
// Selected counter address is requested at TP1.
// Counter address is latched at TP12
void
CTR::execRP_RSCT()
{
BUS::glbl_READ_BUS = 034 + getPriority();
}
void
CTR::execWP_WOVR()
{
unsigned pc = getPriority();
if (register_UpCELL.readField(pc + 1, pc + 1))
{
pcUp[pc] = 0;
}
if (register_DnCELL.readField(pc + 1, pc + 1))
{
pcDn[pc] = 0;
}
// generate various actions in response to counter overflows:
switch (BUS::testOverflow(BUS::glbl_WRITE_BUS))
{
case POS_OVF: // positive overflow
switch (getPriority())
// get the counter
{
case TIME1:
CTR::pcUp[TIME2] = 1;
break; // overflow from TIME1 increments TIME2
case TIME3:
INT::rupt[T3RUPT] = 1;
break; // overflow from TIME3 triggers T3RUPT
case TIME4:
INT::rupt[DSRUPT] = 1;
break; // overflow from TIME4 triggers DSRUPT
}
break;
case NEG_OVF:
break; // no actions for negative counter overflow
}
}
void
CTR::execWP_WOVC()
{
switch (BUS::testOverflow(BUS::glbl_WRITE_BUS))
{
case POS_OVF:
CTR::pcUp[OVCTR] = 1;
break; // incr OVCTR (034)
case NEG_OVF:
CTR::pcDn[OVCTR] = 1;
break; // decr OVCTR (034)
}
}
// register_PCELL: Overflow from the selected counter appears
// on the bus when WOVR or WOVC is asserted;
// it could be used to trigger an interrupt
// or routed to increment another counter