/****************************************************/    
//    FILE        JJY-DENPA-TEST 電波時計                                  
//    DATE        :Tue, Jan 10, 2025                                      
//    DESCRIPTION : JJY模擬発生 試験            	                             
//    CPU TYPE    : Arduino UNO                                           
//                                      by Chiyabo                          
//    This file is generated by Renesas Project Generator.                
/****************************************************/    

#include < LiquidCrystal_I2C.h >         // ライブラリのインクルード                              
LiquidCrystal_I2C lcd( 0x27, 16 , 2 ) ;// 0x27のアドレス,16列2行のLCDを使用                     
                                                                                              
#define TEST_JJY 3													                          								        
#define EXT_INT 2                                                                             
#define MAKER 0   										                                								        
#define OUTPUT_1 1	//'1'								                          								        
#define OUTPUT_2 2      //'0'										                      								        
                                                                                              
#define Timer_Cnt0 63   	// Timer-Int(2) * 800us * Timer_Cnt1 = 100ms                         
#define Timer_Cnt1 225   // Timer-Int(2) * 800us * Timer_Cnt1 = 360ms                         
#define Timer_Cnt2 287   // Timer-Int(2) * 800us * Timer_Cnt2 = 460ms                         
#define Timer_Cnt3 350   // Timer-Int(2) * 800us * Timer_Cnt3 = 560ms                         
#define Timer_Cnt4 413   // Timer-Int(2) * 800us * Timer_Cnt4 = 660ms                         
//#define JJY_TEST_MODE  // 模擬電波 D3からOutPut                                             
#define Timer_Adjust 625 // 1000ms / 1.6ms = 625                                                  


// 電波発生 定義
unsigned int Out_Maker_Cnt = 0 ;
unsigned char OutPut_End = false ;
unsigned char OutPutNomber = 0 ;
unsigned char OutBitFlg = false ;
// 0:Maker 1:H 2:L
const unsigned char OutPutSel[ ] = { 0, 0, 
                                     2, 2, 1, 2, 2, 1, 2, 1, 0, //15分
                                     2, 2, 2, 1, 2, 2, 1, 1, 1  //17時
                                    } ;


//  JJY 電波取り込み
volatile byte Ext_Int_En = true ;  // 外部割込み 開始                                         
volatile byte Ext_Int_Act = false ; // 外部割り込み有                                          
char JJY_Read_Start = false ;                                                                 
char Maker_Chk = 0 ;  // マーカーの0の数                                                       
char Maker_Cnt = 0 ;  // マーカーの0の数が連続4回で’1’セット
								 //マーカー2回読み込み                 
char Level_H_Cnt = 0 ;                                                                        
char Retray = false ;
char Old_hor ;
unsigned char Read_Cnt = 0 ;                                                                  
unsigned char Read_Min = 0 ;                                                                  
unsigned char Read_Hor = 0 ;                                                                  
unsigned int Level_Check_Cnt = 0 ;                                                            

// LED-Display
char sec = 0 ;              // 秒                     
char min = 59 ;          //  分                     
char hor = 23 ;           //  時                     
char SetMinHor = false ;                                                                      
int Sec_Change = 0 ;                                                                          
int Min_Change = 0x59 ;                                                                       
int Hor_Change = 0x23 ;                                                                       
                                                                                              
// Timer INT                                                                    
unsigned int Timer_Cnt = 0 ;    // Timer-Int(2) * 800us = 1.6ms                               
                                                                                              
void setup( ){														                            								        
  //Serial.begin( 9600 ) ;                                                                    
  //Serial.println( "\n Denpa_Tokei Test" ) ;                                                 
                                                                                              
  lcd.init( ) ;                       // LCDの初期化                                          
  lcd.backlight( ) ;             // LCDバックライトの点灯                                  
  lcd.setCursor( 0, 0 ) ;     // カーソルの位置を指定                                   
  lcd.print( "JJY_Tokei Test" ) ;	// カスタムコード(HEX)                                 
  pinMode( TEST_JJY, OUTPUT ) ;										                    								        
  pinMode( EXT_INT,INPUT );  //割り込み番号0用の入力ピン                                        
                                                                                              
  // タイマー割り込み設定                                                                     
  TCCR1A = 0; // タイマー1動作モードを初期化                                                    
  TCCR1B = ( 1 << WGM12 ) | ( 1 << CS11 ) ; // CTCモード 分周比1/8      WGM12 = CS11 = 1       
  OCR1A = 1600 - 1 ; // 800μsとなるように設定                                                  
  TIMSK1 = ( 1 << OCIE1A ) ; // タイマー1のAマッチ割り込みを許可          OCIE1A = 1            
                                                                                              
  // 外部割り込み設定                                                                         
  attachInterrupt(digitalPinToInterrupt( EXT_INT ), JJY_TCO, RISING ) ;   立ち上がり割り込み    
  // 割り込み処理関数 :JJY_TCO                                                               
}																	                                    								        																

