Lambdaya 0.1.1.0 → 0.2.0.0
raw patch · 5 files changed
+472/−276 lines, 5 filesdep +binarydep +networkdep +pipesPVP ok
version bump matches the API change (PVP)
Dependencies added: binary, network, pipes, pipes-binary, pipes-network, pipes-parse
API changes (from Hackage documentation)
- System.RedPitaya.Fpga: data Fpga a
- System.RedPitaya.Fpga: instance Control.Monad.Fix.MonadFix System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance Control.Monad.IO.Class.MonadIO System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance GHC.Base.Alternative System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance GHC.Base.Applicative System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance GHC.Base.Functor System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance GHC.Base.Monad System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: instance GHC.Base.MonadPlus System.RedPitaya.Fpga.Fpga
- System.RedPitaya.Fpga: peekFpgaArray :: Page -> Offset -> Int -> Fpga [Registry]
- System.RedPitaya.Fpga: pokeFpgaArray :: Page -> Offset -> [Registry] -> Fpga ()
- System.RedPitaya.Fpga: withOpenFpga :: Fpga a -> IO a
+ System.RedPitaya.Arm: instance System.RedPitaya.Fpga.FpgaSetGet System.RedPitaya.Arm.FpgaArm
+ System.RedPitaya.Arm: type FpgaArm = ReaderT FpgaPtr IO
+ System.RedPitaya.Arm: withOpenFpga :: FpgaArm () -> IO ()
+ System.RedPitaya.Fpga: class (Monad m) => FpgaSetGet m where fpgaGet off = fmap head $ fpgaGetArray off 1 fpgaSet off v = fpgaSetArray off [v] fpgaGetArray off len = sequence $ map fpgaGet [off, off + 4 .. (off + (4 * len))] fpgaSetArray off d = sequence_ $ zipWith fpgaSet [off, off + 4 .. ] d
+ System.RedPitaya.Fpga: fpgaGet :: FpgaSetGet m => Offset -> m Registry
+ System.RedPitaya.Fpga: fpgaGetArray :: FpgaSetGet m => Offset -> Int -> m [Registry]
+ System.RedPitaya.Fpga: fpgaPageSize :: Offset
+ System.RedPitaya.Fpga: fpgaSet :: FpgaSetGet m => Offset -> Registry -> m ()
+ System.RedPitaya.Fpga: fpgaSetArray :: FpgaSetGet m => Offset -> [Registry] -> m ()
+ System.RedPitaya.Fpga: readFpgaArray :: (FpgaSetGet a) => Page -> Offset -> Int -> a [Registry]
+ System.RedPitaya.Fpga: writeFpgaArray :: (FpgaSetGet m) => Page -> Offset -> [Registry] -> m ()
+ System.RedPitaya.Tcp: instance Data.Binary.Class.Binary System.RedPitaya.Tcp.SimpleProt
+ System.RedPitaya.Tcp: instance GHC.Classes.Eq System.RedPitaya.Tcp.SimpleProt
+ System.RedPitaya.Tcp: instance GHC.Show.Show System.RedPitaya.Tcp.SimpleProt
+ System.RedPitaya.Tcp: instance System.RedPitaya.Fpga.FpgaSetGet System.RedPitaya.Tcp.NetworkFpgaSetGet
+ System.RedPitaya.Tcp: runRemoteRp :: HostName -> PortNumber -> NetworkFpgaSetGet () -> IO ()
+ System.RedPitaya.Tcp: runRpServer :: PortNumber -> IO ()
+ System.RedPitaya.Tcp: type NetworkFpgaSetGet = Pipe FpgaProtocol FpgaProtocol IO
- System.RedPitaya.Fpga: dna :: Fpga Integer
+ System.RedPitaya.Fpga: dna :: (FpgaSetGet a) => a Integer
- System.RedPitaya.Fpga: enableAxiMaster :: Channel -> Bool -> Fpga ()
+ System.RedPitaya.Fpga: enableAxiMaster :: (FpgaSetGet a) => Channel -> Bool -> a ()
- System.RedPitaya.Fpga: enableOscDecimationAvarage :: Bool -> Fpga ()
+ System.RedPitaya.Fpga: enableOscDecimationAvarage :: (FpgaSetGet a) => Bool -> a ()
- System.RedPitaya.Fpga: fpgaFmap :: Page -> Offset -> (Registry -> Registry) -> Fpga ()
+ System.RedPitaya.Fpga: fpgaFmap :: (FpgaSetGet m) => Page -> Offset -> (Registry -> Registry) -> m ()
- System.RedPitaya.Fpga: fpgaId :: Fpga Registry
+ System.RedPitaya.Fpga: fpgaId :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: fpgaRead :: Page -> Offset -> Fpga Registry
+ System.RedPitaya.Fpga: fpgaRead :: (FpgaSetGet m) => Page -> Offset -> m Registry
- System.RedPitaya.Fpga: fpgaWrite :: Page -> Offset -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: fpgaWrite :: (FpgaSetGet m) => Page -> Offset -> Registry -> m ()
- System.RedPitaya.Fpga: getAsgBurstDelay :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAsgBurstDelay :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getAsgCounterReadPtr :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAsgCounterReadPtr :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getAsgNumReadCycles :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAsgNumReadCycles :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getAsgNumRepetitions :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAsgNumRepetitions :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getAsgOption :: Fpga Registry
+ System.RedPitaya.Fpga: getAsgOption :: FpgaSetGet a => a Registry
- System.RedPitaya.Fpga: getAsgOptionBExtGatRep :: Fpga Registry
+ System.RedPitaya.Fpga: getAsgOptionBExtGatRep :: FpgaSetGet a => a Registry
- System.RedPitaya.Fpga: getAxiDelayAfterTrigger :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAxiDelayAfterTrigger :: (FpgaSetGet a) => Channel -> a Registry
- System.RedPitaya.Fpga: getAxiLowerAddress :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAxiLowerAddress :: (FpgaSetGet a) => Channel -> a Registry
- System.RedPitaya.Fpga: getAxiUpperAddress :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAxiUpperAddress :: (FpgaSetGet a) => Channel -> a Registry
- System.RedPitaya.Fpga: getAxiWritePtrCurrent :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAxiWritePtrCurrent :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getAxiWritePtrTrigger :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getAxiWritePtrTrigger :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: getDelayAfterTrigger :: Fpga Registry
+ System.RedPitaya.Fpga: getDelayAfterTrigger :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getEqualFilter :: Channel -> Fpga [Registry]
+ System.RedPitaya.Fpga: getEqualFilter :: (FpgaSetGet a) => Channel -> a [Registry]
- System.RedPitaya.Fpga: getExpDirN :: Fpga Registry
+ System.RedPitaya.Fpga: getExpDirN :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getExpDirP :: Fpga Registry
+ System.RedPitaya.Fpga: getExpDirP :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getExpInN :: Fpga Registry
+ System.RedPitaya.Fpga: getExpInN :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getExpInP :: Fpga Registry
+ System.RedPitaya.Fpga: getExpInP :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getExpOut :: GpioType -> PinNum -> Fpga GpioValue
+ System.RedPitaya.Fpga: getExpOut :: FpgaSetGet f => GpioType -> Int -> f GpioValue
- System.RedPitaya.Fpga: getLed :: Fpga Registry
+ System.RedPitaya.Fpga: getLed :: (FpgaSetGet f) => f Registry
- System.RedPitaya.Fpga: getOscBuffer :: Channel -> Offset -> Int -> Fpga [Registry]
+ System.RedPitaya.Fpga: getOscBuffer :: FpgaSetGet a => Channel -> Offset -> Int -> a [Registry]
- System.RedPitaya.Fpga: getOscDecimationRaw :: Fpga Registry
+ System.RedPitaya.Fpga: getOscDecimationRaw :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getOscHysteresis :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getOscHysteresis :: (FpgaSetGet a) => Channel -> a Registry
- System.RedPitaya.Fpga: getOscWpCurrent :: Fpga Registry
+ System.RedPitaya.Fpga: getOscWpCurrent :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getOscWpTrigger :: Fpga Registry
+ System.RedPitaya.Fpga: getOscWpTrigger :: (FpgaSetGet a) => a Registry
- System.RedPitaya.Fpga: getTreshold :: Channel -> Fpga Registry
+ System.RedPitaya.Fpga: getTreshold :: FpgaSetGet a => Channel -> a Registry
- System.RedPitaya.Fpga: resetWriteSM :: Fpga ()
+ System.RedPitaya.Fpga: resetWriteSM :: FpgaSetGet a => a ()
- System.RedPitaya.Fpga: setAsgAmplitudeOffset :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgAmplitudeOffset :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgAmplitudeScale :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgAmplitudeScale :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgBurstDelay :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgBurstDelay :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgCounterReadPtr :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgCounterReadPtr :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgCounterStartOffset :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgCounterStartOffset :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgCounterStep :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgCounterStep :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgCounterWrap :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgCounterWrap :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgNumReadCycles :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgNumReadCycles :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgNumRepetitions :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgNumRepetitions :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAsgOption :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgOption :: FpgaSetGet a => Registry -> a ()
- System.RedPitaya.Fpga: setAsgOptionBExtGatRep :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAsgOptionBExtGatRep :: FpgaSetGet a => Registry -> a ()
- System.RedPitaya.Fpga: setAxiDelayAfterTrigger :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAxiDelayAfterTrigger :: (FpgaSetGet a) => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAxiLowerAddress :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAxiLowerAddress :: (FpgaSetGet a) => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setAxiUpperAddress :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setAxiUpperAddress :: (FpgaSetGet a) => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setDelayAfterTrigger :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setDelayAfterTrigger :: FpgaSetGet a => Registry -> a ()
- System.RedPitaya.Fpga: setEqualFilter :: Channel -> [Registry] -> Fpga ()
+ System.RedPitaya.Fpga: setEqualFilter :: (FpgaSetGet a) => Channel -> [Registry] -> a ()
- System.RedPitaya.Fpga: setExpDir :: GpioType -> GpioDirection -> PinNum -> Fpga ()
+ System.RedPitaya.Fpga: setExpDir :: (ToBool b, FpgaSetGet m) => GpioType -> b -> Int -> m ()
- System.RedPitaya.Fpga: setExpDirN :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setExpDirN :: (FpgaSetGet a) => Registry -> a ()
- System.RedPitaya.Fpga: setExpDirP :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setExpDirP :: (FpgaSetGet a) => Registry -> a ()
- System.RedPitaya.Fpga: setExpOut :: GpioType -> GpioValue -> PinNum -> Fpga ()
+ System.RedPitaya.Fpga: setExpOut :: (ToBool b, FpgaSetGet m) => GpioType -> b -> Int -> m ()
- System.RedPitaya.Fpga: setExpOutN :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setExpOutN :: (FpgaSetGet a) => Registry -> a ()
- System.RedPitaya.Fpga: setExpOutP :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setExpOutP :: (FpgaSetGet a) => Registry -> a ()
- System.RedPitaya.Fpga: setLed :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setLed :: (FpgaSetGet f) => Registry -> f ()
- System.RedPitaya.Fpga: setOscDecimation :: OscDecimation -> Fpga ()
+ System.RedPitaya.Fpga: setOscDecimation :: (FpgaSetGet a) => OscDecimation -> a ()
- System.RedPitaya.Fpga: setOscDecimationRaw :: Registry -> Fpga ()
+ System.RedPitaya.Fpga: setOscDecimationRaw :: (FpgaSetGet a) => Registry -> a ()
- System.RedPitaya.Fpga: setOscHysteresis :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setOscHysteresis :: (FpgaSetGet a) => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: setOscTrigger :: TriggerSource -> Fpga ()
+ System.RedPitaya.Fpga: setOscTrigger :: FpgaSetGet a => TriggerSource -> a ()
- System.RedPitaya.Fpga: setTreshold :: Channel -> Registry -> Fpga ()
+ System.RedPitaya.Fpga: setTreshold :: FpgaSetGet a => Channel -> Registry -> a ()
- System.RedPitaya.Fpga: triggerDelayEnded :: Fpga Bool
+ System.RedPitaya.Fpga: triggerDelayEnded :: (FpgaSetGet a) => a Bool
- System.RedPitaya.Fpga: triggerNow :: Fpga ()
+ System.RedPitaya.Fpga: triggerNow :: FpgaSetGet a => a ()
Files
- Lambdaya.cabal +17/−4
- src/System/RedPitaya/Arm.hs +120/−0
- src/System/RedPitaya/Fpga.hs +115/−179
- src/System/RedPitaya/Tcp.hs +193/−0
- src/System/RedPitaya/Tutorial.hs +27/−93
Lambdaya.cabal view
@@ -10,7 +10,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.1.1.0+version: 0.2.0.0 -- A short (one-line) description of the package. synopsis: Library for RedPitaya @@ -53,7 +53,10 @@ library -- Modules exported by the library.- exposed-modules: System.RedPitaya.Fpga, System.RedPitaya.Tutorial+ exposed-modules: System.RedPitaya.Fpga, + System.RedPitaya.Arm,+ System.RedPitaya.Tcp,+ System.RedPitaya.Tutorial -- Modules included in this library but not exported. -- other-modules: @@ -64,8 +67,18 @@ -- Other library packages from which modules are imported. build-depends: base >= 3 && < 5, - mtl >= 2 && < 3, - unix >= 2 && < 3+ mtl >= 2 && < 3,+ network >= 2 && < 3,+ binary >=0 && <1,+ pipes >=4 && <5,+ pipes-network >=0 && <1,+ pipes-binary >= 0 && <1,+ pipes-parse >= 3 && <4+ + if arch(arm) {+ build-depends: unix >= 2 && < 3+ }+ -- Directories containing source files. hs-source-dirs: src
+ src/System/RedPitaya/Arm.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE CPP #-}++-- | +-- <http://redpitaya.com/ Red Pitaya> library for accessing FPGA from arm.+-- This code can be executed only natively on RedPitay Zinq proc using arm ghc compiler +--+-- check <https://github.com/ra1u/Lambdaya/blob/master/doc/build.md doc/build.md>+-- for notes on how to compile crosscompiler ++module System.RedPitaya.Arm (+ FpgaArm,+ withOpenFpga,+) where+++#ifdef arm_HOST_ARCH++import Foreign.C.Types+import Foreign.Marshal.Array+import System.Posix.IO+import Foreign.Storable++#endif++import System.RedPitaya.Fpga+import Control.Monad.Reader +import Foreign.Ptr+++type FpgaPtr = Ptr ()++-- | FpgaSetGet get for running on Arm+type FpgaArm = ReaderT FpgaPtr IO+++#ifdef arm_HOST_ARCH++runArm :: FpgaArm a -> FpgaPtr -> IO a+runArm = runReaderT+++instance FpgaSetGet FpgaArm where + fpgaGet o = do+ p <- getPtr+ liftIO $ peek $ plusPtr p o+ fpgaSet o reg = do+ p <- getPtr+ liftIO $ poke (plusPtr p o) reg+ fpgaGetArray o len = do+ p <- getPtr+ liftIO $ peekArray len (plusPtr p o)+ fpgaSetArray o xs = do+ p <- getPtr+ liftIO $ pokeArray (plusPtr p o) xs++getPtr :: FpgaArm FpgaPtr+getPtr = ask++-- | This function handles initialising Fpga memory mapping and+-- evaluates 'Fpga' action.+withOpenFpga :: FpgaArm () -> IO ()+withOpenFpga act = do+ fd <- openFd "/dev/mem" ReadWrite Nothing defaultFileFlags+ setFdOption fd SynchronousWrites True+ p <- mmap nullPtr fpgaMapSize (c'PROT_READ + c'PROT_WRITE ) c'MAP_SHARED (fromIntegral fd) addrAms+ runArm act p+ munmap p fpgaMapSize+ return ()+++-- | get raw pointer on fpga registry calculated from page, offset +-- and internal state that holds memory mapped pointer+-- getOffsetPtr :: Page -> Offset -> FpgaArm (Ptr Registry)+getOffsetPtr page offset = + -- offset on getPtr + (\memmap -> plusPtr memmap (page * fpgaPageSize + offset)) <$> getPtr++++++fpgaMapSize = 0x100000 * 8+addrAms = 0x40000000+++---------- mmap bindings++foreign import ccall "mmap" mmap+ :: Ptr () -> CSize -> CInt -> CInt-> CInt-> CInt -> IO (Ptr ())++foreign import ccall "munmap" munmap+ :: Ptr () -> CSize -> IO CInt++c'PROT_EXEC = 4+c'PROT_NONE = 0+c'PROT_READ = 1+c'PROT_WRITE = 2+c'MAP_FIXED = 16+c'MAP_PRIVATE = 2+c'MAP_SHARED = 1+c'MAP_FAILED = wordPtrToPtr 4294967295+#else+++-- | This function handles initialising Fpga memory mapping and+-- evaluates 'Fpga' action.+withOpenFpga :: FpgaArm () -> IO ()+withOpenFpga act = undefined++instance FpgaSetGet FpgaArm where + fpgaGet = undefined+ fpgaSet = undefined++#endif+++
src/System/RedPitaya/Fpga.hs view
@@ -1,13 +1,12 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | --- <http://redpitaya.com/ Red Pitaya> native library for accessing Fpga+-- <http://redpitaya.com/ Red Pitaya> library for accessing Fpga module System.RedPitaya.Fpga (- Fpga, Registry, Channel(..),- withOpenFpga,+ FpgaSetGet(..),+ -- * Housekeeping -- | various housekeeping and Gpio functions fpgaId,@@ -81,123 +80,84 @@ getAsgBurstDelay, setAsgBurstDelay, -- * Plumbing- -- | low level functions for direct Fpga access, used to extend interface+ -- | low level helper functions, used to extend interface Page, Offset, fpgaRead, fpgaWrite, fpgaFmap,- pokeFpgaArray,- peekFpgaArray+ writeFpgaArray,+ readFpgaArray,+ fpgaPageSize ) where -import Foreign.C.Types-import Foreign.Ptr-import Foreign.Marshal.Array-import System.Posix.IO import Data.Int import Data.Word import Data.Bits-import Foreign.Storable + import Control.Monad import Control.Applicative-import Control.Monad.State -+import Data.Traversable as DT -fpgaPageSize = 0x100000-fpgaMapSize = 0x100000 * 8-addrAms = 0x40000000--type FpgaPtr = Ptr ()-type FpgaState = FpgaPtr- -- | type representing fpga memory offset from page type Offset = Int -- | type representing fpga memory page type Page = Int -- | type representing fpga registry type Registry = Word32--- | Fpga monad is hidden behind this type-type StateMonad a = StateT FpgaState IO a --- | Environment where one can read and write Fpga registries-newtype Fpga a = Fpga (StateMonad a) - deriving (Functor,Applicative, Monad,MonadIO, MonadFix, MonadPlus, Alternative) --- | Redpitaya Channel A or B.-data Channel = A | B--getStateType :: Fpga a -> StateMonad a-getStateType (Fpga s) = s ---- Constructor-fpgaState a = Fpga ( StateT a )--runFpga :: Fpga a -> FpgaState -> IO (a,FpgaState) -runFpga (Fpga s) = runStateT s--store :: FpgaState -> Fpga ()-store v = fpgaState $ \x -> ( return ((),v) )--getState :: Fpga FpgaState-getState = fpgaState $ \x -> ( return (x,x) )+-- | size of Fpga page+fpgaPageSize = 0x100000 :: Offset -getPtr :: Fpga FpgaPtr-getPtr = getState+-- | FpgaSetGet is typeclass for acesssing Fpga+class (Monad m) => FpgaSetGet m where+ fpgaGet :: Offset -> m Registry+ fpgaSet :: Offset -> Registry -> m ()+ fpgaGetArray :: Offset -> Int -> m [Registry]+ fpgaSetArray :: Offset -> [Registry] -> m ()+ -- default implemetations of each others so + -- user can provide only one set and one get if requred+ fpgaGet off = fmap head $ fpgaGetArray off 1+ fpgaSet off v = fpgaSetArray off [v]+ fpgaGetArray off len = sequence $ map fpgaGet [off, off+4 .. (off + (4*len))]+ fpgaSetArray off d = sequence_ $ zipWith fpgaSet [off, off+4 .. ] d --- | This function handles initialising Fpga memory mapping and--- evaluates 'Fpga' action.-withOpenFpga :: Fpga a -> IO a-withOpenFpga act = do- fd <- openFd "/dev/mem" ReadWrite Nothing defaultFileFlags- setFdOption fd SynchronousWrites True- p <- mmap nullPtr fpgaMapSize (c'PROT_READ + c'PROT_WRITE ) c'MAP_SHARED (fromIntegral fd) addrAms- (r,s) <- runFpga act p- munmap p fpgaMapSize- return r+-- | Redpitaya Channel A or B.+data Channel = A | B --- | get raw pointer on fpga registry calculated from page, offset --- and internal state that holds memory mapped pointer-getOffsetPtr :: Page -> Offset -> Fpga (Ptr Registry)-getOffsetPtr page offset = - -- offset on getPtr - (\memmap -> plusPtr memmap (page * fpgaPageSize + offset)) <$> getPtr+getTotalOffset :: Page -> Offset -> Offset+getTotalOffset page offset = page * fpgaPageSize + offset -- | direct read from fpga registry-fpgaRead :: Page -> Offset -> Fpga Registry-fpgaRead page offset = do- p <- getOffsetPtr page offset- liftIO $ peek p+--fpgaRead :: Page -> Offset -> Fpga FpgaMmapM Registry+fpgaRead :: (FpgaSetGet m) => Page -> Offset -> m Registry+fpgaRead page offset = fpgaGet $ getTotalOffset page offset -- | direct write in fpga registry-fpgaWrite :: Page -> Offset -> Registry -> Fpga ()-fpgaWrite page offset reg = do- p <- getOffsetPtr page offset- liftIO $ poke p reg+fpgaWrite :: (FpgaSetGet m) => Page -> Offset -> Registry -> m ()+fpgaWrite page offset reg = fpgaSet (getTotalOffset page offset) reg -- | apply transformation on fpga registry value -fpgaFmap :: Page -> Offset -> (Registry -> Registry) -> Fpga ()+fpgaFmap :: (FpgaSetGet m) => Page -> Offset -> (Registry -> Registry) -> m () fpgaFmap page offset f = do reg <- fpgaRead page offset fpgaWrite page offset (f reg) -- | write array in fpga memory-pokeFpgaArray :: Page -> Offset -> [Registry] -> Fpga ()-pokeFpgaArray page offset xs = do- p <- getOffsetPtr page offset- liftIO $ pokeArray p xs+writeFpgaArray :: (FpgaSetGet m) => Page -> Offset -> [Registry] -> m ()+writeFpgaArray page offset = fpgaSetArray $ getTotalOffset page offset + -- | read array from fpga memory, passing page, offset and length-peekFpgaArray :: Page -> Offset -> Int -> Fpga [Registry]-peekFpgaArray page offset len = do- p <- getOffsetPtr page offset- liftIO $ peekArray len p+readFpgaArray :: (FpgaSetGet a) => Page -> Offset -> Int -> a [Registry]+readFpgaArray page offset = fpgaGetArray ( getTotalOffset page offset ) @@ -205,11 +165,11 @@ -- * Housekeeping memory map -- | get ID , 0 prototype , 1 release-fpgaId :: Fpga Registry+fpgaId :: (FpgaSetGet a) => a Registry fpgaId = fpgaRead 0 0 -- | get DNA-dna :: Fpga Integer+dna :: (FpgaSetGet a) => a Integer dna = do dna1 <- fromIntegral <$> fpgaRead 0 4 dna2 <- fromIntegral <$> fpgaRead 0 8@@ -218,49 +178,49 @@ -- | set expansion connector direction P registry -- -- 1 out , 0 in -setExpDirP :: Registry -> Fpga ()+setExpDirP :: (FpgaSetGet a) => Registry -> a () setExpDirP = fpgaWrite 0 0x10 -- | get expansion connector direction P registry -- -- 1 out , 0 in -getExpDirP :: Fpga Registry+getExpDirP :: (FpgaSetGet a) => a Registry getExpDirP = fpgaRead 0 0x10 -- | set expansion connector direction N registry -- -- 1 out , 0 in -setExpDirN :: Registry -> Fpga ()+setExpDirN :: (FpgaSetGet a) => Registry -> a () setExpDirN = fpgaWrite 0 0x14 -- | get expansion connector direction N registry -- -- 1 out , 0 in -getExpDirN :: Fpga Registry+getExpDirN :: (FpgaSetGet a) => a Registry getExpDirN = fpgaRead 0 0x14 -- | expansion connector P output registry value-setExpOutP :: Registry -> Fpga ()+setExpOutP :: (FpgaSetGet a) => Registry -> a () setExpOutP = fpgaWrite 0 0x18 -- | expansion connector P output registry value-getExpOutP :: Fpga Registry+getExpOutP :: (FpgaSetGet a) => a Registry getExpOutP = fpgaRead 0 0x18 -- | expansion connector N output registry value-setExpOutN :: Registry -> Fpga ()+setExpOutN :: (FpgaSetGet a) => Registry -> a () setExpOutN = fpgaWrite 0 0x1C -- | expansion connector N output registry value-getExpOutN :: Fpga Registry+getExpOutN :: (FpgaSetGet a) => a Registry getExpOutN = fpgaRead 0 0x1C -- | expansion connector P input registry value-getExpInP :: Fpga Registry-getExpInP = fpgaRead 0 0x20+getExpInP :: (FpgaSetGet a) => a Registry+getExpInP = fpgaRead 0 0x20 -- | expansion connector N input registry value-getExpInN :: Fpga Registry+getExpInN :: (FpgaSetGet a) => a Registry getExpInN = fpgaRead 0 0x24 -- | type of gpio can be either P on N@@ -294,7 +254,6 @@ type PinNum = Int -- | Sets direction of pin-setExpDir :: GpioType -> GpioDirection -> PinNum -> Fpga () setExpDir N d p = setBitValue d p <$> getExpDirN >>= setExpDirN setExpDir P d p = setBitValue d p <$> getExpDirP >>= setExpDirP @@ -310,7 +269,6 @@ toBool Hi = True -- | Sets outout value of pin-setExpOut :: GpioType -> GpioValue -> PinNum -> Fpga () -- read using getExpOutN , fmap over setBitValue and bind in setExpOutX setExpOut N v p = setBitValue v p <$> getExpOutN >>= setExpOutN setExpOut P v p = setBitValue v p <$> getExpOutP >>= setExpOutP@@ -321,34 +279,37 @@ toGpioValue False = Low -- | Sets output value of single pin-getExpOut :: GpioType -> PinNum -> Fpga GpioValue getExpOut N p = (\x -> toGpioValue ( testBit x p )) <$> getExpOutN getExpOut P p = (\x -> toGpioValue ( testBit x p )) <$> getExpOutP -- | write in led registry-setLed :: Registry -> Fpga ()+setLed :: (FpgaSetGet f) => Registry -> f () setLed = fpgaWrite 0 0x30 -- | read in led registry-getLed :: Fpga Registry-getLed = fpgaRead 0 0x30+getLed :: (FpgaSetGet f) => f Registry+getLed = fpgaRead 0 0x30 ++ --------------------------------------- -- * Oscilloscope -osciloscpeFpgaPage :: Int osciloscpeFpgaPage = 1 +fpgaWriteOsc :: FpgaSetGet a => Offset -> Registry -> a () fpgaWriteOsc = fpgaWrite osciloscpeFpgaPage++fpgaReadOsc :: FpgaSetGet a => Offset -> a Registry fpgaReadOsc = fpgaRead osciloscpeFpgaPage -- | reset write state machine for oscilloscope-resetWriteSM :: Fpga ()+resetWriteSM :: FpgaSetGet a => a () resetWriteSM = fpgaWriteOsc 0 2 -- | start writing data into memory (ARM trigger).-triggerNow :: Fpga ()+triggerNow :: FpgaSetGet a => a () triggerNow = fpgaWriteOsc 0 1 -- | oscilloscope trigger selection@@ -374,7 +335,6 @@ deriving (Show) -- | set oscilloscope trigger-setOscTrigger :: TriggerSource -> Fpga () setOscTrigger Immediately = setOscTriggerHelper 1 setOscTrigger ChAPositiveEdge = setOscTriggerHelper 2 setOscTrigger ChANegativeEdge = setOscTriggerHelper 3@@ -385,40 +345,37 @@ setOscTrigger AWGPositiveEdge = setOscTriggerHelper 8 setOscTrigger AWGNegativeEdge = setOscTriggerHelper 9 --setOscTriggerHelper :: Registry -> Fpga ()+setOscTriggerHelper :: FpgaSetGet a => Registry -> a () setOscTriggerHelper = fpgaWriteOsc 0x4 -- | when trigger delay is value becomes 'True'-triggerDelayEnded :: Fpga Bool+triggerDelayEnded :: (FpgaSetGet a) => a Bool triggerDelayEnded = (==0) <$> fpgaReadOsc 0x4 -- | Ch x threshold, makes trigger when ADC value cross this value-setTreshold :: Channel -> Registry -> Fpga () setTreshold A = fpgaWriteOsc 0x8 setTreshold B = fpgaWriteOsc 0xc -- | gets ch x threshold-getTreshold :: Channel -> Fpga Registry getTreshold A = fpgaReadOsc 0x8 getTreshold B = fpgaReadOsc 0xc -- | Number of decimated data after trigger written into memory-setDelayAfterTrigger :: Registry -> Fpga ()+setDelayAfterTrigger :: FpgaSetGet a => Registry -> a () setDelayAfterTrigger = fpgaWriteOsc 0x10 -- | gets delay after trigger value-getDelayAfterTrigger :: Fpga Registry+getDelayAfterTrigger :: (FpgaSetGet a) => a Registry getDelayAfterTrigger = fpgaReadOsc 0x10 -- | sets oscilloscope decimation registry, allows only -- 1,8, 64,1024,8192,65536. If other value is written data will NOT be correct.-setOscDecimationRaw :: Registry -> Fpga ()+setOscDecimationRaw :: (FpgaSetGet a) => Registry -> a () setOscDecimationRaw = fpgaWriteOsc 0x14 -- | oscilloscope decimation registry value-getOscDecimationRaw :: Fpga Registry+getOscDecimationRaw :: (FpgaSetGet a) => a Registry getOscDecimationRaw = fpgaReadOsc 0x14 -- | oscilloscope decimation@@ -432,7 +389,7 @@ deriving (Show) -- | set oscilloscope decimation-setOscDecimation :: OscDecimation -> Fpga ()+setOscDecimation :: (FpgaSetGet a) => OscDecimation -> a () setOscDecimation OscDec1 = setOscDecimationRaw 1 setOscDecimation OscDec8 = setOscDecimationRaw 8 setOscDecimation OscDec64 = setOscDecimationRaw 64@@ -441,91 +398,90 @@ setOscDecimation OscDec65536 = setOscDecimationRaw 65536 -- | write pointer - current-getOscWpCurrent:: Fpga Registry-getOscWpCurrent = fpgaReadOsc 0x18+getOscWpCurrent :: (FpgaSetGet a) => a Registry+getOscWpCurrent = fpgaReadOsc 0x18 -- | write pointer - trigger-getOscWpTrigger :: Fpga Registry+getOscWpTrigger :: (FpgaSetGet a) => a Registry getOscWpTrigger = fpgaReadOsc 0x1C -- | ch x hysteresis-getOscHysteresis :: Channel -> Fpga Registry+getOscHysteresis :: (FpgaSetGet a) => Channel -> a Registry getOscHysteresis A = fpgaReadOsc 0x20 getOscHysteresis B = fpgaReadOsc 0x24 -- | set ch x hysteresis-setOscHysteresis :: Channel -> Registry -> Fpga ()+setOscHysteresis :: (FpgaSetGet a) => Channel -> Registry -> a () setOscHysteresis A = fpgaWriteOsc 0x20 setOscHysteresis B = fpgaWriteOsc 0x24 -- | Enable signal average at decimation True enables, False disables-enableOscDecimationAvarage :: Bool -> Fpga ()+enableOscDecimationAvarage :: (FpgaSetGet a) => Bool -> a () enableOscDecimationAvarage True = fpgaWriteOsc 0x28 1 enableOscDecimationAvarage False = fpgaWriteOsc 0x28 0 -- | set ch A equalization filter, takes array with coefficients [AA,BB,KK,PP]-setEqualFilter :: Channel -> [Registry] -> Fpga ()-setEqualFilter A = pokeFpgaArray osciloscpeFpgaPage 0x30 . take 4-setEqualFilter B = pokeFpgaArray osciloscpeFpgaPage 0x40 . take 4+setEqualFilter :: (FpgaSetGet a) => Channel -> [Registry] -> a ()+setEqualFilter A = writeFpgaArray osciloscpeFpgaPage 0x30 . take 4+setEqualFilter B = writeFpgaArray osciloscpeFpgaPage 0x40 . take 4 -- | get ch x equalization filter, return array with coefficients [AA,BB,KK,PP]-getEqualFilter :: Channel -> Fpga [Registry]-getEqualFilter A = peekFpgaArray osciloscpeFpgaPage 0x30 4-getEqualFilter B = peekFpgaArray osciloscpeFpgaPage 0x40 4-+getEqualFilter :: (FpgaSetGet a) => Channel -> a [Registry]+getEqualFilter A = readFpgaArray osciloscpeFpgaPage 0x30 4+getEqualFilter B = readFpgaArray osciloscpeFpgaPage 0x40 4 -setAxiGeneric' :: Offset -> Channel -> Registry -> Fpga ()+setAxiGeneric' :: (FpgaSetGet a) => Offset -> Channel -> Registry -> a () setAxiGeneric' offest A = fpgaWriteOsc offest setAxiGeneric' offest B = fpgaWriteOsc (offest+0x20) -getAxiGeneric' :: Offset -> Channel -> Fpga Registry+getAxiGeneric' :: (FpgaSetGet a) => Offset -> Channel -> a Registry getAxiGeneric' offest A = fpgaReadOsc offest getAxiGeneric' offest B = fpgaReadOsc (offest+0x20) -- | starting writing address ch x - CH x AXI lower address-setAxiLowerAddress :: Channel -> Registry -> Fpga ()+setAxiLowerAddress :: (FpgaSetGet a) => Channel -> Registry -> a () setAxiLowerAddress = setAxiGeneric' 0x50 -- | read - starting writing address ch x - CH x AXI lower address-getAxiLowerAddress :: Channel -> Fpga Registry+getAxiLowerAddress :: (FpgaSetGet a) => Channel -> a Registry getAxiLowerAddress = getAxiGeneric' 0x50 -- | starting writing address ch x - CH x AXI lower address-setAxiUpperAddress :: Channel -> Registry -> Fpga ()+setAxiUpperAddress :: (FpgaSetGet a) => Channel -> Registry -> a () setAxiUpperAddress = setAxiGeneric' 0x54 -- | read - starting writing address ch x - CH x AXI lower address-getAxiUpperAddress :: Channel -> Fpga Registry+getAxiUpperAddress :: (FpgaSetGet a) => Channel -> a Registry getAxiUpperAddress = getAxiGeneric' 0x54 -- | read - Number of decimated data after trigger written into memory-getAxiDelayAfterTrigger :: Channel -> Fpga Registry+getAxiDelayAfterTrigger :: (FpgaSetGet a) => Channel -> a Registry getAxiDelayAfterTrigger = getAxiGeneric' 0x58 -- | set umber of decimated data after trigger written into memory-setAxiDelayAfterTrigger :: Channel -> Registry -> Fpga ()+setAxiDelayAfterTrigger :: (FpgaSetGet a) => Channel -> Registry -> a () setAxiDelayAfterTrigger = setAxiGeneric' 0x58 -- | Enable AXI master-enableAxiMaster :: Channel -> Bool -> Fpga ()+enableAxiMaster :: (FpgaSetGet a) => Channel -> Bool -> a () enableAxiMaster ch True = setAxiGeneric' 0x5c ch 1 enableAxiMaster ch False = setAxiGeneric' 0x5c ch 0 -- | Write pointer for ch x at time when trigger arrived-getAxiWritePtrTrigger :: Channel -> Fpga Registry+getAxiWritePtrTrigger :: FpgaSetGet a => Channel -> a Registry getAxiWritePtrTrigger = getAxiGeneric' 0x60 -- | current write pointer for ch x-getAxiWritePtrCurrent :: Channel -> Fpga Registry+getAxiWritePtrCurrent :: FpgaSetGet a => Channel -> a Registry getAxiWritePtrCurrent = getAxiGeneric' 0x64 -- | reads oscilloscope buffer for channel x from Fpga passing offset and length. -- buffer should fit within 16k sampling range. -- Returns less than requested data if trying to read over the bounds.-getOscBuffer :: Channel -> Offset -> Int -> Fpga [Registry]-getOscBuffer chan off len = peekFpgaArray osciloscpeFpgaPage (off' + (chOff chan)) len'+getOscBuffer :: FpgaSetGet a => Channel -> Offset -> Int -> a [Registry]+getOscBuffer chan off len = readFpgaArray osciloscpeFpgaPage (off' + (chOff chan)) len' where off' = max 0 off len' = min (0x10000 - off) len@@ -534,10 +490,10 @@ -------------------------------------------------------------------- + -- ASG -- | Set registry with value passed as tuple of bit offests -- | setBits (fromBit,toBit) value rin = ..-setBits :: (Int,Int) -> Registry -> Registry -> Registry setBits (fromBit,toBit) value rin = valueShift .|. hole where ones = complement 0 :: Registry@@ -546,7 +502,6 @@ valueShift = ( shiftL value fromBit ) .&. maskShift -- | read bits range from registy-getBits :: (Int,Int) -> Registry -> Registry getBits (fromBit,toBit) value = shiftR andV fromBit where ones = complement 0 :: Registry@@ -554,51 +509,46 @@ andV = maskShift .&. value -type FpgaSet = Registry -> Fpga ()-type FpgaGet = Fpga Registry -asgFpgaPage = 2 +asgFpgaPage = 2 -fpgaWriteAsg :: Offset -> Registry -> Fpga ()+fpgaWriteAsg :: (FpgaSetGet a) => Offset -> Registry -> a () fpgaWriteAsg = fpgaWrite asgFpgaPage -fpgaReadAsg :: Offset -> Fpga Registry+fpgaReadAsg :: (FpgaSetGet a) => Offset -> a Registry fpgaReadAsg = fpgaRead asgFpgaPage -fpgaFmapAsg :: Offset -> (Registry -> Registry) -> Fpga ()+fpgaFmapAsg :: (FpgaSetGet a) => Offset -> (Registry -> Registry) -> a () fpgaFmapAsg = fpgaFmap asgFpgaPage -fpgaWriteAsgChannel :: Offset -> Channel -> Registry -> Fpga () fpgaWriteAsgChannel offset A = fpgaWriteAsg offset fpgaWriteAsgChannel offset B = fpgaWriteAsg ( offset + 0x20) -fpgaReadAsgChannel :: Offset -> Channel -> Fpga Registry fpgaReadAsgChannel offset A = fpgaReadAsg offset fpgaReadAsgChannel offset B = fpgaReadAsg ( offset + 0x20) -fpgaFmapAsgChannel :: Offset -> (Registry -> Registry) -> Channel -> Fpga () fpgaFmapAsgChannel offset f A = fpgaFmapAsg offset f fpgaFmapAsgChannel offset f B = fpgaFmapAsg ( offset + 0x20) f -- | get ASGoption registry-getAsgOption :: Fpga Registry+getAsgOption :: FpgaSetGet a => a Registry getAsgOption = fpgaReadAsg 0x0 -- | set ASG option registry-setAsgOption :: Registry -> Fpga ()+setAsgOption :: FpgaSetGet a => Registry -> a () setAsgOption = fpgaWriteAsg 0x0 -- | ch B external gated repetitions, -- registry can be either 0x0 or 0x1-setAsgOptionBExtGatRep :: Registry -> Fpga ()-setAsgOptionBExtGatRep reg = fpgaFmapAsg 0 ( setBits (24,24) reg)+setAsgOptionBExtGatRep :: FpgaSetGet a => Registry -> a ()+setAsgOptionBExtGatRep = fpgaFmapAsg 0 . setBits (24,24) -- | get ch B external gated repetitions, -- registry can be either 0x0 or 0x1-getAsgOptionBExtGatRep :: Fpga Registry+getAsgOptionBExtGatRep :: FpgaSetGet a => a Registry getAsgOptionBExtGatRep = getBits (24,24) <$> getAsgOption -- | TODO others@@ -606,75 +556,61 @@ -- | todo other registries -- | Ch x amplitude scale (14 bist) - out = (data*scale)/0x2000 + offset-setAsgAmplitudeScale :: Channel -> Registry -> Fpga () setAsgAmplitudeScale ch reg = fpgaFmapAsgChannel 0x4 ( setBits (16,29) reg ) ch -- | Ch x amplitude offset (14 bits) - out = (data*scale)/0x2000 + offset -setAsgAmplitudeOffset :: Channel -> Registry -> Fpga () setAsgAmplitudeOffset ch reg = fpgaFmapAsgChannel 0x4 ( setBits (0,13) reg ) ch -- | Ch x counter wrap - Value where counter wraps around. Depends on SM wrap setting. -- If it is 1 new value is get by wrap, if value is 0 counter goes to offset value. -- 16 bits for decimals.-setAsgCounterWrap :: Channel -> Registry -> Fpga ()+setAsgCounterWrap :: FpgaSetGet a => Channel -> Registry -> a () setAsgCounterWrap = fpgaWriteAsgChannel 0x8 -- | Ch x Counter start offset. Start offset when trigger arrives. 16 bits for decimals.-setAsgCounterStartOffset :: Channel -> Registry -> Fpga ()+setAsgCounterStartOffset :: FpgaSetGet a => Channel -> Registry -> a () setAsgCounterStartOffset = fpgaWriteAsgChannel 0xc -- | Ch x counter step. 16 bits for decimals.-setAsgCounterStep :: Channel -> Registry -> Fpga ()+setAsgCounterStep :: FpgaSetGet a => Channel -> Registry -> a () setAsgCounterStep = fpgaWriteAsgChannel 0x10 -- | get ch x buffer current read pointer-getAsgCounterReadPtr :: Channel -> Fpga Registry+getAsgCounterReadPtr :: FpgaSetGet a => Channel -> a Registry getAsgCounterReadPtr = fpgaReadAsgChannel 0x14 -- | set ch x buffer current read pointer-setAsgCounterReadPtr :: Channel -> Registry -> Fpga ()+setAsgCounterReadPtr :: FpgaSetGet a => Channel -> Registry -> a () setAsgCounterReadPtr = fpgaWriteAsgChannel 0x14 -- | get ch x number of read cycles in one burst-getAsgNumReadCycles :: Channel -> Fpga Registry+getAsgNumReadCycles :: FpgaSetGet a => Channel -> a Registry getAsgNumReadCycles = fpgaReadAsgChannel 0x18 -- | set ch x number of read cycles in one burst-setAsgNumReadCycles :: Channel -> Registry -> Fpga ()+setAsgNumReadCycles :: FpgaSetGet a => Channel -> Registry -> a () setAsgNumReadCycles = fpgaWriteAsgChannel 0x18 -- | get ch x number of read cycles in one burst-getAsgNumRepetitions :: Channel -> Fpga Registry+getAsgNumRepetitions :: FpgaSetGet a => Channel -> a Registry getAsgNumRepetitions = fpgaReadAsgChannel 0x1a -- | set ch x number of read cycles in one burst-setAsgNumRepetitions :: Channel -> Registry -> Fpga ()+setAsgNumRepetitions :: FpgaSetGet a => Channel -> Registry -> a () setAsgNumRepetitions = fpgaWriteAsgChannel 0x1a -- | get ch x delay between burst repetitions, granularity=1us-getAsgBurstDelay :: Channel -> Fpga Registry+getAsgBurstDelay :: FpgaSetGet a => Channel -> a Registry getAsgBurstDelay = fpgaReadAsgChannel 0x20 -- | set ch x delay between burst repetitions, granularity=1us-setAsgBurstDelay :: Channel -> Registry -> Fpga ()+setAsgBurstDelay :: FpgaSetGet a => Channel -> Registry -> a () setAsgBurstDelay = fpgaWriteAsgChannel 0x20 ----------- mmap bindings -foreign import ccall "mmap" mmap- :: Ptr () -> CSize -> CInt -> CInt-> CInt-> CInt -> IO (Ptr ()) -foreign import ccall "munmap" munmap- :: Ptr () -> CSize -> IO CInt -c'PROT_EXEC = 4-c'PROT_NONE = 0-c'PROT_READ = 1-c'PROT_WRITE = 2-c'MAP_FIXED = 16-c'MAP_PRIVATE = 2-c'MAP_SHARED = 1-c'MAP_FAILED = wordPtrToPtr 4294967295+
+ src/System/RedPitaya/Tcp.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+++-- | Implemention of both client and server for contolling fpga over tcp+module System.RedPitaya.Tcp (+ NetworkFpgaSetGet(..),+ runRemoteRp ,+ runRpServer+) where++import System.RedPitaya.Fpga+import System.RedPitaya.Arm++import Network.Socket as NS+import Control.Concurrent (forkIO)+import Data.Word++import Pipes as P+import qualified Pipes.Prelude as PP+import Pipes.Parse++import Pipes.Binary +import Data.Binary.Get+import Data.Binary.Put+import Pipes.Network.TCP+++type Len = Word32+type Addr = Word32+type Reg = Word32+data SimpleProt = WriteSingle Addr Reg + | WriteArray Len Addr [Reg] + | ReadSingle Addr+ | ReadArray Len Addr+ | RespSingle Reg+ | RespArray Len [Reg]+ | Error deriving (Show,Eq)++++toint (WriteSingle _ a) = fromIntegral a+single w = WriteSingle 1 w++cWriteSingle = 1+cWriteArray = 2+cReadSingle = 3+cReadArray = 4+cRespSingle = 5+cRespArray = 6+cError = 7++instance Binary SimpleProt where+ put ( WriteSingle a r) = putWord32be cWriteSingle+ >> putWord32be a+ >> putWord32be r++ put ( WriteArray len a xs) = putWord32be cWriteArray+ >> putWord32be len+ >> putWord32be a+ >> mapM_ putWord32be xs++ put (ReadSingle a) = putWord32be cReadSingle+ >> putWord32be a++ put (ReadArray len addr) = putWord32be cReadArray + >> putWord32be addr++ put (RespSingle reg) = putWord32be cRespSingle >> putWord32be reg++ put (RespArray len arr) = putWord32be cRespArray+ >> putWord32be len+ >> mapM_ putWord32be arr++ put Error = putWord32be cError++ get = do+ ty <- getWord32be+ case () + of _+ | ty == cWriteSingle -> WriteSingle <$> getWord32be <*> getWord32be+ | ty == cWriteArray -> do+ len <- getWord32be+ WriteArray len <$> getWord32be <*> parseArray len + | ty == cReadSingle -> ReadSingle <$> getWord32be+ | ty == cReadArray -> ReadArray <$> getWord32be <*> getWord32be+ | ty == cRespSingle -> RespSingle <$> getWord32be+ | ty == cRespArray -> do + len <- getWord32be+ RespArray len <$> parseArray len + | otherwise -> return Error++parseArray len = sequenceA ( replicate ( fromIntegral len) getWord32be )++-- | This can be used to implement run server on RedPitaya+runRpServer:: PortNumber -> IO ()+runRpServer port = do + sock <- socket AF_INET Stream 0+ setSocketOption sock ReuseAddr 1+ bindSocket sock (SockAddrInet port iNADDR_ANY)+ NS.listen sock 2+ mainLoop sock++mainLoop :: Socket -> IO ()+mainLoop s = go where+ go = do+ (sock, addr) <- NS.accept s+ setSocketOption sock NoDelay 1+ let rx = fromSocket sock (4*1024)+ let tx = toSocket sock+ forkIO $ runConn (rx,tx)+ go++runConn (rx,tx) = withOpenFpga $ runEffect $ + runStream rx >-> P.for cat processPacket >-> PP.takeWhile (/= Error) >-> P.for cat encode >-> tx++frInt :: (Integral a, Num b) => a -> b+frInt = fromIntegral++processPacket = handle+ where + handle (WriteSingle addr reg) = lift $ ( fpgaSet (frInt addr) reg )+ handle (WriteArray len addr arr) = lift $ fpgaSetArray (frInt addr) arr+ handle (ReadSingle addr ) = lift (fpgaGet (frInt addr)) >>= (yield . RespSingle )+ handle (ReadArray len addr ) = lift (fpgaGetArray (frInt len) (frInt addr) ) + >>= yield . RespArray len+ handle _ = yield Error+++main :: IO ()+main = do+ sock <- socket AF_INET Stream 0+ setSocketOption sock ReuseAddr 1+ bindSocket sock (SockAddrInet 4242 iNADDR_ANY)+ NS.listen sock 2+ mainLoop sock+ ++runStream :: (Monad m, Binary b) =>+ Producer ByteString (Proxy x x' () b m) r+ -> Proxy x x' () b m ()+++runStream producer = go producer where + go producer = do+ evalStateT parser producer where + parser = do+ v <- decode+ either stop repeat v where+ stop _ = return ()+ repeat a = do+ lift $ yield a+ parser++++--- Pc side+type FpgaProtocol = SimpleProt++-- | Type that implements FpgaSetGet over network+type NetworkFpgaSetGet = Pipe FpgaProtocol FpgaProtocol IO++-- | This evaluates FpgaSetGet action that sends commands on RedPitaya+runRemoteRp :: HostName -> PortNumber -> NetworkFpgaSetGet () -> IO ()+runRemoteRp addr port act = do+ sock <- socket AF_INET Stream 0+ host <- inet_addr addr+ NS.connect sock $ SockAddrInet port host+ setSocketOption sock NoDelay 1+ runEffect $ runStream (fromSocket sock (4*1024)) >-> act >-> P.for cat encode >-> toSocket sock+ close sock+ return ()++instance FpgaSetGet NetworkFpgaSetGet where + fpgaGet offset = do+ yield (ReadSingle $ frInt offset)+ await >>= respsing+ where+ respsing (RespSingle reg) = return reg+ respsing _ = yield Error >> return 0++ fpgaSet off reg = yield $ WriteSingle (frInt off) reg++ fpgaGetArray offset len = do + yield $ ReadArray ( frInt len) (frInt offset)+ await >>= resparray+ where+ resparray (RespArray _ xs) = return xs+ resparray _ = yield Error >> return []++ fpgaSetArray offset xs = yield $ WriteArray ( frInt (length xs)) (frInt offset) xs++
src/System/RedPitaya/Tutorial.hs view
@@ -6,123 +6,57 @@ == tutorial for System.Readpitaya Libraray #tutorial-for-system.readpitaya-libraray# -System.Readpitaya is native haskell library for-<http://redpitaya.com/ redpitaya> that enables direct bindings on+System.Readpitaya native haskell library for+<http://redpitaya.com/ redpitaya> that enables bindings on <https://github.com/RedPitaya/RedPitaya/blob/master/fpga/doc/RedPitaya_HDL_memory_map.odt?raw=true FPGA>.-This library is aimed to run on redpitaya and is inteded for use with-crosscompiler.--To build and run code and examples you need cross-ghc compiler for armel-processor.+It also supports remote redpitaya contolling trough same inteface over+TCP\/IP. -Here it is simpel an minimal example to use library+Here it is simple an minimal example to use library > import System.RedPitaya.Fpga+> import System.RedPitaya.Tcp >-> main = withOpenFpga (setLed 0x55) --withOpenFpga is function, that takes Fpga operation and executes it. It-handels opening and closing of FPGA resources so it is advisable that-that all operation are executed inside and @withOpenFpga@ gets called-only once.--If you take look of prototype setLed you can see that it has protype-@setLed :: Registry -> Fpga ()@ And that can be understand that it takes-@Registy@ (that is 32 bit unsigned integer) and returns @Fpga ()@.-@Fpga a@ is type that can run in @withOpenFpga@ function. @()@ is empty-or void value that is retured after @setLed@ gets called. What @setLed@-does it takes writes registry value at apropriate addres in fpga-registry map described in document FPGA metioned in first section.--In our next example we will build program that displays value that is-written in this registry using function @getLed@--> import System.RedPitaya.Fpga-> import Numeric (showHex)+> rpIp = "10.42.0.219"+> rpPort = 4242 >-> main = do-> reg <- withOpenFpga getLed-> putStrLn ( show reg)--here @reg@ is value can get \"get\" from @withOpenFpga@. Function-@withOpenFpga@ has prototype of \'Fpga a -> IO a\'. That mean that-returns same value as it is returned from executing last command-executed in block. In our case that is just function @getLed@. Since-@getLed :: Fpga Registry@ that mean that ir returns @Fpga Registry@-type.--@IO Registry@ (@a@ in definition of @withOpenFpga@ becomes @Registry@).-We haven\'t mentioned @IO a@ before but that is type one can execute-commands like @putStrLn@ with.+> main = runRemoteRp rpIp rpPort (setLed 0x55) -> import System.RedPitaya.Fpga-> import Numeric (showHex)->-> main = do-> reg <- withOpenFpga ( do-> setLed 0x44-> r <- getLed-> return r-> )-> putStrLn ( show reg )+@runRemoteRp@ is function that execute @FpgaSetGet@ over network. If you+dont have arm-ghc compiler available, you can use compiled binaries+[bin\/server]((https:\/\/github.com\/RedPitaya\/RedPitaya\/blob\/master\/bin\/server)+and run them on RedPitaya. -This code runs two @do@ blocks. One handles IO type where types @IO a@-are running and other do block with type \'Fpga a\'. If one needs to run-IO types inside Fpga block he\/she needs to change IO type to Fpga type-using function liftIO.+Lambdaya libraray also enables execution of same code natively trough+@withOpenFpga@ from Arm module using same @FpgaSetGet@ action. > import System.RedPitaya.Fpga-> import Numeric (showHex)-> import Control.Monad.IO.Class (liftIO)+> import System.RedPitaya.Arm >-> main = do-> withOpenFpga $ do-> setLed 0x44-> reg <- getLed -> liftIO $ putStrLn $ show reg-> putStrLn "done"--In this example we also use build in operator @$@ that works as a-brackets to to the end.--> liftIO $ putStrLn $ showHex reg "" -> -- is same as-> liftIO ( putStrLn ( showHex reg "" ))--If you like to know more about operator @$@ or any other standard-functions used, you can use invaluable search engine-<https://www.haskell.org/hoogle/?hoogle=%24 Hoogle> where is link on-haddock manuals with description and link to source code. Similar search-engines are also availabe at <http://hayoo.fh-wedel.de/ Hayoo!> and-<https://www.stackage.org/ Stackage>.+> main = withOpenFpga (setLed 0x55) -Lets do some more tricks with diodes and using standard+Inspiration for last example is technology from 1970s+https:\/\/www.youtube.com\/watch?v=Hm3AFz4wrw4 > import System.RedPitaya.Fpga+> import System.RedPitaya.Tcp > import Control.Concurrent (threadDelay) > import Data.Bits > import Control.Monad.IO.Class (liftIO) > > knightRider n = do-> let ledn = 1 + abs ((mod n 12) - 6) -- 6,5,4,3,2,1,2,3,4,5,6,7,6,5,4,3,2,1,2,3,4,5,6,7,6,5...+> let ledn = 1 + abs ((mod n 12) - 6) > setLed ( shiftL 1 ledn ) > liftIO ( threadDelay (30000) ) > knightRider (n + 1) >-> main = withOpenFpga (knightRider 0)--@knightRider@ is function that gets caled each time with next-integer.@ledn@ in generated in way that provides numbering in apropriate-order. shiftL function . Next @threadDelay@ delays execution, by 30000-microseconds and since @nightRider@ runs inside @withOpenFpga@ we have-to use @liftIO@ just to make type compatible. Finaly we call-@nightRider@ with next number and whole procees repeats.+> rpIp = "10.42.0.219"+> rpPort = 4242+>+> main = runRemoteRp rpIp rpPort (knightRider 0) -So far we covered lot if of stuff on how to use this library. Even-though all examples were reading and writing to led registry you can be-sure that all function provided by library that has type signature-@Registry -> Fpga ()@ works and can be used just like @setLed@ and all-functions with type signature @Fpga Registry@ works like getLed.+For full interface and fuctions available for contolling and acessing+registries, check Fpga module. -} )