sdr-0.1.0.0: hs_sources/SDR/RTLSDRStream.hs
{-| Stream samples from a Realtek RTL2832U based device -}
module SDR.RTLSDRStream (
sdrStream
) where
import Control.Monad
import Control.Monad.Trans.Either
import Data.Word
import Foreign.ForeignPtr
import Foreign.C.Types
import Control.Concurrent hiding (yield)
import Foreign.Marshal.Utils
import qualified Data.Vector.Storable as VS
import Pipes
import Pipes.Concurrent
import RTLSDR
-- | Returns a producer that streams data from a Realtek RTL2832U based device. You probably want to use `makeComplexBufferVect` to turn it into a list of complex Floats.
sdrStream :: Word32 -- ^ Frequency
-> Word32 -- ^ Sample rate
-> Word32 -- ^ Number of buffers
-> Word32 -- ^ Buffer length
-> EitherT String IO (Producer (VS.Vector CUChar) IO ()) -- ^ Either a string describing the error that occurred or the Producer
sdrStream frequency sampleRate bufNum bufLen = do
lift $ putStrLn "Initializing RTLSDR device"
dev' <- lift $ open 0
dev <- maybe (left "Failed to open device") return dev'
lift $ do
t <- getTunerType dev
putStrLn $ "Found a: " ++ show t
setFreqCorrection dev 0
setSampleRate dev sampleRate
setCenterFreq dev frequency
setTunerGainMode dev False
resetBuffer dev
(output, input) <- spawn unbounded
forkOS $ void $ readAsync dev bufNum bufLen $ \dat num -> void $ do
let numBytes = fromIntegral $ bufNum * bufLen
fp <- mallocForeignPtrArray numBytes
withForeignPtr fp $ \fpp -> moveBytes fpp dat numBytes
let v = VS.unsafeFromForeignPtr0 fp numBytes
atomically (send output v)
return $ fromInput input