Project

General

Profile

Statistics
| Revision:

root / lab4 / state_machine.c @ 200

History | View | Annotate | Download (4.68 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 92 up20180655
                x_length += event->delta_x;
94
                y_length += event->delta_y;
95
                if (abs(x_length) > tolerance || abs(y_length) > tolerance) {
96 78 up20180655
                    state = INITIAL;
97 92 up20180655
                    x_length = 0;
98
                    y_length = 0;
99
                }
100 78 up20180655
            } else if (event->type == RB_PRESSED) {
101
                state = DRAG_DOWN;
102 92 up20180655
                x_length = 0;
103
                y_length = 0;
104 78 up20180655
            } else if (event->type == LB_PRESSED) {
105
                state = DRAG_UP;
106 92 up20180655
                x_length = 0;
107
                y_length = 0;
108
            } else {
109 78 up20180655
                state = INITIAL;
110 92 up20180655
                x_length = 0;
111
                y_length = 0;
112
            }
113 78 up20180655
            break;
114
        case DRAG_DOWN:
115
            if (event->type == MOUSE_MOV) {
116 87 up20180655
                if (event->delta_x < -tolerance || event->delta_y > tolerance) {
117 78 up20180655
                    state = INITIAL;
118
                    x_length = 0;
119
                    y_length = 0;
120
                    break;
121
                }
122
123
                x_length += event->delta_x;
124
                y_length += event->delta_y;
125
            } else if (event->type == RB_RELEASED) {
126
                if (x_length == 0 || y_length == 0) {
127
                    state = INITIAL;
128
                    break;
129
                }
130
131 91 up20180655
                if (y_length > -x_length || x_length < x_len) {
132 78 up20180655
                    state = INITIAL;
133
                    x_length = 0;
134
                    y_length = 0;
135
                    break;
136
                }
137
138
                state = FINAL;
139 79 up20180655
                response = SUCCESS;
140 78 up20180655
                x_length = 0;
141
                y_length = 0;
142
            } else {
143
                state = INITIAL;
144
                x_length = 0;
145
                y_length = 0;
146
            }
147
            break;
148
        case FINAL: // acception state
149
            response = SUCCESS;
150
        default: // invalid state / dead state
151
            response = INVALID_STATE;
152
    }
153
    return response;
154
}