NewMA,NewPR: Token;

-----------------------------------------------------------------------
-----------------------------------------------------------------------
Class OBU is
Signals tick, receiveMA, checkMA;   -- arrives every 500 ms.

Vars 
  counter :=0;
  maxcycles := 3;
  LastPR := null;
  LastMA := null;

State Top Defers receiveMA

Behavior

CycleWait -> Compute_Position {tick}
 
---------   COMPUTE POSITION ------------
Compute_Position.computing -> Compute_Position.final {-/ 
  -- successful POSITION computation
  LastPR := NewPR;
}

Compute_Position.computing -> Compute_Position.final {-/ 
  -- POSITION computation failure
  LastPR := null;
}

--------------------------------

Compute_Position -> Send_PR

---------   SEND PR  ------------
Send_PR.checkPR -> Send_PR.final {-[LastPR /= null] /
  -- successful sending of PR to RBC
  LastPR :=null;
  RBC.RBCreceive;
}
 
Send_PR.checkPR -> Send_PR.final {-[LastPR /= null] /
  -- PR sending failure
  LastPR := null;
}

Send_PR.checkPR -> Send_PR.final {-[LastPR = null]
  -- nothing to send
}
--------------------------------

Send_PR -> HandleMA {-/self.checkMA;}

---------   Handling MA  ------------

HandleMA.check_MA ->  HandleMA.check_MA {receiveMA/
 -- get MA from events queue
 LastMA := NewMA;
}

HandleMA.check_MA ->  HandleMA.final {checkMA [LastMA != null]/ 
  -- new MA arrived
  counter := 0;
  LastMA:=null;
}

HandleMA.check_MA ->  HandleMA.final {checkMA [LastMA=null and counter < maxcycles] /
  -- no MA arrived
  counter := counter+1;
}

HandleMA.check_MA ->  HandleMA.STOPPED {checkMA [LastMA=null and counter >= maxcycles] /
  -- MA timeout
  counter := counter+1;
}

HandleMA -> CycleWait

end OBU;

-----------------------------------------------------------------------
-----------------------------------------------------------------------
Class RBC is
Signals tick, RBCreceive, Step1;   -- arrives every 500 ms.

Vars
  LastPR :=null;

State Top Defers RBCreceive

Behavior

CycleWait -> Compute_MA {tick/
 self.Step1
}
 
---------   Computing MA  ------------
Compute_MA.check_PR ->  Compute_MA.check_PR {RBCreceive/ 
  -- get PR message from events queue
  LastPR := NewPR;
}

Compute_MA.check_PR -> CycleWait {Step1[LastPR=null] /
  -- no PR available
}

Compute_MA.check_PR ->  Compute_MA.final {Step1[LastPR != null] / 
  -- a new PR is available
  LastPR :=null;
}

Compute_MA -> Send_MA

---------   SEND PR  ------------
Send_MA.MA_available -> Send_MA.final {-/
  -- successful RBC sending of MA to OBU
  OBU.receiveMA;
}
 
Send_MA.MA_available -> Send_MA.final {-/
  -- RBC sending failure
}

--------------------------------

Send_MA -> CycleWait 

end RBC;

-----------------------------------------------
-----------------------------------------------
Class Timer is
 Signals stop, step
Vars
 Priority := -1;
Behaviour
  s0 -> s0 { -   / OBU.tick;RBC.tick}
end Timer;
 
-----------------------------------------------
-----------------------------------------------

RBC:RBC;
OBU:OBU;
Time:Timer;


Abstractions {
  --Action $1($*) and $1 /= tick -> $1($*)
  Action OBU:accept(tick) -> tick
  Action OBU:accept(receiveMA) -> ReceiveMA
  Action OBU:discard(tick) -> DEADLOCK
  State inState(OBU.CycleWait) -> CYCLEWAIT
  State inState(OBU.HandleMA.Compute_Position) -> COMPUTEPOSITION 
  State inState(OBU.HandleMA.Send_PR) -> SENDPR
  State inState(OBU.HandleMA) -> HANDLEMA
  State inState(OBU.HandleMA.STOPPED) -> STOPPED
  State OBU.counter > OBU.maxcycles ->  TIMEOUT  
  State OBU.counter=$1 ->  counter($1)
}


---- PROPERTIES ---------
--  Counter > maxcycles if and only if STOPPED
--  AG (TIMEOUT implies STOPPED)
--  AG (STOPPED impllies TIMEOUT)
--
-- the OBU cycle always either completes and restarts, or ends in STOPPED state
-- AG [CYCLEWAIT] A[ CYCLEWAIT U A[COMPUTEPOSITION U A[SENDPR U A[HANDLEMA U (STOPPED or CYCLEWAIT)] ] ] ]
--
-- liveness
-- EG (not STOPPED and not FINAL)
-- 


