diff --git a/src/data/byte/mod.rs b/src/data/byte/mod.rs index ff07688..34200f4 100644 --- a/src/data/byte/mod.rs +++ b/src/data/byte/mod.rs @@ -1 +1,2 @@ -pub mod u7; \ No newline at end of file +pub mod u7; +pub mod u4; \ No newline at end of file diff --git a/src/data/byte/u4.rs b/src/data/byte/u4.rs new file mode 100644 index 0000000..5cd40b7 --- /dev/null +++ b/src/data/byte/u4.rs @@ -0,0 +1,46 @@ +use core::convert::TryFrom; + +/// A primitive value that can be from 0-0x7F +pub struct U4(u8); + +/// Error representing that this value is not a valid u4 +pub struct InvalidU4(u8); + +impl TryFrom for U4{ + type Error = InvalidU4; + + fn try_from(value:u8) -> Result { + if value > U4::MAX.0 { + Err(InvalidU4(value)) + } else { + Ok(U4(value)) + } + } +} + +impl From for u8 { + fn from(value:U4) -> u8 { + value.0 + } +} + +impl U4 { + pub const MAX: U4= U4(0x0F); + pub const MIN: U4 = U4(0); + + /// Combines two nibbles (u4) eg half byte + /// result will be a full byte + pub fn combine(upper:U4,lower:U4) -> u8 { + let upper = upper.0.overflowing_shl(8).0; + let lower = lower.0 & U4::MAX.0; + upper | lower + } + + /// Constructs a U4 from a u8. + /// Note this clamps off the upper portions + pub fn from_overflowing_u8(value:u8) -> U4 { + const MASK :u8 = 0b0000_1111; + let number = MASK & value; + U4(number) + } +} diff --git a/src/data/midi/mod.rs b/src/data/midi/mod.rs index 6eeac55..710965d 100644 --- a/src/data/midi/mod.rs +++ b/src/data/midi/mod.rs @@ -1,5 +1,4 @@ pub mod notes; -pub mod code_index_number; pub mod channel; pub mod message; pub mod velocity; \ No newline at end of file diff --git a/src/data/usb_midi/cable_number.rs b/src/data/usb_midi/cable_number.rs index 0743c2d..3be05f2 100644 --- a/src/data/usb_midi/cable_number.rs +++ b/src/data/usb_midi/cable_number.rs @@ -1,4 +1,5 @@ use core::convert::TryFrom; +use crate::data::byte::u4::U4; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF /// indicating the number assignment of the Embedded MIDI Jack associated @@ -39,9 +40,15 @@ impl TryFrom for CableNumber { } -impl Into for CableNumber { - fn into(self) -> u8 { - self as u8 +impl From for u8{ + fn from(value:CableNumber) -> u8 { + value as u8 + } +} + +impl From for U4{ + fn from(value:CableNumber) -> U4 { + U4::from_overflowing_u8(u8::from(value)) } } @@ -55,7 +62,7 @@ mod tests { #[test] fn $id() { let (input,expected) = $value; - assert_eq!(input as u8, expected); + assert_eq!(u8::from(input), expected); } )* } diff --git a/src/data/midi/code_index_number.rs b/src/data/usb_midi/code_index_number.rs similarity index 76% rename from src/data/midi/code_index_number.rs rename to src/data/usb_midi/code_index_number.rs index 71d34b9..221699a 100644 --- a/src/data/midi/code_index_number.rs +++ b/src/data/usb_midi/code_index_number.rs @@ -1,4 +1,6 @@ use core::convert::TryFrom; +use crate::data::midi::message::Message; +use crate::data::byte::u4::U4; /// The Code Index Number(CIN) indicates the classification /// of the bytes in the MIDI_x fields @@ -16,12 +18,14 @@ impl TryFrom for CodeIndexNumber { } } -impl Into for CodeIndexNumber { - fn into(self) -> u8 { - self.0 +impl From for U4{ + fn from(value:CodeIndexNumber) -> U4{ + U4::from_overflowing_u8(value.0) } } + + impl CodeIndexNumber { /// Miscellaneous function codes. Reserved for future extensions @@ -60,4 +64,14 @@ impl CodeIndexNumber { /// Single Byte pub const SINGLE_BYTE : CodeIndexNumber= CodeIndexNumber(0xF); + pub fn find_from_message(value:&Message) -> CodeIndexNumber{ + match value { + Message::NoteOn(_,_,_) => CodeIndexNumber::NOTE_ON, + Message::NoteOff(_,_,_) => CodeIndexNumber::NOTE_OFF, + Message::ChannelAftertouch(_,_) => CodeIndexNumber::CHANNEL_PRESSURE, + Message::PitchWheelChange(_,_,_) => CodeIndexNumber::PITCHBEND_CHANGE, + Message::PolyphonicAftertouch(_,_,_) => CodeIndexNumber::POLY_KEYPRESS, + Message::ProgramChange(_,_) => CodeIndexNumber::PROGRAM_CHANGE + } + } } diff --git a/src/data/usb_midi/mod.rs b/src/data/usb_midi/mod.rs index 82ed118..eabf2cb 100644 --- a/src/data/usb_midi/mod.rs +++ b/src/data/usb_midi/mod.rs @@ -1,2 +1,3 @@ pub mod usb_midi_event_packet; -pub mod cable_number; \ No newline at end of file +pub mod cable_number; +pub mod code_index_number; \ 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 6487f0f..da3abff 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -1,50 +1,35 @@ use crate::data::usb_midi::cable_number::CableNumber; -use crate::data::midi::code_index_number::CodeIndexNumber; -use crate::data::midi::notes::Note; -use crate::data::midi::channel::Channel; +use crate::data::usb_midi::code_index_number::CodeIndexNumber; use crate::data::midi::message::Message; -use crate::data::midi::velocity::Velocity; -use crate::util::nibble::{combine_nibble}; -use crate::data::midi::message::raw::Raw; +use crate::data::byte::u4::U4; +use crate::data::midi::message::raw::{Payload,Raw}; /// A packet that communicates with the host -/// Note that the payload seems fairly 'open' -/// It's contents can depend on the cable/code index number -/// but may not!? +/// Currently supported is sending the specified normal midi +/// message over the supplied cable number pub struct UsbMidiEventPacket { cable_number : CableNumber, - code_index_number: CodeIndexNumber, //Is this strictly necessary - //if can be built from the midi message? message: Message } -/// Constructs a note-on midi message given the cable, note and velocity -pub fn note_on( cable:CableNumber, - channel: Channel, - note:Note, - velocity: Velocity) -> UsbMidiEventPacket { +impl From for [u8;4] { + fn from(value:UsbMidiEventPacket) -> [u8;4] { + let message= value.message; + let cable_number = U4::from(value.cable_number); + let index_number = { + let code_index = + CodeIndexNumber::find_from_message(&message); + U4::from(code_index) + }; + let header = U4::combine(cable_number,index_number); + let raw_midi = Raw::from(message); + let status = raw_midi.status; - let message = Message::NoteOn(channel,note,velocity); - - UsbMidiEventPacket{ - cable_number : cable, - code_index_number : CodeIndexNumber::NOTE_ON, - message : message + 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] + } } -} -impl Into<[u8;4]> for UsbMidiEventPacket { - /// Converts the midi packet into a byte array - /// suitable for transfer via usbgit - fn into(self) -> [u8;4] { - let cable_number : u8 = self.cable_number.into(); - let index_number : u8 = self.code_index_number.into(); - let header = combine_nibble(cable_number,index_number); - - let raw : Raw = self.message.into(); - let status : u8 = raw.status.into(); - - panic!() - } -} - +} \ No newline at end of file diff --git a/src/midi_device.rs b/src/midi_device.rs index 44d8431..9693508 100644 --- a/src/midi_device.rs +++ b/src/midi_device.rs @@ -1,6 +1,5 @@ use usb_device::class_prelude::*; use usb_device::Result; -use crate::data::midi::notes::Note; use crate::data::usb::constants::*; use crate::data::usb_midi::usb_midi_event_packet::UsbMidiEventPacket; @@ -34,28 +33,6 @@ impl MidiClass<'_, B> { self.standard_bulkin.write(&bytes) } - pub fn note_on(&mut self, chan: u8, note: Note, vel : u8) -> Result { - let note = note as u8; - self.standard_bulkin.write( - &[ - 0x09,//Note-on message (usb-midi) - 0x90 | (chan & 0x0f),// (note-on, normal midi) - note & 0x7f, //note - vel & 0x7f //vel - ]) - } - - pub fn note_off(&mut self, chan: u8, note: Note, vel : u8) -> Result { - let note = note as u8; - self.standard_bulkin.write( - &[ - 0x08,//Note-on message (usb-midi) - 0x80 | (chan & 0x0f),// (note-on, normal midi) - note & 0x7f, //note - vel & 0x7f //vel - ]) - } - } impl UsbClass for MidiClass<'_, B> { diff --git a/src/util/mod.rs b/src/util/mod.rs index 8d6cac7..e69de29 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1 +0,0 @@ -pub mod nibble; \ No newline at end of file diff --git a/src/util/nibble.rs b/src/util/nibble.rs deleted file mode 100644 index 5f8015f..0000000 --- a/src/util/nibble.rs +++ /dev/null @@ -1,10 +0,0 @@ - - -/// Combines two nibbles. -/// Note that the upper will overflow if greater than 0xF -/// The lower will be clamped to the range 0-0xF -pub fn combine_nibble(upper:u8,lower:u8) -> u8 { - let upper = upper.overflowing_shl(8).0; - let lower = lower & 0xF; - upper | lower -} \ No newline at end of file