startmacro/setup/quiet/nmq=512 u:card[pic1auto] u:aflag[] u:config[siggen_cfg]

if /nm gt 0 then
  nm siggen ^card (^aflag) ^config
  stop
endif

local nn ntc iset item act lact drate flg 
local skip scale ramfile ramfilem subr value keys
local ports formats rates lengths config_tmpl aconfig
local port format rate length sgain nfft psdr psda
local imode ifreq igain ishp ibw taps ibwf spec imute
local /M/

res acts    "Setup,Idle,Run,Rates,SaveCfg,LoadCfg,nmSigGen,Exit"
res ports   "Module:1,Module:2,Core-AWG:1,Core-AWG:2,TBank-MSP:1,TBank-MSP:2"
res formats "CB,CI"
res rates   "Enter,5,10,12.5,20,25,30,40,50,60,64,70,80,90,100,105,125,150,200,250,480,496"
res lengths "Enter,0.1,0.25,0.5,1,2,5,10,20"

fname config_tmpl cfg siggen_tmpl ,, ice

res aconfig config
callp loadconfig

label again
xcntrl on
xcntrl off

if act eqs "NMSIGGEN"
  nm siggen ^card (^aflag) ^config
  goto again
elseif act eqs "RUN"
  label rerun
  res act "RUN"
  res flg "^aflag|MUXCLK=P"
  if rate gt 250 res flg "^flg|VHS|QDRX"
  res flg "^flg|RFFREQ=^rffreq|RFGAIN=^rfgain|NFGAIN=^nfgain"
  calc drate rate 1e6 *
  calc l:skip drate nfft / psda / psdr / round 1 max
  calc scale 32768
  if "B" subs format calc scale 128
  if "L" subs format calc scale 2e9
  calc bps 2
  if "B" subs format calc bps 1
  if "L" subs format calc bps 4
  if "C" subs format calc bps bps*2
  sedit port l:side "TRIM" ":" "" 
  sedit port portn "TRIM" "" ":" 
  res ramfile "^{card}_^{portn}"
  res ramfilem "^{card}_module^side"
  calc l:len drate*length
  erase/nowarn ramfile ramfilem
  if port eqss "MOD" then
    pic/round=64K create ramfile ^format len/skip drate "NONE"
  else
    pic/round=64K create ramfile ^format len/skip drate "NONE"
    pic/round=64K create ramfilem ^format len/skip drate "NONE"
  endif
  picd/flags=^flg reset ^card 
  loop ntc nn
    callp getspecs nn
    if port eqss "TBANK" then
      sedit "^{card}_core_^nn" ramfilei "LOCASE"
      say "Gen fn=^ramfilei sr=^irate len=^ilen"
      nm icewave/id=wave^nn/tl=8k/wrap/ntap=^taps/fwidth=^ibwf/midx=^spec/amp=32k &
        ^ramfilei{DET=1,AUX=^RAMAUX} shape=^ishp freq=0 gain=0 baud=^ibw*1e6 form=ci rate=^irate elem=^ilen
    endif
  endloop
