Project

General

Profile

Statistics
| Revision:

root / lab4 / state_machine.c @ 91

History | View | Annotate | Download (4.31 KB)

1 78 up20180655
#include <lcom/lcf.h>
2
3
#include "state_machine.h"
4
#include "mouse_macros.h"
5
#include "mouse.h"
6
#include "errors.h"
7 79 up20180655
#include "utils.h"
8 78 up20180655
9
struct mouse_ev* mouse_get_event(struct packet *pp) {
10
    static struct mouse_ev event;
11 91 up20180655
    static uint8_t last = 0;
12 78 up20180655
13
    if (pp == NULL)
14
        return &event;
15
16 91 up20180655
    // current button presses
17
    uint8_t button_presses = pp->bytes[0] & (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON);
18 79 up20180655
    int16_t delta_x = pp->delta_x;
19
    int16_t delta_y = pp->delta_y;
20 78 up20180655
21 91 up20180655
    if ((button_presses ^ last) == LEFT_BUTTON && !(last & LEFT_BUTTON)) {
22
        event.type = LB_PRESSED;
23
        last |= LEFT_BUTTON;
24 78 up20180655
25 91 up20180655
    } else if ((button_presses ^ last) == RIGHT_BUTTON && !(last & RIGHT_BUTTON)) {
26
        event.type = RB_PRESSED;
27
        last |= RIGHT_BUTTON;
28 78 up20180655
29 91 up20180655
    } else if ((button_presses ^ last) == LEFT_BUTTON && (last & LEFT_BUTTON)) {
30
        event.type = LB_RELEASED;
31
        last &= ~LEFT_BUTTON;
32 78 up20180655
33 91 up20180655
    } else if ((button_presses ^ last) == RIGHT_BUTTON && (last & RIGHT_BUTTON)) {
34
        event.type = RB_RELEASED;
35
        last &= ~RIGHT_BUTTON;
36
37
    } else if ((delta_x || delta_y) && (button_presses == last)) {
38
        event.type = MOUSE_MOV;
39
40
    } else
41
        event.type = BUTTON_EV;
42
43
    event.delta_x = delta_x;
44
    event.delta_y = delta_y;
45 78 up20180655
    return &event;
46
}
47
48
int state_machine(struct mouse_ev* event, uint8_t x_len, uint8_t tolerance) {
49
50
    static enum states state = INITIAL;
51
    static int response = OTHER_ERROR;
52
    static int x_length = 0;
53
    static int y_length = 0;
54
55
    if (event == NULL)
56
        return response;
57 87 up20180655
58 78 up20180655
    switch (state) {
59
        case INITIAL:
60
            if (event->type == LB_PRESSED)
61
                state = DRAG_UP;
62
            break;
63
        case DRAG_UP:
64
            if (event->type == MOUSE_MOV) {
65 87 up20180655
                if (event->delta_x < -tolerance || event->delta_y < -tolerance) {
66 78 up20180655
                    state = INITIAL;
67
                    x_length = 0;
68
                    y_length = 0;
69
                    break;
70
                }
71
72
                x_length += event->delta_x;
73
                y_length += event->delta_y;
74
            } else if (event->type == LB_RELEASED) {
75 91 up20180655
                if (y_length < x_length || x_length < x_len) {
76 78 up20180655
                    state = INITIAL;
77
                    x_length = 0;
78
                    y_length = 0;
79
                    break;
80
                }
81
82
                state = VERTEX;
83
                x_length = 0;
84
                y_length = 0;
85
            } else {
86
                state = INITIAL;
87
                x_length = 0;
88
                y_length = 0;
89
            }
90
            break;
91
        case VERTEX:
92
            if (event->type == MOUSE_MOV) {
93
                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance)
94
                    state = INITIAL;
95
            } else if (event->type == RB_PRESSED) {
96
                state = DRAG_DOWN;
97
            } else if (event->type == LB_PRESSED) {
98
                state = DRAG_UP;
99
            } else
100
                state = INITIAL;
101
            break;
102
        case DRAG_DOWN:
103
            if (event->type == MOUSE_MOV) {
104 87 up20180655
                if (event->delta_x < -tolerance || event->delta_y > tolerance) {
105 78 up20180655
                    state = INITIAL;
106
                    x_length = 0;
107
                    y_length = 0;
108
                    break;
109
                }
110
111
                x_length += event->delta_x;
112
                y_length += event->delta_y;
113
            } else if (event->type == RB_RELEASED) {
114
                if (x_length == 0 || y_length == 0) {
115
                    state = INITIAL;
116
                    break;
117
                }
118
119 91 up20180655
                if (y_length > -x_length || x_length < x_len) {
120 78 up20180655
                    state = INITIAL;
121
                    x_length = 0;
122
                    y_length = 0;
123
                    break;
124
                }
125
126
                state = FINAL;
127 79 up20180655
                response = SUCCESS;
128 78 up20180655
                x_length = 0;
129
                y_length = 0;
130
            } else {
131
                state = INITIAL;
132
                x_length = 0;
133
                y_length = 0;
134
            }
135
            break;
136
        case FINAL: // acception state
137
            response = SUCCESS;
138
        default: // invalid state / dead state
139
            response = INVALID_STATE;
140
    }
141
    return response;
142
}