! Local Processor 6850 ACIA Terminal Process (interrupt driven) - NEW

option  "-low-nocheck-nodiag-noline-nostack"
include  "moose:mouse.inc"

Recordformat  clockreqfm (record (messagefm) msg,
                          Integer  ms)

! Physical stuff
@16_4000c0 byte  *,acia s,*,acia d

Constinteger  kbbs = 512-1
Recordformat  kb buff fm(Integer  sem,bs,be,in,out,notempty,
                         Bytearray  buff(0:kbbs),integer  op)

Constinteger  opbs = 1024-1
Constinteger  thresh = opbs//2
Recordformat  op buff fm(Integer  notfull,bs,in,out,
                         bytearray  buff(0:opbs),integer  code,ctrlo,
                         Integer  xonsem, integer  xonflag, integer  gotsem)

ownrecord (interrupt handler fm) ih
ownrecord (kbbufffm)name         kb buff
Ownrecord (opbufffm)name         op buff
Ownrecord (mailboxfm)            mbox
Ownrecord (semaphorefm)          sem
ownrecord (semaphorefm)          notfull
Ownrecord (semaphorefm)          notempty
ownrecord (semaphorefm)          xonsem
Ownrecord (semaphorefm)          inmutex,outmutex
Ownrecord (clockreqfm)           clockreq
Ownrecord (mailboxfm)name        clockmbx
Ownrecord (mailboxfm)            inclock

