/** @file tim.h
 * Module handling general purpose and advances TIMers
 */

#ifndef _TIM_H_
#define _TIM_H_

//--includes--------------------------------------------------------------------

#include "stdint.h"


//--type definitions------------------------------------------------------------

enum TimPeriph {
	TIM_PERIPH_1,
	TIM_PERIPH_2,
	TIM_PERIPH_3,
	TIM_PERIPH_4,
};

enum TimChannel {
	TIM_CHANNEL_1,
	TIM_CHANNEL_2,
	TIM_CHANNEL_3,
	TIM_CHANNEL_4,
};

enum TimConfig {
	TIM_CONFIG_DISABLE_UPDATES    = (0x1 <<  1),
	TIM_CONFIG_LIMIT_UPDATE_SRC   = (0x1 <<  2),
	TIM_CONFIG_CONTINUOUS         = (0x0 <<  3),
	TIM_CONFIG_ONE_SHOT           = (0x1 <<  3),
	TIM_CONFIG_DIR_UP             = (0x0 <<  4),
	TIM_CONFIG_DIR_DOWN           = (0x1 <<  4),
	TIM_CONFIG_CENTER_ALIGNED_1   = (0x1 <<  5),
	TIM_CONFIG_CENTER_ALIGNED_2   = (0x2 <<  5),
	TIM_CONFIG_CENTER_ALIGNED_3   = (0x3 <<  5),
	TIM_CONFIG_BUFFERED_ARR       = (0x1 <<  7),
	TIM_CONFIG_FILTER_CLOCK_DIV_1 = (0x0 <<  8),
	TIM_CONFIG_FILTER_CLOCK_DIV_2 = (0x1 <<  8),
	TIM_CONFIG_FILTER_CLOCK_DIV_4 = (0x2 <<  8),
	TIM_CONFIG_DMA_ON_CC_EVENT    = (0x0 << 19),
	TIM_CONFIG_DMA_ON_UPDATE      = (0x1 << 19),
	TIM_CONFIG_XOR_TI1            = (0x1 << 23),
};

enum TimMasterConfig {
	TIM_MASTER_CONFIG_MODE_RESET       = (0x0 << 4),
	TIM_MASTER_CONFIG_MODE_ENABLE      = (0x1 << 4),
	TIM_MASTER_CONFIG_MODE_UPDATE      = (0x2 << 4),
	TIM_MASTER_CONFIG_MODE_COMP_PULSE  = (0x3 << 4),
	TIM_MASTER_CONFIG_MODE_COMP_1      = (0x4 << 4),
	TIM_MASTER_CONFIG_MODE_COMP_2      = (0x5 << 4),
	TIM_MASTER_CONFIG_MODE_COMP_3      = (0x6 << 4),
	TIM_MASTER_CONFIG_MODE_COMP_4      = (0x7 << 4),

};

enum TimSlaveConfig {
	TIM_SLAVE_CONFIG_MODE_ENCODER_1    = (0x1 <<  0),
	TIM_SLAVE_CONFIG_MODE_ENCODER_2    = (0x2 <<  0),
	TIM_SLAVE_CONFIG_MODE_ENCODER_3    = (0x3 <<  0),
	TIM_SLAVE_CONFIG_MODE_RESET        = (0x4 <<  0),
	TIM_SLAVE_CONFIG_MODE_GATED        = (0x5 <<  0),
	TIM_SLAVE_CONFIG_MODE_TRIGGER      = (0x6 <<  0),
	TIM_SLAVE_CONFIG_MODE_EXT_CLK      = (0x7 <<  0),
	TIM_SLAVE_CONFIG_TRIG_INTERNAL_1   = (0x0 <<  4),
	TIM_SLAVE_CONFIG_TRIG_INTERNAL_2   = (0x1 <<  4),
	TIM_SLAVE_CONFIG_TRIG_INTERNAL_3   = (0x2 <<  4),
	TIM_SLAVE_CONFIG_TRIG_INTERNAL_4   = (0x3 <<  4),
	TIM_SLAVE_CONFIG_TRIG_EDGE_DETECT  = (0x4 <<  4),
	TIM_SLAVE_CONFIG_TRIG_FILTERED_1   = (0x5 <<  4),
	TIM_SLAVE_CONFIG_TRIG_FILTERED_2   = (0x6 <<  4),
	TIM_SLAVE_CONFIG_TRIG_EXT          = (0x7 <<  4),
};

