hlibBladeRF 0.1.0.5 → 0.1.0.6
raw patch · 4 files changed
+136/−25 lines, 4 files
Files
- ChangeLog +5/−0
- hlibBladeRF.cabal +2/−2
- src/LibBladeRF/Frequency.hs +16/−14
- src/LibBladeRF/Gpio.hs +113/−9
ChangeLog view
@@ -1,5 +1,10 @@ Changes in 0.1.0.5 +* LibBladeRF/Gpio.hs: Type BladeRFGPIOFlags and handle C ret err codes.+* Handle bladeRFGet{Correction,Frequency} C ret err codes.++Changes in 0.1.0.5+ * Provide 'BladeRFReturnType' type-alias and replace 'Either BladeRFError a' with 'BladeRFReturnType a'. For brevity and clarity, use a type-alias to wrap the Either error or result context in the return type of the
hlibBladeRF.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: hlibBladeRF-version: 0.1.0.5+version: 0.1.0.6 synopsis: Haskell binding to libBladeRF SDR library description: IO Monadic binding for libbladeRF software defined radio. homepage: https://victoredwardocallaghan.github.io/hlibBladeRF@@ -77,4 +77,4 @@ type: git location: git://github.com/victoredwardocallaghan/hlibBladeRF branch: master- tag: v0.1.0.5+ tag: v0.1.0.6
src/LibBladeRF/Frequency.hs view
@@ -34,14 +34,14 @@ return $ bladeRFErrorTy ret -- | Get module's current frequency in Hz.-bladeRFGetFrequency :: DeviceHandle -- ^ Device handle- -> BladeRFModule -- ^ Module to configure- -> IO Int -- ^ Returned frequency-bladeRFGetFrequency dev m = do- f <- alloca $ \pf -> do- c'bladerf_get_frequency (unDeviceHandle dev) ((fromIntegral . fromEnum) m) pf- peek pf- return $ fromIntegral f+bladeRFGetFrequency :: DeviceHandle -- ^ Device handle+ -> BladeRFModule -- ^ Module to configure+ -> IO (BladeRFReturnType Int) -- ^ Returned frequency+bladeRFGetFrequency dev m = alloca $ \pf -> do+ ret <- c'bladerf_get_frequency (unDeviceHandle dev) ((fromIntegral . fromEnum) m) pf+ if ret < 0 then (return . Left . toEnum . fromIntegral) ret -- C ret code to typed error+ else do freq <- peek pf+ (return . Right . fromIntegral) freq -- | Set module's frequency in Hz. bladeRFSetFrequency :: DeviceHandle -- ^ Device handle@@ -53,13 +53,15 @@ return $ bladeRFErrorTy ret -- | Obtain the current value of the specified configuration parameter.-bladeRFGetCorrection :: DeviceHandle -- ^ Device handle- -> BladeRFModule -- ^ Module to retrieve correction information from- -> BladeRFCorrection -- ^ Correction type- -> IO Word16 -- ^ Current value+bladeRFGetCorrection :: DeviceHandle -- ^ Device handle+ -> BladeRFModule -- ^ Module to retrieve correction information from+ -> BladeRFCorrection -- ^ Correction type+ -> IO (BladeRFReturnType Word16) -- ^ Current value bladeRFGetCorrection dev m c = alloca $ \pc -> do- c'bladerf_get_correction (unDeviceHandle dev) ((fromIntegral . fromEnum) m) ((fromIntegral . fromEnum) c) pc- peek pc+ ret <- c'bladerf_get_correction (unDeviceHandle dev) ((fromIntegral . fromEnum) m) ((fromIntegral . fromEnum) c) pc+ if ret < 0 then (return . Left . toEnum . fromIntegral) ret -- C ret code to typed error+ else do corr <- peek pc+ (return . Right) corr -- | Set the value of the specified configuration parameter. bladeRFSetCorrection :: DeviceHandle -- ^ Device handle
src/LibBladeRF/Gpio.hs view
@@ -6,10 +6,27 @@ Stability : provisional Portability : portable - This module GPIO configuration handling.+ This module deals with GPIO configuration handling.++ The following example illustrates the setup of GPIO's+ for timestamping in the usual, read, modify, write+ sequence:++ @+ gpios <- bladeRFConfigGPIORead dev+ case gpios of+ Left e -> throwIO e+ Right gpios -> do+ putStrLn \"========= GPIO Dump =========\"+ mapM_ putStrLn $ debugBladeRFGPIOFlags gpios+ bladeRFConfigGPIOWrite dev $ GPIO_TIMESTAMP : gpios+ @ -} -module LibBladeRF.Gpio ( bladeRFConfigGPIORead+{-# LANGUAGE Trustworthy #-}+module LibBladeRF.Gpio ( BladeRFGPIOFlags(..)+ , debugBladeRFGPIOFlags+ , bladeRFConfigGPIORead , bladeRFConfigGPIOWrite ) where @@ -17,25 +34,112 @@ import Foreign.C.Types import Foreign.C.String +import Data.Maybe+import Data.Tuple+ import Bindings.LibBladeRF import LibBladeRF.LibBladeRF import LibBladeRF.Types +-- | BladeRF GPIO Flag Type.+data BladeRFGPIOFlags = GPIO_LMS_RX_ENABLE -- ^ Enable LMS receive.+ -- N.B. This bit is set/cleared by 'LibBladeRF.Utils.bladeRFEnableModule'+ | GPIO_LMS_TX_ENABLE -- ^ Enable LMS transmit.+ -- N.B. This bit is set/cleared by 'LibBladeRF.Utils.bladeRFEnableModule'+ | GPIO_TX_LB_ENABLE -- ^ Switch to use TX low band (300MHz - 1.5GHz).+ -- N.B. This is set using 'LibBladeRF.Frequency.bladeRFSetFrequency'.+ | GPIO_TX_HB_ENABLE -- ^ Switch to use TX high band (1.5GHz - 3.8GHz).+ -- N.B. This is set using 'LibBladeRF.Frequency.bladeRFSetFrequency'.+ | GPIO_COUNTER_ENABLE -- ^ Counter mode enable.+ --+ -- Setting this bit to 1 instructs the FPGA to replace the (I, Q) pair in+ -- sample data with an incrementing, little-endian, 32-bit counter value. A+ -- 0 in bit specifies that sample data should be sent (as normally done).+ --+ -- This feature is useful when debugging issues involving dropped samples.+ | GPIO_RX_LB_ENABLE -- ^ Switch to use RX low band (300M - 1.5GHz).+ -- N.B. This is set using 'LibBladeRF.Frequency.bladeRFSetFrequency'.+ | GPIO_RX_HB_ENABLE -- ^ Switch to use RX high band (1.5GHz - 3.8GHz).+ -- N.B. This is set using 'LibBladeRF.Frequency.bladeRFSetFrequency'.+ | GPIO_FEATURE_SMALL_DMA_XFER -- ^ This GPIO bit configures the FPGA to use smaller DMA+ -- transfers (256 cycles instead of 512). This is required+ -- when the device is not connected at Super Speed (i.e., when+ -- it is connected at High Speed).+ --+ -- However, the caller need not set this in 'bladeRFConfigGPIOWrite' calls.+ -- The library will set this as needed; callers generally+ -- do not need to be concerned with setting/clearing this bit.+ | GPIO_TIMESTAMP -- ^ Enable-bit for timestamp counter in the FPGA.+ | GPIO_TIMESTAMP_DIV2 -- ^ Timestamp 2x divider control.+ --+ -- By default (value = 0), the sample counter is incremented with I and Q,+ -- yielding two counts per sample.+ --+ -- Set this bit to 1 to enable a 2x timestamp divider, effectively+ -- achieving 1 timestamp count per sample.+ deriving (Eq)++instance Enum BladeRFGPIOFlags where+ fromEnum = fromJust . flip lookup gpios+ toEnum = fromJust . flip lookup (map swap gpios)++gpios = [ (GPIO_LMS_RX_ENABLE, c'BLADERF_GPIO_LMS_RX_ENABLE)+ , (GPIO_LMS_TX_ENABLE, c'BLADERF_GPIO_LMS_TX_ENABLE)+ , (GPIO_TX_LB_ENABLE, c'BLADERF_GPIO_TX_LB_ENABLE)+ , (GPIO_TX_HB_ENABLE, c'BLADERF_GPIO_TX_HB_ENABLE)+ , (GPIO_COUNTER_ENABLE, c'BLADERF_GPIO_COUNTER_ENABLE)+ , (GPIO_RX_LB_ENABLE, c'BLADERF_GPIO_RX_LB_ENABLE)+ , (GPIO_RX_HB_ENABLE, c'BLADERF_GPIO_RX_HB_ENABLE)+ , (GPIO_FEATURE_SMALL_DMA_XFER, c'BLADERF_GPIO_FEATURE_SMALL_DMA_XFER)+ , (GPIO_TIMESTAMP, c'BLADERF_GPIO_TIMESTAMP)+ , (GPIO_TIMESTAMP_DIV2, c'BLADERF_GPIO_TIMESTAMP_DIV2)+ ]++-- | Useful helper function to decode GPIO flags into strings+--+-- Example:+--+-- @+-- gpios <- bladeRFConfigGPIORead dev+-- case gpios of+-- Left e -> throwIO e+-- Right g -> mapM_ putStrLn $ debugBladeRFGPIOFlags g+-- @+--+debugBladeRFGPIOFlags :: [BladeRFGPIOFlags] -> [String]+debugBladeRFGPIOFlags = map fts+ where fts f | f == GPIO_LMS_RX_ENABLE = " [GPIO flag set] " ++ "Enable LMS receive."+ | f == GPIO_LMS_TX_ENABLE = " [GPIO flag set] " ++ "Enable LMS transmit."+ | f == GPIO_TX_LB_ENABLE = " [GPIO flag set] " ++ "Switch to use TX low band (300MHz - 1.5GHz)."+ | f == GPIO_TX_HB_ENABLE = " [GPIO flag set] " ++ "Switch to use TX high band (1.5GHz - 3.8GHz)."+ | f == GPIO_COUNTER_ENABLE = " [GPIO flag set] " ++ "Counter mode enable."+ | f == GPIO_RX_LB_ENABLE = " [GPIO flag set] " ++ "Switch to use RX low band (300M - 1.5GHz)."+ | f == GPIO_RX_HB_ENABLE = " [GPIO flag set] " ++ "Switch to use RX high band (1.5GHz - 3.8GHz)."+ | f == GPIO_FEATURE_SMALL_DMA_XFER = " [GPIO flag set] " ++ "Configures the FPGA to use smaller DMA transfers."+ | f == GPIO_TIMESTAMP = " [GPIO flag set] " ++ "Enable-bit for timestamp counter in the FPGA."+ | f == GPIO_TIMESTAMP_DIV2 = " [GPIO flag set] " ++ "Timestamp 2x divider control."+ -- | Read a configuration GPIO register.-bladeRFConfigGPIORead :: DeviceHandle -- ^ Device handle- -> IO Word32 -- ^ Read data+bladeRFConfigGPIORead :: DeviceHandle -- ^ Device handle+ -> IO (BladeRFReturnType [BladeRFGPIOFlags]) -- ^ Read data bladeRFConfigGPIORead dev = alloca $ \pv -> do- c'bladerf_config_gpio_read (unDeviceHandle dev) pv- peek pv+ ret <- c'bladerf_config_gpio_read (unDeviceHandle dev) pv+ if ret < 0 then (return . Left . toEnum . fromIntegral) ret -- C ret code to typed error+ else do gpior <- peek pv+ (return . Right . wordToFlags . fromIntegral) gpior+ where wordToFlags w = [e | (e, bit) <- gpios, bit .&. w /= 0] -- | Write a configuration GPIO register. -- -- Callers should be sure to perform a read-modify-write sequence to avoid -- accidentally clearing other GPIO bits that may be set by the library internally.-bladeRFConfigGPIOWrite :: DeviceHandle -- ^ Device handle- -> Word32 -- ^ Data to write to GPIO register+bladeRFConfigGPIOWrite :: DeviceHandle -- ^ Device handle+ -> [BladeRFGPIOFlags] -- ^ Data to write to GPIO register -> IO (BladeRFReturnType ()) bladeRFConfigGPIOWrite dev v = do- ret <- c'bladerf_config_gpio_write (unDeviceHandle dev) v+ ret <- c'bladerf_config_gpio_write (unDeviceHandle dev) value return $ bladeRFErrorTy ret+ where+ value = foldr1 (.|.) flags+ flags = map (fromIntegral . fromEnum) v