/**************************************************/     
//  FILE        WIFI時計 7Seg-LED   ** 時;**分;**秒   
//  DATE        :Tue, Jan 10, 2025                                    
//  DESCRIPTION : タイマー割り込みにて 制御。	                          
//  CPU TYPE    : ESP32                                               
//                                    by Chiyabo                      
//  chiya file is generated by Renesas Project Generator.              
/**************************************************/      
//                                                                    
#include < WiFi.h >
#include < time.h >

#define SI  32
#define SCK 33
#define RCK 25
#define SEL1 26
#define SEL2 27
#define SEL3 14

// 家のwifiのssidとパスワードを入力
const char* ssid = "YOUR_SSID";        			  // 各自のWifi環境のSSIDを指定する
const char* password = "YOUR_PASSWORD"; // 各自のWifi環境のPasswordを指定する

// NTPサーバー設定
const char* ntpServer = "ntp.nict.jp" ;  // 日本標準時(JST)
const long gmtOffset_sec = 9 * 3600 ;    // GMT+9(日本時間)
const int daylightOffset_sec = 0 ;       // サマータイム(日本は使用しない)

//timer 初期化
hw_timer_t * timer = NULL ; 

char TimeInEnCnt = 0 ; //WiFi_Time Read時間 時間*TimeInEnCnt = 時間間隔
char TimeInEn = true ; 
char TimeInEnEnd = false ;
char WiFi_TimeReadEnd ;
char ErrFlg = false ;
char Sec ;        // 秒
char Min ;        // 分
char Hor ;        // 時
char TxBuf[ 14 ] ; //TxBuf = 'yyyy/mm/dd/w' + 1 = 13(14)

int Sec_Change ;        
int Min_Change ;     
int Hor_Change ;     

unsigned int Timer_Adjust_10 = 625 ;  // 1000ms / 1.6ms = 625 
unsigned int Timer_Adjust_5 = 313 ; // 500ms / 1.6ms = 313 
unsigned int Timer_Up_Cnt_10 = 0 ;  // 1Sec=( 1.6ms * Timer_Up_Cnt_10(625) )
unsigned int Timer_Up_Cnt_5 = 0 ; // 0.5Sec=( 1.6ms * Timer_Up_Cnt_5(313) )

unsigned char Led_Sel = 0 ;
unsigned char Led_Dot = 0 ;
unsigned char Code ;       
unsigned char Disp_Off = false ;
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"
								                  } ;

//割込みサービスルーチン 1.6mSEc
void IRAM_ATTR LED_Task( ){
  // Disp Off
  digitalWrite( SEL1, HIGH ) ;
  digitalWrite( SEL2, HIGH ) ;
  digitalWrite( SEL3, HIGH ) ;
  if( WiFi_TimeReadEnd == true ){
    LED( ) ;
  }
  else{
    Disp_Off = true ;
  }
}

void setup( ){
  //Serial.begin( 115200 ) ;
  Serial2.begin( 9600, SERIAL_8N1, 16, 17 ) ; // 何故かPIN指定しないと動作せず?
  
  pinMode( SI, OUTPUT ) ;	
  pinMode( SCK, OUTPUT ) ;   
  pinMode( RCK, OUTPUT ) ;
  pinMode( SEL1, OUTPUT ) ; 
  pinMode( SEL2, OUTPUT ) ;
  pinMode( SEL3, OUTPUT ) ;	
   
  digitalWrite( SEL1, HIGH ) ;
  digitalWrite( SEL2, HIGH ) ;
  digitalWrite( SEL3, HIGH ) ;
  
  // 周波数を直接指定(ここでは1MHz = 1µsごとにカウントアップ)
  timer = timerBegin( 1000000 ) ;
  // 割り込み関数を登録
  timerAttachInterrupt( timer, &LED_Task ) ;
  // アラーム設定: 1600カウントごと(=1.6mSec)、繰り返し
  timerAlarm( timer, 1600, true, 0 ) ; // 第3引数をtrue指定で、繰り返し。その際は第4引数は無
  
  // WiFi接続 NTP時刻設定
  //WiFiTime( ) ;
}

void loop( ){
  // 現在時刻を表示
  if( ( TimeInEn == true ) || ( ErrFlg == true ) ){
    WiFi_TimeReadEnd = false ;
    if( Disp_Off == true ){
      TimeInEnEnd = true ;
      TimeInEn = false ;
      //Serial.println( "WiFi RETRAY" ) ;
      WiFiTime( ) ;
    }    
  }
}

void connectToWiFi( ){
  char RtyErr = 0 ;
  
  WiFi.begin( ssid, password ) ;
  //Serial.println( "WiFiに接続中" ) ;
  while( WiFi.status( ) != WL_CONNECTED ){
    delay( 1000 ) ;
    if( RtyErr >= 3 ){
      ErrFlg = true ;
      //Serial.println( "WiFi CONNECTED Err" ) ;
      WiFi.disconnect( true ) ;
      return;
    }
  }
  //Serial.println( "WiFi接続成功!" ) ;
}

