![]() |
HOME
–
BLOG
–
CONTACT
–
ABOUT
|
HOME / BRAWL
brawl:device/onewire
The brawl:device/onewire
interface defines a minimal, hardware-agnostic 1-Wire (Dallas/Maxim) API for WebAssembly (WASM) modules. It provides a consistent way to control and monitor 1-wire devices across diverse embedded targets - ranging from microcontrollers to emulators - while remaining fully compatible with the WASM MVP specification.
Each function follows a simple convention: it returns a signed 32-bit integer, where negative values represent standardized error codes and non-negative values represent valid results or success indicators. This design keeps the ABI deterministic, low-overhead, and portable between environments, enabling WASM applications to interact directly with physical or virtual 1-wire devices without callbacks, threads, or host-specific extensions.
This section outlines the expected behavior and conventions used by the brawl:device/onewire
interface. It provides guidance for both host implementers and guest developers to ensure consistent behavior across WASM targets.
onewireCount()
returns the total number of 1-wire buses available on the target. onewireList()
populates a memory buffer with a list of available 1-Wire bus identifiers (uint8_t
) in the host environment’s canonical order. Each 1-wire bus identifier can be passed directly to onewireOpen()
to obtain a handle for further operations.
Before reserving a pin, always call onewireCapabilities()
to verify that it supports the desired modes. Use onewireOpen()
to reserve the 1-wire bus and obtain a handle; this handle is passed to all subsequent operations. When the 1-wire bus is no longer needed, release it using onewireClose()
. 1-Wire buses remain inactive and unpredictable until configured with onewireSetSpeed()
to define their behavior and electrical characteristics.
A 1-Wire bus may be emulated on a single GPIO pin using open-drain signalling and timing in software. The host reserves the selected pin and drives it low or releases it with a pull-up Strong-pullup after certain commands (e.g. DS18B20 Convert-T) may be emulated or unsupported depending on host capability. All normal 1-Wire commands are available on the resulting software bus handle.
To detect if the host supports a software implementation, call onewireModuleCapabilities()
check for the ONEWIRE_CAPS_SW_PORT
capability, a 1-Wire bus can then be created using the onewireOpenOnPins()
function.
All brawl:device/onewire
functions return a signed 32-bit integer (int32_t
), which encodes both result and error information:
Value | |
---|---|
ret < 0 |
an error occurred. |
ret == 0 |
operation completed successfully (or no value to return). |
ret > 0 |
operation succeeded and returned a value (e.g., a data value or handle). |
All memory access operations are bounds-checked by the host; going outside will return a I2C_ERROR_MEMORY_OOB
error.
All functions return a signed 32-bit integer (int32_t
). If the value is negative, it represents an error code from the table below:
Constant | |
---|---|
ONEWIRE_ERROR_BUSY |
The 1-Wire bus is already in use or reserved by another handle. |
ONEWIRE_ERROR_UNSUPPORTED |
The requested operation or capability is not supported on this 1-Wire bus. |
ONEWIRE_ERROR_TIMEOUT |
The operation did not complete within the expected time. |
ONEWIRE_ERROR_INVALID_HANDLE |
The handle provided was invalid for the operation requested. |
ONEWIRE_ERROR_INVALID_ARG |
The argument provided was invalid for the operation requested. |
ONEWIRE_ERROR_MEMORY_OOB |
The requested operation would result in a MEMORY_OOB Error. |
ONEWIRE_ERROR_NO_DEVICE |
No device was found on the 1-Wire bus. |
ONEWIRE_ERROR_CRC |
The operation resulted in a CRC error. |
A return value >= 0
indicates success - either 0
for non-returning operations or a positive value for operations that produce a result.
Each 1-Wire bus can support one or more capabilities, reported by onewireModuleCapabilities()
and onewireCapabilities()
. These are bit-flags and may be combined using bitwise OR.
Constant (Flag) | |
---|---|
ONEWIRE_CAPS_CONTROLLER |
Supports master role. |
ONEWIRE_CAPS_MULTIDROP |
Supports multi-devices. |
ONEWIRE_CAPS_OVERDRIVE |
Supports 1-Wire overdrive speed. |
ONEWIRE_CAPS_STRONG_PULLUP |
Host can source strong pullup. |
ONEWIRE_CAPS_SEARCH_HW |
Host can accelerate ROM search. |
ONEWIRE_CAPS_SW_PORT |
Supports creating a 1-Wire bus on an arbitrary GPIO pin. |
Combine capability flags with the bitwise OR operator (|
) to describe a pin that supports multiple features.
Possible speed settings.
Constant | |
---|---|
ONEWIRE_SPEED_STANDARD |
Standard speed. |
ONEWIRE_SPEED_OVERDRIVE |
Overdrive speed. |
Possible search settings.
Constant | |
---|---|
ONEWIRE_SEARCH_NORMAL |
Normal search. |
ONEWIRE_SEARCH_ALARM_ONLY |
//--------------------------------------------------------------------------
// brawl:device/onewire
// ONEWIRE errors
enum ONEWIRE_ERROR {
// >= 0 no error
ONEWIRE_ERROR_BUSY = -1, // 1-Wire bus busy
ONEWIRE_ERROR_UNSUPPORTED = -2, // 1-Wire bus operation unsupported
ONEWIRE_ERROR_TIMEOUT = -3, // 1-Wire bus operation timed out
ONEWIRE_ERROR_INVALID_ARG = -4, // invalid argument
ONEWIRE_ERROR_MEMORY_OOB = -5, // memory OOB
ONEWIRE_ERROR_NO_DEVICE = -6, // no presence pulse, or search found none
ONEWIRE_ERROR_CRC = -7 // optional: used by helper ops that verify CRC
};
// ONEWIRE capabilities (flags)
enum ONEWIRE_CAPS {
ONEWIRE_CAPS_CONTROLLER = (1u << 0), // master role
ONEWIRE_CAPS_MULTIDROP = (1u << 1), // multi-device bus
ONEWIRE_CAPS_OVERDRIVE = (1u << 2), // support 1-Wire overdrive speed
ONEWIRE_CAPS_STRONG_PULLUP = (1u << 3), // host can source strong pullup
ONEWIRE_CAPS_SEARCH_HW = (1u << 4), // host can accelerate ROM search
ONEWIRE_CAPS_SW_PORT = (1u << 5) // supports creating a 1-Wire bus on an arbitrary GPIO pin
};
// ONEWIRE speed
enum ONEWIRE_SPEED {
ONEWIRE_SPEED_STANDARD = 0,
ONEWIRE_SPEED_OVERDRIVE = 1
};
// ONEWIRE search
enum ONEWIRE_SEARCH {
ONEWIRE_SEARCH_NORMAL = 0,
ONEWIRE_SEARCH_ALARM_ONLY = 1
};
int32_t // ONEWIRE_ERROR|ONEWIRE_CAPS
onewireModuleCapabilities(void);
int32_t // ONEWIRE_ERROR|int32_t
onewireCount(void);
int32_t // ONEWIRE_ERROR|int32_t
onewireList(int32_t mem_ptr, int32_t max_items);
int32_t // ONEWIRE_ERROR|ONEWIRE_CAPS
onewireCapabilities(int32_t owBus);
int32_t // ONEWIRE_ERROR|int32_t
onewireOpen(int32_t owBus);
int32_t // ONEWIRE_ERROR|int32_t
onewireOpenOnPin(int32_t pinNum);
int32_t // ONEWIRE_ERROR|void
onewireSetSpeed(int32_t handle, enum ONEWIRE_SPEED speed);
int32_t // ONEWIRE_ERROR|void
onewireClose(int32_t handle);
int32_t // ONEWIRE_ERROR|void
onewireReset(int32_t handle);
int32_t // ONEWIRE_ERROR|void
onewireStrongPullup(int32_t handle, int32_t duration_us);
int32_t // ONEWIRE_ERROR|void
onewireSkipRom(int32_t handle);
int32_t // ONEWIRE_ERROR|int32_t
onewireMatchRom(int32_t handle, int32_t rom8_ptr);
int32_t // ONEWIRE_ERROR|int32_t
onewireRead(int32_t handle, int32_t rx_ptr, int32_t len, int32_t timeout_us);
int32_t // ONEWIRE_ERROR|int32_t
onewireWrite(int32_t handle, int32_t tx_ptr, int32_t len, int32_t strong_pullup_us);
int32_t // ONEWIRE_ERROR|int32_t
onewireSearch(int32_t handle, int32_t dst_ptr, int32_t max_roms, enum ONEWIRE_SEARCH opts);
#include <stdint.h>
#include <stdio.h>
#include "brawl-device-onewire.h"
static void onewire_err(int32_t rc, const char *what) {
if (rc < 0) fprintf(stderr, "%s failed: %d\n", what, rc);
}
#define MAX_ONEWIRE 4
int main(void) {
int32_t n, rc;
uint8_t ids[MAX_ONEWIRE];
int32_t ow_h;
uint8_t cmd, scratch[9];
int16_t raw;
// enumerate 1-Wire buses (WASM MVP: caller-allocated buffer)
n = onewireCount();
if (n < 0) { onewire_err(n, "onewireCount"); return 1; }
if (n > MAX_ONEWIRE) n = MAX_ONEWIRE;
rc = onewireList((int32_t)(uintptr_t)ids, n);
if (rc < 0) { onewire_err(rc, "onewireList"); return 1; }
// did we find an 1-Wire bus?
if (rc >= 0) {
// pick first bust
ow_h = onewireOpen(ids[0]);
if (ow_h < 0) { onewire_err(led_h, "onewireOpen"); return 1; }
// set he speed and reset to check presence
rc = onewireSetSpeed(ow_h, ONEWIRE_SPEED_STANDARD);
if (rc < 0) { onewire_err(rc, "onewireSetSpeed"); onewireClose(ow_h); return 1; }
rc = onewireReset(ow_h);
if (rc < 0) { onewire_err(rc, "onewireReset"); onewireClose(ow_h); return 1; }
// start temperature conversion (0x44) with strong pullup (e.g. 750ms)
cmd = 0x44;
rc = onewireWrite(ow_h, (int32_t)(uintptr_t)&cmd, 1, 750000);
if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }
// read scratchpad: reset + skip + (0xBE, read 9 bytes)
rc = onewireReset(ow_h);
if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }
rc = onewireSkipRom(ow_h);
if (rc < 0) { onewire_err(rc, "onewireSkipRom"); onewireClose(ow_h); return 1; }
cmd = 0xBE;
rc = onewireWrite(ow_h, (int32_t)(uintptr_t)&cmd, 1, 0);
if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }
rc = onewireRead(ow_h, (int32_t)(uintptr_t)scratch, 9, 100000);
if (rc < 0) { onewire_err(rc, "onewireRead"); onewireClose(ow_h); return 1; }
// we should have received 9 bytes
if (rc == 9) {
// temperature in little-endian 16-bit
raw = (int16_t)((scratch[1] << 8) | scratch[0]);
// TODO convert per sensor resolution
}
// close access to the 1-Wire bus
rc = onewireClose(ow_h);
if (rc < 0) onewire_err(rc, "onewireClose");
}
return 0;
}
2025-10 (draft)