Project

General

Profile

Statistics
| Revision:

root / lab4 / state_machine.c @ 87

History | View | Annotate | Download (5.58 KB)

1
#include <lcom/lcf.h>
2

    
3
#include "state_machine.h"
4
#include "mouse_macros.h"
5
#include "mouse.h"
6
#include "errors.h"
7
#include "utils.h"
8

    
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
    int16_t delta_x = pp->delta_x;
23
    int16_t delta_y = pp->delta_y;
24

    
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

    
75
    switch (state) {
76
        case INITIAL:
77
            if (event->type == LB_PRESSED)
78
                state = DRAG_UP;
79
            break;
80
        case DRAG_UP:
81
            if (event->type == MOUSE_MOV) {
82
                if (event->delta_x < -tolerance || event->delta_y < -tolerance) {
83
                    state = INITIAL;
84
                    x_length = 0;
85
                    y_length = 0;
86
                    break;
87
                }
88

    
89
                x_length += event->delta_x;
90
                y_length += event->delta_y;
91
            } else if (event->type == LB_RELEASED) {
92
                if (x_length == 0 || y_length == 0) {
93
                    state = INITIAL;
94
                    break;
95
                }
96

    
97
                int slope = y_length / x_length;
98

    
99
                if (slope <= 1 || x_length < x_len) {
100
                    state = INITIAL;
101
                    x_length = 0;
102
                    y_length = 0;
103
                    break;
104
                }
105

    
106
                state = VERTEX;
107
                x_length = 0;
108
                y_length = 0;
109
            } else {
110
                state = INITIAL;
111
                x_length = 0;
112
                y_length = 0;
113
            }
114
            break;
115
        case VERTEX:
116
            if (event->type == MOUSE_MOV) {
117
                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance)
118
                    state = INITIAL;
119
            } else if (event->type == RB_PRESSED) {
120
                state = DRAG_DOWN;
121
            } else if (event->type == LB_PRESSED) {
122
                state = DRAG_UP;
123
            } else
124
                state = INITIAL;
125
            break;
126
        case DRAG_DOWN:
127
            if (event->type == MOUSE_MOV) {
128
                if (event->delta_x < -tolerance || event->delta_y > tolerance) {
129
                    state = INITIAL;
130
                    x_length = 0;
131
                    y_length = 0;
132
                    break;
133
                }
134

    
135
                x_length += event->delta_x;
136
                y_length += event->delta_y;
137
            } else if (event->type == RB_RELEASED) {
138
                if (x_length == 0 || y_length == 0) {
139
                    state = INITIAL;
140
                    break;
141
                }
142
                int slope = y_length / x_length;
143

    
144
                if (slope >= -1 || x_length < x_len) {
145
                    state = INITIAL;
146
                    x_length = 0;
147
                    y_length = 0;
148
                    break;
149
                }
150

    
151
                state = FINAL;
152
                response = SUCCESS;
153
                x_length = 0;
154
                y_length = 0;
155
            } else {
156
                state = INITIAL;
157
                x_length = 0;
158
                y_length = 0;
159
            }
160
            break;
161
        case FINAL: // acception state
162
            response = SUCCESS;
163
        default: // invalid state / dead state
164
            response = INVALID_STATE;
165
    }
166
    return response;
167
}