RiscV-Formal/hs/Peripherals/Uart.hs

62 lines
1.7 KiB
Haskell

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