Project

General

Profile

Statistics
| Revision:

root / lab4 / state_machine.c @ 101

History | View | Annotate | Download (4.68 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
    static struct mouse_ev event;
11
    static uint8_t last = 0;
12

    
13
    if (pp == NULL)
14
        return &event;
15

    
16
    // current button presses
17
    uint8_t button_presses = pp->bytes[0] & (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON);
18
    int16_t delta_x = pp->delta_x;
19
    int16_t delta_y = pp->delta_y;
20

    
21
    if ((button_presses ^ last) == LEFT_BUTTON && !(last & LEFT_BUTTON)) {
22
        event.type = LB_PRESSED;
23
        last |= LEFT_BUTTON;
24

    
25
    } else if ((button_presses ^ last) == RIGHT_BUTTON && !(last & RIGHT_BUTTON)) {
26
        event.type = RB_PRESSED;
27
        last |= RIGHT_BUTTON;
28

    
29
    } else if ((button_presses ^ last) == LEFT_BUTTON && (last & LEFT_BUTTON)) {
30
        event.type = LB_RELEASED;
31
        last &= ~LEFT_BUTTON;
32

    
33
    } 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
    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

    
58
    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
                if (event->delta_x < -tolerance || event->delta_y < -tolerance) {
66
                    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
                if (y_length < x_length || x_length < x_len) {
76
                    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
                x_length += event->delta_x;
94
                y_length += event->delta_y;
95
                if (abs(x_length) > tolerance || abs(y_length) > tolerance) {
96
                    state = INITIAL;
97
                    x_length = 0;
98
                    y_length = 0;
99
                }
100
            } else if (event->type == RB_PRESSED) {
101
                state = DRAG_DOWN;
102
                x_length = 0;
103
                y_length = 0;
104
            } else if (event->type == LB_PRESSED) {
105
                state = DRAG_UP;
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 DRAG_DOWN:
115
            if (event->type == MOUSE_MOV) {
116
                if (event->delta_x < -tolerance || event->delta_y > tolerance) {
117
                    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
                if (y_length > -x_length || x_length < x_len) {
132
                    state = INITIAL;
133
                    x_length = 0;
134
                    y_length = 0;
135
                    break;
136
                }
137

    
138
                state = FINAL;
139
                response = SUCCESS;
140
                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
}