From 9696f0ed88d5c138c072f6581d73157b7b7c80fc Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Sun, 19 May 2024 14:03:12 +0300 Subject: [PATCH] feat: SH1107 --- LICENSE | 2 +- Makefile | 2 +- README.md | 12 +- chip.json | 19 +- diagram.json | 32 -- src/main.c | 377 +++++++++++++++++- src/wokwi-api.h | 30 +- test/.gitignore | 1 - test/blink/blink.ino | 13 - test/blink/build/arduino.avr.uno/.gitignore | 2 - .../blink/build/arduino.avr.uno/blink.ino.elf | Bin 24132 -> 0 bytes .../blink/build/arduino.avr.uno/blink.ino.hex | 122 ------ wokwi.toml | 8 - 13 files changed, 399 insertions(+), 221 deletions(-) delete mode 100644 diagram.json delete mode 100644 test/.gitignore delete mode 100644 test/blink/blink.ino delete mode 100644 test/blink/build/arduino.avr.uno/.gitignore delete mode 100644 test/blink/build/arduino.avr.uno/blink.ino.elf delete mode 100644 test/blink/build/arduino.avr.uno/blink.ino.hex delete mode 100644 wokwi.toml diff --git a/LICENSE b/LICENSE index 620c954..c743ebb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2022 Uri Shaked +Copyright (c) 2024 Uri Shaked Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index f7709e6..15b5a63 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: © 2022 Uri Shaked +# SPDX-FileCopyrightText: © 2024 Uri Shaked # SPDX-License-Identifier: MIT SOURCES = src/main.c diff --git a/README.md b/README.md index d9f3a4f..be0ca13 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,9 @@ -# Inverter Chip example - -Example of a basic custom chip for [Wokwi](https://wokwi.com/). - -The actual source code for the chip lives in [src/main.c](src/main.c), and the pins are described in [chip.json](chip.json). +# SH1107 Chip for Wokwi ## Building The easiest way to build the project is to open it inside a Visual Studio Code dev container, and then run the `make` command. -## Testing - -You can test this project using the [Wokwi extension for VS Code](https://marketplace.visualstudio.com/items?itemName=wokwi.wokwi-vscode). Open the project with Visual Studio Code, press "F1" and select "Wokwi: Start Simulator". - -If you want to make changes to the test project firmware, edit [test/blink/blink.ino](test/blink/blink.ino), and then run `make test` to rebuild the .hex file. You'll need the [arduino-cli](https://arduino.github.io/arduino-cli/latest/installation/), which is already installed in the dev container. - ## License This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more details. diff --git a/chip.json b/chip.json index a94778a..889f48e 100644 --- a/chip.json +++ b/chip.json @@ -1,13 +1,14 @@ { - "version": 1, - "name": "Inverter", + "name": "SH1107", "author": "Uri Shaked", - "license": "MIT", - "docs": "https://github.com/wokwi/inverter-chip/blob/main/docs/README.md", "pins": [ - "OUT", - "IN", - "VCC", - "GND" - ] + "SCL", + "SDA", + "GND", + "VCC" + ], + "display": { + "width": 128, + "height": 128 + } } \ No newline at end of file diff --git a/diagram.json b/diagram.json deleted file mode 100644 index 88a746d..0000000 --- a/diagram.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": 1, - "author": "Uri Shaked", - "editor": "wokwi", - "parts": [ - { "type": "wokwi-arduino-uno", "id": "uno", "top": -57, "left": -0.6, "attrs": {} }, - { "type": "chip-inverter", "id": "chip1", "top": -94.98, "left": 292.8, "attrs": {} }, - { - "type": "wokwi-led", - "id": "led1", - "top": -168.25, - "left": 199.91, - "attrs": { "color": "red" } - }, - { - "type": "wokwi-led", - "id": "led2", - "top": -168.98, - "left": 256.43, - "attrs": { "color": "green" } - } - ], - "connections": [ - [ "chip1:IN", "uno:2", "green", [] ], - [ "chip1:OUT", "led2:A", "blue", [] ], - [ "uno:GND.1", "led1:C", "black", [ "v0" ] ], - [ "uno:2", "led1:A", "green", [ "v0" ] ], - [ "uno:GND.1", "led2:C", "black", [ "v-55.43", "h154.13" ] ], - [ "uno:VIN", "chip1:VCC", "red", [ "v28.7", "h234.5", "v-240" ] ], - [ "chip1:GND", "uno:GND.3", "black", [ "h30.61", "v259.2", "h-259.2" ] ] - ] -} \ No newline at end of file diff --git a/src/main.c b/src/main.c index d0863dd..757dd25 100644 --- a/src/main.c +++ b/src/main.c @@ -1,30 +1,371 @@ -// For information and examples see: -// https://link.wokwi.com/custom-chips-alpha +// Wokwi SH1107 Display Custom Chip - For information and examples see: +// https://docs.wokwi.com/chips-api/getting-started +// +// SPDX-License-Identifier: MIT +// Copyright (C) 2023 Uri Shaked / wokwi.com + +// Datasheet: https://www.displayfuture.com/Display/datasheet/controller/SH1107.pdf #include "wokwi-api.h" #include #include +#include +#include + +#define SH1107_CONTROL_CO 0x80 +#define SH1107_CONTROL_DC 0x40 + +#define CMD_SET_PAGE_ADDR_MODE 0x20 +#define CMD_SET_VERTICAL_ADDR_MODE 0x21 +#define CMD_SET_CONTRAST 0x81 +#define CMD_SEG_REMAP_OFF 0xa0 +#define CMD_SEG_REMAP_ON 0xa1 +#define CMD_DISPLAY_ALL_ON_RESUME 0xa4 +#define CMD_DISPLAY_ALL_ON 0xa5 +#define CMD_NORMAL_DISPLAY 0xa6 +#define CMD_INVERT_DISPLAY 0xa7 +#define CMD_SET_MULTIPLEX 0xa8 +#define CMD_DCDC 0xad +#define CMD_DISPLAY_OFF 0xae +#define CMD_DISPLAY_ON 0xaf +#define CMD_COM_SCAN_INC 0xc0 +#define CMD_COM_SCAN_DEC 0xc8 +#define CMD_SET_DISPLAY_OFFSET 0xd3 +#define CMD_SET_DISPLAY_CLOCK_DIV 0xd5 +#define CMD_SET_PRECHARGE 0xd9 +#define CMD_SET_COM_PINS 0xda +#define CMD_SET_VCOM_DESELECT 0xdb +#define CMD_SET_DISP_START_LINE 0xdc +#define CMD_READ_MODIFY_WRITE 0xe0 +#define CMD_END 0xee +#define CMD_NOP 0xe3 + +// Specifies the number of parameter bytes for each multi-byte command +const uint8_t multi_byte_commands[] = { + [CMD_SET_CONTRAST] = 1, + [CMD_SET_MULTIPLEX] = 1, + [CMD_DCDC] = 1, + [CMD_SET_DISPLAY_OFFSET] = 1, + [CMD_SET_COM_PINS] = 1, + [CMD_SET_DISPLAY_CLOCK_DIV] = 1, + [CMD_SET_PRECHARGE] = 1, + [CMD_SET_VCOM_DESELECT] = 1, + [CMD_SET_DISP_START_LINE] = 1, +}; + +typedef struct +{ + // Display buffer + uint32_t width; + uint32_t height; + int8_t x_offset; + uint8_t pixels[128 * 128 / 8]; + buffer_t framebuffer; + timer_t update_timer; + + // Display settings + bool display_on; + bool updated; + uint8_t contrast; + bool invert; + bool reverse_rows; + bool segment_remap; + + // Speed and timing settings + uint8_t clock_divider; + uint8_t multiplex_ratio; + uint8_t phase1; + uint8_t phase2; + + // Memory and addressing settings + uint8_t active_column; + uint8_t active_page; + uint8_t memory_mode; -typedef struct { - pin_t pin_in; - pin_t pin_out; -} chip_state_t; + uint8_t start_line; + + // Command parsing state machine + bool control_byte; + bool continuous_mode; + bool command_mode; + uint8_t current_command_index; + uint8_t current_command_length; + uint8_t current_command[8]; +} sh1107_state_t; + +static void sh1107_reset(sh1107_state_t *state) +{ + state->width = 128; + state->height = 128; + state->x_offset = 96; // varias between display models + state->memory_mode = CMD_SET_PAGE_ADDR_MODE; + state->contrast = 0x7f; + state->clock_divider = 1; + state->multiplex_ratio = 63; + state->phase1 = 2; + state->phase2 = 2; + state->current_command_index = 0; + state->active_column = 0; + state->active_page = 0; + state->start_line = 0; + state->reverse_rows = false; + state->invert = false; + state->updated = false; +} + +void sh1107_update_buffer(void *user_data) { + sh1107_state_t *state = user_data; + const uint8_t *pixels = state->pixels; + const uint8_t invert = state->invert; + const bool display_on = state->display_on; + const bool reverse_rows = state->reverse_rows; + const uint8_t start_line = state->start_line; + const uint8_t width = state->width; + const uint8_t height = state->height; + const int8_t x_offset = state->x_offset; + + for (uint8_t y = 0; y < height; y++) { + for (uint8_t x = 0; x < width; x++) { + const uint32_t scroll_y = y + start_line; + const uint32_t virtual_y = (reverse_rows ? height - 1 - scroll_y : scroll_y) % width; + const uint32_t pix_index = (virtual_y / 8) * width + (x + x_offset + width) % width; + const bool pixValue = pixels[pix_index] & (1 << virtual_y % 8) ? !invert : invert; + const uint32_t data_offset = (y * width + x) * 4; + uint32_t pixel = pixValue && display_on ? 0xffffffff : 0; + buffer_write(state->framebuffer, data_offset, &pixel, sizeof(pixel)); + } + } + state->updated = false; +} -static void chip_pin_change(void *user_data, pin_t pin, uint32_t value) { - chip_state_t *chip = (chip_state_t*)user_data; - printf("Pin change: %d %d\n", pin, value); - pin_write(chip->pin_out, !value); +void sh1107_schedule_update(sh1107_state_t *state) { + if (!state->updated) { + state->updated = true; + timer_start(state->update_timer, 16667, false); // 16.667 millis for ~60 MHz + } } -void chip_init(void) { - chip_state_t *chip = malloc(sizeof(chip_state_t)); - chip->pin_in = pin_init("IN", INPUT); - chip->pin_out = pin_init("OUT", OUTPUT); +static void sh1107_process_command(sh1107_state_t *state) +{ + uint8_t command_code = state->current_command[0]; + bool auto_update = false; + switch (command_code) + { + case CMD_SET_CONTRAST: + state->contrast = state->current_command[1]; + auto_update = true; + break; + + case CMD_DISPLAY_OFF: + state->display_on = false; + sh1107_schedule_update(state); + break; + + case CMD_DISPLAY_ON: + state->display_on = true; + sh1107_schedule_update(state); + break; + + case CMD_NORMAL_DISPLAY: + state->invert = false; + auto_update = true; + break; + + case CMD_INVERT_DISPLAY: + state->invert = true; + auto_update = true; + break; + + case CMD_NOP: + break; + + case CMD_SET_PAGE_ADDR_MODE: + case CMD_SET_VERTICAL_ADDR_MODE: + state->memory_mode = state->current_command[0]; + break; + + case CMD_SET_DISPLAY_CLOCK_DIV: + state->clock_divider = 1 + (state->current_command[1] & 0xf); + break; + + case CMD_SET_PRECHARGE: + state->phase1 = state->current_command[1] & 0xf; + state->phase2 = (state->current_command[1] >> 4) & 0xf; + break; + + case CMD_COM_SCAN_INC: + state->reverse_rows = false; + auto_update = true; + break; + + case CMD_COM_SCAN_DEC: + state->reverse_rows = true; + auto_update = true; + break; + + case CMD_SEG_REMAP_OFF: + state->segment_remap = false; + auto_update = true; + break; + + case CMD_SEG_REMAP_ON: + state->segment_remap = true; + auto_update = true; + break; + + case CMD_SET_DISP_START_LINE: + state->start_line = state->current_command[1]; + auto_update = true; + break; - const pin_watch_config_t config = { - .edge = BOTH, - .pin_change = chip_pin_change, + case CMD_SET_DISPLAY_OFFSET: + case CMD_SET_MULTIPLEX: + case CMD_SET_VCOM_DESELECT: + case CMD_SET_COM_PINS: + case CMD_DISPLAY_ALL_ON: + case CMD_DISPLAY_ALL_ON_RESUME: + // not implemented + break; + + default: + if (command_code <= 0x0f) + { + state->active_column = (state->active_column & 0x70) | command_code; + break; + } + + if (command_code >= 0x10 && command_code <= 0x17) + { + state->active_column = (state->active_column & 0x0f) | ((command_code & 0x07) << 4); + break; + } + + if (command_code >= 0xb0 && command_code <= 0xc0) + { + state->active_page = command_code & 0x0f; + auto_update = true; + break; + } + + printf("Unknown SH1107 Command %02x\n", command_code); + } + + if (auto_update && state->display_on) + { + sh1107_schedule_update(state); + } + + // Reset command buffer index, ready to read the next command + state->current_command_index = 0; +} + +static void sh1107_process_data(sh1107_state_t *state, uint8_t value) +{ + uint32_t column = !state->segment_remap ? state->active_column : state->width - 1 - state->active_column; + uint32_t target = state->active_page * state->width + column; + state->pixels[target] = value; + + // Memory modes are explained in pages 34-35 of the datasheet, + // and determine how the order of writing the pixels to the + // display RAM. + switch (state->memory_mode) + { + case CMD_SET_PAGE_ADDR_MODE: + state->active_column++; + if (state->active_column >= state->width) { + state->active_column = 0; + } + break; + + case CMD_SET_VERTICAL_ADDR_MODE: + default: + state->active_page++; + if (state->active_page >= 0x10) + { + state->active_page = 0; + state->active_column++; + if (state->active_column >= state->width) { + state->active_column = 0; + } + } + break; + } + sh1107_schedule_update(state); +} + +static bool sh1107_i2c_connect(void *user_data, uint32_t address, bool connect) +{ + sh1107_state_t *state = user_data; + state->control_byte = true; + return true; +} + +static uint8_t sh1107_i2c_read(void *user_data) +{ + return 0xff; // TODO +} + +static bool sh1107_i2c_write(void *user_data, uint8_t value) +{ + sh1107_state_t *state = user_data; + if (state->control_byte) + { + state->command_mode = !(value & SH1107_CONTROL_DC); + state->continuous_mode = !(value & SH1107_CONTROL_CO); + state->control_byte = false; + } + else + { + if (state->command_mode) + { + state->current_command[state->current_command_index] = value; + if (!state->current_command_index) + { + state->current_command_length = 1 + multi_byte_commands[value]; + } + state->current_command_index++; + if (state->current_command_index < state->current_command_length) + { + // Wait for the next command byte + return true; + } + sh1107_process_command(state); + } + else + { + sh1107_process_data(state, value); + } + if (!state->continuous_mode) + { + state->control_byte = true; + } + } + return true; +} + +void chip_init(void) +{ + sh1107_state_t *chip = malloc(sizeof(sh1107_state_t)); + + sh1107_reset(chip); + + const i2c_config_t i2c = { + .address = 0x3c, + .scl = pin_init("SCL", INPUT_PULLUP), + .sda = pin_init("SDA", INPUT_PULLUP), + .connect = sh1107_i2c_connect, + .read = sh1107_i2c_read, + .write = sh1107_i2c_write, + .user_data = chip, + }; + + i2c_init(&i2c); + + const timer_config_t update_timer_config = { + .callback = sh1107_update_buffer, .user_data = chip, }; - pin_watch(chip->pin_in, &config); + chip->update_timer = timer_init(&update_timer_config); + + chip->framebuffer = framebuffer_init(&chip->width, &chip->height); } diff --git a/src/wokwi-api.h b/src/wokwi-api.h index 01300a5..c6d88fe 100644 --- a/src/wokwi-api.h +++ b/src/wokwi-api.h @@ -53,10 +53,17 @@ extern __attribute__((import_name("pinMode"))) void pin_mode(pin_t pin, uint32_t extern __attribute__((import_name("pinADCRead"))) float pin_adc_read(pin_t pin); extern __attribute__((import_name("pinDACWrite"))) float pin_dac_write(pin_t pin, float voltage); +typedef uint32_t string_t; +#define STRING_NULL 0 + +extern __attribute__((import_name("stringGetLength"))) uint32_t string_get_length(string_t string); +extern __attribute__((import_name("stringRead"))) uint32_t string_read(string_t string, char *buf, uint32_t buffer_size); + extern __attribute__((import_name("attrInit"))) uint32_t attr_init(const char *name, uint32_t default_value); -extern __attribute__((import_name("attrInit"))) uint32_t attr_init_float(const char *name, float default_value); +extern __attribute__((import_name("attrInitFloat"))) uint32_t attr_init_float(const char *name, float default_value); extern __attribute__((import_name("attrRead"))) uint32_t attr_read(uint32_t attr_id); extern __attribute__((import_name("attrReadFloat"))) float attr_read_float(uint32_t attr_id); +extern __attribute__((import_name("attrStringInit"))) string_t attr_string_init(const char *name); typedef struct { void *user_data; @@ -128,8 +135,25 @@ static uint64_t get_sim_nanos(void) { typedef uint32_t buffer_t; extern __attribute__((import_name("framebufferInit"))) buffer_t framebuffer_init(uint32_t *pixel_width, uint32_t *pixel_height); -extern __attribute__((import_name("bufferRead"))) void buffer_read(buffer_t buffer, uint32_t offset, uint8_t *data, uint32_t data_len); -extern __attribute__((import_name("bufferWrite"))) void buffer_write(buffer_t buffer, uint32_t offset, uint8_t *data, uint32_t data_len); +extern __attribute__((import_name("bufferRead"))) void buffer_read(buffer_t buffer, uint32_t offset, void *data, uint32_t data_len); +extern __attribute__((import_name("bufferWrite"))) void buffer_write(buffer_t buffer, uint32_t offset, void *data, uint32_t data_len); + +// Experimental API - subject to change +extern __attribute__((import_name("_symbolResolve"))) void* _symbol_resolve(char *symbol_name); +extern __attribute__((import_name("_mcuReadMemory"))) bool _mcu_read_memory(const void *address, void *target, uint32_t size); +extern __attribute__((import_name("_mcuReadUint32"))) uint32_t _mcu_read_uint32(const void *address); +extern __attribute__((import_name("_mcuReadUint32"))) void* _mcu_read_ptr(const void *address); +extern __attribute__((import_name("_mcuReadPC"))) uint32_t _mcu_read_pc(); +extern __attribute__((import_name("_mcuReadSP"))) uint32_t _mcu_read_sp(); + +typedef struct { + void *user_data; + void (*callback)(void *user_data, uint32_t core, uint32_t sp); + uint32_t sp_min; + uint32_t sp_max; + uint32_t reserved[8]; +} sp_monitor_config_t; +extern __attribute__((import_name("_mcuMonitorSP"))) uint32_t _mcu_monitor_sp(const sp_monitor_config_t *config); #ifdef __cplusplus } diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index aeaebb2..0000000 --- a/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio \ No newline at end of file diff --git a/test/blink/blink.ino b/test/blink/blink.ino deleted file mode 100644 index 26655ba..0000000 --- a/test/blink/blink.ino +++ /dev/null @@ -1,13 +0,0 @@ -#define LED_PIN 2 - -void setup() { - Serial.begin(115200); - pinMode(LED_PIN, OUTPUT); -} - -void loop() { - digitalWrite(LED_PIN, HIGH); - delay(1000); - digitalWrite(LED_PIN, LOW); - delay(1000); -} diff --git a/test/blink/build/arduino.avr.uno/.gitignore b/test/blink/build/arduino.avr.uno/.gitignore deleted file mode 100644 index 74e3422..0000000 --- a/test/blink/build/arduino.avr.uno/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -blink.ino.eep -blink.ino.with_bootloader.* diff --git a/test/blink/build/arduino.avr.uno/blink.ino.elf b/test/blink/build/arduino.avr.uno/blink.ino.elf deleted file mode 100644 index 5439a344111103a2120c54facd7af8fbe7631c55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24132 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 OS%_a_4rLvdz5fe~jvRXc diff --git a/test/blink/build/arduino.avr.uno/blink.ino.hex b/test/blink/build/arduino.avr.uno/blink.ino.hex deleted file mode 100644 index df6e899..0000000 --- a/test/blink/build/arduino.avr.uno/blink.ino.hex +++ /dev/null @@ -1,122 +0,0 @@ -:100000000C945D000C9485000C9485000C94850084 -:100010000C9485000C9485000C9485000C9485004C -:100020000C9485000C9485000C9485000C9485003C -:100030000C9485000C9485000C9485000C9485002C -:100040000C9437020C9485000C94A7020C94810246 -:100050000C9485000C9485000C9485000C9485000C -:100060000C9485000C9485000000000024002700FB -:100070002A0000000000250028002B0004040404CE -:100080000404040402020202020203030303030342 -:10009000010204081020408001020408102001021F -:1000A00004081020000000080002010000030407FB -:1000B0000000000000000000810311241FBECFEFEC -:1000C000D8E0DEBFCDBF11E0A0E0B1E0ECE6F7E0A4 -:1000D00002C005900D92A231B107D9F721E0A2E14B -:1000E000B1E001C01D92A83BB207E1F710E0CDE5F9 -:1000F000D0E004C02197FE010E94AE03CC35D107A9 -:10010000C9F70E94D9020C94B4030C940000E6EAEB -:10011000F0E02491E2E9F0E09491EEE7F0E0E49180 -:10012000EE23C9F0222339F0233001F1A8F4213065 -:1001300019F1223029F1F0E0EE0FFF1FEE58FF4FCA -:10014000A591B4912FB7F894EC91811126C09095A8 -:100150009E239C932FBF08952730A9F02830C9F023 -:10016000243049F7209180002F7D03C0209180002A -:100170002F7720938000DFCF24B52F7724BDDBCFEE -:1001800024B52F7DFBCF2091B0002F772093B000B6 -:10019000D2CF2091B0002F7DF9CF9E2BDACF3FB781 -:1001A000F8948091B4019091B501A091B601B091FD -:1001B000B70126B5A89B05C02F3F19F00196A11DD8 -:1001C000B11D3FBFBA2FA92F982F8827BC01CD01A1 -:1001D000620F711D811D911D42E0660F771F881F00 -:1001E000991F4A95D1F708958F929F92AF92BF922F -:1001F000CF92DF92EF92FF920E94CF004B015C0101 -:1002000088EEC82E83E0D82EE12CF12C0E94CF007E -:10021000681979098A099B09683E7340810591052F -:10022000A8F321E0C21AD108E108F10888EE880E8F -:1002300083E0981EA11CB11CC114D104E104F10497 -:1002400029F7FF90EF90DF90CF90BF90AF909F90F5 -:100250008F900895AF92BF92CF92DF92EF92FF926C -:100260000F931F93CF93DF936C017B018B01040FDE -:10027000151FEB015E01AE18BF08C017D10759F07A -:100280006991D601ED91FC910190F081E02DC601BC -:100290000995892B79F7C501DF91CF911F910F91B6 -:1002A000FF90EF90DF90CF90BF90AF900895FC014A -:1002B000538D448D252F30E0842F90E0821B930BCB -:1002C000541710F0CF96089501970895FC01918D71 -:1002D000828D981761F0A28DAE0FBF2FB11D5D9674 -:1002E0008C91928D9F5F9F73928F90E008958FEF16 -:1002F0009FEF0895FC01918D828D981731F0828DCA -:10030000E80FF11D858D90E008958FEF9FEF089520 -:10031000FC01918D228D892F90E0805C9F4F821B84 -:1003200091098F739927089582E191E00E948801D5 -:1003300021E0892B09F420E0822F089580E090E0ED -:10034000892B29F00E94940181110C9400000895DA -:10035000FC01A48DA80FB92FB11DA35ABF4F2C913A -:10036000848D90E001968F739927848FA689B78931 -:100370002C93A089B1898C91837080648C93938D28 -:10038000848D981306C00288F389E02D80818F7DCB -:1003900080830895EF92FF920F931F93CF93DF9383 -:1003A000EC0181E0888F9B8D8C8D98131AC0E889B1 -:1003B000F989808185FF15C09FB7F894EE89FF8980 -:1003C0006083E889F98980818370806480839FBF1E -:1003D00081E090E0DF91CF911F910F91FF90EF901E -:1003E0000895F62E0B8D10E00F5F1F4F0F7311272E -:1003F000E02E8C8D8E110CC00FB607FCFACFE88969 -:10040000F989808185FFF5CFCE010E94A801F1CF47 -:10041000EB8DEC0FFD2FF11DE35AFF4FF0829FB7DC -:10042000F8940B8FEA89FB8980818062CFCFCF93CC -:10043000DF93EC01888D8823B9F0AA89BB89E8890C -:10044000F9898C9185FD03C0808186FD0DC00FB6B2 -:1004500007FCF7CF8C9185FFF2CF808185FFEDCF30 -:10046000CE010E94A801E9CFDF91CF9108951F929C -:100470000F920FB60F9211242F933F938F939F9358 -:10048000AF93BF938091B0019091B101A091B2015F -:10049000B091B3013091AF0123E0230F2D3758F510 -:1004A0000196A11DB11D2093AF018093B0019093DF -:1004B000B101A093B201B093B3018091B4019091C6 -:1004C000B501A091B601B091B7010196A11DB11D72 -:1004D0008093B4019093B501A093B601B093B70196 -:1004E000BF91AF919F918F913F912F910F900FBE30 -:1004F0000F901F90189526E8230F0296A11DB11D9D -:10050000D2CF1F920F920FB60F9211242F933F93C9 -:100510004F935F936F937F938F939F93AF93BF930B -:10052000EF93FF9382E191E00E94A801FF91EF9188 -:10053000BF91AF919F918F917F916F915F914F91FB -:100540003F912F910F900FBE0F901F9018951F9203 -:100550000F920FB60F9211242F938F939F93EF93C7 -:10056000FF93E0912201F09123018081E091280125 -:10057000F091290182FD1BC0908180912B018F5F3A -:100580008F7320912C01821741F0E0912B01F0E054 -:10059000EE5EFE4F958F80932B01FF91EF919F911F -:1005A0008F912F910F900FBE0F901F901895808103 -:1005B000F4CF789484B5826084BD84B5816084BDB5 -:1005C00085B5826085BD85B5816085BD80916E00F1 -:1005D000816080936E001092810080918100826022 -:1005E000809381008091810081608093810080915F -:1005F00080008160809380008091B100846080934E -:10060000B1008091B00081608093B00080917A0049 -:10061000846080937A0080917A00826080937A006F -:1006200080917A00816080937A0080917A0080685E -:1006300080937A001092C100E0912201F091230191 -:1006400082E08083E0911E01F0911F011082E09111 -:100650002001F091210180E1808310922A01E09134 -:100660002601F091270186E08083E0912401F0913A -:100670002501808180618083E0912401F091250132 -:10068000808188608083E0912401F0912501808140 -:1006900080688083E0912401F091250180818F7D25 -:1006A0008083E2E9F0E02491EEE7F0E08491882392 -:1006B00099F090E0880F991FFC01E859FF4FA59130 -:1006C000B491FC01EE58FF4F859194918FB7F89447 -:1006D000EC91E22BEC938FBFC0E0D0E081E00E9470 -:1006E00087000E94F40080E00E9487000E94F400CE -:1006F0002097A1F30E949401882381F30E940000B7 -:10070000EDCFE2E1F1E01382128288EE93E0A0E007 -:10071000B0E084839583A683B78384E091E09183DE -:10072000808385EC90E09587848784EC90E09787C0 -:10073000868780EC90E0918B808B81EC90E0938BAE -:10074000828B82EC90E0958B848B86EC90E0978B8B -:10075000868B118E128E138E148E0895EE0FFF1F4E -:0C0760000590F491E02D0994F894FFCF6F -:10076C0000000000CA012A01570117028801660126 -:02077C007A0100 -:00000001FF diff --git a/wokwi.toml b/wokwi.toml deleted file mode 100644 index e1febb6..0000000 --- a/wokwi.toml +++ /dev/null @@ -1,8 +0,0 @@ -[wokwi] -version = 1 -elf = 'test/blink/build/arduino.avr.uno/blink.ino.elf' -firmware = 'test/blink/build/arduino.avr.uno/blink.ino.hex' - -[[chip]] -name = 'inverter' -binary = 'dist/chip.wasm'