Ejemplo n.º 1
0
	void gwinResize(GHandle gh, coord_t width, coord_t height) {
		gh->width = width; gh->height = height;
		if (gh->width < MIN_WIN_WIDTH) { gh->width = MIN_WIN_WIDTH; }
		if (gh->height < MIN_WIN_HEIGHT) { gh->height = MIN_WIN_HEIGHT; }
		if (gh->x+gh->width > gdispGGetWidth(gh->display))		gh->width = gdispGGetWidth(gh->display) - gh->x;
		if (gh->y+gh->height > gdispGGetHeight(gh->display))	gh->height = gdispGGetHeight(gh->display) - gh->y;
		_gwinUpdate(gh);
	}
Ejemplo n.º 2
0
	void gwinMove(GHandle gh, coord_t x, coord_t y) {
		gh->x = x; gh->y = y;
		if (gh->x < 0) gh->x = 0;
		if (gh->y < 0) gh->y = 0;
		if (gh->x > gdispGGetWidth(gh->display)-MIN_WIN_WIDTH)		gh->x = gdispGGetWidth(gh->display)-MIN_WIN_WIDTH;
		if (gh->y > gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT)	gh->y = gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT;
		if (gh->x+gh->width > gdispGGetWidth(gh->display)) 			gh->width = gdispGGetWidth(gh->display) - gh->x;
		if (gh->y+gh->height > gdispGGetHeight(gh->display)) 		gh->height = gdispGGetHeight(gh->display) - gh->y;
		_gwinUpdate(gh);
	}
