huckleberry 0.9.1.1 → 0.10.0.0
raw patch · 13 files changed
+430/−104 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- System.PIO.Linux: oRdOnly :: Int
- System.PIO.Linux: oRdWr :: Int
- System.PIO.Linux: oWrOnly :: Int
- System.PIO.Linux.I2C: setSlave :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: mode0 :: Word8
- System.PIO.Linux.SPI: mode1 :: Word8
- System.PIO.Linux.SPI: mode2 :: Word8
- System.PIO.Linux.SPI: mode3 :: Word8
- System.PIO.Linux.SPI: setRdBitsPerWord :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: setRdLbsFirst :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: setRdMaxSpeedHz :: Int -> Word32 -> IO Int
- System.PIO.Linux.SPI: setRdMode :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: setWrBitsPerWord :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: setWrLbsFirst :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: setWrMaxSpeedHz :: Int -> Word32 -> IO Int
- System.PIO.Linux.SPI: setWrMode :: Int -> Word8 -> IO Int
- System.PIO.Linux.SPI: transferMessage1 :: Int -> Ptr a -> Int -> Word32 -> Word8 -> IO Int
+ System.PIO.Linux: ReadMode :: IOMode
+ System.PIO.Linux: ReadWriteMode :: IOMode
+ System.PIO.Linux: WriteMode :: IOMode
+ System.PIO.Linux: data IOMode
+ System.PIO.Linux: instance GHC.Enum.Enum System.PIO.Linux.IOMode
+ System.PIO.Linux: type FileDescriptor = Int
+ System.PIO.Linux: type FilePath = String
+ System.PIO.Linux.GPIO: type PinNumber = Int
+ System.PIO.Linux.I2C.Raw: setSlave :: FileDescriptor -> SlaveAddress -> IO ()
+ System.PIO.Linux.I2C.Raw: type SlaveAddress = Word8
+ System.PIO.Linux.PWM: type Channel = Int
+ System.PIO.Linux.PWM: type DutyCycle = Int
+ System.PIO.Linux.PWM: type Period = Int
+ System.PIO.Linux.SPI.Raw: Mode0 :: SPIMode
+ System.PIO.Linux.SPI.Raw: Mode1 :: SPIMode
+ System.PIO.Linux.SPI.Raw: Mode2 :: SPIMode
+ System.PIO.Linux.SPI.Raw: Mode3 :: SPIMode
+ System.PIO.Linux.SPI.Raw: data SPIMode
+ System.PIO.Linux.SPI.Raw: getBitsPerWord :: FileDescriptor -> IO Bits
+ System.PIO.Linux.SPI.Raw: getLsbFirst :: FileDescriptor -> IO Bool
+ System.PIO.Linux.SPI.Raw: getMaxSpeedHz :: FileDescriptor -> IO Speed
+ System.PIO.Linux.SPI.Raw: getMode :: FileDescriptor -> IO SPIMode
+ System.PIO.Linux.SPI.Raw: instance GHC.Enum.Enum System.PIO.Linux.SPI.Raw.SPIMode
+ System.PIO.Linux.SPI.Raw: setBitsPerWord :: FileDescriptor -> Bits -> IO ()
+ System.PIO.Linux.SPI.Raw: setLsbFirst :: FileDescriptor -> Bool -> IO ()
+ System.PIO.Linux.SPI.Raw: setMaxSpeedHz :: FileDescriptor -> Speed -> IO ()
+ System.PIO.Linux.SPI.Raw: setMode :: FileDescriptor -> SPIMode -> IO ()
+ System.PIO.Linux.SPI.Raw: transferRx :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
+ System.PIO.Linux.SPI.Raw: transferTx :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
+ System.PIO.Linux.SPI.Raw: transferTxRx1 :: FileDescriptor -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
+ System.PIO.Linux.SPI.Raw: transferTxRx2 :: FileDescriptor -> Ptr a -> Int -> Ptr a -> Int -> Bits -> Speed -> Delay -> CSChange -> IO ()
+ System.PIO.Linux.SPI.Raw: type Bits = Word8
+ System.PIO.Linux.SPI.Raw: type Speed = Word32
- System.PIO.Linux: fdClose :: Int -> IO Int
+ System.PIO.Linux: fdClose :: FileDescriptor -> IO ()
- System.PIO.Linux: fdGetBuf :: Int -> Ptr a -> Int -> IO Int
+ System.PIO.Linux: fdGetBuf :: FileDescriptor -> Ptr a -> Int -> IO ()
- System.PIO.Linux: fdOpen :: String -> Int -> IO Int
+ System.PIO.Linux: fdOpen :: FilePath -> IOMode -> IO FileDescriptor
- System.PIO.Linux: fdPutBuf :: Int -> Ptr a -> Int -> IO Int
+ System.PIO.Linux: fdPutBuf :: FileDescriptor -> Ptr a -> Int -> IO ()
- System.PIO.Linux.GPIO: getValue :: Int -> IO Bool
+ System.PIO.Linux.GPIO: getValue :: PinNumber -> IO Bool
- System.PIO.Linux.GPIO: setValue :: Int -> Bool -> IO ()
+ System.PIO.Linux.GPIO: setValue :: PinNumber -> Bool -> IO ()
- System.PIO.Linux.PWM: getEnable :: Int -> IO Bool
+ System.PIO.Linux.PWM: getEnable :: Channel -> IO Bool
- System.PIO.Linux.PWM: getValue :: Int -> IO (Int, Int)
+ System.PIO.Linux.PWM: getValue :: Channel -> IO (Period, DutyCycle)
- System.PIO.Linux.PWM: setEnable :: Int -> Bool -> IO ()
+ System.PIO.Linux.PWM: setEnable :: Channel -> Bool -> IO ()
- System.PIO.Linux.PWM: setValue :: Int -> Int -> Int -> IO ()
+ System.PIO.Linux.PWM: setValue :: Channel -> Period -> DutyCycle -> IO ()
Files
- cbits/hs_i2c.c +0/−1
- cbits/hs_spi.c +84/−24
- huckleberry.cabal +3/−1
- include/hs_fcntl.h +0/−2
- include/hs_spi.h +15/−11
- src/System/PIO.hs +4/−0
- src/System/PIO/Linux.hs +69/−16
- src/System/PIO/Linux/GPIO.hs +9/−3
- src/System/PIO/Linux/I2C.hs +1/−6
- src/System/PIO/Linux/I2C/Raw.hs +23/−0
- src/System/PIO/Linux/PWM.hs +21/−4
- src/System/PIO/Linux/SPI.hs +1/−36
- src/System/PIO/Linux/SPI/Raw.hs +200/−0
cbits/hs_i2c.c view
@@ -1,7 +1,6 @@ #include "hs_i2c.h" #include <sys/ioctl.h>-#include <linux/types.h> #include <linux/i2c-dev.h>
cbits/hs_spi.c view
@@ -1,8 +1,8 @@ #include "hs_spi.h" #include <sys/ioctl.h>-#include <linux/types.h> #include <linux/spi/spidev.h>+#include <string.h> unsigned char spi_mode_0() {@@ -19,45 +19,105 @@ } -int spi_transfer_message_1(int fd, void* buff, __u32 buff_len, __u32 speed, __u8 bits) { - struct spi_ioc_transfer spi;- spi.tx_buf = (__u64) buff;- spi.rx_buf = (__u64) buff;- spi.len = buff_len;- spi.speed_hz = speed;- spi.bits_per_word = bits;- spi.delay_usecs = 0;- spi.cs_change = 0;+int spi_transfer_tx_rx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change) { - return ioctl(fd,SPI_IOC_MESSAGE(1),&spi);+ struct spi_ioc_transfer tran;+ memset(&tran,0,sizeof(struct spi_ioc_transfer));+ + tran.tx_buf = (__u64) buff;+ tran.rx_buf = (__u64) buff;+ tran.len = buff_len;+ tran.bits_per_word = bits;+ tran.speed_hz = speed;+ tran.delay_usecs = delay;+ tran.cs_change = cs_change;++ return ioctl(fd,SPI_IOC_MESSAGE(1),&tran);+ }+int spi_transfer_tx_rx_2(int fd,+ void *tx_buff, __u32 tx_buff_len,+ void *rx_buff, __u32 rx_buff_len,+ __u8 bits, __u32 speed, __u16 delay, __u8 cs_change) { -int spi_set_rd_mode(int fd, __u8 mode) {- return ioctl(fd,SPI_IOC_RD_MODE,&mode);+ struct spi_ioc_transfer tran[2];+ memset(tran,0,sizeof(tran));+ + tran[0].tx_buf = (__u64) tx_buff;+ tran[0].len = tx_buff_len;+ tran[0].bits_per_word = bits;+ tran[0].speed_hz = speed;+ tran[0].delay_usecs = delay;+ tran[0].cs_change = cs_change;++ tran[1].rx_buf = (__u64) rx_buff;+ tran[1].len = rx_buff_len;+ tran[1].bits_per_word = bits;+ tran[1].speed_hz = speed;+ tran[1].delay_usecs = delay;+ tran[1].cs_change = cs_change;++ return ioctl(fd,SPI_IOC_MESSAGE(2),tran);+ }-int spi_set_wr_mode(int fd, __u8 mode) {+int spi_transfer_tx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change) {+ + struct spi_ioc_transfer tran;+ memset(&tran,0,sizeof(struct spi_ioc_transfer));+ + tran.tx_buf = (__u64) buff;+ tran.len = buff_len;+ tran.bits_per_word = bits;+ tran.speed_hz = speed;+ tran.delay_usecs = delay;+ tran.cs_change = cs_change;++ return ioctl(fd,SPI_IOC_MESSAGE(1),&tran);++}+int spi_transfer_rx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change) {+ + struct spi_ioc_transfer tran;+ memset(&tran,0,sizeof(struct spi_ioc_transfer));+ + tran.rx_buf = (__u64) buff;+ tran.len = buff_len;+ tran.bits_per_word = bits;+ tran.speed_hz = speed;+ tran.delay_usecs = delay;+ tran.cs_change = cs_change;++ return ioctl(fd,SPI_IOC_MESSAGE(1),&tran);++}+++int spi_get_mode(int fd, __u8 *pmode) {+ return ioctl(fd,SPI_IOC_RD_MODE,pmode);+}+int spi_set_mode(int fd, __u8 mode) { return ioctl(fd,SPI_IOC_WR_MODE,&mode); } -int spi_set_rd_lbs_first(int fd, __u8 lbs) {- return ioctl(fd,SPI_IOC_RD_LSB_FIRST,&lbs);+int spi_get_lsb_first(int fd, __u8 *plsb) {+ return ioctl(fd,SPI_IOC_RD_LSB_FIRST,plsb); }-int spi_set_wr_lbs_first(int fd, __u8 lbs) {- return ioctl(fd,SPI_IOC_WR_LSB_FIRST,&lbs);+int spi_set_lsb_first(int fd, __u8 lsb) {+ return ioctl(fd,SPI_IOC_WR_LSB_FIRST,&lsb); } -int spi_set_rd_bits_per_word(int fd, __u8 bits) {- return ioctl(fd,SPI_IOC_RD_BITS_PER_WORD,&bits);+int spi_get_bits_per_word(int fd, __u8 *pbits) {+ return ioctl(fd,SPI_IOC_RD_BITS_PER_WORD,pbits); }-int spi_set_wr_bits_per_word(int fd, __u8 bits) {+int spi_set_bits_per_word(int fd, __u8 bits) { return ioctl(fd,SPI_IOC_WR_BITS_PER_WORD,&bits); } -int spi_set_rd_max_speed_hz(int fd, __u32 speed) {- return ioctl(fd,SPI_IOC_RD_MAX_SPEED_HZ,&speed);+int spi_get_max_speed_hz(int fd, __u32 *pspeed) {+ return ioctl(fd,SPI_IOC_RD_MAX_SPEED_HZ,pspeed); }-int spi_set_wr_max_speed_hz(int fd, __u32 speed) {+int spi_set_max_speed_hz(int fd, __u32 speed) { return ioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,&speed); }
huckleberry.cabal view
@@ -1,5 +1,5 @@ name: huckleberry-version: 0.9.1.1+version: 0.10.0.0 synopsis: Haskell IOT on Intel Edison and other Linux computers. description: Please see README.md homepage: https://github.com/mitsuji/huckleberry#readme@@ -24,6 +24,8 @@ , System.PIO.Linux.PWM , System.PIO.Linux.I2C , System.PIO.Linux.SPI+ , System.PIO.Linux.I2C.Raw+ , System.PIO.Linux.SPI.Raw build-depends: base >= 4.7 && < 5 default-language: Haskell2010 c-sources: cbits/hs_fcntl.c
include/hs_fcntl.h view
@@ -1,8 +1,6 @@ #ifndef HS_FCNTL_H #define HS_FCNTL_H -#include <linux/types.h>- int o_rdonly(); int o_wronly(); int o_rdwr();
include/hs_spi.h view
@@ -2,27 +2,31 @@ #define HS_SPI_H #include <linux/types.h>-#include <stddef.h>-#include <stdio.h> unsigned char spi_mode_0(); unsigned char spi_mode_1(); unsigned char spi_mode_2(); unsigned char spi_mode_3(); -int spi_transfer_message_1(int fd, void* buff, __u32 buff_len, __u32 speed, __u8 bits);+int spi_transfer_tx_rx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change);+int spi_transfer_tx_rx_2(int fd,+ void *tx_buff, __u32 tx_buff_len,+ void *rx_buff, __u32 rx_buff_len,+ __u8 bits, __u32 speed, __u16 delay, __u8 cs_change);+int spi_transfer_tx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change);+int spi_transfer_rx_1(int fd, void *buff, __u32 buff_len, __u8 bits, __u32 speed, __u16 delay, __u8 cs_change); -int spi_set_rd_mode(int fd, __u8 mode);-int spi_set_wr_mode(int fd, __u8 mode);+int spi_get_mode(int fd, __u8 *pmode);+int spi_set_mode(int fd, __u8 mode); -int spi_set_rd_lbs_first(int fd, __u8 lbs);-int spi_set_wr_lbs_first(int fd, __u8 lbs);+int spi_get_lsb_first(int fd, __u8 *plsb);+int spi_set_lsb_first(int fd, __u8 lsb); -int spi_set_rd_bits_per_word(int fd, __u8 bits);-int spi_set_wr_bits_per_word(int fd, __u8 bits);+int spi_get_bits_per_word(int fd, __u8 *pbits);+int spi_set_bits_per_word(int fd, __u8 bits); -int spi_set_rd_max_speed_hz(int fd, __u32 speed);-int spi_set_wr_max_speed_hz(int fd, __u32 speed);+int spi_get_max_speed_hz(int fd, __u32 *pspeed);+int spi_set_max_speed_hz(int fd, __u32 speed); #endif
src/System/PIO.hs view
@@ -14,18 +14,22 @@ f2 '1' = 1 +-- | an unsigned number in binary notation. binToNum :: (Eq a, Num a) => String -> a binToNum s = case readBin s of (x,""):_ -> x _ -> error "binToNum: parse error" +-- | an unsigned number in octal notation. octToNum :: (Eq a, Num a) => String -> a octToNum s = case readOct s of (x,""):_ -> x _ -> error "octToNum: parse error" +-- | an unsigned number in hexadecimal notation.+-- Both upper or lower case letters are allowed. hexToNum :: (Eq a, Num a) => String -> a hexToNum s = case readHex s of (x,""):_ -> x
src/System/PIO/Linux.hs view
@@ -1,29 +1,82 @@ {-# LANGUAGE ForeignFunctionInterface #-} module System.PIO.Linux (+ FilePath,+ FileDescriptor,+ IOMode(..), fdOpen, fdClose, fdPutBuf, fdGetBuf,- oRdOnly,- oWrOnly,- oRdWr ) where import Foreign.Ptr(Ptr) import Foreign.C.String(CString,withCString)- -foreign import ccall "open" open :: CString -> Int -> IO Int-foreign import ccall "close" fdClose :: Int -> IO Int- -foreign import ccall "write" fdPutBuf :: Int -> Ptr a -> Int -> IO Int-foreign import ccall "read" fdGetBuf :: Int -> Ptr a -> Int -> IO Int- -foreign import ccall "o_rdonly" oRdOnly :: Int-foreign import ccall "o_wronly" oWrOnly :: Int-foreign import ccall "o_rdwr" oRdWr :: Int+import Prelude hiding (FilePath)+import Foreign.C.Error(throwErrno)++-- | File and directory names are values of type String+type FilePath = String++-- | File descriptor numbers are values of type Int+type FileDescriptor = Int+ ++foreign import ccall "o_rdonly" o_rdonly :: Int+foreign import ccall "o_wronly" o_wronly :: Int+foreign import ccall "o_rdwr" o_rdwr :: Int -fdOpen :: String -> Int -> IO Int-fdOpen path flags = withCString path $ \cs -> open cs flags- +foreign import ccall "open" linux_open :: CString -> Int -> IO Int+foreign import ccall "close" linux_close :: Int -> IO Int+foreign import ccall "write" linux_write :: Int -> Ptr a -> Int -> IO Int+foreign import ccall "read" linux_read :: Int -> Ptr a -> Int -> IO Int++ +data IOMode = ReadMode+ | WriteMode+ | ReadWriteMode+ +instance Enum IOMode where+ + toEnum n | n == o_rdonly = ReadMode+ | n == o_wronly = WriteMode+ | n == o_rdwr = ReadWriteMode+ | otherwise = error "toEnum: convert error"++ fromEnum ReadMode = o_rdonly+ fromEnum WriteMode = o_wronly+ fromEnum ReadWriteMode = o_rdwr++++-- | Computation 'fdOpen' @file@ @mode@ allocates and returns a new, open+-- descriptor to manage the file @file@. It manages input if @mode@+-- is 'ReadMode', output if @mode@ is 'WriteMode',+-- and both input and output if mode is 'ReadWriteMode'.+fdOpen :: FilePath -> IOMode -> IO FileDescriptor+fdOpen path mode = withCString path $+ \cpath -> linux_open cpath (fromEnum mode) >>= \fd -> case fd of+ -1 -> throwErrno "fdOpen"+ otherwise -> return fd++-- | Computation 'fdClose' @fd@ makes descriptor @fd@ closed.+fdClose :: FileDescriptor -> IO ()+fdClose fd = linux_close fd >>= \rc -> case rc of+ -1 -> throwErrno "fdClose"+ otherwise -> return ()++-- | 'fdPutBuf' @fd@ @buf@ @count@ writes @count@ 8-bit bytes from the+-- buffer @buf@ to the descriptor @fd@.+fdPutBuf :: FileDescriptor -> Ptr a -> Int -> IO ()+fdPutBuf fd buf bufLen = linux_write fd buf bufLen >>= \rc -> case rc of+ -1 -> throwErrno "fdPutBuf"+ otherwise -> return ()++-- | 'fdGetBuf' @fd@ @buf@ @count@ reads data from the descriptor @fd@+-- into the buffer @buf@ until either EOF is reached or+-- @count@ 8-bit bytes have been read.+fdGetBuf :: FileDescriptor -> Ptr a -> Int -> IO ()+fdGetBuf fd buf bufLen = linux_read fd buf bufLen >>= \rc -> case rc of+ -1 -> throwErrno "fdGetBuf"+ otherwise -> return ()
src/System/PIO/Linux/GPIO.hs view
@@ -1,21 +1,27 @@ module System.PIO.Linux.GPIO (+ PinNumber, setValue, getValue ) where import System.IO (writeFile, readFile) - +-- | GPIO pin numbers are values of type Int+type PinNumber = Int+ valueFilePath :: Int -> String valueFilePath n = "/sys/class/gpio/gpio" ++ (show n) ++ "/value" -setValue :: Int -> Bool -> IO ()+-- | Computation 'setValue' @pinnum@ @True@ makes corresponding pin high.+-- Computation 'setValue' @pinnum@ @False@ makes corresponding pin low.+setValue :: PinNumber -> Bool -> IO () setValue n flag = writeFile (valueFilePath n) $ show $ fromEnum flag -getValue :: Int -> IO Bool+-- | Computation 'getValue' @pinnum@ obtain status of corresponding pin.+getValue :: PinNumber -> IO Bool getValue n = (\flag -> toEnum $ read flag) <$> readFile (valueFilePath n)
src/System/PIO/Linux/I2C.hs view
@@ -1,10 +1,5 @@-{-# LANGUAGE ForeignFunctionInterface #-} + module System.PIO.Linux.I2C (- setSlave ) where--import Data.Word(Word8)--foreign import ccall "i2c_set_slave" setSlave :: Int -> Word8 -> IO Int
+ src/System/PIO/Linux/I2C/Raw.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE ForeignFunctionInterface #-}++module System.PIO.Linux.I2C.Raw (+ SlaveAddress,+ setSlave+ ) where++import Data.Word(Word8)+import System.PIO.Linux(FileDescriptor)+import Foreign.C.Error(throwErrno)++type SlaveAddress = Word8++foreign import ccall "i2c_set_slave" i2c_set_slave :: Int -> Word8 -> IO Int+++-- | Computation 'setSlave' @fd@ @address@ sets the slave address for+-- descriptor @fd@ on I2C.+setSlave :: FileDescriptor -> SlaveAddress -> IO ()+setSlave fd addr = i2c_set_slave fd addr >>= \rc -> case rc of+ -1 -> throwErrno "setSlave"+ otherwize -> return ()+
src/System/PIO/Linux/PWM.hs view
@@ -1,4 +1,7 @@ module System.PIO.Linux.PWM (+ Channel,+ Period,+ DutyCycle, setEnable, getEnable, setValue,@@ -7,7 +10,16 @@ import System.IO (writeFile, readFile) +-- | PWM channel numbers are values of type Int+type Channel = Int +-- | PWM period is a value of type Int+type Period = Int++-- | PWM duty cycle is a value of type Int+type DutyCycle = Int++ interfaceFilePath :: Int -> String -> String interfaceFilePath n file = "/sys/class/pwm/pwmchip0/pwm" ++ (show n) ++ file @@ -21,17 +33,21 @@ dutyCycleFilePath n = interfaceFilePath n "/duty_cycle" -setEnable :: Int -> Bool -> IO ()+-- | Computation 'setEnable' @channel@ @True@ makes corresponding PWM channel enabled.+-- Computation 'setEnable' @channel@ @False@ makes corresponding PWM channel disabled.+setEnable :: Channel -> Bool -> IO () setEnable n flag = writeFile (enableFilePath n) $ show $ fromEnum flag -getEnable :: Int -> IO Bool+-- | Computation 'getEnable' @channel@ obtain status of corresponding PWM channel.+getEnable :: Channel -> IO Bool getEnable n = (\flag -> toEnum $ read flag) <$> readFile (enableFilePath n) -setValue :: Int -> Int -> Int -> IO ()+-- | 'setValue' @channel@ @period@ @dutyCycle@ generates PWM signal on corresponding PWM channel. @period@ and @dutyCycle@ are value of nanoseconds.+setValue :: Channel -> Period -> DutyCycle -> IO () setValue n period dutyCycle = do let dutyCycleFilePath' = dutyCycleFilePath n writeFile dutyCycleFilePath' $ show 0@@ -39,7 +55,8 @@ writeFile dutyCycleFilePath' $ show dutyCycle -getValue :: Int -> IO (Int, Int)+-- | 'getValue' @channel@ obtain status of current PWM signal on corresponding PWM channel.+getValue :: Channel -> IO (Period, DutyCycle) getValue n = (\p dc -> (read p, read dc)) <$> readFile (periodFilePath n) <*> readFile (dutyCycleFilePath n)
src/System/PIO/Linux/SPI.hs view
@@ -1,40 +1,5 @@-{-# LANGUAGE ForeignFunctionInterface #-} + module System.PIO.Linux.SPI (- mode0,- mode1,- mode2,- mode3,- transferMessage1,- setRdMode,- setWrMode,- setRdLbsFirst,- setWrLbsFirst,- setRdBitsPerWord,- setWrBitsPerWord,- setRdMaxSpeedHz,- setWrMaxSpeedHz, ) where--import Foreign.Ptr(Ptr)-import Data.Word(Word8,Word32)--foreign import ccall "spi_mode_0" mode0 :: Word8-foreign import ccall "spi_mode_1" mode1 :: Word8-foreign import ccall "spi_mode_2" mode2 :: Word8-foreign import ccall "spi_mode_3" mode3 :: Word8--foreign import ccall "spi_transfer_message_1" transferMessage1 :: Int -> Ptr a -> Int -> Word32 -> Word8 -> IO Int--foreign import ccall "spi_set_rd_mode" setRdMode :: Int -> Word8 -> IO Int-foreign import ccall "spi_set_wr_mode" setWrMode :: Int -> Word8 -> IO Int--foreign import ccall "spi_set_rd_lbs_first" setRdLbsFirst :: Int -> Word8 -> IO Int-foreign import ccall "spi_set_wr_lbs_first" setWrLbsFirst :: Int -> Word8 -> IO Int--foreign import ccall "spi_set_rd_bits_per_word" setRdBitsPerWord :: Int -> Word8 -> IO Int-foreign import ccall "spi_set_wr_bits_per_word" setWrBitsPerWord :: Int -> Word8 -> IO Int--foreign import ccall "spi_set_rd_max_speed_hz" setRdMaxSpeedHz :: Int -> Word32 -> IO Int-foreign import ccall "spi_set_wr_max_speed_hz" setWrMaxSpeedHz :: Int -> Word32 -> IO Int
+ src/System/PIO/Linux/SPI/Raw.hs view
@@ -0,0 +1,200 @@+{-# LANGUAGE ForeignFunctionInterface #-}++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' @fd@ @buf@ @count@ @bits@ @speed@ @delay@ @csChange@ transfer @count@ 8-bit bytes from the+-- buffer @buf@ to the descriptor @fd@.+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 ()++++-- | Computation 'getMode' @fd@ gets the spi mode for+-- descriptor @fd@.+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+++-- | Computation 'setMode' @fd@ @mode@ sets the spi mode for+-- descriptor @fd@.+setMode :: FileDescriptor -> SPIMode -> IO ()+setMode fd mode =+ spi_set_mode fd (fromIntegral $ fromEnum mode)+ >>= \rc -> case rc of+ -1 -> throwErrno "setMode"+ otherwize -> return ()+++-- | Computation 'getLsbFirst' @fd@ gets the LBS-first flag for+-- descriptor @fd@.+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+++-- | Computation 'setLsbFirst' @fd@ @flag@ sets the LBS-first flag for+-- descriptor @fd@.+setLsbFirst :: FileDescriptor -> Bool -> IO ()+setLsbFirst fd flag =+ spi_set_lsb_first fd (fromIntegral $ fromEnum flag)+ >>= \rc -> case rc of+ -1 -> throwErrno "setLsbFirst"+ otherwize -> return ()+++-- | Computation 'getBitsPerWord' @fd@ gets the number+-- of bits in each SPI transfer word for+-- descriptor @fd@.+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+++-- | Computation 'setBitsPerWord' @fd@ @bits@ sets the number+-- of bits in each SPI transfer word for+-- descriptor @fd@.+setBitsPerWord :: FileDescriptor -> Bits -> IO ()+setBitsPerWord fd bits = spi_set_bits_per_word fd bits+ >>= \rc -> case rc of+ -1 -> throwErrno "setBitsPerWord"+ otherwize -> return ()+++-- | Computation 'getMaxSpeedHz' @fd@ gets the maximum+-- SPI transfer speed, in Hz for+-- descriptor @fd@.+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+++-- | Computation 'setMaxSpeedHz' @fd@ @speed@ sets the maximum+-- SPI transfer speed, in Hz for+-- descriptor @fd@.+setMaxSpeedHz :: FileDescriptor -> Speed -> IO ()+setMaxSpeedHz fd speed = spi_set_max_speed_hz fd speed+ >>= \rc -> case rc of+ -1 -> throwErrno "setMaxSpeedHz"+ otherwize -> return ()++