--{{{  ss.B00x.stream.driver  B001, B002, (B011, B016)
#INCLUDE "process0.inc"
#INCLUDE "process1.inc"
PROC ss.B00x.stream.driver (CHAN OF SS from.user.scrn, CHAN OF KS to.user.kbd,
			    VAL INT board.type, port, baud.rate, screen.type)

  --{{{  specification
  -- Purpose:  To be a terminal driver for a B001 or B002 board.
  -- Channels: from.user.scrn - for input
  --           to.user.kbd - for output of 7-bit ASCII characters in word
  --           length quantities
  -- In:       board.type - 1 for B001
  --                        2 for B002
  --                        otherwise error
  -- In:       port - where the uart port is: 0 for terminal
  --                                          1 for host
  -- In:       baud.rate - one of 38400, 19200, 9600, 7200, 4800, 2400,
  --           2000, 1800, 1200, 1050, 600, 300, 200, 150, 134, 110, 75, 50,
  --           or 0; if non-zero then the uart is reset when the procedure
  --           starts executing
  -- In:       screen.type - 0 for ANSI based terminals
  --                         1 for TVI920 based terminals
  --                         otherwise error
  -- Notes:    This terminal handler does not terminate.
  --}}}
  --{{{  more information
  -- This version successfully uses []PORT OF BYTE, but violates CHAN usage.
  -- As this is for a B001 or B002, this procedure need only be compiled
  -- for a 32-bit transputer.
  --}}}
  --{{{  history
  -- V1.2, 19-Apr-89.
  -- Replaced PAR SKIP SKIP by RESCHEDULE() to be sure to have the
  -- desired effect; V1.3, SRH 15-Aug-90.
  --}}}

  --{{{  B00x.term.driver
  PROC B00x.term.driver (CHAN OF BYTE from.user.scrn, CHAN OF KS to.user.kbd,
			 VAL INT board.type, port, baud.rate)
  
    --{{{  uart placements
    --{{{  duart register addresses
    --{{{  b1 uart info
    VAL   b1.perif.base        IS     #10000 :
    --{{{  
    [64]PORT OF BYTE           b1.UARTs :
    PLACE b1.UARTs             AT     b1.perif.base :
    b1.UARTs.0                 IS [b1.UARTs FROM 0 FOR 16]:
    b1.UARTs.common            IS [b1.UARTs FROM 16 FOR 16]:
    b1.UARTs.1                 IS [b1.UARTs FROM 32 FOR 16]:
    --}}}
    --}}}
    --{{{  b2 uart info
    VAL   b2.perif.base        IS     1 << 19 :
    [64]PORT OF BYTE           b2.UARTs :
    PLACE b2.UARTs             AT     b2.perif.base :
    
    b2.UARTs.0                 IS [b2.UARTs FROM 0 FOR 16]:
    b2.UARTs.common            IS [b2.UARTs FROM 16 FOR 16]:
    b2.UARTs.1                 IS [b2.UARTs FROM 32 FOR 16]:
    --}}}
    --}}}
    --}}}
    --{{{  drive.terminal (from.user, to.user, UARTs, baud.rate)
    PROC drive.terminal (CHAN OF BYTE from.user, CHAN OF KS to.user,
			 [16] PORT OF BYTE uart.ports,
			 [16] PORT OF BYTE common.ports,
			 VAL INT baud.rate)
      --{{{  uart access declarations
      --{{{  offsets in UARTs.0 and UARTs.1
      VAL mode.reg               IS 0 * 4 :     --           MR
      
      VAL status.reg             IS 1 * 4 :     -- read      SR
      VAL clock.select.reg       IS 1 * 4 :     -- write     CSR
      
      VAL command.reg            IS 2 * 4 :     --           CR
      
      VAL rx.reg                 IS 3 * 4 :     -- read
      VAL tx.reg                 IS 3 * 4 :     -- write
      --}}}
      --{{{  offsets in UARTs.common
      VAL aux.control.reg        IS 0 * 4 :     -- write     ACR      uartA only
      
      VAL interrupt.status.reg   IS 1 * 4 :     -- uartA only
      --}}}
      --{{{  values used in these registers
      --{{{  MR1  mode register 1
      
      VAL rx.rts.control      IS #00 :   -- [7]    no rts control
      VAL rx.int.select       IS #00 :   -- [6]    interrupt on rx.ready
      VAL error.mode          IS #00 :   -- [5]    character error mode
      VAL parity.mode         IS #10 :   -- [4:3]  disable parity
      VAL parity.type         IS #00 :   -- [2]    even parity
      VAL bits.per.char       IS #03 :   -- [1:0]  8 bits per char
      
      VAL MR1.control IS ((((rx.rts.control  \/
			     rx.int.select)  \/
			     error.mode)     \/
			     parity.mode)    \/
			     parity.type)    \/
			     bits.per.char  :
      --}}}
      --{{{  MR2  mode register 2
      
      VAL channel.mode    IS #00 :    -- [7:6]  normal channel mode
      VAL tx.trs.control  IS #00 :    -- [5]    rts control not used
      VAL cts.enable.tx   IS #00 :    -- [4]    cts control not used
      VAL stop.bit.length IS #07 :    -- [3:0]  1.000 stop bits
      
      VAL MR2.control IS ((channel.mode       \/
			     tx.trs.control)  \/
			     cts.enable.tx)   \/
			     stop.bit.length :
      --}}}
      --{{{  CR   command register
      VAL bit.seven           IS #00 :
      
      -- [6:4]  misc commands never combined
      
      VAL no.command          IS #00 :
      VAL reset.mr.ptr        IS #10 :  -- make mode register point at MR1
      VAL reset.rx            IS #20 :
      VAL reset.tx            IS #30 :
      VAL reset.error         IS #40 :
      VAL reset.break         IS #50 :
      VAL start.break         IS #60 :
      VAL stop.break          IS #70 :
      
      VAL enable.rx           IS #01 :  -- [3]
      VAL disable.rx          IS #02 :  -- [2]
      VAL enable.tx           IS #04 :  -- [1]
      VAL disable.tx          IS #08 :  -- [0]
      --}}}
      --{{{  SR   status register
      
      VAL received.break IS #80 :  -- [7]
      VAL framing.error  IS #40 :  -- [6]
      VAL parity.error   IS #20 :  -- [5]
      VAL overrun.error  IS #10 :  -- [4]
      VAL tx.empty       IS #08 :  -- [3]
      VAL tx.ready       IS #04 :  -- [2]
      VAL fifo.full      IS #02 :  -- [1]
      VAL rx.ready       IS #01 :  -- [0]
      --}}}
      --{{{  ISR  interrupt status register
      VAL delta.break    IS #04 :  -- [2]
      --}}}
      --}}}
      --}}}
      --{{{  procedures
      --{{{  reset.uart
      PROC reset.uart ([16]PORT OF BYTE uart.ports,
				    common.ports,
		       VAL INT baud.rate)
	PORT OF BYTE command.port IS uart.ports[command.reg]:
	PORT OF BYTE rx.tx.port IS uart.ports[rx.reg]:
	PORT OF BYTE mode.port IS uart.ports[mode.reg]:
	PORT OF BYTE clock.select.port IS uart.ports[clock.select.reg]:
	PORT OF BYTE aux.control.port IS common.ports[aux.control.reg]:
      
	INT   index :
	SEQ
	  IF
	    --{{{  baud rate match
	    --{{{  baud rate tables
	    VAL  baud.settings   IS   18 :
	    VAL  BaudRates       IS [#9600, 19200,  9600,  7200,  4800,  2400,
				      2000,  1800,  1200,  1050,   600,   300,
				       200,   150,   134,   110,    75,    50] :
	    --}}}
	    IF i = 0 FOR baud.settings
	      baud.rate = BaudRates [i]
		index := i
	    --}}}
	    --{{{  default to fastest
	    TRUE
	      index := 0
	    --}}}
	  --{{{  reset uart
	  --{{{  register mask tables
	  VAL  baud.settings   IS   18 :
	  VAL  baud.masks      IS [BYTE #CC, BYTE #CC, BYTE #BB, BYTE #AA,
				   BYTE #99, BYTE #88, BYTE #77, BYTE #AA,
				   BYTE #66, BYTE #77, BYTE #55, BYTE #44,
				   BYTE #33, BYTE #33, BYTE #22, BYTE #11,
				   BYTE #00, BYTE #00 ]:
	  VAL  ACR.masks       IS [BYTE #00, BYTE #80, BYTE #00, BYTE #00,
				   BYTE #00, BYTE #00, BYTE #80, BYTE #80,
				   BYTE #00, BYTE #00, BYTE #00, BYTE #00,
				   BYTE #00, BYTE #80, BYTE #00, BYTE #00,
				   BYTE #80, BYTE #00 ] :
	  --}}}
	  --{{{  set (register, bit.pattern)
	  PROC set (PORT OF BYTE register, VAL BYTE bit.pattern)
	    TIMER   TIME :
	    INT     now :
	    SEQ
	      register ! bit.pattern
	      TIME ? now
	      TIME ? AFTER now PLUS 1000
	  :
	  --}}}
	  SEQ
	    set (command.port,      BYTE ((reset.error \/ disable.rx) \/ disable.tx))
	    set (rx.tx.port,        BYTE reset.rx)
	    set (rx.tx.port,        BYTE reset.tx)
	    set (command.port,      BYTE reset.mr.ptr)
	    set (mode.port,         BYTE MR1.control)
	    set (mode.port,         BYTE MR2.control)
	    set (aux.control.port,  ACR.masks[index])
	    set (clock.select.port, baud.masks[index])
	    set (command.port,      BYTE ((no.command \/ enable.rx) \/ enable.tx))
	  --}}}
      :
      --}}}
      --{{{  read
      PROC read (CHAN OF KS out, PORT OF BYTE status.port, rx.port)
	WHILE TRUE
	  BYTE status:
	  BYTE input.byte:
	  SEQ
	    status.port ? status
	    WHILE ((INT status) /\ rx.ready) = 0
	      SEQ
		RESCHEDULE()  -- SRH 15/08/90
		status.port ? status
	    rx.port ? input.byte
	    out ! (INT input.byte) /\ #7F
      :
      
      --}}}
      --{{{  write
      PROC write (CHAN OF BYTE in, PORT OF BYTE status.port, tx.port)
	BYTE val, status:
	WHILE TRUE
	  --{{{  receive input and send it on
	  SEQ
	    in ? val
	    status.port ? status
	    WHILE ((INT status) /\ tx.ready) = 0
	      SEQ
		RESCHEDULE()  -- SRH 15/08/90
		status.port ? status
	    tx.port ! val
	  --}}}
      :
      
      --}}}
      --}}}
      SEQ
	IF
	  baud.rate > 0
	    reset.uart (uart.ports, common.ports, baud.rate)
	  TRUE
	    SKIP
	PAR
	  read  (to.user,    uart.ports[status.reg], uart.ports[rx.reg])
	  write (from.user,  uart.ports[status.reg], uart.ports[tx.reg])
    :
    
    --}}}
    --{{{  board types constants
    VAL   b1   IS   1 :
    VAL   b2   IS   2 :
    VAL   b6   IS   6 :
    --}}}
    SEQ
      IF
	board.type = b1
	  IF
	    port = 0
	      drive.terminal (from.user.scrn, to.user.kbd,
		b1.UARTs.0, b1.UARTs.common, baud.rate)
	    port = 1
	      drive.terminal (from.user.scrn, to.user.kbd,
		b1.UARTs.1, b1.UARTs.common, baud.rate)
	    TRUE
	      CAUSEERROR()    -- STOP
	board.type = b2
	  IF
	    port = 0
	      drive.terminal (from.user.scrn, to.user.kbd,
		b2.UARTs.0, b2.UARTs.common, baud.rate)
	    port = 1
	      drive.terminal (from.user.scrn, to.user.kbd,
		b2.UARTs.1, b2.UARTs.common, baud.rate)
	    TRUE
	      CAUSEERROR()    -- STOP
	TRUE
	  CAUSEERROR()    -- STOP
  :
  --}}}
  VAL ANSI.screen IS 0:
  VAL TVI.screen IS 1:
  CHAN OF BYTE byter:
  PAR
    B00x.term.driver (byter, to.user.kbd, board.type, port, baud.rate)
    IF
      screen.type = ANSI.screen
	ss.scrstream.to.ANSI.bytes (from.user.scrn, byter)
      screen.type = TVI.screen
	ss.scrstream.to.TVI920.bytes (from.user.scrn, byter)
      TRUE
	CAUSEERROR()    -- STOP
:
--}}}
