openmv/lib/alif/drivers/source/utimer.c
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

599 lines
24 KiB
C

/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*
*/
/**************************************************************************//**
* @file utimer.h
* @author Girish BN, Manoj A Murudi
* @email girish.bn@alifsemi.com, manoj.murudi@alifsemi.com
* @version V1.0.0
* @date 02-April-2023
* @brief Low Level driver file for UTIMER.
* @bug None.
* @Note None
*******************************************************************************/
#include "utimer.h"
/**
\fn void utimer_config_direction (UTIMER_Type *utimer, uint8_t channel, UTIMER_TYPE type, utimer_channel_config *ch_config)
\brief configure counter type for the UTIMER instance.
\param[in] utimer Pointer to the UTIMER register map
\param[in] channel channel number
\param[in] dir counter direction
\param[in] ch_config Pointer to the UTIMER channel specific config structure
\return none
*/
void utimer_config_direction (UTIMER_Type *utimer, uint8_t channel, UTIMER_COUNTER_DIR dir, utimer_channel_config *ch_config)
{
switch (dir)
{
case UTIMER_COUNTER_UP:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= CNTR_CTRL_EN;
if (ch_config->fixed_buffer)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= CNTR_CTRL_SAWTOOTH_ONE_SHOT;
}
break;
}
case UTIMER_COUNTER_DOWN:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= (CNTR_CTRL_EN|CNTR_CTRL_DIR_DOWN);
if (ch_config->fixed_buffer)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= CNTR_CTRL_SAWTOOTH_ONE_SHOT;
}
break;
}
case UTIMER_COUNTER_TRIANGLE:
{
if (ch_config->fixed_buffer)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= (CNTR_CTRL_EN|CNTR_CTRL_TRIANGLE_ONE_SHOT);
}
else
{
if (ch_config->buf_trough_n_crest)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= (CNTR_CTRL_EN|CNTR_CTRL_TRIANGLE_BUF_TROUGH_CREST);
}
else
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_CTRL |= (CNTR_CTRL_EN|CNTR_CTRL_TRIANGLE_BUF_TROUGH);
}
}
break;
}
}
}
/**
\fn void utimer_config_mode (UTIMER_Type *utimer, uint8_t channel, UTIMER_MODE mode, utimer_channel_config *ch_config)
\brief configure counter mode for the UTIMER instance.
\param[in] utimer Pointer to the UTIMER register map
\param[in] channel channel number
\param[in] mode counter mode
\param[in] ch_config Pointer to the UTIMER channel specific config structure
\return none
*/
void utimer_config_mode (UTIMER_Type *utimer, uint8_t channel, UTIMER_MODE mode, utimer_channel_config *ch_config)
{
switch (mode)
{
case UTIMER_MODE_BASIC:
{
/* enabling drive output */
utimer_driver_output_enable(utimer, channel, ch_config);
if (ch_config->driver_A)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_A |= (COMPARE_CTRL_DRV_DRIVER_EN|
(ch_config->driver_a_at_cycle_end<<2)|
(ch_config->driver_a_start_state<<4)|
(ch_config->driver_a_stop_state<<6));
}
if (ch_config->driver_B)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_B |= (COMPARE_CTRL_DRV_DRIVER_EN|
(ch_config->driver_b_at_cycle_end<<2)|
(ch_config->driver_b_start_state<<4)|
(ch_config->driver_b_stop_state<<6));
}
break;
}
case UTIMER_MODE_BUFFERING:
{
/* enabling drive output */
utimer_driver_output_enable(utimer, channel, ch_config);
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= BUF_OP_CTRL_CNTR_BUF_EN;
if (ch_config->buffering_type)
{//SET: Double Buffering
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= BUF_OP_CTRL_CNTR_BUF_OP_BIT1;
}
else
{//CLEAR: Single Buffering
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= BUF_OP_CTRL_CNTR_BUF_OP_BIT0;
}
if (ch_config->driver_A)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_A |= (COMPARE_CTRL_DRV_DRIVER_EN|
(ch_config->driver_a_at_cycle_end << 2)|
(ch_config->driver_a_start_state << 4)|
(ch_config->driver_a_stop_state << 6));
}
if (ch_config->driver_B)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_B |= (COMPARE_CTRL_DRV_DRIVER_EN|
(ch_config->driver_b_at_cycle_end << 2)|
(ch_config->driver_b_start_state << 4)|
(ch_config->driver_b_stop_state << 6));
}
break;
}
case UTIMER_MODE_TRIGGERING:
{
/* disabling drive output */
utimer_driver_output_disable(utimer, channel);
break;
}
case UTIMER_MODE_CAPTURING:
{
/* disabling drive output */
utimer_driver_output_disable(utimer, channel);
if (ch_config->buffer_operation)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= (BUF_OP_CTRL_CAPTURE_BUF_EN|
(ch_config->capt_buffer_type_A << 16)|
(ch_config->capt_buffer_type_B << 18));
}
break;
}
case UTIMER_MODE_COMPARING:
{
/* enabling drive output */
utimer_driver_output_enable(utimer, channel, ch_config);
if (ch_config->driver_A)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_A |= (COMPARE_CTRL_DRV_COMPARE_EN|COMPARE_CTRL_DRV_DRIVER_EN|
(ch_config->driver_a_at_cycle_end << 2)|
(ch_config->driver_a_at_comp_match)|
(ch_config->driver_a_start_state << 4)|
(ch_config->driver_a_stop_state << 6));
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= ((ch_config->comp_buffer_at_crest << 24)|
(ch_config->comp_buffer_at_trough << 25));
if (ch_config->buffer_operation)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= (BUF_OP_CTRL_COMPARE_BUF_EN|(ch_config->buffering_type << 26));
}
if (ch_config->fixed_buffer)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= BUF_OP_CTRL_FORCE_COMPARE_BUF_OP;
}
if (ch_config->dma_ctrl)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_A |= COMPARE_CTRL_DRV_DMA_CLEAR_EN;
}
}
if (ch_config->driver_B)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_B |= (COMPARE_CTRL_DRV_DRIVER_EN|COMPARE_CTRL_DRV_COMPARE_EN|
(ch_config->driver_b_at_cycle_end << 2)|
(ch_config->driver_b_at_comp_match)|
(ch_config->driver_b_start_state << 4)|
(ch_config->driver_b_stop_state << 6));
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= ((ch_config->comp_buffer_at_crest << 28)|
(ch_config->comp_buffer_at_trough << 29));
if (ch_config->buffer_operation)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= (BUF_OP_CTRL_COMPARE_BUF_EN|(ch_config->buffering_type << 30));
}
if (ch_config->fixed_buffer)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_BUF_OP_CTRL |= BUF_OP_CTRL_FORCE_COMPARE_BUF_OP;
}
if (ch_config->dma_ctrl)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_B |= COMPARE_CTRL_DRV_DMA_CLEAR_EN;
}
}
break;
}
case UTIMER_MODE_DEAD_TIME:
{
/* enabling drive output */
utimer_driver_output_enable(utimer, channel, ch_config);
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DEAD_TIME_CTRL |= DEAD_TIME_CTRL_DT_EN;
if (ch_config->buffer_operation)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DEAD_TIME_CTRL |= DEAD_TIME_CTRL_DT_BUF_EN;
}
if (ch_config->driver_A)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_A |= (COMPARE_CTRL_DRV_DRIVER_EN|COMPARE_CTRL_DRV_COMPARE_EN|
(ch_config->driver_a_at_cycle_end << 2)|
(ch_config->driver_a_at_comp_match)|
(ch_config->driver_a_start_state << 4)|
(ch_config->driver_a_stop_state << 6));
}
if (ch_config->driver_B)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_CTRL_B |= (COMPARE_CTRL_DRV_DRIVER_EN|COMPARE_CTRL_DRV_COMPARE_EN|
(ch_config->driver_b_at_cycle_end << 2)|
(ch_config->driver_b_at_comp_match)|
(ch_config->driver_b_start_state << 4)|
(ch_config->driver_b_stop_state << 6));
}
break;
}
}
}
/**
\fn void utimer_set_count (UTIMER_Type *utimer, uint8_t channel, UTIMER_COUNTER counter_type, uint32_t value)
\brief set counter value for the UTIMER instance.
\param[in] utimer Pointer to the UTIMER register map
\param[in] channel channel number
\param[in] counter_type counter type
\param[in] value counter value
\return none
*/
void utimer_set_count (UTIMER_Type *utimer, uint8_t channel, UTIMER_COUNTER counter_type, uint32_t value)
{
switch (counter_type)
{
case UTIMER_CNTR:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR = value;
break;
}
case UTIMER_CNTR_PTR:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR = value;
break;
}
case UTIMER_CNTR_PTR_BUF1:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR_BUF1 = value;
break;
}
case UTIMER_CNTR_PTR_BUF2:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR_BUF2 = value;
break;
}
case UTIMER_DT_UP:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_UP = value;
break;
}
case UTIMER_DT_UP_BUF1:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_UP_BUF1 = value;
break;
}
case UTIMER_DT_DOWN:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_DOWN = value;
break;
}
case UTIMER_DT_DOWN_BUF1:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_DOWN_BUF1 = value;
break;
}
case UTIMER_COMPARE_A:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A = value;
break;
}
case UTIMER_COMPARE_B:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B = value;
break;
}
case UTIMER_COMPARE_A_BUF1:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A_BUF1 = value;
break;
}
case UTIMER_COMPARE_B_BUF1:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B_BUF1 = value;
break;
}
case UTIMER_COMPARE_A_BUF2:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A_BUF2 = value;
break;
}
case UTIMER_COMPARE_B_BUF2:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B_BUF2 = value;
break;
}
default:
break;
}
}
/**
\fn uint32_t utimer_get_count (UTIMER_Type *utimer, uint8_t channel, UTIMER_COUNTER counter, utimer_channel_config *ch_config)
\brief get counter direction for the UTIMER instance.
\param[in] utimer Pointer to the UTIMER register map
\param[in] channel channel number
\param[in] counter_type counter type
\return current counter value
*/
uint32_t utimer_get_count (UTIMER_Type *utimer, uint8_t channel, UTIMER_COUNTER counter_type)
{
uint32_t value = 0;
switch (counter_type)
{
case UTIMER_CNTR:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR;
break;
}
case UTIMER_CNTR_PTR:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR;
break;
}
case UTIMER_CNTR_PTR_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR_BUF1;
break;
}
case UTIMER_CNTR_PTR_BUF2:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PTR_BUF2;
break;
}
case UTIMER_DT_UP:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_UP;
break;
}
case UTIMER_DT_UP_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_UP_BUF1;
break;
}
case UTIMER_DT_DOWN:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_DOWN;
break;
}
case UTIMER_DT_DOWN_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DT_DOWN_BUF1;
break;
}
case UTIMER_COMPARE_A:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A;
break;
}
case UTIMER_COMPARE_B:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B;
break;
}
case UTIMER_COMPARE_A_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A_BUF1;
break;
}
case UTIMER_COMPARE_B_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B_BUF1;
break;
}
case UTIMER_COMPARE_A_BUF2:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_A_BUF2;
break;
}
case UTIMER_COMPARE_B_BUF2:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_COMPARE_B_BUF2;
break;
}
case UTIMER_CAPTURE_A:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_A;
break;
}
case UTIMER_CAPTURE_B:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_B;
break;
}
case UTIMER_CAPTURE_A_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_A_BUF1;
break;
}
case UTIMER_CAPTURE_B_BUF1:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_B_BUF1;
break;
}
case UTIMER_CAPTURE_A_BUF2:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_A_BUF2;
break;
}
case UTIMER_CAPTURE_B_BUF2:
{
value = utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CAPTURE_B_BUF2;
break;
}
}
return value;
}
/**
\fn void utimer_config_trigger (UTIMER_Type *utimer, uint8_t channel, UTIMER_TRIGGER_CONFIG *config_control, utimer_channel_config *ch_config)
\brief configure trigger for the UTIMER instance.
\param[in] utimer Pointer to the UTIMER register map
\param[in] channel channel number
\param[in] config_control Pointer to a trigger configure type argument
\param[in] ch_config Pointer to the UTIMER channel specific config structure
\return none
*/
void utimer_config_trigger (UTIMER_Type *utimer, uint8_t channel, UTIMER_TRIGGER_CONFIG *config_control, utimer_channel_config *ch_config)
{
if(config_control->src_type == UTIMER_SRC_0)
{
switch (config_control->trigger_target)
{
case UTIMER_TRIGGER_START:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_START_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_START_0_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_STOP:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_STOP_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_STOP_0_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CLEAR:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CLEAR_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CLEAR_0_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_UPCOUNT:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_UP_0_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DOWNCOUNT:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DOWN_0_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CAPTURE_A:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_TRIG_CAPTURE_SRC_A_0 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CAPTURE_B:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_TRIG_CAPTURE_SRC_B_0 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DMA_CLEAR_A:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DMA_CLEAR_SRC_A_0 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DMA_CLEAR_B:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DMA_CLEAR_SRC_B_0 |= config_control->trigger_type;
break;
}
}
}
if(config_control->src_type == UTIMER_SRC_1)
{
switch (config_control->trigger_target)
{
case UTIMER_TRIGGER_START:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_START_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_START_1_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_STOP:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_STOP_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_STOP_1_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CLEAR:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CLEAR_1_SRC &= ~(CNTR_SRC1_PGM_EN); /* disabling pgm_en */
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CLEAR_1_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_UPCOUNT:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_UP_1_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DOWNCOUNT:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DOWN_1_SRC |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CAPTURE_A:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_TRIG_CAPTURE_SRC_A_1 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_CAPTURE_B:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_TRIG_CAPTURE_SRC_B_1 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DMA_CLEAR_A:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DMA_CLEAR_SRC_A_1 |= config_control->trigger_type;
break;
}
case UTIMER_TRIGGER_DMA_CLEAR_B:
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_DMA_CLEAR_SRC_B_1 |= config_control->trigger_type;
break;
}
}
}
if(config_control->src_type == UTIMER_FAULT_TRIGGER)
{
if (ch_config->driver_A) {
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_FAULT_CTRL |= (config_control->trigger_type | ch_config->fault_type << 8);
}
if (ch_config->driver_B) {
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_FAULT_CTRL |= (config_control->trigger_type << 16 | ch_config->fault_type << 24);
}
}
if(config_control->src_type == UTIMER_CNTR_PAUSE_TRIGGER)
{
utimer->UTIMER_CHANNEL_CFG[channel].UTIMER_CNTR_PAUSE_SRC |= config_control->trigger_type;
}
}