// DArpaProms.bcpl -- Dicentra Arpa/BBN-1822 Proms
// Last modified August 21, 1983  8:08 PM by Boggs

external [ Ws; OpenFile; Puts; Closes; TruncateDiskStream; CallSwat ]

static [ memory; mbFile ]

structure String [ length byte; char↑1,1 byte ]

manifest [ high = 1; low = 0 ]

//-----------------------------------------------------------------------------------------
let DCSDProms() be
//-----------------------------------------------------------------------------------------
[
mbFile = OpenFile("DArpaProms.mb")

DoMemory("Command", 512, 8, Command)
DoMemory("ImpToHost", 512, 16, ImpToHost)
DoMemory("HostToImp", 512, 16, HostToImp)

Puts(mbFile, 0)  //0 = end of file
TruncateDiskStream(mbFile)
Closes(mbFile)
]

//-----------------------------------------------------------------------------------------
and DoMemory(name, nAddr, nData, Proc) be
//-----------------------------------------------------------------------------------------
// nAddr is number of addresses; nData is number of output bits
[
Ws("*N"); Ws(name)

Puts(mbFile, 4)  //4 = define memory
memory = memory +1
Puts(mbFile, memory)
Puts(mbFile, nData)

// Write Asciz string to word stream.  What a pain!
if name>>String.length gr 1 then
   for i = 1 to name>>String.length-1 by 2 do
      Puts(mbFile, name>>String.char↑i lshift 8 + name>>String.char↑(i+1))
Puts(mbFile, (name>>String.length & 1) eq 0? 0,
 name>>String.char↑(name>>String.length) lshift 8)

Puts(mbFile, 2)  //2 = set current memory
Puts(mbFile, memory)
Puts(mbFile, 0)  //location counter

let data = vec 1; if nData gr 32 then CallSwat("increase data vector size")
for addr = 0 to nAddr-1 do
   [
   Puts(mbFile, 1)  //1 = memory contents
   Puts(mbFile, 0)  //source line number (not used)
   Proc(addr, data)
   for i = 0 to (nData+15)/16 -1 do Puts(mbFile, data!i)
   ]
]

//-----------------------------------------------------------------------------------------
and Command(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   IORC bit		//low true
   IOWC bit		//low true
   ADR1 bit		//low true
   BdSelH bit		//low true
   BdSelL bit		//low true
   ]

structure Data:
   [
   ReadData bit		//low true
   WriteData bit
   ReadStatus bit	//low true
   WriteControl bit
   CmdSelect bit
   blank bit 3
   blank bit 8
   ]

let IORC = addr<<Addr.IORC eq low
let IOWC = addr<<Addr.IOWC eq low
let ADR1 = addr<<Addr.ADR1 eq low
let BdSel = addr<<Addr.BdSelH eq low & addr<<Addr.BdSelL eq low

data>>Data.ReadData = (BdSel & IORC & ADR1)? low, high
data>>Data.WriteData = (BdSel & IOWC & ADR1)? high, low
data>>Data.ReadStatus = (BdSel & IORC & not ADR1)? low, high
data>>Data.WriteControl = (BdSel & IOWC & not ADR1)? high, low
data>>Data.CmdSelect = (BdSel & (IORC % IOWC))? high, low
]

//-----------------------------------------------------------------------------------------
and ImpToHost(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   CurState bit 4
   TYIB bit
   LIB bit
   ReadData bit		//low true
   IEn bit
   CntrCry bit
   ]

structure Data:
   [
   NextState bit 4
   RFNIB bit
   LastI bit
   ISRClk bit		//voltage
   Pad bit		//low true
   IInt bit		//low true
   CntrDat bit 4
   CntrLd bit		//low true
   CntrClr bit		//low true
   CntrEn bit
   ]

manifest
   [
   Off = 0
   WaitForTYIBtrue = 1
   WaitForTYIBfalse = 2
   WaitForReadTrue = 3
   WaitForReadFalse = 4
   Pad1 = 5
   Pad2 = 6
   WaitForLastRead = 7
   End = 8
   ]

let CurState = addr<<Addr.CurState
let TYIB = addr<<Addr.TYIB eq high
let LIB = addr<<Addr.LIB eq high
let ReadData = addr<<Addr.ReadData eq low
let IEn = addr<<Addr.IEn eq high
let CntrCry = addr<<Addr.CntrCry eq high

let NextState = IEn? CurState, Off
let RFNIB = false
let LastI = false
let ISRClk = high
let Pad = false
let IInt = false
let CntrDat = 0
let CntrLd = false
let CntrClr = false
let CntrEn = false

