diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-01-26 22:45:46 +0100 | 
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-01-26 22:45:46 +0100 | 
| commit | 87f55b05f3fb3f7164594362d95f205569c5e6b5 (patch) | |
| tree | 1d39f7e39ee004131546b9ba1b04ee34c625f204 /Year_3 | |
| parent | be0b89e3ce73018e1fb437905e1cf26bf26a9927 (diff) | |
add exam
Diffstat (limited to 'Year_3')
| -rw-r--r-- | Year_3/LSM/ex_20211122.c | 264 | 
1 files changed, 264 insertions, 0 deletions
diff --git a/Year_3/LSM/ex_20211122.c b/Year_3/LSM/ex_20211122.c new file mode 100644 index 0000000..a7980e1 --- /dev/null +++ b/Year_3/LSM/ex_20211122.c @@ -0,0 +1,264 @@ +#include "stm32_unict_lib.h" +#include <stdlib.h> +#include <string.h> + +typedef enum { +    FIRST = 2, +    F_S, +    SECOND, +    S_T, +    THIRD +} floor_t; + +typedef enum { +    CONFIG, +    IDLE, +    CLOSING, +    RUNNING, +    OPENING, +} status_t; + +floor_t curr_floor = FIRST; +floor_t next_floor = FIRST; +short direction = 1; + +unsigned q_index = 0; +floor_t* queue; + +status_t status = IDLE; + +short circular_200ms = 0; /* alternates 0 and 1 thanks to `0 ^ 1` */ +short handle_1500ms = 0; /* until 15, then restart */ + +int time = 10; /* 10 * `time` = 1s */ +int lift_time; +int time_i = 0; + +void +init() +{ +    int i; +    queue = malloc(sizeof(floor_t) * 10); +    for (i = 0; i < 10; ++i) +        queue[i] = 0; + +    GPIO_init(GPIOB); +    GPIO_init(GPIOC); + +    GPIO_config_input(GPIOB, 10); /* X */ +    GPIO_config_EXTI(GPIOB, EXTI10); +    EXTI_enable(EXTI10, FALLING_EDGE); + +    GPIO_config_input(GPIOB, 4); /* Y */ +    GPIO_config_EXTI(GPIOB, EXTI4); +    EXTI_enable(EXTI4, FALLING_EDGE); + +    GPIO_config_input(GPIOB, 5); /* Z */ +    GPIO_config_EXTI(GPIOB, EXTI5); +    EXTI_enable(EXTI5, FALLING_EDGE); + +    GPIO_config_input(GPIOB, 6); /* T */ +    GPIO_config_EXTI(GPIOB, EXTI6); +    EXTI_enable(EXTI6, FALLING_EDGE); + +    GPIO_config_output(GPIOC, 2); /* YELLOW */ +    GPIO_config_output(GPIOC, 3); /* GREEN */ +    GPIO_config_output(GPIOB, 0); /* RED */ + +    DISPLAY_init(); + +    CONSOLE_init(); + +    TIM_init(TIM2); +    TIM_set(TIM2, 0); +    TIM_on(TIM2); +    TIM_config_timebase(TIM2, 8400, 840); +    TIM_enable_irq(TIM2, IRQ_UPDATE); + +    ADC_init(ADC1, ADC_RES_8, ADC_ALIGN_RIGHT); +    ADC_channel_config(ADC1, GPIOC, 1, 11); +    ADC_on(ADC1); +    ADC_sample_channel(ADC1, 11); + +    ADC_start(ADC1); +    while (!ADC_completed(ADC1)) +        ; +    int adc_read = ADC_read(ADC1); +    time = ((adc_read * (10 - 4) / 255.0) + 4); +} + +int +main() +{ +    init(); + +    char s[4]; +    int i; +    int adc_read; + +    sprintf(s, "%3d ", curr_floor); + +    for (;;) { +        ADC_start(ADC1); +        if (status == CONFIG) { +            while (!ADC_completed(ADC1)) +                ; +            adc_read = ADC_read(ADC1); +            time = ((adc_read * (10 - 4) / 255.0) + 4); +            sprintf(s, "%f", time / 10.0); +            DISPLAY_puts(0, s); +        } else { +            sprintf(s, "%3d%c", curr_floor / 2, ((curr_floor % 2) ? '-' : ' ')); +            DISPLAY_puts(0, s); +            lift_time = (time / 10 / 2.0) / 0.1; +        } +    } + +    free(queue); +    return 0; +} + +void +check_queue() +{ +    int i; + +    for (i = q_index; i != (q_index - 1) % 10; i = (i + 1) % 10) { +        if (queue[i] != 0) { +            goto_floor(queue[i]); +            queue[i] = 0; +            return; +        } +    } + +    if (queue[i] != 0) { +        goto_floor(queue[i]); +        queue[i] = 0; +    } +} + +void +    goto_floor(floor) +{ +    status = CLOSING; +    switch (floor) { +    case 1: +        next_floor = FIRST; +        break; +    case 2: +        next_floor = SECOND; +        break; +    case 3: +        next_floor = THIRD; +        break; +    } + +    if (curr_floor < next_floor) { +        direction = 1; +    } else if (curr_floor > next_floor) { +        direction = -1; +    } else { +        direction = 0; +    } +} + +void +    call_floor(floor) +{ +    if (queue[(q_index - 1) % 10] == floor) +        return; + +    if (status == IDLE) { +        goto_floor(floor); +    } else { +        queue[q_index] = floor; +        q_index = (q_index + 1) % 10; +    } +} + +void +EXTI15_10_IRQHandler(void) +{ +    if (EXTI_isset(EXTI10)) { +        call_floor(1); +        EXTI_clear(10); +    } +} + +void +EXTI9_5_IRQHandler(void) +{ +    if (EXTI_isset(EXTI5)) { +        call_floor(2); +        EXTI_clear(EXTI5); +    } + +    if (EXTI_isset(EXTI6)) { +        if (status == IDLE) { +            status = CONFIG; +        } else if (status == CONFIG) { +            status = IDLE; +        } +        EXTI_clear(EXTI6); +    } +} + +void +EXTI4_IRQHandler(void) +{ +    if (EXTI_isset(EXTI4)) { +        call_floor(3); +        EXTI_clear(EXTI4); +    } +} + +void +TIM2_IRQHandler(void) +{ +    if (TIM_update_check(TIM2)) { +        if (status == RUNNING) { +            if (circular_200ms) { +                GPIO_toggle(GPIOC, 2); +            } + +            time_i++; + +            if (time_i >= lift_time) { +                time_i = 0; +                if (curr_floor == next_floor) { +                    GPIO_write(GPIOC, 2, 0); +                    status = OPENING; +                    time_i = 0; +                } else { +                    curr_floor += direction; +                } +            } +        } else if (status == CLOSING || status == OPENING) { +            if (circular_200ms) { +                if (status == CLOSING) +                    GPIO_toggle(GPIOB, 0); +                else +                    GPIO_toggle(GPIOC, 3); +            } + +            handle_1500ms++; +            if (handle_1500ms == 15) { +                if (status == CLOSING) { +                    status = RUNNING; +                } else { +                    status = IDLE; +                } + +                handle_1500ms = 0; +                GPIO_write(GPIOB, 0, 0); +                GPIO_write(GPIOC, 3, 0); + +                if (status == IDLE) +                    check_queue(); +            } +        } + +        circular_200ms ^= 1; +        TIM_update_clear(TIM2); +    } +}  |