Ejemplo n.º 3
0
void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
	coord_t		w, h;

	w = gdispGGetWidth(g);
	h = gdispGGetHeight(g);

	#if GDISP_NEED_CONTROL && !GINPUT_MOUSE_NO_ROTATION
		switch(gdispGGetOrientation(g)) {
			case GDISP_ROTATE_0:
				break;
			case GDISP_ROTATE_90:
				{
					coord_t t = pt->x;
					pt->x = w - 1 - pt->y;
					pt->y = t;
				}
				break;
			case GDISP_ROTATE_180:
				pt->x = w - 1 - pt->x;
				pt->y = h - 1 - pt->y;
				break;
			case GDISP_ROTATE_270:
				{
					coord_t t = pt->y;
					pt->y = h - 1 - pt->x;
					pt->x = t;
				}
				break;
			default:
				break;
		}
	#endif

	if (doClip) {
		if (pt->x < 0)	pt->x = 0;
		else if (pt->x >= w) pt->x = w-1;
		if (pt->y < 0)	pt->y = 0;
		else if (pt->y >= h) pt->y = h-1;
	}
}
Ejemplo n.º 4
0
static void GetMouseReading(GMouse *m) {
	GMouseReading	r;

	// Step 1 - Get the Raw Reading
	{
		m->flags &= ~GMOUSE_FLG_NEEDREAD;
		if (!gmvmt(m)->get(m, &r))
			return;
	}

	// Step 2 - Handle touch and button 0 debouncing
	{
		// Clean off button garbage
		r.buttons &= GINPUT_MOUSE_BTN_MASK;

		#if !GINPUT_TOUCH_NOTOUCH
			// If touch then calculate button 0 from z
			if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH)) {
				if (gmvmt(m)->z_min <= gmvmt(m)->z_max) {
					if (r.z >= gmvmt(m)->z_touchon)			r.buttons |= GINPUT_MOUSE_BTN_LEFT;
					else if (r.z <= gmvmt(m)->z_touchoff)	r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
					else									return;				// bad transitional reading
				} else {
					if (r.z <= gmvmt(m)->z_touchon)			r.buttons |= GINPUT_MOUSE_BTN_LEFT;
					else if (r.z >= gmvmt(m)->z_touchoff)	r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
					else									return;				// bad transitional reading
				}
			}

			// Devices with poor button 0 transitioning need debouncing
			if ((gmvmt(m)->d.flags & GMOUSE_VFLG_POORUPDOWN)) {
				// Are we in a transition test
				if ((m->flags & GMOUSE_FLG_INDELTA)) {
					if (!((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
						// Transition failed
						m->flags &= ~GMOUSE_FLG_INDELTA;
						return;
					}
					// Transition succeeded
					m->flags &= ~GMOUSE_FLG_INDELTA;

				// Should we start a transition test
				} else if (((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
					m->flags |= GMOUSE_FLG_INDELTA;
					return;
				}
			}
		#endif

		#if !GINPUT_TOUCH_NOCALIBRATE_GUI
			// Stop here with just the raw x,y reading during calibration
			if ((m->flags & GMOUSE_FLG_IN_CAL)) {
				if ((r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
					m->r.x = r.x;
					m->r.y = r.y;
				}
				m->r.buttons = r.buttons;
				return;
			}
		#endif
	}

	// Step 3 - Apply calibration, rotation and display clipping
	{
		// If the mouse is up we may need to keep our previous position
		if ((gmvmt(m)->d.flags & GMOUSE_VFLG_ONLY_DOWN) && !(r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
			r.x = m->r.x;
			r.y = m->r.y;

		} else {

			#if !GINPUT_TOUCH_NOCALIBRATE
				// Do we need to calibrate the reading?
				if ((m->flags & GMOUSE_FLG_CALIBRATE))
					CalibrationTransform(&r, &m->caldata);
			#endif

			// We can't clip or rotate if we don't have a display
			if (m->display) {
				coord_t			w, h;

				// We now need display information
				w = gdispGGetWidth(m->display);
				h = gdispGGetHeight(m->display);

				#if GDISP_NEED_CONTROL
					// Do we need to rotate the reading to match the display
					if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
						coord_t		t;

						switch(gdispGGetOrientation(m->display)) {
							case GDISP_ROTATE_0:
								break;
							case GDISP_ROTATE_90:
								t = r.x;
								r.x = w - 1 - r.y;
								r.y = t;
								break;
							case GDISP_ROTATE_180:
								r.x = w - 1 - r.x;
								r.y = h - 1 - r.y;
								break;
							case GDISP_ROTATE_270:
								t = r.y;
								r.y = h - 1 - r.x;
								r.x = t;
								break;
							default:
								break;
						}
					}
				#endif

				// Do we need to clip the reading to the display
				if ((m->flags & GMOUSE_FLG_CLIP)) {
					if (r.x < 0)		r.x = 0;
					else if (r.x >= w)	r.x = w-1;
					if (r.y < 0)		r.y = 0;
					else if (r.y >= h)	r.y = h-1;
				}
			}
		}
	}

	// Step 4 - Apply jitter detection
	#if !GINPUT_TOUCH_NOTOUCH
	{
		const GMouseJitter	*pj;
		uint32_t			diff;

		// Are we in pen or finger mode
		pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter;

		// Is this just movement jitter
		if (pj->move > 0) {
			diff = (uint32_t)(r.x - m->r.x) * (uint32_t)(r.x - m->r.x) + (uint32_t)(r.y - m->r.y) * (uint32_t)(r.y - m->r.y);
			if (diff < (uint32_t)pj->move * (uint32_t)pj->move) {
				r.x = m->r.x;
				r.y = m->r.y;
			}
		}

		// Check if the click has moved outside the click area and if so cancel the click
		if (pj->click > 0 && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
			diff = (uint32_t)(r.x - m->clickpos.x) * (uint32_t)(r.x - m->clickpos.x) + (uint32_t)(r.y - m->clickpos.y) * (uint32_t)(r.y - m->clickpos.y);
			if (diff > (uint32_t)pj->click * (uint32_t)pj->click)
				m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
		}
	}
	#endif

	// Step 5 - Click, context-click and other meta event detection
	{
		uint16_t		upbtns, dnbtns;

		// Calculate button transitions
		dnbtns = r.buttons & ~m->r.buttons;
		upbtns = ~r.buttons & m->r.buttons;

		// Left mouse down generates the Mouse-down meta event
		if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
			r.buttons |= GMETA_MOUSE_DOWN;

		// Left mouse up generates the Mouse-up meta event
		if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
			r.buttons |= GMETA_MOUSE_UP;

		// Left/Right mouse down starts the click timer
		if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
			m->clickpos.x = r.x;
			m->clickpos.y = r.y;
			m->clicktime = gfxSystemTicks();
			m->flags |= GMOUSE_FLG_CLICK_TIMER;
		}

		// Left/Right mouse up with the click timer still running may generate a click or context click
		if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT)) && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
			m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
			m->clicktime = gfxSystemTicks() - m->clicktime;

			// Was this a short click?
			if (m->clicktime <= gfxMillisecondsToTicks(GINPUT_MOUSE_CLICK_TIME)) {
				if ((upbtns & GINPUT_MOUSE_BTN_RIGHT))
					r.buttons |= GMETA_MOUSE_CXTCLICK;
				if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
					r.buttons |= GMETA_MOUSE_CLICK;
			}

			#if !GINPUT_TOUCH_NOTOUCH
				// Was this a long click on a touch device?
				if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) && m->clicktime >= gfxMillisecondsToTicks(GINPUT_TOUCH_CXTCLICK_TIME))
					r.buttons |= GMETA_MOUSE_CXTCLICK;
			#endif
		}
	}

	// Step 6 - Send the event to the listeners that are interested.
	{
		GSourceListener	*psl;

		// Send to the "All Mice" source listeners
		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)&MouseTimer, psl)))
			SendMouseEvent(psl, m, &r);

		// Send to the mouse specific source listeners
		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)m, psl)))
			SendMouseEvent(psl, m, &r);
	}

	// Step 7 - Finally save the results
	m->r.x = r.x;
	m->r.y = r.y;
	m->r.z = r.z;
	m->r.buttons = r.buttons;
}
Ejemplo n.º 5
0
	static uint32_t CalibrateMouse(GMouse *m) {
		coord_t		w, h;
		point		cross[4];		// The locations of the test points on the display
		point		points[4];		// The x, y readings obtained from the mouse for each test point
		uint32_t	err;
		#if GDISP_NEED_TEXT
			font_t		font1, font2;
		#endif

		#if GDISP_NEED_TEXT
			font1 = gdispOpenFont(CALIBRATION_FONT);
			if (!font1) font1 = gdispOpenFont("*");
			font2 = gdispOpenFont(CALIBRATION_FONT2);
			if (!font2) font2 = gdispOpenFont("*");
		#endif
		err = 0;
		w  =  gdispGGetWidth(m->display);
		h  =  gdispGGetHeight(m->display);
		#if GDISP_NEED_CLIP
			gdispGSetClip(m->display, 0, 0, w, h);
		#endif

		// Ensure we get minimaly processed readings for the calibration
		m->flags |= GMOUSE_FLG_IN_CAL;

		// Set up our calibration locations
        if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_EXTREMES)) {
            cross[0].x = 0;		cross[0].y = 0;
            cross[1].x = w-1;	cross[1].y = 0;
            cross[2].x = w-1;	cross[2].y = h-1;
            cross[3].x = w/2;	cross[3].y = h/2;
        } else {
            cross[0].x = w/4;	cross[0].y = h/4;
            cross[1].x = w-w/4;	cross[1].y = h/4;
            cross[2].x = w-w/4;	cross[2].y = h-h/4;
            cross[3].x = w/2;	cross[3].y = h/2;
        }

		// Set up the calibration display
		gdispGClear(m->display, Blue);
		#if GDISP_NEED_TEXT
			gdispGFillStringBox(m->display,
								0, CALIBRATION_TITLE_Y, w, CALIBRATION_TITLE_HEIGHT,
								CALIBRATION_TITLE, font1,  CALIBRATION_TITLE_COLOR, CALIBRATION_TITLE_BACKGROUND,
								justifyCenter);
		#endif

		// Calculate the calibration
		{
			unsigned	i, maxpoints;

			maxpoints = (gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST) ? 4 : 3;

			// Loop through the calibration points
			for(i = 0; i < maxpoints; i++) {
				int32_t		px, py;
				unsigned	j;

				// Draw the current calibration point
				CalibrationCrossDraw(m, &cross[i]);

				// Get a valid "point pressed" average reading
				do {
					// Wait for the mouse to be pressed
					while(!(m->r.buttons & GINPUT_MOUSE_BTN_LEFT))
						gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD);

					// Sum samples taken every CALIBRATION_POLL_PERIOD milliseconds while the mouse is down
					px = py = j = 0;
					while((m->r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
						// Limit sampling period to prevent overflow
						if (j < CALIBRATION_MAXPRESS_PERIOD/CALIBRATION_POLL_PERIOD) {
							px += m->r.x;
							py += m->r.y;
							j++;
						}
						gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD);
					}

					// Ignore presses less than CALIBRATION_MAXPRESS_PERIOD milliseconds
				} while(j < CALIBRATION_MINPRESS_PERIOD/CALIBRATION_POLL_PERIOD);
				points[i].x = px / j;
				points[i].y = py / j;

				// Clear the current calibration point
				CalibrationCrossClear(m, &cross[i]);
			}
		}

		// Apply 3 point calibration algorithm
		CalibrationCalculate(m, cross, points);

		 /* Verification of correctness of calibration (optional) :
		 *  See if the 4th point (Middle of the screen) coincides with the calibrated
		 *  result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
		 *  Else return the error.
		 */
		if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST)) {
			const GMouseJitter	*pj;

			// Are we in pen or finger mode
			pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter;

			// Transform the co-ordinates
			CalibrationTransform((GMouseReading *)&points[3], &m->caldata);

			// Do we need to rotate the reading to match the display
			#if GDISP_NEED_CONTROL
				if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
					coord_t		t;

					switch(gdispGGetOrientation(m->display)) {
						case GDISP_ROTATE_0:
							break;
						case GDISP_ROTATE_90:
							t = points[3].x;
							points[3].x = w - 1 - points[3].y;
							points[3].y = t;
							break;
						case GDISP_ROTATE_180:
							points[3].x = w - 1 - points[3].x;
							points[3].y = h - 1 - points[3].y;
							break;
						case GDISP_ROTATE_270:
							t = points[3].y;
							points[3].y = h - 1 - points[3].x;
							points[3].x = t;
							break;
						default:
							break;
					}
				}
			#endif

			// Is this accurate enough?
			err = (points[3].x - cross[3].x) * (points[3].x - cross[3].x) + (points[3].y - cross[3].y) * (points[3].y - cross[3].y);
			if (err > (uint32_t)pj->calibrate * (uint32_t)pj->calibrate) {
				#if GDISP_NEED_TEXT
					// No - Display error and return
					gdispGFillStringBox(m->display,
											0, CALIBRATION_ERROR_Y, w, CALIBRATION_ERROR_HEIGHT,
											CALIBRATION_ERROR_TEXT, font2,  CALIBRATION_ERROR_COLOR, CALIBRATION_ERROR_BACKGROUND,
											justifyCenter);
					gfxSleepMilliseconds(CALIBRATION_ERROR_DELAY);
				#endif
			} else
				err = 0;
		}

		// We are done calibrating
		#if GDISP_NEED_TEXT
			gdispCloseFont(font1);
			gdispCloseFont(font2);
		#endif
		m->flags &= ~GMOUSE_FLG_IN_CAL;
		m->flags |= GMOUSE_FLG_CLIP;

		// Save the calibration data (if possible)
		if (!err) {
			m->flags |= GMOUSE_FLG_CALIBRATE;

			#if GINPUT_TOUCH_USER_CALIBRATION_SAVE
				SaveMouseCalibration(gdriverGetDriverInstanceNumber((GDriver *)m), &m->caldata, sizeof(GMouseCalibration));
			#endif
			if (gmvmt(m)->calsave)
				gmvmt(m)->calsave(m, &m->caldata, sizeof(GMouseCalibration));
		}

		// Force an initial reading
		m->r.buttons = 0;
		GetMouseReading(m);

		// Clear the screen using the GWIN default background color
		#if GFX_USE_GWIN
			gdispGClear(m->display, gwinGetDefaultBgColor());
		#else
			gdispGClear(m->display, GDISP_STARTUP_COLOR);
		#endif

		return err;
	}
