23 #include "freertos/FreeRTOS.h" 37 bool Mouse::s_quickCheckHardware =
false;
41 : m_mouseAvailable(false),
44 m_movementAcceleration(180),
45 m_wheelAcceleration(60000),
46 m_absoluteUpdateTimer(nullptr),
47 m_absoluteQueue(nullptr),
48 m_updateDisplayController(nullptr),
62 if (s_quickCheckHardware)
63 PS2Device::quickCheckHardware();
64 PS2Device::begin(PS2Port);
72 PS2->
begin(clkGPIO, dataGPIO);
80 if (s_quickCheckHardware) {
81 m_mouseAvailable = send_cmdReset();
84 for (
int i = 0; i < 3; ++i) {
85 m_mouseAvailable = send_cmdReset();
88 vTaskDelay(500 / portTICK_PERIOD_MS);
93 if (m_mouseAvailable) {
103 return m_mouseAvailable;
107 int Mouse::getPacketSize()
115 return dataAvailable() / getPacketSize();
122 int packetSize = getPacketSize();
124 for (
int i = 0; i < packetSize; ++i) {
126 rcv[i] = getData(timeOutMS);
130 if (rcv[i] == -1 && requestResendOnTimeOut) {
131 requestToResendLastByte();
141 if ((rcv[0] & 8) == 0) {
146 m_prevStatus = m_status;
153 delta->
deltaX = (int16_t)(rcv[0] & 0x10 ? 0xFF00 | rcv[1] : rcv[1]);
154 delta->
deltaY = (int16_t)(rcv[0] & 0x20 ? 0xFF00 | rcv[2] : rcv[2]);
155 delta->
deltaZ = (int8_t)(packetSize > 3 ? rcv[3] : 0);
156 delta->
overflowX = (rcv[0] & 0x40 ? 1 : 0);
157 delta->
overflowY = (rcv[0] & 0x80 ? 1 : 0);
174 m_prevStatus = m_status;
176 m_updateDisplayController = updateDisplayController;
180 if (createAbsolutePositionsQueue && m_absoluteQueue ==
nullptr) {
181 m_absoluteQueue = xQueueCreate(FABGLIB_MOUSE_EVENTS_QUEUE_SIZE,
sizeof(
MouseStatus));
184 if (m_updateDisplayController) {
189 if ((m_updateDisplayController || createAbsolutePositionsQueue || m_uiApp) && m_absoluteUpdateTimer ==
nullptr) {
191 m_absoluteUpdateTimer = xTimerCreate(
"", pdMS_TO_TICKS(10), pdTRUE,
this, absoluteUpdateTimerFunc);
192 xTimerStart(m_absoluteUpdateTimer, portMAX_DELAY);
199 m_updateDisplayController =
nullptr;
201 if (m_absoluteQueue) {
202 vQueueDelete(m_absoluteQueue);
203 m_absoluteQueue =
nullptr;
205 if (m_absoluteUpdateTimer) {
206 xTimerDelete(m_absoluteUpdateTimer, portMAX_DELAY);
207 m_absoluteUpdateTimer =
nullptr;
214 const int maxDeltaTimeUS = 500000;
220 int64_t now = esp_timer_get_time();
221 int deltaTime = now - m_prevDeltaTime;
223 if (deltaTime < maxDeltaTimeUS) {
226 if (dx != 0 || dy != 0) {
227 int deltaDist = isqrt(dx * dx + dy * dy);
228 float vel = (float)deltaDist / deltaTime;
229 float newVel = vel + m_movementAcceleration * vel * vel;
230 int newDeltaDist = newVel * deltaTime;
231 dx = dx * newDeltaDist / deltaDist;
232 dy = dy * newDeltaDist / deltaDist;
237 int deltaDist = abs(dz);
238 float vel = (float)deltaDist / deltaTime;
239 float newVel = vel + m_wheelAcceleration * vel * vel;
240 int newDeltaDist = newVel * deltaTime;
241 dz = dz * newDeltaDist / deltaDist;
246 m_status.
X = tclamp((
int)m_status.
X + dx, 0, m_area.
width - 1);
247 m_status.
Y = tclamp((
int)m_status.
Y - dy, 0, m_area.
height - 1);
249 m_prevDeltaTime = now;
253 void Mouse::absoluteUpdateTimerFunc(TimerHandle_t xTimer)
255 Mouse * mouse = (
Mouse*) pvTimerGetTimerID(xTimer);
261 if (mouse->m_updateDisplayController)
265 if (mouse->m_absoluteQueue) {
266 xQueueSend(mouse->m_absoluteQueue, &mouse->m_status, 0);
269 if (mouse->m_uiApp) {
271 if (mouse->m_prevStatus.
X != mouse->m_status.
X || mouse->m_prevStatus.
Y != mouse->m_status.
Y) {
273 uiEvent evt = uiEvent(
nullptr, UIEVT_MOUSEMOVE);
274 evt.params.mouse.status = mouse->m_status;
275 evt.params.mouse.changedButton = 0;
280 uiEvent evt = uiEvent(
nullptr, UIEVT_MOUSEWHEEL);
281 evt.params.mouse.status = mouse->m_status;
282 evt.params.mouse.changedButton = 0;
287 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
left ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
288 evt.params.mouse.status = mouse->m_status;
289 evt.params.mouse.changedButton = 1;
294 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
middle ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
295 evt.params.mouse.status = mouse->m_status;
296 evt.params.mouse.changedButton = 2;
301 uiEvent evt = uiEvent(
nullptr, mouse->m_status.
buttons.
right ? UIEVT_MOUSEBUTTONDOWN : UIEVT_MOUSEBUTTONUP);
302 evt.params.mouse.status = mouse->m_status;
303 evt.params.mouse.changedButton = 3;
314 return m_absoluteQueue ? uxQueueMessagesWaiting(m_absoluteQueue) : 0;
322 xQueueReceive(m_absoluteQueue, &
status, msToTicks(timeOutMS));
329 while (getData(0) != -1)
332 xQueueReset(m_absoluteQueue);
This file contains fabgl::PS2Controller definition.
Represents the whole application base class.
bool setSampleRate(int value)
Sets the maximum rate of mouse movements reporting.
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.
static PS2Controller * instance()
Returns the singleton instance of PS2Controller class.
void terminateAbsolutePositioner()
Terminates absolute position handler.
bool getNextDelta(MouseDelta *delta, int timeOutMS=-1, bool requestResendOnTimeOut=false)
Gets a mouse movement from the queue.
Represents a bidimensional size.
The PS2 device controller class.
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.
int deltaAvailable()
Determines the number of mouse movements available in the queue.
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.
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.