Skip to content

Commit

Permalink
First iteration of badge sim (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperAuguste authored Apr 10, 2024
1 parent 592e429 commit c6a68f9
Show file tree
Hide file tree
Showing 41 changed files with 11,782 additions and 206 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/publish-simulator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Publish Simulator
on:
push:
branches: [main]
paths:
- simulator/**

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Use Node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x

- name: Build simulator
run: |
cd simulator
npm run build
touch dist/.nojekyll
- name: Upload Artifacts
uses: actions/upload-pages-artifact@v1
with:
# this should match the `pages` option in your adapter-static options
path: "dist/"

deploy:
needs: build
runs-on: ubuntu-latest

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Deploy
id: deployment
uses: actions/deploy-pages@v1
114 changes: 88 additions & 26 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,20 @@ pub const sycl_badge_2024 = MicroZig.Target{

pub fn build(b: *Build) void {
const mz = MicroZig.init(b, .{});

const optimize = b.standardOptimizeOption(.{});

//const fw_options = b.addOptions();
//fw_options.addOption(bool, "have_cart", false);
_ = b.addModule("wasm4", .{ .root_source_file = .{ .path = "src/wasm4.zig" } });

var dep: std.Build.Dependency = .{ .builder = b };
const cart = add_cart(&dep, b, .{
.name = "sample",
.optimize = optimize,
.root_source_file = .{ .path = "samples/feature_test.zig" },
});

const watch_step = b.step("watch", "");
watch_step.dependOn(&cart.watch_run_cmd.step);

//const modified_memory_regions = b.allocator.dupe(MicroZig.MemoryRegion, py_badge.chip.memory_regions) catch @panic("out of memory");
//for (modified_memory_regions) |*memory_region| {
Expand Down Expand Up @@ -81,8 +91,10 @@ pub fn build(b: *Build) void {
}

pub const Cart = struct {
mz: *MicroZig,
fw: *MicroZig.Firmware,
// mz: *MicroZig,
// fw: *MicroZig.Firmware,

watch_run_cmd: *std.Build.Step.Run,
};

pub const CartOptions = struct {
Expand All @@ -96,36 +108,86 @@ pub fn add_cart(
b: *Build,
options: CartOptions,
) *Cart {
const cart_lib = b.addStaticLibrary(.{
const lib = b.addExecutable(.{
.name = "cart",
.root_source_file = options.root_source_file,
.target = py_badge.chip.cpu.getDescriptor().target,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.os_tag = .freestanding,
}),
.optimize = options.optimize,
.link_libc = false,
.single_threaded = true,
.use_llvm = true,
.use_lld = true,
});
cart_lib.addModule("wasm4", d.builder.createModule(.{ .root_source_file = .{ .path = "src/wasm4.zig" } }));

const fw_options = b.addOptions();
fw_options.addOption(bool, "have_cart", true);

const mz = MicroZig.init(d.builder, "microzig");
const fw = mz.addFirmware(d.builder, .{
.name = options.name,
.target = py_badge,
.optimize = .Debug, // TODO
.root_source_file = .{ .path = "src/main.zig" },
.linker_script = .{ .root_source_file = .{ .path = "src/cart.ld" } },
b.installArtifact(lib);

lib.entry = .disabled;
lib.import_memory = true;
lib.initial_memory = 65536;
lib.max_memory = 65536;
lib.stack_size = 14752;
lib.global_base = 160 * 128 * 2 + 0x1e;

lib.rdynamic = true;

lib.root_module.addImport("wasm4", d.module("wasm4"));

const watch = d.builder.addExecutable(.{
.name = "watch",
.root_source_file = .{ .path = "src/watch/main.zig" },
.target = b.resolveTargetQuery(.{}),
.optimize = options.optimize,
});
watch.root_module.addImport("ws", d.builder.dependency("ws", .{}).module("websocket"));
watch.root_module.addImport("mime", d.builder.dependency("mime", .{}).module("mime"));

const watch_run_cmd = b.addRunArtifact(watch);
watch_run_cmd.step.dependOn(b.getInstallStep());

watch_run_cmd.addArgs(&.{
"serve",
b.graph.zig_exe,
"--zig-out-bin-dir",
b.pathJoin(&.{ b.install_path, "bin" }),
"--input-dir",
options.root_source_file.dirname().getPath(b),
});
fw.artifact.linkLibrary(cart_lib);
fw.artifact.step.dependOn(&fw_options.step);
fw.modules.app.dependencies.put("options", fw_options.createModule()) catch @panic("out of memory");

const cart: *Cart = b.allocator.create(Cart) catch @panic("out of memory");
cart.* = .{ .mz = mz, .fw = fw };
cart.* = .{
.watch_run_cmd = watch_run_cmd,
};
return cart;

// const cart_lib = b.addStaticLibrary(.{
// .name = "cart",
// .root_source_file = options.source_file,
// .target = py_badge.chip.cpu.getDescriptor().target,
// .optimize = options.optimize,
// .link_libc = false,
// .single_threaded = true,
// .use_llvm = true,
// .use_lld = true,
// });
// cart_lib.addModule("wasm4", d.module("wasm4"));

// const fw_options = b.addOptions();
// fw_options.addOption(bool, "have_cart", true);

// const mz = MicroZig.init(d.builder, "microzig");

// const fw = mz.addFirmware(d.builder, .{
// .name = options.name,
// .target = py_badge,
// .optimize = .Debug, // TODO
// .source_file = .{ .path = "src/main.zig" },
// .linker_script = .{ .source_file = .{ .path = "src/cart.ld" } },
// });
// fw.artifact.linkLibrary(cart_lib);
// fw.artifact.step.dependOn(&fw_options.step);
// fw.modules.app.dependencies.put("options", fw_options.createModule()) catch @panic("out of memory");

// const cart: *Cart = b.allocator.create(Cart) catch @panic("out of memory");
// cart.* = .{ .mz = mz, .fw = fw };
// return cart;
}

pub fn install_cart(b: *Build, cart: *Cart) void {
Expand Down
8 changes: 8 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,13 @@
.@"microzig/bsp/microchip/atsam" = .{
.path = "../microzig/bsp/microchip/atsam",
},
.mime = .{
.url = "git+https://github.com/andrewrk/mime.git#bf80e2e8b1d9413ddf9abe7d94537388b54c83ab",
.hash = "122074ce2f776dc9dc4a0d2588a5d76b97212a2c311ef8125d4aadffa4b84e5b8b3e",
},
.ws = .{
.url = "git+https://github.com/karlseguin/websocket.zig.git#1f2c4a56c642dab52fe12cdda1bd3f56865d1f86",
.hash = "1220ce168e550f8904364acd0a72f5cafd40caa08a50ba83aac50b97ba700d7bcf20",
},
},
}
91 changes: 91 additions & 0 deletions samples/feature_test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const std = @import("std");
const wasm4 = @import("wasm4");

export fn start() void {}

var green_565: u6 = 0;

var offset: u16 = 0;

fn read_stored_number() u64 {
var dst: u64 = undefined;
std.debug.assert(wasm4.read_flash(0, std.mem.asBytes(&dst)) == @sizeOf(u64));
return dst;
}

fn write_stored_number(number: u64) void {
var page: [wasm4.flash_page_size]u8 = undefined;
// @as(*u64, @alignCast(@ptrCast(page[0..8]))).* = number;
std.mem.bytesAsSlice(u64, &page)[0] = number;
wasm4.write_flash_page(0, page);
}

export fn update() void {
if (offset % (60 * 2) == 0) {
wasm4.tone(440, 20, 10, .{
.channel = .pulse1,
.duty_cycle = .@"1/8",
.panning = .left,
});
}

offset +%= 1;

var inputs_buf: [128]u8 = undefined;
var fbs = std.io.fixedBufferStream(&inputs_buf);

fbs.writer().print("{d}\n", .{read_stored_number()}) catch unreachable;

inline for (std.meta.fields(wasm4.Controls)) |control| {
if (comptime !std.mem.eql(u8, control.name, "padding")) {
if (@field(wasm4.controls.*, control.name)) {
fbs.writer().writeAll(control.name) catch unreachable;
fbs.writer().writeAll("\n") catch unreachable;
}
}
}

if (wasm4.controls.up) {
green_565 +%= 1;
} else if (wasm4.controls.down) {
green_565 -%= 1;
}

if (wasm4.controls.left) {
write_stored_number(read_stored_number() -| 1);
} else if (wasm4.controls.right) {
write_stored_number(read_stored_number() +| 1);
}

wasm4.red_led.* = wasm4.controls.click;

for (0..wasm4.screen_height) |y| {
for (0..wasm4.screen_width) |x| {
wasm4.framebuffer[y * wasm4.screen_width + x] = .{
.red = @intFromFloat(@as(f32, @floatFromInt(x)) / wasm4.screen_width * 31),
.green = green_565,
.blue = @intFromFloat(@as(f32, @floatFromInt(y)) / wasm4.screen_height * 31),
};
}
}

for (wasm4.neopixels, 0..) |*np, i| {
np.* = .{
.red = @intFromFloat(@as(f32, @floatFromInt(i)) / 5 * 255),
.green = @intFromFloat(@as(f32, @floatFromInt(wasm4.light_level.*)) / std.math.maxInt(u12) * 255),
.blue = @intFromFloat(@as(f32, @floatFromInt(i)) / 5 * 255),
};
}

// TODO: blit, blitSub

wasm4.line(.{ .red = 0, .green = 63, .blue = 0 }, 50, 50, 70, 70);

wasm4.hline(.{ .red = 31, .green = 0, .blue = 0 }, 30, 30, 20);
wasm4.vline(.{ .red = 31, .green = 0, .blue = 0 }, 30, 30, 20);

wasm4.oval(.{ .red = 0, .green = 0, .blue = 31 }, .{ .red = 31, .green = 0, .blue = 31 }, 80, 80, 10, 10);
wasm4.rect(.{ .red = 31, .green = 31, .blue = 31 }, .{ .red = 0, .green = 63, .blue = 31 }, 100, 100, 10, 10);

wasm4.text(.{ .red = 0, .green = 0, .blue = 0 }, .{ .red = 31, .green = 63, .blue = 31 }, fbs.getWritten(), 0, 0);
}
11 changes: 11 additions & 0 deletions simulator/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
]
}
1 change: 1 addition & 0 deletions simulator/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.nelua text linguist-language=lua
5 changes: 5 additions & 0 deletions simulator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/dist
public/cart.wasm
src/**/*.generated.js
/.parcel-cache
node_modules
3 changes: 3 additions & 0 deletions simulator/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Adapted from https://github.com/aduros/wasm4.

See `LICENSE-WASM4` and `LICENSE-BADGE`.
21 changes: 21 additions & 0 deletions simulator/LICENSE-BADGE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) Auguste Rame

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
13 changes: 13 additions & 0 deletions simulator/LICENSE-WASM4
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) Bruno Garcia

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
27 changes: 27 additions & 0 deletions simulator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SYCL 2024 Badge Simulator

Simulate your badge on the interwebz.

## Controls

- Escape: open menu
- WASD/Arrow Keys + Shift: 4 direction pad + click
- Space: start
- Enter: select

## Supported Hardware Components

- [x] Light Sensor
- [x] 160x128 RGB screen
- [x] 5x RGB LEDs
- [x] 1x Red LED on the back
- [x] Speaker
- [x] Start/Option buttons
- [x] A/B buttons
- [x] A navstick with up/down/left/right. Unsure up/left will both be activated on diagonal
- [x] Navstick is pressable too
- [x] 2MB flash separate from the microcontroller's flash

## Additional Features

- [ ] Live reload
Binary file added simulator/assets/font.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c6a68f9

Please sign in to comment.