summaryrefslogtreecommitdiff
path: root/Year_3/LSM
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2022-01-26 22:45:46 +0100
committerSanto Cariotti <santo@dcariotti.me>2022-01-26 22:45:46 +0100
commit87f55b05f3fb3f7164594362d95f205569c5e6b5 (patch)
tree1d39f7e39ee004131546b9ba1b04ee34c625f204 /Year_3/LSM
parentbe0b89e3ce73018e1fb437905e1cf26bf26a9927 (diff)
add exam
Diffstat (limited to 'Year_3/LSM')
-rw-r--r--Year_3/LSM/ex_20211122.c264
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);
+ }
+}