Skip to content

Maschine Mk3: dual-screen support with frame-diff partial updates - #115

Open
RufusIbiza wants to merge 6 commits into
openAVproductions:masterfrom
RufusIbiza:feature/maschine-mk3-support
Open

Maschine Mk3: dual-screen support with frame-diff partial updates#115
RufusIbiza wants to merge 6 commits into
openAVproductions:masterfrom
RufusIbiza:feature/maschine-mk3-support

Conversation

@RufusIbiza

@RufusIbiza RufusIbiza commented Mar 23, 2026

Copy link
Copy Markdown

Summary

Adds full Maschine Mk3 dual-screen support to openAV-Ctlra, with efficient partial screen updates that match the Kontrol D2's capabilities.

Screen API

  • ni_maschine_mk3_screen_get_pixels(dev, screen_idx) -- access each screen's pixel buffer independently
  • ni_maschine_mk3_screen_blit(dev, screen_idx) -- full-frame update (used for keyframes)
  • ni_maschine_mk3_screen_blit_zone(dev, screen_idx, x, y, w, h) -- partial update of just the dirty bounding box

Dual-screen USB fix

The async USB write pipeline silently dropped the second screen's transfers once the inflight counter hit its cap. Switched Mk3 screen blits to synchronous bulk transfers so both screens get fair access to the shared endpoint.

Frame-diff partial updates

The example diffs each frame against the previous one and sends only the dirty bounding box via blit_zone, with a full-screen keyframe every 60 frames. This cuts per-frame USB traffic from ~522 KB down to just the changed region, leaving headroom for both screens to update smoothly.

New header and example

  • ctlra/devices/ni_maschine_mk3.h -- public API and all button/encoder defines
  • examples/maschine_mk3/ -- Cairo-based dual-screen graphics demo with buttons, pads, encoders, and touchstrip

Documentation

  • Rewrote project README with build instructions, supported device table, usage guide, and project layout
  • resources/maschine_mk3/PARTIAL_SCREEN_UPDATES.md -- full API reference, frame-diff pattern, pixel format, USB details
  • resources/maschine_mk3/MASCHINE_MK3_MAPPINGS.md -- all control mappings with tables

Test plan

  • Connect Maschine Mk3 and run examples/maschine_mk3/run_maschine_mk3.sh
  • Verify both left and right screens update continuously without stalling
  • Verify frame counter increments steadily in terminal output
  • Verify button presses, encoder turns, and pad hits generate events
  • Confirm D2 example still works unchanged

RufusIbiza and others added 6 commits March 16, 2026 13:22
…and build files, and remove the valgrind_jack suppression file.
…e docs

The async USB write pipeline silently dropped the second screen's
transfers once the inflight counter hit its cap of 10.  Switched Mk3
screen blits to synchronous bulk transfers so both screens get fair
access to the shared USB endpoint.

The example now diffs each frame against the previous one and sends only
the dirty bounding box via blit_zone, with a full-screen keyframe every
60 frames.  This cuts per-frame USB traffic from ~522 KB to just the
changed region, leaving headroom for both screens to update smoothly.

Rewrote the Mk3 resource docs (mappings, partial screen protocol) and
the project README with build instructions, device table, usage guide,
and project layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@RufusIbiza RufusIbiza changed the title Add NI Maschine Mk3 dual-screen support and partial screen update API Maschine Mk3: dual-screen support with frame-diff partial updates Mar 24, 2026

@harryhaaren harryhaaren left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot be merged as is. Reviewed commit by commit, saw the first is good, 2nd is bad, 3rd fixes up some of the accidentally introduced stuff. Lots more cleanup to be done.

Before you do the work - lets sync on what/if the longer term goal is - i'm not sure Ctlra in this shape is very useful unless actively maintained and improved - and I'm not sure if I'll have/make/find bandwidth to be that active in maintaining etc the library.

@@ -0,0 +1,19 @@
#!/bin/bash

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a new example is required, it should be integrated into the existing build system.

cairo_set_source_rgb(cr, 0.05, 0.05, 0.08);
cairo_rectangle(cr, 0, 0, WIDTH, HEIGHT);
cairo_fill(cr);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this code looks familiar (from AVTK, AVTKA or Ctlra example code i'm not sure anymore, but duplication is never good..)

@@ -0,0 +1,131 @@
#include <libusb-1.0/libusb.h>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what value this adds, ctlra can already print what USB devices it knows, or "usbview" or lsusb linux tools would do this too.

@@ -0,0 +1,75 @@
# D2 LED Mapping Discovery Results

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useful to have the data, but a machine readable format (JSON or .ini or something small/easy to parse without deps ideally..) would allow this to be updated/fixed if there were issues?

@@ -0,0 +1,75 @@
# VirtualDJ D2 Screen Communication Analysis

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting info, I hadn't investigated that in detail before. not sure we want to commit all the AI generated files.

// --- 1. Main Screen Data Packet Construction and Sender ---
// Address: 140c40860
// Constructs the 20-byte magic header and the nested 16/20-byte rectangle command.
uint32_t sub_140c40860(void* arg1, int64_t arg2, int32_t x, int32_t width, int32_t height, char display_part, int32_t stride)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

messy function names etc - this is research/POC code, not ready for merging.

@@ -0,0 +1,64 @@
#ifndef CTLRA_NI_MASCHINE_MK3_H

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure that a bunch of these were already somewhere in the Ctlra repo - perhaps on another branch? Is this duplicate..?

Comment thread ctlra/usb.c
* from ctlra->ctx. Without also pumping NULL here, async bulk-write
* completion callbacks never fire, USB_XFER_INFLIGHT_WRITE never
* decrements, and new screen blits are silently dropped after 10. */
libusb_handle_events_timeout_completed(NULL, &tv, NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice bugfix in the middle of everything else.. this should probably be a seperate commit.

@mickeyl

mickeyl commented Jul 15, 2026

Copy link
Copy Markdown

I'm working on a first-class remote control using the KK S61 mk2 for a new macOS AMIGA Tracker project.

Thanks for the Maschine MK3 display work in this PR—it inspired us to investigate the same display command family on the S-Series MK2. We confirmed chained literal/repeat/skip commands on hardware and built an adaptive single-transfer encoder around them.

In a seven-scenario hardware A/B run, average transport dropped from 144.1 KB to 59.6 KB (58.6%), and median USB time from 14.86 ms to 1.33 ms, while incompressible full-noise traffic remained essentially unchanged. Thanks for pointing us in this direction!
exec-4a5fe1ad-b974-411a-aa50-b4299fe7e933
exec-28fd7beb-8f39-407f-8fdb-c79877e1ae5a

@RufusIbiza

Copy link
Copy Markdown
Author

I'm working on a first-class remote control using the KK S61 mk2 for a new macOS AMIGA Tracker project.

Thanks for the Maschine MK3 display work in this PR—it inspired us to investigate the same display command family on the S-Series MK2. We confirmed chained literal/repeat/skip commands on hardware and built an adaptive single-transfer encoder around them.
@mickeyl - You're very welcome - really glad that you were able to get some use out of this system!

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.

3 participants