bus-pirate 0.5 → 0.6
raw patch · 5 files changed
+143/−32 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- System.Hardware.BusPirate.I2C: I2cConfig :: Bool -> Bool -> Bool -> Bool -> I2cConfig
- System.Hardware.BusPirate.I2C: data I2cConfig
- System.Hardware.BusPirate.I2C: i2cAux :: I2cConfig -> Bool
- System.Hardware.BusPirate.I2C: i2cChipSelect :: I2cConfig -> Bool
- System.Hardware.BusPirate.I2C: i2cPower :: I2cConfig -> Bool
- System.Hardware.BusPirate.I2C: i2cPullups :: I2cConfig -> Bool
- System.Hardware.BusPirate.I2C: instance Show I2cConfig
- System.Hardware.BusPirate.I2C: writeRead :: ByteString -> Int -> I2cM ByteString
+ System.Hardware.BusPirate: runI2c :: FilePath -> I2cM a -> IO (Either String a)
+ System.Hardware.BusPirate: runSpi :: FilePath -> SpiM a -> IO (Either String a)
+ System.Hardware.BusPirate.I2C: PConfig :: Bool -> Bool -> Bool -> Bool -> PeripheralConfig
+ System.Hardware.BusPirate.I2C: data PeripheralConfig
+ System.Hardware.BusPirate.I2C: perAux :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.I2C: perChipSelect :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.I2C: perPower :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.I2C: perPullups :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.SPI: PConfig :: Bool -> Bool -> Bool -> Bool -> PeripheralConfig
+ System.Hardware.BusPirate.SPI: Spi125KHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi1MHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi250KHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi2MHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi2_6MHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi30KHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi4MHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: Spi8MHz :: SpiSpeed
+ System.Hardware.BusPirate.SPI: bulkTransfer :: ByteString -> SpiM ByteString
+ System.Hardware.BusPirate.SPI: data PeripheralConfig
+ System.Hardware.BusPirate.SPI: data SpiM a
+ System.Hardware.BusPirate.SPI: data SpiSpeed
+ System.Hardware.BusPirate.SPI: instance Applicative SpiM
+ System.Hardware.BusPirate.SPI: instance Bounded SpiSpeed
+ System.Hardware.BusPirate.SPI: instance Enum SpiSpeed
+ System.Hardware.BusPirate.SPI: instance Eq SpiSpeed
+ System.Hardware.BusPirate.SPI: instance Functor SpiM
+ System.Hardware.BusPirate.SPI: instance Monad SpiM
+ System.Hardware.BusPirate.SPI: instance MonadIO SpiM
+ System.Hardware.BusPirate.SPI: instance Ord SpiSpeed
+ System.Hardware.BusPirate.SPI: instance Show SpiSpeed
+ System.Hardware.BusPirate.SPI: perAux :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.SPI: perChipSelect :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.SPI: perPower :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.SPI: perPullups :: PeripheralConfig -> Bool
+ System.Hardware.BusPirate.SPI: setCS :: Bool -> SpiM ()
+ System.Hardware.BusPirate.SPI: setConfig :: PeripheralConfig -> SpiM ()
+ System.Hardware.BusPirate.SPI: setSpeed :: SpiSpeed -> SpiM ()
+ System.Hardware.BusPirate.SPI: spiMode :: SpiM a -> BusPirateM a
- System.Hardware.BusPirate.I2C: setConfig :: I2cConfig -> I2cM ()
+ System.Hardware.BusPirate.I2C: setConfig :: PeripheralConfig -> I2cM ()
Files
- System/Hardware/BusPirate.hs +13/−2
- System/Hardware/BusPirate/Core.hs +19/−0
- System/Hardware/BusPirate/I2C.hs +21/−29
- System/Hardware/BusPirate/SPI.hs +88/−0
- bus-pirate.cabal +2/−1
System/Hardware/BusPirate.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}- + module System.Hardware.BusPirate ( -- * General BusPirateM , runBusPirate -- * I2C mode- , module System.Hardware.BusPirate.I2C+ , runI2c+ -- * SPI mode+ , runSpi ) where import Control.Monad (replicateM)@@ -17,3 +19,12 @@ import System.Hardware.BusPirate.Core import System.Hardware.BusPirate.I2C+import System.Hardware.BusPirate.SPI++-- | Convenient way to run an I2C action+runI2c :: FilePath -> I2cM a -> IO (Either String a)+runI2c path action = runBusPirate path $ i2cMode action++-- | Convenient way to run an I2C action+runSpi :: FilePath -> SpiM a -> IO (Either String a)+runSpi path action = runBusPirate path $ spiMode action
System/Hardware/BusPirate/Core.hs view
@@ -94,3 +94,22 @@ command :: Word8 -> BusPirateM () command cmd = commandExpect cmd "\x01"++data PeripheralConfig+ = PConfig { perPower :: Bool+ , perPullups :: Bool+ , perAux :: Bool+ , perChipSelect :: Bool+ }+ deriving (Show)++setPeripherals :: PeripheralConfig -> BusPirateM ()+setPeripherals config = do+ command $ 0x40+ + bit 3 (perPower config)+ + bit 2 (perPullups config)+ + bit 1 (perAux config)+ + bit 0 (perChipSelect config)+ where+ bit n True = 2^n+ bit _ _ = 0
System/Hardware/BusPirate/I2C.hs view
@@ -11,9 +11,8 @@ , ackBit , nackBit , bulkWrite- , writeRead -- * Configuration- , I2cConfig(..)+ , PeripheralConfig(..) , setConfig , I2cSpeed(..) , setSpeed@@ -44,10 +43,13 @@ newtype I2cM a = I2cM (BusPirateM a) deriving (Functor, Applicative, Monad, MonadIO)- ++err :: String -> I2cM a+err = I2cM . BPM . left+ -- | Enter I2C mode and run given action i2cMode :: I2cM a -> BusPirateM a-i2cMode (I2cM m) = commandExpect 0x2 "I2C1" >> m+i2cMode (I2cM m) = commandExpect 0x2 "I2C1" >> m -- | Send a start bit startBit :: I2cM ()@@ -61,11 +63,11 @@ readByte :: I2cM Word8 readByte = I2cM $ putByte 0x4 >> getByte --- | Send an ACK +-- | Send an ACK ackBit :: I2cM () ackBit = I2cM $ command 0x6 --- | Send a NACK +-- | Send a NACK nackBit :: I2cM () nackBit = I2cM $ command 0x7 @@ -74,10 +76,10 @@ -- | Write some bytes bulkWrite :: ByteString -> I2cM ()-bulkWrite d +bulkWrite d | BS.null d = return () | BS.length d > 16 = I2cM $ BPM $ left "Too many bytes"- | otherwise = I2cM $ do + | otherwise = I2cM $ do command $ fromIntegral $ 0x10 + BS.length d - 1 put d acks <- replicateM (BS.length d) $ toEnum . fromIntegral <$> getByte@@ -87,41 +89,31 @@ bytes = if length nacks > 1 then "bytes" else "byte" in fail $ "Nack after "++bytes++" "++nacks'++" during bulkWrite of "++show d -data I2cConfig = I2cConfig { i2cPower :: Bool- , i2cPullups :: Bool- , i2cAux :: Bool- , i2cChipSelect :: Bool- }- deriving (Show) --- | Set Bus Pirate I2C configuration bits-setConfig :: I2cConfig -> I2cM ()-setConfig config = I2cM $ - command $ 0x40- + bit 3 (i2cPower config)- + bit 2 (i2cPullups config)- + bit 1 (i2cAux config)- + bit 0 (i2cChipSelect config)- where- bit n True = 2^n- bit _ _ = 0+-- | Set Bus Pirate peripheral configuration bits+setConfig :: PeripheralConfig -> I2cM ()+setConfig config = I2cM $ setPeripherals config +-- | I2C bus speed data I2cSpeed = I2c_5kHz | I2c_50kHz | I2c_100kHz | I2c_400kHz deriving (Show, Eq, Ord, Enum, Bounded)- + -- | Set I2C bus speed setSpeed :: I2cSpeed -> I2cM () setSpeed speed = I2cM $ command $ fromIntegral $ 0x60 + fromEnum speed -- | Send Start bit, write some bytes, then read some bytes (ACKing -- each until the last), then send a stop bit+--+-- This is very likely broken as the command structure itself appears+-- to be horribly broken, requiring a conditional read of a status byte. writeRead :: ByteString -> Int -> I2cM ByteString-writeRead send recv - | BS.length send > 0xffff = error "Too large send request"- | recv > 0xffff = error "Too large recieve request"+writeRead send recv+ | BS.length send > 0xffff = err "Too large send request"+ | recv > 0xffff = err "Too large recieve request" | otherwise = I2cM $ do putByte 0x8 putWord16 $ fromIntegral $ BS.length send
+ System/Hardware/BusPirate/SPI.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}++module System.Hardware.BusPirate.SPI+ ( -- * Types+ SpiM+ , spiMode+ -- * Bus operations+ , bulkTransfer+ , setCS+ -- * Configuration+ , PeripheralConfig(..)+ , setConfig+ , SpiSpeed(..)+ , setSpeed+ ) where++import Control.Applicative+import Control.Monad (replicateM)+import Control.Monad.IO.Class+import Control.Monad.Trans.Either+import Data.Word++import qualified Data.ByteString as BS+import Data.ByteString (ByteString)++import System.Hardware.BusPirate.Core++newtype SpiM a = SpiM (BusPirateM a)+ deriving (Functor, Applicative, Monad, MonadIO)++err :: String -> SpiM a+err = SpiM . BPM . left++-- | Enter I2C mode and run given action+spiMode :: SpiM a -> BusPirateM a+spiMode (SpiM m) = commandExpect 0x1 "SPI1" >> m++-- | Set chip select+setCS :: Bool -> SpiM ()+setCS True = SpiM $ command 0x21+setCS False = SpiM $ command 0x20++bulkTransfer :: ByteString -> SpiM ByteString+bulkTransfer d+ | BS.null d = return BS.empty+ | BS.length d > 16 = SpiM $ BPM $ left "Too many bytes"+ | otherwise = SpiM $ do+ command $ fromIntegral $ 0x10 + BS.length d - 1+ put d+ reply <- replicateM (BS.length d) $ getByte+ return $ BS.pack reply++-- | Set Bus Pirate peripheral configuration bits+setConfig :: PeripheralConfig -> SpiM ()+setConfig config = SpiM $ setPeripherals config++data SpiSpeed+ = Spi30KHz+ | Spi125KHz+ | Spi250KHz+ | Spi1MHz+ | Spi2MHz+ | Spi2_6MHz+ | Spi4MHz+ | Spi8MHz+ deriving (Show, Ord, Eq, Enum, Bounded)++-- | Set bus speed+setSpeed :: SpiSpeed -> SpiM ()+setSpeed speed = SpiM $ command $ 0x6 + fromIntegral (fromEnum speed)++-- | Write-then-read+--+-- This is very likely broken as the command structure itself appears+-- to be horribly broken, requiring a conditional read of a status byte.+writeRead :: Bool -> ByteString -> Word16 -> SpiM ByteString+writeRead toggleCS write readLen+ | readLen >= 4096 = err "Read length too long"+ | BS.length write >= 4096 = err "Write length too long"+ | otherwise = SpiM $ do+ putByte $ if toggleCS then 0x4 else 0x5+ putWord16 $ fromIntegral $ BS.length write+ putWord16 readLen+ status <- getByte+ case status of+ 0 -> BPM $ left "Data too long"+ 1 -> do put write+ get (fromIntegral readLen)
bus-pirate.cabal view
@@ -1,5 +1,5 @@ name: bus-pirate-version: 0.5+version: 0.6 synopsis: Haskell interface to the Bus Pirate binary interface homepage: http://www.github.com/bgamari/bus-pirate license: BSD3@@ -20,6 +20,7 @@ library exposed-modules: System.Hardware.BusPirate System.Hardware.BusPirate.I2C+ System.Hardware.BusPirate.SPI other-modules: System.Hardware.BusPirate.Core build-depends: base >=4.6 && <4.8, serialport >=0.4 && <0.5,