// ============================================
//  4-Legged walking robot "Chappi" Control Software
//  Arduino nano
// ============================================
//  PORT ASSIGNMENT
// ============================================
// D2:BUZZ       
// D3:SONAR ECHO D4:SONAR TRIG
// D5:SERVO FR   D6:SERVO FL
// D7:SERVO RR   D8:SERVO RL
// D9:SERVO TABLE
// D10:LED       D11:RGB
// D12:IR
// A0:PHOTO TR   A1:CHARGING
// ============================================
//  FILE INCLUDE 
// ============================================
  #include "Notes.h"                                   // 
  #include <Servo.h>  
  #include <Ultrasonic.h> 
   Servo FRsvo; Servo FLsvo; Servo RRsvo; Servo RLsvo; // 4 legs
   Servo TBL;                                          // Turntable
   Ultrasonic ultrasonic(4,3);                         // (Trig PIN,Echo PIN)    
// ============================================
//  CONTROL VALUABLES
// ============================================ 
   int stepp = 0;                               // walking sequence step
   boolean autom = true;                        // IR controller/auto mode
   int part = 0;                                // voice part on qualtet
// ============================================
//  SETUP
// ============================================
void setup() {
  Serial.begin(9600);                // Serial Monitor  
  pinMode(10, OUTPUT);               // LED
  pinMode(13, OUTPUT);               // nano on board LED
  pinMode(12, INPUT_PULLUP);         // IR
  pinMode(A1, INPUT);                // Charge voltage 0-560
  TBL.attach(9);                     // Table Servo Attach
  SVOattach(1);                      // 4-Legs Servo attach
  pause(0);                          // Set home position
  delay(300);   
}
// ============================================
//  LOOP
  int inter = 1000; 
  int zone;                                 // 0: short 1:middle 2:long
  long itime1, itime2, itime3;              // event timer  
  boolean tgll, tg;                         // led tggle
// ============================================
void loop() {
  IRreceiver(); if(autom) {
    if(millis() - itime2 > 200) { itime2 = millis();                       // 200ms loop
      ultras();                                                            // measure distance
      if(!zone) { SVOattach(1); FR(65*tg+10); FL(65*!tg+10); noTone(2); }  // short distance                                                                       // 15cm RED
      else if(zone == 1 || stepp) { go(); }                                // middle distance
      else if(zone == 2) { noTone(2); SVOattach(0); }                      // long distance Servo detach
    } tablecontrol();                                                      // Turntable control
  } 
  if(millis() - itime1 > inter) { itime1 = millis(); tgll = !tgll;         // table/charge check
    int vol = analogRead(A1);                                              // Serial.print("A1 voltage: "); Serial.println(vol);
    inter = 1000; if(vol > 300) { inter = 400; } digitalWrite(13,  tgll);  // ON board LED flash
  }   
  if(millis() - itime3 > 1800) { itime3 = millis(); tg = !tg; }            // near distance pause interval timer
}
// ============================================
//  TURNTABLE control
  int Rstate, Rtim;
  int dstep = 90; int ddir = 1;                // Table Control parameters  
  long itime1t, itime2t;
