/** * \brief Handle maXTouch messages * * This function handles the maXTouch messages, triggering the drawing of * squares around new or moved touches, and removing the squares around * released touches. * * \param device Pointer to mxt_device struct */ static void mxt_handler(struct mxt_device *device) { static struct finger fingers[MAX_TOUCHES]; static const gfx_color_t finger_colors[MAX_TOUCHES] = { GFX_COLOR_RED, GFX_COLOR_GREEN, GFX_COLOR_BLUE, GFX_COLOR_CYAN, GFX_COLOR_YELLOW, GFX_COLOR_MAGENTA, GFX_COLOR_WHITE, GFX_COLOR_GRAY, }; struct mxt_touch_event touch_event; struct finger *curr_finger; uint8_t finger_index; do { /* Get the first touch event in queue */ if (mxt_read_touch_event(device, &touch_event) != STATUS_OK) { continue; } /* Discard non press, movement or release events */ if (!(touch_event.status & (MXT_PRESS_EVENT | MXT_MOVE_EVENT | MXT_RELEASE_EVENT))) { continue; } /* Use the touch ID as finger index */ finger_index = touch_event.id; /* Skip if touch ID is out of bounds */ if (!(finger_index < MAX_TOUCHES)) { continue; } /* Get address of current finger info struct */ curr_finger = &fingers[finger_index]; /* If finger already registered (and thus drawn), clear it on the display */ if (curr_finger->enable) { draw_finger_square(curr_finger, DISPLAY_COLOR); } /* Update finger info - finger is enabled unless it was released */ curr_finger->enable = !(touch_event.status & MXT_RELEASE_EVENT); /* If the finger is now enabled, we need to update its position and redraw */ if (curr_finger->enable) { /* Compute new display coordinates from touch coordinates */ get_finger_display_coordinates(&touch_event, curr_finger); /* Draw updated representation on the display */ draw_finger_square(curr_finger, finger_colors[finger_index]); } } while (mxt_is_message_pending(device)); }
/** * \brief Main application function * * This function executes the necessary initialization calls and displays the * demo widgets before entering the main work loop of the application. * * The main work loop reads out the touch events from the mXT143E Xplained and * enqueues the corresponding touch events in the window system, before * processing the window system's event queue. */ int main(void) { static struct mxt_device device; board_init(); sysclk_init(); membag_init(); gfx_init(); mxt_init(&device); win_init(); setup_root_window(); app_widget_launch(); while (true) { /* Process received messages from the maXTouch device */ while (mxt_is_message_pending(&device)) { struct mxt_touch_event touch_event; struct win_pointer_event win_touch_event; /* Get the first touch event in queue */ if (mxt_read_touch_event(&device, &touch_event) != STATUS_OK) { continue; } /* Translate touch event type into a WTK event type */ if (touch_event.status & MXT_PRESS_EVENT) { win_touch_event.type = WIN_POINTER_PRESS; } else if (touch_event.status & MXT_MOVE_EVENT) { win_touch_event.type = WIN_POINTER_MOVE; } else if (touch_event.status & MXT_RELEASE_EVENT) { win_touch_event.type = WIN_POINTER_RELEASE; } else { continue; } /* Indicate the touch event is a non-relative movement * with the virtual touch button pressed */ win_touch_event.is_relative = false; win_touch_event.buttons = WIN_TOUCH_BUTTON; /* Translate the touch X and Y position into a screen * coordinate */ win_touch_event.pos.x = ((uint32_t)(4096 - touch_event.x) * gfx_get_width()) / 4096; win_touch_event.pos.y = ((uint32_t)(4096 - touch_event.y) * gfx_get_height()) / 4096; win_queue_pointer_event(&win_touch_event); } /* Process queued events in the windowing system */ win_process_events(); } }
/** * \brief Convert touch events from the touchscreen into window pointer events * * Reads touch events in from the touchscreen and converts them into a * Window Manager pointer event, for enqueuing into the window event queue. * * \return Boolean true if a touch event was read, false if no touch event * or a corrupt touch event was received */ static bool read_touch_event(struct mxt_device *device, struct win_pointer_event *win_touch_event) { struct mxt_touch_event touch_event; /* Abort if no touch event is pending */ if (!(mxt_is_message_pending(device))) { return false; } /* Get the first touch event in queue */ if (mxt_read_touch_event(device, &touch_event) != STATUS_OK) { return false; } /* Translate touch event type into a WTK event type */ if (touch_event.status & MXT_PRESS_EVENT) { win_touch_event->type = WIN_POINTER_PRESS; } else if (touch_event.status & MXT_MOVE_EVENT) { win_touch_event->type = WIN_POINTER_MOVE; } else if (touch_event.status & MXT_RELEASE_EVENT) { win_touch_event->type = WIN_POINTER_RELEASE; } else { return false; } /* Indicate the touch event is a non-relative movement with the virtual * touch button pressed */ win_touch_event->is_relative = false; win_touch_event->buttons = WIN_TOUCH_BUTTON; /* Translate the touch X and Y position into a screen coordinate */ win_touch_event->pos.x = ((uint32_t)(4096 - touch_event.x) * gfx_get_width()) / 4096; win_touch_event->pos.y = ((uint32_t)(4096 - touch_event.y) * gfx_get_height()) / 4096; return true; }
static void mxt_handler(struct mxt_device *device) { /* USART tx buffer initialized to 0 */ char tx_buf[STRING_LENGTH * MAX_ENTRIES] = {0}; uint8_t i = 0; /* Iterator */ /* Temporary touch event data struct */ struct mxt_touch_event touch_event; /* Collect touch events and put the data in a string, * maximum 2 events at the time */ do { /* Temporary buffer for each new touch event line */ char buf[STRING_LENGTH]; /* Read next next touch event in the queue, discard if read fails */ if (mxt_read_touch_event(device, &touch_event) != STATUS_OK) { continue; } /* Format a new entry in the data string that will be sent over USART */ sprintf(buf, "Nr: %1d, X:%4d, Y:%4d, Status:0x%2x\n\r", touch_event.id, touch_event.x, touch_event.y, touch_event.status); /* Add the new string to the string buffer */ strcat(tx_buf, buf); i++; /* Check if there is still messages in the queue and * if we have reached the maximum numbers of events */ } while ((mxt_is_message_pending(device)) & (i < MAX_ENTRIES)); /* If there is any entries in the buffer, send them over USART */ if (i > 0) { usart_serial_write_packet(USART_SERIAL_EXAMPLE, (uint8_t *)tx_buf, strlen(tx_buf)); } }
/** * \brief Handle maXTouch messages * * This function handles the maXTouch messages, triggering the drawing of * squares around new or moved touches, and removing the squares around * released touches. * * \param device Pointer to mxt_device struct */ static void mxt_handler(struct mxt_device *device) { struct mxt_touch_event touch_event; gfx_coord_t screen_touch_x, screen_touch_y, screen_touch_size; do { /* Get the first touch event in queue */ if (mxt_read_touch_event(device, &touch_event) != STATUS_OK) { continue; } /* Discard non press, movement or release events */ if (!(touch_event.status & (MXT_PRESS_EVENT | MXT_MOVE_EVENT | MXT_RELEASE_EVENT))) { continue; } /* Rescale from 4k touch X-coordinate to the display width */ screen_touch_x = ((uint32_t)(4096 - touch_event.x) * gfx_get_width()) / 4096; /* Rescale from 4k touch Y-coordinate to the display height */ screen_touch_y = ((uint32_t)(4096 - touch_event.y) * gfx_get_height()) / 4096; /* Scale the touch size to a value suitable for the target display */ screen_touch_size = touch_event.size; /* Check if the touch is within the drawing area */ if (screen_touch_y < (gfx_get_height() - PALLET_HEIGHT)) { /* Obtain the color to draw from the pallet colors */ gfx_color_t draw_color = pallet_colors[selected_pallet_color]; /* Color pallet index 0 selects multi-color mode */ if (selected_pallet_color == 0) { draw_color = get_next_rainbow_color(); } /* Set clipping area */ gfx_set_clipping(0, 0, gfx_get_width(), (gfx_get_height() - PALLET_HEIGHT - 2)); /* Draw touch point on the screen in the selected color */ gfx_draw_filled_circle(screen_touch_x, screen_touch_y, screen_touch_size, draw_color, GFX_WHOLE); /* Reset clipping area */ gfx_set_clipping(0, 0, gfx_get_width(), gfx_get_height()); } else if (touch_event.status & MXT_PRESS_EVENT) { /* Calculate the pressed pallet entry */ uint8_t pallete_index = (screen_touch_x / PALLET_COLOR_WIDTH); /* The last entry in the pallet clears the screen */ if (pallete_index == (NUM_PALLET_COLORS - 1)) { /* Indicate display is being cleared */ draw_pallet_labels(true); /* Clear the display */ gfx_draw_filled_rect(0, 0, gfx_get_width(), (gfx_get_height() - PALLET_HEIGHT - 1), GFX_COLOR_BLACK); /* Indicate display has been cleared */ draw_pallet_labels(false); } else { /* Change color selection based on the color chosen */ selected_pallet_color = pallete_index; /* Draw new selection box around chosen color */ update_pallet_selection(); } } } while (mxt_is_message_pending(device)); }
/** * \brief Main application function * * This function ensures that the hardware and drivers are initialized before * entering an infinite work loop. * * In the work loop, the maXTouch device is polled for new touch events and any * new event is passed on to the user interface implementation for processing. * The loop then attempts to enter sleep. * * The user interface processing itself is not started by the work loop, but by * the USB callback function for start of frame. */ int main(void) { #ifdef USB_DEVICE_LOW_SPEED uint16_t virtual_sof_sub; uint16_t virtual_sof; #endif /* maXTouch data structure */ static struct mxt_device device; /* Initialize system clocks */ sysclk_init(); /* Initialize interrupt vectors */ irq_initialize_vectors(); /* Enable interrupts */ cpu_irq_enable(); /* Initialize the sleep manager */ sleepmgr_init(); /* Initialize the board */ board_init(); /* Initialize the mXT touch device */ mxt_init(&device); /* Initialize the graphical library */ gfx_init(); /* Set correct landscape orientation */ gfx_set_orientation(GFX_SWITCH_XY | GFX_FLIP_Y); /* Set background color */ gfx_draw_filled_rect(0, 0, gfx_get_width(), gfx_get_height(), COLOR_BACKGROUND); /* Draw the help text */ gfx_draw_string_aligned( "Middle finger to move cursor\n" "Index finger to left click\n" "Ring finger to right click", gfx_get_width() / 2, gfx_get_height() / 2, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_CENTER, TEXT_ALIGN_CENTER); /* Initialize the user interface */ ui_init(); ui_powerdown(); /* Start USB stack to authorize VBus monitoring */ udc_start(); /* Check if there are any new touch data pending */ while (true) { if (mxt_is_message_pending(&device)) { if (mxt_read_touch_event(&device, &ui_touch_event) == STATUS_OK) { ui_flag_new_touch_event(); } } /* Try to sleep */ sleepmgr_enter_sleep(); #ifdef USB_DEVICE_LOW_SPEED /* No USB "Keep alive" interrupt available in low speed * to scan mouse interface then use main loop */ if (main_b_mouse_enable) { virtual_sof_sub = 0; virtual_sof = 0; if (virtual_sof_sub++ == 700) { virtual_sof_sub = 0; ui_process(virtual_sof++); } } #endif } }