{-| Module : $Header$ Copyright : (c) 2014 Edward O'Callaghan License : LGPL-2.1 Maintainer : eocallaghan@alterapraxis.com Stability : provisional Portability : portable This module encapsulates misc libbladeRF library functions. -} module LibBladeRF.Utils ( bladeRFLogSetVerbosity , bladeRFLibVersion , bladeRFFwVersion , bladeRFFPGAVersion , bladeRFDeviceSpeed , bladeRFLoadFPGA , bladeRFGetDevInfo , bladeRFGetSerial , bladeRFGetFPGASize , bladeRFEnableModule , bladeRFSetLoopback , bladeRFGetLoopback ) where import Foreign import Foreign.C.Types import Foreign.C.String import Bindings.LibBladeRF import LibBladeRF.LibBladeRF import LibBladeRF.Types -- | Sets the filter level for displayed log messages. -- -- Messages that are at or above the specified log level will be printed, while -- messages with a lower log level will be suppressed. bladeRFLogSetVerbosity :: BladeRFLogLevel -- ^ The new log level filter value -> IO () bladeRFLogSetVerbosity l = c'bladerf_log_set_verbosity $ (fromIntegral . fromEnum) l -- internal use only toBladeRFVer :: C'bladerf_version -> String -> BladeRFVersion toBladeRFVer brfv desc = BladeRFVersion { major = c'bladerf_version'major brfv , minor = c'bladerf_version'minor brfv , patch = c'bladerf_version'patch brfv , descr = desc } -- | Get libbladeRF version information. bladeRFLibVersion :: IO BladeRFVersion bladeRFLibVersion = do brfv <- alloca $ \p -> do c'bladerf_version p peek p desc <- peekCString $ c'bladerf_version'describe brfv return $ toBladeRFVer brfv desc -- | Query firmware version. bladeRFFwVersion :: DeviceHandle -- ^ Device handle -> IO BladeRFVersion -- ^ Returned firmware version bladeRFFwVersion dev = do brfv <- alloca $ \p -> do c'bladerf_fw_version (unDeviceHandle dev) p peek p desc <- peekCString $ c'bladerf_version'describe brfv return $ toBladeRFVer brfv desc -- | Query FPGA version. bladeRFFPGAVersion :: DeviceHandle -- ^ Device handle -> IO BladeRFVersion -- ^ Returned firmware version bladeRFFPGAVersion dev = do status <- c'bladerf_is_fpga_configured (unDeviceHandle dev) if status > 0 then do brfv <- alloca $ \p -> do c'bladerf_fpga_version (unDeviceHandle dev) p peek p desc <- peekCString $ c'bladerf_version'describe brfv return $ toBladeRFVer brfv desc else return BladeRFVersion { major = 0 , minor = 0 , patch = 0 , descr = "Unknown (FPGA not loaded)" } -- | Load device's FPGA. -- -- Note that this FPGA configuration will be reset at the next -- power cycle. Pass Full path to FPGA bitstream. bladeRFLoadFPGA :: DeviceHandle -- ^ Device handle -> String -- ^ Full path to FPGA bitstream -> IO (BladeRFReturnType ()) bladeRFLoadFPGA dev s = do p <- newCString s ret <- c'bladerf_load_fpga (unDeviceHandle dev) p return $ bladeRFErrorTy ret -- | Obtain the bus speed at which the device is operating. bladeRFDeviceSpeed :: DeviceHandle -- ^ Device handle -> IO BladeRFSpeed -- ^ Device speed bladeRFDeviceSpeed dev = do speed <- c'bladerf_device_speed (unDeviceHandle dev) return $ (toEnum . fromEnum) speed -- | Fill out a provided 'LibBladeRF.Types.BladeRFDevInfo' structure, given an open device handle. bladeRFGetDevInfo :: DeviceHandle -- ^ Device handle -> IO BladeRFDeviceInfo -- ^ Device information populated by this function bladeRFGetDevInfo dev = do brfv <- alloca $ \p -> do c'bladerf_get_devinfo (unDeviceHandle dev) p -- XXX ^ handle status return error with Maybe monad??? peek p let info = BladeRFDeviceInfo { backend = toEnum . fromEnum . c'bladerf_devinfo'backend $ brfv , serial = map castCCharToChar . c'bladerf_devinfo'serial $ brfv , usbBus = c'bladerf_devinfo'usb_bus brfv , usbAddr = c'bladerf_devinfo'usb_addr brfv , inst = c'bladerf_devinfo'instance brfv } return info -- | Query a device's serial number. bladeRFGetSerial :: DeviceHandle -- ^ Device handle -> IO String -- ^ Returned serial number. bladeRFGetSerial dev = allocaBytes (c'BLADERF_SERIAL_LENGTH + 1) $ \cstring -> do -- API bug bladerf_get_serial() should be allocating the buffer itself, not the call site! -- See upstream report: https://github.com/Nuand/bladeRF/issues/382 -- device serial is 33 bytes long + null terminating byte. c'bladerf_get_serial (unDeviceHandle dev) cstring peekCString cstring -- | Query a device's FPGA size. bladeRFGetFPGASize :: DeviceHandle -- ^ Device handle -> IO BladeRFFPGASize -- ^ Returned on-board FPGA's size. bladeRFGetFPGASize dev = do sz <- alloca $ \p -> do c'bladerf_get_fpga_size (unDeviceHandle dev) p peek p return $ (toEnum . fromEnum) sz -- | Enable or disable the specified RX/TX module. -- -- When a synchronous stream is associated with the specified module, this -- will shut down the underlying asynchronous stream when `enable` = 'False'. bladeRFEnableModule :: DeviceHandle -- ^ Device handle -> BladeRFModule -- ^ Device module -> Bool -- ^ 'True' to enable, 'False' to disable -> IO (BladeRFReturnType ()) bladeRFEnableModule dev m t = do ret <- c'bladerf_enable_module (unDeviceHandle dev) ((fromIntegral . fromEnum) m) t return $ bladeRFErrorTy ret -- | Apply specified loopback mode. -- -- Loopback modes should only be enabled or disabled while the RX and TX -- modules are both disabled (and therefore, when no samples are being -- actively streamed). Otherwise, unexpected behavior may occur. bladeRFSetLoopback :: DeviceHandle -- ^ Device handle -> BladeRFLoopback -- ^ Loopback mode. Note that 'LB_NONE' -- disables the use of loopback functionality. -> IO (BladeRFReturnType ()) bladeRFSetLoopback dev l = do ret <- c'bladerf_set_loopback (unDeviceHandle dev) ((fromIntegral . fromEnum) l) return $ bladeRFErrorTy ret -- | Get current loopback mode. bladeRFGetLoopback :: DeviceHandle -- ^ Device handle -> IO BladeRFLoopback -- ^ Current loopback mode bladeRFGetLoopback dev = do l <- alloca $ \lp -> do c'bladerf_get_loopback (unDeviceHandle dev) lp peek lp return $ (toEnum . fromEnum) l