// ============================================
void tablecontrol() {
   if(inter < 1000) {                                                 // table activate mode 
     if(millis() - itime1t > 300 && zone == 2) { itime1t = millis();  // table rotation 300ms loop 
        if(ddir) { if(dstep < 150) dstep++; } else { if(dstep > 60) dstep--; } TBL.write(dstep);
     }   
     if(millis() - itime2t > Rtim) { itime2t = millis();              // table random pose
        Rtim = random(5000*2, 12000*2); ddir = !ddir;                 // random interval time/direction change
        Rstate++; if(Rstate > 7) { Rstate = 0; }
        switch(Rstate) {
             case 0: pause(0);                     break;  // Home
             case 1: pause(8);                     break;  // Right stretch
             case 2: pause(0);                     break;  // Home
             case 3: pause(1);                     break;  // Rear stretch!! 
             case 4: pause(0);                     break;  // Home             
             case 5: pause(9);                     break;  // Left stretch
             case 6: pause(0);                     break;  // Home
             case 7: pause(2); CloseEncounters();  break;  // ful stretch!! 
        }           
     }  
   }    
}
// ============================================
//  IR RECEIVER
// ============================================
void IRreceiver() { // command decode
   char foo = IRdrcv();
   if(foo) {
     switch(foo) {
       case '1':  Serial.print("charge voltage level(0-600): ");      
                  Serial.println(analogRead(A1));          break;  // light/charge sensor test
       case '2':  Serial.print("ultrasonic distance measurement(cm): ");
                  Serial.println(ultrasonic.Ranging(CM));  break;  // ultrasonic test
       case '3':  DanceoftheRead();            break;  // buzz test
       case '4':  pause(1);                    break;  // Rear ful stretch
       case '5':  pause(2);                    break;  // Ful stretch
       case '6':  pause(3);                    break;  // Front stretch
       case '7':  pause(4);                    break;  // Rear fuse
       case '8':  pause(5);                    break;  // Ful fuse
       case '9':  pause(6);                    break;  // Front fuse 
       case '0':  //pause(7); 
                  CloseEncounters(); break;  // Square Home position  
       case '*':  ImperialMarch1();            break;  // * small steps
       case '#':  ImperialMarch2();            break;  // #
       case 'U':  go();                        break;  // UP    forward steps
       case 'D':  goback();                    break;  // DOWN  reverse steps
       case 'L':  ImperialMarch3();            break;  // LEFT  left direction
       case 'R':  LadyMaddonna();              break;  // RIGTH right direction
       case 'K':  Serial.print("auto mode:");  autom = !autom; digitalWrite(10, !autom);  
                  Serial.println(autom);       break;  // OK    auto or manual
     }
   }    
}
// ============================================
// Servo Control
// Front leg         
// 10<-------- |--..
//     25-------90
//           <80>    Rear leg
//         ..--| -------->180
//           <53>
//              75---120
//           45---90                                      
 void FR(int posi) { if(posi != zzz) { posi = constrain(posi, 5, 95);   FRsvo.write(180-posi); } } // 10(Fstretch), 25-90(swing), 80(*)
 void FL(int posi) { if(posi != zzz) { posi = constrain(posi, 5, 95);   FLsvo.write(posi);     } } //             
 void RR(int posi) { if(posi != zzz) { posi = constrain(posi, 40, 180); RRsvo.write(180-posi); } } // 53(*), 45-75(swing1), 90-120(swing2), 180(Rstretch)
 void RL(int posi) { if(posi != zzz) { posi = constrain(posi, 40, 180); RLsvo.write(posi);     } } // *Square Position   
// ============================================
int pause(int pp) {
    SVOattach(1);  // SVO ON
    switch(pp) {
       case 0:  Serial.println("Base position:"); FR(70); FL(70); RR(110); RL(110); break;  // Base postion
       case 1:  Serial.println("Rear stretch:");  FR(90); FL(90); RR(180); RL(180); break;  // Rear ful stretch
       case 2:  Serial.println("Ful stretch:");   FR(10); FL(10); RR(180); RL(180); break;  // Ful stretch
       case 3:  Serial.println("Front stretch:"); FR(10); FL(10); RR(90);  RL(90);  break;  // Front stretch
       case 4:  Serial.println("Rear fuse:");     FR(90); FL(90); RR(120); RL(120); break;  // Rear fuse
       case 5:  Serial.println("Ful fuse:");      FR(25); FL(25); RR(120); RL(120); break;  // Ful fuse
       case 6:  Serial.println("Front fuse: ");   FR(25); FL(25); RR(75);  RL(75);  break;  // Front fuse 
       case 7:  Serial.println("Home postion:");  FR(80); FL(80); RR(53);  RL(53);          // 
                TBL.attach(9); dstep = 90; TBL.write(dstep); noTone(2);             break;  // Square Home position  
       case 8:  Serial.println("Right stretch:"); FR(10); FL(90); RR(90);  RL(180); break;  // Right stretch;
       case 9:  Serial.println("Left stretch:");  FR(90); FL(10); RR(180); RL(90);  break;  // Left stretch;
    }  delay(300); SVOattach(0); // SVO OFF
}
int go() {     tone(2, 200  + 200*stepp); stepp++; if(stepp > 5) { stepp = 0; } mogaki(stepp); } // normal steps
int goback() { tone(2, 2000 + 200*stepp); stepp--; if(stepp < 0) { stepp = 5; } mogaki(stepp); } // reverse steps
void mogaki(int para) { // walking sequence
   SVOattach(1);        // Serial.print("step:"); Serial.println(para);
   switch(para) {
     case 0: FL(90);     FR(25);         //  -   ^  (-)  ^
             RL(75);     RR(120);        // (-)  v   -   v
             break;
     case 1: FL(25);     FR(25);         // (^)  ^   ^  (^)
             RL(75-30);  RR(120);        //  -   v   -   v
             break;
     case 2: FL(25);     FR(90);         //  ^  (-)  ^   -
             RL(120-30); RR(120);        // (v)  v   v  (v)  
             break; 
           
     case 3: FL(25);     FR(90);         //  ^   -   ^  (-)
             RL(120);    RR(75);         //  v  (-)  v   - 
             break;     
     case 4: FL(25);     FR(25);         //  ^  (^) (^)  ^ 
             RL(120);    RR(75-30);      //  V   -   V   -  
             break;   
     case 5: FL(90);     FR(25);         // (-)  ^   -   ^
             RL(120);    RR(120-30);     //  V  (V) (V)  V   
             break;    
   }
}   
// ============================================
//  - Dance of the Reed Flutes data
//  - Lady Madonna data 
//  - The Imperial March data
//  - Theme from Close Encouters of the Third Kind
  int unitt = 40; // tempo
  long Ttime;     // 
