sensor_ldc1612: Convert homing code to use trigger_analog system

Remove the homing code from sensor_ldc1612.c and utilize the generic
homing support found in trigger_analog.c .

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2026-01-20 22:56:29 -05:00
parent 147022dee2
commit 58cc059e31
4 changed files with 40 additions and 146 deletions

View file

@ -87,7 +87,6 @@ class LDC1612:
self._sensor_errors = {}
self.oid = oid = mcu.create_oid()
self.query_ldc1612_cmd = None
self.ldc1612_setup_home_cmd = self.query_ldc1612_home_state_cmd = None
self.clock_freq = config.getint("frequency", DEFAULT_LDC1612_FREQ,
2000000, 40000000)
# Coil frequency divider, assume 12MHz is BTT Eddy
@ -120,23 +119,22 @@ class LDC1612:
hdr = ('time', 'frequency', 'z')
self.batch_bulk.add_mux_endpoint("ldc1612/dump_ldc1612", "sensor",
self.name, {'header': hdr})
def setup_trigger_analog(self, trigger_analog_oid):
self.mcu.add_config_cmd(
"ldc1612_attach_trigger_analog oid=%d trigger_analog_oid=%d"
% (self.oid, trigger_analog_oid), is_init=True)
def _build_config(self):
cmdqueue = self.i2c.get_command_queue()
self.query_ldc1612_cmd = self.mcu.lookup_command(
"query_ldc1612 oid=%c rest_ticks=%u", cq=cmdqueue)
self.ffreader.setup_query_command("query_status_ldc1612 oid=%c",
oid=self.oid, cq=cmdqueue)
self.ldc1612_setup_home_cmd = self.mcu.lookup_command(
"ldc1612_setup_home oid=%c clock=%u threshold=%u"
" trsync_oid=%c trigger_reason=%c error_reason=%c", cq=cmdqueue)
self.query_ldc1612_home_state_cmd = self.mcu.lookup_query_command(
"query_ldc1612_home_state oid=%c",
"ldc1612_home_state oid=%c homing=%c trigger_clock=%u",
oid=self.oid, cq=cmdqueue)
errors = self.mcu.get_enumerations().get("ldc1612_error:", {})
self._sensor_errors = {v: k for k, v in errors.items()}
def get_mcu(self):
return self.i2c.get_mcu()
def get_samples_per_second(self):
return self.data_rate
def read_reg(self, reg):
if self.mcu.is_fileoutput():
return 0
@ -148,20 +146,10 @@ class LDC1612:
minclock=minclock)
def add_client(self, cb):
self.batch_bulk.add_client(cb)
# Homing
def setup_home(self, print_time, trigger_freq,
trsync_oid, hit_reason, err_reason):
clock = self.mcu.print_time_to_clock(print_time)
tfreq = int(trigger_freq / self.freq_conv + 0.5)
self.ldc1612_setup_home_cmd.send(
[self.oid, clock, tfreq, trsync_oid, hit_reason, err_reason])
def clear_home(self):
self.ldc1612_setup_home_cmd.send([self.oid, 0, 0, 0, 0, 0])
params = self.query_ldc1612_home_state_cmd.send([self.oid])
tclock = self.mcu.clock32_to_clock64(params['trigger_clock'])
return self.mcu.clock_to_print_time(tclock)
def lookup_sensor_error(self, error):
return self._sensor_errors.get(error, "Unknown ldc1612 error")
def convert_frequency(self, freq):
return int(freq / self.freq_conv + 0.5)
# Measurement decoding
def _convert_samples(self, samples):
freq_conv = self.freq_conv

View file

