#include <IRremote.h>
// ===== ピン設定 =====
const int motor1A = 6;
const int motor1B = 7;
const int motor2A = 4;
const int motor2B = 5;
const int speakerPin = 13;
const int redLED   = 10;
const int greenLED = 9;
const int blueLED  = 8;
const int RECV_PIN = 2;
// ===== IR 受信オブジェクト =====
IRrecv irrecv(RECV_PIN);
decode_results results;
// ===== リモコンコード =====
#define BTN_0   0xFF6897
#define BTN_1   0xFF30CF
#define BTN_2   0xFF18E7
#define BTN_3   0xFF7A85
#define BTN_4   0xFF10EF
#define BTN_5   0xFF38C7
#define BTN_6   0xFF5AA5
#define BTN_7   0xFF42BD
#define BTN_8   0xFF4AB5
#define BTN_9   0xFF52AD
#define BTN_A   0xFFA25D
#define BTN_B   0xFF629D
#define BTN_C   0xFFE21D
#define BTN_D   0xFF22DD
#define BTN_E   0xFFC23D
#define BTN_CENTER 0xFFA857
#define BTN_UP    0xFF02FD
#define BTN_DOWN  0xFF9867
#define BTN_RIGHT 0xFF906F
#define BTN_LEFT  0xFFE01F
#define BTN_HOLD  0xFFFFFFFF
// ===== モータ制御関数 =====
void motorStop() {
  digitalWrite(motor1A, LOW);
  digitalWrite(motor1B, LOW);
  digitalWrite(motor2A, LOW);
  digitalWrite(motor2B, LOW);
}
void motorForward() {
  digitalWrite(motor1A, HIGH);
  digitalWrite(motor1B, LOW);
  digitalWrite(motor2A, HIGH);
  digitalWrite(motor2B, LOW);
}
void motorBackward() {
  digitalWrite(motor1A, LOW);
  digitalWrite(motor1B, HIGH);
  digitalWrite(motor2A, LOW);
  digitalWrite(motor2B, HIGH);
}
void motorRight() {
  digitalWrite(motor1A, HIGH);
  digitalWrite(motor1B, LOW);
  digitalWrite(motor2A, LOW);
  digitalWrite(motor2B, HIGH);
}
void motorLeft() {
  digitalWrite(motor1A, LOW);
  digitalWrite(motor1B, HIGH);
  digitalWrite(motor2A, HIGH);
  digitalWrite(motor2B, LOW);
}
// ===== LED制御 =====
void ledOffAll() {
  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, LOW);
}
// ===== セットアップ =====
void setup() {
  pinMode(motor1A, OUTPUT);
  pinMode(motor1B, OUTPUT);
  pinMode(motor2A, OUTPUT);
  pinMode(motor2B, OUTPUT);
  pinMode(speakerPin, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);
  motorStop();
  ledOffAll();
  irrecv.enableIRIn();  // 受信開始
  irrecv.blink13(true); // デバッグ用に13ピン点滅
}
// ===== メインループ =====
void loop() {
  if (irrecv.decode(&results)) {
    unsigned long value = results.value;
    // 同じボタン押し続けの場合は無視
    if (value != BTN_HOLD) {
      // --- 動作分岐 ---
      switch (value) {
        case BTN_UP:   // 前進
          digitalWrite(blueLED, HIGH);
          delay(1000);
          ledOffAll();
          motorForward();
          delay(1000);
          motorStop();
          break;
        case BTN_DOWN: // 後退
          digitalWrite(greenLED, HIGH);
          delay(1000);
          ledOffAll();
          motorBackward();
          delay(1000);
          motorStop();
          break;
        case BTN_RIGHT: // 右折
          digitalWrite(redLED, HIGH);
          delay(100);
          ledOffAll();
          motorRight();
          delay(100);
          motorForward();
          delay(100);
          motorStop();
          break;
        case BTN_LEFT: // 左折
          digitalWrite(redLED, HIGH);
          delay(100);
          ledOffAll();
          motorLeft();
          delay(100);
          motorForward();
          delay(100);
          motorStop();
          break;
        case BTN_1:
          digitalWrite(redLED, HIGH); delay(1000); ledOffAll(); break;
        case BTN_2:
          digitalWrite(blueLED, HIGH); delay(1000); ledOffAll(); break;
        case BTN_3:
          digitalWrite(greenLED, HIGH); delay(1000); ledOffAll(); break;
        case BTN_4:
          digitalWrite(redLED, HIGH); digitalWrite(blueLED, HIGH);
          delay(1000); ledOffAll(); break;
        case BTN_5:
          digitalWrite(greenLED, HIGH); digitalWrite(blueLED, HIGH);
          delay(1000); ledOffAll(); break;
        case BTN_6:
          digitalWrite(redLED, HIGH); digitalWrite(greenLED, HIGH);
          delay(1000); ledOffAll(); break;
        case BTN_7:
          digitalWrite(redLED, HIGH); digitalWrite(greenLED, HIGH); digitalWrite(blueLED, HIGH);
          delay(1000); ledOffAll(); break;
        case BTN_9:   // リセット
          asm volatile ("jmp 0");
          break;
        default:  // それ以外
          motorForward();
          tone(speakerPin, 1000);
          delay(300);
          motorStop();
          noTone(speakerPin);
          break;
      }
    }
    irrecv.resume(); // 次の受信に備える
  }
}