Skip to content

Commit

Permalink
feat: implement millisecond sleep
Browse files Browse the repository at this point in the history
  • Loading branch information
heypoom committed Apr 8, 2024
1 parent 81e6363 commit c67fdce
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 14 deletions.
1 change: 1 addition & 0 deletions canvas/machine-wasm/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Cargo.lock
bin/
pkg/
wasm-pack.log
pkg-release
4 changes: 4 additions & 0 deletions canvas/machine-wasm/src/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ impl Controller {
m.mem.write(address, &data);
Ok(true.into())
}

pub fn wake(&mut self, machine_id: u16) {
self.canvas.seq.wake(machine_id);
}
}

#[cfg(test)]
Expand Down
3 changes: 2 additions & 1 deletion canvas/src/engine/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Effect } from "machine-wasm"

import { processSynthEffect } from "@/services/audio"
import { processMidiEvent } from "@/services/midi"
import { processSleepEffect } from "@/services/sleep"

export function processEffects(effects: Effect[], block: number) {
for (const effect of effects) {
Expand All @@ -13,7 +14,7 @@ export function processEffects(effects: Effect[], block: number) {
processSynthEffect(block, effect)
break
case "Sleep":
console.log("[SLEEP]", effect.duration)
processSleepEffect(block, effect)
break
default:
console.warn("unknown effect:", effect)
Expand Down
20 changes: 20 additions & 0 deletions canvas/src/services/sleep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Effect } from "machine-wasm"

import { engine } from "@/engine"

export function processSleepEffect(id: number, effect: Effect) {
if (effect.type !== "Sleep") return

const { duration } = effect

if (duration.type === "Tick") {
// tick sleep logic - count n ticks before sleep?
}

if (duration.type === "Ms") {
// ms sleep logic
setTimeout(() => {
engine.ctx.wake(id)
}, duration.value)
}
}
16 changes: 8 additions & 8 deletions machine/src/canvas/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ use tsify::Tsify;
use crate::audio::midi::{MidiOutputFormat};
use crate::audio::synth::SynthTrigger;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Tsify)]
#[serde(tag = "type", content = "value")]
#[tsify(into_wasm_abi, from_wasm_abi, namespace)]
pub enum SleepDuration {
Ms(u16),
Tick(u16),
}

/// Events that can be sent by blocks and machines.
/// This event can be considered a side effect that will be executed by the host.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Tsify)]
Expand Down Expand Up @@ -34,11 +42,3 @@ pub enum Event {
},
}

#[derive(Tsify, Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
#[tsify(into_wasm_abi, from_wasm_abi, namespace)]
pub enum SleepDuration {
Ms(u16),
Tick(u16),
}

11 changes: 9 additions & 2 deletions machine/src/machine/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,15 @@ impl Execute for Machine {
Op::RightShift => s.apply_two(|a, b| Ok(a >> b))?,

// Pause the execution of the thread
Op::Sleep(tick) => self.events.push(Event::Sleep {duration: SleepDuration::Tick(tick)}),
Op::SleepMs(ms) => self.events.push(Event::Sleep {duration: SleepDuration::Ms(ms)}),
Op::Sleep(tick) => {
self.sleeping = true;
self.events.push(Event::Sleep {duration: SleepDuration::Tick(tick)})
},

Op::SleepMs(ms) => {
self.sleeping = true;
self.events.push(Event::Sleep {duration: SleepDuration::Ms(ms)})
},
};

// Advance or jump the program counter.
Expand Down
5 changes: 5 additions & 0 deletions machine/src/machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub struct Machine {

/// How many messages does the machine expect to receive?
pub expected_receives: u16,

/// Is the machine sleeping?
pub sleeping: bool,
}

impl Machine {
Expand All @@ -57,6 +60,7 @@ impl Machine {
outbox: vec![],

is_debug: false,
sleeping: false,
expected_receives: 0,
}
}
Expand Down Expand Up @@ -90,6 +94,7 @@ impl Machine {
self.reg.reset();
self.mem.reset_stacks();
self.expected_receives = 0;
self.sleeping = false;
}
}

Expand Down
21 changes: 19 additions & 2 deletions machine/src/sequencer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use status::MachineStatus::{Awaiting, Halted, Running};

pub use seq_error::SequencerError::*;
pub use seq_error::SequencerError;
use crate::status::MachineStatus::{Errored, Invalid, Loaded, Ready};
use crate::status::MachineStatus::{Errored, Invalid, Loaded, Ready, Sleeping};

type Errorable = Result<(), SequencerError>;
type Statuses = HashMap<u16, MachineStatus>;
Expand Down Expand Up @@ -106,7 +106,7 @@ impl Sequencer {

// Manage state transitions of the machine.
match status {
Halted | Invalid | Loaded | Errored => continue,
Halted | Invalid | Loaded | Sleeping | Errored => continue,
Ready => { self.statuses.insert(id, Running); }
_ => {}
}
Expand Down Expand Up @@ -160,6 +160,12 @@ impl Sequencer {
break;
}

// Sleep the machine.
if machine.sleeping {
self.statuses.insert(id, Sleeping);
break;
}

// Halt the machine if we reached the end of the program.
if machine.should_halt() {
self.statuses.insert(id, Halted);
Expand All @@ -171,6 +177,17 @@ impl Sequencer {
Ok(())
}

/// Wake the machine up from sleep.
pub fn wake(&mut self, machine_id: u16) {
// Resume the machine's execution state.
self.statuses.insert(machine_id, Running);

// Reset the machine's sleeping flag.
if let Some(machine) = self.get_mut(machine_id) {
machine.sleeping = false;
}
}

pub fn is_halted(&self) -> bool {
self.statuses.values().all(|s| s == &Halted || s == &Invalid || s == &Errored)
}
Expand Down
3 changes: 3 additions & 0 deletions machine/src/sequencer/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub enum MachineStatus {
/// Machine is awaiting a message.
Awaiting,

/// Machine is sleeping for a pre-determined duration. zzzzzz!
Sleeping,

/// Machine has reached the end of execution.
Halted,

Expand Down
2 changes: 1 addition & 1 deletion machine/tests/sleep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod sleep_tests {
.into();

m.run().expect("cannot run the test program");

assert_eq!(m.sleeping, true);
assert_eq!(m.mem.read_stack(2), [0xFF, 0xAB]);
assert_eq!(m.events[0], Event::Sleep {duration: SleepDuration::Tick(10)});
assert_eq!(m.events[1], Event::Sleep {duration: SleepDuration::Ms(200)});
Expand Down

0 comments on commit c67fdce

Please sign in to comment.