2021-07-12 14:37:54 +02:00
|
|
|
#include <wasm3.h>
|
|
|
|
#include <m3_env.h>
|
2021-07-12 16:33:43 +02:00
|
|
|
#include "wled.h"
|
2021-07-12 14:37:54 +02:00
|
|
|
|
|
|
|
#define WASM_STACK_SLOTS 1024
|
|
|
|
#define NATIVE_STACK_SIZE (32*1024)
|
|
|
|
|
|
|
|
// For (most) devices that cannot allocate a 64KiB wasm page
|
|
|
|
#define WASM_MEMORY_LIMIT 4096
|
|
|
|
|
2021-08-11 14:10:38 +02:00
|
|
|
/*unsigned char app_wasm[] = {
|
2021-07-12 22:08:22 +02:00
|
|
|
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x03, 0x60,
|
|
|
|
0x00, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x00,
|
|
|
|
0x00, 0x02, 0x2b, 0x04, 0x03, 0x6c, 0x65, 0x64, 0x03, 0x6e, 0x6f, 0x77,
|
|
|
|
0x00, 0x00, 0x03, 0x6c, 0x65, 0x64, 0x03, 0x6c, 0x65, 0x6e, 0x00, 0x00,
|
|
|
|
0x03, 0x6c, 0x65, 0x64, 0x03, 0x73, 0x65, 0x74, 0x00, 0x01, 0x03, 0x6c,
|
|
|
|
0x65, 0x64, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x00, 0x00, 0x03, 0x02,
|
|
|
|
0x01, 0x02, 0x05, 0x03, 0x01, 0x00, 0x00, 0x07, 0x0f, 0x02, 0x02, 0x66,
|
|
|
|
0x78, 0x00, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00,
|
|
|
|
0x0a, 0x45, 0x01, 0x43, 0x01, 0x04, 0x7f, 0x10, 0x00, 0x41, 0x02, 0x76,
|
|
|
|
0x21, 0x00, 0x10, 0x01, 0x21, 0x02, 0x03, 0x40, 0x20, 0x01, 0x20, 0x02,
|
|
|
|
0x49, 0x04, 0x40, 0x20, 0x01, 0x20, 0x00, 0x41, 0xff, 0x01, 0x71, 0x22,
|
|
|
|
0x03, 0x20, 0x03, 0x41, 0x01, 0x76, 0x41, 0x00, 0x10, 0x02, 0x20, 0x00,
|
|
|
|
0x10, 0x03, 0x41, 0x04, 0x76, 0x41, 0x01, 0x6a, 0x6a, 0x21, 0x00, 0x20,
|
|
|
|
0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x0b, 0x0b, 0x00,
|
2021-07-12 16:38:36 +02:00
|
|
|
0x20, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70,
|
|
|
|
0x69, 0x6e, 0x67, 0x55, 0x52, 0x4c, 0x0e, 0x2e, 0x2f, 0x61, 0x70, 0x70,
|
|
|
|
0x2e, 0x77, 0x61, 0x73, 0x6d, 0x2e, 0x6d, 0x61, 0x70
|
2021-08-11 14:10:38 +02:00
|
|
|
};*/
|
|
|
|
//unsigned int app_wasm_len = 201;
|
2021-07-12 22:08:22 +02:00
|
|
|
|
2021-07-12 16:38:36 +02:00
|
|
|
|
2021-07-12 14:37:54 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* API bindings
|
|
|
|
*
|
|
|
|
* Note: each RawFunction should complete with one of these calls:
|
|
|
|
* m3ApiReturn(val) - Returns a value
|
|
|
|
* m3ApiSuccess() - Returns void (and no traps)
|
|
|
|
* m3ApiTrap(trap) - Returns a trap
|
|
|
|
*/
|
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_millis)
|
|
|
|
{
|
|
|
|
m3ApiReturnType (uint32_t)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiReturn(millis());
|
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_delay)
|
|
|
|
{
|
|
|
|
m3ApiGetArg (uint32_t, ms)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
// You can also trace API calls
|
2021-07-12 22:08:22 +02:00
|
|
|
Serial.print("api: delay "); Serial.println(ms);
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
//delay(ms);
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiSuccess();
|
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
// This maps pin modes from arduino_wasm_api.h
|
|
|
|
// to actual platform-specific values
|
|
|
|
uint8_t mapPinMode(uint8_t mode)
|
|
|
|
{
|
|
|
|
switch(mode) {
|
|
|
|
case 0: return INPUT;
|
|
|
|
case 1: return OUTPUT;
|
|
|
|
case 2: return INPUT_PULLUP;
|
2021-07-12 14:37:54 +02:00
|
|
|
}
|
2021-07-12 16:33:43 +02:00
|
|
|
return INPUT;
|
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_pinMode)
|
|
|
|
{
|
|
|
|
m3ApiGetArg (uint32_t, pin)
|
|
|
|
m3ApiGetArg (uint32_t, mode)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
pinMode(pin, (uint8_t)mapPinMode(mode));
|
2021-07-12 14:37:54 +02:00
|
|
|
|
|
|
|
m3ApiSuccess();
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_digitalWrite)
|
|
|
|
{
|
|
|
|
m3ApiGetArg (uint32_t, pin)
|
|
|
|
m3ApiGetArg (uint32_t, value)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
digitalWrite(pin, value);
|
2021-07-12 14:37:54 +02:00
|
|
|
|
|
|
|
m3ApiSuccess();
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_getPinLED)
|
|
|
|
{
|
|
|
|
m3ApiReturnType (uint32_t)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiReturn(2);
|
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
m3ApiRawFunction(m3_arduino_print)
|
|
|
|
{
|
|
|
|
m3ApiGetArgMem (const uint8_t *, buf)
|
|
|
|
m3ApiGetArg (uint32_t, len)
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
Serial.write(buf, len);
|
|
|
|
m3ApiSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_now) {
|
|
|
|
m3ApiReturnType(uint32_t)
|
|
|
|
m3ApiReturn(wasmfx.now());
|
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_speed) {
|
|
|
|
m3ApiReturnType(uint32_t)
|
2021-07-12 22:08:22 +02:00
|
|
|
m3ApiReturn(wasmfx.speed());//strip._segments[strip._segment_index].speed);
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_intensity) {
|
|
|
|
m3ApiReturnType(uint32_t)
|
2021-07-12 22:08:22 +02:00
|
|
|
m3ApiReturn(wasmfx.intensity());//strip._segments[strip._segment_index].intensity);
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_len) {
|
|
|
|
m3ApiReturnType(uint32_t)
|
2021-07-12 22:08:22 +02:00
|
|
|
m3ApiReturn(wasmfx.len());//strip._virtualSegmentLength);
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_fill) {
|
|
|
|
m3ApiGetArg (uint32_t, color)
|
|
|
|
|
|
|
|
strip.fill(color);
|
|
|
|
|
|
|
|
m3ApiSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_set) {
|
|
|
|
m3ApiGetArg (uint32_t, index)
|
2021-07-12 22:08:22 +02:00
|
|
|
m3ApiGetArg (uint32_t, r)
|
|
|
|
m3ApiGetArg (uint32_t, g)
|
|
|
|
m3ApiGetArg (uint32_t, b)
|
2021-07-12 16:33:43 +02:00
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
strip.setPixelColor(index, r,g,b);
|
2021-07-12 16:33:43 +02:00
|
|
|
|
|
|
|
m3ApiSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_led_rgb) {
|
|
|
|
m3ApiGetArg (uint32_t, r)
|
|
|
|
m3ApiGetArg (uint32_t, g)
|
|
|
|
m3ApiGetArg (uint32_t, b)
|
|
|
|
|
|
|
|
m3ApiReturnType(uint32_t)
|
|
|
|
uint32_t c = (r << 16) + (g << 8) + b;
|
|
|
|
m3ApiReturn(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
M3Result LinkArduino (IM3Runtime runtime)
|
|
|
|
{
|
|
|
|
IM3Module module = runtime->modules;
|
|
|
|
const char* arduino = "arduino";
|
|
|
|
const char* led = "led";
|
|
|
|
|
|
|
|
m3_LinkRawFunction (module, arduino, "millis", "i()", &m3_arduino_millis);
|
|
|
|
m3_LinkRawFunction (module, arduino, "delay", "v(i)", &m3_arduino_delay); //temp
|
|
|
|
m3_LinkRawFunction (module, arduino, "pinMode", "v(ii)", &m3_arduino_pinMode); //temp
|
|
|
|
m3_LinkRawFunction (module, arduino, "digitalWrite", "v(ii)", &m3_arduino_digitalWrite); //temp
|
|
|
|
|
|
|
|
// Test functions
|
|
|
|
m3_LinkRawFunction (module, arduino, "getPinLED", "i()", &m3_arduino_getPinLED); //temp
|
|
|
|
m3_LinkRawFunction (module, arduino, "print", "v(*i)", &m3_arduino_print);
|
|
|
|
|
|
|
|
//WLED functions
|
|
|
|
m3_LinkRawFunction (module, led, "now", "i()", &m3_led_now);
|
|
|
|
m3_LinkRawFunction (module, led, "speed", "i()", &m3_led_speed);
|
|
|
|
m3_LinkRawFunction (module, led, "intensity", "i()", &m3_led_intensity);
|
|
|
|
m3_LinkRawFunction (module, led, "len", "i()", &m3_led_len);
|
|
|
|
m3_LinkRawFunction (module, led, "fill", "v(i)", &m3_led_fill);
|
2021-07-12 22:08:22 +02:00
|
|
|
m3_LinkRawFunction (module, led, "set", "v(iiii)",&m3_led_set);
|
2021-07-12 16:33:43 +02:00
|
|
|
m3_LinkRawFunction (module, led, "rgb", "i(iii)", &m3_led_rgb);
|
|
|
|
|
|
|
|
return m3Err_none;
|
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
/*
|
|
|
|
* Engine start, liftoff!
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; }
|
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
M3Result result;
|
|
|
|
IM3Environment env;
|
|
|
|
IM3Runtime runtime;
|
|
|
|
IM3Module module;
|
|
|
|
IM3Function fu;
|
|
|
|
|
2021-10-24 11:30:53 +02:00
|
|
|
//uint32_t app_wasm_len = MAX_WASM_BIN_SIZE;
|
|
|
|
//uint8_t* app_wasm = nullptr;
|
2021-08-11 14:10:38 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
void wasm_task(void*)
|
|
|
|
{
|
2021-07-12 22:08:22 +02:00
|
|
|
result = m3Err_none;
|
2021-07-12 16:33:43 +02:00
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
env = m3_NewEnvironment ();
|
2021-07-12 16:33:43 +02:00
|
|
|
if (!env) FATAL("NewEnv", "failed");
|
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
runtime = m3_NewRuntime (env, WASM_STACK_SLOTS, NULL);
|
2021-07-12 16:33:43 +02:00
|
|
|
if (!runtime) FATAL("NewRt", "failed");
|
|
|
|
|
|
|
|
#ifdef WASM_MEMORY_LIMIT
|
|
|
|
runtime->memoryLimit = WASM_MEMORY_LIMIT;
|
|
|
|
#endif
|
|
|
|
|
2021-12-16 23:39:49 +01:00
|
|
|
if (!wasm_buffer) { //from filesystem (fx.wasm)
|
2021-10-24 11:30:53 +02:00
|
|
|
wasm_buffer_len = MAX_WASM_BIN_SIZE;
|
|
|
|
if (!readToBuffer("/fx.wasm", &wasm_buffer, &wasm_buffer_len)) {
|
|
|
|
result = "fload";
|
|
|
|
return;
|
|
|
|
}
|
2021-08-11 14:10:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Serial.println(app_wasm_len);
|
|
|
|
//Serial.println((uint32_t)app_wasm);
|
|
|
|
|
2021-10-24 11:30:53 +02:00
|
|
|
if (wasm_buffer == nullptr) {
|
2021-08-11 14:10:38 +02:00
|
|
|
result = "npr";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-24 11:30:53 +02:00
|
|
|
result = m3_ParseModule (env, &module, wasm_buffer, wasm_buffer_len);
|
2021-07-12 22:08:22 +02:00
|
|
|
if (result) FATAL("Prs", result);
|
2021-07-12 16:33:43 +02:00
|
|
|
|
2021-10-24 11:30:53 +02:00
|
|
|
delete[] wasm_buffer; wasm_buffer = nullptr; wasm_buffer_len = 0;
|
2021-08-11 14:10:38 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
result = m3_LoadModule (runtime, module);
|
2021-07-12 22:08:22 +02:00
|
|
|
if (result) FATAL("Load", result);
|
2021-07-12 16:33:43 +02:00
|
|
|
|
|
|
|
result = LinkArduino (runtime);
|
2021-07-12 22:08:22 +02:00
|
|
|
if (result) FATAL("Lnk", result);
|
2021-07-12 16:33:43 +02:00
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
result = m3_FindFunction (&fu, runtime, "fx");
|
|
|
|
if (result) FATAL("Func", result);
|
2021-07-12 16:33:43 +02:00
|
|
|
|
2021-07-12 22:08:22 +02:00
|
|
|
Serial.println(F("WASM init success!"));
|
2021-10-24 11:30:53 +02:00
|
|
|
wasm_state = WASM_STATE_READY;
|
2021-07-12 16:33:43 +02:00
|
|
|
}
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-07-12 16:33:43 +02:00
|
|
|
void wasmInit()
|
|
|
|
{
|
2021-10-24 11:30:53 +02:00
|
|
|
if (runtime || env) wasmEnd();
|
2021-07-12 16:33:43 +02:00
|
|
|
wasm_task(NULL);
|
|
|
|
}
|
|
|
|
|
2021-12-22 17:28:13 +01:00
|
|
|
volatile bool wasmRunning = false;
|
2021-07-12 14:37:54 +02:00
|
|
|
|
2021-12-22 17:28:13 +01:00
|
|
|
void wasmRun(void * parameter) {
|
2021-12-16 23:39:49 +01:00
|
|
|
result = m3_CallV(fu);
|
2021-07-12 22:08:22 +02:00
|
|
|
|
|
|
|
if (result) {
|
|
|
|
M3ErrorInfo info;
|
|
|
|
m3_GetErrorInfo (runtime, &info);
|
|
|
|
Serial.print("Err: ");
|
|
|
|
Serial.print(result);
|
|
|
|
Serial.print(" (");
|
|
|
|
Serial.print(info.message);
|
|
|
|
Serial.println(")");
|
|
|
|
if (info.file && strlen(info.file) && info.line) {
|
2021-07-23 00:30:25 +02:00
|
|
|
Serial.print("At ");
|
|
|
|
Serial.print(info.file);
|
|
|
|
Serial.print(":");
|
|
|
|
Serial.println(info.line);
|
2021-07-12 22:08:22 +02:00
|
|
|
}
|
2021-10-24 11:30:53 +02:00
|
|
|
wasm_state = WASM_STATE_ERROR;
|
2021-07-23 00:30:25 +02:00
|
|
|
}
|
2021-12-22 17:28:13 +01:00
|
|
|
wasmRunning = false;
|
|
|
|
#ifdef ESP32
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void wasmRunTask() {
|
|
|
|
//re-init after wasm_buffer refresh
|
|
|
|
if (wasm_state == WASM_STATE_STALE) wasmInit();
|
|
|
|
|
|
|
|
if (wasm_state != WASM_STATE_READY) return;
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
Serial.print("WASM run error");
|
|
|
|
Serial.println(result);
|
|
|
|
wasm_state = WASM_STATE_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ESP32
|
|
|
|
// On ESP32, we can launch in a separate thread
|
|
|
|
wasmRunning = true;
|
|
|
|
unsigned long startTime = millis();
|
|
|
|
TaskHandle_t xHandle = NULL;
|
|
|
|
xTaskCreate(&wasmRun, "wasm3", 8096, NULL, 1, &xHandle);
|
|
|
|
while (wasmRunning) {
|
|
|
|
if (millis() - startTime > 250) { //bail
|
|
|
|
if (xHandle != NULL) vTaskDelete(xHandle);
|
|
|
|
wasmRunning = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
wasmRun(nullptr); //no hang protection (e.g. "while (true);")
|
|
|
|
#endif
|
2021-07-12 22:08:22 +02:00
|
|
|
}
|
2021-07-23 00:30:25 +02:00
|
|
|
|
|
|
|
void wasmEnd() {
|
2021-08-11 14:10:38 +02:00
|
|
|
//if (module) m3_FreeModule(module); module = nullptr;
|
|
|
|
Serial.println("F");
|
2021-07-23 00:30:25 +02:00
|
|
|
if (runtime) m3_FreeRuntime(runtime); runtime = nullptr;
|
|
|
|
if (env) m3_FreeEnvironment(env); env = nullptr;
|
2021-08-11 14:10:38 +02:00
|
|
|
Serial.println("F later");
|
2021-10-24 11:30:53 +02:00
|
|
|
wasm_state = WASM_STATE_UNLOADED;
|
2021-07-12 14:37:54 +02:00
|
|
|
}
|