Initial LinuxCNC WebAssembly workspace snapshot
This commit is contained in:
166
wasm-core/src/sim_hal.c
Normal file
166
wasm-core/src/sim_hal.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "sim_hal.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t used;
|
||||
char name[SIM_HAL_NAME_CAPACITY];
|
||||
sim_hal_value value;
|
||||
} pin_entry;
|
||||
|
||||
typedef struct {
|
||||
uint32_t used;
|
||||
char name[SIM_HAL_NAME_CAPACITY];
|
||||
uint32_t period;
|
||||
} thread_entry;
|
||||
|
||||
typedef struct {
|
||||
uint32_t used;
|
||||
char name[SIM_HAL_NAME_CAPACITY];
|
||||
uint32_t thread;
|
||||
uint32_t calls;
|
||||
uint32_t fail;
|
||||
} function_entry;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tick;
|
||||
pin_entry pins[SIM_HAL_PIN_CAPACITY];
|
||||
thread_entry threads[SIM_HAL_THREAD_CAPACITY];
|
||||
function_entry functions[SIM_HAL_FUNCTION_CAPACITY];
|
||||
} hal_state;
|
||||
|
||||
static hal_state state;
|
||||
|
||||
static int valid_name(const char *name) {
|
||||
return name != NULL && name[0] != '\0' && strlen(name) < SIM_HAL_NAME_CAPACITY;
|
||||
}
|
||||
|
||||
static int find_pin(const char *name) {
|
||||
uint32_t index;
|
||||
for (index = 0; index < SIM_HAL_PIN_CAPACITY; ++index) {
|
||||
if (state.pins[index].used && strcmp(state.pins[index].name, name) == 0) return (int)index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_thread(const char *name) {
|
||||
uint32_t index;
|
||||
for (index = 0; index < SIM_HAL_THREAD_CAPACITY; ++index) {
|
||||
if (state.threads[index].used && strcmp(state.threads[index].name, name) == 0) return (int)index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_function(const char *name) {
|
||||
uint32_t index;
|
||||
for (index = 0; index < SIM_HAL_FUNCTION_CAPACITY; ++index) {
|
||||
if (state.functions[index].used && strcmp(state.functions[index].name, name) == 0) return (int)index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sim_hal_reset(void) {
|
||||
memset(&state, 0, sizeof(state));
|
||||
}
|
||||
|
||||
int32_t sim_hal_register_pin(const char *name, uint32_t type) {
|
||||
uint32_t index;
|
||||
if (!valid_name(name) || type < SIM_HAL_BIT || type > SIM_HAL_FLOAT) return SIM_HAL_ERR_ARGUMENT;
|
||||
if (find_pin(name) >= 0) return SIM_HAL_ERR_DUPLICATE;
|
||||
for (index = 0; index < SIM_HAL_PIN_CAPACITY; ++index) {
|
||||
if (!state.pins[index].used) {
|
||||
state.pins[index].used = 1;
|
||||
strcpy(state.pins[index].name, name);
|
||||
state.pins[index].value.type = type;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
}
|
||||
return SIM_HAL_ERR_FULL;
|
||||
}
|
||||
|
||||
int32_t sim_hal_set_pin(const char *name, sim_hal_value value) {
|
||||
int index = find_pin(name);
|
||||
if (index < 0) return SIM_HAL_ERR_NOT_FOUND;
|
||||
if (value.type != state.pins[index].value.type) return SIM_HAL_ERR_TYPE;
|
||||
if (value.type == SIM_HAL_BIT && value.value.bit > 1U) return SIM_HAL_ERR_RANGE;
|
||||
state.pins[index].value = value;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
|
||||
int32_t sim_hal_get_pin(const char *name, sim_hal_value *out) {
|
||||
int index = find_pin(name);
|
||||
if (index < 0 || out == NULL) return index < 0 ? SIM_HAL_ERR_NOT_FOUND : SIM_HAL_ERR_ARGUMENT;
|
||||
*out = state.pins[index].value;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
|
||||
int32_t sim_hal_connect(const char *source, const char *target) {
|
||||
int source_index = find_pin(source);
|
||||
int target_index = find_pin(target);
|
||||
if (source_index < 0 || target_index < 0) return SIM_HAL_ERR_NOT_FOUND;
|
||||
if (state.pins[source_index].value.type != state.pins[target_index].value.type) return SIM_HAL_ERR_CONNECTION;
|
||||
state.pins[target_index].value = state.pins[source_index].value;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
|
||||
int32_t sim_hal_register_thread(const char *name, uint32_t period_ticks) {
|
||||
uint32_t index;
|
||||
if (!valid_name(name) || period_ticks == 0U || period_ticks > 1000000U) return SIM_HAL_ERR_RANGE;
|
||||
if (find_thread(name) >= 0) return SIM_HAL_ERR_DUPLICATE;
|
||||
for (index = 0; index < SIM_HAL_THREAD_CAPACITY; ++index) {
|
||||
if (!state.threads[index].used) {
|
||||
state.threads[index].used = 1;
|
||||
strcpy(state.threads[index].name, name);
|
||||
state.threads[index].period = period_ticks;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
}
|
||||
return SIM_HAL_ERR_FULL;
|
||||
}
|
||||
|
||||
int32_t sim_hal_register_function(const char *thread, const char *name) {
|
||||
uint32_t index;
|
||||
int thread_index = find_thread(thread);
|
||||
if (thread_index < 0) return SIM_HAL_ERR_NOT_FOUND;
|
||||
if (!valid_name(name)) return SIM_HAL_ERR_ARGUMENT;
|
||||
if (find_function(name) >= 0) return SIM_HAL_ERR_DUPLICATE;
|
||||
for (index = 0; index < SIM_HAL_FUNCTION_CAPACITY; ++index) {
|
||||
if (!state.functions[index].used) {
|
||||
state.functions[index].used = 1;
|
||||
strcpy(state.functions[index].name, name);
|
||||
state.functions[index].thread = (uint32_t)thread_index;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
}
|
||||
return SIM_HAL_ERR_FULL;
|
||||
}
|
||||
|
||||
int32_t sim_hal_set_function_failure(const char *name, uint32_t fail) {
|
||||
int index = find_function(name);
|
||||
if (index < 0) return SIM_HAL_ERR_NOT_FOUND;
|
||||
state.functions[index].fail = fail ? 1U : 0U;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
|
||||
int32_t sim_hal_step(uint32_t ticks) {
|
||||
uint32_t target = state.tick + ticks;
|
||||
uint32_t tick;
|
||||
uint32_t function_index;
|
||||
for (tick = state.tick + 1U; tick <= target; ++tick) {
|
||||
for (function_index = 0; function_index < SIM_HAL_FUNCTION_CAPACITY; ++function_index) {
|
||||
function_entry *function = &state.functions[function_index];
|
||||
if (!function->used || tick % state.threads[function->thread].period != 0U) continue;
|
||||
if (function->fail) return SIM_HAL_ERR_FUNCTION;
|
||||
function->calls += 1U;
|
||||
}
|
||||
}
|
||||
state.tick = target;
|
||||
return SIM_HAL_OK;
|
||||
}
|
||||
|
||||
uint32_t sim_hal_tick(void) { return state.tick; }
|
||||
uint32_t sim_hal_function_calls(const char *name) { int index = find_function(name); return index < 0 ? 0U : state.functions[index].calls; }
|
||||
uint32_t sim_hal_pin_count(void) { uint32_t i, count = 0; for (i = 0; i < SIM_HAL_PIN_CAPACITY; ++i) count += state.pins[i].used; return count; }
|
||||
uint32_t sim_hal_thread_count(void) { uint32_t i, count = 0; for (i = 0; i < SIM_HAL_THREAD_CAPACITY; ++i) count += state.threads[i].used; return count; }
|
||||
uint32_t sim_hal_function_count(void) { uint32_t i, count = 0; for (i = 0; i < SIM_HAL_FUNCTION_CAPACITY; ++i) count += state.functions[i].used; return count; }
|
||||
Reference in New Issue
Block a user