bool getLocalTime( ){
  struct tm timeinfo ;
  return getLocalTime( &timeinfo ) ;
}

void printLocalTime( ){
  int Test ;
  struct tm timeinfo ;
  
  if ( !getLocalTime( &timeinfo ) ){
    // 時刻取得エラー
    ErrFlg = true ;
    //Serial.println( "WiFi TIME Err" ) ;
    WiFi.disconnect( true ) ;
    return ;
  }
  ErrFlg = false ;  
  
  // 時刻を整形して表示
  //Serial.printf( "%04d/%02d/%02d %d %02d:%02d:%02d\n ",
  //              timeinfo.tm_year + 1900,
  //              timeinfo.tm_mon + 1,
  //              timeinfo.tm_mday,
  //              timeinfo.tm_wday,    // 曜日 
  //              timeinfo.tm_hour,
  //              timeinfo.tm_min,
  //              timeinfo.tm_sec ) ;
  
  Serial2.print( timeinfo.tm_year + 1900 ) ;
  Serial2.print( '/' ) ;
  Serial2.print( timeinfo.tm_mon + 1 ) ;
  Serial2.print( '/' ) ;
  Serial2.print( timeinfo.tm_mday ) ;
  Serial2.print( ' ' ) ;
  Serial2.println( timeinfo.tm_wday ) ;
  
  Sec = ( char )timeinfo.tm_sec ;        // 秒
  Min = ( char )timeinfo.tm_min ;        // 分
  Hor = ( char )timeinfo.tm_hour ;       // 時
 
  Sec_Change = HexChgDec( Sec ) ;  
  Min_Change = HexChgDec( Min ) ; 
  Hor_Change = HexChgDec( Hor ) ;   
  
  //ESP32のWi-Fi切断
  WiFi.disconnect( true ) ;

  Timer_Up_Cnt_10 = 525 ; // 1Sec Adjust (1Sec = 625 )
  WiFi_TimeReadEnd = true ;
  Disp_Off = false ;
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
//	FunctionName : WiFi時刻取得					
//	Prototype: void WiFiTime( void )                
//	Function : WiFi時刻設定       					
//		Input    : NONE								        
//		Output   : NONE	    						
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>    
void WiFiTime( void ){
  
  connectToWiFi( ) ;
  
  // NTP時刻設定
  configTime( gmtOffset_sec, daylightOffset_sec, ntpServer ) ;
  // 時刻同期を待つ
  // NTPサーバーから時刻を取得中
  printLocalTime( ) ;
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
//	FunctionName : Led Write Task		
//		Prototype: void LED( void )                   				            
//		Function : LED DATA SET	& WRITE								                    
//		Input    : NONE								                                    
//		Output   : NONE	    									                            
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
void LED( void ){                                                                             
  unsigned char	Code ;													                      					              
  unsigned char	Change_Code ;                                                                 
                                                                      					              
  if( ++Led_Sel >= 6 ){									                              					              
    Led_Sel = 0 ;       								                              					              
  }																                                    					              
                                                                                              
  if( ++Timer_Up_Cnt_5 >= Timer_Adjust_5 ){ // 0.5Sec経過
    Led_Dot = !Led_Dot ;
    Timer_Up_Cnt_5 = 0 ;
  }
  if( ++Timer_Up_Cnt_10 >= Timer_Adjust_10 ){ // 1Sec経過
    Timer_Up_Cnt_10 = 0 ;
    if( ++Sec >= 60 ){ 
      Sec = 0 ;       
      if( TimeInEnEnd == true ){
        TimeInEnEnd = false ;
      }
      Sec_Change = HexChgDec( Sec ) ; // HEXをDEC値に変換する  
      if( ++Min >= 60 ){                  
        Min = 0 ;
        Min_Change = HexChgDec( Min ) ; // HEXをDEC値に変換する                         
        if( ++Hor >= 24 ){
          Hor = 0 ;                        
          Hor_Change = HexChgDec( Hor ) ;// HEXをDEC値に変換する
        }
        else{
          Hor_Change = HexChgDec( Hor ) ;// HEXをDEC値に変換する
        }
        if( ++TimeInEnCnt >= 6 ){
          TimeInEnCnt = 0 ;
          TimeInEn = true ;
          //WiFiTime( ) ;
        }
      }                       
      else{                    
        Min_Change = HexChgDec( Min ) ; // HEXをDEC値に変換する
      }
    }
    else{                                                                                   
        Sec_Change = HexChgDec( Sec ) ;                         HEXをDEC値に変換する    
    }                                                                                       
  }                                                                                                 
  
  switch( Led_Sel ){									                                					              
    case	0 :													                                					              
      Change_Code = ( char )( Sec_Change & 0x000f ) ;                                         
      Code = ~Led_Code[ Change_Code ] ;                               					              
      if( TimeInEnEnd == true ){                                                              
        if( Led_Dot == 0 ){                                            					              
          Code = ( Code & 0x7F ) ;                                    					                
        }                                                             					              
        else{                                                         					              
          Code = ( Code | 0x80 ) ;                                    					              
        }                                                             					              
      }                                                                                          
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, LOW ) ;                                                             
      digitalWrite( SEL2, LOW ) ;                                                             
      digitalWrite( SEL3, LOW ) ;                                                             
    break ;												                                    					              
                                                                      					              
    case	1:													                                					              
      Change_Code =( char )( ( Sec_Change & 0x00f0 ) >> 4 ) ;                                 
      Code = ~Led_Code[ Change_Code ] ;	                              					              
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, HIGH ) ;                                                            
      digitalWrite( SEL2, LOW ) ;                                                               
      digitalWrite( SEL3, LOW ) ;                                                             
    break ;		  										                                  					              
                                                                      					              
    case	2:													                                					              
      Change_Code =( char )( Min_Change & 0x000f ) ;                                          
      Code = ~Led_Code[ Change_Code ] ;                               					              
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, LOW ) ;                                                             
      digitalWrite( SEL2, HIGH ) ;                                                              
      digitalWrite( SEL3, LOW ) ;                                                             
    break ;				  								                                  					              
                                                                      					              
    case	3:													                                					              
      Change_Code =( char )(( Min_Change & 0x00f0 ) >> 4 ) ;                                  
      Code = ~Led_Code[ Change_Code ] ;	// Test                       					              
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, HIGH ) ;                                                            
      digitalWrite( SEL2, HIGH ) ;                                                              
      digitalWrite( SEL3, LOW ) ;                                                             
    break ;												                                    					              
                                                                      					              
    case	4:													                                					              
      Change_Code =( char )( Hor_Change & 0x000f ) ;                                          
      Code = ~Led_Code[ Change_Code ] ;                               					              
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, LOW ) ;                                                             
      digitalWrite( SEL2, LOW ) ;                                                               
      digitalWrite( SEL3, HIGH ) ;                                                            
    break ;												                                    					              
                                                                      					              
    case	5:													                                					              
      Change_Code =( char )(( Hor_Change & 0x00f0 ) >> 4 ) ;                                     
      Code = ~Led_Code[ Change_Code ] ;                               					              
      if( TimeInEnEnd == true ){                                                              
        if( Led_Dot == 0){                                            					              
          Code = ( Code & 0x7F ) ;                                    					                
        }                                                             					              
        else{                                                         					              
          Code = ( Code | 0x80 ) ;                                    					              
        }                                                             					              
      }         
      ShiftCode( Code ) ;                                                                       
      digitalWrite( SEL1, HIGH ) ;                                                            
      digitalWrite( SEL2, LOW ) ;                                                               
      digitalWrite( SEL3, HIGH ) ;                                                            
    break ;												                                    					              
                                                                      					              
    default:													                                					              
      // Disp Off                                                                             
      digitalWrite( SEL1, HIGH ) ;                                                            
      digitalWrite( SEL2, HIGH ) ;                                                            
      digitalWrite( SEL3, HIGH ) ;                                                             
    break ;												                                    					              
  }																                                    					              
}																	                                    					              
                                                                      					              
  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
  	FunctionName : ShiftCode Task									                      
  		Prototype: void ShiftCode( unsigned char )                        
  		Function : LED DATA SET	& WRITE								                    
  		Input    : NONE								                                    
  		Output   : NONE										                                
  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>    
void ShiftCode( unsigned char Code ){                                                         
  char  Count ;                                                                               
  unsigned char  Scode ;                                                                      
                                                                                              
  Scode = Code ;                                                                              
  for( Count = 0 ; Count <= 7 ; ++Count ){                                                    
    if( ( Scode & 0x80 ) == 0x80 ){                                                           
      digitalWrite( SI, HIGH ) ;                                                               
    }                                                                                         
    else{                                                                                     
      digitalWrite( SI, LOW ) ;                                                                
    }                                                                                           
    Scode = ( Scode << 1 ) ;                                                                    
    //delayMicroseconds( 5 ) ;                                                                 
    digitalWrite( SCK, HIGH ) ;                                                                
    //delayMicroseconds( 5 ) ;                                                                 
    digitalWrite( SCK, LOW ) ;                                                                 
    //delayMicroseconds( 5 ) ;                                                                 
  }                                                                                           
  digitalWrite( RCK, HIGH ) ;                                                                  
  //delayMicroseconds( 5 ) ;                                                                   
  digitalWrite( RCK, LOW ) ;                                                                   
}                                                                                             

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
//	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;										
}