diff --git a/Java/MoppyDesk/nbproject/build-impl.xml b/Java/MoppyDesk/nbproject/build-impl.xml index c23fa79..a46461e 100644 --- a/Java/MoppyDesk/nbproject/build-impl.xml +++ b/Java/MoppyDesk/nbproject/build-impl.xml @@ -55,7 +55,14 @@ is divided into following sections: - + + + + + + + + @@ -70,8 +77,14 @@ is divided into following sections: + + + + + + @@ -84,40 +97,41 @@ is divided into following sections: - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + @@ -173,8 +187,17 @@ is divided into following sections: - + + + + + + + + + + @@ -291,14 +314,19 @@ is divided into following sections: Must set javac.includes - + + + - + + + + @@ -309,7 +337,8 @@ is divided into following sections: - + + @@ -325,11 +354,56 @@ is divided into following sections: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + @@ -424,6 +498,7 @@ is divided into following sections: + @@ -439,7 +514,7 @@ is divided into following sections: - + @@ -568,10 +643,10 @@ is divided into following sections: - + - + @@ -580,44 +655,53 @@ is divided into following sections: - To run this application from the command line without Ant, try: + To run this application from the command line without Ant, try: - java -cp "${run.classpath.with.dist.jar}" ${main.class} + java -cp "${run.classpath.with.dist.jar}" ${main.class} - + + + + + + + + + + + + + + - - - - - - - To run this application from the command line without Ant, try: - - java -jar "${dist.jar.resolved}" + + + - - - - - - - To run this application from the command line without Ant, try: + + + To run this application from the command line without Ant, try: - java -jar "${dist.jar.resolved}" + java -jar "${dist.jar.resolved}" + + + + + + - + + + + + + + + + + + Must select one file in the IDE or set profile.class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + Must select some files in the IDE or set javac.includes diff --git a/Java/MoppyDesk/nbproject/genfiles.properties b/Java/MoppyDesk/nbproject/genfiles.properties index 976043d..74b2ede 100644 --- a/Java/MoppyDesk/nbproject/genfiles.properties +++ b/Java/MoppyDesk/nbproject/genfiles.properties @@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=28e38971@1.38.2.45 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=23b52058 -nbproject/build-impl.xml.script.CRC32=05ef9bdb -nbproject/build-impl.xml.stylesheet.CRC32=f33e10ff@1.38.2.45 +nbproject/build-impl.xml.script.CRC32=9ea63390 +nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45 diff --git a/Java/MoppyDesk/nbproject/project.properties b/Java/MoppyDesk/nbproject/project.properties index 5fa0508..81cd7c3 100644 --- a/Java/MoppyDesk/nbproject/project.properties +++ b/Java/MoppyDesk/nbproject/project.properties @@ -1,9 +1,9 @@ annotation.processing.enabled=true annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= annotation.processing.run.all.processors=true annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=MoppyDesk +application.vendor=Sam build.classes.dir=${build.dir}/classes build.classes.excludes=**/*.java,**/*.form # This directory is removed when the project is cleaned: @@ -24,6 +24,7 @@ debug.test.classpath=\ dist.dir=dist dist.jar=${dist.dir}/MoppyDesk.jar dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= excludes= file.reference.RXTXcomm.jar=lib\\RXTXcomm.jar includes=** @@ -39,9 +40,7 @@ javac.source=1.5 javac.target=1.5 javac.test.classpath=\ ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit.classpath}:\ - ${libs.junit_4.classpath} + ${build.classes.dir} javac.test.processorpath=\ ${javac.test.classpath} javadoc.additionalparam= @@ -58,6 +57,7 @@ javadoc.windowtitle= main.class=moppydesk.Main manifest.file=manifest.mf meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false platform.active=default_platform run.classpath=\ ${javac.classpath}:\ @@ -65,7 +65,7 @@ run.classpath=\ # Space-separated list of JVM arguments used when running the project # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value # or test-sys-prop.name=value to set system properties for unit tests): -run.jvmargs= +run.jvmargs=-Djava.library.path="../SerialDrivers/rxtx-2.1-7-bins-r2/Windows/ch-rxtx-2.2-20081207-win-x64;${env_var:PATH}" run.test.classpath=\ ${javac.test.classpath}:\ ${build.test.classes.dir} diff --git a/Java/MoppyDesk/src/moppydesk/MIDINotes.java b/Java/MoppyDesk/src/moppydesk/MIDINotes.java deleted file mode 100644 index 40cc5ad..0000000 --- a/Java/MoppyDesk/src/moppydesk/MIDINotes.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package moppydesk; - -/** - * - * @author Sam - */ -public class MIDINotes { - - public static int[] microPeriods = { - 0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,21622,20409,19263,18182,17161,16198, //C1 - B1 - 15289,14436,13621,12856,12135,11454,10811,10205,9632,9091,8581,8099, //C2 - B2 - 7645,7218,6811,6428,6068,5727,5406,5103,4816,4546,4291,4050, //C3 - B3 - 0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0 - }; - -} diff --git a/Java/MoppyDesk/src/moppydesk/Main.java b/Java/MoppyDesk/src/moppydesk/Main.java index 503e770..fa63a8e 100644 --- a/Java/MoppyDesk/src/moppydesk/Main.java +++ b/Java/MoppyDesk/src/moppydesk/Main.java @@ -1,12 +1,8 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package moppydesk; /** * - * @author Sam + * @author Sammy1Am */ import gnu.io.NoSuchPortException; import gnu.io.PortInUseException; @@ -34,19 +30,17 @@ public class Main { MoppyPlayer mp = null; try { - mb = new MoppyBridge("COM3"); + mb = new MoppyBridge("COM6"); //Create MoppyBridge on the COM port with the Arduino mp = new MoppyPlayer(mb); mb.resetDrives(); - - - - - Sequence sequence = MidiSystem.getSequence(new File("songs/ImperialMarch.mid")); + //Load a MIDI file (TODO: Make this an argument, or a GUI window) + Sequence sequence = MidiSystem.getSequence(new File("samplesongs/KirbysTheme.mid")); final Sequencer sequencer = MidiSystem.getSequencer(false); + //Start a new thread to listen on the command-line to exit the program early new Thread(){ @Override public void run(){ @@ -54,6 +48,8 @@ public class Main { while (true){ try { if (br.readLine().equalsIgnoreCase("exit")) { + sequencer.stop(); + sequencer.close(); System.exit(0); } } catch (IOException ex) { @@ -63,16 +59,22 @@ public class Main { } }.start(); + + //Start the sequencer, and set the tempo (not being read from file!) sequencer.open(); sequencer.setSequence(sequence); - sequencer.setTempoInBPM(110); + sequencer.setTempoInBPM(160); System.out.println(sequence.getTracks().length); - sequencer.getTransmitter().setReceiver(mp); + sequencer.getTransmitter().setReceiver(mp); // Set MoppyPlayer as a receiver. - sequencer.start(); + sequencer.start(); //GO! + + //Wait til the sequence is done... while (sequencer.isRunning()){ Thread.sleep(3000); } + + //Close the sequencer sequencer.close(); } catch (MidiUnavailableException ex) { @@ -90,7 +92,7 @@ public class Main { } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } finally { - + //Reset everything and close down cleanly (hopefully) if (mb != null){ mb.resetDrives(); mb.close(); diff --git a/Java/MoppyDesk/src/moppydesk/MoppyBridge.java b/Java/MoppyDesk/src/moppydesk/MoppyBridge.java index fbe7271..e949c64 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppyBridge.java +++ b/Java/MoppyDesk/src/moppydesk/MoppyBridge.java @@ -1,8 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - package moppydesk; import gnu.io.CommPortIdentifier; @@ -17,10 +12,13 @@ import java.util.logging.Logger; /** * - * @author Sam + * @author Sammy1Am */ public class MoppyBridge { + static int FIRST_PIN = 2; + static int MAX_PIN = 9; + int SERIAL_RATE = 9600; OutputStream os; SerialPort com; @@ -32,10 +30,22 @@ public class MoppyBridge { os = com.getOutputStream(); } + /** + * Convenience method that splits the periodData int + * into two bytes for sending over serial. + * @param pin Controller pin to handle ntoe + * @param periodData length of period in microSeconds + */ public void sendEvent(byte pin, int periodData){ sendEvent(pin, (byte)((periodData >> 8) & 0xFF), (byte)(periodData & 0xFF)); } + /** + * Sends an event to the Arduino. + * @param pin Controller pin + * @param b1 + * @param b2 + */ public void sendEvent(byte pin, byte b1, byte b2){ sendArray(new byte[] {pin, b1, b2}); } @@ -49,13 +59,19 @@ public class MoppyBridge { } } + /** + * Sends a '0' period to all drives to silence them. + */ private void silenceDrives(){ // Stop notes - for (int d=2;d<=6;d+=2){ + for (int d=FIRST_PIN;d<=MAX_PIN;d+=2){ sendArray(new byte[] {(byte)d,(byte)0,(byte)0}); } } + /** + * Sends a special code (first byte=100) to reset the drives + */ public void resetDrives(){ silenceDrives(); //Send reset code @@ -68,8 +84,8 @@ public class MoppyBridge { } public void close(){ - silenceDrives(); if (os != null){ + silenceDrives(); try { os.close(); } catch (IOException ex) { diff --git a/Java/MoppyDesk/src/moppydesk/MoppyPlayer.java b/Java/MoppyDesk/src/moppydesk/MoppyPlayer.java index cbf1e8a..03b11c9 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppyPlayer.java +++ b/Java/MoppyDesk/src/moppydesk/MoppyPlayer.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package moppydesk; import gnu.io.SerialPort; @@ -9,10 +5,17 @@ import javax.sound.midi.MidiMessage; import javax.sound.midi.Receiver; /** * - * @author Sam + * @author Sammy1Am */ public class MoppyPlayer implements Receiver { + /** + * The periods for each MIDI note in an array. The floppy drives + * don't really do well outside of the defined range, so skip those notes. + * Periods are in microseconds because that's what the Arduino uses for its + * clock-cycles in the micro() function, and because milliseconds aren't + * precise enough for musical notes. + */ public static int[] microPeriods = { 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, @@ -36,15 +39,26 @@ public class MoppyPlayer implements Receiver { mb.close(); } + //Is called by Java MIDI libraries for each MIDI message encountered. public void send(MidiMessage message, long timeStamp) { if (message.getStatus() > 127 && message.getStatus() < 144){ // Note OFF + //Convert the MIDI channel being used to the controller pin on the + //Arduino by multipying by 2. byte pin = (byte)(2*(message.getStatus() - 127)); + //System.out.println("Got note OFF on pin: " + (channel & 0xFF)); mb.sendEvent(pin, 0); } else if (message.getStatus() > 143 && message.getStatus() < 160){ // Note ON + //Convert the MIDI channel being used to the controller pin on the + //Arduino by multipying by 2. byte pin = (byte)(2*(message.getStatus() - 143)); + + //Get note number from MIDI message, and look up the period. + //NOTE: Java bytes range from -128 to 127, but we need to make them + //0-255 to use for lookups. & 0xFF does the trick. int period = microPeriods[(message.getMessage()[1] & 0xff)]; + //System.out.println("Got note ON on pin: " + (pin & 0xFF) + " with period " + period); mb.sendEvent(pin, period); } diff --git a/Java/MoppyDesk/src/moppydesk/MoppyPlayer1.java b/Java/MoppyDesk/src/moppydesk/MoppyPlayer1.java deleted file mode 100644 index e69ea45..0000000 --- a/Java/MoppyDesk/src/moppydesk/MoppyPlayer1.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package moppydesk; - -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.UnsupportedCommOperationException; -import java.io.IOException; -import java.io.OutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.sound.midi.ControllerEventListener; -import javax.sound.midi.InvalidMidiDataException; -import javax.sound.midi.MidiMessage; -import javax.sound.midi.Receiver; -import javax.sound.midi.ShortMessage; - -/** - * - * @author Sam - */ -public class MoppyPlayer1 implements Receiver { - - OutputStream os; - SerialPort com; - - public MoppyPlayer1(String portName) throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException { - CommPortIdentifier cpi = CommPortIdentifier.getPortIdentifier(portName); - com = (SerialPort) cpi.open("MoppyDesk", 2000); - com.setSerialPortParams(31250, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - os = com.getOutputStream(); - } - - public void close(){ - if (os!=null){ - try { - os.close(); - } catch (IOException ex) { - Logger.getLogger(MoppyPlayer1.class.getName()).log(Level.SEVERE, null, ex); - } - } - if (com!=null){ - com.close(); - } - - } - - public void send(MidiMessage message, long timeStamp) { - if (message.getStatus() > 127 && message.getStatus() < 160){ - try { - ShortMessage sm = (ShortMessage) message; - //System.out.println(sm.getChannel()); - //TODO Channels start at 0?? - sm.setMessage(sm.getStatus()+1, sm.getData1(), sm.getData2()); //Try shifting channel - os.write(sm.getMessage()); - } catch (InvalidMidiDataException ex) { - Logger.getLogger(MoppyPlayer1.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(MoppyPlayer1.class.getName()).log(Level.SEVERE, null, ex); - } - } - } -} diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..8547856 --- /dev/null +++ b/README.txt @@ -0,0 +1,37 @@ + __ ___ + / |/ /__ ___ ___ __ __ + / /|_/ / _ \/ _ \/ _ \/ // / +/_/ /_/\___/ .__/ .__/\_, / + /_/ /_/ /___/ + +by Sammy1Am + +Moppy is a M_usical Fl_oppy controller program built for the Ardiuno UNO. + +--INSTALLATION-- + +Upload the included Arduino code to the Arduino of your choice, and open up the included Java code in your favorite IDE. This code includes a NetBeans project for your convenience, so you should be able to open the project directly in NetBeans. + + +--HARDWARE-- + +I built Moppy using an Arduino UNO, though it should work just fine on most Arduinos. The pins are connected in pairs to floppy drives as follows: Even pins (2,4,6...) are connected to the drive's STEP pin, the matching odd pins (3,5,7...) are connected to the drive's DIRECTION control pin. + +Some pinout information can be found here: http://pinouts.ru/Storage/InternalDisk_pinout.shtml + +Make sure you short the correct drive-select pin, or the drive won't respond to any input. Also, it's VERY IMPORTANT that your Arduino is grounded with the drives, or the drives will not register the pulses correctly. + + +--CONFIGURAITON / USE-- + +Right now, there is no configuration for MoppyDesk (the Moppy Desktop application for controlling) and any variables need to be changed in the code itself. This will be improved in the future. + +Edit the code to select the appropriate COM port, and point to the correct MIDI file. Don't forget to edit the tempo in the code as well. + +MIDI files should have one MIDI track for each controller pin on the Arduino. Track 1 will be sent to pin2, track 2 to pin4, &c. + +Run the java code, cross your fingers, and enjoy! + +--HELP/CONTRIBUTIONS-- + +https://github.com/SammyIAm/Moppy \ No newline at end of file