xpipe/controls on
  if port eqss "CORE" then
    res l:i0 side+2
    sinkpic/id=11/port=core^i0/flags=^flg|MCS=^ntc|NODMA/srate=drate/wb=1/verbose=0 ramfile ramfile card ,,, sgain
    sourcepic/id=12/tl=1/port=module^side/skip=skip/skiponcard/flags=muxclk=N|hxfd/wb=2/verbose=0 ramfilem(fs=^nfft) _cb card
    res icport "^card:^i0"
  elseif port eqss "TBANK" then
    res l:i0 side+2
    sinkpic/id=11/port=core^i0/flags=(^flg|MCS=^ntc|MCI=0|ICSEL|TSIG=MOD)/srate=drate/wb=1/verbose=0 ramfile ramfile card ,,, sgain
    sourcepic/id=12/tl=1/port=module^side/skip=skip/skiponcard/flags=muxclk=N|hxfd/wb=2/verbose=0 ramfilem(fs=^nfft) _cb card
    res icport "^card:^i0"
  else
    sinkpic/id=11/port=^portn/flags=^flg/wb=1 ramfile ramfile card
  endif
  loop ntc nn
    res l:ii (nn-1)*2+side
    callp getspecs nn
    if port eqss "CORE" then
      icecore/id=100+nn/mcid=nn/core=icex/coredev=^icport|mcs=^ntc|mci=^nn|verbose=0/ifmt=ci/ofmt=ci ,,, "MOD" &
        SHAPE=^ishp "NTAP=^taps" FS=^rate*1e6 FSYM=^ibw*1e6 FBWF=^ibwf MIDX=^spec COFF=^ifreq*1e6 GAIN=^igain MUTE=^imute BPW=0
    elseif port eqss "TBANK" then
      res ramfilei "^{card}_core_^nn"
      sinkpic/id=100+nn/port=TUNER^ii/flags=^flg|TSIG=MOD|RGO/srate=rate*1e6 ramfilei ramfilei card -1 ifreq*1e6 igain
    endif
  endloop
  ubiq/wb=3 _cb(fs=0) _cbf nfft HANN 0 ,, psda
  xrtplot/xs=4/xn="Time Domain" _cb -scale scale re
  xdatalist/xs=2/msgid=1/mask=-1/xn="Config File"/mod ^config ^config_tmpl
  xrtplot/xs=3/dbrange=100/xn="PSD"/grid _cbf ,,, d1
xpipe off
  if act eqs "RERUN" goto rerun
  if act neqs "EXIT" 
    res act "SETUP"
    goto again
  endif
endif

erase/nowarn ramfile ramfilem

endmacro

startcontrols

label initialentry
xcontrol/lab=lset menu iset  0 "Settings;"
xcontrol/lab=msg msmon 1
callp dosets
return

label lset
if iset eq 1 then
  res lact act
  xcall menu item 0 "Action;^acts"
  if item le 0 return
  sedit acts act parse item
  if act eqs lact return
  if act eqs "IDLE" 
    callp stopALL
  elseif act eqs "RUN"
    callp exitALL
    stop
  elseif act eqs "RATES"
    picd get card "SPEEDS"
    res act lact
    return
  elseif act eqs "SAVECFG"
    callp save_cfg
    res act lact
  elseif act eqs "LOADCFG"
    callp load_cfg
    res act lact
  elseif act eqs "SETUP"
    callp exitALL
    stop
  elseif act eqs "NMSIGGEN"
    stop
  elseif act eqs "EXIT"
    callp exitALL
    stop
  endif
elseif iset eq 4
  xcall menu item 0 "Port;^ports"
  if item gt 0 sedit ports port parse item
elseif iset eq 5
  xcall menu item 0 "Format;^formats"
  if item gt 0 sedit formats format parse item
elseif iset eq 6
  xcall menu item 0 "Length;^lengths"
  if item eq 1 xcall dprompt length length "Length: "
  if item gt 1 sedit lengths d:length parse item
elseif iset eq 7
  xcall menu item 0 "Rate;^rates"
  if item eq 1 xcall dprompt rate rate "Rate: "
  if item gt 1 sedit rates d:rate parse item
elseif iset eq 8
  xcall dprompt sgain sgain "Gain: "
  if act eqs "RUN" message send "GAIN" 11 0 1 "L" sgain
elseif iset eq 9
  xcall dprompt nfgain nfgain "NFGain: "
  if act eqs "RUN" message send "NFGAIN" 11 0 1 "L" nfgain
elseif iset eq 10
  xcall dprompt rffreq rffreq "RFFreq: "
  if act eqs "RUN" message send "RFFREQ" 11 0 1 "D" rffreq
elseif iset eq 11
  xcall dprompt rfgain rfgain "RFGain: "
  if act eqs "RUN" message send "RFGAIN" 11 0 1 "L" rfgain
elseif iset eq 12
  xcall aprompt aconfig aconfig "CfgFile: " 30
endif
if act eqs "RUN" and iset lt 8
  res act "RERUN"
  stop
else
  callp dosets
endif
return

