-
Notifications
You must be signed in to change notification settings - Fork 3
Docs
Documentation for the plmctrl C++ shared library. Function prototypes are defined in plmctrl.h; implementations live in plmctrl.cpp. Wrappers in other languages call these functions with light error handling.
The library supports two PLM types, auto-detected from the window dimensions you pass to SetPLMWindowPos:
| Mode | Resolution (N × M) |
Superpixel (rows, cols) | Levels | Bitpacked frame |
|---|---|---|---|---|
| VIS | 1358 × 800 | 2 × 2 | 16 | 2N × 2M |
| NIR alpha sample | 904 × 800 | 3 × 2 | 32 | (3N+4) × 2M |
Each bitpacked frame stores 24 holograms by spreading their bits across the R, G and B channels (8 bits each). The alpha channel is set to 255.
void StartUI(unsigned int number_of_frames)Starts the display thread and opens the PLM debug window. Allocates internal storage for number_of_frames bitpacked frames (each frame holds 24 holograms).
unsigned int number_of_frames
// Maximum number of bitpacked frames stored in plmctrl's memory.void SetPLMWindowPos(int width, int height, int x0 = 0, int y0 = 0)Sets the PLM window's physical pixel size and the screen-space top-left corner where it should be placed. The mode (VIS / NIR) is auto-detected from (width, height):
-
1358 × 800→ VIS -
904 × 800→ NIR
int width // Window width in pixels.
int height // Window height in pixels.
int x0 // X coordinate of the window's top-left corner, in virtual desktop space.
int y0 // Y coordinate of the window's top-left corner, in virtual desktop space.
// Example: a 1080p main monitor with the PLM panel sitting to its right → (x0, y0) = (1920, 0).void SetWindowed(bool windowed_mode)Switches between fullscreen-borderless on the target monitor and a regular movable window. Useful when debugging in another secondary monitor (not the PLM).
bool windowed_mode // true = windowed, false = borderless fullscreen.bool StartSequence(int number_of_frames)Starts displaying the configured sequence from the beginning. number_of_frames must not exceed the value passed to StartUI. Returns true on success.
int number_of_frames // Number of frames in the sequence to play.bool SetFrameSequence(unsigned long long* sequence, unsigned long long length)Defines the playback order. sequence[i] is the index of the bitpacked frame to display in slot i. Returns false if length > number_of_frames (from StartUI).
unsigned long long* sequence // Array of frame indices.
unsigned long long length // Number of entries in `sequence`.bool SetPLMFrame(unsigned long long offset = 0)Selects which bitpacked frame is currently shown on the PLM. Returns false if offset is past the end of storage.
unsigned long long offset // Frame index in plmctrl storage.bool InsertPLMFrame(unsigned char* frame,
unsigned long long num_frames = 1,
unsigned long long offset = 0,
int type = 0)Copies num_frames bitpacked frames into plmctrl's storage starting at slot offset. The expected per-pixel layout depends on type:
unsigned char* frame // Pointer to source frame data, row-major.
unsigned long long num_frames // Number of frames to insert.
unsigned long long offset // Destination slot index in plmctrl storage.
int type // 0 = RGB (3 bytes/pixel), 1 = RGBA (4 bytes/pixel).Each frame is width × height pixels, where width / height are the bitpacked-frame dimensions for the current PLM mode (see table at top).
The bitpack functions take a stack of phase profiles in [0, 1) (representing [0, 2π)) and pack them into a single RGBA frame. CPU and GPU variants exist for both VIS and NIR. The GPU variants run a DirectX 11 compute shader (BitpackHologramsCS.hlsl for VIS, BitpackHologramsNIR_CS.hlsl for NIR) and are typically much faster.
bool BitpackHolograms(float* phase, unsigned char* frame,
unsigned long long N, unsigned long long M,
int num_holograms)float* phase // N × M × num_holograms floats, row-major, normalised [0, 1).
unsigned char* frame // Output buffer, sized 4 × (2N) × (2M) bytes (RGBA).
unsigned long long N // Phase profile width.
unsigned long long M // Phase profile height.
int num_holograms // 1..24.bool BitpackHologramsNIR(float* phase, unsigned char* frame,
unsigned long long N, unsigned long long M,
int num_holograms)Same as BitpackHolograms but produces the NIR (3N+4) × 2M output and uses the NIR per-column-parity LUT for quantization.
float* phase // N × M × num_holograms floats.
unsigned char* frame // Output buffer, sized 4 × (3N+4) × (2M) bytes.
unsigned long long N // Phase profile width.
unsigned long long M // Phase profile height.
int num_holograms // 1..24.bool BitpackHologramsGPU(float* phase, unsigned char* frame,
unsigned long long N, unsigned long long M,
int num_holograms,
bool same_phase)Compute-shader version of BitpackHolograms.
float* phase // Phase profile data (see same_phase below).
unsigned char* frame // Output buffer, 4 × (2N) × (2M) bytes.
unsigned long long N // Phase profile width.
unsigned long long M // Phase profile height.
int num_holograms // 1..24.
bool same_phase // false: phase contains N × M × num_holograms floats (one per hologram).
// true: phase contains a single N × M frame, used for all holograms.
// Lets you skip the 24× allocation for uniform test patterns.bool BitpackHologramsNIRGPU(float* phase, unsigned char* frame,
unsigned long long N, unsigned long long M,
int num_holograms,
bool same_phase)Compute-shader version of BitpackHologramsNIR. Output is 4 × (3N+4) × (2M) bytes. same_phase works as for the VIS variant.
bool BitpackAndInsertGPU(float* phase,
unsigned long long N, unsigned long long M,
int num_holograms,
unsigned long long offset,
bool same_phase)
bool BitpackAndInsertNIRGPU(float* phase,
unsigned long long N, unsigned long long M,
int num_holograms,
unsigned long long offset,
bool same_phase)Convenience wrappers — equivalent to calling BitpackHologramsGPU / BitpackHologramsNIRGPU followed by InsertPLMFrame and SetPLMFrame. The bitpacked output is written into plmctrl's internal buffer at offset, and that frame is then displayed.
unsigned long long offset // Destination slot in plmctrl frame storage.
// All other parameters as for the corresponding BitpackHolograms*GPU.The phase map controls how each quantized level drives the four (VIS) or six (NIR) sub-pixel electrodes of a superpixel. This is not really necessary with the default settings from the library. This was added before we knew the proper mapping, so we measured it and used the following functions to set it.
bool SetPhaseMap(int* new_phase_map)Sets the VIS phase map: 16 levels × 4 cells = 64 ints ({0, 1}). Cell order per level follows the TI DLP6750 layout — [E3, E2, E1, E0]. Switches the library to VIS mode.
int* new_phase_map // 64 ints, row-major (level then cell).bool SetPhaseMapNIR(int* new_phase_map)Sets the NIR phase map: 32 levels × 6 cells = 192 ints ({0, 1}). Switches the library to NIR mode.
int* new_phase_map // 192 ints, row-major (level then cell).These functions talk to the PLM's over USB. They are just a convenience to avoid using LightCrafter for configuring the PLM.
Note: these are only available in builds with
INCLUDE_LIGHTCRAFTER_WRAPPERSdefined.
int Open()
int Close()Open or close the USB connection to the PLM. Most other comms calls require the device to be open.
int Play()
int Stop()Start / stop the PLM's pattern sequence on the device side (independent of the host display thread).
int SetSource(unsigned int source, unsigned int portWidth)Selects the input source (e.g. parallel RGB, FPD-Link) and the input port bus width.
int SetPortSwap(unsigned int port, unsigned int swap)Configures port-swap settings on the input bus.
int SetPortConfig(int connection_type)
int SetConnectionType(int connection_type)Configure the data port / connection type.
int SetVideoPatternMode()
int GetVideoPatternMode()Switches the PLM into Video Pattern mode (required for 24×-bitpacked playback) and reads the current mode back.
int GetConnectionType()Returns the currently configured input connection type.
int UpdateLUT(int play_mode, int connection_type)Pushes the LUT/sequence configuration to the controller for the given play mode and connection type.