enum TimExtConfig {
	TIM_EXT_CONFIG_FILTER_1        = (0x1 <<  8),
	TIM_EXT_CONFIG_FILTER_2        = (0x2 <<  8),
	TIM_EXT_CONFIG_FILTER_3        = (0x3 <<  8),
	TIM_EXT_CONFIG_FILTER_4        = (0x4 <<  8),
	TIM_EXT_CONFIG_FILTER_5        = (0x5 <<  8),
	TIM_EXT_CONFIG_FILTER_6        = (0x6 <<  8),
	TIM_EXT_CONFIG_FILTER_7        = (0x7 <<  8),
	TIM_EXT_CONFIG_FILTER_8        = (0x8 <<  8),
	TIM_EXT_CONFIG_FILTER_9        = (0x9 <<  8),
	TIM_EXT_CONFIG_FILTER_10       = (0xA <<  8),
	TIM_EXT_CONFIG_FILTER_11       = (0xB <<  8),
	TIM_EXT_CONFIG_FILTER_12       = (0xC <<  8),
	TIM_EXT_CONFIG_FILTER_13       = (0xD <<  8),
	TIM_EXT_CONFIG_FILTER_14       = (0xE <<  8),
	TIM_EXT_CONFIG_FILTER_15       = (0xF <<  8),
	TIM_EXT_CONFIG_PRESCALER_DIV_1 = (0x0 <<  12),
	TIM_EXT_CONFIG_PRESCALER_DIV_2 = (0x1 <<  12),
	TIM_EXT_CONFIG_PRESCALER_DIV_4 = (0x2 <<  12),
	TIM_EXT_CONFIG_PRESCALER_DIV_8 = (0x3 <<  12),
	TIM_EXT_CONFIG_USE_AS_CLK      = (0x3 <<  14),
	TIM_EXT_CONFIG_INVERT          = (0x3 <<  15),
};

enum TimOutputConfig {
	TIM_OUTPUT_CONFIG_FAST_MODE           = (0x1 << 2),
	TIM_OUTPUT_CONFIG_PRELOAD_EN          = (0x1 << 3),
	TIM_OUTPUT_CONFIG_MODE_FROZEN         = (0x0 << 4),
	TIM_OUTPUT_CONFIG_MODE_ACTIVE         = (0x1 << 4),
	TIM_OUTPUT_CONFIG_MODE_INACTIVE       = (0x2 << 4),
	TIM_OUTPUT_CONFIG_MODE_TOGGLE         = (0x3 << 4),
	TIM_OUTPUT_CONFIG_MODE_FORCE_ACTIVE   = (0x4 << 4),
	TIM_OUTPUT_CONFIG_MODE_FORCE_INACTIVE = (0x5 << 4),
	TIM_OUTPUT_CONFIG_MODE_PWM_1          = (0x6 << 4),
	TIM_OUTPUT_CONFIG_MODE_PWM_2          = (0x7 << 4),
	TIM_OUTPUT_CONFIG_CLEAR_ON_EXT_TRIG   = (0x1 << 7),
};

enum TimIntputConfig {
	TIM_INPUT_CONFIG_ALTERNATE_TRIGGER      = (0x2 << 0),
	TIM_INPUT_CONFIG_INTERNAL_TRIGGER       = (0x3 << 0),
	TIM_INPUT_CONFIG_PRESCALER_1            = (0x0 << 2),
	TIM_INPUT_CONFIG_PRESCALER_2            = (0x1 << 2),
	TIM_INPUT_CONFIG_PRESCALER_4            = (0x2 << 2),
	TIM_INPUT_CONFIG_PRESCALER_8            = (0x3 << 2),
};

enum TimIRQSource {
	TIM_IRQ_SOURCE_TRIGGER,
	TIM_IRQ_SOURCE_UPDATE,
};

typedef void (*TimCallback)(enum TimIRQSource src);


//--functions-------------------------------------------------------------------


void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
		enum TimMasterConfig master_config_mask, TimCallback callback);
void tim_configure_slave(enum TimPeriph periph, enum TimConfig config_mask,
		enum TimSlaveConfig slave_config_mask, TimCallback callback);

void tim_start(enum TimPeriph periph);
void tim_stop(enum TimPeriph periph);
void tim_update(enum TimPeriph periph);

void tim_set_auto_reload(enum TimPeriph periph, uint16_t auto_reload);
void tim_set_prescaler(enum TimPeriph periph, uint16_t prescaler);
void tim_set_counter(enum TimPeriph periph, uint16_t counter);

uint16_t tim_get_auto_reload(enum TimPeriph periph);
uint16_t tim_get_prescaler(enum TimPeriph periph);
uint16_t tim_get_counter(enum TimPeriph periph);

void tim_configure_output_channel(enum TimPeriph periph,
		enum TimChannel channel_mask, enum TimOutputConfig config_mask,
		uint16_t value);
void tim_configure_input_channel(enum TimPeriph periph,
		enum TimChannel channel_mask, enum TimInputConfig config_mask,
		uint16_t value);
void tim_configure_ext_trigger(enum TimPeriph periph,
		enum TimExtConfig ext_config_mask);

#endif //_TIM_H_

