From ec145cee8ff46e90211ded54b5645a0cbae270a0 Mon Sep 17 00:00:00 2001 From: Sammy1Am Date: Wed, 14 Dec 2011 11:47:10 -0800 Subject: [PATCH 1/5] Updated Arduino code for 8 floppy drives. --- Arduino/Moppy/Moppy.pde | 75 +++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/Arduino/Moppy/Moppy.pde b/Arduino/Moppy/Moppy.pde index b64de7b..67a94d8 100644 --- a/Arduino/Moppy/Moppy.pde +++ b/Arduino/Moppy/Moppy.pde @@ -4,7 +4,7 @@ boolean firstRun = true; // Used for one-run-only stuffs; //First pin being used for floppies, and the last pin. Used for looping over all pins. const byte FIRST_PIN = 2; -const byte PIN_MAX = 9; +const byte PIN_MAX = 17; #define RESOLUTION 40 //Microsecond resolution for notes @@ -21,28 +21,28 @@ are used for control, so only even numbers need a value here. 3.5" Floppies hav half a position (use 158 and 98). */ byte MAX_POSITION[] = { - 0,0,158,0,158,0,158,0,158,0}; + 0,0,158,0,158,0,158,0,158,0,158,0,158,0,158,0,158,0}; //Array to track the current position of each floppy head. (Only even indexes (i.e. 2,4,6...) are used) byte currentPosition[] = { - 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}; /*Array to keep track of state of each pin. Even indexes track the control-pins for toggle purposes. Odd indexes track direction-pins. LOW = forward, HIGH=reverse */ int currentState[] = { - 0,0,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW + 0,0,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW }; //Current period assigned to each pin. 0 = off. Each period is of the length specified by the RESOLUTION //variable above. i.e. A period of 10 is (RESOLUTION x 10) microseconds long. unsigned int currentPeriod[] = { - 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 }; //Current tick unsigned int currentTick[] = { - 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 }; @@ -57,7 +57,15 @@ void setup(){ pinMode(6, OUTPUT); // Step control 3 pinMode(7, OUTPUT); // Direction 3 pinMode(8, OUTPUT); // Step control 4 - pinMode(9, OUTPUT); // Direction 5 + pinMode(9, OUTPUT); // Direction 4 + pinMode(10, OUTPUT); // Step control 5 + pinMode(11, OUTPUT); // Direction 5 + pinMode(12, OUTPUT); // Step control 6 + pinMode(13, OUTPUT); // Direction 6 + pinMode(14, OUTPUT); // Step control 7 + pinMode(15, OUTPUT); // Direction 7 + pinMode(16, OUTPUT); // Step control 8 + pinMode(17, OUTPUT); // Direction 8 Timer1.initialize(RESOLUTION); // Set up a timer at the defined resolution Timer1.attachInterrupt(tick); // Attach the tick function @@ -127,6 +135,34 @@ void tick() currentTick[8]=0; } } + if (currentPeriod[10]>0){ + currentTick[10]++; + if (currentTick[10] >= currentPeriod[10]){ + togglePin(10,11); + currentTick[10]=0; + } + } + if (currentPeriod[12]>0){ + currentTick[12]++; + if (currentTick[12] >= currentPeriod[12]){ + togglePin(12,13); + currentTick[12]=0; + } + } + if (currentPeriod[14]>0){ + currentTick[14]++; + if (currentTick[14] >= currentPeriod[14]){ + togglePin(14,15); + currentTick[14]=0; + } + } + if (currentPeriod[16]>0){ + currentTick[16]++; + if (currentTick[16] >= currentPeriod[16]){ + togglePin(16,17); + currentTick[16]=0; + } + } } @@ -178,14 +214,33 @@ void reset(byte pin) } currentPosition[pin] = 0; // We're reset. digitalWrite(pin+1,LOW); - currentPosition[pin+1] = LOW; // Ready to go forward. + currentPosition[pin+1] = 0; // Ready to go forward. } //Resets all the pins void resetAll(){ + + // Old one-at-a-time reset + //for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){ + // reset(p); + //} + + // New all-at-once reset + for (byte s=0;s<80;s++){ // For max drive's position + for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){ + digitalWrite(p+1,HIGH); // Go in reverse + digitalWrite(p,HIGH); + digitalWrite(p,LOW); + } + delay(5); + } + for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){ - reset(p); - } + currentPosition[p] = 0; // We're reset. + digitalWrite(p+1,LOW); + currentState[p+1] = 0; // Ready to go forward. + } + } From 50cd38c32a53ff23480e66d03157c88b82f35df1 Mon Sep 17 00:00:00 2001 From: Sammy1Am Date: Wed, 14 Dec 2011 13:12:23 -0800 Subject: [PATCH 2/5] Reorganized UI; stability changes --- .../src/moppydesk/MoppyMainWindow.form | 369 +++++++++++++----- .../src/moppydesk/MoppyMainWindow.java | 336 ++++++++++++---- .../src/moppydesk/MoppySequencer.java | 4 +- Java/MoppyDesk/src/moppydesk/MoppyUI.java | 3 +- 4 files changed, 540 insertions(+), 172 deletions(-) diff --git a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form index 821a7e7..f151dfe 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form +++ b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form @@ -3,6 +3,10 @@
+ + + + @@ -28,26 +32,14 @@ - + - - - - - - - - - - - - - - - - + + + + + - @@ -56,26 +48,14 @@ - - - - - - + + - + - - - - - - - - @@ -85,25 +65,6 @@ - - - - - - - - - - - - - - - - - - - @@ -126,46 +87,276 @@ - + - - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java index 29c119e..67dfc6b 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java +++ b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java @@ -11,6 +11,7 @@ package moppydesk; import gnu.io.CommPortIdentifier; +import java.awt.Component; import java.io.File; import java.util.Enumeration; import java.util.logging.Level; @@ -25,11 +26,10 @@ import javax.swing.JSlider; * * @author Sam */ -public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusConsumer{ +public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusConsumer { static String PREF_COM_PORT = "comPort"; static String PREF_LOADED_SEQ = "loadedSequencePath"; - MoppyUI app; Preferences prefs = Preferences.userNodeForPackage(MoppyUI.class); final JFileChooser sequenceChooser = new JFileChooser(); @@ -42,12 +42,11 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo updateComSelectionMenu(); - initializeSequencer((String) comSelectionMenu.getSelectedItem()); - - String previouslyLoadedFile = prefs.get(PREF_LOADED_SEQ, null); - if (previouslyLoadedFile != null){ - loadSequenceFile(new File(previouslyLoadedFile)); - } + statusLabel.setText("Ready"); + +// initializeSequencer((String) comSelectionMenu.getSelectedItem()); +// +// } private void updateComSelectionMenu() { @@ -75,6 +74,25 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo JOptionPane.showMessageDialog(rootPane, ex); } statusLabel.setText("Sequencer connected to " + comPort); + + String previouslyLoadedFile = prefs.get(PREF_LOADED_SEQ, null); + if (previouslyLoadedFile != null) { + loadSequenceFile(new File(previouslyLoadedFile)); + } + + setSequenceControlsEnabled(true); + connectSeqButton.setText("Disconnect"); + } + + private void shutdownSequencer() { + statusLabel.setText("Closing sequencer..."); + if (app.ms != null) { + app.ms.closeSequencer(); + app.ms = null; + } + setSequenceControlsEnabled(false); + connectSeqButton.setText("Connect"); + statusLabel.setText("Sequencer closed"); } /** This method is called from within the constructor to @@ -86,41 +104,34 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo // //GEN-BEGIN:initComponents private void initComponents() { - startButton = new javax.swing.JButton(); - stopButton = new javax.swing.JButton(); comSelectionMenu = new javax.swing.JComboBox(); statusLabel = new javax.swing.JLabel(); jSeparator1 = new javax.swing.JSeparator(); - loadButton = new javax.swing.JButton(); - sequenceNameLabel = new javax.swing.JLabel(); + jTabbedPane1 = new javax.swing.JTabbedPane(); + jPanel1 = new javax.swing.JPanel(); + sequencerControlsPanel = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); + sequenceNameLabel = new javax.swing.JLabel(); + startButton = new javax.swing.JButton(); + stopButton = new javax.swing.JButton(); + loadButton = new javax.swing.JButton(); jSlider1 = new javax.swing.JSlider(); bpmLabel = new javax.swing.JLabel(); + jSeparator2 = new javax.swing.JSeparator(); + connectSeqButton = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setTitle("MoppyDesk"); + setMinimumSize(new java.awt.Dimension(480, 410)); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { MoppyMainWindow.this.windowClosing(evt); } }); - startButton.setText("Start"); - startButton.setEnabled(false); - startButton.setName("startButton"); // NOI18N - startButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - startButtonClicked(evt); - } - }); - - stopButton.setText("Stop/Reset"); - stopButton.setName("stopButton"); // NOI18N - stopButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - stopResetClicked(evt); - } - }); - comSelectionMenu.setName("comSelectionMenu"); // NOI18N comSelectionMenu.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -133,7 +144,46 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo jSeparator1.setName("jSeparator1"); // NOI18N + jTabbedPane1.setName("bridgePanel"); // NOI18N + + jPanel1.setName("sequencerPanel"); // NOI18N + jPanel1.addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentHidden(java.awt.event.ComponentEvent evt) { + seqTabHidden(evt); + } + }); + + sequencerControlsPanel.setName("sequencerControlsPanel"); // NOI18N + sequencerControlsPanel.setPreferredSize(new java.awt.Dimension(200, 200)); + + jLabel1.setText("Current Sequence:"); + jLabel1.setEnabled(false); + jLabel1.setName("jLabel1"); // NOI18N + + sequenceNameLabel.setText(""); + sequenceNameLabel.setEnabled(false); + sequenceNameLabel.setName("sequenceNameLabel"); // NOI18N + + startButton.setText("Start"); + startButton.setEnabled(false); + startButton.setName("startButton"); // NOI18N + startButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + startButtonClicked(evt); + } + }); + + stopButton.setText("Stop/Reset"); + stopButton.setEnabled(false); + stopButton.setName("stopButton"); // NOI18N + stopButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + stopResetClicked(evt); + } + }); + loadButton.setText("Load Sequence"); + loadButton.setEnabled(false); loadButton.setName("loadButton"); // NOI18N loadButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -141,17 +191,12 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo } }); - sequenceNameLabel.setText(""); - sequenceNameLabel.setName("sequenceNameLabel"); // NOI18N - - jLabel1.setText("Current Sequence:"); - jLabel1.setName("jLabel1"); // NOI18N - jSlider1.setMajorTickSpacing(10); jSlider1.setMaximum(210); jSlider1.setMinimum(20); jSlider1.setPaintTicks(true); jSlider1.setValue(120); + jSlider1.setEnabled(false); jSlider1.setName("jSlider1"); // NOI18N jSlider1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseDragged(java.awt.event.MouseEvent evt) { @@ -160,8 +205,127 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo }); bpmLabel.setText(jSlider1.getValue() + " bpm"); + bpmLabel.setEnabled(false); bpmLabel.setName("bpmLabel"); // NOI18N + javax.swing.GroupLayout sequencerControlsPanelLayout = new javax.swing.GroupLayout(sequencerControlsPanel); + sequencerControlsPanel.setLayout(sequencerControlsPanelLayout); + sequencerControlsPanelLayout.setHorizontalGroup( + sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(sequenceNameLabel) + .addComponent(jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 220, Short.MAX_VALUE) + .addComponent(loadButton)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, sequencerControlsPanelLayout.createSequentialGroup() + .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 66, Short.MAX_VALUE) + .addComponent(startButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(stopButton)))) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addGap(136, 136, 136) + .addComponent(bpmLabel))) + .addContainerGap()) + ); + sequencerControlsPanelLayout.setVerticalGroup( + sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(sequencerControlsPanelLayout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(sequenceNameLabel)) + .addComponent(loadButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 100, Short.MAX_VALUE) + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(sequencerControlsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(stopButton) + .addComponent(startButton)) + .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, sequencerControlsPanelLayout.createSequentialGroup() + .addComponent(bpmLabel) + .addGap(54, 54, 54)))) + ); + + bpmLabel.getAccessibleContext().setAccessibleName(jSlider1.getValue() + " bpm"); + + jSeparator2.setName("jSeparator2"); // NOI18N + + connectSeqButton.setText("Connect"); + connectSeqButton.setToolTipText("Attempts to open selected COM port."); + connectSeqButton.setName("connectSequencerButton"); // NOI18N + connectSeqButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + connectSequencerPressed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(sequencerControlsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 436, Short.MAX_VALUE) + .addContainerGap()) + .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 456, Short.MAX_VALUE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(connectSeqButton) + .addContainerGap(373, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(connectSeqButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(sequencerControlsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 187, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + jTabbedPane1.addTab("Sequencer", jPanel1); + + jPanel2.setName("jPanel2"); // NOI18N + + jLabel2.setText("Coming soon... (sorry!)"); + jLabel2.setName("jLabel2"); // NOI18N + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addContainerGap(333, Short.MAX_VALUE)) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addContainerGap(229, Short.MAX_VALUE)) + ); + + jTabbedPane1.addTab("Bridge", jPanel2); + + jLabel3.setText("Arduino Port:"); + jLabel3.setName("jLabel3"); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -169,50 +333,33 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jTabbedPane1) .addComponent(statusLabel) - .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(sequenceNameLabel) - .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bpmLabel, javax.swing.GroupLayout.Alignment.TRAILING)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 30, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addComponent(startButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(stopButton)) - .addComponent(loadButton))) - .addComponent(jLabel1)) + .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 461, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 107, Short.MAX_VALUE) - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(sequenceNameLabel) - .addComponent(loadButton)) + .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel3)) .addGap(18, 18, 18) - .addComponent(bpmLabel) + .addComponent(jTabbedPane1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(startButton) - .addComponent(stopButton)) - .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(11, 11, 11) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 8, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(statusLabel) .addContainerGap()) ); + jTabbedPane1.getAccessibleContext().setAccessibleName("Bridge"); // NOI18N + pack(); }// //GEN-END:initComponents @@ -230,8 +377,8 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo private void loadSequence(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadSequence String previouslyLoaded = prefs.get(PREF_LOADED_SEQ, null); - if (previouslyLoaded != null){ - sequenceChooser.setCurrentDirectory(new File(previouslyLoaded)); + if (previouslyLoaded != null) { + sequenceChooser.setCurrentDirectory(new File(previouslyLoaded)); } int returnVal = sequenceChooser.showOpenDialog(this); @@ -242,21 +389,21 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo } }//GEN-LAST:event_loadSequence - private void loadSequenceFile(File sequenceFile){ + private void loadSequenceFile(File sequenceFile) { try { - statusLabel.setText("Loading file..."); - app.ms.loadFile(sequenceFile.getPath()); - sequenceNameLabel.setText(sequenceFile.getName()); - prefs.put(PREF_LOADED_SEQ, sequenceFile.getPath()); - statusLabel.setText("Loaded " + sequenceFile.getName()); - startButton.setEnabled(true); - } catch (Exception ex) { - Logger.getLogger(MoppyMainWindow.class.getName()).log(Level.SEVERE, null, ex); - statusLabel.setText("File loading error!"); - JOptionPane.showMessageDialog(rootPane, ex); - } + statusLabel.setText("Loading file..."); + app.ms.loadFile(sequenceFile.getPath()); + sequenceNameLabel.setText(sequenceFile.getName()); + prefs.put(PREF_LOADED_SEQ, sequenceFile.getPath()); + statusLabel.setText("Loaded " + sequenceFile.getName()); + startButton.setEnabled(true); + } catch (Exception ex) { + Logger.getLogger(MoppyMainWindow.class.getName()).log(Level.SEVERE, null, ex); + statusLabel.setText("File loading error!"); + JOptionPane.showMessageDialog(rootPane, ex); + } } - + private void tempoSliderChanged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tempoSliderChanged JSlider s = (JSlider) evt.getSource(); app.ms.setTempo(s.getValue()); @@ -267,15 +414,35 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo JComboBox cb = (JComboBox) evt.getSource(); if (comboBoxReady) { String comPort = (String) cb.getSelectedItem(); - initializeSequencer(comPort); + shutdownSequencer(); prefs.put(PREF_COM_PORT, comPort); } }//GEN-LAST:event_comPortSelected private void windowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_windowClosing - app.ms.closeSequencer(); + if (app.ms != null){ + app.ms.closeSequencer(); + } }//GEN-LAST:event_windowClosing + private void connectSequencerPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectSequencerPressed + if (connectSeqButton.getText().equals("Connect")) { + initializeSequencer((String) comSelectionMenu.getSelectedItem()); + } else { + shutdownSequencer(); + } + }//GEN-LAST:event_connectSequencerPressed + + private void seqTabHidden(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_seqTabHidden + shutdownSequencer(); + }//GEN-LAST:event_seqTabHidden + + private void setSequenceControlsEnabled(boolean enabled) { + for (Component c : sequencerControlsPanel.getComponents()) { + c.setEnabled(enabled); + } + } + public void tempoChanged(int newTempo) { jSlider1.setValue(newTempo); bpmLabel.setText(newTempo + " bpm"); @@ -283,14 +450,21 @@ public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusCo // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel bpmLabel; private javax.swing.JComboBox comSelectionMenu; + private javax.swing.JButton connectSeqButton; private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; private javax.swing.JSeparator jSeparator1; + private javax.swing.JSeparator jSeparator2; private javax.swing.JSlider jSlider1; + private javax.swing.JTabbedPane jTabbedPane1; private javax.swing.JButton loadButton; private javax.swing.JLabel sequenceNameLabel; + private javax.swing.JPanel sequencerControlsPanel; private javax.swing.JButton startButton; private javax.swing.JLabel statusLabel; private javax.swing.JButton stopButton; // End of variables declaration//GEN-END:variables - } diff --git a/Java/MoppyDesk/src/moppydesk/MoppySequencer.java b/Java/MoppyDesk/src/moppydesk/MoppySequencer.java index dcbed8d..2c1d2c6 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppySequencer.java +++ b/Java/MoppyDesk/src/moppydesk/MoppySequencer.java @@ -55,7 +55,9 @@ public class MoppySequencer implements MetaEventListener{ } public void stopSequencer(){ - sequencer.stop(); + if (sequencer.isOpen()){ + sequencer.stop(); + } mb.resetDrives(); } diff --git a/Java/MoppyDesk/src/moppydesk/MoppyUI.java b/Java/MoppyDesk/src/moppydesk/MoppyUI.java index e142c2d..f630d74 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppyUI.java +++ b/Java/MoppyDesk/src/moppydesk/MoppyUI.java @@ -16,7 +16,8 @@ public class MoppyUI extends SingleFrameApplication{ @Override protected void startup() { - show(new MoppyMainWindow(this)); + MoppyMainWindow mainWindow = new MoppyMainWindow(this); + show(mainWindow); } /** From 5296e478c864475d9f5a8ff1c664720e14e69619 Mon Sep 17 00:00:00 2001 From: Sammy1Am Date: Wed, 14 Dec 2011 13:12:36 -0800 Subject: [PATCH 3/5] Added a new sample song --- .../O Cara Mia, Addio (Turret Opera).mid | Bin 0 -> 10111 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Java/MoppyDesk/samplesongs/O Cara Mia, Addio (Turret Opera).mid diff --git a/Java/MoppyDesk/samplesongs/O Cara Mia, Addio (Turret Opera).mid b/Java/MoppyDesk/samplesongs/O Cara Mia, Addio (Turret Opera).mid new file mode 100644 index 0000000000000000000000000000000000000000..e5ecb1517158be954ec9b105480c2113fc8d4a95 GIT binary patch literal 10111 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 literal 0 HcmV?d00001 From 391fc0ff587497b68195bde644b2502f2aef6fba Mon Sep 17 00:00:00 2001 From: Sammy1Am Date: Wed, 14 Dec 2011 14:39:15 -0800 Subject: [PATCH 4/5] Clarified reported MIDI channels on load. --- Java/MoppyDesk/src/moppydesk/MoppySequencer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Java/MoppyDesk/src/moppydesk/MoppySequencer.java b/Java/MoppyDesk/src/moppydesk/MoppySequencer.java index 2c1d2c6..7dcffe5 100644 --- a/Java/MoppyDesk/src/moppydesk/MoppySequencer.java +++ b/Java/MoppyDesk/src/moppydesk/MoppySequencer.java @@ -47,7 +47,7 @@ public class MoppySequencer implements MetaEventListener{ Sequence sequence = MidiSystem.getSequence(new File(filePath)); sequencer.setSequence(sequence); - System.out.println("Loaded sequence with "+sequence.getTracks().length+" tracks."); + System.out.println("Loaded sequence with "+(sequence.getTracks().length-1)+" MIDI channels."); } public void startSequencer(){ From 991c45e86ff85d75fb82b7b1cd438d5826d9563e Mon Sep 17 00:00:00 2001 From: Sammy1Am Date: Wed, 14 Dec 2011 14:49:31 -0800 Subject: [PATCH 5/5] Updated Readme --- README.txt | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/README.txt b/README.txt index 548e7fc..e98d038 100644 --- a/README.txt +++ b/README.txt @@ -21,18 +21,30 @@ I built Moppy using an Arduino UNO, though it should work just fine on most Ardu 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. +Make sure you ground the correct drive-select pin, or the drive won't respond to any input. You can tell when you have the right drive selected, because the light on the front of the drive will come on. 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. +- Open up the code in NetBeans (or your favorite IDE) and run it. Alternatively, you can build the MoppyDesk.jar file and run that. +- Select the COM port that the Arduino is hooked up to from the "Arduino Port" drop-down. You will need to have this configured before you launch MoppyDesk. +- Click the "Connect" button to create a new Sequencer connected to the specified COM port. +- Click the "Load Sequence" button and select a suitable MIDI file (see below). +- Click "Start" to start playback (if all goes well). +- The Stop/Reset button will stop playback and reset the drives. Pressing "Start" again will resume from where the sequencer left off. You will need to reload the MIDI to start from the beginning. -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. +--MIDI FILE INFORMATION / GUIDELINES-- -Run the java code, cross your fingers, and enjoy! +- MIDI files should have one MIDI channel for each controller pin on the Arduino. Channel 1 will be sent to pin2, channel 2 to pin4, &c. +- Each drive can only play a single note at a time. +- The software will only attempt to play notes between C1 and B4. Floppy drives don't seem to respond well to notes outside of this range (especially higher). +- Generally shorter notes tend to sound better, as longer notes are marred by the read-heads changing directions repeatedly. + + + + +Cross your fingers, and enjoy! --HELP/CONTRIBUTIONS--