//
// Created by enik on 18.02.2022.
//

#include "micros.h"

#define    DWT_CYCCNT    *(volatile uint32_t*)0xE0001004
#define    DWT_CONTROL   *(volatile uint32_t*)0xE0001000
#define    SCB_DEMCR     *(volatile uint32_t*)0xE000EDFC

static volatile bool dwt_enabled = 0;

/**
 * @brief Enable DWT Counter
 */
void EnableDWT(void){
    SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // allow to use DWT
    DWT_CONTROL |= DWT_CTRL_CYCCNTENA_Msk;   // Start DWT counter
    dwt_enabled = 1;
}

/**
 * @brief Delay Microseconds
 * @param[in] val Value in microseconds to delay
 */
void DelayMicros(u32_t val){
    if (!dwt_enabled) EnableDWT();
    u32_t us_count_tic =  val * (SystemCoreClock / 1000000); // get delay value in ticks
    DWT->CYCCNT = 0U; // zero counter value
    while(DWT->CYCCNT < us_count_tic);
}

/**
 * @brief Start code measure from this point
 */
void StartCodeMeasure(void){
    if (!dwt_enabled) EnableDWT();
    DWT_CYCCNT = 0; // zero counter value
}

/**
 * @brief Stop code measure in this point
 * @param[out] micros Value in microseconds
 */
void StopCodeMeasure(u32_t *micros){
    if (!dwt_enabled){ *micros = 0; return; }
    //*micros = DWT_CYCCNT / SystemCoreClock; // get counter value
    *micros = DWT_CYCCNT; // get counter value
}