diff --git a/frontend/wasm/infiniemu.d.ts b/frontend/wasm/infiniemu.d.ts index 6addbfe..153245d 100644 --- a/frontend/wasm/infiniemu.d.ts +++ b/frontend/wasm/infiniemu.d.ts @@ -48,6 +48,8 @@ const module: EmscriptenModuleFactory([]); const consoleLines = ref([]); @@ -177,7 +199,10 @@ worker.onmessage = async (event) => { performance.cps.value = data.cps; performance.loopTime.value = data.loopTime; performance.sramSize.value = data.totalSRAM; - pins.value = data.pins; + break; + + case "pins": + pins.value = data; break; case "rttFound": @@ -225,7 +250,7 @@ function onFileLoadEnd() { } function onButtonDown(isDown: boolean) { - sendMessage(worker, "setPin", { pin: PinetimePins.Button, value: isDown }); + sendMessage(worker, "setPinVoltage", { pin: 13, value: isDown ? HIGH_VOLTAGE : 0 }); } const swipeCenter = (direction: Direction) => { @@ -266,4 +291,8 @@ function onStartTouch(x: number, y: number, isLongPress = false) { function reset() { sendMessage(worker, "reset", undefined); } + +function setPin(index: number, value: boolean | number) { + sendMessage(worker, "setPinVoltage", { pin: index, value: typeof value === "boolean" ? (value ? HIGH_VOLTAGE : 0) : value }); +} diff --git a/frontend/wasm/src/pinetime.ts b/frontend/wasm/src/pinetime.ts index e11a629..7156bc9 100644 --- a/frontend/wasm/src/pinetime.ts +++ b/frontend/wasm/src/pinetime.ts @@ -1,23 +1,41 @@ -// https://github.com/InfiniTimeOrg/InfiniTime/blob/7b39d81c8c03d14a950b844e2b8cb15107df92bf/src/drivers/PinMap.h -export enum PinetimePins { - Charging = 12, - Cst816sReset = 10, - Button = 13, - ButtonEnable = 15, - Cst816sIrq = 28, - PowerPresent = 19, - Bma421Irq = 8, - Motor = 16, - LcdBacklightLow = 14, - LcdBacklightMedium = 22, - LcdBacklightHigh = 23, - SpiSck = 2, - SpiMosi = 3, - SpiMiso = 4, - SpiFlashCsn = 5, - SpiLcdCsn = 25, - LcdDataCommand = 18, - LcdReset = 26, - TwiScl = 7, - TwiSda = 6, -}; +// From the perspective of the MCU +export type PinDirection = "i" | "o" | "io"; + +export function isInput(dir: PinDirection) { + return dir == "i" || dir == "io"; +} + +export function isOutput(dir: PinDirection) { + return dir == "o" || dir == "io"; +} + +export type Pin = { number: number; name: string; } & ( + { dir: "i"; canChange?: boolean; analog?: false; pull?: "up" | "down" } | + { dir: "i"; canChange?: boolean; analog: true, intialValue?: number } | + { dir: "o"; } | + { dir: "io"; canChange?: boolean; } +); + +export const pinetimePins: Pin[] = [ + { number: 2, name: "SpiSck", dir: "o" }, + { number: 3, name: "SpiMosi", dir: "o" }, + { number: 4, name: "SpiMiso", dir: "i" }, + { number: 5, name: "SpiFlashCsn", dir: "o" }, + { number: 6, name: "TwiSda", dir: "io" }, + { number: 7, name: "TwiScl", dir: "io" }, + { number: 8, name: "Bma421Irq", dir: "i" }, + { number: 10, name: "Cst816sReset", dir: "o" }, + { number: 12, name: "Charging", dir: "i", canChange: true, pull: "up" }, + { number: 13, name: "Button", dir: "i", canChange: true }, + { number: 14, name: "LcdBacklightLow", dir: "o" }, + { number: 15, name: "ButtonEnable", dir: "o" }, + { number: 16, name: "Motor", dir: "o" }, + { number: 18, name: "LcdDataCommand", dir: "o" }, + { number: 19, name: "PowerPresent", dir: "i", canChange: true, pull: "up" }, + { number: 22, name: "LcdBacklightMedium", dir: "o" }, + { number: 23, name: "LcdBacklightHigh", dir: "o" }, + { number: 25, name: "SpiLcdCsn", dir: "o" }, + { number: 26, name: "LcdReset", dir: "o" }, + { number: 28, name: "Cst816sIrq", dir: "i" }, + { number: 31, name: "BatteryVoltage", dir: "i", canChange: true, analog: true, intialValue: 3.9 / 2 }, +]; diff --git a/frontend/wasm/src/worker.ts b/frontend/wasm/src/worker.ts index 4878322..6ac5d76 100644 --- a/frontend/wasm/src/worker.ts +++ b/frontend/wasm/src/worker.ts @@ -1,6 +1,7 @@ import type { CPU, CST816S, Commander, LFS, NRF52832, Pinetime, Pins, Pointer, Program, RTT, SPINorFlash, ST7789 } from "../infiniemu.js" import createModule from "../infiniemu.js" import type { FileInfo, MessageFromWorkerType, MessageToWorkerType } from "./common"; +import { pinetimePins } from "./pinetime.js"; import { getZipOrNested, isFile, joinLFSPaths } from "./utils"; const iterations = 100000; @@ -115,6 +116,20 @@ class Emulator { this.displayBuffer = numberToPointer(Module._malloc(240 * 240 * 2)); this.rgbaBuffer = numberToPointer(Module._malloc(240 * 240 * 4)); this.rttReadBuffer = numberToPointer(Module._malloc(this.rttReadBufferSize)); + + this.reset(); + + for (const pin of pinetimePins) { + if (pin.dir == "i" && pin.analog && pin.intialValue) { + this.Module._pins_set_voltage(this.pins, pin.number, pin.intialValue * 1000); + } + else if (pin.dir == "i" && !pin.analog && pin.pull) { + if (pin.pull == "up") + this.Module._pins_set(this.pins, pin.number); + else + this.Module._pins_clear(this.pins, pin.number); + } + } } private doLoop(cycles: number) { @@ -169,8 +184,14 @@ class Emulator { loopTime: end - start, cps: (this.cycleCount - cycleCountStart) / ((end - start) / 1000), totalSRAM: this.Module._nrf52832_get_sram_size(this.nrf52), - pins: this.Module._pins_read_all(this.pins), }); + + const allPins = this.Module._pins_read_all(this.pins); + sendMessage("pins", pinetimePins.map(pin => { + if (pin.dir == "i" && pin.analog) + return this.Module._pins_get_voltage(this.pins, pin.number); + return (allPins & (1 << pin.number)) != 0; + })); } private sendScreenUpdate() { @@ -219,11 +240,9 @@ class Emulator { this.Module._cst816s_release_touch(this.touch); } - changePin(pin: number, isSet: boolean) { - if (isSet) - this.Module._pins_set(this.pins, pin); - else - this.Module._pins_clear(this.pins, pin); + changePin(pin: number, volts: number) { + console.log("Setting pin", pin, "to", volts, "V"); + this.Module._pins_set_voltage(this.pins, pin, volts * 1000); } private useLFS(fn: (lfs: LFS) => T) { @@ -515,7 +534,7 @@ async function handleMessage(msg: MessageToWorkerType) { emulator.clearTouch(); break; - case "setPin": + case "setPinVoltage": emulator.changePin(data.pin, data.value); break; diff --git a/include/pins.h b/include/pins.h index 5525093..9e4067b 100644 --- a/include/pins.h +++ b/include/pins.h @@ -44,7 +44,7 @@ void pins_reset(pins_t *); void pins_set(pins_t *, int pin); void pins_clear(pins_t *, int pin); void pins_toggle(pins_t *, int pin); -void pins_change(pins_t *, int pin, uint16_t value); // value is 0 or 1 if digital, millivolts if analog +void pins_set_voltage(pins_t *pins, int pin, uint16_t mv); bool pins_is_analog(pins_t *, int pin); void pins_set_analog(pins_t *, int pin, bool analog); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 403c925..c48f1a0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,7 +75,7 @@ set(WASM_EXPORTS pinetime_new pinetime_step pinetime_loop pinetime_reset pinetime_get_st7789 st7789_read_screen_rgba st7789_is_sleeping st7789_get_write_count st7789_is_sleeping pinetime_get_cst816s cst816s_do_touch cst816s_release_touch - pinetime_get_nrf52832 nrf52832_get_sram_size nrf52832_get_pins pins_set pins_clear pins_read_all + pinetime_get_nrf52832 nrf52832_get_sram_size nrf52832_get_pins pins_set_voltage pins_set pins_clear pins_read_all pins_get_voltage pinetime_get_spinorflash spinorflash_get_buffer spinorflash_get_buffer_size nrf52832_get_cpu cpu_is_sleeping cpu_mem program_new program_load_binary program_load_elf program_write_variable diff --git a/src/peripherals/nrf52832/saadc.c b/src/peripherals/nrf52832/saadc.c index 77a11d7..4d8c608 100644 --- a/src/peripherals/nrf52832/saadc.c +++ b/src/peripherals/nrf52832/saadc.c @@ -190,7 +190,6 @@ PPI_TASK_HANDLER(saadc_task_handler) case TASK_ID(TASKS_START): if (!saadc->running) { - printf("SAADC started\n"); saadc->running = true; ppi_fire_event(current_ppi, INSTANCE_SAADC, EVENT_ID(EVENTS_STARTED), saadc->inten.STARTED); } @@ -199,7 +198,6 @@ PPI_TASK_HANDLER(saadc_task_handler) case TASK_ID(TASKS_SAMPLE): if (saadc->running) { - printf("SAADC sample\n"); int16_t reading = get_reading(saadc, saadc->sample_counter); dma_write(saadc->dma, saadc->result.ptr + (saadc->sample_counter * 2), 2, (uint8_t *)&reading); @@ -217,7 +215,6 @@ PPI_TASK_HANDLER(saadc_task_handler) case TASK_ID(TASKS_STOP): if (saadc->running) { - printf("SAADC stopped\n"); saadc->running = false; ppi_fire_event(current_ppi, INSTANCE_SAADC, EVENT_ID(EVENTS_STOPPED), saadc->inten.STOPPED); } @@ -241,8 +238,6 @@ OPERATION(saadc) OP_IGNORE_LOAD_DATA OP_ASSERT_SIZE(op, WORD); - printf("read saadc offset 0x%x\n", offset); - switch (offset) { OP_TASK(TASKS_START) @@ -315,8 +310,9 @@ OPERATION(saadc) *value = saadc->channels[ch_idx].pselp; else if (*value != saadc->channels[ch_idx].pselp) { - pins_set_analog(saadc->pins, saadc->channels[ch_idx].pselp, false); - pins_set_analog(saadc->pins, *value, true); + // TODO: Check for zero + pins_set_analog(saadc->pins, pins_table[saadc->channels[ch_idx].pselp - 1], false); + pins_set_analog(saadc->pins, pins_table[*value - 1], true); saadc->channels[ch_idx].pselp = *value; } @@ -327,8 +323,9 @@ OPERATION(saadc) *value = saadc->channels[ch_idx].pseln; else if (*value != saadc->channels[ch_idx].pseln) { - pins_set_analog(saadc->pins, saadc->channels[ch_idx].pseln, false); - pins_set_analog(saadc->pins, *value, true); + // TODO: Check for zero + pins_set_analog(saadc->pins, pins_table[saadc->channels[ch_idx].pseln - 1], false); + pins_set_analog(saadc->pins, pins_table[*value - 1], true); saadc->channels[ch_idx].pseln = *value; } diff --git a/src/pins.c b/src/pins.c index 441ca69..2f963d3 100644 --- a/src/pins.c +++ b/src/pins.c @@ -4,6 +4,7 @@ #include #include #include +#include typedef struct { @@ -43,40 +44,25 @@ void pins_free(pins_t *pins) void pins_reset(pins_t *pins) { - memset(pins->pins, 0, sizeof(pins->pins)); - pins->pin_states = 0; pins->latch = 0; - - pins_set_analog(pins, 31, true); - pins_change(pins, 31, 3000); } -static inline void pins_set_voltage(pins_t *pins, int pin, uint16_t mv) +void pins_set_voltage(pins_t *pins, int pin, uint16_t mv) { assert(pin >= 0 && pin < PINS_COUNT); bool is_set = mv >= pins->high_threshold_mv; - - if (pins_is_set(pins, pin) == is_set) - return; + bool was_set = pins_is_set(pins, pin); pin_t *p = &pins->pins[pin]; pins->pin_states = (pins->pin_states & ~(1 << pin)) | (is_set << pin); pins->pins[pin].voltage = mv; - if (p->sense != SENSE_DISABLED && ((is_set && (p->sense == SENSE_HIGH)) || (!is_set && (p->sense == SENSE_LOW)))) + if (was_set != is_set && p->sense != SENSE_DISABLED && ((is_set && (p->sense == SENSE_HIGH)) || (!is_set && (p->sense == SENSE_LOW)))) pins->latch |= 1 << pin; } -void pins_change(pins_t *pins, int pin, uint16_t value) -{ - if (pins->pins[pin].analog) - pins_set_voltage(pins, pin, value); - else - pins_set_voltage(pins, pin, value ? pins->high_voltage_mv : 0); -} - void pins_set(pins_t *pins, int pin) { pins_set_voltage(pins, pin, pins->high_voltage_mv); @@ -110,6 +96,7 @@ void pins_set_analog(pins_t *pins, int pin, bool analog) { assert(pin >= 0 && pin < PINS_COUNT); + printf("Setting pin %d to %s\n", pin, analog ? "analog" : "digital"); pins->pins[pin].analog = analog; }