#!/usr/bin/bash


###
#
# Options Section
#
###

set -e
set -o pipefail


###
#
# Variable Section
#
###

CURRENT_DUTY_CYCLE='-1'
PWM_CHIP_PATH='/sys/class/pwm/pwmchip0'


###
#
# Function Section
#
###

function num_compare () {
  /usr/bin/mawk "BEGIN {exit !($*)}"
}

function pwm_get_chip_path () {
  local SUB_PATH="${1}"
  if [ -n "${SUB_PATH}" ]; then
    /usr/bin/echo "${PWM_CHIP_PATH}/${SUB_PATH}"
  else
    /usr/bin/echo "${PWM_CHIP_PATH}"
  fi
}

function pwm_get_channel_path () {
  local CHANNEL="${1}"
  local SUB_PATH="${2}"
  local PWM_PATH="${PWM_CHIP_PATH}/pwm${CHANNEL}"
  if [ -n "${SUB_PATH}" ]; then
    /usr/bin/echo "${PWM_PATH}/${SUB_PATH}"
  else
    /usr/bin/echo "${PWM_PATH}"
  fi
}

function pwm_create () {
  local CHANNEL="${1}"
  PWM_CHANNEL_PATH="$(pwm_get_channel_path "${CHANNEL}")"
  if [[ ! -d "${PWM_CHANNEL_PATH}" ]]; then
    /usr/bin/echo "${CHANNEL}" > "$(pwm_get_chip_path 'export')"
  fi
}

function frequency_to_period () {
  local FREQUENCY="${1}"
  PERC=$(/usr/bin/mawk -v freq="${FREQUENCY}" 'BEGIN { printf "%.0f", 1 / freq * 1000 * 1000000; exit(0) }')
  /usr/bin/echo "${PERC}"
}

function pwm_change_duty_cycle () {
  local CHANNEL="${1}"
  local FREQUENCY="${2}"
  local DUTY_CYCLE="${3}"
  if [[ "${DUTY_CYCLE}" -lt '0' ]] || [[ "${DUTY_CYCLE}" -gt '100' ]]; then
    return 1
  fi
  PERIOD=$(frequency_to_period "${FREQUENCY}")
  NEW_DUTY_CYCLE=$(/usr/bin/mawk -v period="${PERIOD}" -v dc="${DUTY_CYCLE}" 'BEGIN { printf "%.0f", period * dc / 100; exit(0) }')
  /usr/bin/echo "${NEW_DUTY_CYCLE}" > "$(pwm_get_channel_path "${CHANNEL}" 'duty_cycle')"
}

function pwm_change_frequency () {
  local CHANNEL="${1}"
  local FREQUENCY="${2}"
  if num_compare "${FREQUENCY} < 0.1"; then
    return 1
  fi
  if [[ "${CURRENT_DUTY_CYCLE}" == '-1' ]]; then
    CURRENT_DUTY_CYCLE='0'
  elif [[ "${CURRENT_DUTY_CYCLE}" -gt '0' ]]; then
    pwm_change_duty_cycle "${CHANNEL}" "${FREQUENCY}" '0'
  fi
  PERIOD=$(frequency_to_period "${FREQUENCY}")
  /usr/bin/echo "${PERIOD}" > "$(pwm_get_channel_path "${CHANNEL}" 'period')"
  pwm_change_duty_cycle "${CHANNEL}" "${FREQUENCY}" "${CURRENT_DUTY_CYCLE}"
}

function pwm_start () {
  local CHANNEL="${1}"
  /usr/bin/echo '1' > "$(pwm_get_channel_path "${CHANNEL}" 'enable')"
}

function pwm_stop () {
  local CHANNEL="${1}"
  /usr/bin/echo "${CHANNEL}" > "$(pwm_get_chip_path 'unexport')"
}

function pwm_init () {
  local CHANNEL="${1}"
  local FREQUENCY="${2}"
  if [[ ! -d "${PWM_CHIP_PATH}" ]]; then
    exit 1
  fi
  if [[ ! -w "$(pwm_get_chip_path 'export')" ]]; then
    exit 1
  fi
  if [[ "${CHANNEL}" != '0' ]] && [[ "${CHANNEL}" != '1' ]]; then
    exit 1
  fi
  pwm_create "${CHANNEL}"
  pwm_change_frequency "${CHANNEL}" "${FREQUENCY}"
  pwm_start "${CHANNEL}"
}

function get_temp () {
  RAW_TEMP="$(/usr/bin/cat '/sys/class/thermal/thermal_zone0/temp')"
  TEMP=$(/usr/bin/echo "scale=2; ${RAW_TEMP} / 1000" | bc)
  /usr/bin/echo "${TEMP}"
}


###
#
# Runtime Environment
#
###

trap "pwm_stop '0'" EXIT
pwm_init '0' '2000'

while true; do
  TEMP="$(get_temp)"
  DUTY_CYCLE='0'
  CUR_TEMP=${TEMP%.*}
  if [[ "${CUR_TEMP}" -ge '70' ]]; then
    DUTY_CYCLE='100'
  elif [[ "${CUR_TEMP}" -ge '60' ]]; then
    DUTY_CYCLE='75'
  elif [[ "${CUR_TEMP}" -ge '50' ]]; then
    DUTY_CYCLE='50'
  elif [[ "${CUR_TEMP}" -ge '25' ]]; then
    DUTY_CYCLE='40'
  fi
  if [[ "${DUTY_CYCLE}" != "${CURRENT_DUTY_CYCLE}" ]]; then
    pwm_change_duty_cycle '0' '2000' "${DUTY_CYCLE}"
    CURRENT_DUTY_CYCLE="${DUTY_CYCLE}"
  fi
  /usr/bin/sleep '15s'
done
