148
src/main.rs
Normal file
148
src/main.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use macroquad::prelude::*;
|
||||
use serialport::SerialPortType;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Instruction {
|
||||
NoteOn(u8),
|
||||
NoteOff,
|
||||
Modulation { depth: u8, rate: u8 },
|
||||
Frequency(u16),
|
||||
}
|
||||
|
||||
pub struct SerialDevice {
|
||||
port: Box<dyn serialport::SerialPort>,
|
||||
ready: bool,
|
||||
}
|
||||
|
||||
const CHANNEL_COUNT: u8 = 4;
|
||||
|
||||
impl SerialDevice {
|
||||
pub fn new() -> Result<Self> {
|
||||
let ports = serialport::available_ports()?;
|
||||
let mut this: anyhow::Result<Self> = Err(anyhow!("No serial port found"));
|
||||
for port in ports {
|
||||
match port.port_type {
|
||||
SerialPortType::UsbPort(_) => {
|
||||
this = Ok(Self {
|
||||
port: serialport::new(port.port_name, 115200).open()?,
|
||||
ready: true,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
break;
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
fn note_off(&mut self, ch: u8) -> Result<()> {
|
||||
assert!(self.ready);
|
||||
assert!((0..CHANNEL_COUNT).contains(&ch));
|
||||
let bytes: Vec<u8> = vec![0x80 + ch];
|
||||
self.port.write(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn note_on(&mut self, ch: u8, note: u8) -> Result<()> {
|
||||
assert!(self.ready);
|
||||
assert!((0..CHANNEL_COUNT).contains(&ch));
|
||||
assert!((0..=127).contains(¬e));
|
||||
let bytes: Vec<u8> = vec![0x90 + ch, note];
|
||||
self.port.write(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn modulation(&mut self, ch: u8, depth: u8, rate: u8) -> Result<()> {
|
||||
assert!(self.ready);
|
||||
assert!((0..CHANNEL_COUNT).contains(&ch));
|
||||
assert!((0..=127).contains(&depth));
|
||||
assert!((0..=255).contains(&rate));
|
||||
let bytes: Vec<u8> = vec![0xA0 + ch, depth, rate];
|
||||
self.port.write(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn frequency_on(&mut self, ch: u8, freq: u16) -> Result<()> {
|
||||
assert!(self.ready);
|
||||
assert!((0..CHANNEL_COUNT).contains(&ch));
|
||||
let bytes: Vec<u8> = vec![0xB0 + ch, (freq & 0xff) as u8, (freq & 0xff00 >> 8) as u8];
|
||||
self.port.write(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) -> Result<()> {
|
||||
let bytes: Vec<u8> = vec![0xff];
|
||||
self.port.write(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute(&mut self, ch: u8, instruction: Instruction) -> Result<()> {
|
||||
match instruction {
|
||||
Instruction::NoteOn(note) => self.note_on(ch, note),
|
||||
Instruction::NoteOff => self.note_off(ch),
|
||||
Instruction::Modulation { depth, rate } => self.modulation(ch, depth, rate),
|
||||
Instruction::Frequency(freq) => self.frequency_on(ch, freq),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const INSTRUCTIONS_PATTERN: usize = 1024;
|
||||
|
||||
pub struct Pattern {
|
||||
pub channels: [[Option<Instruction>; INSTRUCTIONS_PATTERN]; CHANNEL_COUNT as usize],
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
channels: [[None; INSTRUCTIONS_PATTERN]; CHANNEL_COUNT as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Song {
|
||||
pub patterns: Vec<Pattern>,
|
||||
pub pattern_order: Vec<usize>, // index into patterns
|
||||
}
|
||||
|
||||
impl Song {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
patterns: Vec::new(),
|
||||
pattern_order: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct App {}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Self {
|
||||
Self { ..App::default() }
|
||||
}
|
||||
|
||||
pub async fn run(&self) {
|
||||
loop {
|
||||
self.update().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn update(&self) {
|
||||
clear_background(RED);
|
||||
|
||||
draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE);
|
||||
draw_rectangle(screen_width() / 2.0 - 60.0, 100.0, 120.0, 60.0, GREEN);
|
||||
|
||||
draw_text("Hello, Macroquad!", 20.0, 20.0, 30.0, DARKGRAY);
|
||||
|
||||
next_frame().await
|
||||
}
|
||||
}
|
||||
|
||||
#[macroquad::main("singer")]
|
||||
async fn main() {
|
||||
let app = App::new();
|
||||
app.run().await;
|
||||
}
|
||||
Reference in New Issue
Block a user