// This code includes different header files needed to run this program. #include <TF_handler.h> #include <RTC_handler.h> #include "Jaffl.h" // Here, two different modes of operation are defined: ORIGINAL and OPTIMIZED. // The user can uncomment the one they want to use. By default, OPTIMIZED is chosen. #define OPTIMIZED //#define ORIGINAL // Define whether the duration of runtime should be printed. // Two options exist, one for when the program is open and one for when it is closed. //#define DURATION_RUNTIME_CLOSED //#define DURATION_RUNTIME_OPEN // If DURATION_RUNTIME_OPEN is defined, start measuring time at this point. #if defined(DURATION_RUNTIME_OPEN) unsigned long if_start_1 = micros(); #endif // Various variables and objects are defined here, such as file object, time-related variables and objects, voltage pin, etc. FIL fp; int64_t unixtime_start = 0; int64_t unixtime_end = 0; RTC_handler rtc_handler; // RTC (Real Time Clock) handler object TF_handler tf_handler(P1_3); // TF (Transfer Function) handler object and pin assignment int const voltage_pin = P1_5; char datetime_start[20]; char datetime_end[20]; char data[120]; int64_t duration_data = 0 ; // If OPTIMIZED mode is defined, a timestamp object is created. #ifdef OPTIMIZED struct ts tp; #endif // subroutine function definition, capturing and storing the start time of a particular process. void subroutine() { tf_handler.begin(fp); // start the transfer function handler with file object // Depending on whether ORIGINAL or OPTIMIZED mode is defined, it fetches the start time differently. #if defined(ORIGINAL) unixtime_start = rtc_handler.get_unix_time(); rtc_handler.get_datetime(datetime_start, 20); #elif defined(OPTIMIZED) rtc_handler.get_time_s(&tp); unixtime_start = tp.unixtime; rtc_handler.get_datetime_s(datetime_start, 20, tp); #endif // If DURATION_RUNTIME_OPEN is defined, calculate the duration it took to open the routine. #if defined(DURATION_RUNTIME_OPEN) unsigned long if_end_1 = micros(); char time_duration[128]; unsigned long duration = -if_end_1 + if_start_1 ; snprintf(time_duration, 128, "open routine duration: %d us\n", duration ); tf_handler.store_data(fp, time_duration); #endif } // setup function, runs once when the program starts, calling the subroutine function to take the first time and timestamp. void setup() { subroutine(); } // Main program loop. Checks for voltage conditions and performs operations based on the mode of operation (ORIGINAL or OPTIMIZED). void loop() { // Start measuring time if DURATION_RUNTIME_CLOSED is defined. #if defined(DURATION_RUNTIME_CLOSED) unsigned long if_start = micros(); #endif // Checks if the voltage at voltage_pin is below 3V or if voltage_pin is in a low state. If yes, then continue with the if block. if (analogRead(voltage_pin) < 1241 * 3 || !digitalRead(voltage_pin)) { // Depending on whether ORIGINAL or OPTIMIZED mode is defined, it fetches the end time differently. #if defined(ORIGINAL) unixtime_end = rtc_handler.get_unix_time(); rtc_handler.get_datetime(datetime_end, 20); #elif defined(OPTIMIZED) rtc_handler.get_time_s(&tp); unixtime_end = tp.unixtime; rtc_handler.get_datetime_s(datetime_end, 20, tp); #endif // Calculating the duration of data duration_data = unixtime_end - unixtime_start; // If the duration is less than 2, it continuously executes a while loop. if (duration_data < 2) { while (1) {} // Waste CPU time until brownout (undervoltage condition leading to device reset). } // Formats the data to be stored. snprintf(data, 120, "ON\t%lld\t%s\t%s\n", duration_data, datetime_start, datetime_end); tf_handler.store_data(fp, data); // Stores the data into the file. // If DURATION_RUNTIME_CLOSED is defined, calculate the duration it took to complete the loop. #if defined(DURATION_RUNTIME_CLOSED) unsigned long if_end = micros(); char time_duration[128]; int duration = (int)if_end - (int)if_start; snprintf(time_duration, 128, "Close routine duration: %d us\n", duration); tf_handler.store_data(fp, time_duration); #endif // If voltage_pin is in a high state, call subroutine function again to redo first time and timestamp. if (digitalRead(voltage_pin)) { subroutine(); } else // If voltage_pin is in a low state, continuously execute a while loop until brownout. while (1) { Jaffl.close(&fp); // Close the file with the Jaffl library. }; } } // Removes MSP startup protocol to avoid 2-second startup delay. #ifdef __cplusplus extern "C" { #endif void enableXtal() { } #ifdef __cplusplus } #endif