Now using timer inturrupts for the Arduino.
This commit is contained in:
parent
93277776bc
commit
2d01e01a65
|
@ -1,8 +1,11 @@
|
||||||
|
#include <TimerOne.h>
|
||||||
|
|
||||||
boolean firstRun = true; // Used for one-run-only stuffs;
|
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.
|
//First pin being used for floppies, and the last pin. Used for looping over all pins.
|
||||||
const byte FIRST_PIN = 2;
|
const byte FIRST_PIN = 2;
|
||||||
const byte PIN_MAX = 9;
|
const byte PIN_MAX = 9;
|
||||||
|
#define RESOLUTION 40 //Microsecond resolution for notes
|
||||||
|
|
||||||
|
|
||||||
/*NOTE: Many of the arrays below contain unused indexes. This is
|
/*NOTE: Many of the arrays below contain unused indexes. This is
|
||||||
|
@ -14,24 +17,36 @@ stored in index 4.*/
|
||||||
|
|
||||||
/*An array of maximum track positions for each step-control pin. Even pins
|
/*An array of maximum track positions for each step-control pin. Even pins
|
||||||
are used for control, so only even numbers need a value here. 3.5" Floppies have
|
are used for control, so only even numbers need a value here. 3.5" Floppies have
|
||||||
80 tracks, 5.25" have 50 (use 79 and 49).
|
80 tracks, 5.25" have 50. These should be doubled, because each tick is now
|
||||||
|
half a position (use 158 and 98).
|
||||||
*/
|
*/
|
||||||
byte MAX_POSITION[] = {
|
byte MAX_POSITION[] = {
|
||||||
0,0,79,0,79,0,79,0,79,0};
|
0,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)
|
//Array to track the current position of each floppy head. (Only even indexes (i.e. 2,4,6...) are used)
|
||||||
byte currentPosition[] = {
|
byte currentPosition[] = {
|
||||||
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 the direction for each floppy head. (Only even indexes are used)
|
/*Array to keep track of state of each pin. Even indexes track the control-pins for toggle purposes. Odd indexes
|
||||||
boolean stepDirection[] = {
|
track direction-pins. LOW = forward, HIGH=reverse
|
||||||
false,false,false,false,false,false,false,false,false,false}; // false = forward, true=reverse (i.e. true=HIGH)
|
*/
|
||||||
|
int currentState[] = {
|
||||||
|
0,0,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW
|
||||||
|
};
|
||||||
|
|
||||||
//Current period assigned to each pin. 0 = off.
|
//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[] = {
|
unsigned int currentPeriod[] = {
|
||||||
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Setup pins (Even-odd pairs for step control and direction
|
//Setup pins (Even-odd pairs for step control and direction
|
||||||
void setup(){
|
void setup(){
|
||||||
pinMode(13, OUTPUT);// Pin 13 has an LED connected on most Arduino boards
|
pinMode(13, OUTPUT);// Pin 13 has an LED connected on most Arduino boards
|
||||||
|
@ -44,6 +59,9 @@ void setup(){
|
||||||
pinMode(8, OUTPUT); // Step control 4
|
pinMode(8, OUTPUT); // Step control 4
|
||||||
pinMode(9, OUTPUT); // Direction 5
|
pinMode(9, OUTPUT); // Direction 5
|
||||||
|
|
||||||
|
Timer1.initialize(RESOLUTION); // Set up a timer at the defined resolution
|
||||||
|
Timer1.attachInterrupt(tick); // Attach the tick function
|
||||||
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,61 +87,79 @@ void loop(){
|
||||||
currentPeriod[Serial.read()] = (Serial.read() << 8) | Serial.read();
|
currentPeriod[Serial.read()] = (Serial.read() << 8) | Serial.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
voice();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The voice() method controls WHEN each pin will be stepped by mod'ing the Arduino system-clock
|
Called by the timer inturrupt at the specified resolution.
|
||||||
against the currentPeriod for each pin. A period of 0 will skip the pin (i.e. pin is off)
|
|
||||||
*/
|
*/
|
||||||
void voice()
|
void tick()
|
||||||
{
|
{
|
||||||
if (currentPeriod[2] > 0 && micros()%currentPeriod[2] < 100){
|
/*
|
||||||
stepPin(2,3,4);
|
If there is a period set for control pin 2, count the number of
|
||||||
|
ticks that pass, and toggle the pin if the current period is reached.
|
||||||
|
*/
|
||||||
|
if (currentPeriod[2]>0){
|
||||||
|
currentTick[2]++;
|
||||||
|
if (currentTick[2] >= currentPeriod[2]){
|
||||||
|
togglePin(2,3);
|
||||||
|
currentTick[2]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (currentPeriod[4] > 0 && micros()%currentPeriod[4] < 100){
|
if (currentPeriod[4]>0){
|
||||||
stepPin(4,5,4);
|
currentTick[4]++;
|
||||||
|
if (currentTick[4] >= currentPeriod[4]){
|
||||||
|
togglePin(4,5);
|
||||||
|
currentTick[4]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (currentPeriod[6] > 0 && micros()%currentPeriod[6] < 100){
|
if (currentPeriod[6]>0){
|
||||||
stepPin(6,7,4);
|
currentTick[6]++;
|
||||||
|
if (currentTick[6] >= currentPeriod[6]){
|
||||||
|
togglePin(6,7);
|
||||||
|
currentTick[6]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (currentPeriod[8] > 0 && micros()%currentPeriod[8] < 100){
|
if (currentPeriod[8]>0){
|
||||||
stepPin(8,9,4);
|
currentTick[8]++;
|
||||||
|
if (currentTick[8] >= currentPeriod[8]){
|
||||||
|
togglePin(8,9);
|
||||||
|
currentTick[8]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void togglePin(byte pin, byte direction_pin) {
|
||||||
The stepPin() method controls the actual stepping of each pin. It uses the
|
|
||||||
stepDireciton array to determine the state of the direction_pin, and will automatically
|
|
||||||
reverse the direction when needed.
|
|
||||||
*/
|
|
||||||
void stepPin(byte pin, byte direction_pin, byte wait) {
|
|
||||||
|
|
||||||
//Switch directions if end has been reached
|
//Switch directions if end has been reached
|
||||||
if (currentPosition[pin] >= MAX_POSITION[pin]) {
|
if (currentPosition[pin] >= MAX_POSITION[pin]) {
|
||||||
stepDirection[pin] = true;
|
currentState[direction_pin] = HIGH;
|
||||||
|
digitalWrite(direction_pin,HIGH);
|
||||||
}
|
}
|
||||||
else if (currentPosition[pin] <= 0) {
|
else if (currentPosition[pin] <= 0) {
|
||||||
stepDirection[pin] = false;
|
currentState[direction_pin] = LOW;
|
||||||
|
digitalWrite(direction_pin,LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set direction_pin state, and update currentPosition
|
//Update currentPosition
|
||||||
if (stepDirection[pin]){
|
if (currentState[direction_pin] == HIGH){
|
||||||
digitalWrite(direction_pin,HIGH);
|
|
||||||
currentPosition[pin]--;
|
currentPosition[pin]--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
digitalWrite(direction_pin,LOW);
|
|
||||||
currentPosition[pin]++;
|
currentPosition[pin]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Pulse the control pin
|
//Pulse the control pin
|
||||||
digitalWrite(pin,HIGH);
|
digitalWrite(pin,currentState[pin]);
|
||||||
delayMicroseconds(wait);
|
currentState[pin] = ~currentState[pin];
|
||||||
digitalWrite(pin,LOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//// UTILITY FUNCTIONS
|
||||||
|
//
|
||||||
|
|
||||||
//Not used now, but good for debugging...
|
//Not used now, but good for debugging...
|
||||||
void blinkLED(){
|
void blinkLED(){
|
||||||
digitalWrite(13, HIGH); // set the LED on
|
digitalWrite(13, HIGH); // set the LED on
|
||||||
|
@ -135,13 +171,14 @@ void blinkLED(){
|
||||||
void reset(byte pin)
|
void reset(byte pin)
|
||||||
{
|
{
|
||||||
digitalWrite(pin+1,HIGH); // Go in reverse
|
digitalWrite(pin+1,HIGH); // Go in reverse
|
||||||
for (byte s=0;s<MAX_POSITION[pin];s++){
|
for (byte s=0;s<MAX_POSITION[pin];s+=2){ //Half max because we're stepping directly (no toggle)
|
||||||
digitalWrite(pin,HIGH);
|
digitalWrite(pin,HIGH);
|
||||||
digitalWrite(pin,LOW);
|
digitalWrite(pin,LOW);
|
||||||
delay(5);
|
delay(5);
|
||||||
}
|
}
|
||||||
currentPosition[pin] = 0; // We're reset.
|
currentPosition[pin] = 0; // We're reset.
|
||||||
stepDirection[pin] = false; // Ready to go forward.
|
digitalWrite(pin+1,LOW);
|
||||||
|
currentPosition[pin+1] = LOW; // Ready to go forward.
|
||||||
}
|
}
|
||||||
|
|
||||||
//Resets all the pins
|
//Resets all the pins
|
||||||
|
|
|
@ -27,6 +27,12 @@ public class MoppyPlayer implements Receiver {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolution of the Arduino code in microSeconds.
|
||||||
|
*/
|
||||||
|
public static int ARDUINO_RESOLUTION = 40;
|
||||||
|
|
||||||
|
|
||||||
MoppyBridge mb;
|
MoppyBridge mb;
|
||||||
SerialPort com;
|
SerialPort com;
|
||||||
|
@ -46,7 +52,7 @@ public class MoppyPlayer implements Receiver {
|
||||||
//Arduino by multipying by 2.
|
//Arduino by multipying by 2.
|
||||||
byte pin = (byte)(2*(message.getStatus() - 127));
|
byte pin = (byte)(2*(message.getStatus() - 127));
|
||||||
|
|
||||||
//System.out.println("Got note OFF on pin: " + (channel & 0xFF));
|
//System.out.println("Got note OFF on pin: " + (pin & 0xFF));
|
||||||
mb.sendEvent(pin, 0);
|
mb.sendEvent(pin, 0);
|
||||||
}
|
}
|
||||||
else if (message.getStatus() > 143 && message.getStatus() < 160){ // Note ON
|
else if (message.getStatus() > 143 && message.getStatus() < 160){ // Note ON
|
||||||
|
@ -57,10 +63,22 @@ public class MoppyPlayer implements Receiver {
|
||||||
//Get note number from MIDI message, and look up the period.
|
//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
|
//NOTE: Java bytes range from -128 to 127, but we need to make them
|
||||||
//0-255 to use for lookups. & 0xFF does the trick.
|
//0-255 to use for lookups. & 0xFF does the trick.
|
||||||
int period = microPeriods[(message.getMessage()[1] & 0xff)];
|
|
||||||
|
// After looking up the period, devide by (the Arduino resolution * 2).
|
||||||
|
// The Arduino's timer will only tick once per X microseconds based on the
|
||||||
|
// resolution. And each tick will only turn the pin on or off. So a full
|
||||||
|
// on-off cycle (one step on the floppy) is two periods.
|
||||||
|
int period = microPeriods[(message.getMessage()[1] & 0xff)]/(ARDUINO_RESOLUTION*2);
|
||||||
|
|
||||||
//System.out.println("Got note ON on pin: " + (pin & 0xFF) + " with period " + period);
|
//System.out.println("Got note ON on pin: " + (pin & 0xFF) + " with period " + period);
|
||||||
mb.sendEvent(pin, period);
|
//System.out.println(message.getLength() + " " + message.getMessage()[message.getLength()-1]);
|
||||||
|
|
||||||
|
//Zero velocity events turn off the pin.
|
||||||
|
if (message.getMessage()[2] == 0){
|
||||||
|
mb.sendEvent(pin, 0);
|
||||||
|
} else {
|
||||||
|
mb.sendEvent(pin, period);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,12 @@ by Sammy1Am
|
||||||
Moppy is a M_usical Fl_oppy controller program built for the Ardiuno UNO.
|
Moppy is a M_usical Fl_oppy controller program built for the Ardiuno UNO.
|
||||||
|
|
||||||
--INSTALLATION--
|
--INSTALLATION--
|
||||||
|
The Arduino code requires the TimeOne library available here: http://www.arduino.cc/playground/Code/Timer1
|
||||||
|
|
||||||
|
You will need to follow the directions in the appropriate Java/SerialDrivers folder for your system to install the serial drivers prior to running Moppy.
|
||||||
|
|
||||||
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.
|
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--
|
--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.
|
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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user