Routine  Initialise
   Label  x,y,l,nw,rej,nott,noto,notq,nots,rint,nwrp,endt,noty
   Label  tint,dcdint,nosig,notx, done
   Integer  t
   @0(a6)Record (interrupthandlerfm) nih
   @0(a4)Record (kbbufffm) kb
   @0(a0)Record (opbufffm) op

   kbbuff == new(kbbuff); kbbuff=0
{   putstring("Kb buff @");putlong(addr(kbbuff));putsym(10)
   kbbuff_sem = addr(sem)
   kbbuff_bs = addr(kbbuff_buff(0))
   kbbuff_be = addr(kbbuff_buff(kbbs))+1
   kbbuff_in = kbbuff_bs
   kbbuff_out = kbbuff_bs
   kbbuff_op = addr(opbuff)
   kbbuff_notempty = addr(notempty)

   setup interrupt handler (ih, addr(x))
   ih_a4 = addr(kbbuff)
   add interrupt handler (ih,5)
   acias = 16_91  ;! Enable interrupts
   Return 

x: *move.b acia s, d0

   *btst #2,d0;  ! DCD
   *bne dcdint
   
   *btst #5,d0;  ! OVRN
   *bne dcdint

   *btst #4,d0;  ! FE
   *bne dcdint

   *btst #0,d0;  ! RDRF
   *bne rint

   *btst #1,d0;  ! TDRE
   *bne tint

done:
   return from interrupt

dcdint:
   ! Read the data register to clear the condition
   ! (throw the character away, as it's rubbish)
   *move.b acia d, d0
   ! Now, in case there's been a TX interrupt while we were
   ! unplugged, we have to test the TX data register status....
   *btst.b #1, acia s;  ! TDRE
   *beq done

tint:
   *move.l kb_op,a0
   *move.l op_out,d0
   *cmp.l op_in,d0
   *beq endt
   *and.l  #opbs,d0
   *move.l op_bs,a1
   *move.b 0(a1,d0),aciad
   *addq.l #1,op_out
   *move.l op_in, a1
   *sub.l  op_out, a1
   *cmp.l #thresh, a1
   *bne nosig
   int signal semaphore (record(op_notfull))
nosig:
   -> done
endt:
   *move.b #16_91,acias;  ! RX int on, TX int off, 8+2
   -> done

rint:
   *move.b acia d,d0
   *and.b #127,d0

   *cmp.b #30,d0     ;! Control T {now CTRL-^ actually !}
   *bne nott
   *reset
   *mtsr #16_2700
   *move.l 0,sp
   *move.l 4,-(sp)
   *rts
nott:
   *cmp.b #15,d0     ;! Control O
   *bne noto
   *move.l kb_op, a0
   op_ctrlo = op_ctrlo!!1
   if  op_ctrlo = 1 start 
      acias = 16_91;  ! TX int off to zap output
      op_out = op_in
      int signal semaphore (record(op_notfull))
   finish 
   -> done
noto:
   *cmp.b #19,d0     ;! Control S
   *bne nots
   *move.l kb_op,a0
   op_xonflag = 1
   acias = 16_91;  ! TX int off to freeze output
   -> done
nots:
   *cmp.b #17,d0     ;! Control Q
   *bne notq
   *move.l kb_op, a0
   if  op_xonflag = 1 start 
      op_xonflag=0
      acias = 16_B1;  ! TX int on (& RX int, 8+2)
      int signal semaphore (record(op_xonsem))
   Finish 
   -> done      
notq:
   *cmp.b #24,d0    ;! Control X 
   *bne notx
   kb_in = kb_out
!   -> done
notx:
   *move.l kb_in,a0
   *move.b d0,(a0)+
   *Cmp.l  kb_be,a0
   *Bne nw
   *move.l kb_bs,a0
nw:
   *Cmp.l  kb_out,a0
   *Beq rej
   *Move.l a0,kb_in
   int signal semaphore (record(kb_notempty))   ;! Should only do when going
                                                ;! notempty
   -> done
rej:
   *move.b #7,d0
   *jsr 16_41c;  !????
   -> done
End 

Routine  fire timer
{   putstring("Fire timer")
   clockreq_ms = realtime + 10000
   send message (clockreq,clockmbx,inclock)
End 

Begin 
   Integer  k,t, waiting=0,sym,i,diff
   record (Dictfm)name  m
   record (messagefm)Name  clockrep

   on  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 start 
      PutString("Local Terminal process failed -")
      putlong(event_event);putsym(' ');putstring(event_message)
      putsym(10)
      Stop 
   Finish 

   putstring("Local Terminal process - 13/4/88");putsym(10)

   setup semaphore (sem)
   setup semaphore (notfull)
   setup semaphore (inmutex)
   setup semaphore (outmutex)
   setup semaphore (xonsem)
   setup semaphore (notempty)
   setup mailbox (inclock,sem)
   setup message (clockreq,sizeof(clockreq))

   i = Find Entry ("CLOCK_REQ",poa_logdict)
   Signal  3,0,0,"Failed to find CLOCK_REQ" if  i = 0
   clockmbx == record(integer(i))

   opbuff == new(opbuff)
   opbuff = 0
   opbuff_bs = addr(opbuff_buff(0))
   opbuff_in = 0
   opbuff_out= 0
   opbuff_notfull = addr(notfull)
   opbuff_xonsem = addr(xonsem)
   opbuff_xonflag = 0
   opbuff_ctrlo = 0
   Initialise
   m == poa_logdict
   m == m_alt while  m_alt ## NIL

   i = make entry("T_MUTEX_IN", m)
   Signal  3,0,0, "Failed to enter T_MUTEX_IN" if  i = 0
   integer (i) = addr(inmutex)
   
   i = make entry("T_MUTEX_OUT", m)
   Signal  3,0,0, "Failed to enter T_MUTEX_OUT" if  i = 0
   integer (i) = addr(outmutex)

   i = make entry("T_OP_BUFFER",m)
   signal  3,0,0, "Failed to enter T_OP_BUFFER" if  i = 0
   integer (i) = addr(opbuff)

   i = make entry("T_KB_BUFFER",m)
   signal  3,0,0, "Failed to enter T_KB_BUFFER" if  i = 0
   integer (i) = addr(kbbuff)

   signal semaphore (inmutex)
   signal semaphore (outmutex)

   fire timer
   Cycle 
      Semaphore Wait (sem)
      clockrep == dequeue(inclock_queue)
      if  clockrep ## NIL start 
         if  opbuff_gotsem = 1 start 
            if  outmutex_count < 0 start 
               {PutString("*Grab*")
               opbuff_gotsem = 0
               signal semaphore (outmutex)
            finish 
         finish 
         fire timer
      Finish 
   Repeat 
End