# note: in order to sactivate the sensirion flow meter
# instconfig sensrion has to be set to 1s

namespace eval sensirion {} {
}

proc stdConfig::sensirion {} {
  variable name

  # bin <checksum-algorithm> <timeout> <number-of-retries>
  controller bin chksum-crc 1 2

  # <fast> <slow> <history resolution>
  pollperiod 1 10 5
  obj sensirion rd
  prop readcmd "str1 ? int 10 / str18"
  # overwrite controller properties on trinamic:
  prop read stdSct::read
  prop update sensirion::updateFlow

  kids "n.v. flow" {

      node stddev upd

      # ?<nsample>_  nsample=160: <~= 1 sec, nsample=800: <~= 5 sec
      node nsamples -int wr
      prop read stdSct::read
      prop complete sensirion::update
      prop update sensirion::update
      prop write stdSct::write
      prop readcmd "str1 n int 10 / str9"
      prop writecmd "str7 n%-6d int 10 / str9"

      node offset wr
      prop check sensirion::checkCalib
      prop read stdSct::read
      prop complete sensirion::update
      prop update sensirion::update
      prop write stdSct::write
      prop readcmd "str1 o int 10 / str9"
      prop writecmd "str7 o%-6.2f int 10 / str9"

      node scale wr
      prop read stdSct::read
      prop complete sensirion::update
      prop update sensirion::update
      prop check sensirion::checkCalib
      prop write stdSct::write
      prop readcmd "str1 g int 10 / str9"
      prop writecmd "str7 g%-6.4f int 10 / str9"

      node save out
      prop enum 1
      prop write sensirion::saveCalib
      prop help "unchecked: current calib is not saved. set checked: save calib"

  }

  hset $name/nsamples 160
  hset $name/scale 2.3
}

proc sensirion::updateFlow {} {
  lassign [sct result] flow stddev
  sct update $flow
  updateval [sct]/stddev $stddev
  if {[silent "" hgetpropval [sct]/save saved] eq "" && [silent "" currentCalib] ne ""} {
    hsetprop [sct]/save saved [currentCalib]
    hupdate [sct]/save 1
  }
  return idle
}

proc sensirion::currentCalib {} {
  return [format {%.4f %.4f} [hval [sct objectPath]/offset] [hval [sct objectPath]/scale]]
}

proc sensirion::checkCalib {} {
  if {[silent "" currentCalib] ne "[silent 0 sct saved]"} {
    hupdate [sct parent]/save 0
  } else {
    hupdate [sct parent]/save 0
  }
}

proc sensirion::saveCalib {} {
  if {[sct target]} {
    sct send "str1 s int 10 / str1"
    sct saved [currentCalib]
    sct print "saved calib [sct saved]"
  } else {
    sct print "marked calib as dirty"
  }
  sct update [sct target]
  return stdSct::complete
}

proc sensirion::update {} {
  sct update [sct result]
  return idle
}
