//AIproms.bcpl
// L. Stewart
//last modified April 19, 1978  9:36 PM

get "Streams.d"

external
[
//incoming procedures
OpenFile; Ws; Puts; Closes

//incoming statics
dsp
]

static [ mbFile; memoryNumber ]

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

//-------------------------------------------------------------------
let AltoImpRoms() be
//-------------------------------------------------------------------
[
mbFile = OpenFile("AIProms.mb",ksTypeWriteOnly,charItem)
DoMemory(256,4,"Control",GenControl)
DoMemory(256,4,"Input",GenInput)
DoMemory(256,4,"Output",GenOutput)
PutWord(mbFile,0)  //end of file
Closes(mbFile)
]

//-------------------------------------------------------------------
and DoMemory(length,width,name,Generator) be
//-------------------------------------------------------------------
//length is 2↑(number of address bits)
//width is the number of output bits
//name is a BCPL string
//generator is a procedure
[
Puts(dsp,$*N); Ws(name)

PutWord(mbFile,4)  //declare memory parameters
memoryNumber = memoryNumber +1
PutWord(mbFile,memoryNumber)
PutWord(mbFile,width)
for i = 1 to name>>String.length do Puts(mbFile,name>>String.char↑i)
Puts(mbFile,0)  //asciz end of string
if (name>>String.length & 1) eq 0 then Puts(mbFile,0)  //pad to word boundry

PutWord(mbFile,2)  //set current memory and location
PutWord(mbFile,memoryNumber)
PutWord(mbFile,0)  //location = 0

for addr = 0 to length-1 do
   [
   PutWord(mbFile,1)  //memory data word
   PutWord(mbFile,0)  //source line number (not used)
   PutWord(mbFile,Generator(addr))
   ]
]

//-------------------------------------------------------------------
and PutWord(stream,w) be
//-------------------------------------------------------------------
[
Puts(stream,w rshift 8)
Puts(stream,w)
]

//-------------------------------------------------------------------
and GenControl(address) = valof
//-------------------------------------------------------------------
//an I3601
[
manifest
   [
   //states
   stateIdle = 0
   stateStartOutput = 1
   stateSetControl = 2
   stateStartInput = 3
	//wakeups      NOTE: Low bit inverted before reaching NEXT
   nothing = 0
   wakeupControl = 0
   wakeupInputStart = 1
   wakeupInputData = 2
   wakeupOutputData = 3
   //SIO's
   sioSetControl = 3
   sioStartInput = 2
   sioStartOutput = 1
   sioOtherDevice = 0
   ]

structure Address:
   [
   blank bit 8
   NotSIO bit  //A0 pin 5
   NotBus bit 2
   NotISWakC bit
   NotIWake bit
   NotOWake bit
   OldState bit 2
   ]

structure Data:
   [
   Nextbits bit 2  //Q0 pin 12
   NewState bit 2
   blank bit 12
   ]

let SIO = address<<Address.NotSIO eq 0
let Bus = address<<Address.NotBus xor #3
let ISWakC = address<<Address.NotISWakC eq 0
let IWake = address<<Address.NotIWake eq 0
let OWake = address<<Address.NotOWake eq 0
let OldState = address<<Address.OldState
let data = 0
let newState= 0
let NEXTbits= 0

switchon OldState into
   [
   case stateIdle:
      [
      test SIO
         ifso switchon Bus into
            [
            case sioSetControl:   //Control request
               [
               newState = stateSetControl
               NEXTbits = wakeupControl
               endcase
               ]
            case sioStartInput:   //Input request
               [
               newState = stateStartInput
               NEXTbits = wakeupInputStart
               endcase
               ]
            case sioStartOutput:   //Output request
               [
               newState = stateStartOutput
               NEXTbits = nothing
               endcase
               ]
            case sioOtherDevice:   //Nothing
               [
               newState = OldState
               NEXTbits = nothing
               endcase
               ]
            ]
         ifnot test IWake
            ifso
               [
               newState = stateIdle
               NEXTbits = wakeupInputData
               ]
            ifnot test OWake
               ifso
                  [
                  newState = stateIdle
                  NEXTbits = wakeupOutputData
                  ]
               ifnot
                  [
                  newState = OldState
                  NEXTbits = nothing
                  ]
      endcase
      ]
   case stateStartOutput:
      [
      test SIO
         ifnot
            [
            newState = stateIdle
            NEXTbits = nothing
            ]
         ifso
            [
            newState = OldState
            NEXTbits = nothing
            ]
      endcase
      ]
   case stateStartInput:
      [
      test SIO
         ifso
            [
            newState = OldState
            NEXTbits = wakeupInputStart
            ]
         ifnot
            [
            test ISWakC
               ifso
                  [
                  newState = stateIdle
                  NEXTbits = nothing
                  ]
               ifnot
                  [
                  newState = OldState
                  NEXTbits = wakeupInputStart
                  ]
            ]
      endcase
      ]
   case stateSetControl:
      [
      test SIO
         ifnot
            [
            test ISWakC
               ifso
                  [
                  newState = stateIdle
                  NEXTbits = nothing
                  ]
               ifnot
                  [
                  newState = OldState
                  NEXTbits = wakeupControl
                  ]
            ]
         ifso
            [
            newState = OldState
            NEXTbits = wakeupControl
            ]
      endcase
      ]
   ]
data<<Data.NewState = newState 
data<<Data.Nextbits= NEXTbits
//cheating to set file bits correctly
data = data xor #170000
// sigh
resultis data
]

