module System.PIO.Linux.SPI.Raw (
SPIMode(..),
Bits,
Speed,
transferTxRx1,
transferTxRx2,
transferTx,
transferRx,
getMode,
setMode,
getLsbFirst,
setLsbFirst,
getBitsPerWord,
setBitsPerWord,
getMaxSpeedHz,
setMaxSpeedHz,
) where
import Foreign.Ptr(Ptr)
import Data.Word(Word8,Word16,Word32)
import System.PIO.Linux(FileDescriptor)
import Foreign.Marshal.Alloc(alloca)
import Foreign.Storable(peek)
import Foreign.C.Error(throwErrno)
type Bits = Word8
type Speed = Word32
type Delay = Word16
type CSChange = Bool
foreign import ccall "spi_mode_0" spi_mode0 :: Word8
foreign import ccall "spi_mode_1" spi_mode1 :: Word8
foreign import ccall "spi_mode_2" spi_mode2 :: Word8
foreign import ccall "spi_mode_3" spi_mode3 :: Word8
foreign import ccall "spi_transfer_tx_rx_1" spi_transfer_tx_rx_1
:: Int -> Ptr a -> Int -> Word8 -> Word32 -> Word16 -> Word8 -> IO Int
foreign import ccall "spi_transfer_tx_rx_2" spi_transfer_tx_rx_2
:: Int -> Ptr a -> Int -> Ptr a -> Int -> Word8 -> Word32 -> Word16 -> Word8 -> IO Int
foreign import ccall "spi_transfer_tx_1" spi_transfer_tx_1
:: Int -> Ptr a -> Int -> Word8 -> Word32 -> Word16 -> Word8 -> IO Int
foreign import ccall "spi_transfer_rx_1" spi_transfer_rx_1
:: Int -> Ptr a -> Int -> Word8 -> Word32 -> Word16 -> Word8 -> IO Int
foreign import ccall "spi_get_mode" spi_get_mode :: Int -> Ptr Word8 -> IO Int
foreign import ccall "spi_set_mode" spi_set_mode :: Int -> Word8 -> IO Int
foreign import ccall "spi_get_lsb_first" spi_get_lsb_first :: Int -> Ptr Word8 -> IO Int
foreign import ccall "spi_set_lsb_first" spi_set_lsb_first :: Int -> Word8 -> IO Int
foreign import ccall "spi_get_bits_per_word" spi_get_bits_per_word :: Int -> Ptr Word8 -> IO Int
foreign import ccall "spi_set_bits_per_word" spi_set_bits_per_word :: Int -> Word8 -> IO Int
foreign import ccall "spi_get_max_speed_hz" spi_get_max_speed_hz :: Int -> Ptr Word32 -> IO Int
foreign import ccall "spi_set_max_speed_hz" spi_set_max_speed_hz :: Int -> Word32 -> IO Int
data SPIMode = Mode0
| Mode1
| Mode2
| Mode3
instance Enum SPIMode where
toEnum n | (fromIntegral n) == spi_mode0 = Mode0
| (fromIntegral n) == spi_mode1 = Mode1
| (fromIntegral n) == spi_mode2 = Mode2
| (fromIntegral n) == spi_mode3 = Mode3
| otherwise = error "toEnum: convert error"
fromEnum Mode0 = (fromIntegral spi_mode0)
fromEnum Mode1 = (fromIntegral spi_mode1)
fromEnum Mode2 = (fromIntegral spi_mode2)
fromEnum Mode3 = (fromIntegral spi_mode3)
transferTxRx1 :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
transferTxRx1 fd buf bufLen bits speed delay csChange =
spi_transfer_tx_rx_1 fd buf bufLen bits speed delay (fromIntegral $ fromEnum csChange)
>>= \rc -> case rc of
1 -> throwErrno "transferTxRx1"
otherwize -> return ()
transferTxRx2 :: FileDescriptor -> Ptr a -> Int -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
transferTxRx2 fd txBuf txBufLen rxBuf rxBufLen bits speed delay csChange =
spi_transfer_tx_rx_2 fd txBuf txBufLen rxBuf rxBufLen bits speed delay (fromIntegral $ fromEnum csChange)
>>= \rc -> case rc of
1 -> throwErrno "transferTxRx2"
otherwize -> return ()
transferTx :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
transferTx fd buf bufLen bits speed delay csChange =
spi_transfer_tx_1 fd buf bufLen bits speed delay (fromIntegral $ fromEnum csChange)
>>= \rc -> case rc of
1 -> throwErrno "transferTx"
otherwize -> return ()
transferRx :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
transferRx fd buf bufLen bits speed delay csChange =
spi_transfer_rx_1 fd buf bufLen bits speed delay (fromIntegral $ fromEnum csChange)
>>= \rc -> case rc of
1 -> throwErrno "transferRx"
otherwize -> return ()
getMode :: FileDescriptor -> IO SPIMode
getMode fd = alloca $
\p -> spi_get_mode fd p >>= \rc -> case rc of
1 -> throwErrno "getMode"
otherwize -> do
mode <- peek p
return $ toEnum $ fromIntegral mode
setMode :: FileDescriptor -> SPIMode -> IO ()
setMode fd mode =
spi_set_mode fd (fromIntegral $ fromEnum mode)
>>= \rc -> case rc of
1 -> throwErrno "setMode"
otherwize -> return ()
getLsbFirst :: FileDescriptor -> IO Bool
getLsbFirst fd = alloca $
\p -> spi_get_lsb_first fd p >>= \rc -> case rc of
1 -> throwErrno "getLsbFirst"
otherwize -> do
flag <- peek p
return $ toEnum $ fromIntegral flag
setLsbFirst :: FileDescriptor -> Bool -> IO ()
setLsbFirst fd flag =
spi_set_lsb_first fd (fromIntegral $ fromEnum flag)
>>= \rc -> case rc of
1 -> throwErrno "setLsbFirst"
otherwize -> return ()
getBitsPerWord :: FileDescriptor -> IO Bits
getBitsPerWord fd = alloca $
\p -> spi_get_bits_per_word fd p >>= \rc -> case rc of
1 -> throwErrno "getBitsPerWord"
otherwize -> peek p
setBitsPerWord :: FileDescriptor -> Bits -> IO ()
setBitsPerWord fd bits = spi_set_bits_per_word fd bits
>>= \rc -> case rc of
1 -> throwErrno "setBitsPerWord"
otherwize -> return ()
getMaxSpeedHz :: FileDescriptor -> IO Speed
getMaxSpeedHz fd = alloca $
\p -> spi_get_max_speed_hz fd p >>= \rc -> case rc of
1 -> throwErrno "getMaxSpeedHz"
otherwize -> peek p
setMaxSpeedHz :: FileDescriptor -> Speed -> IO ()
setMaxSpeedHz fd speed = spi_set_max_speed_hz fd speed
>>= \rc -> case rc of
1 -> throwErrno "setMaxSpeedHz"
otherwize -> return ()