/****************************************************/  
//  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 Sec ;        // 秒
char Min ;        // 分
char Hor ;        // 時

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 ;       

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( ){
  LED( ) ;
}

void setup( ){
  //Serial.begin( 115200 ) ;
   
  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 ){
    TimeInEn = false ;
    WiFiTime( ) ;    
  }
}

void connectToWiFi( ){
  WiFi.begin( ssid, password ) ;
  //Serial.println( "WiFiに接続中" ) ;
    
  while( WiFi.status( ) != WL_CONNECTED ){
    delay( 500 ) ;
    //Serial.print( "WiFi?." ) ;
  }
  //Serial.println( ) ;
  //Serial.println( "WiFi接続成功!" ) ;
  //Serial.print( "IPアドレス: " ) ;
  //Serial.println( WiFi.localIP( ) ) ;
}

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

void printLocalTime( ){
  struct tm timeinfo ;
  if ( !getLocalTime( &timeinfo ) ){
    //Serial.println( "時刻取得エラー" ) ;
    return;
  }
  // 時刻を整形して表示
  //Serial.printf( "現在時刻: %04d/%02d/%02d %02d:%02d:%02d\n",
  //              timeinfo.tm_year + 1900,
  //              timeinfo.tm_mon + 1,
  //              timeinfo.tm_mday,
  //              timeinfo.tm_hour,
  //              timeinfo.tm_min,
  //              timeinfo.tm_sec ) ;
  
  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 ) ;
  //Serial.println( "Wi-Fi切断" ) ;
}

/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/  
//	FunctionName : WiFi時刻取得									                      
//		Prototype: void WiFiTime( void )                   				     
//		Function : WiFi時刻設定       								                  
//		Input    : NONE								                                  
//		Output   : NONE	    									                          
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/  
void WiFiTime( void ){
  
  connectToWiFi( ) ;
  
  // NTP時刻設定
  configTime( gmtOffset_sec, daylightOffset_sec, ntpServer ) ;
  
  // 時刻同期を待つ
  //Serial.println("NTPサーバーから時刻を取得中...") ;
  
  while ( !getLocalTime( ) ){
    //Serial.println( "時刻取得に失敗しました。再試行中..." ) ;
    delay( 100 ) ;
  }
  //Serial.println( "時刻取得完了!" ) ;
  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 ;                     
                                                            
  // Disp Off                                                
  digitalWrite( SEL1, HIGH ) ;                    
  digitalWrite( SEL2, HIGH ) ;                         
  digitalWrite( SEL3, HIGH ) ;                         
                                                          
  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 ;       
      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 >= 2 ){
          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( TimeInEn == true ){                                                
        if( Led_Dot == 1){                                              
          Code = ( Code | 0x80 ) ;                                
        }                                                           
        else{                                                       
          Code = ( Code & 0x7F ) ;                   
        }                                                            
      }                                                                    
      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 ] ;                 
      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;										
}