hlibBladeRF-0.1.0.6: src/LibBladeRF/Gpio.hs
{-|
Module : $Header$
Copyright : (c) 2014 Edward O'Callaghan
License : LGPL-2.1
Maintainer : eocallaghan@alterapraxis.com
Stability : provisional
Portability : portable
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
@
-}
{-# LANGUAGE Trustworthy #-}
module LibBladeRF.Gpio ( BladeRFGPIOFlags(..)
, debugBladeRFGPIOFlags
, bladeRFConfigGPIORead
, bladeRFConfigGPIOWrite
) where
import Foreign
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 (BladeRFReturnType [BladeRFGPIOFlags]) -- ^ Read data
bladeRFConfigGPIORead dev = alloca $ \pv -> do
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
-> [BladeRFGPIOFlags] -- ^ Data to write to GPIO register
-> IO (BladeRFReturnType ())
bladeRFConfigGPIOWrite dev v = do
ret <- c'bladerf_config_gpio_write (unDeviceHandle dev) value
return $ bladeRFErrorTy ret
where
value = foldr1 (.|.) flags
flags = map (fromIntegral . fromEnum) v