Project

General

Profile

Statistics
| Revision:

root / lab4 / state_machine.c @ 82

History | View | Annotate | Download (5.59 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
11
    static struct mouse_ev event;
12
    static struct packet last; // compare consecutive events
13
    static int aux = 1; // first iteration
14
15
    if (pp == NULL)
16
        return &event;
17
18
    // current packet
19
    uint8_t lb_press = pp->bytes[0] & LEFT_BUTTON;
20
    uint8_t rb_press = pp->bytes[0] & RIGHT_BUTTON;
21
    uint8_t mb_press = pp->bytes[0] & MIDDLE_BUTTON;
22 79 up20180655
    int16_t delta_x = pp->delta_x;
23
    int16_t delta_y = pp->delta_y;
24 78 up20180655
25
    if (aux) { // first event detected
26
        if (lb_press && (rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0)
27
            event.type = LB_PRESSED;
28
        else if (rb_press && (lb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0)
29
            event.type = RB_PRESSED;
30
        else if ((delta_x || delta_y) && (lb_press | rb_press | mb_press) == 0) {
31
            event.type = MOUSE_MOV;
32
            event.delta_x = delta_x;
33
            event.delta_y = delta_y;
34
        } else
35
            event.type = BUTTON_EV;
36
        aux = 0;
37
    } else {
38
        // last packet
39
        uint8_t last_lb_press = last.bytes[0] & LEFT_BUTTON;
40
        uint8_t last_rb_press = last.bytes[0] & RIGHT_BUTTON;
41
        uint8_t last_mb_press = last.bytes[0] & MIDDLE_BUTTON;
42
43
        if (lb_press && (rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_lb_press == 0)
44
            event.type = LB_PRESSED;
45
        else if (rb_press && (lb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_rb_press == 0)
46
            event.type = RB_PRESSED;
47
        else if ((lb_press | rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_lb_press)
48
            event.type = LB_RELEASED;
49
        else if ((lb_press | rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_rb_press)
50
            event.type = RB_RELEASED;
51
        else if ((delta_x || delta_y) && (lb_press | rb_press | mb_press) == (last_lb_press | last_rb_press | last_mb_press)) {
52
            event.type = MOUSE_MOV;
53
            event.delta_x = delta_x;
54
            event.delta_y = delta_y;
55
        } else
56
            event.type = BUTTON_EV;
57
    }
58
59
    // update last packet for comparison
60
    last = *pp;
61
62
    return &event;
63
}
64
65
int state_machine(struct mouse_ev* event, uint8_t x_len, uint8_t tolerance) {
66
67
    static enum states state = INITIAL;
68
    static int response = OTHER_ERROR;
69
    static int x_length = 0;
70
    static int y_length = 0;
71
72
    if (event == NULL)
73
        return response;
74
    switch (state) {
75
        case INITIAL:
76
            if (event->type == LB_PRESSED)
77
                state = DRAG_UP;
78
            break;
79
        case DRAG_UP:
80
            if (event->type == MOUSE_MOV) {
81
                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance) {
82
                    state = INITIAL;
83
                    x_length = 0;
84
                    y_length = 0;
85
                    break;
86
                }
87
88
                x_length += event->delta_x;
89
                y_length += event->delta_y;
90
            } else if (event->type == LB_RELEASED) {
91
                if (x_length == 0 || y_length == 0) {
92
                    state = INITIAL;
93
                    break;
94
                }
95
96
                int slope = y_length / x_length;
97
98
                if (slope <= 1 || x_length < x_len) {
99
                    state = INITIAL;
100
                    x_length = 0;
101
                    y_length = 0;
102
                    break;
103
                }
104
105
                state = VERTEX;
106
                x_length = 0;
107
                y_length = 0;
108
            } else {
109
                state = INITIAL;
110
                x_length = 0;
111
                y_length = 0;
112
            }
113
            break;
114
        case VERTEX:
115
            if (event->type == MOUSE_MOV) {
116
                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance)
117
                    state = INITIAL;
118
            } else if (event->type == RB_PRESSED) {
119
                state = DRAG_DOWN;
120
            } else if (event->type == LB_PRESSED) {
121
                state = DRAG_UP;
122
            } else
123
                state = INITIAL;
124
            break;
125
        case DRAG_DOWN:
126
            if (event->type == MOUSE_MOV) {
127
                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance) {
128
                    state = INITIAL;
129
                    x_length = 0;
130
                    y_length = 0;
131
                    break;
132
                }
133
134
                x_length += event->delta_x;
135
                y_length += event->delta_y;
136
            } else if (event->type == RB_RELEASED) {
137
                if (x_length == 0 || y_length == 0) {
138
                    state = INITIAL;
139
                    break;
140
                }
141
                int slope = y_length / x_length;
142
143
                if (slope >= -1 || x_length < x_len) {
144
                    state = INITIAL;
145
                    x_length = 0;
146
                    y_length = 0;
147
                    break;
148
                }
149
150
                state = FINAL;
151 79 up20180655
                response = SUCCESS;
152 78 up20180655
                x_length = 0;
153
                y_length = 0;
154
            } else {
155
                state = INITIAL;
156
                x_length = 0;
157
                y_length = 0;
158
            }
159
            break;
160
        case FINAL: // acception state
161
            response = SUCCESS;
162
        default: // invalid state / dead state
163
            response = INVALID_STATE;
164
    }
165
    return response;
166
}