diff --git a/timer/counter.c b/timer/counter.c new file mode 100644 index 0000000..96b088d --- /dev/null +++ b/timer/counter.c @@ -0,0 +1,43 @@ +#include "counter.h" +#include "modules/modules.h" +#include "utils/counter.h" + + +METHOD_INIT_IMPL(M_counter, cnt) +{ +} + +METHOD_DEINIT_IMPL(M_counter, cnt) +{ +} + +static void counter_control(M_counter* cnt) +{ + if(cnt->control & CONTROL_START){ + cnt->out_value = 0; + cnt->m_ref_counter = sys_time.r_counter_ms; + + cnt->status = STATUS_RUN; + } + if(cnt->control & CONTROL_STOP){ + + cnt->status = STATUS_NONE; + } + + cnt->control = CONTROL_NONE; +} + +METHOD_CALC_IMPL(M_counter, cnt) +{ + counter_control(cnt); + + if(cnt->status & STATUS_RUN){ + // Пройденное время с начала счёта. + cnt->out_value = counter_calc_diff(sys_time.r_counter_ms, cnt->m_ref_counter); + } +} + +METHOD_CONTROL_IMPL(M_counter, cnt) +{ + counter_control(cnt); +} diff --git a/timer/counter.h b/timer/counter.h new file mode 100644 index 0000000..2cd43c6 --- /dev/null +++ b/timer/counter.h @@ -0,0 +1,65 @@ +#ifndef COUNTER_H +#define COUNTER_H + +#include "module/base.h" + + +//! Перечисление возможных бит управления. +enum _E_Counter_Control { + COUNTER_CONTROL_NONE = CONTROL_NONE, + COUNTER_CONTROL_START = CONTROL_START, + COUNTER_CONTROL_STOP = CONTROL_STOP, +}; + +//! Перечисление возможных бит статуса. +enum _E_Counter_Status { + COUNTER_STATUS_NONE = STATUS_NONE, + COUNTER_STATUS_RUN = STATUS_RUN, +}; + +//! Предварительная декларация типа модуля. +typedef struct _S_Counter M_counter; + +//! Структура модуля. +struct _S_Counter { + // Базовые поля. + control_t control; //!< Слово управления. + status_t status; //!< Слово состояния. + // Входные данные. + // Выходные данные. + reg_u32_t out_value; //!< Значение счётчика. + // Параметры. + // Регистры. + // Методы. + METHOD_INIT(M_counter); + METHOD_DEINIT(M_counter); + METHOD_CALC(M_counter); + METHOD_CONTROL(M_counter); + // Коллбэки. + // Внутренние данные. + uint32_t m_ref_counter; //!< Опорное значение счётчика. +}; + +EXTERN METHOD_INIT_PROTO(M_counter); +EXTERN METHOD_DEINIT_PROTO(M_counter); +EXTERN METHOD_CALC_PROTO(M_counter); +EXTERN METHOD_CONTROL_PROTO(M_counter); + +#define COUNTER_DEFAULTS {\ + /* Базовые поля */\ + 0, 0, /* control, status */\ + /* Входные данные */\ + /* Выходные данные */\ + 0, /* out_value */\ + /* Параметры */\ + /* Регистры */\ + /* Методы */\ + METHOD_INIT_PTR(M_counter), METHOD_DEINIT_PTR(M_counter),\ + METHOD_CALC_PTR(M_counter),\ + METHOD_CONTROL_PTR(M_counter),\ + /* Коллбэки */\ + /* Внутренние данные */\ + 0, /* m_ref_counter */\ + } + +#endif /* COUNTER_H */ diff --git a/timer/timer.c b/timer/timer.c index cfb47c3..5d5285b 100644 --- a/timer/timer.c +++ b/timer/timer.c @@ -1,5 +1,6 @@ #include "timer.h" #include "modules/modules.h" +#include "utils/counter.h" METHOD_INIT_IMPL(M_timer, tim) @@ -32,14 +33,6 @@ static void timer_control(M_timer* tim) tim->control = CONTROL_NONE; } -static uint32_t timer_calc_diff(uint32_t ref, uint32_t cur) -{ - // Текущее значение больше опорного - счётчик не переполнился. - if(cur >= ref) return cur - ref; - // Иначе cur < ref - счётчик переполнился. - return UINT32_MAX - ref + cur + 1; -} - METHOD_CALC_IMPL(M_timer, tim) { tim->out_timeout = STROBE_NONE; @@ -48,7 +41,7 @@ METHOD_CALC_IMPL(M_timer, tim) if(tim->status & STATUS_RUN){ // Пройденное время с начала счёта. - uint32_t elapsed_time = timer_calc_diff(tim->m_ref_counter, sys_time.r_counter_ms); + uint32_t elapsed_time = counter_calc_diff(sys_time.r_counter_ms, tim->m_ref_counter); // Если времени прошло больше чем интервал таймера. if(elapsed_time >= tim->r_interval){ tim->status = STATUS_NONE; diff --git a/timer/timer.h b/timer/timer.h index f0d1297..d36bcf0 100644 --- a/timer/timer.h +++ b/timer/timer.h @@ -19,6 +19,7 @@ enum _E_Timer_Control { //! Перечисление возможных бит статуса. enum _E_Timer_Status { TIMER_STATUS_NONE = STATUS_NONE, + TIMER_STATUS_RUN = STATUS_RUN, }; //! Предварительная декларация типа модуля. diff --git a/timer/timer_on.c b/timer/timer_on.c new file mode 100644 index 0000000..36bf1b0 --- /dev/null +++ b/timer/timer_on.c @@ -0,0 +1,41 @@ +#include "timer_on.h" + + +METHOD_INIT_IMPL(M_timer_on, tmr) +{ +} + +METHOD_DEINIT_IMPL(M_timer_on, tmr) +{ +} + +METHOD_CALC_IMPL(M_timer_on, tmr) +{ + tmr->m_ed.in_value = tmr->in_value; + CALC(tmr->m_ed); + + flag_t res = FLAG_NONE; + flag_t cur = FLAG_NONE; + + switch(tmr->m_ed.out_value){ + default: + case EDGE_DETECT_LOW: + break; + case EDGE_DETECT_HIGH: + cur = FLAG_ACTIVE; + break; + case EDGE_DETECT_LEADING: + tmr->r_tmr.control = CONTROL_START; + CONTROL(tmr->r_tmr); + break; + case EDGE_DETECT_FALLING: + tmr->r_tmr.control = CONTROL_STOP; + CONTROL(tmr->r_tmr); + break; + } + CALC(tmr->r_tmr); + + res = (cur & tmr->r_tmr.out_expired); + + tmr->out_value = res; +} diff --git a/timer/timer_on.h b/timer/timer_on.h new file mode 100644 index 0000000..5135464 --- /dev/null +++ b/timer/timer_on.h @@ -0,0 +1,71 @@ +#ifndef TIMER_ON_H +#define TIMER_ON_H + +#include "module/base.h" +#include "edge_detect/edge_detect.h" +#include "timer.h" + + +//! Перечисление возможных бит управления. +enum _E_Timer_On_Control { + TIMER_ON_CONTROL_NONE = CONTROL_NONE, +}; + +//! Перечисление возможных бит статуса. +enum _E_Timer_On_Status { + TIMER_ON_STATUS_NONE = STATUS_NONE, +}; + +//! Предварительная декларация типа модуля. +typedef struct _S_Timer_On M_timer_on; + +//! Структура модуля. +struct _S_Timer_On { + // Базовые поля. + control_t control; //!< Слово управления. + status_t status; //!< Слово состояния. + // Входные данные. + flag_t in_value; //!< Входное значение сигнала. + // Выходные данные. + flag_t out_value; //!< Выходное значение сигнала. + // Параметры. + //reg_u32_t r_time_on_ms; //!< Время задержки в мс. // в m_tmr. + // Регистры. + M_timer r_tmr; //!< Таймер времени до срабатывания выхода. + // Методы. + METHOD_INIT(M_timer_on); + METHOD_DEINIT(M_timer_on); + METHOD_CALC(M_timer_on); + // Коллбэки. + // Внутренние данные. + // Внутренние модули. + M_edge_detect m_ed; //!< Детект фронта. +}; + +EXTERN METHOD_INIT_PROTO(M_timer_on); +EXTERN METHOD_DEINIT_PROTO(M_timer_on); +EXTERN METHOD_CALC_PROTO(M_timer_on); + +#define TIMER_ON_DEFCFG(TIME) {\ + /* Базовые поля */\ + 0, 0, /* control, status */\ + /* Входные данные */\ + 0, /* in_value */\ + /* Выходные данные */\ + 0, /* out_value */\ + /* Параметры */\ + /* Регистры */\ + TIMER_DEFCFG(TIME), /* r_tmr */\ + /* TIME,*/ /* r_time_on_ms */\ + /* Методы */\ + METHOD_INIT_PTR(M_timer_on), METHOD_DEINIT_PTR(M_timer_on),\ + METHOD_CALC_PTR(M_timer_on),\ + /* Коллбэки */\ + /* Внутренние данные */\ + /* Внутренние модули */\ + EDGE_DETECT_DEFAULTS, /* m_ed */\ + } + +#define TIMER_ON_DEFAULTS TIMER_ON_DEFCFG(0) + +#endif /* TIMER_ON_H */ diff --git a/utils/counter.h b/utils/counter.h new file mode 100755 index 0000000..144f0c2 --- /dev/null +++ b/utils/counter.h @@ -0,0 +1,25 @@ +#ifndef UTILS_COUNTER_H +#define UTILS_COUNTER_H + + +#include +#include "defs/defs.h" + + +/** + * Вычисляет разницу двух счётчиков + * с учётом возможного переполнения. + * @param cur Текущее значение счётчика. + * @param ref Опорное (прошлое) значение счётчика. + * @return Разница. + */ +ALWAYS_INLINE static uint32_t counter_calc_diff(uint32_t cur, uint32_t ref) +{ + // Текущее значение больше опорного - счётчик не переполнился. + if(cur >= ref) return cur - ref; + // Иначе cur < ref - счётчик переполнился. + return UINT32_MAX - ref + cur + 1; +} + + +#endif /* UTILS_COUNTER_H */