namespace eval fungen {} {
}

proc stdConfig::fungen {} {
  controller std "\n" 5
  prop startcmd "*IDN?"
  
  pollperiod 1 1

  obj "AGILENT33210A" rd
  prop read fungen::read
  
  kids "function generator settings" {
    node remote -int wr
    default 1
    prop check fungen::remote
    prop read fungen::remoteupd
    prop write stdSct::complete
    prop enum 1

    node waveform -text par SIN

    node freq out
    default 1000
    prop write "fungen::write 0"

    node volt out
    default 0
    prop write "fungen::write 0"

    node offset out
    default 0
    prop write "fungen::write 0"

    node width wr
    prop writecmd "FUNC:PULS:WIDT %g\nFUNC:PULS:WIDT?"
    prop readcmd "FUNC:PULS:WIDT?"
    prop readfmt "%g"

    node burstfreq out
    default 1000
    prop write "fungen::write 1"
    prop newline 1

    node burstvolt out
    default 0
    prop write "fungen::write 1"

    node burstoffset out
    default 0
    prop write "fungen::write 1"

    node burstcycles wr -int
    default 1
    prop writecmd "BURS:NCYC %d\nBURS:NCYC?"
    prop readcmd "BURS:NCYC?"
    prop readfmt "%f"

    node burstperiod wr
    prop writecmd "BURS:INT:PER %g\nBURS:INT:PER?"
    prop readcmd "BURS:INT:PER?"
    prop readfmt "%f"

    node burst -int out
    default 0
    prop enum continuous,burst,off
    prop write fungen::burst
  }

  return "AGILENT 33210a function generator"
}

proc fungen::remoteupd {} {
  sct update 1
  return idle
}

proc fungen::remote {} {
  if {[sct target]} {
    [sct controller] reconnect
  } else {
    [sct controller] disconnect
  }
  sct update [sct target]
  return idle
}

proc fungen::read {} {
  sct send "APPLY?;OUTP?;BURS:STAT?"
  return fungen::complete
}

proc fungen::complete {} {
  stdSct::scanf {"%s %f,%f,%f";%d;%d} waveform freq volt offset output burst
  if {$output == 0} {
    updateval [sct]/burst 2
    sct update 0
    return idle
  }
  set oldburst [hvali [sct]/burst]
  if {$oldburst < 2} {
    updateval [sct]/burst $burst
  }
  updateval [sct]/waveform $waveform
  sct update $freq
  if {$burst != $oldburst} {
    return idle
  }
  if {$burst} {
    updateval [sct]/burstfreq $freq
    updateval [sct]/burstvolt $volt
    updateval [sct]/burstoffset $offset
  } else {
    updateval [sct]/freq $freq
    updateval [sct]/volt $volt
    updateval [sct]/offset $offset
  }
  return idle
}

proc fungen::write {burstmode} {
  set burst [sctval [sct parent]/burst]
  if {$burst != $burstmode} {
    sct update [sct target]
    return idle
  }
  set waveform [sctval [sct parent]/waveform]
  if {$burst} {
    set freq [sctval [sct parent]/burstfreq]
    set volt [sctval [sct parent]/burstvolt]
    set offset [sctval [sct parent]/burstoffset]
  } else {
    set freq [sctval [sct parent]/freq]
    set volt [sctval [sct parent]/volt]
    set offset [sctval [sct parent]/offset]
  }
  sct send "APPLY:$waveform $freq Hz,$volt Vpp,$offset V\nAPPLY?"
  return "fungen::acomplete $burst"
}

proc fungen::acomplete {burst} {
  stdSct::scanf {"%s %f,%f,%f"} waveform freq volt offset
  if {$burst} {
    updateval [sct parent]/burstfreq $freq
    updateval [sct parent]/burstvolt $volt
    updateval [sct parent]/burstoffset $offset
  } else {
    updateval [sct parent]/freq $freq
    updateval [sct parent]/volt $volt
    updateval [sct parent]/offset $offset
  }
  updateval [sct parent] $freq
  return idle
}

proc fungen::burst {} {
  if {[sct target] == 2} {
    sct send "OUTP 0\nOUTP?"
    return stdSct::completeUpdate
  }
  set waveform [sctval [sct parent]/waveform]
  if {[sct target]} {
    set freq [sctval [sct parent]/burstfreq]
    set volt [sctval [sct parent]/burstvolt]
    set offset [sctval [sct parent]/burstoffset]
  } else {
    set freq [sctval [sct parent]/freq]
    set volt [sctval [sct parent]/volt]
    set offset [sctval [sct parent]/offset]
  }
  sct send "APPLY:$waveform $freq Hz,$volt Vpp,$offset V\nOUTP 1\nBURS:STAT [sct target]\nOUTP?"
  return stdSct::completeUpdate
}

proc fungen::readburst {} {
  sct send "BURS:STAT?"
  return fungen::updateburst
}

proc fungen::updateburst {} {
  set burst [sct result]
  if {[sctval [sct]] <= 1} {
    sct update $burst
  }
  return idle
}
