// DCSD-Proms.bcpl -- Dicentra Control Store/Debugger Proms
// Last modified October 29, 1983  6:33 PM by Boggs

external [ Ws; OpenFile; Puts; Closes; Allocate; Free; sysZone ]

static [ memory; mbFile ]

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

manifest [ high = 1; low = 0 ]

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

DoMemory("CS", 512, 16, CS)
DoMemory("HB", 512, 8, HB)
DoMemory("CSBank", 512, 8, CSBank)

Puts(mbFile, 0)  //0 = end of file
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)
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 (not used)

let data = Allocate(sysZone, (nData+15)/16)
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)
   ]
Free(sysZone, data)
]

//-----------------------------------------------------------------------------------------
and CS(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   curState bit 3
   CSIn bit 4
   read bit
   write bit
   ]

structure Data:
   [
   nextState bit 3
   CSOut bit 4
   CSRun bit
   incCSA bit		//low true
   readCSA bit		//low true
   writeTemp bit
   readTemp bit		//low true
   enCSWrite bit
   enCSRead bit
   blank bit 2
   ]

let curState = addr<<Addr.curState
let CSIn = addr<<Addr.CSIn
let read = addr<<Addr.read eq high
let write = addr<<Addr.write eq high

let nextState = curState
let CSOut = CSIn
let CSRun = true
let incCSA, readCSA = false, false
let writeTemp, readTemp = false, false
let enCSWrite, enCSRead = false, false

// CS (cont'd)

switchon curState into
   [
   case 0:
      [
      if read % write then
         [
         if CSIn le 7 then [ CSRun = false; readCSA = true ]
         nextState = 1
         ]
      endcase
      ]
   case 1:
      [
      // In the worst case data is valid on the internal data bus 4.5 Arcs
      //  after the falling edge of a command.
      if (write & CSIn ge 2 & CSIn le 7) % (read & CSIn le 9) then enCSRead = true
      if CSIn le 7 then [ CSRun = false; readCSA = true ]
      if read & CSIn ge 10 then readTemp = true
      nextState = 2
      endcase
      ]
   case 2:
      [
      if (write & CSIn ge 2 & CSIn le 7) % (read & CSIn le 9) then enCSRead = true
      if CSIn le 7 then [ CSRun = false; readCSA = true; enCSWrite = write ]
      test read & CSIn ge 10 ifso readTemp = true ifnot writeTemp = true
      nextState = 3
      endcase
      ]
   case 3: case 4:
      [
      if CSIn le 7 then CSRun = false
      if read then readTemp = true
      nextState = curState +1
      endcase
      ]
   case 5:
      [
      test read % write
         ifso if read then readTemp = true
         ifnot
            [
            if CSIn ls 10 then CSOut = CSIn +1
            if CSIn eq 7 then [ CSOut = 0; incCSA = true ]
            nextState = 0
            ]
      endcase
      ]
   default: nextState = 0
   ]

data>>Data.nextState = nextState
data>>Data.CSOut = CSOut
data>>Data.CSRun = CSRun? high, low
data>>Data.incCSA = incCSA? low, high
data>>Data.readCSA = readCSA? low, high
data>>Data.writeTemp = writeTemp? high, low
data>>Data.readTemp = readTemp? low, high
data>>Data.enCSWrite = enCSWrite? high, low
data>>Data.enCSRead = enCSRead? high, low
]

//-----------------------------------------------------------------------------------------
and HB(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   curState bit 2
   blank bit
   HBIn bit 3
   read bit
   write bit
   blank bit
   ]

structure Data:
   [
   nextState bit 2
   HBOut bit 3
   enHBRead bit
   enHBWrite bit
   incHBA bit		//low true
   blank bit 8
   ]

let curState = addr<<Addr.curState
let HBIn = addr<<Addr.HBIn
let read = addr<<Addr.read eq high
let write = addr<<Addr.write eq high

let nextState = curState
let HBOut = HBIn
let enHBRead, enHBWrite = false, false
let incHBA = false

switchon curState into
   [
   case 0:
      [
      if read % write then
         [
         enHBWrite = write
         enHBRead = read
         nextState = 1
         ]
      endcase
      ]
   case 1:
      [
      test read % write
         ifso enHBRead = read
         ifnot
            [
            if HBIn ls 7 then HBOut = HBIn +1
            if HBIn eq 3 then [ HBOut = 1; incHBA = true ]
            nextState = 0
            ]
      endcase
      ]
   default: nextState = 0
   ]

data>>Data.nextState = nextState
data>>Data.HBOut = HBOut
data>>Data.enHBRead = enHBRead? high, low
data>>Data.enHBWrite = enHBWrite? high, low
data>>Data.incHBA = incHBA? low, high
]

//-----------------------------------------------------------------------------------------
and CSBank(addr, data) be
//-----------------------------------------------------------------------------------------
[
structure Addr:
   [
   blank bit 7
   bank bit 4
   useRom bit
   switches bit 2	//hidden feature
   blank bit 2
   ]

structure Data:
   [
   enBank0 bit		//low true
   enBank1 bit		//low true
   enBank2 bit		//low true
   enBank3 bit		//low true
   blank bit 12
   ]

let bank = addr<<Addr.bank
let useRom = addr<<Addr.useRom ne 0
let switches = addr<<Addr.switches
let enBank0, enBank1, enBank2, enBank3 = false, false, false, false

test useRom
   ifso
      [
      if bank eq 4 then enBank0 = true
      if bank eq 5 then enBank1 = true
      if bank eq 6 then enBank2 = true
      if bank eq 7 then enBank3 = true
      ]
   ifnot
      [
      if bank eq 0 then enBank0 = true
      if bank eq 1 then enBank1 = true
      if bank eq 2 then enBank2 = true
      if bank eq 3 then enBank3 = true
      ]

data>>Data.enBank0 = enBank0? low, high
data>>Data.enBank1 = enBank1? low, high
data>>Data.enBank2 = enBank2? low, high
data>>Data.enBank3 = enBank3? low, high
]