forked from Yehowshua/RiscV-Formal
78 lines
2.3 KiB
Haskell
78 lines
2.3 KiB
Haskell
module Peripherals.Uart (read, write, UartAddr) where
|
|
|
|
import Clash.Prelude hiding (read)
|
|
import Types (Byte)
|
|
import Data.Char (ord, chr)
|
|
|
|
import Peripherals.UartCFFI (
|
|
getCharFromTerminal,
|
|
writeCharToTerminal,
|
|
isCharAvailable,
|
|
)
|
|
|
|
import BusTypes (
|
|
TransactionSize(..),
|
|
BusVal(..),
|
|
)
|
|
import Util((|>))
|
|
|
|
-- 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
|
|
|
|
thrAddr :: UartAddr
|
|
thrAddr = 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 :: Byte) <- fmap fromIntegral isCharAvailable
|
|
-- highly unlikely that we overflow stdout buffer, so we set
|
|
-- transmit to always ready
|
|
let (transmit_ready :: Byte) = 0b0010_0000
|
|
return (char_available .|. transmit_ready)
|
|
|
|
-- Updated 'read' function to handle RBR and LSR reads
|
|
read :: TransactionSize -> UartAddr -> IO BusVal
|
|
read size addr
|
|
| addr == rbrAddr = fmap (busValFromByte size) buildRBR
|
|
| addr == lsrAddr = fmap (busValFromByte size) buildLSR
|
|
| otherwise = return |> busValFromByte size 0x00
|
|
|
|
extractLowestByte :: BusVal -> Byte
|
|
extractLowestByte (BusByte b) = b
|
|
extractLowestByte (BusHalfWord hw) = resize hw
|
|
extractLowestByte (BusFullWord fw) = resize fw
|
|
extractLowestByte (BusDoubleWord dw) = resize dw
|
|
extractLowestByte (BusQuadWord qw) = resize qw
|
|
|
|
byteToChar :: Byte -> Char
|
|
byteToChar = chr . fromIntegral
|
|
|
|
write :: BusVal -> UartAddr -> IO ()
|
|
write val addr
|
|
| addr == thrAddr = writeCharToTerminal |> byteToChar |> extractLowestByte val
|
|
| otherwise = return ()
|