/********************************************/
//  tone関数で音を鳴らすプログラムその1 
/********************************************/
 
#define Start_Sw  4     //Switci 入力
#define school_Sw  5  //予備入力 
#define Down_Sw  6  //1オクターブダウン
#define Up_Sw  7       //1オクターブアップ
#define BAUDRATE 9600

int melo_300 = 300 ;    // 音の長さを指定 
int melo_500 = 500 ;  
int melo_150 = 150 ; 
 
int pin = 3 ;  // ブザーを接続したピン番号

const int KeyNum = 8 ; // キーの数  
                                                     // ド レ ミ ファ ソ ラ  シ ド
const int threshold[KeyNum] = { 128, 281, 376, 522, 684, 820, 909, 1011 } ; // AD変換値の閾値
const int frequency[KeyNum] = { 524, 588, 660, 698, 784, 880, 988, 1046 } ; // 各キーの周波数
                                                     // ド レ ミ ファ ソ ラ  シ ド 
int sounds[ ] = { 262, 294, 330, 349, 392, 440, 494, 523 } ;
 
int kirakira[ ] = { 262, 262, 392, 392, 440, 440, 392, 0,
                    349, 349, 330, 330, 294, 294, 262, 0,
                    392, 392, 349, 349, 330, 330, 294, 0 } ;

int School_A[ ] = { 698, 880, 784, 523, 0, 698, 784, 880, 698, 0,
                 880, 698, 784, 523, 0, 523, 784, 880, 698, 0 } ;

int Jr1[ ] = { 784, 660, 588, 524, 588,660 } ;// 4回リピート
int Jr2[ ] = { 880, 660, 588, 524, 588,660 } ;// 4回リピート
int Jr3[ ] = { 784, 660, 524, 988, 524, 660, 660, 784, 1046, 784, 1046, 1764, 1980,
               660, 524, 988, 784, 988, 524, 524, 660, 784, 660, 784, 988, 1046 } ;
// 遠き山に日は落ちて  
int School_B[ ] = { 330, 0, 392, 392, 0, 330, 0, 294, 262, 0, 294, 0, 330, 392, 0, 330, 294, 0, 0, 0,/*0~19*/
                  330, 0, 392, 392, 0, 330, 0, 294, 262, 0, 294, 330, 294, 0, 262, 262, 0, 0, 0,/*20~38*/
                  440, 0, 523, 523, 0, 494, 392, 440, 0, 440, 523, 494, 392, 440, 0, 0, 0,/*39~55*/
                  440, 0, 523, 523, 0, 494, 392, 440, 0, 440, 523, 494, 392, 440, 0, 0, 0,/*56~72*/
                  330, 0, 392, 392, 0, 330, 0, 294, 262, 0, 294, 0, 330, 392, 0, 330, 294, 0, 0, 0,/*73~92*/
                  330, 0, 392, 392, 0, 523, 0, 588, 660, 0, 588, 0, 523, 588, 440, 523, 0,/*93~109*/
                  588, 0, 523, 588, 440, 523, 0 } ; /*110~116*/
 
void setup( ){
    pinMode( Start_Sw, INPUT_PULLUP ) ;     //  ピンモード設定 
    pinMode( school_Sw, INPUT_PULLUP ) ;   //  ピンモード設定 
    pinMode( Down_Sw, INPUT_PULLUP ) ;   //  ピンモード設定 
    pinMode( Up_Sw, INPUT_PULLUP ) ;        //  ピンモード設定 
    Serial.begin( BAUDRATE ) ; 
    Serial.println( "\nIr Recive - Read" ) ;
    delay( 1000 ) ; 
} 
 
