succd: move out processing blocks to separate file

This commit is contained in:
Serge Bazanski 2024-09-28 09:39:44 +02:00
parent 4df00f0a63
commit 451b44e31b
3 changed files with 76 additions and 66 deletions

View file

@ -28,71 +28,6 @@ type daemon struct {
daemonState daemonState
} }
// momentaryOutput is an output that can be triggered for 500ms.
type momentaryOutput struct {
// output of the block.
output bool
// scheduledOff is when the block should be outputting false again.
scheduledOff time.Time
}
func (m *momentaryOutput) process() {
m.output = m.scheduledOff.After(time.Now())
}
func (m *momentaryOutput) trigger() {
m.scheduledOff = time.Now().Add(time.Millisecond * 500)
}
// thresholdOutput outputs true if a given value is above a setpoint/threshold.
// It contains debounce logic for processing noisy analog signals.
type thresholdOutput struct {
// output of the block.
output bool
// debounce is when the debouncer should be inactive again.
debounce time.Time
// threshold is the setpoint of the block.
threshold float64
}
func (t *thresholdOutput) process(value float64) {
if time.Now().Before(t.debounce) {
return
}
new := value > t.threshold
if new != t.output {
t.output = new
t.debounce = time.Now().Add(time.Second * 5)
}
}
// ringbufferInput accumulates analog data up to limit samples, and calculates
// an average.
type ringbufferInput struct {
data []float32
limit uint
avg float32
}
func (r *ringbufferInput) process(input float32) {
// TODO(q3k): use actual ringbuffer
// TODO(q3k): optimize average calculation
// TODO(q3k): precalculate value in mbar
r.data = append(r.data, input)
trim := len(r.data) - int(r.limit)
if trim > 0 {
r.data = r.data[trim:]
}
avg := float32(0.0)
for _, v := range r.data {
avg += v
}
if len(r.data) != 0 {
avg /= float32(len(r.data))
}
r.avg = avg
}
// process runs the pain acquisition and control loop of succd. // process runs the pain acquisition and control loop of succd.
func (d *daemon) process(ctx context.Context) { func (d *daemon) process(ctx context.Context) {
ticker := time.NewTicker(time.Millisecond * 100) ticker := time.NewTicker(time.Millisecond * 100)

View file

@ -0,0 +1,75 @@
package main
import "time"
// momentaryOutput is an output that can be triggered for 500ms.
type momentaryOutput struct {
// output of the block.
output bool
// scheduledOff is when the block should be outputting false again.
scheduledOff time.Time
}
func (m *momentaryOutput) process() {
m.output = m.scheduledOff.After(time.Now())
}
func (m *momentaryOutput) trigger() {
m.scheduledOff = time.Now().Add(time.Millisecond * 500)
}
// thresholdOutput outputs true if a given value is above a setpoint/threshold.
// It contains debounce logic for processing noisy analog signals.
type thresholdOutput struct {
// output of the block.
output bool
// debounce is when the debouncer should be inactive again.
debounce time.Time
// threshold is the setpoint of the block.
threshold float64
}
func (t *thresholdOutput) process(value float64) {
if time.Now().Before(t.debounce) {
return
}
new := value > t.threshold
if new != t.output {
t.output = new
t.debounce = time.Now().Add(time.Second * 5)
}
}
// ringbufferInput accumulates analog data up to limit samples, and calculates
// an average.
type ringbufferInput struct {
data []float32
limit uint
// avg is the mean average of the samples in data, or 0.0 if no data is
// present yet. This is the main output of the block.
avg float32
}
func (r *ringbufferInput) process(input float32) {
// TODO(q3k): use actual ringbuffer
// TODO(q3k): optimize average calculation
// TODO(q3k): precalculate value in mbar
r.data = append(r.data, input)
trim := len(r.data) - int(r.limit)
if trim > 0 {
r.data = r.data[trim:]
}
avg := float32(0.0)
for _, v := range r.data {
avg += v
}
if len(r.data) != 0 {
avg /= float32(len(r.data))
}
r.avg = avg
}
// saturated returns true if the number of samples is at the configured limit.
func (r *ringbufferInput) saturated() bool {
return len(r.data) >= int(r.limit)
}

View file

@ -50,7 +50,7 @@ func piraniVoltsToMbar(v float32) float32 {
// piraniDetection guesses whether the pirani gauge is connected. // piraniDetection guesses whether the pirani gauge is connected.
func (d *daemonState) piraniDetection() piraniDetection { func (d *daemonState) piraniDetection() piraniDetection {
if len(d.piraniVolts3.data) < int(d.piraniVolts3.limit) { if !d.piraniVolts3.saturated() {
return piraniDetectionUnknown return piraniDetectionUnknown
} }
mbar := piraniVoltsToMbar(d.piraniVolts3.avg) mbar := piraniVoltsToMbar(d.piraniVolts3.avg)