Ejemplo n.º 6
0
	static inline void CalibrationCalculate(GMouse *m, const point *cross, const point *points) {
		float		dx;
		coord_t		c0, c1, c2;
		(void)		m;

		// Work on x values
		c0 = cross[0].x;
		c1 = cross[1].x;
		c2 = cross[2].x;

		#if GDISP_NEED_CONTROL
			if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
				/* Convert all cross points back to GDISP_ROTATE_0 convention
				 * before calculating the calibration matrix.
				 */
				switch(gdispGGetOrientation(m->display)) {
				case GDISP_ROTATE_90:
					c0 = cross[0].y;
					c1 = cross[1].y;
					c2 = cross[2].y;
					break;
				case GDISP_ROTATE_180:
					c0 = c1 = c2 = gdispGGetWidth(m->display) - 1;
					c0 -= cross[0].x;
					c1 -= cross[1].x;
					c2 -= cross[2].x;
					break;
				case GDISP_ROTATE_270:
					c0 = c1 = c2 = gdispGGetHeight(m->display) - 1;
					c0 -= cross[0].y;
					c1 -= cross[1].y;
					c2 -= cross[2].y;
					break;
                default:
                    break;
				}
			}
		#endif

		/* Compute all the required determinants */
		dx  = (float)(points[0].x - points[2].x) * (float)(points[1].y - points[2].y)
				- (float)(points[1].x - points[2].x) * (float)(points[0].y - points[2].y);

		m->caldata.ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
							- (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
		m->caldata.bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
							- (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
		m->caldata.cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
							- c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
							+ c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;

		// Work on y values
		c0 = cross[0].y;
		c1 = cross[1].y;
		c2 = cross[2].y;

		#if GDISP_NEED_CONTROL
			if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
				switch(gdispGGetOrientation(m->display)) {
				case GDISP_ROTATE_90:
					c0 = c1 = c2 = gdispGGetWidth(m->display) - 1;
					c0 -= cross[0].x;
					c1 -= cross[1].x;
					c2 -= cross[2].x;
					break;
				case GDISP_ROTATE_180:
					c0 = c1 = c2 = gdispGGetHeight(m->display) - 1;
					c0 -= cross[0].y;
					c1 -= cross[1].y;
					c2 -= cross[2].y;
					break;
				case GDISP_ROTATE_270:
					c0 = cross[0].x;
					c1 = cross[1].x;
					c2 = cross[2].x;
					break;
                default:
                    break;
				}
			}
		#endif

		m->caldata.ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
							- (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
		m->caldata.by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
							- (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
		m->caldata.cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
							- c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
							+ c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
	}
Ejemplo n.º 7
0
static bool_t read_xyz(GMouse* m, GMouseReading* pdr)
{
	#if GMOUSE_STMPE811_TEST_MODE
		static GMouseReading n;
	#endif
	uint8_t		status;

	// Button information will be regenerated
	pdr->buttons = 0;

	#if GMOUSE_STMPE811_TEST_MODE
		aquire_bus(m);

		// Set the buttons to match various touch signals
		if ((read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80))
			pdr->buttons |= 0x02;

		status = read_byte(m, STMPE811_REG_FIFO_STA);
		if (!(status & 0x20))
			pdr->buttons |= 0x04;

		#if GMOUSE_STMPE811_GPIO_IRQPIN
			if (getpin_irq(m))
				pdr->buttons |= 0x08;
		#endif

		if ((status & 0x20)) {
			// Nothing in the fifo - just return the last position and pressure
			pdr->x = n.x;
			pdr->y = n.y;
			pdr->z = n.z;
			#if GMOUSE_STMPE811_GPIO_IRQPIN
				write_reg(m, STMPE811_REG_INT_STA, 0xFF);
			#endif
			release_bus(m);
			return TRUE;
		}

	#else
		// Is there a new sample or a touch transition
		#if GMOUSE_STMPE811_GPIO_IRQPIN
			if(!getpin_irq(m))
				return FALSE;
		#endif

		// Is there something in the fifo
		status = read_byte(m, STMPE811_REG_FIFO_STA);
		if ((status & 0x20)) {

			// Nothing in the fifo.

			// If not touched return the pseudo result
			if (!(read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80)) {

				pdr->z = gmvmt(m)->z_min;
				#if GMOUSE_STMPE811_GPIO_IRQPIN
					write_reg(m, STMPE811_REG_INT_STA, 0xFF);
				#endif
				release_bus(m);
				return TRUE;
			}

			// No new result
			#if GMOUSE_STMPE811_GPIO_IRQPIN
				write_reg(m, STMPE811_REG_INT_STA, 0xFF);
			#endif
			release_bus(m);
			return FALSE;
		}

	#endif

	// Time to get some readings
	pdr->x = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_X);
	pdr->y = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_Y);
	#if GMOUSE_STMPE811_READ_PRESSURE
		pdr->z = (coord_t)read_byte(m, STMPE811_REG_TSC_DATA_Z);
	#else
		pdr->z = gmvmt(m)->z_max;
	#endif

	#if !GMOUSE_STMPE811_SLOW_CPU
		if (!(status & 0xC0)) {
			// Is there more data to come
			if (!(read_byte(m, STMPE811_REG_FIFO_STA) & 0x20))
				_gmouseWakeup(m);
		} else
	#endif

	// Clear the rest of the fifo
	{
		write_reg(m, STMPE811_REG_FIFO_STA, 0x01);		// FIFO reset enable
		write_reg(m, STMPE811_REG_FIFO_STA, 0x00);		// FIFO reset disable
	}

	// All done
	#if GMOUSE_STMPE811_GPIO_IRQPIN
		write_reg(m, STMPE811_REG_INT_STA, 0xFF);
	#endif
	release_bus(m);

	#if GMOUSE_STMPE811_TEST_MODE
		// Save the result for later
		n.x = pdr->x;
		n.y = pdr->y;
		n.z = pdr->z;
	#endif

	// Rescale X,Y if we are using self-calibration
	#if GMOUSE_STMPE811_SELF_CALIBRATE
		#if GDISP_NEED_CONTROL
			switch(gdispGGetOrientation(m->display)) {
			default:
			case GDISP_ROTATE_0:
			case GDISP_ROTATE_180:
				pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
				pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
				break;
			case GDISP_ROTATE_90:
			case GDISP_ROTATE_270:
				pdr->x = gdispGGetHeight(m->display) - pdr->x / (4096/gdispGGetHeight(m->display));
				pdr->y = pdr->y / (4096/gdispGGetWidth(m->display));
				break;
			}
		#else
			pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
			pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
		#endif
	#endif

	return TRUE;
}
Ejemplo n.º 8
0
bool_t ginputCalibrateMouse(uint16_t instance) {
	#if !GINPUT_MOUSE_NEED_CALIBRATION
		(void) instance;
		
		return FALSE;
	#else

		const coord_t height  =  gdispGGetHeight(MouseConfig.display);
		const coord_t width  =  gdispGGetWidth(MouseConfig.display);
		#if GINPUT_MOUSE_CALIBRATE_EXTREMES
			const MousePoint cross[]  =  {{0, 0},
									{(width - 1) , 0},
									{(width - 1) , (height - 1)},
									{(width / 2), (height / 2)}}; /* Check point */
		#else
			const MousePoint cross[]  =  {{(width / 4), (height / 4)},
									{(width - (width / 4)) , (height / 4)},
									{(width - (width / 4)) , (height - (height / 4))},
									{(width / 2), (height / 2)}}; /* Check point */
		#endif
		MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS];
		const MousePoint	*pc;
		MousePoint *pt;
		int32_t px, py;
		unsigned i, j;
		font_t	font1, font2;
		#if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
			unsigned	err;
		#endif

		if (instance || (MouseConfig.flags & FLG_IN_CAL))
			return FALSE;

		font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT);
		font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2);

		MouseConfig.flags |= FLG_IN_CAL;
		gtimerStop(&MouseTimer);
		MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW);

		#if GDISP_NEED_CLIP
			gdispGSetClip(MouseConfig.display, 0, 0, width, height);
		#endif

		#if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
			while(1) {
		#endif
				gdispGClear(MouseConfig.display, Blue);

				gdispGFillStringBox(MouseConfig.display, 0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1,  White, Blue, justifyCenter);

				for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {
					_tsDrawCross(pc);

					do {

						/* Wait for the mouse to be pressed */
						while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT))
							gfxSleepMilliseconds(20);

						/* Average all the samples while the mouse is down */
						for(px = py = 0, j = 0;
								gfxSleepMilliseconds(20),			/* Settling time between readings */
								get_raw_reading(&MouseConfig.t),
								(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT);
								j++) {
							px += MouseConfig.t.x;
							py += MouseConfig.t.y;
						}

					} while(!j);

					pt->x = px / j;
					pt->y = py / j;

					_tsClearCross(pc);

					if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) {
						gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2,  Red, Yellow, justifyCenter);
						gfxSleepMilliseconds(5000);
						gdispGFillArea(MouseConfig.display, 0, 35, width, 40, Blue);
					}

				}

				/* Apply 3 point calibration algorithm */
				_tsDo3PointCalibration(cross, points, MouseConfig.display, &MouseConfig.caldata);

				 /* Verification of correctness of calibration (optional) :
				 *  See if the 4th point (Middle of the screen) coincides with the calibrated
				 *  result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
				 *  Else, start from the beginning.
				 */
		#if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
				/* Transform the co-ordinates */
				MouseConfig.t.x = points[3].x;
				MouseConfig.t.y = points[3].y;
				_tsTransform(&MouseConfig.t, &MouseConfig.caldata);
				_tsOrientClip(&MouseConfig.t, MouseConfig.display, FALSE);

				/* Calculate the delta */
				err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) +
					(MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y);

				if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)
					break;

				gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2,  Red, Yellow, justifyCenter);
				gfxSleepMilliseconds(5000);
			}
		#endif

		// Restart everything
		gdispCloseFont(font1);
		gdispCloseFont(font2);
		MouseConfig.flags |= FLG_CAL_OK;
		MouseConfig.last_buttons = 0;
		get_calibrated_reading(&MouseConfig.t);
		MouseConfig.flags &= ~FLG_IN_CAL;
		if ((MouseConfig.flags & FLG_INIT_DONE))
			gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
		
		// Save the calibration data (if possible)
		if (MouseConfig.fnsavecal) {
			MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
			MouseConfig.flags |= FLG_CAL_SAVED;
		}

		// Clear the screen using the GWIN default background color
		#if GFX_USE_GWIN
			gdispGClear(MouseConfig.display, gwinGetDefaultBgColor());
		#else
			gdispGClear(MouseConfig.display, Black);
		#endif
	
		return TRUE;
	#endif
}
Ejemplo n.º 9
0
	static inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, GDisplay *g, Calibration *c) {
		float		dx;
		coord_t		c0, c1, c2;

		#if GDISP_NEED_CONTROL
			/* Convert all cross points back to GDISP_ROTATE_0 convention
			 * before calculating the calibration matrix.
			 */
			switch(gdispGGetOrientation(g)) {
			case GDISP_ROTATE_90:
				c0 = cross[0].y;
				c1 = cross[1].y;
				c2 = cross[2].y;
				break;
			case GDISP_ROTATE_180:
				c0 = c1 = c2 = gdispGGetWidth(g) - 1;
				c0 -= cross[0].x;
				c1 -= cross[1].x;
				c2 -= cross[2].x;
				break;
			case GDISP_ROTATE_270:
				c0 = c1 = c2 = gdispGGetHeight(g) - 1;
				c0 -= cross[0].y;
				c1 -= cross[1].y;
				c2 -= cross[2].y;
				break;
			case GDISP_ROTATE_0:
			default:
				c0 = cross[0].x;
				c1 = cross[1].x;
				c2 = cross[2].x;
				break;
			}
		#else
			(void)	g;

			c0 = cross[0].x;
			c1 = cross[1].x;
			c2 = cross[2].x;
		#endif

		/* Compute all the required determinants */
		dx  = (float)(points[0].x - points[2].x) * (float)(points[1].y - points[2].y)
				- (float)(points[1].x - points[2].x) * (float)(points[0].y - points[2].y);

		c->ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
				- (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
		c->bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
				- (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
		c->cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
				- c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
				+ c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;

		#if GDISP_NEED_CONTROL
			switch(gdispGGetOrientation(g)) {
			case GDISP_ROTATE_90:
				c0 = c1 = c2 = gdispGGetWidth(g) - 1;
				c0 -= cross[0].x;
				c1 -= cross[1].x;
				c2 -= cross[2].x;
				break;
			case GDISP_ROTATE_180:
				c0 = c1 = c2 = gdispGGetHeight(g) - 1;
				c0 -= cross[0].y;
				c1 -= cross[1].y;
				c2 -= cross[2].y;
				break;
			case GDISP_ROTATE_270:
				c0 = cross[0].x;
				c1 = cross[1].x;
				c2 = cross[2].x;
				break;
			case GDISP_ROTATE_0:
			default:
				c0 = cross[0].y;
				c1 = cross[1].y;
				c2 = cross[2].y;
				break;
			}
		#else
			c0 = cross[0].y;
			c1 = cross[1].y;
			c2 = cross[2].y;
		#endif

		c->ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
				- (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
		c->by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
				- (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
		c->cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
				- c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
				+ c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
	}
Ejemplo n.º 10
0
static void WM_Move(GHandle gh, coord_t x, coord_t y) {
	coord_t		u, v;

	#if GWIN_NEED_CONTAINERS
		if (gh->parent) {
			// Clip to the parent size
			u = gh->parent->width - ((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent) - ((const gcontainerVMT *)gh->parent->vmt)->RightBorder(gh->parent);
			v = gh->parent->height - ((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent) - ((const gcontainerVMT *)gh->parent->vmt)->BottomBorder(gh->parent);
		} else
	#endif
	{
		// Clip to the screen
		u = gdispGGetWidth(gh->display);
		v = gdispGGetHeight(gh->display);
	}

	// Make sure we are positioned in the appropriate area
	if (x+gh->width > u)	x = u-gh->width;
	if (x < 0) x = 0;
	if (y+gh->height > v)	y = v-gh->height;
	if (y < 0) y = 0;

	// Make sure we don't overflow the appropriate area
	u -= x;
	v -= y;
	if (gh->width < u)	u = gh->width;
	if (gh->height < v)	v = gh->height;
	if (u != gh->width || v != gh->height)
		WM_Size(gh, u, v);

	#if GWIN_NEED_CONTAINERS
		if (gh->parent) {
			// Convert to a screen relative position
			x += gh->parent->x + ((const gcontainerVMT *)gh->parent->vmt)->LeftBorder(gh->parent);
			y += gh->parent->y + ((const gcontainerVMT *)gh->parent->vmt)->TopBorder(gh->parent);
		}
	#endif

	// If there has been no move just exit
	if (gh->x == x && gh->y == y)
		return;

	// Clear the old area and then redraw
	if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
		// We need to make this window invisible and ensure that has been drawn
		gwinSetVisible(gh, FALSE);
		_gwinFlushRedraws(REDRAW_WAIT);

		// Do the move
		u = gh->x; gh->x = x;
		v = gh->y; gh->y = y;

		#if GWIN_NEED_CONTAINERS
			// Any children need to be moved
			if ((gh->flags & GWIN_FLG_CONTAINER)) {
				GHandle		child;

				// Move to their old relative location. THe WM_Move() will adjust as necessary
				for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
					WM_Move(child, child->x-u-((const gcontainerVMT *)gh->vmt)->LeftBorder(gh), child->y-v-((const gcontainerVMT *)gh->vmt)->TopBorder(gh));
			}
		#endif

		gwinSetVisible(gh, TRUE);
	} else {
		u = gh->x; gh->x = x;
		v = gh->y; gh->y = y;

		#if GWIN_NEED_CONTAINERS
			// Any children need to be moved
			if ((gh->flags & GWIN_FLG_CONTAINER)) {
				GHandle		child;

				// Move to their old relative location. THe WM_Move() will adjust as necessary
				for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
					WM_Move(child, child->x-u-((const gcontainerVMT *)gh->vmt)->LeftBorder(gh), child->y-v-((const gcontainerVMT *)gh->vmt)->TopBorder(gh));
			}
		#endif
	}
}
Ejemplo n.º 11
0
static void WM_Size(GHandle gh, coord_t w, coord_t h) {
	coord_t		v;

	#if GWIN_NEED_CONTAINERS
		if (gh->parent) {
			// Clip to the container
			v = gh->parent->x + gh->parent->width - ((const gcontainerVMT *)gh->parent->vmt)->RightBorder(gh->parent);
			if (gh->x+w > v)	w = v - gh->x;
			v = gh->parent->y + gh->parent->height - ((const gcontainerVMT *)gh->parent->vmt)->BottomBorder(gh->parent);
			if (gh->y+h > v) 	h = v - gh->y;
		}
	#endif

	// Clip to the screen
	v = gdispGGetWidth(gh->display);
	if (gh->x+w > v) 	w = v - gh->x;
	v = gdispGGetHeight(gh->display);
	if (gh->y+h > v) 	h = v - gh->y;

	// Give it a minimum size
	if (w < MIN_WIN_WIDTH)	w = MIN_WIN_WIDTH;
	if (h < MIN_WIN_HEIGHT)	h = MIN_WIN_HEIGHT;

	// If there has been no resize just exit
	if (gh->width == w && gh->height == h)
		return;

	// Set the new size and redraw
	if ((gh->flags & GWIN_FLG_SYSVISIBLE)) {
		if (w >= gh->width && h >= gh->height) {

			// The new size is larger - just redraw
			gh->width = w; gh->height = h;
			_gwinUpdate(gh);

		} else {
			// We need to make this window invisible and ensure that has been drawn
			gwinSetVisible(gh, FALSE);
			_gwinFlushRedraws(REDRAW_WAIT);

			// Resize
			gh->width = w; gh->height = h;

			#if GWIN_NEED_CONTAINERS
				// Any children outside the new area need to be moved
				if ((gh->flags & GWIN_FLG_CONTAINER)) {
					GHandle		child;

					// Move to their old relative location. THe WM_Move() will adjust as necessary
					for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
						WM_Move(child, child->x-gh->x-((const gcontainerVMT *)gh->vmt)->LeftBorder(gh), child->y-gh->y-((const gcontainerVMT *)gh->vmt)->TopBorder(gh));
				}
			#endif

			// Mark it visible again in its new location
			gwinSetVisible(gh, TRUE);
		}
	} else {
		gh->width = w; gh->height = h;

		#if GWIN_NEED_CONTAINERS
			// Any children outside the new area need to be moved
			if ((gh->flags & GWIN_FLG_CONTAINER)) {
				GHandle		child;

				// Move to their old relative location. THe WM_Move() will adjust as necessary
				for(child = gwinGetFirstChild(gh); child; child = gwinGetSibling(child))
					WM_Move(child, child->x-gh->x-((const gcontainerVMT *)gh->vmt)->LeftBorder(gh), child->y-gh->y-((const gcontainerVMT *)gh->vmt)->TopBorder(gh));
			}
		#endif
	}
}