diff --git a/Cargo.toml b/Cargo.toml index 3db2212..d1a92e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,4 @@ edition = "2018" [dependencies] embedded-hal = "0.2.2" nb = "0.1.2" -usb-device = {version = "0.2.3"} +usb-device = {version = "0.2.3"} \ No newline at end of file diff --git a/src/data/byte/from_traits.rs b/src/data/byte/from_traits.rs new file mode 100644 index 0000000..b5e881a --- /dev/null +++ b/src/data/byte/from_traits.rs @@ -0,0 +1,12 @@ + + +/// Like from, but will conceptually overflow if the value is too big +/// this is useful from going from higher ranges to lower ranges +pub trait FromOverFlow:Sized { + fn from_overflow(_:T) -> Self; +} + +/// Like from, but will clamp the value to a maximum value +pub trait FromClamped:Sized{ + fn from_clamped(_:T) -> Self; +} \ No newline at end of file diff --git a/src/data/byte/mod.rs b/src/data/byte/mod.rs index 34200f4..f017cdd 100644 --- a/src/data/byte/mod.rs +++ b/src/data/byte/mod.rs @@ -1,2 +1,3 @@ pub mod u7; -pub mod u4; \ No newline at end of file +pub mod u4; +pub mod from_traits; \ No newline at end of file diff --git a/src/data/byte/u4.rs b/src/data/byte/u4.rs index 5cd40b7..eb60eae 100644 --- a/src/data/byte/u4.rs +++ b/src/data/byte/u4.rs @@ -26,7 +26,7 @@ impl From for u8 { impl U4 { pub const MAX: U4= U4(0x0F); - pub const MIN: U4 = U4(0); + pub const MIN: U4= U4(0); /// Combines two nibbles (u4) eg half byte /// result will be a full byte diff --git a/src/data/byte/u7.rs b/src/data/byte/u7.rs index bd6d244..f0ba796 100644 --- a/src/data/byte/u7.rs +++ b/src/data/byte/u7.rs @@ -1,4 +1,5 @@ use core::convert::TryFrom; +use crate::data::byte::from_traits::{FromOverFlow,FromClamped}; /// A primitive value that can be from 0-0x7F pub struct U7(u8); @@ -24,7 +25,25 @@ impl From for u8 { } } +impl FromOverFlow for U7 { + fn from_overflow(value:u8) -> U7 { + const MASK :u8 = 0b0111_1111; + let value = MASK & value; + U7(value) + } +} + +impl FromClamped for U7{ + fn from_clamped(value:u8) -> U7{ + match U7::try_from(value) { + Ok(x) => x, + _ => U7::MAX + } + } +} + impl U7 { pub const MAX: U7= U7(0x7F); pub const MIN: U7 = U7(0); + } \ No newline at end of file diff --git a/src/data/midi/message/message.rs b/src/data/midi/message/message.rs index bae35d5..bdfd4c2 100644 --- a/src/data/midi/message/message.rs +++ b/src/data/midi/message/message.rs @@ -1,10 +1,11 @@ use crate::data::midi::channel::Channel; -use crate::data::midi::velocity::Velocity; use crate::data::midi::notes::Note; use crate::data::byte::u7::U7; use crate::data::midi::message::raw::{Raw,Payload}; +type Velocity = U7; + /// Represents midi messages /// Note: not current exhaustive and SysEx messages end up /// being a confusing case. So are currently note implemented @@ -29,32 +30,32 @@ impl From for Raw { fn from(value:Message) -> Raw { match value { Message::NoteOn(chan,note,vel) => { - let payload = Payload::DoubleByte(note.into(),vel.into()); + let payload = Payload::DoubleByte(note.into(),vel); let status = NOTE_ON_MASK | u8::from(chan); Raw { status, payload } }, Message::NoteOff(chan,note,vel) => { - let payload = Payload::DoubleByte(note.into(),vel.into()); + let payload = Payload::DoubleByte(note.into(),vel); let status = NOTE_OFF_MASK | u8::from(chan); Raw {status, payload} }, Message::PolyphonicAftertouch(chan,note,pressure) => { - let payload = Payload::DoubleByte(note.into(),pressure.into()); + let payload = Payload::DoubleByte(note.into(),pressure); let status = POLYPHONIC_MASK | u8::from(chan); Raw {status, payload} }, Message::ProgramChange(chan,program) => { - let payload = Payload::SingleByte(u8::from(program)); + let payload = Payload::SingleByte(program); let status = PROGRAM_MASK | u8::from(chan); Raw {status, payload} }, Message::ChannelAftertouch(chan,pressure) => { - let payload = Payload::SingleByte(u8::from(pressure)); + let payload = Payload::SingleByte(pressure); let status = CHANNEL_AFTERTOUCH_MASK | u8::from(chan); Raw {status, payload} }, Message::PitchWheelChange(chan,lsb,msb) => { - let payload = Payload::DoubleByte(u8::from(lsb),u8::from(msb)); + let payload = Payload::DoubleByte(lsb,msb); let status = PITCH_BEND_MASK | u8::from(chan); Raw {status , payload} } diff --git a/src/data/midi/message/mod.rs b/src/data/midi/message/mod.rs index af3f77a..bb7b6df 100644 --- a/src/data/midi/message/mod.rs +++ b/src/data/midi/message/mod.rs @@ -1,4 +1,3 @@ -pub mod voice; pub mod message; pub mod raw; pub use crate::data::midi::message::message::{Message}; \ No newline at end of file diff --git a/src/data/midi/message/raw.rs b/src/data/midi/message/raw.rs index 3384794..4494a38 100644 --- a/src/data/midi/message/raw.rs +++ b/src/data/midi/message/raw.rs @@ -1,8 +1,10 @@ +use crate::data::byte::u7::U7; + /// Represents the payloads that the midi message may contain pub enum Payload { Empty, - SingleByte(u8), - DoubleByte(u8,u8) + SingleByte(U7), + DoubleByte(U7,U7) } /// A struct that captures the valid states @@ -13,4 +15,4 @@ pub enum Payload { pub struct Raw { pub status: u8, pub payload: Payload -} +} \ No newline at end of file diff --git a/src/data/midi/message/voice.rs b/src/data/midi/message/voice.rs deleted file mode 100644 index 234d3bb..0000000 --- a/src/data/midi/message/voice.rs +++ /dev/null @@ -1,15 +0,0 @@ - -pub use crate::data::midi::channel::Channel; -pub use crate::data::midi::notes::Note; -pub use crate::data::midi::velocity::Velocity; - -pub enum Voice { - NoteOff(Channel,Note,Velocity), - NoteOn(Channel,Note,Velocity), - PolyPressure(Channel) -} - - -impl Voice { - -} \ No newline at end of file diff --git a/src/data/midi/mod.rs b/src/data/midi/mod.rs index 710965d..f0b4a56 100644 --- a/src/data/midi/mod.rs +++ b/src/data/midi/mod.rs @@ -1,4 +1,3 @@ pub mod notes; pub mod channel; -pub mod message; -pub mod velocity; \ No newline at end of file +pub mod message; \ No newline at end of file diff --git a/src/data/midi/notes.rs b/src/data/midi/notes.rs index f754d8b..b610c46 100644 --- a/src/data/midi/notes.rs +++ b/src/data/midi/notes.rs @@ -1,4 +1,5 @@ - +use crate::data::byte::u7::U7; +use crate::data::byte::from_traits::FromOverFlow; /// A simple enum type that represents all the midi 'notes' /// note the flat versions are associated constants /// but can be referenced like Note::Bb3 @@ -26,6 +27,14 @@ impl Into for Note { } } +impl From for U7 { + fn from(value:Note) -> U7{ + let byte = value as u8; + U7::from_overflow(byte) + } +} + + impl Note { #[allow(non_upper_case_globals)] pub const Db1m : Note = Note::Cs1m; #[allow(non_upper_case_globals)] pub const Eb1m : Note = Note::Ds1m; diff --git a/src/data/midi/velocity.rs b/src/data/midi/velocity.rs deleted file mode 100644 index 2ec05fb..0000000 --- a/src/data/midi/velocity.rs +++ /dev/null @@ -1,28 +0,0 @@ -use core::convert::TryFrom; - -pub struct Velocity(u8); - -pub struct InvalidVelocity(u8); - -impl TryFrom for Velocity{ - type Error = InvalidVelocity; - - fn try_from(value:u8) -> Result { - if value > 0x7F { - Err(InvalidVelocity(value)) - } else { - Ok(Velocity(value)) - } - } -} - -impl Into for Velocity { - fn into(self) -> u8 { - self.0 - } -} - -impl Velocity { - pub const MAX: Velocity= Velocity(0x7F); - pub const MIN: Velocity = Velocity(0); -} \ No newline at end of file diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/usb_midi/usb_midi_event_packet.rs index da3abff..cec7575 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -28,8 +28,10 @@ impl From for [u8;4] { match raw_midi.payload { Payload::Empty => [header,status,0,0], - Payload::SingleByte(byte) => [header,status,byte,0], - Payload::DoubleByte(byte1,byte2) => [header,status,byte1,byte2] + Payload::SingleByte(byte) => + [header,status,byte.into(),0], + Payload::DoubleByte(byte1,byte2) => + [header,status,byte1.into(),byte2.into()] } } } \ No newline at end of file