Skip to main content

Sending Inputs to the Module

Each recipe on this page packs bytes into the input buffer on the host, and shows how the device application turns those bytes into distributional values. The Cookbook conventions define the compute_module object, the round trip, and the buffer capacities that the snippets rely on.

Send floats and build a parametric distribution

The host sends plain floats as distribution parameters, and the device application constructs the distribution with one UxHw call. This is the leanest input path, because the host needs no distributional tooling at all.

On the host

import struct

compute_module.write_input_buffer(struct.pack("<2f", 4.5, 5.5))
compute_module.calculate_command(1, poll_sleep_time=0.001, verbose=False)

On the module

#include <uxhw.h>
#include "C0HAL.h"

float inputDistribution = UxHwFloatUniformDist(
kC0HALInputBufferFloat[0],
kC0HALInputBufferFloat[1]);

The same shape works for any parametric distribution. For example, UxHwFloatGaussDist(kC0HALInputBufferFloat[0], kC0HALInputBufferFloat[1]) reads the two floats as mean and standard deviation instead. See Parametric Distributions for the full list.

Send measured samples and build a distribution from them

The host sends raw measurements, and the device application turns them into a distribution. Use this when the input distribution comes from measured data rather than from a known distribution family.

On the host

import struct

samples = [4.97, 5.03, 5.01, 4.97, 5.05, 4.99, 5.02, 4.98]
payload = struct.pack("<I", len(samples)) + struct.pack(f"<{len(samples)}f", *samples)
compute_module.write_input_buffer(payload)
compute_module.calculate_command(1, poll_sleep_time=0.001, verbose=False)

On the module

#include <uxhw.h>
#include "C0HAL.h"

uint32_t sampleCount = kC0HALInputBufferUint32[0];
float inputDistribution = UxHwFloatDistFromSamples(
(float *) &kC0HALInputBufferUint32[1],
sampleCount);

The 4-byte count header leaves room for 1023 samples on the C0-microSD and 8191 samples on the C0-microSD+. When your samples carry weights, send position and weight pairs instead and construct the distribution with UxHwFloatDistFromWeightedSamples(). See Distribution from Samples and Distribution from Weighted Samples.

Send an arbitrary distribution as Ux Binary data

The host sends a complete distribution, and the device application reconstructs it exactly. Use this to feed the module a distribution that came from a previous computation, a file, or host-side construction, without reducing it to parameters or samples.

On the host

The signaloid package parses any Ux String into a DistributionalValue, and bytes() exports the same value as Ux Binary Data.

import struct
from signaloid.distributional.distributional import DistributionalValue

dist = DistributionalValue.parse(ux_string)
payload = bytes(dist)
compute_module.write_input_buffer(struct.pack("<I", len(payload)) + payload)
compute_module.calculate_command(1, poll_sleep_time=0.001, verbose=False)

On the module

#include <uxhw.h>
#include "C0HAL.h"

float inputDistribution = UxHwFloatByteArrayToDistribution(
(uint8_t *) &kC0HALInputBufferUint32[1],
kC0HALInputBufferUint32[0]);

See Ux Binary Data to Distribution for the device-side call and Uncertainty Hexadecimal (“Ux”) Data Format for the data format itself.

Send integers as configuration

Not every input is a distribution. Sample counts, iteration counts, and mode flags travel as unsigned integers in the same buffer.

On the host

import struct

compute_module.write_input_buffer(struct.pack("<I", 100))
compute_module.calculate_command(2, poll_sleep_time=0.001, verbose=False)

On the module

#include "C0HAL.h"

uint32_t requestedSampleCount = kC0HALInputBufferUint32[0];

The recipe Return Samples From a Distributional Value uses exactly this word to size its output.

Next steps