diff options
| author | Jan Sucan <sucanjan@fit.cvut.cz> | 2019-09-22 21:17:50 +0200 |
|---|---|---|
| committer | Jan Sucan <sucanjan@fit.cvut.cz> | 2019-09-22 21:17:50 +0200 |
| commit | cefd0601b91fa642163c82021d454b3c17d8adf4 (patch) | |
| tree | 0470eaa5d2186905f439c10e2bea8e86020d5cbe /FanController/fan_controller/delay.c | |
Initial commit
Diffstat (limited to 'FanController/fan_controller/delay.c')
| -rw-r--r-- | FanController/fan_controller/delay.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/FanController/fan_controller/delay.c b/FanController/fan_controller/delay.c new file mode 100644 index 0000000..9f793b9 --- /dev/null +++ b/FanController/fan_controller/delay.c @@ -0,0 +1,113 @@ +/* Autor: Ján Sučan <jan@jansucan.sk> + * + * Zdrojove kody, ich casti a subory z nich vzniknute priamo alebo nepriamo + * (objektove subory, Intel Hex, ...) prosim nepouzivajte komercne, ani ako + * sucast komercnych diel. Vsetky ostatne pripady pouzitia su dovolene. + * + * Please don't use the source codes, their parts and files created from them + * directly or indirectly, (object files, Intel Hex files, ...) for commercial + * purposes, not even as a part of commercial products. All other use cases + * are allowed. + */ + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include <fan_controller/delay.h> +#include <fan_controller/error.h> + +/** Pocet milisekund pre jeden tik casovaca. */ +#define DELAY_MS_FOR_1_TIMER_TICK 16U // ms + +/** Pristup k hodnote systemoveho casu priamo bez zakazania presusenia (nie bezpecny). */ +#define DELAY_SYSTEM_TIME_UNSAFE (delay_system_time) + +static uint32_t delay_get_system_time(void); + +/** Systemovy cas. Inkrementuje sa vzdy s kazdym pretecenim Casovaca 2. */ +static volatile uint32_t delay_system_time = 0; + +/** + * @brief Obsluha pretecenie Casovaca 2. Inkrementuje sa systemovy cas. + */ +ISR(TIMER2_OVF_vect) +{ + delay_system_time++; +} + +/** + * @brief Inicializacia cakania a systemoveho casu. + */ +void +delay_init(void) +{ + delay_system_time = 0; + // Enable interrupt + TIMSK |= (1 << TOIE2); +} + +/** + * @brief Blokujuce cakanie zadaneho poctu milisekund. Minimalna hodnota je 16. + * + * @param ms Pocet milisekund ktore sa bude cakat. + */ +void +delay_ms(unsigned int ms) +{ + const uint32_t d = delay_get_deadline_ms(ms); + bool end_waiting = false; + + while (!end_waiting) { + // Aby sa nemuselo stale zakazovat a povolovat prerusenie, dosiahnutie konca cakanie sa detekuje najprv len priblizne + if (DELAY_SYSTEM_TIME_UNSAFE > d) { + // Potom sa skontroluje aj presne, tzn. hodnota systemoveho casovaca sa ziska so zakazanim prerusenia. + if (delay_get_system_time() > d) { + end_waiting = true; + } + } + } +} + +/** + * @brief Bezpecne ziskanie hodnoty systemoveho casu. + * + * Zakaze sa prerusenie od Casovaca 2 pri pristupe k premennej zdielanej s obsluhou prerusenia. + * + * @return Hodnota systemoveho casovaca. + */ +uint32_t +delay_get_system_time(void) +{ + TIMSK &= ~(1 << TOIE2); + const uint32_t t = DELAY_SYSTEM_TIME_UNSAFE; + TIMSK |= (1 << TOIE2); + return t; +} + +/** + * @brief Ziskanie buducej hodnoty systemoveho casu, ktora sa dosiahne za zadany pocet milisekund. + * + * @param ms Pocet milisekund pre cakanie. Minimalna hodnota je 16. + * @return Hodnota systemoveho casu, ktora sa dosiahne za zadany pocet milisekund. + */ +uint32_t +delay_get_deadline_ms(uint16_t ms) +{ + if (ms < DELAY_MS_FOR_1_TIMER_TICK) { + error(); + } + return (delay_get_system_time() + (ms / DELAY_MS_FOR_1_TIMER_TICK)); +} + +/** + * @brief Zistenie, ci bola prekrocena zadana hodnota systemoveho casovaca. + * + * @param deadline Hodnota systemoveho casu z funkcie delay_get_deadline_ms(). + * @retval true Hodnota bola prekrocena. + * @retval false Hodnota nebola prekrocena. + */ +bool +delay_has_deadline_expired(uint32_t deadline) +{ + return (delay_get_system_time() > deadline); +}
\ No newline at end of file |