label msg
message get /M/
!say "Got message ^M.name ^M.info "
if act neqs "RUN" return
if M.name eqs "=MODIFY" then
  res nn M.modifyinfo_elemt
  res subr M.modifyinfo_name
  res value config(nn;~^subr)
 if port eqss "CORE" then
  res keys "{}"
  if subr eqs "MODE" 
    if value eqs  "OFF" res keys {L:MUTE=1}
    if value neqs "OFF" res keys {L:MUTE=0}
  endif
  if subr eqs "SHP"  res keys {S:SHAPE=^value}
  if subr eqs "GAIN" res keys {L:GAIN=^value}
  if subr eqs "TAPS" res keys {L:NTAP=^value}
  if subr eqs "FBWF" res keys {D:FBWF=^value}
  if subr eqs "SPEC" res keys {D:MIDX=^value}
  if subr eqs "BAUD" res keys {D:FSYM=^{value}e6}
  if subr eqs "FREQ" res keys {D:COFF=^{value}e6}
  message send "SETKEYS" 100+nn 0 1 "S[40]" keys
 elseif port eqss "TBANK" then
  if subr eqs "FREQ" message send "FREQ" 100+nn 0 1 "D" ^{value}e6
  if subr eqs "GAIN" message send "GAIN" 100+nn 0 1 "L" ^value
 endif
endif
return

procedure dosets
xcontrol/over=1/lab=lset menu iset 0 "Cfg;&
  Action = ^act,File = ^file,Card = ^card,Port = ^port,Format = ^format,&
  Length = ^length sec,Rate = ^rate MHz,Gain = ^sgain dB,NFGain = ^nfgain dB,&
  RFFreq = ^rffreq MHz,RFGain = ^rfgain,Config = ^config"
return

procedure stopAll
if lact eqs "RUN" then
  message send "REPLAY" 11 0 0
  message send "REPLAY" 12 0 0
endif
return

procedure exitAll
if lact eqs "RUN" then
  message send "REPLAY" 11 8 0
  message send "REPLAY" 12 8 0
endif
return

procedure loadconfig
keyword config get "FORM" format "LENGTH" length "RATE" rate "GAIN" sgain "RFFREQ" rffreq "RFGAIN" rfgain 
switch/action="Setup" "ACTION" a:act get
switch/defport="MODULE1" "DEFPORT" a:port get
switch/rffreq=1000 "RFFREQ" d:rffreq  get
switch/nfgain=-100 "NFGAIN" l:nfgain get
switch/rfgain=0   "RFGAIN"  l:rfgain  get
switch/nfft=4K "NFFT" l:nfft get
switch/psdr=5  "PSDR" l:psdr get
switch/psda=10 "PSDA" l:psda get
switch/psda=1  "PSDE" l:psde get
switch/dec=1   "DEC"  l:dec  get
status config size=l:size
switch/ntc=^size "NTC" l:ntc get
if ntc neq size then
  header config sz=ntc
endif
return

procedure load_cfg
noop aconfig config
callp loadconfig
info "Loaded configuration from ^aconfig"
message send "REREAD" 2 -1 0
return

procedure save_cfg
keyword config replace "FORM" format "LENGTH" length "RATE" rate "GAIN" sgain "RFFREQ" rffreq "RFGAIN" rfgain 
noop config aconfig
info "Saved configuration to ^aconfig"
return

procedure getspecs l:nn
res imode config(nn;~MODE)
res ifreq config(nn;~FREQ)
res igain config(nn;~GAIN)
res ishp  config(nn;~SHP)
res ibw   config(nn;~BAUD)
res taps  config(nn;~TAPS)
res ibwf  config(nn;~FBWF)
res spec  config(nn;~SPEC)
res sbw   ibw
if ishp eqs "FSK" then calc sbw spec 1 * 2 + sbw *
if ishp eqs "4FSK" then calc sbw spec 3 * 2 + sbw *
calc irate sbw*ibwf*1.5*1e6
calc l:ilen irate*length 256 / round 256 *
res imute 0
if imode eqs "OFF" res imute 1
return

endcontrols
