ftdi 0.1 → 0.2
raw patch · 2 files changed
+63/−44 lines, 2 filesdep +monads-fddep ~basedep ~base-unicode-symbolsdep ~transformersPVP ok
version bump matches the API change (PVP)
Dependencies added: monads-fd
Dependency ranges changed: base, base-unicode-symbols, transformers
API changes (from Hackage documentation)
- System.FTDI: readData :: (MonadIO m) => InterfaceHandle -> Int -> ChunkedReaderT m [ByteString]
+ System.FTDI: readData :: (MonadIO m) => InterfaceHandle -> m Bool -> Int -> ChunkedReaderT m [ByteString]
Files
- System/FTDI/Internal.hs +58/−40
- ftdi.cabal +5/−4
System/FTDI/Internal.hs view
@@ -14,7 +14,7 @@ -- Imports ------------------------------------------------------------------------------- --- base+-- from base: import Control.Applicative ( Applicative, (<$>), Alternative ) import Control.Exception ( Exception, bracket, throwIO ) import Control.Monad ( Functor@@ -24,6 +24,9 @@ ) import Control.Monad.Fix ( MonadFix ) import Data.Bool ( Bool, otherwise )+#ifdef __HADDOCK__+import Data.Bool ( Bool(False, True) )+#endif import Data.Bits ( Bits, (.|.) , setBit, shiftL, shiftR, testBit )@@ -50,30 +53,31 @@ import Text.Read ( Read ) import Text.Show ( Show ) --- base-unicode-symbols+-- from base-unicode-symbols: import Data.Eq.Unicode ( (≡) ) import Data.Function.Unicode ( (∘) ) import Data.Monoid.Unicode ( (⊕) ) import Prelude.Unicode ( (⋅), (÷) ) --- bytestring-import qualified Data.ByteString as BS ( drop, length, null, splitAt, unpack )-#ifdef __HADDOCK__-import qualified Data.ByteString as BS ( empty )-#endif+-- from bytestring:+import qualified Data.ByteString as BS ( empty, drop, length+ , null, splitAt, unpack+ ) import Data.ByteString ( ByteString ) --- ftdi+-- from ftdi: import System.FTDI.Utils ( divRndUp, clamp, genFromEnum, orBits ) --- safe+-- from monads-fd:+import Control.Monad.Trans ( MonadTrans, MonadIO, lift, liftIO )++-- from safe: import Safe ( atMay, headMay ) --- transformers-import Control.Monad.Trans ( MonadTrans, MonadIO, liftIO )+-- from transformers: import Control.Monad.Trans.State ( StateT, get, put, runStateT ) --- usb+-- from usb: import qualified System.USB as USB @@ -158,7 +162,7 @@ -- Devices ------------------------------------------------------------------------------- --- |A representation of an FTDI device. +-- |A representation of an FTDI device. data Device = Device { devUSB ∷ USB.Device , devUSBConf ∷ USB.ConfigDesc@@ -279,7 +283,7 @@ closeDevice ∷ DeviceHandle → IO () closeDevice = USB.closeDevice ∘ devHndUSB --- |The recommended way to acquire a handle. Ensures that the handles+-- |The recommended way to acquire a handle. Ensures that the handle -- is released when the monadic computation is completed. Even, or -- especially, when an exception is thrown. withDeviceHandle ∷ Device → (DeviceHandle → IO α) → IO α@@ -360,9 +364,9 @@ @ example ∷ 'InterfaceHandle' → IO () example ifHnd = do- (packets1, rest1) ← runChunkedReaderT ('readData' ifHnd 400) 'BS.empty'+ (packets1, rest1) ← runChunkedReaderT ('readData' ifHnd (return 'False') 400) 'BS.empty' print $ 'BS.concat' packets1- (packets2, rest2) ← runChunkedReaderT ('readData' ifHnd 200) rest1+ (packets2, rest2) ← runChunkedReaderT ('readData' ifHnd (return 'False') 200) rest1 print $ 'BS.concat' packets2 @ @@ -372,9 +376,9 @@ @ example ∷ 'InterfaceHandle' → IO () example ifHnd =- let reader = do packets1 ← 'readData' ifHnd 400+ let reader = do packets1 ← 'readData' ifHnd (return 'False') 400 liftIO $ print $ 'BS.concat' packets1- packets2 ← 'readData' ifHnd 200+ packets2 ← 'readData' ifHnd (return 'False') 200 liftIO $ print $ 'BS.concat' packets1 in runChunkedReaderT reader 'BS.empty' @@@ -385,23 +389,31 @@ {-| Reads data from the given FTDI interface by performing bulk reads. -This function produces an action in the ChunkedReaderT monad that, when-executed, will read exactly the requested number of bytes. Executing the-readData action will block until all data is read. The result value is a list-of chunks, represented as ByteStrings. This representation was choosen for-efficiency reasons.+This function produces an action in the @ChunkedReaderT@ monad that+will read exactly the requested number of bytes unless it is+explicitly asked to stop early. Executing the @readData@ action will+block until either: -Data is read in packets. The function may choose to request more than needed in-order to get the highest possible bandwidth. The excess of bytes is kept as the-state of the ChunkedReaderT monad. A subsequent invocation of readData will-first return bytes from the stored state before requesting more from the device-itself. A consequence of this behaviour is that even when you request 100 bytes-the function will actually request 512 bytes (depending on the packet size) and-/block/ until all 512 bytes are read! There is no workaround since requesting+ * All data are read++ * The given checkStop action returns 'True'++The result value is a list of chunks, represented as+@ByteString@s. This representation was choosen for efficiency reasons.++Data are read in packets. The function may choose to request more than+needed in order to get the highest possible bandwidth. The excess of+bytes is kept as the state of the @ChunkedReaderT@ monad. A subsequent+invocation of @readData@ will first return bytes from the stored state+before requesting more from the device itself. A consequence of this+behaviour is that even when you request 100 bytes the function will+actually request 512 bytes (depending on the packet size) and /block/+until all 512 bytes are read! There is no workaround since requesting less bytes than the packet size is an error. -USB timeouts will not interrupt readData. In case of a timeout readData will-simply resume reading data. A small USB timeout can degrade performance.+USB timeouts will not interrupt @readData@. In case of a timeout+@readData@ will simply resume reading data. A small USB timeout can+degrade performance. The FTDI latency timer can cause poor performance. If the FTDI chip can't fill a packet before the latency timer fires it is forced to send an incomplete@@ -420,13 +432,16 @@ @ -- Read 100 data bytes from ifHnd- (packets, rest) ← 'runChunkedReaderT' ('readData' ifHnd 100) 'BS.empty'+ (packets, rest) ← 'runChunkedReaderT' ('readData' ifHnd (return 'False') 100) 'BS.empty' @ -}--- TODO: timeout-readData ∷ ∀ m. MonadIO m ⇒ InterfaceHandle → Int → ChunkedReaderT m [ByteString]-readData ifHnd numBytes = ChunkedReaderT $+readData ∷ ∀ m. MonadIO m+ ⇒ InterfaceHandle+ → m Bool -- ^ Check stop action+ → Int -- ^ Number of bytes to read+ → ChunkedReaderT m [ByteString]+readData ifHnd checkStop numBytes = ChunkedReaderT $ do prevRest ← get let readNumBytes = numBytes - BS.length prevRest if readNumBytes > 0@@ -462,12 +477,15 @@ -- receivedBytes < packetSize if receivedDataBytes < readNumBytes then let xs = splitPackets bytes- in liftM (xs ⊕) (readLoop $ readNumBytes - receivedDataBytes)+ in lift checkStop >>= \stop →+ if stop+ then put BS.empty >> return xs+ else liftM (xs ⊕)+ (readLoop $ readNumBytes - receivedDataBytes) else -- We might have received too much data, since we can only -- request multiples of 'packetSize' bytes. Split the byte -- string at such an index that the first part contains- -- readNumBytes of data bytes. The rest is kept for future- -- usage.+ -- readNumBytes of data. The rest is kept for future usage. let (bs, newRest) = BS.splitAt (splitIndex readNumBytes) bytes in put newRest >> return (splitPackets bs) @@ -489,7 +507,7 @@ -- |Perform a bulk read. ----- Returns the data that was read (in the form of a 'ByteString') and a flag+-- Returns the bytes that where read (in the form of a 'ByteString') and a flag -- which indicates whether a timeout occured during the request. readBulk ∷ InterfaceHandle → Int -- ^Number of bytes to read
ftdi.cabal view
@@ -1,5 +1,5 @@ name: ftdi-version: 0.1+version: 0.2 cabal-version: >=1.6 build-type: Custom stability: experimental@@ -39,11 +39,12 @@ exposed-modules: System.FTDI other-modules: System.FTDI.Internal , System.FTDI.Utils- build-depends: base >= 4 && < 4.3- , base-unicode-symbols >= 0.1.1 && < 0.2+ build-depends: base >= 3.0.3 && < 4.3+ , base-unicode-symbols >= 0.1.1 && < 0.3 , bytestring >= 0.9.1 && < 0.10+ , monads-fd >= 0.1 && < 0.2 , safe >= 0.2 && < 0.3- , transformers >= 0.1.4 && < 0.2+ , transformers >= 0.2 && < 0.3 , usb >= 0.3 && < 0.4 ghc-options: -Wall