root / lab4 / state_machine.c @ 81
History | View | Annotate | Download (5.59 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 |
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 |
response = SUCCESS; |
152 |
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 |
} |