27 #include "freertos/FreeRTOS.h" 34 #pragma GCC optimize ("O2") 41 bool Mouse::s_quickCheckHardware =
false;
45 : m_mouseAvailable(false),
47 m_mouseUpdateTask(nullptr),
48 m_receivedPacket(nullptr),
49 m_absoluteUpdate(false),
51 m_movementAcceleration(180),
52 m_wheelAcceleration(60000),
53 m_absoluteQueue(nullptr),
54 m_updateDisplayController(nullptr),
62 PS2DeviceLock
lock(
this);
64 if (m_mouseUpdateTask)
65 vTaskDelete(m_mouseUpdateTask);
67 vQueueDelete(m_receivedPacket);
73 if (s_quickCheckHardware)
74 PS2Device::quickCheckHardware();
75 PS2Device::begin(PS2Port);
77 m_receivedPacket = xQueueCreate(1,
sizeof(
MousePacket));
78 xTaskCreate(&mouseUpdateTask,
"", 1600,
this, 5, &m_mouseUpdateTask);
86 PS2Controller::setMouse(
this);
93 if (s_quickCheckHardware) {
94 m_mouseAvailable = send_cmdReset();
97 for (
int i = 0; i < 3; ++i) {
98 m_mouseAvailable = send_cmdReset();
101 vTaskDelay(500 / portTICK_PERIOD_MS);
104 vTaskDelay(200 / portTICK_PERIOD_MS);
108 if (m_mouseAvailable) {
118 return m_mouseAvailable;
130 return uxQueueMessagesWaiting(m_receivedPacket) > 0;
136 return xQueueReceive(m_receivedPacket, packet, msToTicks(timeOutMS));
165 if ((mousePacket->data[0] & 8) == 0)
168 m_prevStatus = m_status;
171 m_status.
buttons.
left = (mousePacket->data[0] & 0x01 ? 1 : 0);
172 m_status.
buttons.
middle = (mousePacket->data[0] & 0x04 ? 1 : 0);
173 m_status.
buttons.
right = (mousePacket->data[0] & 0x02 ? 1 : 0);
175 delta->
deltaX = (int16_t)(mousePacket->data[0] & 0x10 ? 0xFF00 | mousePacket->data[1] : mousePacket->data[1]);
176 delta->
deltaY = (int16_t)(mousePacket->data[0] & 0x20 ? 0xFF00 | mousePacket->data[2] : mousePacket->data[2]);
178 delta->
overflowX = (mousePacket->data[0] & 0x40 ? 1 : 0);
179 delta->
overflowY = (mousePacket->data[0] & 0x80 ? 1 : 0);
190 return getNextPacket(&mousePacket, timeOutMS, requestResendOnTimeOut) && decodeMousePacket(&mousePacket, delta);
205 m_prevStatus = m_status;
207 m_updateDisplayController = updateDisplayController;
211 if (createAbsolutePositionsQueue && m_absoluteQueue ==
nullptr) {
215 if (m_updateDisplayController) {
220 m_absoluteUpdate = (m_updateDisplayController || createAbsolutePositionsQueue || m_uiApp);
226 if (m_absoluteQueue) {
227 vQueueDelete(m_absoluteQueue);
228 m_absoluteQueue =
nullptr;
230 m_absoluteUpdate =
false;
231 m_updateDisplayController =
nullptr;
238 const int maxDeltaTimeUS = 500000;
244 int64_t now = esp_timer_get_time();
245 int deltaTime = now - m_prevDeltaTime;
247 if (deltaTime < maxDeltaTimeUS) {
250 if (dx != 0 || dy != 0) {
251 int deltaDist = isqrt(dx * dx + dy * dy);
252 float vel = (float)deltaDist / deltaTime;
253 float newVel = vel + m_movementAcceleration * vel * vel;
254 int newDeltaDist = newVel * deltaTime;
255 dx = dx * newDeltaDist / deltaDist;
256 dy = dy * newDeltaDist / deltaDist;
261 int deltaDist = abs(dz);
262 float vel = (float)deltaDist / deltaTime;
263 float newVel = vel + m_wheelAcceleration * vel * vel;
264 int newDeltaDist = newVel * deltaTime;
265 dz = dz * newDeltaDist / deltaDist;
270 m_status.
X = tclamp((
int)m_status.
X + dx, 0, m_area.
width - 1);
271 m_status.
Y = tclamp((
int)m_status.
Y - dy, 0, m_area.
height - 1);
273 m_prevDeltaTime = now;
277 void Mouse::mouseUpdateTask(
void * arg)
279 constexpr
int MAX_TIME_BETWEEN_DATA_US = 500000;
283 int64_t prevDataTime = 0;
288 int mousePacketLen = 0;
290 int r = mouse->getData(-1);
291 if (mouse->parityError() || mouse->syncError()) {
295 int64_t now = esp_timer_get_time();
296 if (mousePacketLen > 0 && prevDataTime > 0 && (now - prevDataTime) > MAX_TIME_BETWEEN_DATA_US) {
301 mousePacket.data[mousePacketLen++] = r;
306 if (mouse->m_absoluteUpdate) {
308 if (mouse->decodeMousePacket(&mousePacket, &delta)) {
312 if (mouse->m_updateDisplayController)
316 if (mouse->m_absoluteQueue) {
317 xQueueSend(mouse->m_absoluteQueue, &mouse->m_status, 0);
320 if (mouse->m_uiApp) {
322 if (mouse->m_prevStatus.
X != mouse->m_status.
X || mouse->m_prevStatus.
Y != mouse->m_status.
Y) {
324 uiEvent evt = uiEvent(
nullptr, UIEVT_MOUSEMOVE);
325 evt.params.mouse.status = mouse->m_status;
326 evt.params.mouse.changedButton = 0;
331 uiEvent evt = uiEvent(
nullptr, UIEVT_MOUSEWHEEL);
332 evt.params.mouse.status = mouse->m_status;
333 evt.params.mouse.changedButton = 0;
338 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
left ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
339 evt.params.mouse.status = mouse->m_status;
340 evt.params.mouse.changedButton = 1;
345 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
middle ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
346 evt.params.mouse.status = mouse->m_status;
347 evt.params.mouse.changedButton = 2;
352 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
right ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
353 evt.params.mouse.status = mouse->m_status;
354 evt.params.mouse.changedButton = 3;
363 xQueueOverwrite(mouse->m_receivedPacket, &mousePacket);
373 return m_absoluteQueue ? uxQueueMessagesWaiting(m_absoluteQueue) : 0;
381 xQueueReceive(m_absoluteQueue, &
status, msToTicks(timeOutMS));
388 while (getData(0) != -1)
391 xQueueReset(m_absoluteQueue);
This file contains fabgl::PS2Controller definition.
bool lock(int timeOutMS)
Gets exclusive access to the device.
Represents the whole application base class.
Contains raw data received from mouse.
bool setSampleRate(int value)
Sets the maximum rate of mouse movements reporting.
int getPacketSize()
Gets mouse packet size.
#define FABGLIB_MOUSE_EVENTS_QUEUE_SIZE
This file contains fabgl::BitmappedDisplayController definition.
Represents the base abstract class for bitmapped display controllers.
Describes mouse movement and buttons status.
This file contains fabgl::Mouse definition.
Describes mouse absolute position, scroll wheel delta and buttons status.
PS2DeviceType identify()
Identifies the device attached to the PS2 port.
MouseStatus getNextStatus(int timeOutMS=-1)
Gets the next status from the status queue.
void emptyQueue()
Empties the mouse status and events queue.
bool deltaAvailable()
Determines if there is a mouse movement available in the queue.
bool packetAvailable()
Determines if there is a raw mouse movement available in the queue.
void terminateAbsolutePositioner()
Terminates absolute position handler.
bool getNextPacket(MousePacket *packet, int timeOutMS=-1, bool requestResendOnTimeOut=false)
Gets a mouse raw movement (packet) from the queue.
bool getNextDelta(MouseDelta *delta, int timeOutMS=-1, bool requestResendOnTimeOut=false)
Gets a mouse movement from the queue.
Represents a bidimensional size.
void setMouseCursorPos(int X, int Y)
Sets mouse cursor position.
bool postEvent(uiEvent const *event)
Places an event in the event queue and returns without waiting for the receiver to process the event...
MouseStatus & status()
Gets or sets current mouse status.
int availableStatus()
Gets the number of available mouse status.
void begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO)
Initializes Mouse specifying CLOCK and DATA GPIOs.
void updateAbsolutePosition(MouseDelta *delta)
Updates absolute position from the specified mouse delta event.
The PS2 Mouse controller class.
void setupAbsolutePositioner(int width, int height, bool createAbsolutePositionsQueue, BitmappedDisplayController *updateDisplayController=nullptr, uiApp *app=nullptr)
Initializes absolute position handler.
bool reset()
Sends a Reset command to the mouse.
static void begin(gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO, gpio_num_t port1_clkGPIO=GPIO_UNUSED, gpio_num_t port1_datGPIO=GPIO_UNUSED)
Initializes PS2 device controller.