Created
March 9, 2014 22:00
-
-
Save johan-bjareholt/9455421 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <TimerOne.h> | |
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 = 17; | |
#define RESOLUTION 40 //Microsecond resolution for notes | |
/*NOTE: Many of the arrays below contain unused indexes. This is | |
to prevent the Arduino from having to convert a pin input to an alternate | |
array index and save as many cycles as possible. In other words information | |
for pin 2 will be stored in index 2, and information for pin 4 will be | |
stored in index 4.*/ | |
/*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 | |
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[] = { | |
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}; | |
/*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,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 | |
}; | |
//Current tick | |
unsigned int currentTick[] = { | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | |
}; | |
//Setup pins (Even-odd pairs for step control and direction | |
void setup(){ | |
pinMode(13, OUTPUT);// Pin 13 has an LED connected on most Arduino boards | |
pinMode(2, OUTPUT); // Step control 1 | |
pinMode(3, OUTPUT); // Direction 1 | |
pinMode(4, OUTPUT); // Step control 2 | |
pinMode(5, OUTPUT); // Direction 2 | |
pinMode(6, OUTPUT); // Step control 3 | |
pinMode(7, OUTPUT); // Direction 3 | |
pinMode(8, OUTPUT); // Step control 4 | |
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 | |
Serial.begin(9600); | |
} | |
void loop(){ | |
//The first loop, reset all the drives, and wait 2 seconds... | |
if (firstRun) | |
{ | |
firstRun = false; | |
resetAll(); | |
delay(2000); | |
} | |
currentPeriod[2] = 30578/80; | |
} | |
/* | |
Called by the timer inturrupt at the specified resolution. | |
*/ | |
void tick() | |
{ | |
/* | |
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){ | |
currentTick[4]++; | |
if (currentTick[4] >= currentPeriod[4]){ | |
togglePin(4,5); | |
currentTick[4]=0; | |
} | |
} | |
if (currentPeriod[6]>0){ | |
currentTick[6]++; | |
if (currentTick[6] >= currentPeriod[6]){ | |
togglePin(6,7); | |
currentTick[6]=0; | |
} | |
} | |
if (currentPeriod[8]>0){ | |
currentTick[8]++; | |
if (currentTick[8] >= currentPeriod[8]){ | |
togglePin(8,9); | |
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; | |
} | |
} | |
} | |
void togglePin(byte pin, byte direction_pin) { | |
//Switch directions if end has been reached | |
if (currentPosition[pin] >= MAX_POSITION[pin]) { | |
currentState[direction_pin] = HIGH; | |
digitalWrite(direction_pin,HIGH); | |
} | |
else if (currentPosition[pin] <= 0) { | |
currentState[direction_pin] = LOW; | |
digitalWrite(direction_pin,LOW); | |
} | |
//Update currentPosition | |
if (currentState[direction_pin] == HIGH){ | |
currentPosition[pin]--; | |
} | |
else { | |
currentPosition[pin]++; | |
} | |
//Pulse the control pin | |
digitalWrite(pin,currentState[pin]); | |
currentState[pin] = ~currentState[pin]; | |
} | |
// | |
//// UTILITY FUNCTIONS | |
// | |
//Not used now, but good for debugging... | |
void blinkLED(){ | |
digitalWrite(13, HIGH); // set the LED on | |
delay(250); // wait for a second | |
digitalWrite(13, LOW); | |
} | |
//For a given controller pin, runs the read-head all the way back to 0 | |
void reset(byte pin) | |
{ | |
digitalWrite(pin+1,HIGH); // Go in reverse | |
for (byte s=0;s<MAX_POSITION[pin];s+=2){ //Half max because we're stepping directly (no toggle) | |
digitalWrite(pin,HIGH); | |
digitalWrite(pin,LOW); | |
delay(5); | |
} | |
currentPosition[pin] = 0; // We're reset. | |
digitalWrite(pin+1,LOW); | |
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); | |
//} | |
//Stop all notes (don't want to be playing during/after reset) | |
for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){ | |
currentPeriod[p] = 0; // Stop playing notes | |
} | |
// 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){ | |
currentPosition[p] = 0; // We're reset. | |
digitalWrite(p+1,LOW); | |
currentState[p+1] = 0; // Ready to go forward. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment