unsigned long getRTC(char *TimeDate) { unsigned long lData; lData = HibernateRTCGet(); return day2date(lData,TimeDate); }
//***************************************************************************** // //! This is the hibernate module handler. //! When the RTC timer expires, an interrupt is generated and the the GPS //! data is parsed and logged. //! //! If the Wake button is pressed, low power mode is disabled. //! A reset/power cycle is required to re-enable low power mode after Wake has //! been pressed. // //***************************************************************************** void lowPowerMode(int delaySeconds) { uint32_t ui32Status; // // Set the RTC to 0 or an initial value. The RTC can be set once when the // system is initialized after the cold startup and then left to run. Or // it can be initialized before every hibernate. // HibernateRTCSet(0); // // Set the match 0 register for 30 seconds from now. // HibernateRTCMatchSet(0, HibernateRTCGet() + delaySeconds); // // Clear any pending status. // ui32Status = HibernateIntStatus(0); HibernateIntClear(ui32Status); // // Save the program state information. The state information is stored in // the pui32NVData[] array. It is not necessary to save the full 16 words // of data, only as much as is actually needed by the program. // HibernateDataSet(&lowPowerOn, 1); // // Configure to wake on RTC match or when wake button is pressed. // HibernateWakeSet(HIBERNATE_WAKE_RTC | HIBERNATE_WAKE_PIN); // // Request hibernation. The following call may return because it takes a // finite amount of time for power to be removed. // HibernateRequest(); // // Spin here to wait for the power to be removed. // for(;;) { } } // End function lowPowerMode
uint8_t getRtc() { static uint32_t rtcUpdateCounter = 0; uint8_t data=0; time_t now; struct tm *tm; if(rtcUpdateCounter++>1000) { rtcUpdateCounter = 0; updateTime(); } now = HibernateRTCGet(); //get the current value in seconds tm = localtime (&now); rtcCurrent = *tm; LOGprintf("Time: %d:%d:%d", rtcCurrent.tm_hour, rtcCurrent.tm_min, rtcCurrent.tm_sec); return data; }
//***************************************************************************** // // Callback function from the menu widget. This function is called whenever // the menu is used to activate a child widget that is associated with the // menu. It is also called when the widget is deactivated and control is // returned to the menu widget. It can be used to trigger different actions // depending on which menus are chosen, and to track the state of the // application and control focus for the user interface. // // This function is called in the context of widget tree message processing // so care should be taken if doing any operation that affects the display // or widget tree. // //***************************************************************************** static void WidgetActivated(tWidget *psWidget, tSlideMenuItem *psMenuItem, bool bActivated) { char *pcMenuText; uint32_t ui32RTC; // // Handle the activation or deactivation of the strip chart. The strip // chart widget is activated when the user selects the START menu. // if(psWidget == &g_sStripChart.sBase) { // // If the strip chart is activated, start the logger running. // if(bActivated) { // // Get the current state of the menus // MenuGetState(&g_sConfigState); // // Save the state in battery backed memory // SetSavedState(&g_sConfigState); // // Start logger and update the logger state // AcquireStart(&g_sConfigState); g_iLoggerState = eSTATE_LOGGING; } else { // // If the strip chart is deactivated, stop the logger. // AcquireStop(); g_iLoggerState = eSTATE_IDLE; } } else if((psWidget == &g_sAINContainerCanvas.sBase) || (psWidget == &g_sAccelContainerCanvas.sBase) || (psWidget == &g_sCurrentContainerCanvas.sBase) || (psWidget == &g_sClockContainerCanvas.sBase) || (psWidget == &g_sTempContainerCanvas.sBase)) { // // Handle the activation or deactivation of any of the container // canvas that is used for showing the acquired data as a numerical // display. This happens when the VIEW menu is used. // // A viewer has been activated. // if(bActivated) { static tConfigState sLocalState; // // Get the current menu configuration state and save it in a local // storage. // MenuGetState(&sLocalState); // // Modify the state to set values that are suitable for using // with the viewer. The acquisition rate is set to 1/2 second // and all channels are selected. The storage medium is set to // "viewer" so the acquistion module will write the value of // acquired data to the appropriate viewing canvas. // sLocalState.ui8Storage = CONFIG_STORAGE_VIEWER; sLocalState.ui32Period = 0x00000040; sLocalState.ui16SelectedMask = 0x3ff; // // Start the acquisition module running. // AcquireStart(&sLocalState); g_iLoggerState = eSTATE_VIEWING; } else { // // The viewer has been deactivated so turn off the acquisition // module. // AcquireStop(); g_iLoggerState = eSTATE_IDLE; } } else if(psWidget == &g_sStatusContainerCanvas.sBase) { // // Handle the case when a status display has been activated. This can // occur when any of several menu items are selected. // // Get pointer to the text of the current menu item. // if(psMenuItem) { pcMenuText = psMenuItem->pcText; } else { return; } // // If activated from the SAVE menu, then the flash data needs to be // saved to USB stick. Enter the saving state. // if(!strcmp(pcMenuText, "SAVE")) { if(bActivated) { g_iLoggerState = eSTATE_SAVING; } else { g_iLoggerState = eSTATE_IDLE; } } else if(!strcmp(pcMenuText, "ERASE DATA?")) { // // If activated from the ERASE menu, then the flash data needs to // be erased. Enter the erasing state. // if(bActivated) { g_iLoggerState = eSTATE_ERASING; } else { g_iLoggerState = eSTATE_IDLE; } } else if(!strcmp(pcMenuText, "FLASH SPACE")) { // // If activated from the FLASH SPACE menu, then the user will be // shown a report on the amount of free space in flash. Enter the // reporting state. // if(bActivated) { g_iLoggerState = eSTATE_FREEFLASH; } else { g_iLoggerState = eSTATE_IDLE; } } } else if(psWidget == &g_sClockSetter.sBase) { // // Handle the activation of the clock setting widget. Deactivation is // handled through a separate callback. // // If the clock setter is activated, load the time structure fields. // if(bActivated) { // // Get the current time in seconds from the RTC. // ui32RTC = HibernateRTCGet(); // // Convert the RTC time to a time structure. // ulocaltime(ui32RTC, &g_sTimeClock); // // Set the callback that will be called when the clock setting // widget is deactivated. Since the clock setting widget needs // to take over the focus for button events, it uses a separate // callback when it is finsihed. // ClockSetCallbackSet((tClockSetWidget *)psWidget, ClockSetOkCallback); // // Give the clock setter widget focus for the button events // g_ui32KeyFocusWidgetHandle = (uint32_t)psWidget; g_iLoggerState = eSTATE_CLOCKSET; } } }
//***************************************************************************** // // This function is called to start an acquisition running. It determines // which channels are to be logged, enables the ADC sequencers, and computes // the first RTC match value. This will start the acquisition running. // //***************************************************************************** void AcquireStart(tConfigState *psConfig) { uint32_t ui32Idx, pui32RTC[2], ui32SelectedMask; // // Check the parameters // ASSERT(psConfig); if(!psConfig) { return; } // // Update the config state pointer, save the selected item mask // g_psConfigState = psConfig; ui32SelectedMask = psConfig->ui16SelectedMask; // // Get the logging period from the logger configuration. Split the // period into seconds and subseconds pieces and save for later use in // generating RTC match values. // g_pui32MatchPeriod[0] = psConfig->ui32Period >> 8; g_pui32MatchPeriod[1] = (psConfig->ui32Period & 0xFF) << 8; // // Determine how many channels are to be logged // ui32Idx = ui32SelectedMask; g_ui32NumItems = 0; while(ui32Idx) { if(ui32Idx & 1) { g_ui32NumItems++; } ui32Idx >>= 1; } // // Initialize the strip chart manager for a new run. Don't bother with // the strip chart if we are using viewer mode, or sleep-logging. // if((psConfig->ui8Storage != CONFIG_STORAGE_VIEWER) && !psConfig->ui32SleepLogging) { StripChartMgrInit(); StripChartMgrConfigure(ui32SelectedMask); } // // Configure USB for memory stick if USB storage is chosen // if(psConfig->ui8Storage == CONFIG_STORAGE_USB) { USBStickOpenLogFile(0); } else if(psConfig->ui8Storage == CONFIG_STORAGE_FLASH) { // // Flash storage is to be used, prepare the flash storage module. // If already sleep-logging, then pass in the saved flash address // so it does not need to be searched. // if(psConfig->ui32SleepLogging) { FlashStoreOpenLogFile(psConfig->ui32FlashStore); } else { // // Otherwise not sleep logging, so just initialize the flash store, // this will cause it to search for the starting storage address. // FlashStoreOpenLogFile(0); } } // // Enable the ADC sequencers // MAP_ADCSequenceEnable(ADC0_BASE, 0); MAP_ADCSequenceEnable(ADC1_BASE, 0); // // Flush the ADC sequencers to be sure there is no lingering data. // MAP_ADCSequenceDataGet(ADC0_BASE, 0, g_pui32ADCData); MAP_ADCSequenceDataGet(ADC1_BASE, 0, g_pui32ADCData); // // Enable ADC interrupts // MAP_ADCIntClear(ADC0_BASE, 0); MAP_ADCIntClear(ADC1_BASE, 0); MAP_ADCIntEnable(ADC0_BASE, 0); MAP_IntEnable(INT_ADC0SS0); // // If we are not already sleep-logging, then initialize the RTC match. // If we are sleep logging then this does not need to be set up. // if(!psConfig->ui32SleepLogging) { // // Get the current RTC value // do { pui32RTC[0] = HibernateRTCGet(); pui32RTC[1] = HibernateRTCSSGet(); } while(pui32RTC[0] != HibernateRTCGet()); // // Set an initial next match value. Start with the subseconds always // 0 so the first match value will always be an even multiple of the // subsecond match. Add 2 seconds to the current RTC just to be clear // of an imminent rollover. This means that the first match will occur // between 1 and 2 seconds from now. // g_pui32NextMatch[0] = pui32RTC[0] + 2; g_pui32NextMatch[1] = 0; // // Now set the match value // HibernateRTCMatchSet(0, g_pui32NextMatch[0]); HibernateRTCSSMatchSet(0, g_pui32NextMatch[1]); } // // If we are configured to sleep, but not sleeping yet, then enter sleep // logging mode if allowed. // if(psConfig->bSleep && !psConfig->ui32SleepLogging) { // // Allow sleep logging if storing to flash at a period of 1 second // or greater. // if((psConfig->ui8Storage == CONFIG_STORAGE_FLASH) && (psConfig->ui32Period >= 0x100)) { psConfig->ui32SleepLogging = 1; } } // // Enable the RTC interrupts from the hibernate module // HibernateIntClear(HibernateIntStatus(0)); HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_PIN_WAKE); MAP_IntEnable(INT_HIBERNATE); // // Logging data should now start running // }
//***************************************************************************** // // This is the handler for the RTC interrupt from the hibernate peripheral. // It occurs on RTC match. This handler will initiate an ADC acquisition, // which will run all of the ADC sequencers. Then it computes the next // match value and sets it in the RTC. // //***************************************************************************** void RTCHandler(void) { uint32_t ui32Status, ui32Seconds; // // Increment RTC interrupt counter // g_pui32RTCInts++; // // Clear the RTC interrupts (this can be slow for hib module) // ui32Status = HibernateIntStatus(1); HibernateIntClear(ui32Status); // // Read and save the current value of the seconds counter. // ui32Seconds = HibernateRTCGet(); // // If we are sleep logging, then there will be no remembered value for // the next match value, which is also used as the time stamp when // data is collected. In this case we will just use the current // RTC seconds. This is safe because if sleep-logging is used, it // is only with periods of whole seconds, 1 second or longer. // if(g_psConfigState->ui32SleepLogging) { g_pui32NextMatch[0] = ui32Seconds; g_pui32NextMatch[1] = 0; } // // If we are logging data to PC and using a period greater than one // second, then use special handling. For PC logging, if no data is // collected, then we must send a keep-alive packet once per second. // if((g_psConfigState->ui8Storage == CONFIG_STORAGE_HOSTPC) && (g_pui32MatchPeriod[0] > 1)) { // // If the current seconds count is less than the match value, that // means we got the interrupt due to one-second keep alive for the // host PC. // if(ui32Seconds < g_pui32NextMatch[0]) { // // Set the next match for one second ahead (next keep-alive) // HibernateRTCMatchSet(0, ui32Seconds + 1); // // Set flag to indicate that a keep alive packet is needed // g_bNeedKeepAlive = true; // // Nothing else to do except wait for next keep alive or match // return; } // // Else, this is a real match so proceed to below to do a normal // acquisition. // } // // Kick off the next ADC acquisition. When these are done they will // cause an ADC interrupt. // MAP_ADCProcessorTrigger(ADC1_BASE, 0); MAP_ADCProcessorTrigger(ADC0_BASE, 0); // // Set the next RTC match. Add the match period to the previous match // value. We are making an assumption here that there is enough time from // when the match interrupt occurred, to this point in the code, that we // are still setting the match time in the future. If the period is too // long, then we could miss a match and never get another RTC interrupt. // g_pui32NextMatch[0] += g_pui32MatchPeriod[0]; g_pui32NextMatch[1] += g_pui32MatchPeriod[1]; if(g_pui32NextMatch[1] > 32767) { // // Handle subseconds rollover // g_pui32NextMatch[1] &= 32767; g_pui32NextMatch[0]++; } // // If logging to host PC at greater than 1 second period, then set the // next RTC wakeup for 1 second from now. This will cause a keep alive // packet to be sent to the PC // if((g_psConfigState->ui8Storage == CONFIG_STORAGE_HOSTPC) && (g_pui32MatchPeriod[0] > 1)) { HibernateRTCMatchSet(0, ui32Seconds + 1); } else { // // Otherwise this is a normal match and the next match should also be a // normal match, so set the next wakeup to the calculated match time. // HibernateRTCMatchSet(0, g_pui32NextMatch[0]); HibernateRTCSSMatchSet(0, g_pui32NextMatch[1]); } // // Toggle the LED on the board so the user can see that the acquisition // is running. // MAP_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_2, ~MAP_GPIOPinRead(GPIO_PORTG_BASE, GPIO_PIN_2)); // // Now exit the int handler. The ADC will trigger an interrupt when // it is finished, and the RTC is set up for the next match. // }
//***************************************************************************** // // This function is called when in VIEW mode. The acquired data is written // as text strings which will appear on the eval board display. // //***************************************************************************** static void UpdateViewerData(const tLogRecord *psRecord) { static char pcViewerBuf[24]; uint32_t ui32Idx, pui32RTC; struct tm sTime; // // Loop through the analog channels and update the text display strings. // for(ui32Idx = LOG_ITEM_USER0; ui32Idx <= LOG_ITEM_USER3; ui32Idx++) { usnprintf(pcViewerBuf, sizeof(pcViewerBuf), " CH%u: %u.%03u V ", ui32Idx - LOG_ITEM_USER0, psRecord->pi16Items[ui32Idx] / 1000, psRecord->pi16Items[ui32Idx] % 1000); MenuUpdateText(ui32Idx, pcViewerBuf); } // // Loop through the accel channels and update the text display strings. // for(ui32Idx = LOG_ITEM_ACCELX; ui32Idx <= LOG_ITEM_ACCELZ; ui32Idx++) { int16_t i16Accel = psRecord->pi16Items[ui32Idx]; i16Accel *= (i16Accel < 0) ? -1 : 1; usnprintf(pcViewerBuf, sizeof(pcViewerBuf), " %c: %c%d.%02u g ", (ui32Idx - LOG_ITEM_ACCELX) + 'X', psRecord->pi16Items[ui32Idx] < 0 ? '-' : '+', i16Accel / 100, i16Accel % 100); MenuUpdateText(ui32Idx, pcViewerBuf); } // // Update the display string for internal temperature. // usnprintf(pcViewerBuf, sizeof(pcViewerBuf), " INT: %d.%01u C ", psRecord->pi16Items[LOG_ITEM_INTTEMP] / 10, psRecord->pi16Items[LOG_ITEM_INTTEMP] % 10); MenuUpdateText(LOG_ITEM_INTTEMP, pcViewerBuf); // // Update the display string for external temperature. // usnprintf(pcViewerBuf, sizeof(pcViewerBuf), " EXT: %d.%01u C ", psRecord->pi16Items[LOG_ITEM_EXTTEMP] / 10, psRecord->pi16Items[LOG_ITEM_EXTTEMP] % 10); MenuUpdateText(LOG_ITEM_EXTTEMP, pcViewerBuf); // // Update the display string for processor current. // usnprintf(pcViewerBuf, sizeof(pcViewerBuf), " %u.%01u mA ", psRecord->pi16Items[LOG_ITEM_CURRENT] / 10, psRecord->pi16Items[LOG_ITEM_CURRENT] % 10); MenuUpdateText(LOG_ITEM_CURRENT, pcViewerBuf); // // Update the display strings for time and data. // pui32RTC = HibernateRTCGet(); ulocaltime(pui32RTC, &sTime); usnprintf(pcViewerBuf, sizeof(pcViewerBuf), "%4u/%02u/%02u", sTime.tm_year+1900, sTime.tm_mon + 1, sTime.tm_mday); MenuUpdateText(TEXT_ITEM_DATE, pcViewerBuf); usnprintf(pcViewerBuf, sizeof(pcViewerBuf), "%02u:%02u:%02u", sTime.tm_hour, sTime.tm_min, sTime.tm_sec); MenuUpdateText(TEXT_ITEM_TIME, pcViewerBuf); }