package Deserializer(
  mkDeserialize,
  IDeserializer(..),
  State(..)) 
  where

import ClkDivider
import State


interface (IDeserializer :: # -> # -> *) clkFreq baudRate = 
  get         ::  Bit 8            
  putBitIn    :: (Bit 1) -> Action {-# always_enabled, always_ready #-}

mkDeserialize :: Handle -> Module (IDeserializer clkFreq baudRate)
mkDeserialize fileHandle = do
  ftdiRxIn :: Wire(Bit 1) <- mkBypassWire
  shiftReg :: Reg(Bit 8) <- mkReg(0)
  ftdiState <- mkReg(IDLE)

  clkDivider :: (ClkDivider (TDiv clkFreq baudRate)) <- mkClkDivider fileHandle

  addRules $
    rules

      {-# ASSERT fire when enabled #-}
      "IDLE" : when (ftdiState == IDLE), (ftdiRxIn == 0) ==>
        do
          clkDivider.reset
          ftdiState := ftdiState' ftdiState

      {-# ASSERT fire when enabled #-}
      "NOT IDLE" : when (ftdiState /= IDLE), (clkDivider.isAdvancing) ==>
        do
          ftdiState := ftdiState' ftdiState

      {-# ASSERT fire when enabled #-}
        "SAMPLING" : when 
          DATA(n) <- ftdiState,
          n >= 0,
          n <= 7, 
          let sampleTrigger = clkDivider.isHalfCycle
            in sampleTrigger
          ==>
            do
              shiftReg := ftdiRxIn ++ shiftReg[7:1]

  return $
    interface IDeserializer
    {get      = shiftReg when (ftdiState == STOP), (clkDivider.isAdvancing)
    ;putBitIn bit = 
      ftdiRxIn := bit
    }