if IEn switchon CurState into
   [
   case Off:
      [
      CntrDat = 0
      CntrLd = true
      NextState = WaitForTYIBtrue
      endcase
      ]
   case WaitForTYIBtrue:
      [
      RFNIB = true
      if TYIB then
         [
         ISRClk = low
         CntrEn = true
         NextState = WaitForTYIBfalse
         if LIB then [ Pad = true; NextState = Pad1 ]
         if CntrCry then NextState = LIB? WaitForLastRead, WaitForReadTrue
         ]
      endcase
      ]
   case WaitForTYIBfalse:
      [
      if not TYIB then NextState = WaitForTYIBtrue
      endcase
      ]
   case WaitForReadTrue:
      [
      IInt = true
      if ReadData then NextState = WaitForReadFalse
      endcase
      ]
   case WaitForReadFalse:
      [
      if not ReadData then NextState = WaitForTYIBfalse
      endcase
      ]

   // ImpToHost (cont'd)

   case Pad1:
      [
      Pad = true
      CntrEn = true
      ISRClk = low
      NextState = CntrCry? WaitForLastRead, Pad2
      endcase
      ]
   case Pad2:
      [
      Pad = true
      NextState = Pad1
      endcase
      ]
   case WaitForLastRead:
      [
      LastI = true
      IInt = true
      if ReadData then NextState = End
      endcase
      ]
   case End:
      [
      LastI = true
      endcase
      ]
   ]

data>>Data.NextState = NextState
data>>Data.RFNIB = RFNIB? high, low
data>>Data.LastI = LastI? high, low
data>>Data.ISRClk = ISRClk
data>>Data.Pad = Pad? low, high
data>>Data.IInt = IInt? low, high
data>>Data.CntrDat = CntrDat
data>>Data.CntrLd = CntrLd? low, high
data>>Data.CntrClr = CntrClr? low, high
data>>Data.CntrEn = CntrEn? high, low
]

//-----------------------------------------------------------------------------------------
and HostToImp(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   CurState bit 4
   RFNHB bit
   LastH bit
   WriteData bit
   OEn bit
   CntrCry bit
   ]

structure Data:
   [
   NextState bit 4
   TYHB bit
   LHB bit
   ClkInh bit
   Shift bit
   OInt bit		//low true
   CntrDat bit 4
   CntrLd bit		//low true
   CntrClr bit		//low true
   CntrEn bit
   ]

manifest
   [
   Off = 0
   WaitForWrite = 1
   WaitForRFNHBtrue = 2
   WaitForRFNHBfalse = 3
   ]

let CurState = addr<<Addr.CurState
let RFNHB = addr<<Addr.RFNHB eq high
let LastH = addr<<Addr.LastH eq high
let WriteData = addr<<Addr.WriteData eq high
let OEn = addr<<Addr.OEn eq high
let CntrCry = addr<<Addr.CntrCry eq high

let NextState = OEn? CurState, Off
let TYHB = false
let LHB = false
let ClkInh = true
let Shift = true
let OInt = false
let CntrDat = 0
let CntrLd = false
let CntrClr = false
let CntrEn = false

if OEn switchon CurState into
   [
   case Off:
      [
      CntrDat = 0
      CntrLd = true
      NextState = WaitForWrite
      endcase
      ]
   case WaitForWrite:
      [
      OInt = true
      if WriteData then
         [
         ClkInh = false
         Shift = false
         NextState = WaitForRFNHBtrue
         ]
      endcase
      ]
   case WaitForRFNHBtrue:
      [
      LHB = LastH & CntrCry
      if RFNHB then NextState = WaitForRFNHBfalse
      endcase
      ]
   case WaitForRFNHBfalse:
      [
      TYHB = true
      if not RFNHB then
         [
         ClkInh = false
         CntrEn = true
         NextState = CntrCry? WaitForWrite, WaitForRFNHBtrue
         ]
      endcase
      ]
   ]

data>>Data.NextState = NextState
data>>Data.TYHB = TYHB? high, low
data>>Data.LHB = LHB? high, low
data>>Data.ClkInh = ClkInh? high, low
data>>Data.Shift = Shift? high, low
data>>Data.OInt = OInt? low, high
data>>Data.CntrDat = CntrDat
data>>Data.CntrLd = CntrLd? low, high
data>>Data.CntrClr = CntrClr? low, high
data>>Data.CntrEn = CntrEn? high, low
]