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) {
|
if (addr == ADC_DATA1 || addr == ADC_DATA2) {
|
||||||
return s->channel < ESP32C3_ADC_CHANNELS
|
return s->channel < ESP32C3_ADC_CHANNELS
|
||||||
? MIN(s->input[s->channel], ADC_MAX)
|
? MIN(qatomic_read(&s->input[s->channel]), ADC_MAX)
|
||||||
: ADC_MAX;
|
: ADC_MAX;
|
||||||
}
|
}
|
||||||
return s->regs[addr / 4];
|
return s->regs[addr / 4];
|
||||||
|
|||||||
@@ -9,6 +9,60 @@
|
|||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "hw/display/xteink_x3_eink.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_OFF 0x02
|
||||||
#define CMD_POWER_ON 0x04
|
#define CMD_POWER_ON 0x04
|
||||||
#define CMD_DTM1 0x10
|
#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);
|
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);
|
DisplaySurface *surface = qemu_console_surface(s->console);
|
||||||
memset(surface_data(surface), 0xff,
|
memset(surface_data(surface), 0xff,
|
||||||
surface_stride(surface) * surface_height(surface));
|
surface_stride(surface) * surface_height(surface));
|
||||||
|
xteink_wasm_frame_updated(s->console);
|
||||||
dpy_gfx_update(s->console, 0, 0, 480, 800);
|
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)
|
static void esp32_gpio_set_input(void *opaque, int pin, int level)
|
||||||
{
|
{
|
||||||
Esp32GpioState *s = ESP32_GPIO(opaque);
|
esp32_gpio_set_input_level(ESP32_GPIO(opaque), pin, level);
|
||||||
s->input_level = deposit32(s->input_level, pin, 1, !!level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esp32_gpio_get_input(Object *obj, Visitor *v, const char *name,
|
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);
|
Esp32GpioState *s = ESP32_GPIO(obj);
|
||||||
int pin = GPOINTER_TO_INT(opaque);
|
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);
|
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:
|
case A_GPIO_STRAP:
|
||||||
return s->strap_mode;
|
return s->strap_mode;
|
||||||
case GPIO_IN:
|
case GPIO_IN:
|
||||||
return s->input_level;
|
return qatomic_read(&s->input_level);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,10 @@
|
|||||||
#include "hw/sd/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
#include "hw/net/can/esp32c3_twai.h"
|
#include "hw/net/can/esp32c3_twai.h"
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ESP32C3_IO_WARNING 0
|
#define ESP32C3_IO_WARNING 0
|
||||||
|
|
||||||
#define ESP32C3_RESET_ADDRESS 0x40000000
|
#define ESP32C3_RESET_ADDRESS 0x40000000
|
||||||
@@ -103,6 +107,27 @@ struct Esp32C3MachineState {
|
|||||||
Esp32C3TWAIState twai;
|
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 */
|
/* 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
|
#define A_SYSCON_ORIGIN_REG 0x3F8
|
||||||
/* Temporary macro for generating a random value from register SYSCON_RND_DATA_REG */
|
/* 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);
|
Esp32C3MachineState *ms = ESP32C3_MACHINE(machine);
|
||||||
ms->xteink = true;
|
ms->xteink = true;
|
||||||
esp32c3_machine_init(machine);
|
esp32c3_machine_init(machine);
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
xteink_wasm_machine = ms;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* X3 exposes the fingerprint chips; X4 omits them so stock firmware's
|
/* 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. */
|
* all-NAK probe selects X4. The X4 panel is a blank protocol stub. */
|
||||||
|
|||||||
@@ -33,3 +33,5 @@ typedef struct Esp32GpioState {
|
|||||||
typedef struct Esp32GpioClass {
|
typedef struct Esp32GpioClass {
|
||||||
SysBusDeviceClass parent_class;
|
SysBusDeviceClass parent_class;
|
||||||
} Esp32GpioClass;
|
} Esp32GpioClass;
|
||||||
|
|
||||||
|
void esp32_gpio_set_input_level(Esp32GpioState *s, int pin, bool level);
|
||||||
|
|||||||
Reference in New Issue
Block a user