This is an mbed platform port for the musical floppy system created by sammy1am https://github.com/SammyIAm/Moppy

Dependencies:   MODSERIAL mbed

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;
            }
        }
    }
}