SBD-DL22 / MainV8 / MainV8.ino
MainV8.ino
Raw
// 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