# read 8 ADC channels with taskit RS232 ADC
namespace eval ana8 {
}

if {![namespace exists lsc]} {
  source drivers/lsc.tcl
}

proc stdConfig::ana8 {channel {scale 1} {offset 0} {curve ""}} {
  
  controller std "\r" 2
  prop node_$channel 0
  prop time_$channel 0
  poll 1 read ana8::poll

  pollperiod 5
  obj ANA8 rd
  prop read "ana8::read $channel"
  variable name
  variable path
  kids "$name analog input" {
    node scale par $scale

    node offset par $offset

    node raw upd

    node curve out -text
    prop width 32
    prop model 0
    prop check ana8::curve
    prop write stdSct::completeUpdate

    kids "calibration" {
      hfactory $path/points plain mugger floatvarar 1
    }
  }
  if {$curve ne "" && $curve ne "raw"} {
    hset /$name/curve $curve
  } else {
    hupdate /$name/curve ""
  }
  return "ANA8"
}

proc ana8::start {} {
# set adc rate to 11
  sct send ":10000D000102000B.."
  return ana8::start2
}

proc ana8::start2 {} {
# set all i/o to output / push-pull / low
  sct send ":10000000030600FF00FF0000.."
  return ana8::getidn
}

proc ana8::getidn {} {
  sct send ":0300030001.."
  return stdSct::completeStart
}

proc ana8::read {channel} {
  sct node_$channel [sct]
  sct time_$channel [DoubleTime]
  return idle
}

proc ana8::poll {} {
  set now [DoubleTime]
  set channels [list ]
  foreach channel {0 1 2 3 4 5 6 7} {
    if {$now < [silent 0 sct time_$channel] + 30} {
      lappend channels $channel
    }
  }
  if {[llength $channels] == 0} {
    return idle
  }
  set first [lindex $channels 0]
  set nchan [expr [lindex $channels end] - $first + 1]
  if {$nchan > 0} {
    sct channels $channels
    sct nchan $nchan
    sct send ":04000${first}000${nchan}.."
    return ana8::update
  }
  return idle
}

proc ana8::update {} {
  set first [lindex [sct channels] 0]
  set nb [format %.2X [expr [sct nchan] * 2]]
  set res [scan [sct result] ":04${nb}%4x%4x%4x%4x%4x%4x%4x%4x" a0 a1 a2 a3 a4 a5 a6 a7]
  if {$res < [sct nchan]} {
    error "bad response to '[sct send]': '[sct result]'"
  }
  foreach ch [sct channels] {
    set i [expr $ch - $first]
    set scale [hval [sct node_$ch]/scale]
    set offset [hval [sct node_$ch]/offset]
#       26214 = (2^32-1) steps / 2.5 V
    set raw [expr [set a$i] / 26214. * $scale + $offset]
    set node [sct node_$ch]
    updateval $node/raw $raw
    if {[hval $node/curve] eq ""} {
      updateval $node $raw
    } else {
      set t [interpolate [hvali $node/curve/points] 0 $raw logy extrapolate]
      updateval $node $t
    }
  }
  return idle
}

proc ana8::curve {} {
  if {[sct requested] ne "" && [sct requested] ne "raw"} {
    lsc::read_curve
  }
}