//-------------------------------------------------------------------
and GenInput(address) = valof
//-------------------------------------------------------------------
//an I3601
[
manifest
   [
   //states
   stateIdle = 0
   stateWaitforBit = 1
   stateClock = 2
   stateHandshake = 5
   stateWakeup = 7
   stateLastWakeup = 3
   stateLastWakeupDelay = 6
   ]

structure Address:
   [
   blank bit 8
   NotIRead bit  //A0 pin 5
   NotIIEnbl bit
   Pad bit
   IC15 bit
   TYInBS bit
   OldState bit 3
   ]

structure Data:
   [
   ILastW bit  //Q0 pin 12
   NewState bit 3
   blank bit 12
   ]

let IRead = address<<Address.NotIRead eq 0
let IIEnbl = address<<Address.NotIIEnbl eq 0
let Pad = address<<Address.Pad ne 0
let IC15 = address<<Address.IC15 ne 0
let TYInBS = address<<Address.TYInBS ne 0
let OldState = address<<Address.OldState
let data = 0
let newState= 0

switchon OldState into
   [
   case stateIdle:
      [
      newState = IIEnbl ? stateWaitforBit, OldState
      if IRead then newState = stateIdle
      endcase
      ]
   case stateWaitforBit:
      [
      newState = TYInBS ? stateClock, OldState
      if IIEnbl then newState = OldState
      if IRead then newState = stateIdle
      endcase
      ]
   case stateClock:
      [
      newState = stateHandshake
      if IRead then newState = stateIdle
      endcase
      ]
   case stateHandshake:
      [
      test TYInBS
         ifso newState = OldState
         ifnot test IC15
            ifso newState = Pad ? stateLastWakeup, stateWakeup
            ifnot newState = Pad ? stateClock, stateWaitforBit
      if IRead then newState = stateIdle
      endcase
      ]
   case stateLastWakeup:      //wait for first IREAD
      [
      newState = IRead ? stateLastWakeupDelay, OldState
      endcase
      ]
   case stateLastWakeupDelay:      //wait for first IREAD to go away
      [
      newState = IRead ? OldState, stateWakeup
      endcase
      ]
   case stateWakeup:     // wait for last IREAD
      [
      newState = IRead ? stateIdle, OldState
      endcase
      ]
   default:
      [
      newState = stateIdle
      endcase
      ]
   ]
data<<Data.NewState = newState 
data<<Data.ILastW= ((newState eq stateLastWakeup) % (newState eq stateLastWakeupDelay)) ? 1, 0
//cheating to set file bits correctly
data = data xor #170000
// sigh
resultis data
]

//-------------------------------------------------------------------
and GenOutput(address) = valof
//-------------------------------------------------------------------
//an I3601
[
manifest
   [
   //states
   stateIdle = 0
   stateWaitforRdy = 1
   stateClock = 5
   stateSendBit = 2
   stateWakeup = 3
   ]

structure Address:
   [
   blank bit 8
   NotIOClr bit  //A0 pin 5
   NotIWrite bit
   NotIOStrt bit
   OC15 bit
   NotRFNOBS bit
   OldState bit 3
   ]

structure Data:
   [
   TYOB bit  //Q0 pin 12
   NewState bit 3
   blank bit 12
   ]

let IOClr = address<<Address.NotIOClr eq 0
let IWrite = address<<Address.NotIWrite eq 0
let IOStrt = address<<Address.NotIOStrt eq 0
let OC15 = address<<Address.OC15 ne 0
let RFNOBS = address<<Address.NotRFNOBS eq 0
let OldState = address<<Address.OldState
let data = 0
let newState= 0

switchon OldState into
   [
   case stateIdle:
      [
      test IOStrt
      ifso newState = stateWakeup
      ifnot newState = IWrite ? stateWaitforRdy, OldState
      endcase
      ]
   case stateWaitforRdy:
      [
      newState = RFNOBS ? stateSendBit, OldState
      if IWrite then newState = OldState
      endcase
      ]
   case stateSendBit:
      [
      test RFNOBS
         ifso newState = OldState
         ifnot newState = OC15 ? stateWakeup, stateClock
      endcase
      ]
   case stateClock:
      [
      newState = stateWaitforRdy
      endcase
      ]
   case stateWakeup:
      [
      newState = OldState
      //  if IOClr then newState = stateIdle
      endcase
      ]
   default:
      [
      newState = stateIdle
      endcase
      ]
   ]
if IOClr then newState = stateIdle
data<<Data.NewState = newState
data<<Data.TYOB= newState eq stateSendBit ? 1, 0
//cheating to set file bits correctly
data = data xor #170000
// sigh
resultis data
]