Add xteink browser bridge
This commit is contained in:
@@ -27,7 +27,7 @@ static uint64_t esp32c3_adc_read(void *opaque, hwaddr addr, unsigned size)
|
||||
}
|
||||
if (addr == ADC_DATA1 || addr == ADC_DATA2) {
|
||||
return s->channel < ESP32C3_ADC_CHANNELS
|
||||
? MIN(s->input[s->channel], ADC_MAX)
|
||||
? MIN(qatomic_read(&s->input[s->channel]), ADC_MAX)
|
||||
: ADC_MAX;
|
||||
}
|
||||
return s->regs[addr / 4];
|
||||
|
||||
@@ -9,6 +9,60 @@
|
||||
#include "hw/irq.h"
|
||||
#include "hw/display/xteink_x3_eink.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
static QemuConsole *xteink_wasm_console;
|
||||
static uint32_t xteink_wasm_generation;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE uintptr_t xteink_wasm_framebuffer(void)
|
||||
{
|
||||
DisplaySurface *surface = xteink_wasm_console
|
||||
? qemu_console_surface(xteink_wasm_console)
|
||||
: NULL;
|
||||
return surface ? (uintptr_t)surface_data(surface) : 0;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int xteink_wasm_width(void)
|
||||
{
|
||||
DisplaySurface *surface = xteink_wasm_console
|
||||
? qemu_console_surface(xteink_wasm_console)
|
||||
: NULL;
|
||||
return surface ? surface_width(surface) : 0;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int xteink_wasm_height(void)
|
||||
{
|
||||
DisplaySurface *surface = xteink_wasm_console
|
||||
? qemu_console_surface(xteink_wasm_console)
|
||||
: NULL;
|
||||
return surface ? surface_height(surface) : 0;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE int xteink_wasm_stride(void)
|
||||
{
|
||||
DisplaySurface *surface = xteink_wasm_console
|
||||
? qemu_console_surface(xteink_wasm_console)
|
||||
: NULL;
|
||||
return surface ? surface_stride(surface) : 0;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE uint32_t xteink_wasm_frame_generation(void)
|
||||
{
|
||||
return qatomic_read(&xteink_wasm_generation);
|
||||
}
|
||||
|
||||
static void xteink_wasm_frame_updated(QemuConsole *console)
|
||||
{
|
||||
xteink_wasm_console = console;
|
||||
qatomic_inc(&xteink_wasm_generation);
|
||||
}
|
||||
#else
|
||||
static void xteink_wasm_frame_updated(QemuConsole *console)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CMD_POWER_OFF 0x02
|
||||
#define CMD_POWER_ON 0x04
|
||||
#define CMD_DTM1 0x10
|
||||
@@ -33,6 +87,7 @@ static void xteink_x3_eink_render(XteinkX3EinkState *s)
|
||||
}
|
||||
}
|
||||
|
||||
xteink_wasm_frame_updated(s->console);
|
||||
dpy_gfx_update(s->console, 0, 0, XTEINK_X3_HEIGHT, XTEINK_X3_WIDTH);
|
||||
}
|
||||
|
||||
@@ -171,6 +226,7 @@ static void xteink_x4_eink_render(XteinkX4EinkState *s)
|
||||
DisplaySurface *surface = qemu_console_surface(s->console);
|
||||
memset(surface_data(surface), 0xff,
|
||||
surface_stride(surface) * surface_height(surface));
|
||||
xteink_wasm_frame_updated(s->console);
|
||||
dpy_gfx_update(s->console, 0, 0, 480, 800);
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -38,10 +38,20 @@ static void esp32_gpio_drive_outputs(Esp32GpioState *s)
|
||||
}
|
||||
}
|
||||
|
||||
void esp32_gpio_set_input_level(Esp32GpioState *s, int pin, bool level)
|
||||
{
|
||||
uint32_t old_level;
|
||||
uint32_t new_level;
|
||||
|
||||
do {
|
||||
old_level = qatomic_read(&s->input_level);
|
||||
new_level = deposit32(old_level, pin, 1, level);
|
||||
} while (qatomic_cmpxchg(&s->input_level, old_level, new_level) != old_level);
|
||||
}
|
||||
|
||||
static void esp32_gpio_set_input(void *opaque, int pin, int level)
|
||||
{
|
||||
Esp32GpioState *s = ESP32_GPIO(opaque);
|
||||
s->input_level = deposit32(s->input_level, pin, 1, !!level);
|
||||
esp32_gpio_set_input_level(ESP32_GPIO(opaque), pin, level);
|
||||
}
|
||||
|
||||
static void esp32_gpio_get_input(Object *obj, Visitor *v, const char *name,
|
||||
@@ -49,7 +59,7 @@ static void esp32_gpio_get_input(Object *obj, Visitor *v, const char *name,
|
||||
{
|
||||
Esp32GpioState *s = ESP32_GPIO(obj);
|
||||
int pin = GPOINTER_TO_INT(opaque);
|
||||
bool level = extract32(s->input_level, pin, 1);
|
||||
bool level = extract32(qatomic_read(&s->input_level), pin, 1);
|
||||
visit_type_bool(v, name, &level, errp);
|
||||
}
|
||||
|
||||
@@ -78,7 +88,7 @@ static uint64_t esp32_gpio_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
case A_GPIO_STRAP:
|
||||
return s->strap_mode;
|
||||
case GPIO_IN:
|
||||
return s->input_level;
|
||||
return qatomic_read(&s->input_level);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
#include "hw/sd/sd.h"
|
||||
#include "hw/net/can/esp32c3_twai.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#define ESP32C3_IO_WARNING 0
|
||||
|
||||
#define ESP32C3_RESET_ADDRESS 0x40000000
|
||||
@@ -103,6 +107,27 @@ struct Esp32C3MachineState {
|
||||
Esp32C3TWAIState twai;
|
||||
};
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
static struct Esp32C3MachineState *xteink_wasm_machine;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void xteink_wasm_set_adc(int channel, uint32_t value)
|
||||
{
|
||||
if (xteink_wasm_machine && channel >= 0 &&
|
||||
channel < ESP32C3_ADC_CHANNELS) {
|
||||
qatomic_set(&xteink_wasm_machine->adc.input[channel],
|
||||
MIN(value, UINT32_C(0xfff)));
|
||||
}
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void xteink_wasm_set_gpio(int pin, int level)
|
||||
{
|
||||
if (xteink_wasm_machine && pin >= 0 && pin < ESP32_GPIO_COUNT) {
|
||||
esp32_gpio_set_input_level(&xteink_wasm_machine->gpio.parent,
|
||||
pin, level);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fake register used by ESP-IDF application to determine whether the code is running on real hardware or on QEMU */
|
||||
#define A_SYSCON_ORIGIN_REG 0x3F8
|
||||
/* Temporary macro for generating a random value from register SYSCON_RND_DATA_REG */
|
||||
@@ -722,6 +747,9 @@ static void xteink_machine_init(MachineState *machine)
|
||||
Esp32C3MachineState *ms = ESP32C3_MACHINE(machine);
|
||||
ms->xteink = true;
|
||||
esp32c3_machine_init(machine);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
xteink_wasm_machine = ms;
|
||||
#endif
|
||||
|
||||
/* X3 exposes the fingerprint chips; X4 omits them so stock firmware's
|
||||
* all-NAK probe selects X4. The X4 panel is a blank protocol stub. */
|
||||
|
||||
@@ -33,3 +33,5 @@ typedef struct Esp32GpioState {
|
||||
typedef struct Esp32GpioClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
} Esp32GpioClass;
|
||||
|
||||
void esp32_gpio_set_input_level(Esp32GpioState *s, int pin, bool level);
|
||||
|
||||
Reference in New Issue
Block a user