This is an mbed platform port for the musical floppy system created by sammy1am https://github.com/SammyIAm/Moppy
main.cpp
- Committer:
- aallport
- Date:
- 2015-10-10
- Revision:
- 0:e313e46f2b3d
File content as of revision 0:e313e46f2b3d:
#include "mbed.h" #include <Ticker.h> #include "MODSERIAL.h" bool firstRun = true; const int FIRST_PIN = 2; const int PIN_MAX=17; //in the array MODSERIAL pc(USBTX, USBRX); #define RESOLUTION 0.0040 DigitalOut MyLED(LED1); Ticker tick_flip; /*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). */ char 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) char 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 */ //go to line 52 //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 }; DigitalOut currentState[]= { LED3, LED4, p5,//S1 p6,//D1 p7,//S2 p8,//D2 p9,//S3 p10,//D3 p11,//S4 p12,//D4 p13,//S5 p14,//D5 p15,//S6 p16,//D6 p17,//S7 p18,//D7 p19,//S8 p20,//S8 }; void togglePin(unsigned char pin, unsigned char direction_pin) { //Switch directions if end has been reached if (currentPosition[pin] >= MAX_POSITION[pin]) { currentState[direction_pin] = 1; wait_us(2); } else if (currentPosition[pin] <= 0) { currentState[direction_pin] = 0; wait_us(2); } //Update currentPosition if (currentState[direction_pin] == 1) { currentPosition[pin]--; } else { currentPosition[pin]++; } //Pulse the control pin currentState[pin] = !currentState[pin]; wait_us(2); } 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; } } } // //// UTILITY FUNCTIONS // //Not used now, but good for debugging... void blinkLED() { MyLED = 1; // set the LED on wait(0.25); // wait for a second MyLED = 0; } //For a given controller pin, runs the read-head all the way back to 0 void reset(unsigned char pin) { currentState[pin+1] = 1; // Go in reverse wait_us(2); for (unsigned char s = 0; s < MAX_POSITION[pin]; s+= 2) { //Half max because we're stepping directly (no toggle) currentState[pin]=1; wait_us(2); currentState[pin]=0; wait_us(2); } currentPosition[pin] = 0; // We're reset. currentState[pin+1]=0; wait_us(2); 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 (int p=FIRST_PIN; p<=PIN_MAX; p+=2) { currentPeriod[p]=0; // Stop playing notes } // New all-at-once reset for (int s=0; s<80 ; s++) { // For max drive's position for (int p=FIRST_PIN; p<=PIN_MAX; p+=2) { currentState[p+1]=1; // Go in reverse wait_us(2); currentState[p]=1; wait_us(2); currentState[p]=0; wait_us(2); } } for (unsigned char p = FIRST_PIN; p <= PIN_MAX; p+= 2) { currentPosition[p] = 0; // We're reset. currentState[p+1] = 0; // Ready to go forward. wait_us(2); } } int main() { tick_flip.attach(&tick,RESOLUTION); //Setup Pins (Even-odd pairs for step control and direction /* pinMode(LED1, OUTPUT);// Pin 13 has an LED connected on most Arduino boards pinMode(5, OUTPUT); // Step control 1 pinMode(6, OUTPUT); // Direction 1 pinMode(7, OUTPUT); // Step control 2 pinMode(8, OUTPUT); // Direction 2 pinMode(9, OUTPUT); // Step control 3 pinMode(10, OUTPUT); // Direction 3 pinMode(11, OUTPUT); // Step control 4 pinMode(12, OUTPUT); // Direction 4 pinMode(13, OUTPUT); // Step control 5 pinMode(14, OUTPUT); // Direction 5 pinMode(15, OUTPUT); // Step control 6 pinMode(16, OUTPUT); // Direction 6 pinMode(17, OUTPUT); // Step control 7 pinMode(18, OUTPUT); // Direction 7 pinMode(19, OUTPUT); // Step control 8 pinMode(20, OUTPUT); // Direction 8 */ resetAll(); while(1) { //The first loop, reset all the drives, and wait 2 seconds... if (firstRun) { firstRun = false; resetAll(); wait(2); } //Only read if we have if (pc.rxBufferGetCount() > 2) { char part0 = pc.getc(); char part1 = pc.getc(); char part2 = pc.getc(); //Watch for special 100-message to reset the drives if (part0 == 100) { resetAll(); //Flush any remaining messages. pc.rxBufferFlush(); } else { currentPeriod[part0] = (part1 << 8) | part2; } } } }