steppersync: Support sending messages directly from syncemitter

Move msg_queue allocation from stepcompress to syncemitter.  With this
change the pwm_tool module does not need to allocate a stepcompress
object.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor
2025-09-18 21:03:39 -04:00
parent d831d66c11
commit e78d11bc6f
8 changed files with 40 additions and 48 deletions

View File

@@ -48,8 +48,6 @@ defs_stepcompress = """
, uint64_t clock);
int stepcompress_queue_msg(struct stepcompress *sc
, uint32_t *data, int len);
int stepcompress_queue_mq_msg(struct stepcompress *sc, uint64_t req_clock
, uint32_t *data, int len);
int stepcompress_extract_old(struct stepcompress *sc
, struct pull_history_steps *p, int max
, uint64_t start_clock, uint64_t end_clock);
@@ -61,6 +59,8 @@ defs_stepcompress = """
defs_steppersync = """
struct stepcompress *syncemitter_get_stepcompress(struct syncemitter *se);
void syncemitter_queue_msg(struct syncemitter *se, uint64_t req_clock
, uint32_t *data, int len);
struct syncemitter *steppersync_alloc_syncemitter(struct steppersync *ss
, char name[16], int alloc_stepcompress);
void steppersync_setup_movequeue(struct steppersync *ss

View File

@@ -38,7 +38,7 @@ struct stepcompress {
double mcu_time_offset, mcu_freq, last_step_print_time;
// Message generation
uint64_t last_step_clock;
struct list_head msg_queue;
struct list_head *msg_queue;
uint32_t oid;
int32_t queue_step_msgtag, set_next_step_dir_msgtag;
int sdir, invert_sdir;
@@ -258,13 +258,13 @@ static void sc_thread_free(struct stepcompress *sc);
// Allocate a new 'stepcompress' object
struct stepcompress *
stepcompress_alloc(char name[16])
stepcompress_alloc(char name[16], struct list_head *msg_queue)
{
struct stepcompress *sc = malloc(sizeof(*sc));
memset(sc, 0, sizeof(*sc));
list_init(&sc->msg_queue);
list_init(&sc->history_list);
sc->sdir = -1;
sc->msg_queue = msg_queue;
int ret = sc_thread_alloc(sc, name);
if (ret)
@@ -317,7 +317,6 @@ stepcompress_free(struct stepcompress *sc)
return;
sc_thread_free(sc);
free(sc->queue);
message_queue_free(&sc->msg_queue);
stepcompress_history_expire(sc, UINT64_MAX);
free(sc);
}
@@ -334,12 +333,6 @@ stepcompress_get_step_dir(struct stepcompress *sc)
return sc->next_step_dir;
}
struct list_head *
stepcompress_get_msg_queue(struct stepcompress *sc)
{
return &sc->msg_queue;
}
// Determine the "print time" of the last_step_clock
static void
calc_last_step_print_time(struct stepcompress *sc)
@@ -377,7 +370,7 @@ add_move(struct stepcompress *sc, uint64_t first_clock, struct step_move *move)
qm->min_clock = qm->req_clock = sc->last_step_clock;
if (move->count == 1 && first_clock >= sc->last_step_clock + CLOCK_DIFF_MAX)
qm->req_clock = first_clock;
list_add_tail(&qm->node, &sc->msg_queue);
list_add_tail(&qm->node, sc->msg_queue);
sc->last_step_clock = last_clock;
// Create and store move in history tracking
@@ -441,7 +434,7 @@ set_next_step_dir(struct stepcompress *sc, int sdir)
};
struct queue_message *qm = message_alloc_and_encode(msg, 3);
qm->req_clock = sc->last_step_clock;
list_add_tail(&qm->node, &sc->msg_queue);
list_add_tail(&qm->node, sc->msg_queue);
return 0;
}
@@ -640,22 +633,7 @@ stepcompress_queue_msg(struct stepcompress *sc, uint32_t *data, int len)
struct queue_message *qm = message_alloc_and_encode(data, len);
qm->req_clock = sc->last_step_clock;
list_add_tail(&qm->node, &sc->msg_queue);
return 0;
}
// Queue an mcu command that will consume space in the mcu move queue
int __visible
stepcompress_queue_mq_msg(struct stepcompress *sc, uint64_t req_clock
, uint32_t *data, int len)
{
int ret = stepcompress_flush(sc, UINT64_MAX);
if (ret)
return ret;
struct queue_message *qm = message_alloc_and_encode(data, len);
qm->min_clock = qm->req_clock = req_clock;
list_add_tail(&qm->node, &sc->msg_queue);
list_add_tail(&qm->node, sc->msg_queue);
return 0;
}

View File

@@ -11,7 +11,9 @@ struct pull_history_steps {
int step_count, interval, add;
};
struct stepcompress *stepcompress_alloc(char name[16]);
struct list_head;
struct stepcompress *stepcompress_alloc(char name[16]
, struct list_head *msg_queue);
void stepcompress_fill(struct stepcompress *sc, uint32_t oid, uint32_t max_error
, int32_t queue_step_msgtag
, int32_t set_next_step_dir_msgtag);
@@ -21,7 +23,6 @@ void stepcompress_history_expire(struct stepcompress *sc, uint64_t end_clock);
void stepcompress_free(struct stepcompress *sc);
uint32_t stepcompress_get_oid(struct stepcompress *sc);
int stepcompress_get_step_dir(struct stepcompress *sc);
struct list_head *stepcompress_get_msg_queue(struct stepcompress *sc);
void stepcompress_set_time(struct stepcompress *sc
, double time_offset, double mcu_freq);
int stepcompress_append(struct stepcompress *sc, int sdir
@@ -33,8 +34,6 @@ int stepcompress_set_last_position(struct stepcompress *sc, uint64_t clock
int64_t stepcompress_find_past_position(struct stepcompress *sc
, uint64_t clock);
int stepcompress_queue_msg(struct stepcompress *sc, uint32_t *data, int len);
int stepcompress_queue_mq_msg(struct stepcompress *sc, uint64_t req_clock
, uint32_t *data, int len);
int stepcompress_extract_old(struct stepcompress *sc
, struct pull_history_steps *p, int max
, uint64_t start_clock, uint64_t end_clock);

View File

@@ -27,16 +27,29 @@
struct syncemitter {
// List node for storage in steppersync list
struct list_node ss_node;
// Transmit message queue
struct list_head msg_queue;
// Step compression and generation
struct stepcompress *sc;
};
// Return this emitters 'struct stepcompress' (or NULL if not allocated)
struct stepcompress * __visible
syncemitter_get_stepcompress(struct syncemitter *se)
{
return se->sc;
}
// Queue an mcu command that will consume space in the mcu move queue
void __visible
syncemitter_queue_msg(struct syncemitter *se, uint64_t req_clock
, uint32_t *data, int len)
{
struct queue_message *qm = message_alloc_and_encode(data, len);
qm->min_clock = qm->req_clock = req_clock;
list_add_tail(&qm->node, &se->msg_queue);
}
/****************************************************************
* StepperSync - sort move queue for a micro-controller
@@ -65,8 +78,9 @@ steppersync_alloc_syncemitter(struct steppersync *ss, char name[16]
struct syncemitter *se = malloc(sizeof(*se));
memset(se, 0, sizeof(*se));
list_add_tail(&se->ss_node, &ss->se_list);
list_init(&se->msg_queue);
if (alloc_stepcompress)
se->sc = stepcompress_alloc(name);
se->sc = stepcompress_alloc(name, &se->msg_queue);
return se;
}
@@ -137,10 +151,9 @@ steppersync_flush(struct steppersync *ss, uint64_t move_clock)
struct queue_message *qm = NULL;
struct syncemitter *se;
list_for_each_entry(se, &ss->se_list, ss_node) {
struct list_head *sc_mq = stepcompress_get_msg_queue(se->sc);
if (!list_empty(sc_mq)) {
if (!list_empty(&se->msg_queue)) {
struct queue_message *m = list_first_entry(
sc_mq, struct queue_message, node);
&se->msg_queue, struct queue_message, node);
if (m->req_clock < req_clock) {
qm = m;
req_clock = m->req_clock;
@@ -205,6 +218,7 @@ steppersyncmgr_free(struct steppersyncmgr *ssm)
&ss->se_list, struct syncemitter, ss_node);
list_del(&se->ss_node);
stepcompress_free(se->sc);
message_queue_free(&se->msg_queue);
free(se);
}
free(ss);

View File

@@ -5,6 +5,8 @@
struct syncemitter;
struct stepcompress *syncemitter_get_stepcompress(struct syncemitter *se);
void syncemitter_queue_msg(struct syncemitter *se, uint64_t req_clock
, uint32_t *data, int len);
struct steppersync;
struct syncemitter *steppersync_alloc_syncemitter(

View File

@@ -77,13 +77,13 @@ class PrinterMotionQueuing:
ss = ffi_lib.steppersyncmgr_alloc_steppersync(self.steppersyncmgr)
self.steppersyncs.append((mcu, ss))
return ss
def allocate_stepcompress(self, mcu, name):
def allocate_syncemitter(self, mcu, name, alloc_stepcompress=True):
name = name.encode("utf-8")[:15]
ss = self._lookup_steppersync(mcu)
ffi_main, ffi_lib = chelper.get_ffi()
se = ffi_lib.steppersync_alloc_syncemitter(ss, name, True)
se = ffi_lib.steppersync_alloc_syncemitter(ss, name, alloc_stepcompress)
self.syncemitters.append(se)
return ffi_lib.syncemitter_get_stepcompress(se)
return se
def setup_mcu_movequeue(self, mcu, serialqueue, move_count):
# Setup steppersync object for the mcu's main movequeue
ffi_main, ffi_lib = chelper.get_ffi()

View File

@@ -18,9 +18,10 @@ class MCU_queued_pwm:
printer = mcu.get_printer()
sname = config.get_name().split()[-1]
self._motion_queuing = printer.load_object(config, 'motion_queuing')
self._stepqueue = self._motion_queuing.allocate_stepcompress(mcu, sname)
self._syncemitter = self._motion_queuing.allocate_syncemitter(
mcu, sname, alloc_stepcompress=False)
ffi_main, ffi_lib = chelper.get_ffi()
self._stepcompress_queue_mq_msg = ffi_lib.stepcompress_queue_mq_msg
self._syncemitter_queue_msg = ffi_lib.syncemitter_queue_msg
mcu.register_config_callback(self._build_config)
self._pin = pin_params['pin']
self._invert = pin_params['invert']
@@ -107,10 +108,7 @@ class MCU_queued_pwm:
self._last_clock = clock = max(self._last_clock, clock)
self._last_value = val
data = (self._set_cmd_tag, self._oid, clock & 0xffffffff, val)
ret = self._stepcompress_queue_mq_msg(self._stepqueue, clock,
data, len(data))
if ret:
raise error("Internal error in stepcompress")
self._syncemitter_queue_msg(self._syncemitter, clock, data, len(data))
# Notify toolhead so that it will flush this update
wakeclock = clock
if self._last_value != self._default_value:

View File

@@ -45,8 +45,9 @@ class MCU_stepper:
self._active_callbacks = []
motion_queuing = printer.load_object(config, 'motion_queuing')
sname = self._name.split()[-1]
self._stepqueue = motion_queuing.allocate_stepcompress(mcu, sname)
syncemitter = motion_queuing.allocate_syncemitter(mcu, sname)
ffi_main, ffi_lib = chelper.get_ffi()
self._stepqueue = ffi_lib.syncemitter_get_stepcompress(syncemitter)
ffi_lib.stepcompress_set_invert_sdir(self._stepqueue, self._invert_dir)
self._stepper_kinematics = None
self._itersolve_check_active = ffi_lib.itersolve_check_active