/*
 * Utils.cpp
 *
 *  Created on: Feb 19, 2025
 *      Author: Murdock
 */
#include <Arduino.h>
#include "Utils.h"

Utils::Utils() {
	// TODO Auto-generated constructor stub

}

/**
 * Converts a temperature value from Celsius to Fahrenheit.
 *
 * @param celsius The temperature in Celsius.
 * @return The equivalent temperature in Fahrenheit.
 */
float Utils::getFahrenheit(float celsius) {
    return ((celsius * 9) / 5 + 32);
}

/**
 * Maps a float value from one range to another.
 * Similar to the built-in `map` function, but works with floating-point values.
 *
 * @param value The input value to map.
 * @param inMin The minimum value of the input range.
 * @param inMax The maximum value of the input range.
 * @param outMin The minimum value of the output range.
 * @param outMax The maximum value of the output range.
 * @return The mapped value in the output range.
 */
float Utils::mapFloat(float value, float inMin, float inMax, float outMin, float outMax) {
    return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}

/**
 * Converts a raw sensor value to a temperature in Celsius.
 *
 * This function is specifically designed for the TMP36 temperature sensor.
 * It first scales the sensor value to an intermediate voltage-like value, then maps
 * that to the temperature range supported by the TMP36 sensor (-40°C to +125°C).
 *
 * @param sensorValue The raw analog reading from the sensor (0-1023).
 * @return The calculated temperature in Celsius.
 */
float Utils::getCelsius(int sensorValue) {
    float fValue = ((sensorValue - 20) * 3.04); // Convert raw reading to voltage-like value
    // Map the voltage-like value to the TMP36 temperature range (-40 to +125°C)
    return mapFloat(fValue, 0, 1023, -40, 125);
}

/**
 * @brief Get the amount of free SRAM available.
 *
 * This function calculates the free RAM available for use by the program.
 *
 * - The stack grows downward from RAMEND.
 * - The heap grows upward from `__heap_start`.
 * - If `__brkval` is NULL, it means no dynamic allocations have occurred.
 * - The free memory is the difference between the current stack pointer
 *   (local variable `freeMemory`) and the heap.
 *
 * @return The amount of free SRAM in bytes.
 */
unsigned int Utils::getFreeMemory() {
    int freeMemory;

    // If __brkval is NULL, no heap allocations were made, so we compare to __heap_start
    if ((int)__brkval == 0) {
        freeMemory = ((int)&freeMemory) - ((int)&__heap_start);
    }
    // Otherwise, we compare to __brkval, which points to the end of the heap
    else {
        freeMemory = ((int)&freeMemory) - ((int)__brkval);
    }

    return freeMemory;
}

/**
 * @brief Get the total available SRAM size.
 *
 * This function calculates the total SRAM available on the microcontroller.
 *
 * - `RAMEND` is a built-in macro that defines the last valid RAM address.
 * - `__data_start` marks the beginning of the SRAM usage.
 * - The total memory is calculated as the difference plus one.
 *
 * @return The total SRAM in bytes.
 */
unsigned int Utils::getTotalMemory() {
    return RAMEND - (unsigned int)&__data_start + 1;
}

/**
 * @brief Get the amount of used SRAM.
 *
 * This function calculates how much SRAM is currently occupied.
 *
 * - It subtracts free memory from the total available SRAM.
 * - This includes usage by the stack, heap, `.data`, and `.bss` sections.
 *
 * @return The amount of used SRAM in bytes.
 */
unsigned int Utils::getUsedMemory() {
    return getTotalMemory() - getFreeMemory();
}
