/**************************************************************/
//  FILE   赤外線リモコン受信ユニット OSRB38C9AA  
//             TOSIBAリモコンコードで動くリモコン車
//  DATE        :Tue, Jan 10, 2025  
//  DESCRIPTION : 赤外線リモコン受信ユニット OSRB38C9AA 
//  CPU TYPE    : Arduino UNO  
//                                                                    by Chiyabo
//  This file is generated by Renesas Project Generator. 
//超シンプル 赤外線リモコン受信(NECフォーマット)
/**************************************************************/

#define BAUDRATE 9600  
#define DATAPIN 8   // ArduinoUNO:2   M5Stamp:19 RaspberryPi PICO:8 
// 赤外線リモコン受信 *************************************************/ 
#define NECT 562   //クロック基準時間(NECフォーマット)
// Port 
const int motorL1Pin = 2 ; 
const int motorL2Pin = 3;  
const int motorR1Pin = 4 ; 
const int motorR2Pin = 7 ; 
const int L_PWM_Pin = 6 ;   //左モーターへのPWM出力
const int R_PWM_Pin = 5 ;  //右モーターへのPWM出力 
  
int pin = 12 ;         // ブザーを接続したピン番号  
int melo = 500 ;    // 音の長さを指定  
char i ;  
char j ; 
//char k ;  
char Start ; 
bool iRrepeatCoomand ; 
uint16_t iRAddr ;  
uint8_t iRCommand ; 
uint8_t R_And_L ; 
 
int Jr1[ ] = { 784, 660, 588, 524, 588,660 } ;  // 4回リピート 2回短縮 
int Jr2[ ] = { 880, 660, 588, 524, 588,660 } ;  // 4回リピート 2回短縮  
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 } ;
 
bool readIrData( ){
  bool retStat = true ;
  uint8_t readData[ 4 ] ; 
  int setPos = 0 ;
  int bitLen = 0 ; 
  int stat = HIGH ; 
  uint8_t bitData ; 
  unsigned long beginTime ; 
  unsigned long passTime ;  
  memset( readData, 0, sizeof( readData ) ) ; 
  iRrepeatCoomand = false ; 
 
  // ----- データ受信開始待ち -----  
  while( digitalRead( DATAPIN ) == HIGH ) ;  // LOWになるまで待つ
                                                                    // ----- FRAMAE受信開始 ----- 
  beginTime = micros( ) ; 
  while( digitalRead( DATAPIN ) == LOW ) ;   // LeaderのHIGHの長さを計測 
  passTime = micros( ) - beginTime ;
  if( passTime < NECT * 12  || passTime > NECT * 20 ){ 
    return false ;  
  }
 
  // ----- FRAMAE種別 ----- 
  beginTime = micros( ) ; 
  while( digitalRead( DATAPIN ) == HIGH ) ; 
  passTime = micros( ) - beginTime ;
  if( passTime <= NECT * 6 ){  //LOW時間が6T以下ならばRepeatと判断 
    // Repeace FRAME 
    iRrepeatCoomand = true ; 
    return true ; 
  }
  
  // ----- データ受信 -----   
  bitData = 0x01 ;  
  beginTime = micros( ) ;
  bitLen = 0 ;  
  stat = LOW ; 
  passTime = 0 ; 
  while( bitLen < 32 && passTime < NECT * 6 ){ 
    passTime = micros( ) - beginTime ; 
    if( digitalRead( DATAPIN ) !=  stat ){ 
      if( stat == HIGH ){   
        // ----- 1Bit 受信 -----
        if( passTime >= NECT * 2 ){ 
          readData[ setPos ] |= bitData ; 
        } 
        if( bitData != 0x80 ){ 
          bitData <<= 1 ; 
        } 
        else{  
          bitData = 0x01 ;  
          setPos ++ ; 
        }  
        beginTime = micros( ) ;  
        bitLen ++ ;  
        stat = LOW ; 
      } 
      else{ 
        beginTime = micros( ) ; 
        stat = HIGH ; 
      } 
    }  
  } 
  bitData = ~readData[ 3 ] ; 
  retStat = ( bitData == readData[ 2 ] ) ? true :false ; 
  iRAddr = readData[ 1 ] << 8 | readData[ 0 ] ; 
  iRCommand = readData[ 2 ] ;  
  
  switch ( iRCommand ){ 
    case 0x3E : //上  
      motorStop( 100 ) ; 
      if( Start == false ){
        Start = true ; 
        // JR  
        for ( j = 0; j <= 2;  ++j ){ 
          for( i = 0; i <= 5; ++i ){
            tone( pin, Jr1[ i ], 150 ) ;  // ソミレドレミ2回 
            delay( 150 ) ; 
          }
        }
        for ( j = 0; j <= 2;  ++j ){ 
          for( i = 0; i <= 5; ++i ){
            tone( pin, Jr2[ i ], 150 ) ;  // ラミレドレミ2回
            delay( 150 ) ;  
          } 
        }  
        for( i = 0; i <= 25; ++i ){   //  ソミドシドミ 
          tone( pin, Jr3[ i ], 150 ) ; //  ミソドソドレミ
          delay( 150 ) ;                   //  ミドシソシド
        }                                         //  ドミソミソシド 
      }  
      else{ 
        for( i = 13; i <= 25; ++i ){ 
          tone( pin, Jr3[ i ], 150 ) ; 
          delay( 150 ) ;         //  ミドシソシド
        }                               //  ドミソミソシド
      } 
      forward( 115, 115, 130 ) ;   //直進  
    break ;  
   
    case 0x3F :  //下 
      motorStop( 100 ) ; 
      for( i= 0; i <= 3;  ++i ){ 
        tone( pin, 880, melo ) ; 
        delay( 1000 ) ; 
      } 
      back( 115, 115, 300 ) ;  
    break ; 
     
    case 0x5F :  //左    
      motorStop( 100 ) ;  
      left( 115, 115, 350 ) ;  
      R_And_L = false ;   // left 
      motorStop( 100 ) ; 
      //delay( 500 ) ;
      forward( 115, 115, 130 ) ;   //直進 
    break ; 
 
    case 0x5B :  //右 
      motorStop( 100 ) ;  
      right( 115, 115, 350 ) ; 
      R_And_L = true ;   // right 
      motorStop( 100 ) ; 
      //delay( 500 ) ; 
      forward( 115, 115, 130 ) ;   //直進 
    break ;
  
    case 0x1A :  //左右+
      motorStop( 100 ) ;  
      if( R_And_L == true ){
        right( 115, 115, 100 ) ; 
      }
      else{  
        left( 115, 115, 100 ) ;  
      }  
      motorStop( 100 ) ; 
      //delay( 500 ) ; 
      forward( 115, 115, 130 ) ;   //直進 
    break ; 
   
    case 0x1E :  //左右-   
      motorStop( 100 ) ;  
      if( R_And_L == true ){  
        left( 115, 115, 100 ) ;  
      } 
      else{  
        right( 115, 115, 100 ) ; 
      }
      motorStop( 100 ) ;  
      //delay( 500 ) ;  
      forward( 115, 115, 130 ) ;   //直進  
    break ;  
      
    case 0x3D :  //決定  
      motorStop( 100 ) ;  
    break ; 
     
    default : 
      ; 
    break ; 
 
  } 
  return retStat ;  
} 

