packages feed

sdr 0.1.0.4 → 0.1.0.5

raw patch · 8 files changed

+169/−12 lines, 8 filesdep ~sdr

Dependency ranges changed: sdr

Files

benchmarks/Benchmarks.hs view
@@ -43,6 +43,10 @@         inBufComplex =  VG.fromList $ take size $ do             i <- [0..]             return $ i :+ i+        inBufRTLSDR  :: VS.Vector CUChar+        inBufRTLSDR  =  VG.fromList $ take size [0 ..]+        inBufBladeRF :: VS.Vector CShort+        inBufBladeRF =  VG.fromList $ take size [0 ..]          numConv   = 16386         inBufConv :: VS.Vector CUChar@@ -127,6 +131,20 @@                 (const True, bench "c"               $ nfIO $ scaleC    0.3 inBuf outBuf),                 (hasSSE42,   bench "cSSE"            $ nfIO $ scaleCSSE 0.3 inBuf outBuf),                 (hasAVX,     bench "cAVX"            $ nfIO $ scaleCAVX 0.3 inBuf outBuf)+            ],+            bgroup "conversion" [+                bgroup "RTLSDR" $ hasFeatures [+                    (const True, bench "h"    $ nf (interleavedIQUnsigned256ToFloat :: VS.Vector CUChar -> VS.Vector (Complex Float)) inBufRTLSDR),+                    (const True, bench "c"    $ nf interleavedIQUnsignedByteToFloat    inBufRTLSDR),+                    (hasSSE42,   bench "cSSE" $ nf interleavedIQUnsignedByteToFloatSSE inBufRTLSDR),+                    (hasAVX2,    bench "cAVX" $ nf interleavedIQUnsignedByteToFloatAVX inBufRTLSDR)+                ],+                bgroup "BladeRF" $ hasFeatures [+                    (const True, bench "h"    $ nf (interleavedIQSigned2048ToFloat :: VS.Vector CShort -> VS.Vector (Complex Float))  inBufBladeRF),+                    (const True, bench "c"    $ nf interleavedIQSignedWordToFloat    inBufBladeRF),+                    (hasSSE42,   bench "cSSE" $ nf interleavedIQSignedWordToFloatSSE inBufBladeRF),+                    (hasAVX2,    bench "cAVX" $ nf interleavedIQSignedWordToFloatAVX inBufBladeRF)+                ]             ]         ] 
c_sources/convert.c view
@@ -48,3 +48,39 @@         _mm256_storeu_ps(out + i, res);     } }++void convertCBladeRF(int num, int16_t *in, float *out){+    int i;+    for(i=0; i<num; i++){+        out[i] = (float)in[i] * (1/2048.0);+    }+}++void convertCSSEBladeRF(int num, int16_t *in, float *out){+    int i;+    __m128 mul = _mm_set1_ps(1/2048.0);+    for(i=0; i<num; i+=4){+        __m128i val  = _mm_loadu_si128((__m128i *)(in + i));+        __m128i ints = _mm_cvtepi16_epi32(val);+        __m128  cvtd = _mm_cvtepi32_ps(ints);++        __m128  res  = _mm_mul_ps(cvtd, mul);++        _mm_storeu_ps(out + i, res);+    }+}++void convertCAVXBladeRF(int num, int16_t *in, float *out){+    int i;+    __m256 mul = _mm256_set1_ps(1/2048.0);+    for(i=0; i<num; i+=8){+        __m128i val  = _mm_loadu_si128((__m128i *)(in + i));+        __m256i ints = _mm256_cvtepi16_epi32(val);+        __m256  cvtd = _mm256_cvtepi32_ps(ints);++        __m256  res  = _mm256_mul_ps(cvtd, mul);++        _mm256_storeu_ps(out + i, res);+    }+}+
hs_sources/SDR/FilterDesign.hs view
@@ -4,6 +4,9 @@     -- * Sinc Function     sinc, +    -- * Root raised cosine+    srrc,+     -- * Windows     hanning,     hamming,@@ -74,3 +77,17 @@ plotFrequency coeffs = toFile def "frequency_response.png" $ do     layout_title .= "Frequency Response"     plot (line "Frequency Response" [signal coeffs $ takeWhile (< pi) $ iterate (+ 0.01) 0])++--ts is really the ratio ts / sampling period+-- | Square root raised cosine+srrc :: (Ord a, Floating a) => Int -> Int -> a -> [a]+srrc n ts beta = map func [(-n) .. n]+    where+    func x +        | x == 0                                                 = 1 - beta + 4 * beta / pi+        | abs (fromIntegral x) ~= (fromIntegral ts / (4 * beta)) = (beta / sqrt 2) * ((1 + 2/pi) * sin (pi / (4 * beta)) + (1 - 2/pi) * cos (pi / (4 * beta)))+        | otherwise                                              = (sin (pi * xdivts * (1 - beta)) + 4 * beta * xdivts * cos (pi * xdivts * (1 + beta))) / (pi * xdivts * (1 - (4 * beta * xdivts) ** 2))+            where+            xdivts = fromIntegral x / fromIntegral ts+    x ~= y = abs (x - y) < 0.001+
hs_sources/SDR/PipeUtils.hs view
@@ -5,6 +5,7 @@     printStream,     devnull,     rate,+    pMapAccum     ) where  import Data.Time.Clock@@ -52,4 +53,13 @@             yield res             rate' (buffers + 1)     rate' 1++pMapAccum :: (Monad m) => (acc -> x -> (acc, y)) -> acc -> Pipe x y m () +pMapAccum func acc = go acc+    where+    go acc = do+        dat <- await+        let (acc', res) = func acc dat+        yield res+        go acc' 
hs_sources/SDR/Util.hs view
@@ -12,7 +12,11 @@     interleavedIQUnsignedByteToFloatSSE,     interleavedIQUnsignedByteToFloatAVX,     interleavedIQUnsignedByteToFloatFast,+     interleavedIQSigned2048ToFloat,+    interleavedIQSignedWordToFloat,+    interleavedIQSignedWordToFloatSSE,+    interleavedIQSignedWordToFloatAVX,      -- * Scaling     scaleC,@@ -108,6 +112,42 @@     convert idx  = convert' (input `VG.unsafeIndex` (2 * idx)) :+ convert' (input `VG.unsafeIndex` (2 * idx + 1))     {-# INLINE convert' #-}     convert' val = fromIntegral val / 2048++foreign import ccall unsafe "convertCBladeRF"+    convertCBladeRF_c :: CInt -> Ptr CShort -> Ptr CFloat -> IO ()++-- | Same as `interleavedIQUnsigned256ToFloat` but written in C and specialized for unsigned byte inputs and Float outputs.+interleavedIQSignedWordToFloat :: VS.Vector CShort -> VS.Vector (Complex Float)+interleavedIQSignedWordToFloat inBuf = unsafePerformIO $ do+    outBuf <- VGM.new $ VG.length inBuf `quot` 2+    VS.unsafeWith inBuf $ \iPtr -> +        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +            convertCBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr+    VG.freeze outBuf++foreign import ccall unsafe "convertCSSEBladeRF"+    convertCSSEBladeRF_c :: CInt -> Ptr CShort -> Ptr CFloat -> IO ()++-- | Same as `interleavedIQUnsigned256ToFloat` but written in C using SSE intrinsics and specialized for unsigned byte inputs and Float outputs.+interleavedIQSignedWordToFloatSSE :: VS.Vector CShort -> VS.Vector (Complex Float)+interleavedIQSignedWordToFloatSSE inBuf = unsafePerformIO $ do+    outBuf <- VGM.new $ VG.length inBuf `quot` 2+    VS.unsafeWith inBuf $ \iPtr -> +        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +            convertCSSEBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr+    VG.freeze outBuf++foreign import ccall unsafe "convertCAVXBladeRF"+    convertCAVXBladeRF_c :: CInt -> Ptr CShort -> Ptr CFloat -> IO ()++-- | Same as `interleavedIQUnsigned256ToFloat` but written in C using AVX intrinsics and specialized for unsigned byte inputs and Float outputs.+interleavedIQSignedWordToFloatAVX :: VS.Vector CShort -> VS.Vector (Complex Float)+interleavedIQSignedWordToFloatAVX inBuf = unsafePerformIO $ do+    outBuf <- VGM.new $ VG.length inBuf `quot` 2+    VS.unsafeWith inBuf $ \iPtr -> +        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +            convertCAVXBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr+    VG.freeze outBuf  -- | Scaling foreign import ccall unsafe "scale"
hs_sources/SDR/VectorUtils.hs view
@@ -5,10 +5,12 @@     mapAccumMV,     stride,     fill,+    vUnfoldr     ) where  import Control.Monad import Control.Monad.Primitive+import Control.Monad.ST  import           Data.Vector.Generic               as VG   hiding ((++)) import qualified Data.Vector.Generic.Mutable       as VGM@@ -62,3 +64,18 @@         VGM.unsafeWrite outBuf i x         return $ i + 1 +vUnfoldr :: VG.Vector v x => Int -> (acc -> (x, acc)) -> acc -> (v x, acc)+vUnfoldr size func acc = runST $ do+    vect <- VGM.new size+    acc' <- go vect 0 acc+    vect' <- VG.unsafeFreeze vect+    return (vect', acc')+    where+    go vect offset acc = go' offset acc+        where+        go' offset acc +            | offset == size = return acc+            | otherwise      = do+                let (res, acc') = func acc+                VGM.write vect offset res+                go' (offset + 1) acc'
sdr.cabal view
@@ -1,5 +1,5 @@ name:                sdr-version:             0.1.0.4+version:             0.1.0.5 synopsis:            A software defined radio library description:              Write software defined radio applications in Haskell.@@ -116,7 +116,7 @@         base                       >=4.6  && <4.9,          QuickCheck                 >=2.8  && <2.9,          vector                     >=0.10 && <0.11, -        sdr                        ==0.1.0.2, +        sdr                        ==0.1.0.5,          primitive                  >=0.5  && <0.7,          storable-complex           >=0.2  && <0.3,         test-framework             >=0.8  && <0.9,@@ -132,7 +132,7 @@         base             >=4.6  && <4.9,          criterion        >=1.0  && <1.2,         vector           >=0.10 && <0.11, -        sdr              ==0.1.0.2, +        sdr              ==0.1.0.5,          primitive        >=0.5  && <0.7,          storable-complex >=0.2  && <0.3     hs-source-dirs:      benchmarks
tests/TestSuite.hs view
@@ -41,7 +41,10 @@         testGroup "resamplers" [             testProperty "real" propResamplingReal         ],-        testProperty "conversion" propConversion,+        testGroup "conversion" [+            testProperty "rtlsdr"  propConversionRTLSDR,+            testProperty "BladeRF" propConversionBladeRF+        ],         testProperty "scaling"    propScaleReal     ]     where@@ -191,19 +194,35 @@             ]         assert res -    propConversion = +    propConversionRTLSDR =          forAll sizes $ \size ->              forAll (vectorOf (2 * size) (choose (-10, 10))) $ \inBuf -> -                testConversion size inBuf-    testConversion :: Int -> [Int] -> Property-    testConversion size inBuf = monadicIO $ do+                testConversionRTLSDR size inBuf+    testConversionRTLSDR :: Int -> [Int] -> Property+    testConversionRTLSDR size inBuf = monadicIO $ do         let vInput = VS.fromList $ map fromIntegral inBuf          let res = sameResult eqDeltaC $ map (VG.toList $) $ hasFeatures [-                (const True, (makeComplexBufferVect vInput :: VS.Vector (Complex Float))),-                (const True, convertC              vInput),-                (hasSSE42,   convertCSSE           vInput),-                (hasAVX2,    convertCAVX           vInput)+                (const True, (interleavedIQUnsigned256ToFloat    vInput :: VS.Vector (Complex Float))),+                (const True, interleavedIQUnsignedByteToFloat    vInput),+                (hasSSE42,   interleavedIQUnsignedByteToFloatSSE vInput),+                (hasAVX2,    interleavedIQUnsignedByteToFloatAVX vInput)+                ]+        assert res++    propConversionBladeRF = +        forAll sizes $ \size -> +            forAll (vectorOf (2 * size) (choose (-10, 10))) $ \inBuf -> +                testConversionBladeRF size inBuf+    testConversionBladeRF :: Int -> [Int] -> Property+    testConversionBladeRF size inBuf = monadicIO $ do+        let vInput = VS.fromList $ map fromIntegral inBuf++        let res = sameResult eqDeltaC $ map (VG.toList $) $ hasFeatures [+                (const True, (interleavedIQSigned2048ToFloat   vInput :: VS.Vector (Complex Float))),+                (const True, interleavedIQSignedWordToFloat    vInput),+                (hasSSE42,   interleavedIQSignedWordToFloatSSE vInput),+                (hasAVX2,    interleavedIQSignedWordToFloatAVX vInput)                 ]         assert res