// Returns 1 (BIT_SET) if time is not older than the DCF_ACCEPTED_AGE_IN_HOURS BitAction DcfTimeWasSetRecently( void ){ RTC_t currentTime = UB_RTC_GetClock(RTC_DEC); int timeDifferenceInHours = currentTime.std - gLastSuccessfulDcfRxTime.std; int timeDifferenceInDays = currentTime.tag - gLastSuccessfulDcfRxTime.tag; if ( timeDifferenceInDays < 0 ){ switch ( gLastSuccessfulDcfRxTime.monat ) { case 2: // Februar timeDifferenceInDays += 28; break; case 4: // April timeDifferenceInDays += 30; break; case 6: // Juni timeDifferenceInDays += 30; break; case 9: // September timeDifferenceInDays += 30; break; case 11:// November timeDifferenceInDays += 30; break; default:// Rest timeDifferenceInDays += 31; break; } } timeDifferenceInHours += timeDifferenceInDays * 24; if ( timeDifferenceInHours < DCF_ACCEPTED_AGE_IN_HOURS ) return Bit_SET; return Bit_RESET; }
void WC_OneMinute_ISR() { if( WC_OneMinute_ISR_Count >= 1 ) { WC_OneMinute_ISR_Count = 0; // Get time to UB_RTC global and use it to set the matrix if ( gDcfRxWasSuccesful == Bit_SET ) { SetWordMatrix( UB_RTC_GetClock(RTC_DEC) ); gWcIsToBeRefreshed = Bit_SET; } else if( Esp8266_curTime.status == RTC_TIME_OK ) { SetWordMatrix( UB_RTC_GetClock(RTC_DEC) ); gWcIsToBeRefreshed = Bit_SET; } } else { WC_OneMinute_ISR_Count++; } }
void GetRTCTime ( ) { if( xSemaphoreTake ( xCDCSemaphore, ( portTickType ) 10 ) == pdTRUE ) { UB_RTC_GetClock(RTC_DEC); printf ( "%02d.%02d.%02d %02d:%02d:%02d\r\n", UB_RTC.tag, UB_RTC.monat, UB_RTC.jahr, UB_RTC.std, UB_RTC.min, UB_RTC.sek ); xSemaphoreGive( xCDCSemaphore ); }; };
void SendTimeToLCD ( struct ALCDMessage *pxLCDMessage ) { if ( 0 != xLCDQueue ) { UB_RTC_GetClock(RTC_DEC); pxLCDMessage->ucX = 0; pxLCDMessage->ucY = 8; sprintf ( pxLCDMessage->ucData, "%02d:%02d:%02d", UB_RTC.std, UB_RTC.min, UB_RTC.sek ); xQueueSendToBack ( xLCDQueue, ( void * ) &pxLCDMessage, ( portTickType ) 0 ); }; };
//#################################################################################################### //################################## FUNCTIONS IMPLEMENTATION ######################################## //#################################################################################################### // Function that uses a received IR command to do stuff void ProcessIrDataPacket( IRMP_DATA irPacket ){ // Process packet only if it came from the right remote if ( irAddressFirstSeen == -1 ) irAddressFirstSeen = irPacket.address; else if ( irAddressFirstSeen != irPacket.address ) return; switch ( irPacket.command ) { // Commands case IR_REMOTE_KEY_BRIGHTNESS_INC: AdjustBrightnessArray( 1, ambientBrightnessCurrent, ambientBrightnessLedDimmingFactors ); break; case IR_REMOTE_KEY_BRIGHTNESS_DEC: AdjustBrightnessArray( 0, ambientBrightnessCurrent, ambientBrightnessLedDimmingFactors ); break; case IR_REMOTE_KEY_OFF: gCurrentMatrixColor = WC_GetColor(); WC_SetColor(WS2812_HSV_COL_OFF); break; case IR_REMOTE_KEY_ON: WC_SetColor(gCurrentMatrixColor); break; // case IR_REMOTE_KEY_FLASH: // // break; // case IR_REMOTE_KEY_STROBE: // // break; // case IR_REMOTE_KEY_FADE: // // break; #ifdef ENABLE_TESTMODE case IR_REMOTE_KEY_SMOOTH: UB_RTC = UB_RTC_GetClock( RTC_DEC ); UB_RTC.min = ( UB_RTC.min + 3 ) % 60; UB_RTC.std = ( UB_RTC.std + 1 ) % 24; UB_RTC_SetClock( RTC_DEC ); break; #endif // Basic colors case IR_REMOTE_KEY_RED: WC_SetColor(WS2812_HSV_COL_RED); break; case IR_REMOTE_KEY_GREEN: WC_SetColor(WS2812_HSV_COL_GREEN); break; case IR_REMOTE_KEY_BLUE: WC_SetColor(WS2812_HSV_COL_BLUE); break; case IR_REMOTE_KEY_WHITE: WC_SetColor(WS2812_HSV_COL_WHITE); break; // Other colors case IR_REMOTE_KEY_ORANGE: WC_SetColor(WS2812_HSV_COL_ORANGE); break; case IR_REMOTE_KEY_LIGHTORANGE: WC_SetColor(WS2812_HSV_COL_LIGHTORANGE); break; case IR_REMOTE_KEY_DARKYELLOW: WC_SetColor(WS2812_HSV_COL_DARKYELLLOW); break; case IR_REMOTE_KEY_YELLOW: WC_SetColor(WS2812_HSV_COL_YELLOW); break; case IR_REMOTE_KEY_LIGHTGREEN: WC_SetColor(WS2812_HSV_COL_LIGHTGREEN); break; case IR_REMOTE_KEY_LIGHTGREENBLUE: WC_SetColor(WS2812_HSV_COL_LIGHTGREENBLUE); break; case IR_REMOTE_KEY_CYAN: WC_SetColor(WS2812_HSV_COL_CYAN); break; case IR_REMOTE_KEY_DARKGREENBLUE: WC_SetColor(WS2812_HSV_COL_DARKGREENBLUE); break; case IR_REMOTE_KEY_DARKBLUE: WC_SetColor(WS2812_HSV_COL_DARKBLUE); break; case IR_REMOTE_KEY_PURPLE: WC_SetColor(WS2812_HSV_COL_PURPLE); break; case IR_REMOTE_KEY_PINK: WC_SetColor(WS2812_HSV_COL_PINK); break; case IR_REMOTE_KEY_DARKPINK: WC_SetColor(WS2812_HSV_COL_DARKPINK); break; } // Save current color if ( irPacket.command != IR_REMOTE_KEY_OFF ) gCurrentMatrixColor = WC_GetColor(); }
//-------------------------------------------------------------- // Init und Start der RTC // Return Wert : // -> RTC_UNDEFINED = RTC war noch nicht initialisiert // -> RTC_INIT_OK = RTC war schon initialisiert // (aber noch nicht eingestellt) // -> RTC_TIME_OK = RTC war schon eingestellt //-------------------------------------------------------------- RTC_STATUS_t UB_RTC_Init(void) { RTC_STATUS_t ret_wert=RTC_UNDEFINED; uint32_t status; // Clock enable fuer PWR RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Zugriff auf RTC freigeben PWR_BackupAccessCmd(ENABLE); // Test vom Status-Register status=RTC_ReadBackupRegister(RTC_STATUS_REG); if(status==RTC_STATUS_TIME_OK) { // wenn Uhrzeit schon eingestellt ist ret_wert=RTC_TIME_OK; UB_RTC.status=RTC_TIME_OK; // warte bis synconisiert RTC_WaitForSynchro(); #if RTC_USE_WAKEUP_ISR==1 RTC_ClearITPendingBit(RTC_IT_WUT); EXTI_ClearITPendingBit(EXTI_Line22); #endif // RTC auslesen UB_RTC_GetClock(RTC_DEC); } else if(status==RTC_STATUS_INIT_OK) { // wenn RTC schon initialisiert ist ret_wert=RTC_INIT_OK; UB_RTC.status=RTC_INIT_OK; // warte bis synconisiert RTC_WaitForSynchro(); #if RTC_USE_WAKEUP_ISR==1 RTC_ClearITPendingBit(RTC_IT_WUT); EXTI_ClearITPendingBit(EXTI_Line22); #endif // RTC auslesen UB_RTC_GetClock(RTC_DEC); } else { // wenn RTC noch nicht initialisiert ist ret_wert=RTC_UNDEFINED; UB_RTC.status=RTC_UNDEFINED; // RTC Konfig und start P_RTC_Config(); // RTC zuruecksetzen auf (0:00:00 / 1.1.00) UB_RTC.std=0; UB_RTC.min=0; UB_RTC.sek=0; UB_RTC.tag=1; UB_RTC.monat=1; UB_RTC.jahr=0; UB_RTC.wotag=1; UB_RTC_SetClock(RTC_DEC); UB_RTC.status=RTC_INIT_OK; } return(ret_wert); }
int main(void) { RTC_STATUS_t check; uint8_t old_sek=0; char buf[APP_TX_BUF_SIZE]; // puffer fuer Datenempfang SystemInit(); // Quarz Einstellungen aktivieren // Init der LEDs UB_Led_Init(); // Init der Buttons UB_Button_Init ( ); // Init und start der RTC check=UB_RTC_Init(); if(check==RTC_UNDEFINED) { // RTC war noch nie initialisiert UB_Led_On(LED_RED); } else { // RTC war schon initialisiert UB_Led_On(LED_GREEN); } // Init vom USB-OTG-Port als CDC-Device // (Virtueller-ComPort) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * die nächste Zeile auskommentieren, * dann funktioniert das Zurücksetzen * des RTC */ UB_USB_CDC_Init(); while ( 1 ) { // wenn Button gedrückt -> RTC zurücksetzen if ( UB_Button_Read ( BTN_USER ) ) { // orange LED ein UB_Led_On ( LED_ORANGE ); // RTC zurücksetzen ResetRTC ( ); // warten bis Button gelöst while ( UB_Button_Read ( BTN_USER ) ); // die LED noch ein Weilchen an lassen Delay ( 10000000 ); UB_Led_Off ( LED_ORANGE ); } // aktuelle RTC-Zeit auslesen UB_RTC_GetClock(RTC_DEC); if(UB_RTC.sek!=old_sek) { // wenn eine Sekunde um ist old_sek=UB_RTC.sek; UB_Led_Toggle(LED_BLUE); // aktuelle Zeit als String formatieren sprintf ( buf, "%02d.%02d.%02d %02d:%02d:%02d", UB_RTC.tag, UB_RTC.monat, UB_RTC.jahr, UB_RTC.std, UB_RTC.min, UB_RTC.sek ); // an Semihosting senden printf ( "%s\r\n", buf ); // Test ob USB-Verbindung zum PC besteht if(UB_USB_CDC_GetStatus()==USB_CDC_CONNECTED) { // an PC senden UB_USB_CDC_SendString ( buf, LFCR ); } } } }
/***************************************** * MAIN *****************************************/ int main(void) { SystemInit(); UB_Systick_Init(); // Init of UB libs UB_TIMER2_Init_FRQ( 100 ); UB_TIMER5_Init_FRQ( 10000 ); UB_Led_Init(); UB_DigIn_Init(); UB_DigOut_Init(); UB_ADC1_SINGLE_Init(); UB_RTC_Init(); UB_RTC_SetWakeUpInterrupt(RTC_WAKEUP_5s); // Note: code needs to be reconfigured for Nucleo Board (Frequency of 96 MHz should also be checked) UB_WS2812_Init(); WC_DisableAllElements(); WC_SetColor( WS2812_HSV_COL_WHITE ); WC_SetBrightness( 10 ); WC_SetElement(WC_ELEMENT_ES, 1); WC_Refresh(); UB_Uart_Init(); esp8266_init(); UB_Systick_Pause_ms(1000); // Indicate successful booting UB_Led_On( LED_GREEN ); UB_Systick_Pause_s(1); UB_Led_Off( LED_GREEN ); // Start timers and therefore cyclic actions in the call backs below UB_TIMER2_Start(); UB_TIMER5_Start(); UB_DigOut_Lo(DOUT_PB7); // Set ground for LDR UB_DigOut_Lo(DOUT_PB9); // Set PC9 low to start DCF module while(1) { // Handle word matrix refreshes if ( gWcIsToBeRefreshed == Bit_SET ){ WC_Refresh(); gWcIsToBeRefreshed = Bit_RESET; } // Check if update of time is necessary #ifndef DISABLE_DCF if ( DcfTimeWasSetRecently() == Bit_RESET ) gDcfRxInProgress = Bit_SET; #endif // Handle IR remote if ( irmp_get_data( &irData ) ) ProcessIrDataPacket( irData ); // Read Ambient brightness and set LED brightness if ( gDcfRxInProgress == Bit_RESET ){ ambientBrightnessCurrent = SlidingAverageOnLastValues( UB_ADC1_SINGLE_Read( ADC_PA1 ) ); int brightnessToSet = 100.0 * GetBrightnessFactor( ambientBrightnessPoints, ambientBrightnessLedDimmingFactors, ambientBrightnessCurrent ); if ( brightnessToSet < LED_BRIGHTNESS_OFF_THRESHOLD ) WC_SetColor( WS2812_HSV_COL_OFF ); else WC_SetBrightness( brightnessToSet ); gWcIsToBeRefreshed = Bit_SET; } // Handle ESP8266 receive esp8266_handle_receive(); if( esp8266_request_time_from_google() == 1 ) { UB_RTC = Esp8266_curTime; UB_RTC_SetClock( RTC_DEC ); SetWordMatrix( UB_RTC_GetClock(RTC_DEC) ); gWcIsToBeRefreshed = Bit_SET; } } }
/***************************************** * Timer 2 Callback @100Hz * - Used for: DCF77 sampling *****************************************/ void UB_TIMER2_ISR_CallBack( void ) { #ifdef DISABLE_DCF return; #endif gDcfInputState = UB_DigIn_Read( DIN_PB8 ); if ( gDcfInputState == Bit_SET ) UB_Led_On( LED_GREEN ); else UB_Led_Off( LED_GREEN ); #ifdef ENABLE_TESTMODE //Testing: Just set a time gLastSuccessfulDcfRxTime.jahr = 0; gLastSuccessfulDcfRxTime.monat = 1; gLastSuccessfulDcfRxTime.tag = 1; gLastSuccessfulDcfRxTime.wotag = 1; gLastSuccessfulDcfRxTime.sek = 0; gLastSuccessfulDcfRxTime.min = 0; gLastSuccessfulDcfRxTime.std = 0; WC_SetElement(WC_ELEMENT_ES, 1); SetWordMatrix( UB_RTC_GetClock(RTC_DEC) ); gDcfRxInProgress = Bit_RESET; gDcfRxWasSuccesful = Bit_SET; gCurrentMatrixColor = WS2812_HSV_COL_WHITE; #else dcf77_SignalState_t dcf77state = Dcf77_ProcessSignal( gDcfInputState ); if ( dcf77state == dcf77_TimeRxSuccess ) { gLastSuccessfulDcfRxTime = Dcf77_GetTime(); UB_RTC = gLastSuccessfulDcfRxTime; UB_RTC_SetClock( RTC_DEC ); gDcfRxWasSuccesful = Bit_SET; // Set word matrix directly after first DCF RX if ( gDcfRxInProgress == Bit_SET ){ WC_SetElement(WC_ELEMENT_ES, 1); SetWordMatrix( UB_RTC_GetClock(RTC_DEC) ); gDcfRxInProgress = Bit_RESET; gCurrentMatrixColor = WS2812_HSV_COL_WHITE; } } // Indicate status of DCF reception by FUNK in red/green while DCF RX in progress if ( gDcfRxWasSuccesful == Bit_RESET ){ WC_DisableAllElements(); WC_SetElement( WC_ELEMENT_FUNK, 1 ); if ( dcf77state == dcf77_RxStateUnkown ) WC_SetColor( WS2812_HSV_COL_RED ); else if ( dcf77state == dcf77_RxStateGood ) WC_SetColor( WS2812_HSV_COL_GREEN ); WC_SetBrightness( 50 ); WC_SetElement( WC_ELEMENT_FUNK, 1 ); } else{ // Disable FUNK and set normal color WC_SetElement( WC_ELEMENT_FUNK, 0 ); WC_SetColor( gCurrentMatrixColor ); } #endif gWcIsToBeRefreshed = Bit_SET; }