void stop_back( int backtime ){ 
  motorStop( 80 ) ;  
  back(130, 130, backtime ) ; 
  motorStop( 80 ) ; 
} 

void forward( int Lduty, int Rduty, int keeptime ){ 
  analogWrite( L_PWM_Pin, Lduty ) ; 
  analogWrite( R_PWM_Pin, Rduty ) ; 
  digitalWrite( motorL1Pin, HIGH ) ; 
  digitalWrite( motorL2Pin, LOW ) ;  
  digitalWrite( motorR1Pin, HIGH ) ; 
  digitalWrite( motorR2Pin, LOW ) ;  
  delay( keeptime ) ; 
}  

void back( int Lduty, int Rduty, int keeptime ){ 
  analogWrite( L_PWM_Pin, Lduty ) ;  
  analogWrite( R_PWM_Pin, Rduty ) ;  
  digitalWrite( motorL1Pin, LOW ) ;
  digitalWrite( motorL2Pin, HIGH ) ;  
  digitalWrite( motorR1Pin, LOW ) ;   
  digitalWrite( motorR2Pin, HIGH ) ;  
  delay( keeptime ) ;  
} 
 
void left( int Lduty, int Rduty, int keeptime ){
  analogWrite( L_PWM_Pin, Lduty ) ; 
  analogWrite( R_PWM_Pin, Rduty ) ; 
  digitalWrite( motorL1Pin, HIGH ) ; 
  digitalWrite( motorL2Pin, LOW ) ;  
  digitalWrite( motorR1Pin, LOW ) ;   
  digitalWrite( motorR2Pin, HIGH ) ;  
  delay( keeptime ) ;  
}  

void right( int Lduty, int Rduty, int keeptime ){
  analogWrite( L_PWM_Pin, Lduty ) ; 
  analogWrite( R_PWM_Pin, Rduty ) ;  
  digitalWrite( motorL1Pin, LOW ) ;  
  digitalWrite( motorL2Pin, HIGH ) ; 
  digitalWrite( motorR1Pin, HIGH ) ;  
  digitalWrite( motorR2Pin, LOW ) ;  
  delay( keeptime ) ;  
}  

void motorStop( int keeptime ){ 
  digitalWrite( motorL1Pin, LOW ) ;  
  digitalWrite( motorL2Pin, LOW ) ; 
  digitalWrite( motorR1Pin, LOW ) ;  
  digitalWrite( motorR2Pin, LOW ) ;  
  delay( keeptime ) ;  
}  

void setup( ){ 
  Serial.begin( BAUDRATE ) ;
  Serial.println( "\nIr Recive - Read" ) ; 
  pinMode( DATAPIN, INPUT ) ;     // ピンモード設定
  pinMode( motorL1Pin, OUTPUT ) ; 
  pinMode( motorL2Pin, OUTPUT ) ; 
  pinMode( motorR1Pin, OUTPUT ) ; 
  pinMode( motorR2Pin, OUTPUT ) ;  
  pinMode( L_PWM_Pin, OUTPUT ) ;  
  pinMode( R_PWM_Pin, OUTPUT ) ; 
  R_And_L = false ; 
  Start = false ;  
}  

void loop( ){ 
  if( readIrData( ) ){  
    if( iRrepeatCoomand ){
      Serial.print( "Repeat " ) ;  
    }  
    Serial.print( "Addr:" ) ;   
    Serial.print( iRAddr, HEX ) ;  
    Serial.print("  Command:" ) ;  
    Serial.println( iRCommand,HEX ) ; 
  }  
  delay( 10 ) ;  
}