// ============================================
void DanceoftheRead()  {  humming(xcountI, xtoneIa, xtoneIb, xtoneIc, xtoneId, xlegIa, xlegIb, xlegIc, xlegId,  8);   // Dance of the Reed Flutes data Intro
                          humming(xcountA, xtoneAa, xtoneAb, xtoneAc, xtoneAd, xlegAa, xlegAb, xlegAc, xlegAd, 16);   // Dance of the Reed Flutes data 1
                          humming(xcountB, xtoneBa, xtoneBb, xtoneBc, xtoneBd, xlegBa, xlegBb, xlegBc, xlegBd, 13); } // Dance of the Reed Flutes data 2
void LadyMaddonna()    {  humming(xcountC, xtoneCa, xtoneCb, xtoneCc, xtoneCd, xlegCa, xlegCb, xlegCc, xlegCd, 19);   // Lady Maddonna 19
                          humming(xcountD, xtoneDa, xtoneDb, xtoneDc, xtoneDd, xlegDa, xlegDb, xlegDc, xlegDd, 15); } // 14
void ImperialMarch1()  {  humming(count1,   tone1a,  tone1b,  tone1c,  tone1d,  leg1a,  leg1b,  leg1c,  leg1d,  9); } // The Imperial March data 1/3
void ImperialMarch2()  {  humming(count2,   tone2a,  tone2b,  tone2c,  tone2d,  leg2a,  leg2b,  leg2c,  leg2d,  9); } // The Imperial March data 2/3
void ImperialMarch3()  {  humming(count3,   tone3a,  tone3b,  tone3c,  tone3d,  leg3a,  leg3b,  leg3c,  leg3d, 10);   // The Imperial March data 3/3
                          humming(count4,   tone4a,  tone4b,  tone4c,  tone4d,  leg4a,  leg4b,  leg4c,  leg4d,  8);
                          humming(count5,   tone5a,  tone5b,  tone5c,  tone5d,  leg5a,  leg5b,  leg5c,  leg5d, 12); }
void CloseEncounters() {  humming(count6,   tone6a,  tone6b,  tone6c,  tone6d,  leg6a,  leg6b,  leg6c,  leg6d,  9); } // Theme from Close Encouters of the Third Kind               
void humming(const int *countn, const int *tonena, const int *tonenb, const int *tonenc, const int *tonend, 
             const int *legna,  const int *legnb,  const int *legnc,  const int *legnd, int len) {          
  digitalWrite(13, 0);
  for(int n = 0; n < len; n++)  { Ttime = millis();
     SVOattach(1);
     FR(pgm_read_word_near(legna + n)); 
     FL(pgm_read_word_near(legnb + n)); 
     RR(pgm_read_word_near(legnc + n)); 
     RL(pgm_read_word_near(legnd + n));
     switch(part) { // select voice part
       case 0: setTone(pgm_read_word_near(tonena + n));  break;
       case 1: setTone(pgm_read_word_near(tonenb + n));  break;
       case 2: setTone(pgm_read_word_near(tonenc + n));  break;
       case 3: setTone(pgm_read_word_near(tonend + n));  break;
     }      
     while(millis() - Ttime < unitt * pgm_read_word_near(countn + n)) { vivrato(); } //
  } setTone(0); digitalWrite(13, 0);
} 
// ============================================
//  Tone
// x    yyy          zzzz
// viv  octave 1-7   note 0-12
// ============================================
 #define o1 0x10   // short base note
 #define o2 0x20   // short base note
 #define o3 0x30   // 
 #define o4 0x40   //
 #define o5 0x50   //
 #define o6 0x60   //
 #define o7 0x70   //
 #define v1 0x10|0x80 // with vivrato
 #define v2 0x20|0x80 // with vivrato
 #define v3 0x30|0x80 // with vivrato
 #define v4 0x40|0x80 // with vivrato
 #define v5 0x50|0x80 // with vivrato
 #define v6 0x60|0x80 // with vivrato
 #define v7 0x70|0x80 // with vivrato
 #define zzz 0xff     // no action
 #define nT 0         // no tone
 #define C  1
 #define Cs 2
 #define D  3
 #define Ds 4
 #define E  5
 #define Ff 6
 #define Fs 7
 #define G  8
 #define Gs 9
 #define A  10
 #define As 11
 #define B  12
