Skip to content

Feature: firmware/hardware emulator#13

Draft
Funkenjaeger wants to merge 5 commits into
bartei:mainfrom
Funkenjaeger:add-emulator
Draft

Feature: firmware/hardware emulator#13
Funkenjaeger wants to merge 5 commits into
bartei:mainfrom
Funkenjaeger:add-emulator

Conversation

@Funkenjaeger
Copy link
Copy Markdown

@Funkenjaeger Funkenjaeger commented Apr 12, 2026

Introduces a native Linux emulator for hardware-free testing with the rotary-controller-python UI. It compiles the real firmware sources (Ramps.c, Modbus.c, Scales.c, UARTCallback.c) against a HAL/FreeRTOS shim layer and simulates lathe physics — spindle with inertia, leadscrew, carriage with half-nut engagement, and cross-slide. The emulator exposes Modbus RTU via PTY pair and TCP socket so the unmodified rotary-controller-python GUI can connect as if talking to real hardware.

This emulator is Lathe-focused, for integrating with ELS or DRO modes. The concept could be extended to emulate rotary table mechanics, but I haven't tackled that.

A two-pane ANSI terminal dashboard with sparklines provides live visualization, with keyboard controls for spindle RPM, manual axis movement, half-nut engagement, and more. All parameters are configurable via TOML file.

{7AE9C06A-A30F-483F-AE60-E748E06ACB4F}

I'm submitting this as a draft as I'm still tinkering and integrating, but would like to gauge interest and solicit feedback.

Introduces a native Linux emulator for hardware-free testing with the rotary-controller-python UI. It compiles the real firmware sources (`Ramps.c`, `Modbus.c`, `Scales.c`, `UARTCallback.c`) against a HAL/FreeRTOS shim layer and simulates lathe physics — spindle with inertia, leadscrew, carriage with half-nut engagement, and cross-slide. The emulator exposes Modbus RTU via PTY pair and TCP socket so the unmodified rotary-controller-python GUI can connect as if talking to real hardware.

A two-pane ANSI terminal dashboard with sparklines provides live visualization, with keyboard controls for spindle RPM, manual axis movement, half-nut engagement, and more. All parameters are configurable via TOML file.
This was a placeholder for assisted threading/advanced ELS features coming in other branches; will add such features back into the emulator on those branches when ready.
@Funkenjaeger
Copy link
Copy Markdown
Author

Funkenjaeger commented Apr 14, 2026

Here's a quick demo of this in action in ELS mode.

2026-04-13.22-09-02.mp4

One of my next steps is to add some means of feedback on the phase relationship between spindle and leadscrew/carriage, for confirmation of alignment during multiple passes of thread cutting. With the current RCP firmware that should be guaranteed as long as the user doesn't open the half nut, but this will pave the way for integration of advanced ELS features which electronically stop/start the leadscrew while the spindle is turning and thus break and have to re-establish phase sync between passes - such as the "advanced ELS" mode I'm working on, or the Automatic Threading changes that Pawcu is working on.

I did make one "breaking" change to the Modbus holding register memory map: there was a timerHandle pointer included in the input_t typedef for the scales. Those were set in firmware, and it's not clear that there's any good reason to expose them externally via Modbus even for read, let alone write. Trouble is, those pointers end up being different sizes (4 bytes vs 8 bytes) on ARM vs x86-64, so when I compile and run the emulator on a 64-bit desktop machine, everything in the bottom of the memory map (scales and fastData) gets shifted and then there's misalignment when the RCP GUI SW accesses those registers.
I addressed this by just moving the timerHandle pointers out of the input_t typedef (which also removes it from the Modbus memory map), but that means the memory map definition in the RCP GUI SW needs to change accordingly. A dummy int32_t replaces the timerHandle in the input_t typedef so the overall memory map remains aligned to the original, thus the SW doesn't need to change.

The different sizes (# bytes) of the timerHandle pointers in ARM vs x86-64 caused a shift in the memory map of the emulator versus the real hardware, breaking the memory map.  Those pointers don't need to be exposed via Modbus anyway, so just breaking them out of there mitigates this issue.

dummy int32 replaces timerHandle in input_t typedef to maintain alignment to original memory map so SW doesn't need to change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant