A program to automatically tune a guitar. Written by Justin Reidhead and Steven Swenson

Dependencies:   FFT FrequencyFinder Motor NewTextLCD PinDetect mbed strings

main.cpp

Committer:
melangeaddict
Date:
2012-04-15
Revision:
2:9c0a83c5ded5
Parent:
1:4a82a5178506
Child:
3:c672e782f19b

File content as of revision 2:9c0a83c5ded5:

#include "mbed.h"
#include "Motor.h"
#include "FrequencyFinder.h"
#include "NewTextLCD.h"
#include "PinDetect.h"
#include "strings.h"
#include <iostream>
#include <stdio.h>
#include <vector>

using namespace std;
//***************************************************
//***************Globals*****************************
PinDetect string_but(p11);
PinDetect pitch_but(p12);
PinDetect start_but(p13);
PinDetect mode_but(p14);

DigitalOut led1(LED1);
DigitalOut led2(LED2);

TextLCD lcd(p23,p24,p25,p26,p27,p28);
Motor motor(p20,p21,p22);//enable, direction, step
FrequencyFinder guitar(p19);//input

int selected_string;
bool current_mode;
bool start_tuning;
bool up, down;

vector<strings> strings_array;

//***************************************************
//*****************constants*************************
const bool tuning_mode=false;
const bool winding_mode=true;

//***************************************************
//******************prototypes***********************
void device_init();

void string_sel();
void pitch_sel();
void start();
void stop();
void mode();
void do_nothing();
void wind_up();
void wind_down();

void button_init();
void setup_buttons();
void output_menu();
void motor_calibration();
bool check_threshold(float);
//*************************************************
//*********************main************************
int main() {
    lcd.cls();
    lcd.printf("Perfect\n      Pitch");

    wait(.5);

    device_init();

    int state=0,next_state=0;
    //float old_freq=0;
    float new_freq=0;
    float desired_freq=0;
    strings *temp=&strings_array[0];
    while (1) {

        state=next_state;

        switch (state) {
                //------------------------------------
            case 0://Stay here till the user selects the string and pitch
                if (start_tuning==true) {
                    next_state=1;
                } else {
                    next_state=0;
                }

                break;
                //----------------------------------------
            case 1://motor calibration state
                motor_calibration();
                next_state=2;
                break;
                //-----------------------------------------
            case 2://begin the actual tuning
                temp=&strings_array[selected_string];
                desired_freq=temp->get_freq();

                next_state=3;
                break;
                //-----------------------------------------
            case 3:
                new_freq=guitar.find_frequency();
                if (check_threshold(new_freq)) {
                    if ((desired_freq-.5)<new_freq && (desired_freq+.5)>new_freq) {//We are within .5Hz of the desired frequency
                        lcd.cls();
                        lcd.printf("String %d\ntuned",selected_string);
                        wait(.5);

                        start_tuning=false;
                        next_state=0;
                    } else if ((desired_freq-.5)>new_freq) {
                        //motor(up,# of steps);
                        next_state=3;
                    } else {
                        //motor(down,# of steps);
                        next_state=3;
                    }
                } else {
                    next_state=3;
                }

                //TODO:Determine number of steps per frequency change
                //old_freq=new_freq;
                break;
                //-----------------------------------------
            default:
                break;
        }
        wait_ms(5);

        if (start_tuning==false) {//If the stop button is pressed, the state machine returns to user input
            next_state=0;
        }
    }

    //   return 0;
}

//***************************************************
//******************functions************************
void output_menu() {
    lcd.cls();
    strings temp=strings_array[selected_string];
    lcd.printf("Select String: %d\nSelect Pitch: %s",selected_string,temp.get_note().c_str());
}

//***************************************************
void button_init() {
    string_but.mode( PullDown );
    string_but.setSampleFrequency();

    pitch_but.mode( PullDown );
    pitch_but.setSampleFrequency();

    start_but.mode( PullDown );
    start_but.setSampleFrequency();

    mode_but.mode( PullDown );
    mode_but.setSampleFrequency();
}

//***************************************************
void setup_buttons() {
    if (current_mode==tuning_mode) {
        string_but.attach_asserted(&string_sel);
        pitch_but.attach_asserted(&pitch_sel);
        start_but.attach_asserted(&start);
        mode_but.attach_asserted(&mode);
    } else {
        string_but.attach_asserted(&wind_up);
        pitch_but.attach_asserted(&wind_down);
        start_but.attach_asserted(&do_nothing);
        mode_but.attach_asserted(&mode);
    }
}
//***************************************************
void string_sel() {
    selected_string++;
    if (selected_string>6)
        selected_string=1;

    output_menu();
}
//***************************************************
void pitch_sel() {
    strings *temp=&strings_array[selected_string];
    temp->inc_index();

    output_menu();
}
//***************************************************
void start() {
    start_tuning=true;
}
//***************************************************
void mode() {
    if (current_mode==tuning_mode) {
        current_mode=winding_mode;
        lcd.cls();
        lcd.printf("Winding Mode");
        wait(1);
    } else {
        current_mode=tuning_mode;
        lcd.cls();
        lcd.printf("Tuning Mode");
        wait(1);
    }
    setup_buttons();
}
//***************************************************
void stop() {
    start_tuning=false;
}
//***************************************************
void do_nothing() {
    return;
}
//***************************************************
void wind_up() {
    motor.motor_turn(1,10);
}
//***************************************************
void wind_down() {
    motor.motor_turn(0,10);
}
//***************************************************
void device_init() {
    strings string1(1);
    strings string2(2);
    strings string3(3);
    strings string4(4);
    strings string5(5);
    strings string6(6);
    strings_array.push_back(string1);
    strings_array.push_back(string2);
    strings_array.push_back(string3);
    strings_array.push_back(string4);
    strings_array.push_back(string5);
    strings_array.push_back(string6);

    selected_string=1;
    current_mode=tuning_mode;
    start_tuning=false;
    up=true;
    down=false;

    button_init();

    output_menu();
}
//***************************************************
void motor_calibration() {
    lcd.cls();
    lcd.printf("Calibrate Motor");

    float freq=0, freq_up=0, freq_down=0;
    bool done=false;
    lcd.cls();
    lcd.printf("Please pluck\nstring");

    //motor.motor_turn(up,25)//TODO: Adjust the number of steps here
    //On second thought, we don't need to tune up and down for this, we can find the current frequency
    //and then turn the peg for the two frequencies!
    while (!done) {
        freq=guitar.find_frequency();

        if (check_threshold(freq)) {
            freq_up=freq;
            done=true;
        }
    }
    motor.motor_turn(down,25);//TODO: Adjust the number of steps here
    done=false;
    while (!done) {
        freq=guitar.find_frequency();

        if (check_threshold(freq)) {
            freq_down=freq;
            done=true;
        }
    }

    if (freq_up<freq_down) {
        down=true;
        up=false;
    }

    lcd.cls();
    lcd.printf("Calibration Done");
}
//**********************************************
bool check_threshold(float freq) {
    if (freq>500) {
        lcd.cls();
        lcd.printf("Pluck string \nagain");
        return false;
    } else
        return true;
}