// ============================================
//  Dance of the Reed Flutes data
// ============================================
// <I>
const PROGMEM int xcountI[] = {    12,    12,    12,    12,    12,    12,    12,    12 }; // count[8]
const PROGMEM int xtoneIa[] = {  C|o1,  G|o1,  G|o1,  G|o1,  C|o1,  G|o1,  G|o1,  G|o1 }; // toneA
const PROGMEM int xtoneIb[] = {    nT,  G|o2,    nT,  G|o2,    nT,  G|o2,    nT,  G|o2 }; // toneB
const PROGMEM int xtoneIc[] = {    nT,    nT,    nT,    nT,    nT,    nT,    nT,    nT }; // toneC
const PROGMEM int xtoneId[] = {    nT,    nT,    nT,    nT,    nT,    nT,    nT,    nT }; // toneD
const PROGMEM int xlegIa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legA
const PROGMEM int xlegIb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legB
const PROGMEM int xlegIc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legC
const PROGMEM int xlegId[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legD
// <A>                              |             |             |             |             |             |                           |      |
const PROGMEM int xcountA[] = {     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     3,     3,     3,     3,    12,    12  }; // count [16]
const PROGMEM int xtoneAa[] = {  C|o6,  B|o5,  C|o6,  B|o5,  C|o6,    nT,  B|o5,    nT,  D|o6,    nT,  C|o6,  E|o6,  G|o6,  C|o7,  E|v7,   zzz  }; // toneA
const PROGMEM int xtoneAb[] = {  E|o4,  D|o4,  E|o4,  D|o4,  E|o4,    nT,  D|o4,    nT, Ff|o4,    nT,  E|o4,  G|o4,  C|o4,  E|o4,  G|v4,   zzz  }; // toneB
const PROGMEM int xtoneAc[] = {    nT,   zzz,  B|o2,   zzz,    nT,   zzz,  C|o2,   zzz,    nT,   zzz,  D|o2,   zzz,   zzz,   zzz,    nT,  E|o2  }; // toneC
const PROGMEM int xtoneAd[] = {  B|o1,   zzz,  B|o1,   zzz,  C|o1,   zzz,  C|o1,   zzz,  D|o1,   zzz,  D|o1,   zzz,   zzz,   zzz,  E|o1,  E|o1  }; // toneD
const PROGMEM int xlegAa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legA
const PROGMEM int xlegAb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legB
const PROGMEM int xlegAc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legC
const PROGMEM int xlegAd[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legD
// <B>                              |             |             |             |             |      |             |      |
const PROGMEM int xcountB[] = {     6,     6,     6,     6,     6,     6,     6,     6,    12,     6,     6,    12,    12   }; // count [13]
const PROGMEM int xtoneBa[] = { Ff|o7,  E|o7, Ff|o7,  E|o7,  D|o7,  C|o7,  G|o6,  E|o6,  C|o6,   zzz,  C|o7,  B|v6,   zzz   }; // toneA
const PROGMEM int xtoneBb[] = {  A|o5,  G|o5,  A|o5,  G|o5, Ff|o5,  E|o5,  C|o5,  E|o5, Gs|o5,   zzz,   zzz, Ff|v5,   zzz   }; // toneB
const PROGMEM int xtoneBc[] = {    nT,   zzz, Ff|o2,   zzz,    nT,   zzz,  G|o2,   zzz,    nT,  G|o2,   zzz,    nT,  G|o2   }; // toneC
const PROGMEM int xtoneBd[] = { Ff|o1,   zzz, Ff|o1,   zzz,  G|o1,   zzz,  G|o1,   zzz,  G|o1,  G|o1,   zzz,  G|o1,  G|o1   }; // toneD
const PROGMEM int xlegBa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legA
const PROGMEM int xlegBb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legB
const PROGMEM int xlegBc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legC
const PROGMEM int xlegBd[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legD
// ============================================
//  Lady Madonna data 
// ============================================
// <C>                                    <|             |             |             |       >    <|             |                           |             |       > 
const PROGMEM int xcountC[] = {     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     3,     4,     3,     4,     7,     7,     7,     5 }; // count [16x6]
const PROGMEM int xtoneCa[] = {   zzz, Cs|o5, Cs|o5,   zzz,  B|o4,  B|o4,  A|o4,   zzz,   zzz, Cs|o5, Cs|o5,  B|o4,    nT,  C|o4,  A|o4,   zzz,   zzz,   zzz,   zzz }; // toneA
const PROGMEM int xtoneCb[] = {  D|o1,  B|o1,  A|o2, Cs|o1, Cs|o2,  D|o2,  D|o1,  D|o1,  D|o1,  B|o1,  A|o2, Cs|o1,   zzz, Cs|o2,   zzz,  D|o2,  D|o1,  D|o1,  D|o1 }; // toneB
const PROGMEM int xtoneCc[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // toneC
const PROGMEM int xtoneCd[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // toneD
const PROGMEM int xlegCa[]  = {    30,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,   zzz,    60,    30,   zzz }; // legA
const PROGMEM int xlegCb[]  = {    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,    60,   zzz,    30,   zzz,   zzz,   zzz }; // legB
const PROGMEM int xlegCc[]  = {    30,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,   zzz,    60,    30,   zzz,   zzz }; // legC
const PROGMEM int xlegCd[]  = {    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,   zzz,    30,   zzz,   zzz,   zzz,    60,    30 }; // legD  
//                                 L      W      R      W      L      W      R      W      L      W      R      W             L             W      R      W      L  
// <D>                             <|      |      |      |      |      |      |      |             |      |      |             |>
const PROGMEM int xcountD[] = {     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,   35 }; // count [13x6]
const PROGMEM int xtoneDa[] = { Cs|o6, Cs|o6,  E|o6, Cs|o6, Fs|o6,  E|o6, Cs|o6,  A|o5,   zzz,  G|o5,  B|o5,  A|o5,   zzz,  A|v6,  zzz }; // toneA
const PROGMEM int xtoneDb[] = {  B|o1,  A|o2, Cs|o1, Cs|o2,  D|o2,  D|o1,  E|o2,  E|o1, Ff|o1, Ff|o2, Cs|o1,  G|o2,  A|o2,  E|v5,  zzz }; // toneB
const PROGMEM int xtoneDc[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  E|v7,  zzz }; // toneC
const PROGMEM int xtoneDd[] = {  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,  A|v4,  zzz }; // toneD
const PROGMEM int xlegDa[]  = {    10,   zzz,   zzz,   zzz,    58,   zzz,   zzz,   zzz,    20,   zzz,    48,   zzz,    58,   zzz,    0 }; // legA
const PROGMEM int xlegDb[]  = {    10,   zzz,   zzz,   zzz,    58,   zzz,   zzz,   zzz,   zzz,   zzz,    20,   zzz,    58,   zzz,    0 }; // legB
const PROGMEM int xlegDc[]  = {    58,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,   zzz,   zzz,    48,   zzz,    58,   zzz,    0 }; // legC
const PROGMEM int xlegDd[]  = {    58,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,    48,   zzz,    20,   zzz,    58,   zzz,    0 }; // legD  
// ============================================
//  The Imperial March data
// ============================================
// <1>                             |+1    |2     |3     |4            |5     |6           ||7,8
const PROGMEM int count1[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone1a[] = {  A|o3,  A|o3,  A|o3, Ff|o3,  C|o4,  A|o3, Ff|o3,  C|o4,  A|v3 }; // toneA
const PROGMEM int tone1b[] = {  E|o2,  E|o2,  E|o2,   zzz,   zzz,  E|o2,   zzz,   zzz,  E|v2 }; // toneB
const PROGMEM int tone1c[] = {  B|o1,  B|o1,  B|o1,  B|o2,   zzz,  B|o1,  B|o2,   zzz,  B|v1 }; // toneC
const PROGMEM int tone1d[] = {  A|o1,   zzz,   zzz, Gs|o2,   zzz,  A|o1, Gs|o2,   zzz,  E|v1 }; // toneD
const PROGMEM int leg1a[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legA  0:Straight >>>> 62:Angle
const PROGMEM int leg1b[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legB  i.e. 35|p3
const PROGMEM int leg1c[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legC
const PROGMEM int leg1d[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legD
// <2>                             |+1    |2     |3     |4            |5     |6           ||7,8
const PROGMEM int count2[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone2a[] = {  E|o4,  E|o4,  E|o4, Ff|o4,  C|o4, Gs|o3, Ff|o3,  C|o4,  A|v3 }; // toneA
const PROGMEM int tone2b[] = {  A|o2,  A|o2,  A|o2, Gs|o1,   zzz,  A|o2, Gs|o1,   zzz,  C|v2 }; // toneB
const PROGMEM int tone2c[] = {  C|o1,  C|o1,  C|o1,  C|o2,   zzz,  C|o1,  C|o2,   zzz,  E|v1 }; // toneC
const PROGMEM int tone2d[] = {  A|o1,   zzz,   zzz, Gs|o2,   zzz,  A|o1, Gs|o2,   zzz,  A|v1 }; // toneD
const PROGMEM int leg2a[]  = {    60,    20,   60,    20,   zzz,    60,    20,   zzz,    60 }; // legA  0:Straight >>>> 62:Angle
const PROGMEM int leg2b[]  = {    20,    60,   20,    60,   zzz,    60,    20,   zzz,    60 }; // legB  i.e. 35|p3
const PROGMEM int leg2c[]  = {    60,    20,   60,    20,   zzz,    20,    60,   zzz,    60 }; // legC
const PROGMEM int leg2d[]  = {    20,    60,   20,    60,   zzz,    20,    60,   zzz,    60 }; // legD
// <3>                             |+1    |2            |3     |4            |+1                  |2
const PROGMEM int count3[] = {    16,    13,     3,    16,     8,     8,     4,     4,     8,     8 }; // count
const PROGMEM int tone3a[] = {  A|o4,  A|o3,  A|o3,  A|o4, Gs|o4,  G|o4, Fs|o4, Ff|o4, Fs|o4,    nT }; // toneA
const PROGMEM int tone3b[] = {  C|o2,  C|o2,   zzz,  C|o2,  C|o2,   zzz, Ds|o2,   zzz,   zzz,    nT }; // toneB  c  d
const PROGMEM int tone3c[] = {  E|o1,  E|o1,   zzz,  E|o1,  E|o1,   zzz,  A|o1,   zzz,   zzz,    nT }; // toneC  a  b
const PROGMEM int tone3d[] = {  A|o1,   zzz,   zzz,   zzz,   zzz,   zzz, Fs|o1,   zzz,   zzz,    nT }; // toneD
const PROGMEM int leg3a[]  = {    62,   zzz,   zzz,     0,   zzz,    50,   zzz,   zzz,   zzz,    15 }; // legA NE:abcd 
const PROGMEM int leg3b[]  = {   zzz,    15,   zzz,   zzz,    50,   zzz,    62,   zzz,   zzz,   zzz }; // legB NW:bdac
const PROGMEM int leg3c[]  = {   zzz,    15,   zzz,   zzz,    50,   zzz,     0,   zzz,   zzz,   zzz }; // legC SW:dcba   
const PROGMEM int leg3d[]  = {     0,   zzz,   zzz,    62,   zzz,   zzz,   zzz,   zzz,   zzz,    15 }; // legD SE:cadb
// <4>                                    |3     |4            |+1                  |2     
const PROGMEM int count4[] = {     8,    16,     8,     8,     4,     4,     8,     8 }; // count
const PROGMEM int tone4a[] = { As|o3, Ds|o4,  D|o4, Cs|o4,  C|o4,  B|o3,  C|o4,    nT }; // toneA
const PROGMEM int tone4b[] = {   zzz,  A|o2,  A|o2,   zzz,  E|o2,   zzz,   zzz,   zzz }; // toneB
const PROGMEM int tone4c[] = {   zzz, Ds|o1, Ds|o1,   zzz,  A|o1,   zzz,   zzz,   zzz }; // toneC
const PROGMEM int tone4d[] = {   zzz,  A|o1,  A|o1,   zzz,  C|o2,   zzz,   zzz,   zzz }; // toneD
const PROGMEM int leg4a[]  = {   zzz,   zzz,    50,   zzz,     0,   zzz,   zzz,   zzz }; // legA
const PROGMEM int leg4b[]  = {   zzz,     0,   zzz,    50,   zzz,   zzz,   zzz,    15 }; // legB
const PROGMEM int leg4c[]  = {   zzz,    62,   zzz,   zzz,   zzz,   zzz,   zzz,    15 }; // legC
const PROGMEM int leg4d[]  = {   zzz,   zzz,    50,   zzz,    62,   zzz,   zzz,   zzz }; // legD
// <5>                                    |3     |4                   |+1           |2                   |3     |4
const PROGMEM int count5[] = {     8,    16,     8,     5,     3,     8,     8,     8,     5,     3,    16,    16 }; // count
const PROGMEM int tone5a[] = { Ff|o3, Gs|o3, Ff|o3,   zzz,  C|o4,  A|o3,   zzz, Ff|o3,   zzz,  C|o4,  A|v3,   zzz }; // toneA
const PROGMEM int tone5b[] = {   zzz,   zzz,   zzz,   zzz,   zzz,  A|o1,   zzz,   zzz,   zzz,   zzz,  E|v2,   zzz }; // toneB
const PROGMEM int tone5c[] = {   zzz,  C|o1,  C|o1,   zzz,   zzz,  E|o2,   zzz,   zzz,   zzz,   zzz,  C|v1,   zzz }; // toneC
const PROGMEM int tone5d[] = {   zzz, Gs|o2, Ff|o2,   zzz,   zzz,  C|o1,   zzz,   zzz,   zzz,   zzz,  A|v1,   zzz }; // toneD
const PROGMEM int leg5a[]  = {   zzz,    62,   zzz,   zzz,   zzz,    60,    50,    60,    50,   zzz,    60,     0 }; // legA
const PROGMEM int leg5b[]  = {   zzz,   zzz,    50,   zzz,   zzz,    50,    60,    50,    60,   zzz,    50,     0 }; // legB
const PROGMEM int leg5c[]  = {   zzz,   zzz,    50,   zzz,   zzz,    50,    30,    50,    30,   zzz,    50,     0 }; // legC
const PROGMEM int leg5d[]  = {   zzz,     0,   zzz,    50,   zzz,    30,    50,    30,    50,   zzz,    30,     0 }; // legD
// ============================================
//  Theme from Close Encouters of the Third Kind
// ============================================
// <6>                             |      |      |      |      |      |      |      |      |    
const PROGMEM int count6[] = {    16,    16,    16,    16,    16,    16,    16,    16,    64  }; // count
const PROGMEM int tone6a[] = {  A|o6,  B|o6,  G|o6,  G|o5,  D|o5,   zzz,   zzz,   zzz,  D|v5  }; // toneA
const PROGMEM int tone6b[] = {   zzz,   zzz,   zzz,   zzz,  A|o4,  B|o4,  G|o4,  G|o3,  D|v3  }; // toneB
const PROGMEM int tone6c[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  A|v3  }; // toneC
const PROGMEM int tone6d[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  D|v2  }; // toneD
const PROGMEM int leg6a[]  = {    10,   zzz,   zzz,   zzz,    90,   zzz,   zzz,   zzz,    10  }; // legA
const PROGMEM int leg6b[]  = {    90,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,    10  }; // legB
const PROGMEM int leg6c[]  = {    90,   zzz,   zzz,   zzz,   180,   zzz,   zzz,   zzz,   180  }; // legC
const PROGMEM int leg6d[]  = {   180,   zzz,   zzz,   zzz,    90,   zzz,   zzz,   zzz,   180  }; // legD
// ============================================
//  Sub Functions
// ============================================
// ============================================
//  Servo Enable Disable
// ============================================
void SVOattach(int tt) { // Servo attach, detach
  if(tt) {  FRsvo.attach(5);  FLsvo.attach(6);   // Front Right/Left leg
            RRsvo.attach(7);  RLsvo.attach(8);   // Rear  Right/Left leg
  } else {  FRsvo.detach();   FLsvo.detach();    // Front RightLeft leg
            RRsvo.detach();   RLsvo.detach();  } // Rear  Right/Left leg      
}
// ============================================
//  Ultrasonic Distance Meter
//  0: short 1:middle 2:long
// ============================================
void ultras() { // check distance to object
  int dist = ultrasonic.Ranging(CM); // Serial.print(dist); Serial.println(" cm" );
  if(dist <= 13) { zone = 0; } else if(dist > 13 && dist < 30) { zone = 1; } else { zone = 2; }    
}
// ============================================
//  Tone Control
//    12note + octave, vivrato, short base note
// x    yyy          zzzz
// viv  octave 1-7   note 0-12
   long itime1s, itime2s;      // system timers
   int vcnt, octo;             // base counter
   long frq;                   // tone frequency   
   int  viv = 0;               // vivrato switch
   boolean tglv = true;        // vivrato tgl
   float vvv;                  // vivrato depth
// ============================================
long oto[]  = {  // divide 0 to 7 times(3bit)
   0,       // 0  notone
   2093*2,  // 1  C
   2217*2,  // 2  Cs
   2349*2,  // 3  D
   2489*2,  // 4  Ds
   2637*2,  // 5  E
   2794*2,  // 6  F
   2960*2,  // 7  Fs
   3136*2,  // 8  G
   3322*2,  // 9  Gs
   3520*2,  // 10 A
   3729*2,  // 11 As
   3951*2   // 12 B  5bit(0-16)
};
void setTone(int note) { if(note != zzz) { noTone(2); frq = frqcalc(note); vcnt = 0; digitalWrite(13, 1); } }
long frqcalc(int dd) { // decode from ddd to freqeucy and octave
  long frqq = oto[min(dd & 0x0f, 12)];                                   // frequency
  octo = 7 - ((dd & 0x70) >> 4);                                         // octave
  if(octo < 7) { for (int k = 0; k < octo; k++) { frqq /= 2; } tone(2, frqq); } else { frqq = 0; }
  viv = bitRead(dd, 7);  vvv = frqq * 0.006;  return frqq;
}
void vivrato() { //
  if(millis() - itime1s > 20) { itime1s = millis(); 
     vcnt++; if(vcnt > 6 && !viv && octo > 4) { noTone(2); }             // short tone for base line  
     if(vcnt > 5 && vcnt < 7) { digitalWrite(13, 0); }                   // LED off @count 6
  }
  if(millis() - itime2s > 80 && viv && frq) { itime2s = millis();        // vivrato
     if(tglv) { tone(2, frq - vvv); } else { tone(2, frq); }             // sound vibration
     digitalWrite(13, tglv); tglv = !tglv;                               // LED flashing     
  }        
}
// ============================================
//  IR Command Receiver
//  --start-------    --"0"------    --"1"----------    --stop------
//    9ms     4ms     600us 600us    600us  1600us      600us          total 50 to 80ms 
// ============================================
char IRdrcv() {
  long TStime; long sTStime; int lap[40]; int n = 0; long ddd = 0; char moji = 0;
  if(!digitalRead(12)) {
    sTStime = millis();                                                        // total length check timer
      TStime = micros(); while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'a'; } 
      if(micros() - TStime < 4000) return 'b';                                 // start "L" 9ms   
      while( digitalRead(12)) { if(millis() - sTStime > 100) return 'c'; }     // start space "H" 4ms 
    for(int n = 0; n < 32; n++) {
      while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'd'; }     // data carry
      TStime = micros(); while( digitalRead(12)) { if(millis() - sTStime > 100) return 'e'; } 
      lap[n] = micros() - TStime;                                              // data space check   
    } while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'f'; }     // stop bit check
    for(int n = 0; n < 32; n++) { if(lap[n] > 1000) { bitSet(ddd, 31 - n); } } // Serial.print("data:"); Serial.println(ddd, HEX); 
    switch(ddd) {                                                              // decode
       case 0xFFA25D:  moji = '1'; break;    
       case 0xFF629D:  moji = '2'; break;
       case 0xFFE21D:  moji = '3'; break;
       case 0xFF22DD:  moji = '4'; break;
       case 0xFF02FD:  moji = '5'; break;
       case 0xFFC23D:  moji = '6'; break;
       case 0xFFE01F:  moji = '7'; break; 
       case 0xFFA857:  moji = '8'; break;
       case 0xFF906F:  moji = '9'; break;
       case 0xFF9867:  moji = '0'; break;
       case 0xFF6897:  moji = '*'; break;
       case 0xFFB04F:  moji = '#'; break; 
       case 0xFF18E7:  moji = 'U'; break; // "^"
       case 0xFF4AB5:  moji = 'D'; break; // "v"
       case 0xFF10EF:  moji = 'L'; break; // "<-"
       case 0xFF5AA5:  moji = 'R'; break; // "->"
       case 0xFF38C7:  moji = 'K'; break; // "ok"
    }  Serial.print("["); Serial.print(moji); Serial.print("]");
  } return moji;  
}
Comments