module Peripherals.Uart (read) where import Clash.Prelude hiding (read) import Types (Byte) import Data.Char (ord) import Peripherals.UartCFFI ( initTerminal, restoreTerminal, getCharFromTerminal, writeCharToTerminal, isCharAvailable, setupSigintHandler, wasCtrlCReceived ) import BusTypes ( TransactionSize(..), BusVal(..), ReadResponse(..), WriteResponse(..) ) -- based on a 16550 UART which has an address space of 8 bytes type UartAddr = Unsigned 3 -- Receiver Buffer Register address (commonly 0x0 for 16550 UART) rbrAddr :: UartAddr rbrAddr = 0x0 -- Line Status Register address lsrAddr :: UartAddr lsrAddr = 0x5 -- Helper function to convert Byte to BusVal based on TransactionSize busValFromByte :: TransactionSize -> Byte -> BusVal busValFromByte size val = case size of SizeByte -> BusByte val SizeHalfWord -> BusHalfWord (resize val) SizeFullWord -> BusFullWord (resize val) SizeDoubleWord -> BusDoubleWord (resize val) SizeQuadWord -> BusQuadWord (resize val) -- Reads a character from the terminal (RBR equivalent) buildRBR :: IO Byte buildRBR = do c <- getCharFromTerminal return $ fromIntegral (ord c) -- Convert Char to Byte -- Reads the Line Status Register (LSR) to check character availability buildLSR :: IO Byte buildLSR = do char_available <- isCharAvailable return $ fromIntegral char_available -- Updated 'read' function to handle RBR and LSR reads read :: TransactionSize -> UartAddr -> IO BusVal read size addr | addr == rbrAddr = busValFromByte size <$> buildRBR | addr == lsrAddr = busValFromByte size <$> buildLSR | otherwise = return $ busValFromByte size 0x00