/*
 * FSL_Wait.c
 *
 *  Created on: Mar 11, 2015
 *      Author: B52414
 */

#include "FSL_Wait.h"

/**
 * Waits for at least specified amount of cycles which is given by 32bit value range.
 * Assumption for this function is that target architecture is using 32bit general purpose registers.
 * It is recommended to use predefined macros in case number of cycles is in range from 1 to 10 when desired more precise solution.
 * @brief
 * @param cycles
 * @return void
 */
inline void WaitCycles(uint32_t cycles) {
  /* advance to next multiple of 3 */
  while (cycles % 3) {
    cycles++;
  }
  WAIT_FOR_MUL3_CYCLES(cycles);
}

/**
 * Waits for specified amount of seconds.
 * @brief
 * @param sec
 * @return void
 */
void WaitSec(uint16_t sec) {
  for (; sec > 0; sec--) {
    WaitMS(1000);
  }
}

/**
 * Waits for specified amount of milliseconds.
 * @brief
 * @param ms
 * @return void
 */
void WaitMS(uint16_t ms) {
  uint32_t cycles = GET_CYCLES_FOR_MS(1, CPU_CORE_CLK_HZ);

  for (; ms > 0; ms--) {
    WaitCycles(cycles);
  }
}

/**
 * Waits for specified amount of microseconds.
 * @brief
 * @param us
 * @return void
 */
inline void WaitUS(uint16_t us) {
  WaitCycles(GET_CYCLES_FOR_US(us, CPU_CORE_CLK_HZ));
}

/**
 * Waits for specified amount of nanoseconds.
 * @brief
 * @param ns
 * @return void
 */
inline void WaitNS(uint16_t ns) {
  WaitCycles(GET_CYCLES_FOR_NS(ns, CPU_CORE_CLK_HZ));
}

/**
 * Toggles pin with specified delay.
 */
void TogglePin(uint32_t delay)
{
  uint32_t cycles = (uint32_t)GET_CYCLES_FOR_NS(delay, CPU_CORE_CLK_HZ); /* the needed cycles */
  uint16_t correction = (uint16_t)GET_CYCLES_FOR_NS(80, CPU_CORE_CLK_HZ); /* GPIO toggle delay correction */

  cycles = (correction > cycles) ? 3 : (cycles - correction);

  while (cycles % 3) { /* advance to next multiple of 3 */
    cycles++;
  }

  __DI(); /* disables maskable interrupts */
  //GPIO_PDD_ClearPortDataOutputMask(CSpin1_MODULE_BASE_ADDRESS, CSpin1_PORT_MASK);
  WAIT_FOR_MUL3_CYCLES(cycles);
  //GPIO_PDD_SetPortDataOutputMask(CSpin1_MODULE_BASE_ADDRESS, CSpin1_PORT_MASK);
  __EI(); /* enable maskable interrupts */
}
