Skip to content

Commit

Permalink
No sound on harwdare yet
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperAuguste committed May 20, 2024
1 parent d3c7cb2 commit dc010af
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 121 deletions.
6 changes: 3 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ pub fn build(b: *Build) void {
}

inline for (.{
"neopixels",
"song",
// "neopixels",
// "song",
}) |name| {
const mvp = add_cart(&dep, b, .{
.name = std.fmt.comptimePrint("badge.demo.{s}", .{name}),
Expand Down Expand Up @@ -144,7 +144,7 @@ pub const Cart = struct {

pub fn install_with_watcher(c: *const Cart, d: *Build.Dependency, b: *Build, opt: CartWatcherOptions) *Build.Step.Run {
if (opt.build_firmware) {
// c.mz.install_firmware(b, c.fw, .{ .format = .{ .uf2 = .SAMD51 } });
c.mz.install_firmware(b, c.fw, .{ .format = .{ .uf2 = .SAMD51 } });
}
const install_artifact_step = b.addInstallArtifact(c.wasm, .{});
b.getInstallStep().dependOn(&install_artifact_step.step);
Expand Down
3 changes: 3 additions & 0 deletions simulator/src/apu-worklet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class APUProcessor extends AudioWorkletProcessor {
if (this.port != null) {
this.port.onmessage = (event: MessageEvent<"reset" | {left: number[], right: number[]}>) => {
if (event.data === "reset") {
console.log("Reset");
this.samplesLeft = [];
this.samplesRight = [];
} else {
Expand All @@ -33,6 +34,8 @@ class APUProcessor extends AudioWorkletProcessor {
outputRight[index] = pcmRight[index] / 32767;
}

console.log(pcmLeft.length);

return true;
}
}
Expand Down
19 changes: 10 additions & 9 deletions simulator/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,16 @@ export class Runtime {

// TODO: should this be called via a message from the worklet maybe?
let audio_function = this.wasm!.exports["audio"] as any;
// if (typeof audio_function === "function") {
// this.bluescreenOnError(audio_function);
// }

if (audio_function(constants.ADDR_AUDIO_BUFFER)) {
this.apu.send(
[...new Int16Array(this.memory.buffer.slice(constants.ADDR_AUDIO_BUFFER)).slice(0, 512)],
[...new Int16Array(this.memory.buffer.slice(constants.ADDR_AUDIO_BUFFER + 512 * 2)).slice(0, 512)],
);

if (typeof update_function === "function") {
// this is terrible
for (let i = 0; i < 2; i++) {
this.bluescreenOnError(audio_function);
this.apu.send(
[...new Int16Array(this.memory.buffer.slice(constants.ADDR_AUDIO_BUFFER)).slice(0, 512)],
[...new Int16Array(this.memory.buffer.slice(constants.ADDR_AUDIO_BUFFER + 512 * 2)).slice(0, 512)],
);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/badge.zig
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub fn main() !void {
});

timer.init();
audio.init();
audio.init(&cart.call_audio);

// Light sensor adc
microzig.board.A6_LIGHT.set_mux(.B);
Expand Down
8 changes: 7 additions & 1 deletion src/badge/cart.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const libcart = struct {

extern fn start() void;
extern fn update() void;
extern fn audio() void;

export fn __return_thunk__() linksection(".text.cart") noreturn {
asm volatile (" svc #12");
unreachable;
Expand Down Expand Up @@ -123,7 +125,7 @@ pub const HSRAM = struct {
};

pub fn start() void {
@memset(@as(*[0xA020]u8, @ptrFromInt(0x20000000)), 0);
@memset(@as(*[0xA820]u8, @ptrFromInt(0x20000000)), 0);

// fill .bss with zeroes
{
Expand Down Expand Up @@ -188,6 +190,10 @@ fn call(func: *const fn () callconv(.C) void) void {
});
}

pub fn call_audio() void {
call(libcart.audio);
}

fn User(comptime T: type) type {
return extern struct {
const Self = @This();
Expand Down
18 changes: 8 additions & 10 deletions src/badge/feature_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,15 @@ export fn update() void {
});
}

const raw_data = std.mem.bytesAsSlice(i16, @embedFile("pepsi.raw"));
var wave_t: f32 = 0;

var audio_offset: usize = 0;
export fn audio() void {
for (&cart.audio_buffer[0], &cart.audio_buffer[1]) |*l, *r| {
const val: i16 = @intFromFloat(@sin(wave_t) * std.math.maxInt(i16));

export fn audio(buffer: *volatile [2][512]i16) bool {
if (audio_offset >= raw_data.len) return false;
l.* = val;
r.* = val;

@memcpy(&buffer[0], raw_data[audio_offset..][0..512]);
@memcpy(&buffer[1], raw_data[audio_offset..][0..512]);

audio_offset += 512;

return true;
wave_t += 0.1;
}
}
106 changes: 9 additions & 97 deletions src/board/audio.zig
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
pub const sample_buffer: *volatile [2][512]u16 = &sample_buffer_storage;
pub const sample_buffer: *volatile [2][512]i16 = @ptrFromInt(0x20000000 + 0xa020);
var call_audio: *const fn () void = undefined;

pub const Channel = struct {
duty: u32,
phase: u32,
phase_step: u31,
phase_step_step: i32,

duration: u31,
attack_duration: u31,
decay_duration: u31,
sustain_duration: u31,
release_duration: u31,

volume: u31,
volume_step: i32,
peak_volume: u31,
sustain_volume: u31,
attack_volume_step: i32,
decay_volume_step: i32,
release_volume_step: i32,
};

pub fn init() void {
pub fn init(call_audio_fn: *const fn () void) void {
@setCold(true);
call_audio = call_audio_fn;

board.A0_SPKR.set_dir(.out);
board.A1_VCC.set_dir(.in);
Expand Down Expand Up @@ -204,89 +185,20 @@ pub fn init() void {
}

pub fn mix() callconv(.C) void {
var local_channels = channels.*;
var speaker_enable: port.Level = .low;

call_audio();

for (&sample_buffer[
(dma.get_audio_part() + sample_buffer.len - 1) % sample_buffer.len
]) |*out_sample| {
var sample: i32 = 0;
inline for (&local_channels) |*channel| {
if (channel.duty > 0) {
// generate sample;
if (channel.phase < channel.duty) {
sample += channel.volume;
} else {
sample -= channel.volume;
}
// update
channel.phase +%= channel.phase_step;
channel.phase_step = @intCast(channel.phase_step + channel.phase_step_step);
if (channel.duration > 0) {
channel.duration -= 1;
channel.volume = @intCast(channel.volume + channel.volume_step);
} else if (channel.attack_duration > 0) {
channel.duration = channel.attack_duration;
channel.attack_duration = 0;
channel.volume = 0;
channel.volume_step = channel.attack_volume_step;
} else if (channel.decay_duration > 0) {
channel.duration = channel.decay_duration;
channel.decay_duration = 0;
channel.volume = channel.peak_volume;
channel.volume_step = channel.decay_volume_step;
} else if (channel.sustain_duration > 0) {
channel.duration = channel.sustain_duration;
channel.sustain_duration = 0;
channel.volume = channel.sustain_volume;
channel.volume_step = 0;
} else if (channel.release_duration > 0) {
channel.duration = channel.release_duration;
channel.release_duration = 0;
channel.volume = channel.sustain_volume;
channel.volume_step = channel.release_volume_step;
} else {
channel.duty = 0;
}
}
}
]) |sample| {
if (sample != 0) speaker_enable = .high;
out_sample.* = @intCast((sample >> 16) - std.math.minInt(i16));
}
channels.* = local_channels;

board.SPKR_EN.write(speaker_enable);
dma.ack_audio();
}

pub fn set_channel(channel: usize, state: Channel) void {
NVIC.ICER[32 / 32].write(.{ .CLRENA = 1 << 32 % 32 });
channels[channel] = state;
NVIC.ISER[32 / 32].write(.{ .SETENA = 1 << 32 % 32 });
}

var channels_storage: [4]Channel = .{.{
.duty = 0,
.phase = 0,
.phase_step = 0,
.phase_step_step = 0,

.duration = 0,
.attack_duration = 0,
.decay_duration = 0,
.sustain_duration = 0,
.release_duration = 0,

.volume = 0,
.volume_step = 0,
.peak_volume = 0,
.sustain_volume = 0,
.attack_volume_step = 0,
.decay_volume_step = 0,
.release_volume_step = 0,
}} ** 4;
const channels: *volatile [4]Channel = &channels_storage;

var sample_buffer_storage: [2][512]u16 = .{.{0} ** 512} ** 2;

const board = @import("../board.zig");
const std = @import("std");
const microzig = @import("microzig");
Expand Down
1 change: 1 addition & 0 deletions src/cart/api.zig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub const neopixels: *[5]NeopixelColor = @ptrFromInt(base + 0x08);
pub const red_led: *bool = @ptrFromInt(base + 0x1c);
pub const battery_level: *u12 = @ptrFromInt(base + 0x1e);
pub const framebuffer: *volatile [screen_width][screen_height]Pixel = @ptrFromInt(base + 0x20);
pub const audio_buffer: *volatile [2][512]i16 = @ptrFromInt(base + 0xa020);

pub const BlitOptions = struct {
pub const Flags = packed struct(u32) {
Expand Down

0 comments on commit dc010af

Please sign in to comment.