const unsigned char Led_Code[ ] = {0x5f,0x50,0x6d,0x79,0x72,0x3b,0x3f,	// "0"~"6"
								                  0x51,0x7f,0x73,0x77,0x3e,0x0f,0x7c,		// "7"~"d"
								                  0x2f,0x27								              // "e"~"f"
								                  } ;
															                                    								        

void loop( ){														                              								        
  if( Timer_Cnt == 0 ){                                                                       
    Timer_Cnt = 2 ; // 800us*2=1.6ms 625Hz                                                    
    JJY_TCO_READ( ) ;                                                                         
    #ifdef	JJY_TEST_MODE                         										  							          
		  if( Ext_Int_En == true ){
        // 模擬JJY発生Pro
        if( OutPut_End == true){
          if( ++OutPutNomber >= 20 ){  ; 
            Serial.println( "\n JJY-OutPut Retry" ) ; 
            OutPutNomber = 0 ;
          }
          OutPut_End = false ; 
          Out_Maker_Cnt = 0 ;
        }
        if( OutBitFlg == false ){
          OutBitFlg = true ;
          Serial.println( OutPutSel[ OutPutNomber ], DEC ) ;
        }
        Denpa( OutPutSel[ OutPutNomber ] ) ;    
      }
    #endif		 													                                                                  
  } 
}                                                                                                   
                                                                                              
// TIMER割込みサービスルーチン                                                                  
ISR( TIMER1_COMPA_vect ){                                                                     
  if( Timer_Cnt > 0 ){                                                                        
    --Timer_Cnt ;                                                                             
  }                                                                                            
}                                                                                             
                                                                                              
//  外部割込みサービスルーチン                                                                  
void JJY_TCO( ){                                                                              
  char i ;                                                                                    
  char j = 0 ;                                                                                
                                                                                              
  if(  Ext_Int_En == true ){                                                                  
    for( i = 0 ; i < 10 ; i++ ){
      if( digitalRead( EXT_INT ) == 1 ){                                                      
        j++ ;                                                                                     
      }                                                                                         
      else{
        j = 0 ;                                                                               
      }
    } 
    if( j >= 10 ){
      Ext_Int_Act = true ;                                                                    
    } 
  }                                                                                           
}                                                                                             
                                                                                               
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/    
  	FunctionName : DENPA TEST Task								                      
  		Prototype: void Denpa( unsigned char )                            
  		Function : LED DATA SET	& WRITE								                    
  		Input    : JJY_SEL								                                
  		Output   : NONE										                                
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/    
void Denpa( unsigned char JJY_SEL ){                                                          
  
  ++Out_Maker_Cnt ; 

  switch( JJY_SEL ){
      case	MAKER :	
          if( Out_Maker_Cnt <= 125 ){
            digitalWrite( TEST_JJY, HIGH ) ; 
          }
          if( Out_Maker_Cnt >= 126 ){
            digitalWrite( TEST_JJY, LOW ) ; 
          }
      break ;	
        
      case	OUTPUT_1:	  //'1' 
          if( Out_Maker_Cnt <= 312 ){ 
            digitalWrite( TEST_JJY, HIGH ) ; 
          }
          if( Out_Maker_Cnt >= 313 ){
            digitalWrite( TEST_JJY, LOW ) ; 
          }
      break ;
        
      case	OUTPUT_2:	  //'0'
          if( Out_Maker_Cnt <= 500 ){
            digitalWrite( TEST_JJY, HIGH ) ; 
          }
          if( Out_Maker_Cnt >= 501 ){
              digitalWrite( TEST_JJY, LOW ) ; 
          }
      break ;
      
      default:
            ;
      break ;	
  }	
  if( Out_Maker_Cnt >= Timer_Adjust ){ // !sec経過
    OutPut_End = true ; 
    Out_Maker_Cnt = 0 ;
    OutBitFlg = false ;
    //Serial.println( JJY_SEL, DEC ) ;
  }
}


