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