@ -5,7 +5,7 @@
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging, math, bisect
import mcu
from . import ldc1612, probe, manual_probe
from . import ldc1612, trigger_analog, probe, manual_probe
OUT_OF_RANGE = 99.9
@ -388,9 +388,10 @@ class EddyGatherSamples:
self._probe_times.append((start_time, end_time, pos_time, None))
self._check_samples()
MAX_VALID_RAW_VALUE=0x03ffffff
# Helper for implementing PROBE style commands (descend until trigger)
class EddyDescend:
REASON_SENSOR_ERROR = mcu.MCU_trsync.REASON_COMMS_TIMEOUT + 1
def __init__(self, config, sensor_helper, calibration,
probe_offsets, param_helper):
self._printer = config.get_printer()
@ -399,43 +400,20 @@ class EddyDescend:
self._calibration = calibration
self._probe_offsets = probe_offsets
self._param_helper = param_helper
self._trigger_analog = trigger_analog.MCU_trigger_analog(sensor_helper)
self._z_min_position = probe.lookup_minimum_z(config)
self._dispatch = mcu.TriggerDispatch(self._mcu)
self._trigger_time = 0.
self._gather = None
probe.LookupZSteppers(config, self._dispatch.add_stepper)
# Interface for phoming.probing_move()
def get_steppers(self):
return self._dispatch.get_steppers()
def home_start(self, print_time, sample_time, sample_count, rest_time,
triggered=True):
self._trigger_time = 0.
dispatch = self._trigger_analog.get_dispatch()
probe.LookupZSteppers(config, dispatch.add_stepper)
def _prep_trigger_analog(self):
self._trigger_analog.set_raw_range(0, MAX_VALID_RAW_VALUE)
z_offset = self._probe_offsets.get_offsets()[2]
trigger_freq = self._calibration.height_to_freq(z_offset)
trigger_completion = self._dispatch.start(print_time)
self._sensor_helper.setup_home(
print_time, trigger_freq, self._dispatch.get_oid(),
mcu.MCU_trsync.REASON_ENDSTOP_HIT, self.REASON_SENSOR_ERROR)
return trigger_completion
def home_wait(self, home_end_time):
self._dispatch.wait_end(home_end_time)
trigger_time = self._sensor_helper.clear_home()
res = self._dispatch.stop()
if res >= mcu.MCU_trsync.REASON_COMMS_TIMEOUT:
if res == mcu.MCU_trsync.REASON_COMMS_TIMEOUT:
raise self._printer.command_error(
"Communication timeout during homing")
error_code = res - self.REASON_SENSOR_ERROR
error_msg = self._sensor_helper.lookup_sensor_error(error_code)
raise self._printer.command_error(error_msg)
if res != mcu.MCU_trsync.REASON_ENDSTOP_HIT:
return 0.
if self._mcu.is_fileoutput():
trigger_time = home_end_time
self._trigger_time = trigger_time
return trigger_time
conv_freq = self._sensor_helper.convert_frequency(trigger_freq)
self._trigger_analog.set_trigger('gt', conv_freq)
# Probe session interface
def start_probe_session(self, gcmd):
self._prep_trigger_analog()
offsets = self._probe_offsets.get_offsets()
self._gather = EddyGatherSamples(self._printer, self._sensor_helper,
self._calibration, offsets)
@ -447,9 +425,9 @@ class EddyDescend:
speed = self._param_helper.get_probe_params(gcmd)['probe_speed']
# Perform probing move
phoming = self._printer.lookup_object('homing')
trig_pos = phoming.probing_move(self, pos, speed)
trig_pos = phoming.probing_move(self._trigger_analog, pos, speed)
# Extract samples
start_time = self._trigger_time + 0.050
start_time = self._trigger_analog.get_last_trigger_time() + 0.050
end_time = start_time + 0.100
toolhead_pos = toolhead.get_position()
self._gather.note_probe(start_time, end_time, toolhead_pos)
@ -472,13 +450,13 @@ class EddyEndstopWrapper:
def add_stepper(self, stepper):
pass
def get_steppers(self):
return self._eddy_descend.get_steppers()
return self._eddy_descend._trigger_analog.get_steppers()
def home_start(self, print_time, sample_time, sample_count, rest_time,
triggered=True):
return self._eddy_descend.home_start(
return self._eddy_descend._trigger_analog.home_start(
print_time, sample_time, sample_count, rest_time, triggered)
def home_wait(self, home_end_time):
return self._eddy_descend.home_wait(home_end_time)
return self._eddy_descend._trigger_analog.home_wait(home_end_time)
def query_endstop(self, print_time):
return False # XXX
# Interface for HomingViaProbeHelper

View file

@ -179,7 +179,7 @@ config NEED_SENSOR_BULK
default y
config WANT_TRIGGER_ANALOG
bool
depends on WANT_HX71X || WANT_ADS1220
depends on WANT_HX71X || WANT_ADS1220 || WANT_LDC1612
default y
config NEED_SOS_FILTER
bool

View file

@ -13,11 +13,10 @@
#include "i2ccmds.h" // i2cdev_oid_lookup
#include "sched.h" // DECL_TASK
#include "sensor_bulk.h" // sensor_bulk_report
#include "trsync.h" // trsync_do_trigger
#include "trigger_analog.h" // trigger_analog_update
enum {
LDC_PENDING = 1<<0, LDC_HAVE_INTB = 1<<1,
LH_AWAIT_HOMING = 1<<1, LH_CAN_TRIGGER = 1<<2
};
struct ldc1612 {
@ -27,12 +26,7 @@ struct ldc1612 {
uint8_t flags;
struct sensor_bulk sb;
struct gpio_in intb_pin;
// homing
struct trsync *ts;
uint8_t homing_flags;
uint8_t trigger_reason, error_reason;
uint32_t trigger_threshold;
uint32_t homing_clock;
struct trigger_analog *ta;
};
static struct task_wake ldc1612_wake;
@ -91,83 +85,15 @@ DECL_COMMAND(command_config_ldc1612_with_intb,
"config_ldc1612_with_intb oid=%c i2c_oid=%c intb_pin=%c");
void
command_ldc1612_setup_home(uint32_t *args)
{
ldc1612_attach_trigger_analog(uint32_t *args) {
struct ldc1612 *ld = oid_lookup(args[0], command_config_ldc1612);
ld->trigger_threshold = args[2];
if (!ld->trigger_threshold) {
ld->ts = NULL;
ld->homing_flags = 0;
return;
}
ld->homing_clock = args[1];
ld->ts = trsync_oid_lookup(args[3]);
ld->trigger_reason = args[4];
ld->error_reason = args[5];
ld->homing_flags = LH_AWAIT_HOMING | LH_CAN_TRIGGER;
ld->ta = trigger_analog_oid_lookup(args[1]);
}
DECL_COMMAND(command_ldc1612_setup_home,
"ldc1612_setup_home oid=%c clock=%u threshold=%u"
" trsync_oid=%c trigger_reason=%c error_reason=%c");
DECL_COMMAND(ldc1612_attach_trigger_analog,
"ldc1612_attach_trigger_analog oid=%c trigger_analog_oid=%c");
void
command_query_ldc1612_home_state(uint32_t *args)
{
struct ldc1612 *ld = oid_lookup(args[0], command_config_ldc1612);
sendf("ldc1612_home_state oid=%c homing=%c trigger_clock=%u"
, args[0], !!(ld->homing_flags & LH_CAN_TRIGGER), ld->homing_clock);
}
DECL_COMMAND(command_query_ldc1612_home_state,
"query_ldc1612_home_state oid=%c");
// Cancel homing due to an error
static void
cancel_homing(struct ldc1612 *ld, int error_code)
{
if (!(ld->homing_flags & LH_CAN_TRIGGER))
return;
ld->homing_flags = 0;
trsync_do_trigger(ld->ts, ld->error_reason + error_code);
}
#define MAX_VALID_RAW_VALUE 0x03ffffff
#define DATA_ERROR_AMPLITUDE (1L << 28)
static int
check_data_bits(struct ldc1612 *ld, uint32_t raw_data) {
// Ignore amplitude errors
raw_data &= ~DATA_ERROR_AMPLITUDE;
// Datasheet define valid frequency input as < F_ref / 4
if (raw_data < MAX_VALID_RAW_VALUE)
return 0;
cancel_homing(ld, SE_SENSOR_ERROR);
return -1;
}
// Check if a sample should trigger a homing event
static void
check_home(struct ldc1612 *ld, uint32_t raw_data)
{
uint8_t homing_flags = ld->homing_flags;
if (!(homing_flags & LH_CAN_TRIGGER))
return;
if (check_data_bits(ld, raw_data))
return;
uint32_t data = raw_data & 0x0fffffff;
uint32_t time = timer_read_time();
if ((homing_flags & LH_AWAIT_HOMING)
&& timer_is_before(time, ld->homing_clock))
return;
homing_flags &= ~LH_AWAIT_HOMING;
if (data > ld->trigger_threshold) {
homing_flags = 0;
ld->homing_clock = time;
trsync_do_trigger(ld->ts, ld->trigger_reason);
}
ld->homing_flags = homing_flags;
}
// Chip registers
#define REG_DATA0_MSB 0x00
#define REG_DATA0_LSB 0x01
@ -196,7 +122,7 @@ read_reg_status(struct ldc1612 *ld, uint16_t *status)
static void
report_sample_error(struct ldc1612 *ld, int error_code)
{
cancel_homing(ld, error_code);
trigger_analog_note_error(ld->ta, error_code);
uint8_t *d = &ld->sb.data[ld->sb.data_count];
d[0] = 0xff;
@ -238,12 +164,14 @@ ldc1612_query(struct ldc1612 *ld, uint8_t oid)
goto out;
}
// Check for endstop trigger
uint32_t data = ((uint32_t)d[0] << 24)
| ((uint32_t)d[1] << 16)
| ((uint32_t)d[2] << 8)
| ((uint32_t)d[3]);
check_home(ld, data);
// Check for homing trigger
uint32_t raw_data = (((uint32_t)d[0] << 24) | ((uint32_t)d[1] << 16)
| ((uint32_t)d[2] << 8) | ((uint32_t)d[3]));
if (raw_data & 0xe0000000)
trigger_analog_note_error(ld->ta, SE_SENSOR_ERROR);
else
trigger_analog_update(ld->ta, raw_data & 0x0fffffff);
out:
ld->sb.data_count += BYTES_PER_SAMPLE;
// Flush local buffer if needed