Skip to content

Commit

Permalink
HAL and demos for verifying hardware subsystems
Browse files Browse the repository at this point in the history
  • Loading branch information
mattnite committed Apr 3, 2024
1 parent cb19297 commit 592e429
Show file tree
Hide file tree
Showing 26 changed files with 3,056 additions and 25 deletions.
91 changes: 66 additions & 25 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,74 @@ pub const py_badge: MicroZig.Target = .{
.hal = null,
};

pub const sycl_badge_2024 = MicroZig.Target{
.preferred_format = .elf,
.chip = atsam.chips.atsamd51j19.chip,
.hal = .{
.root_source_file = .{ .cwd_relative = "src/hal.zig" },
},
.board = .{
.name = "SYCL Badge 2024",
.root_source_file = .{ .cwd_relative = "src/board.zig" },
},
};

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);

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| {
if (memory_region.kind != .ram) continue;
memory_region.offset += 0x19A0;
memory_region.length -= 0x19A0;
break;
}
var modified_py_badge = py_badge;
modified_py_badge.chip.memory_regions = modified_memory_regions;
//const fw_options = b.addOptions();
//fw_options.addOption(bool, "have_cart", false);

const fw = mz.add_firmware(b, .{
.name = "pybadge-io",
.target = modified_py_badge,
//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| {
// if (memory_region.kind != .ram) continue;
// memory_region.offset += 0x19A0;
// memory_region.length -= 0x19A0;
// break;
//}
//var modified_py_badge = py_badge;
//modified_py_badge.chip.memory_regions = modified_memory_regions;

//const fw = mz.add_firmware(b, .{
// .name = "pybadge-io",
// .target = modified_py_badge,
// .optimize = optimize,
// .source_file = .{ .path = "src/main.zig" },
//});
//fw.artifact.step.dependOn(&fw_options.step);
//fw.modules.app.addImport("options", fw_options.createModule());x
//mz.install_firmware(b, fw, .{});
//mz.install_firmware(b, fw, .{ .format = .{ .uf2 = .SAMD51 } });

const badge = mz.add_firmware(b, .{
.name = "badge",
.target = sycl_badge_2024,
.optimize = optimize,
.source_file = .{ .path = "src/main.zig" },
.root_source_file = .{ .path = "src/badge.zig" },
});
fw.artifact.step.dependOn(&fw_options.step);
fw.modules.app.addImport("options", fw_options.createModule());
mz.install_firmware(b, fw, .{});
mz.install_firmware(b, fw, .{ .format = .{ .uf2 = .SAMD51 } });
mz.install_firmware(b, badge, .{});

inline for (.{
"blinky",
"blinky_timer",
"usb_cdc",
"usb_storage",
"buttons",
"lcd",
"audio",
"light_sensor",
"neopixels",
"qspi",
}) |name| {
const mvp = mz.add_firmware(b, .{
.name = std.fmt.comptimePrint("badge.demo.{s}", .{name}),
.target = sycl_badge_2024,
.optimize = optimize,
.root_source_file = .{ .path = std.fmt.comptimePrint("src/badge/demos/{s}.zig", .{name}) },
});
mz.install_firmware(b, mvp, .{});
}
}

pub const Cart = struct {
Expand All @@ -47,7 +88,7 @@ pub const Cart = struct {
pub const CartOptions = struct {
name: []const u8,
optimize: std.builtin.OptimizeMode,
source_file: Build.LazyPath,
root_source_file: Build.LazyPath,
};

pub fn add_cart(
Expand All @@ -57,15 +98,15 @@ pub fn add_cart(
) *Cart {
const cart_lib = b.addStaticLibrary(.{
.name = "cart",
.root_source_file = options.source_file,
.root_source_file = options.root_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.builder.createModule(.{ .source_file = .{ .path = "src/wasm4.zig" } }));
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);
Expand All @@ -75,8 +116,8 @@ pub fn add_cart(
.name = options.name,
.target = py_badge,
.optimize = .Debug, // TODO
.source_file = .{ .path = "src/main.zig" },
.linker_script = .{ .source_file = .{ .path = "src/cart.ld" } },
.root_source_file = .{ .path = "src/main.zig" },
.linker_script = .{ .root_source_file = .{ .path = "src/cart.ld" } },
});
fw.artifact.linkLibrary(cart_lib);
fw.artifact.step.dependOn(&fw_options.step);
Expand Down
55 changes: 55 additions & 0 deletions src/badge.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! This is firmware for the SYCL badge.
//!
//! The badge image
//! For normal operation, the default app will run. Pressing select will go to
//! the main menu. The default app will display the SYCL logo, users will be
//! able to change the default app.
//!
//! Apps will have the option to to save state to non-volatile memory. This
//! will prompt the user. The user will either exit without saving, save and
//! exit, or cancel.
//!
//! TODO:
//! - USB mass drive
//! - USB CDC logging
const std = @import("std");

const microzig = @import("microzig");
const board = microzig.board;
const hal = microzig.hal;
const usb = hal.usb;

const peripherals = microzig.chip.peripherals;
const MCLK = peripherals.MCLK;

const led_pin = board.D13;
const backlight = board.TFT_LITE;
const @"D+" = board.@"D+";
const @"D-" = board.@"D-";

pub fn main() !void {
// Initialize clocks
MCLK.AHBMASK.modify(.{ .USB_ = 1 });
MCLK.APBBMASK.modify(.{ .USB_ = 1 });

// Initialize pins
led_pin.set_dir(.out);
backlight.set_dir(.out);
@"D+".set_mux(.H);
@"D-".set_mux(.H);

backlight.write(.low);

const period = 200000;
while (true) {
delay_count(period);
led_pin.write(.high);
delay_count(period);
led_pin.write(.low);
}
}

fn delay_count(count: u32) void {
var i: u32 = 0;
while (i < count) : (i += 1) {}
}
35 changes: 35 additions & 0 deletions src/badge/demos/audio.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const std = @import("std");
const microzig = @import("microzig");
const hal = microzig.hal;
const gclk = hal.gclk;
const timer = hal.timer;

const spkr_en_pin = microzig.board.SPKR_EN;
const analog_out_pin = microzig.board.A0;
const led_pin = microzig.board.D13;

pub fn main() !void {
spkr_en_pin.set_dir(.out);
analog_out_pin.set_dir(.out);
led_pin.set_dir(.out);

analog_out_pin.write(.low);
spkr_en_pin.write(.high);

gclk.enable_generator(.GCLK1, .DFLL, .{
.divsel = .DIV1,
.div = 48,
});

timer.init();
while (true) {
led_pin.toggle();
analog_out_pin.toggle();
timer.delay_us(std.time.us_per_ms);
}
}

fn delay_count(count: u32) void {
var i: u32 = 0;
while (i < count) : (i += 1) {}
}
21 changes: 21 additions & 0 deletions src/badge/demos/blinky.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const microzig = @import("microzig");

const led_pin = microzig.board.D13;

pub fn main() !void {
// Initialize pins
led_pin.set_dir(.out);

const period = 200000;
while (true) {
delay_count(period);
led_pin.write(.high);
delay_count(period);
led_pin.write(.low);
}
}

fn delay_count(count: u32) void {
var i: u32 = 0;
while (i < count) : (i += 1) {}
}
23 changes: 23 additions & 0 deletions src/badge/demos/blinky_timer.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const std = @import("std");
const microzig = @import("microzig");
const hal = microzig.hal;
const timer = hal.timer;
const gclk = hal.gclk;

const led_pin = microzig.board.D13;

pub fn main() !void {
// Initialize pins
led_pin.set_dir(.out);

gclk.enable_generator(.GCLK1, .DFLL, .{
.divsel = .DIV1,
.div = 48,
});

timer.init();
while (true) {
led_pin.toggle();
timer.delay_us(1 * std.time.us_per_s);
}
}
98 changes: 98 additions & 0 deletions src/badge/demos/buttons.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const std = @import("std");
const microzig = @import("microzig");
const board = microzig.board;

// pins
const Buttons = board.Buttons;
const led_pin = board.D13;

const Symbol = enum {
dot,
dash,

fn blink(symbol: Symbol, pin: microzig.hal.port.Pin) void {
pin.write(.high);
delay_count(switch (symbol) {
.dot => unit_period_count,
.dash => 3 * unit_period_count,
});
pin.write(.low);
delay_count(unit_period_count);
}
};

const unit_period_count = 200000;

const Mapping = struct {
character: u8,
symbols: []const Symbol,
};

const alphabet = [_]Mapping{
.{ .character = 'a', .symbols = &.{ .dot, .dash } }, // A: .-
.{ .character = 'b', .symbols = &.{ .dash, .dot, .dot, .dot } }, // B: -...
.{ .character = 'c', .symbols = &.{ .dash, .dot, .dash, .dot } }, // C: -.-.
.{ .character = 'd', .symbols = &.{ .dash, .dot, .dot } }, // D: -..
.{ .character = 'e', .symbols = &.{.dot} }, // E: .
.{ .character = 'f', .symbols = &.{ .dot, .dot, .dash, .dot } }, // F: ..-.
.{ .character = 'g', .symbols = &.{ .dash, .dash, .dot } }, // G: --.
.{ .character = 'h', .symbols = &.{ .dot, .dot, .dot, .dot } }, // H: ....
.{ .character = 'i', .symbols = &.{ .dot, .dot } }, // I: ..
.{ .character = 'j', .symbols = &.{ .dot, .dash, .dash, .dash } }, // J: .---
.{ .character = 'k', .symbols = &.{ .dash, .dot, .dash } }, // K: -.-
.{ .character = 'l', .symbols = &.{ .dot, .dash, .dot, .dot } }, // L: .-..
.{ .character = 'm', .symbols = &.{ .dash, .dash } }, // M: --
.{ .character = 'n', .symbols = &.{ .dash, .dot } }, // N: -.
.{ .character = 'o', .symbols = &.{ .dash, .dash, .dash } }, // O: ---
.{ .character = 'p', .symbols = &.{ .dot, .dash, .dash, .dot } }, // P: .--.
.{ .character = 'q', .symbols = &.{ .dash, .dash, .dot, .dash } }, // Q: --.-
.{ .character = 'r', .symbols = &.{ .dot, .dash, .dot } }, // R: .-.
.{ .character = 's', .symbols = &.{ .dot, .dot, .dot } }, // S: ...
.{ .character = 't', .symbols = &.{.dash} }, // T: -
.{ .character = 'u', .symbols = &.{ .dot, .dot, .dash } }, // U: ..-
.{ .character = 'v', .symbols = &.{ .dot, .dot, .dot, .dash } }, // V: ...-
.{ .character = 'w', .symbols = &.{ .dot, .dash, .dash } }, // W: .--
.{ .character = 'x', .symbols = &.{ .dash, .dot, .dot, .dash } }, // X: -..-
.{ .character = 'y', .symbols = &.{ .dash, .dot, .dash, .dash } }, // Y: -.--
.{ .character = 'z', .symbols = &.{ .dash, .dash, .dot, .dot } }, // Z: --..
};

fn get_symbols(character: u8) []const Symbol {
return for (alphabet) |entry| {
if (entry.character == character)
break entry.symbols;
} else unreachable;
}

pub fn main() !void {
Buttons.configure();
// Use morse code to convey which button is currently pressed
led_pin.set_dir(.out);

while (true) {
const message: []const u8 = blk: {
const buttons = Buttons.read_from_port();
inline for (@typeInfo(Buttons).Struct.fields) |field| {
if (@field(buttons, field.name) == 1)
break :blk field.name;
}

continue;
};

for (message) |character| {
const symbols = get_symbols(character);
for (symbols) |symbol| symbol.blink(led_pin);

// there's supposed to be 3, but we already wait one period after every symbol
delay_count(2 * unit_period_count);
}

delay_count(5 * unit_period_count);
}
}

fn delay_count(count: u32) void {
var i: u32 = 0;
while (i < count) : (i += 1) {}
}
Loading

0 comments on commit 592e429

Please sign in to comment.