#!/usr/bin/bash

# Trip point 1: reduces cpu speed
TRIP_POINT_1=75000

# Trip point 2: [de]activate mod-noise-removal (if enabled)
TRIP_POINT_2=80000

# Trip point 3: too late!
TRIP_POINT_3=84000

# Get CPU speed range
MIN_FREQ_0=$(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq)
MID_FREQ_0=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies | awk '{ print $(NF - 1) }')
MAX_FREQ_0=$(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq)

if [ -e /sys/devices/system/cpu/cpufreq/policy4/ ]; then
    HAS_FREQ_4=1
    MIN_FREQ_4=$(cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_min_freq)
    MAX_FREQ_4=$(cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_max_freq)
fi

# ---------------------------------------------------------------------------------------------------------------------

function create_new_csv_file {
    # create a new unique file
    index=$(ls /data/temperature_*.csv 2>/dev/null | wc -l)
    index=$(printf "%03d" $((index+1)))
    csvfile="/data/temperature_${index}.csv"

    # CSV header/fields
    if [ -n "${HAS_FREQ_4}" ]; then
        echo "Time (s),Temperature (deg),Clock Speed 1 (MHz),Clock Speed 2 (MHz)" > ${csvfile}
    else
        echo "Time (s),Temperature (deg),Clock Speed (MHz)" > ${csvfile}
    fi

    # print file path
    echo ${csvfile}
}

function append_csv_data {
    time=$((csvstep * 5))
    temp=$((cur_temp / 1000))
    freq=$((cur_freq / 1000))

    if [ -n "${HAS_FREQ_4}" ]; then
        freq4=$((cur_freq4 / 1000))
        echo "${time},${temp},${freq},${freq4}" >> ${csvfile}
    else
        echo "${time},${temp},${freq}" >> ${csvfile}
    fi

    # increase for next time
    csvstep=$((csvstep + 1))
}

# ---------------------------------------------------------------------------------------------------------------------

function maybe_too_hot {
    if [ ${cur_temp} -ge ${TRIP_POINT_1} ] && [ ! -e /data/noise-removal-active ]; then
        if [ "$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq)" != "${MID_FREQ_0}" ]; then
            echo "Reducing CPU speed"
            echo ${MID_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
            # don't kill jack on this turn, let the unit try to cool down with reduced cpu speed first
            return
        fi
    fi
    if [ ${cur_temp} -ge ${TRIP_POINT_2} ] && [ -e /data/noise-removal-active ]; then
        if systemctl -q is-active mod-noise-removal; then
            echo "Stopping mod-noise-removal"
            systemctl stop mod-noise-removal
            # don't kill jack on this turn, let the unit try to cool down without mod-noise-removal first
            return
        fi
    fi
    if [ ${cur_temp} -ge ${TRIP_POINT_3} ]; then
        echo "Killing JACK (I am sorry...)"
        killall jackd
    fi
}

function maybe_too_cold {
    if [ ${cur_temp} -le ${TRIP_POINT_1} ] && [ ! -e /data/noise-removal-active ]; then
        if [ "$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq)" != "${MAX_FREQ_0}" ]; then
            echo "Resetting CPU speed (to max)"
            echo ${MAX_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
        fi
    fi
    if [ ${cur_temp} -le ${TRIP_POINT_2} ] && [ -e /data/noise-removal-active ]; then
        if ! systemctl -q is-active mod-noise-removal; then
            echo "Starting mod-noise-removal"
            systemctl start mod-noise-removal
        fi
    fi
}

function init_loop {
    cur_freq=$(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq)
    if [ -n "${HAS_FREQ_4}" ]; then
    cur_freq4=$(cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_cur_freq)
    fi
    cur_temp=$(cat /sys/class/thermal/thermal_zone0/temp)
    prev_temp=${cur_temp}
    # append_csv_data

    # Check if temperature exceeds any tripping point
    if [ ${cur_temp} -ge ${TRIP_POINT_1} ]; then
        maybe_too_hot
    fi

    if [ -n "${HAS_FREQ_4}" ]; then
        echo "cpu-freq-manager started. temp:${cur_temp} freq:${cur_freq},${cur_freq4}"
    else
        echo "cpu-freq-manager started. temp:${cur_temp} freq:${cur_freq}"
    fi
}

function run_loop {
    cur_freq=$(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq)
    if [ -n "${HAS_FREQ_4}" ]; then
    cur_freq4=$(cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_cur_freq)
    fi
    cur_temp=$(cat /sys/class/thermal/thermal_zone0/temp)
    # append_csv_data

    # Check if frequency should change
    if [ -e /data/noise-removal-active ]; then
        cur_nr_active=1
    else
        cur_nr_active=0
    fi
    if [ ${prev_nr_active} != ${cur_nr_active} ]; then
        if [ ${cur_nr_active} -eq 1 ]; then
            echo ${MID_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
            if ! systemctl -q is-active mod-noise-removal; then
                echo "Starting mod-noise-removal"
                systemctl start mod-noise-removal
            fi
        else
            echo ${MAX_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
            if systemctl -q is-active mod-noise-removal; then
                echo "Stopping mod-noise-removal"
                systemctl stop mod-noise-removal
            fi
        fi
        prev_nr_active=${cur_nr_active}
        prev_temp=${cur_temp}
        continue
    fi

    # cooling down
    if [ ${cur_temp} -lt ${prev_temp} ]; then
        if [ -n "${HAS_FREQ_4}" ]; then
            echo "cpu-freq-manager run_loop cooling down, temp:${cur_temp} freq:${cur_freq},${cur_freq4}"
        else
            echo "cpu-freq-manager run_loop cooling down, temp:${cur_temp} freq:${cur_freq}"
        fi
        maybe_too_cold
    # warming up
    elif [ ${cur_temp} -gt ${prev_temp} ]; then
        if [ -n "${HAS_FREQ_4}" ]; then
            echo "cpu-freq-manager run_loop heating up, temp:${cur_temp} freq:${cur_freq},${cur_freq4}"
        else
            echo "cpu-freq-manager run_loop heating up, temp:${cur_temp} freq:${cur_freq}"
        fi
        maybe_too_hot
    fi
    prev_temp=${cur_temp}
}

# ---------------------------------------------------------------------------------------------------------------------

# init global vars
prev_temp=0
cur_freq=0
cur_temp=0

# csvfile=$(create_new_csv_file)
# csvstep=0

# ---------------------------------------------------------------------------------------------------------------------

# Activate userspace
echo userspace > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor

if [ -n "${HAS_FREQ_4}" ]; then
    echo userspace > /sys/devices/system/cpu/cpufreq/policy4/scaling_governor
fi

# set frequency to max possible
if [ -e /data/noise-removal-active ]; then
    prev_nr_active=1
    echo ${MID_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
else
    prev_nr_active=0
    echo ${MAX_FREQ_0} > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
fi

if [ -n "${HAS_FREQ_4}" ]; then
    echo ${MAX_FREQ_4} > /sys/devices/system/cpu/cpufreq/policy4/scaling_setspeed
fi

init_loop

while true; do
    if sleep 2.5; then
        run_loop
    else
        break
    fi
done

# ---------------------------------------------------------------------------------------------------------------------