/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/    
  	FunctionName : JJY_TCO READ Task							                      
  		Prototype: void JJY_TCO_READ( void )           				            
  		Function : 電波受信処理          							                     
  		Input    : NONE								                                    
  		Output   : NONE	    									                            
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/    
void JJY_TCO_READ( void ){                                                                        
  char Set_Min = 0 ;                                                                          
  char Set_Hor = 0 ;                                                                          
                                                                                                
  if( ( Ext_Int_En == true ) && ( Ext_Int_Act == true ) ){                                                          
    // Maker Read Stage1                                                                      
    if( JJY_Read_Start == false ){                                                            
      if( ++Level_Check_Cnt == Timer_Cnt0 ){ // 0.1Sec                                        
        if( digitalRead( EXT_INT ) == 1 ){                                                    
          ++Maker_Chk ;                                                                       
        }                                                                                     
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }                                                                                         
      if( Level_Check_Cnt == Timer_Cnt1 ){ // 0.36Sec                                         
        if( digitalRead( EXT_INT ) == 0 ){                                                    
          ++Maker_Chk ;                                                                       
        }                                                                                     
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }                                                                                       
      if( Level_Check_Cnt == Timer_Cnt2 ){ // 0.46Sec                                         
        if( digitalRead( EXT_INT ) == 0 ){                                                    
          ++Maker_Chk ;                                                                       
        }                                                                                     
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }                                                                                       
      if( Level_Check_Cnt == Timer_Cnt3 ){ // 0.56Sec                                         
        if( digitalRead( EXT_INT ) == 0 ){                                                    
          ++Maker_Chk ;                                                                       
        }                                                                                     
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }                                                                                       
      if( Level_Check_Cnt == Timer_Cnt4 ){ // 0.66Sec                                         
        if( digitalRead( EXT_INT ) == 0 ){                                                    
          if( ( ++Maker_Chk == 5 ) && ( Maker_Cnt == 0 ) ){                                   
            ++Maker_Cnt ; // マーカー2回目読み込み要求                                         
            Level_Check_Cnt = 0 ;
            Ext_Int_Act = false ;     
            Maker_Chk = 0 ;
            lcd.setCursor( 0, 0 ) ;               // カーソルの位置を指定                                   
            lcd.print( "Maker_Set1      " ) ;     // カスタムコード(HEX)                                 
            lcd.setCursor( 0, 1 ) ;               // カーソルの位置を指定                                   
            lcd.print( "                " ) ;     // カスタムコード(HEX)                                  
            //Serial.println( "Maker_Set1 " ) ;                                    
          }                                                                                   
          else if( ( Maker_Chk == 5 ) && ( Maker_Cnt == 1 ) ){                                
            Maker_Cnt = 0 ; // マーカー2回目読み込みリセット                                    
            Maker_Chk = 0 ;
            JJY_Read_Start = true ;                                                           
            lcd.setCursor( 0, 0 ) ;               // カーソルの位置を指定                                   
            lcd.print( "Maker_Read_Start" ) ;     // カスタムコード(HEX)                                 
            //Serial.println( "Maker_Set2 JJY_Read_Start" ) ;                                    
            Level_Check_Cnt = 0 ;
            Ext_Int_Act = false ;     
          }                                                                                   
          else{                                                                               
            Retray = true ;                                                                    
          }                                                                                   
        }                                                                                      
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }  
      if( Retray == true ){                                                                   
        //Serial.println( " Retray Maker" ) ;
        JJY_Read_Start = false ;
        Retray = false ;                                                                         
        Ext_Int_Act = false ;     
        Maker_Chk = 0 ;                                                                            
        Maker_Cnt = 0 ;   
        Level_Check_Cnt = 0 ;
      }
    }                                                                                         
    // JJY_Read_Start == true 
    else{                                                                                     
      if( ++Level_Check_Cnt == Timer_Cnt0 ){ // 0.1Sec                                        
        if( digitalRead( EXT_INT ) == 1 ){                                                    
          ++Level_H_Cnt ;                                                                                                                                            
        }                                                                                     
        else{                                                                                 
          Retray = true ;                                                                     
        }                                                                                     
      }                  
      if( Level_Check_Cnt == Timer_Cnt1 ){ // 0.36Sec                                         
        if( digitalRead( EXT_INT ) == 1 ){                                                    
          ++Level_H_Cnt ;                                                                     
        }                                                                                     
      }  
      if( Level_Check_Cnt == Timer_Cnt2 ){ // 0.46Sec                                         
        if( digitalRead( EXT_INT ) == 1  ){                                                   
          ++Level_H_Cnt ;                                                                     
        }                                                                                     
      }    
      if( Level_Check_Cnt == Timer_Cnt3 ){ // 0.56Sec                                         
        if( digitalRead( EXT_INT ) == 1  ){                                                   
          ++Level_H_Cnt ;                                                                     
        }                                                                                     
      }      
      if( Level_Check_Cnt == Timer_Cnt4 ){ // 0.66Sec                                         
        if( digitalRead( EXT_INT ) == 1  ){                                                   
          ++Level_H_Cnt ;                                                                     
        }                                                                                     
        // 信号確認
        if( ( Level_H_Cnt == 5 ) && ( Read_Cnt <= 8 ) ){
          Read_Min = ( Read_Min & 0xfe ) ;  
        }
        else if( ( Level_H_Cnt == 5 ) && ( Read_Cnt >= 12 ) ){
          Read_Hor = ( Read_Hor & 0xfe ) ; 
        } 
        if( ( Level_H_Cnt == 3 ) && ( Read_Cnt <= 8 ) ){
          Read_Min = ( Read_Min | 0x01 ) ; 
        }    
        else if( ( Level_H_Cnt == 3 ) && ( Read_Cnt >= 12 ) ){
          Read_Hor = ( Read_Hor | 0x01 ) ; 
        } 
        if( Read_Cnt != 8 ){
          //if( ( Level_H_Cnt != 3 ) && ( Level_H_Cnt != 5 ) ){
          if( Level_H_Cnt < 3 ){
            lcd.setCursor( 0, 0 ) ;               // カーソルの位置を指定                                   
            lcd.print( "Retry_Data_NG   " ) ;     // カスタムコード(HEX)                                 
            //Serial.println( "Retry_Data_NG" ) ;
            Retray = true ;                                                                        
          }
        }
        Level_H_Cnt = 0 ;
        
        if( Retray == false ){
          if( ++Read_Cnt <= 7 ){                                                                
            Read_Min = ( Read_Min << 1 ) ;                                                      
          }  
          lcd.setCursor( 0, 0 ) ;               // カーソルの位置を指定                                   
          lcd.print( "Read_Cnt        " ) ;     // カスタムコード(HEX)                                 
          lcd.setCursor( 0, 1 ) ;               // カーソルの位置を指定                                   
          lcd.print( "                " ) ;  
          lcd.setCursor( 0, 1 ) ;               // カーソルの位置を指定                                   
          lcd.print( Read_Cnt, DEC    ) ;     // カスタムコード(HEX)                                 
          
          //Serial.println( "Read_Cnt" ) ;                                                  
          //Serial.println( Read_Cnt, DEC ) ;                    
          
          if( ( Read_Cnt >= 12 ) && ( Read_Cnt <= 17 ) ){                                          
            // 信号確認
            Read_Hor = ( Read_Hor << 1 ) ;                                                    
          }                                                                                   
          if( Read_Cnt == 18 ){                                                               
            //lcd.setCursor( 0, 0 ) ;               // カーソルの位置を指定                                   
            //lcd.print( "JJY_Read_Hor    " ) ;     // カスタムコード(HEX)                                 
            //lcd.setCursor( 0, 1 ) ;               // カーソルの位置を指定                                   
            //lcd.print( Read_Hor, BIN ) ;     // カスタムコード(HEX)                                 
            //Serial.println( " JJY_Read_Hor:" ) ; 
            //Serial.println( Read_Hor, BIN ) ;                                                 
            // 取得時間の計算                                                                  
            Set_Min = Set_Min + ( bitRead( Read_Min, 7 ) * 40 ) ;                             
            Set_Min = Set_Min + ( bitRead( Read_Min, 6 ) * 20 ) ;                             
            Set_Min = Set_Min + ( bitRead( Read_Min, 5 ) * 10 ) ;                             
            Set_Min = Set_Min + ( bitRead( Read_Min, 3 ) * 8 ) ;                              
            Set_Min = Set_Min + ( bitRead( Read_Min, 2 ) * 4 ) ;                              
            Set_Min = Set_Min + ( bitRead( Read_Min, 1 ) * 2 ) ;                              
            Set_Min = Set_Min + ( bitRead( Read_Min, 0 ) * 1 ) ;                              
                                                                                                
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 6 ) * 20 ) ;                              
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 5 ) * 10 ) ;                                   
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 3 ) * 8 ) ;                               
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 2 ) * 4 ) ;                               
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 1 ) * 2 ) ;                               
            Set_Hor = Set_Hor +( bitRead( Read_Hor, 0 ) * 1 ) ;                               
                                                                                                
            //Serial.println( Set_Min, DEC ) ;                                                  
            //Serial.println( Set_Hor, DEC ) ;                                                  
                   
            sec = 20 ;                                                                         
            if(  ( Set_Min <= 59 ) && ( Set_Hor <= 23 ) ){   // 時分確定                
              min = Set_Min ;                                                                   
              Min_Change = HexChgDec( min ) ;            // HEXをDEC値に変換する    
                                                                                              
              if( Old_hor == Set_Hor ){
                hor = Set_Hor ;                                                               
                Hor_Change = HexChgDec( hor ) ;           // HEXをDEC値に変換する    
                Ext_Int_En = false ;                                                           
                lcd.setCursor( 0, 0 ) ;               	// カーソルの位置を指定                                   
                lcd.print( "Good-End        " ) ;     // カスタムコード(HEX)                                 
                lcd.setCursor( 0, 1 ) ;               	// カーソルの位置を指定                                      
                lcd.print( "                " ) ;  
                lcd.setCursor( 0, 1 ) ;               	// カーソルの位置を指定                                      
                lcd.print( Set_Hor, DEC ) ;  
                lcd.setCursor( 3, 1 ) ;               	// カーソルの位置を指定                                      
                lcd.print( Set_Min, DEC ) ;  
                //Serial.println( " Good-End" ) ; 
                JJY_Read_Start = false ;                                                                 
              }
              else{
                Old_hor = Set_Hor ;                                   
                //Serial.println( " OutPut Retry_Old_Hor2" ) ;
                JJY_Read_Start = false ;
                Level_Check_Cnt = 0 ;
                Read_Min = 0 ;                                                                 
                Read_Hor = 0 ;                                                                 
                Read_Cnt = 0 ;
              }
            }
            else{
              Retray = true ;                                                                          
            }
          }
        }        
        Ext_Int_Act = false ;     
        Level_Check_Cnt = 0 ;
      }
      if( Retray == true ){                                                                   
        //Serial.println( " Retray Hor-Min" ) ;
        Retray = false ;                                                                         
        Ext_Int_Act = false ;     
        Level_Check_Cnt = 0 ;
        Level_H_Cnt = 0 ; 
        JJY_Read_Start = false ;                                                              
        Maker_Chk = 0 ;
        Read_Min = 0 ;                                                                 
        Read_Hor = 0 ;                                                                 
        Read_Cnt = 0 ;
      }  
    }  
  }
}                                                                                          

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
//	FunctionName : HexChgDec								
//		Prototype: int HexChgDec(unsigned char HexByte)
//		Function : HEXをDEC値に変換する								 
//		Input    : 00h-->ffh										
//    Output   : 変換結果											 
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
int HexChgDec( unsigned char HexByte ){
	unsigned char i ;										
	int Value , Work ;									
  
	i = 0 ;
	Value = Work = 0 ;
	for( Work = 0 ; HexByte >= 0x0a ; Work++ ){
		HexByte = ( HexByte - 0x0a ) ;
	}																
	if( Work >= 0x0a ){							
		for( i = 0 ;  Work >= 0x0a ; i++ ){
			Work = ( Work - 0x0a ) ;						
		}															
	}																
	Value = ( ( i * 0x100 ) + ( Work * 0x10 ) + ( int )HexByte ) ;
	return Value;										
}