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 ()
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
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 ()
getOffsetPtr page offset = 
    
    (\memmap -> plusPtr memmap (page * fpgaPageSize + offset)) <$> getPtr
fpgaMapSize = 0x100000 * 8
addrAms = 0x40000000
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
withOpenFpga :: FpgaArm () -> IO ()
withOpenFpga act = undefined
instance FpgaSetGet FpgaArm where 
    fpgaGet = undefined
    fpgaSet = undefined
#endif