void loop( ){ 
    char i ;  
    char j ; 
    char k ;   
    
    int LastResult = -2 ; // 前回のキーデコード結果
    int result ; // 今回のキーデコード結果 
    int cnt = 0 ; // デコード結果が一致した回数/
    static int LastDisplayed = -2 ; // 前回loop関数が呼ばれたと時に表示したキー
        // 複数回のloop関数の呼び出しにわたって値を保持するために、static変数にしている
 
    if( digitalRead( Start_Sw ) != 1 ){ 
        // ドレミファソラシド 
        for( i = 0; i <= 7; ++i ){  
            tone( pin, sounds[ i ], melo_300 ) ;
            delay( melo_300 ) ; 
        }  
        delay( 1000 ) ; 
  
        for( i = 0; i <= 7; ++i ){ 
            tone( pin, ( sounds[ i ] * 2 ), melo_300 ) ;
            delay( melo_300 ) ; 
        } 
        delay( 1000 ) ; 
  
        // キラキラ星 
        for( i = 0; i <= 23; ++i ){ 
            tone( pin, kirakira[ i ], melo_300 ) ;
            delay( melo_500 ) ;  
        }
        for( i = 16; i <= 23; ++i ){ 
            tone( pin, kirakira[ i ], melo_300 ) ;
            delay( melo_500 ) ; 
        } 
        for( i = 0; i <= 15; ++i ){ 
            tone( pin, kirakira[ i ], melo_300 ) ;
            delay( melo_500 ) ;  
        } 
        delay( 1000 ) ; 
       
        // 学校のチャイム  
        for( i = 0; i <= 19; ++i ){ 
            tone( pin, School_A[ i ], melo_300 ) ;
            delay( melo_500 ) ;  
        } 
 
        // JR
        for( k = 0; k <= 1; ++k ){
            for( j = 0; j <= 3; ++j ){ 
                for( i = 0; i <= 5; ++i ){ 
                    tone( pin, Jr1[ i ], melo_150 ) ;//ソミレドレミ4回
                    delay( melo_150 ) ;
                }
            }
            for( j = 0; j <= 3; ++j ){ 
                for( i = 0; i <= 5; ++i ){
                    tone( pin, Jr2[ i ], melo_150 ) ;//ラミレドレミ4回
                    delay( melo_150 ) ; 
                } 
            } 
        } 
        for( i = 0; i <= 25; ++i ){              //  ソミドシドミ 
            tone( pin, Jr3[ i ], melo_150 ) ;// ミソドソドレミ
            delay( melo_150 ) ;                   //  ミドシソシド 
        }                                                     // ドミソミソシド
    } 
    
    // 遠き山に日は落ちて                 
    if( digitalRead( school_Sw ) != 1 ){ 
        for( i = 0; i <= 116; ++i ){ 
            tone( pin, School_B[ i ], melo_300 ) ;
            delay( melo_300 ) ; 
        } 
    }
 
    // キーを読み取る 
    // チャタリングの除去などのため、A/D変換の値が落ち着くまで待つ
    // 1ms間隔でキーを読み取り、10回連続で同じキーが押されていたら、落ち着いたと判断する
    do{ 
        result = KeyDecode( analogRead( A0 ) ) ; 
        if( result == LastResult ){ 
            cnt++ ; 
        } 
        else{
            LastResult = result ; 
            cnt = 0 ; 
        }
        delay( 1 ) ;  
    } 
    while( cnt<10 ) ; 
    // 音を出す/止める  
    if( result != LastDisplayed ){ 
        if( result < 0 ){ // 音を止める 
            noTone( pin ) ;  
        } 
        else{ // 音を出す 
            if( digitalRead( Down_Sw ) != 1 ){
                tone( pin, ( frequency[ result ] / 2 )) ;   
            }
            else if( digitalRead( Up_Sw ) != 1 ){
                tone( pin, ( frequency[ result ] * 2 )) ;
            } 
            else{ 
                tone( pin, frequency[ result ] ) ;
            }
        } 
    } 
    LastDisplayed = result ;  
} 
 
// キーデコード関数 
// 引数をA/D変換結果(0~1023)にして呼ぶと、押したキーの番号(0~KeyNum-1)を返す。
// 何もキーを押していない時は、-1を返す。
int KeyDecode( int n ){
    int i = 0 ; 
 
    while( ( i < KeyNum ) && ( n > threshold[ i ] ) ) i++ ;
    if( i >= KeyNum ) return -1 ;
    //Serial.println( i,HEX ) ; 
    return i ; 
} // KeyDecode