module Hardware.SiClock.FSK
where
import Control.Monad
import Control.Monad.IO.Class
import Control.Concurrent (threadDelay)
import Data.Ratio
import Data.Time
import Hardware.SiClock
clkOff :: Synth ()
clkOff = setCLKControl CLK_0 [CLK_off]
someMsgBaudot :: String
someMsgBaudot = concatMap addStartStop
[ "10000","00001","00101","10000","00100","11011"
,"10111","10011","11111","00100","00011","11001","01110","00100"]
where
addStartStop :: String -> String
addStartStop x = "0" ++ reverse x ++ "11"
symbolTime45 :: DiffTime
symbolTime45 = 0.022
rtty :: DiffTime -> Frequency -> String -> Synth ()
rtty symbolTime f msg = do
liftIO $ print msg
pllFreq <- askMaxPLLFrequency
xtalFreq <- askXtalFrequency
let
space = f + 2125
mark = f + 2295
clkDivider = (round (pllFreq / mark) % 1)
pllMarkConf = toDividerConf 0 ( mark * clkDivider / xtalFreq )
pllSpaceConf = toDividerConf 0 ( space * clkDivider / xtalFreq )
sendSymbol '1' = setDividerRaw PLL_A pllMarkConf
sendSymbol '0' = setDividerRaw PLL_A pllSpaceConf
sendSymbol _ = setDividerRaw PLL_A pllSpaceConf
setCLKDivider CLK_0 0 clkDivider
setCLKControl CLK_0 [CLK_on,CLK_multi,CLK_DRV8,CLK_multiPLLA,CLK_integer]
pllReset
sendSymbol '1'
now <- liftIO $ fmap utctDayTime getCurrentTime
let times = [now+symbolTime, now + 2*symbolTime ..]
d <- forM (zip times msg) $ \(t,c) -> do
delay <- liftIO $ waitUntil t
sendSymbol c
return delay
liftIO $ print $ minimum d
setCLKControl CLK_0 [CLK_off]
timedFrequencyHopping :: Frequency -> [(DiffTime,Frequency)] -> Synth ()
timedFrequencyHopping baseFrequency schedule = do
pllFreq <- askMaxPLLFrequency
xtalFreq <- askXtalFrequency
let
startTimes = map fst schedule
clkDivider = (floor (pllFreq / baseFrequency ) % 1)
pllDividers
= map (\(_,f) -> toDividerConf 0 $
(f + baseFrequency) * clkDivider / xtalFreq)
schedule
((start_time,start_divider):plan) = zip startTimes pllDividers
setCLKDivider CLK_0 0 clkDivider
pllReset
void $ liftIO $ waitUntil start_time
setDividerRaw PLL_A start_divider
setCLKControl CLK_0 [CLK_on,CLK_multi,CLK_DRV8,CLK_multiPLLA,CLK_integer]
d <- forM plan $ \(t,divider) -> do
delay <- liftIO $ waitUntil t
setDividerRaw PLL_A divider
return delay
liftIO $ print $ minimum d
setCLKControl CLK_0 [CLK_off]
waitUntil :: DiffTime -> IO Int
waitUntil time = do
now <- fmap utctDayTime getCurrentTime
let
sleep :: Int
sleep = truncate $ (time now) * 1000000
if sleep < 0
then putStrLn "missed time slot"
else threadDelay sleep
return sleep