(*==========================================================================*)
(*========================= ASYNCRONOUS RECEIVER ===========================*)
(*==========================================================================*)
(****************************************************************************)
(*                                                                          *)
(* PRIMITIVE : ASYN__RXD                                                     *)
(* Written by: Ewald Liess, Motorola Munich (0049) 89/92103-574             *)
(* Date      : 25/08/90                                                     *)
(*                                                                          *)
(* Valid State Entry Conditions:                                            *)
(*  State HSR0  HSR1  M/TSR  LSR  Pin  Flag0          ACTION                *)
(*    1     1     1     x     x    x     x     Initialise Pin State         *)
(*    2     0     0     1     x    x     0     Start-Bit occured            *)
(*    3     0     0     1     x    x     1     Read next Bit at MATCHRATE   *)
(*                                                                          *)
(****************************************************************************)

(* Parameters *)
%macro CHANNEL_CONTROL         'prm0'.
%macro MATCH_RATE              'prm1'.
%macro RECEIVED_DATA           'prm2'.
%macro DATA_SIZE               'prm3'.
%macro ACTUAL_BIT_COUNT        'prm4'.
%macro RxD_SHFT_REG            'prm5'.

(**********************************************************************)
(*                                                                    *)
(* State 1: Initialisation                                            *)
(*                                                                    *)
(* Wait for a falling edge at the Input Pin.                          *)
(**********************************************************************)

(* prim specified by parameter passed by %include in calling file *)

%entry   start_address *; disable_match;
name = INIT_RECEIVE;
cond hsr1 = 1,  hsr0 = 1.

INIT_RECEIVER:   chan pac:=high_low; clear flag0;enable_mtsr.
		 chan neg_tdl,neg_mrl,neg_lsl.
                 end.

(**********************************************************************)
(*                                                                    *)
(* State 2: START BIT OCCURED                                         *)
(*                                                                    *)
(* receive START-Bit and start sampling in the middle of a BIT        *)
(**********************************************************************)

%entry ram diob <- @MATCH_RATE; start_address *; disable_match;
name = RECEIVE_START_BIT;
cond hsr1 = 0,  hsr0 = 0,  m/tsr = 1,  lsr = x,  pin = x, flag0 = 0.

                 au   diob :=>> diob;                 (* MATCHRATE/2 *)
                 ram  p <- @DATA_SIZE.
                 au   ert := ert + diob;
                 chan pac := no_detect; set flag0;
                      write_mer, neg_mrl, neg_lsl, neg_tdl.
                 au   p := p + 1;                     (* count startbit *)
                 ram  p -> @ACTUAL_BIT_COUNT;
                 end.

(**********************************************************************)
(*                                                                    *)
(* STATE 3: RECEIVE BITS                                              *)
(*                                                                    *)
(* Read the value at the PIN and shift this value in the RxD_SHFT_REG.*)
(* Also decrement the number of received bits.                        *)
(**********************************************************************)

%entry  ram diob <- @MATCH_RATE; start_address *; disable_match;
name = RECEIVE_DATA_BITS;
cond hsr1 = 0,  hsr0 = 0,  m/tsr = 1,  lsr = x,  pin = x,  flag0 = 1.

RECEIVE_DATA_BITS: au   ert := ert + diob;
                   ram  p <- @ACTUAL_BIT_COUNT.
                   au   p := p - 1, ccl;
                   ram  diob <- @RxD_SHFT_REG.
                   if   N = 1 then goto RECEIVE_STOP_BIT.
		   au a:=max;
                   ram  p -> @ACTUAL_BIT_COUNT.
                   if   PSL = 1 then goto RECEIVE_HIGH_BIT.
                   au   diob :=>> diob;      (* shift zero into bit15 *)
                   chan write_mer, neg_tdl, neg_lsl, neg_mrl.

RECEIVE_LOW_BIT:   ram  diob -> @RxD_SHFT_REG;
                   end.

RECEIVE_HIGH_BIT:  au   diob := diob + max;
                   ram  diob -> @RxD_SHFT_REG;
                   end.

RECEIVE_STOP_BIT:  if PSL = 1 then goto OK, flush.

SET_FE_FLAG:	   au a:=>>a.
		   au a:=a+max.                      (* here you can add Framing Error-Bit *)

OK:                ram  p <- @DATA_SIZE.
                   au   dec := dec - p;           (* align to the right side *)
                   chan pac := high_low;      (* wait for new startbit *)
                        clear flag0;neg_tdl,neg_mrl;cir.

                   repeat;
                   au   diob :=>> diob.
                   au   diob := diob + a;     (* set TDRE *)
                   ram  diob -> @RECEIVED_DATA;
                   end.

(**********************************************************************)
(*     UNDEFINED ENTRIES - execute an end.                            *)
(**********************************************************************)
%entry start_address DONOTHING; disable_match;
name = UART_UNDEF;
cond hsr1 = 0, hsr0 = 1.

%entry start_address DONOTHING; disable_match;
name = UART_UNDEF;
cond hsr1 = 1, hsr0 = 0.

%entry start_address DONOTHING; disable_match;
name = UART_UNDEF;
cond hsr1 = 0, hsr0 = 0, m/tsr = 0, lsr = 1.

(* EOF *)
