PiTFT and with no X11. Just got touch working. :)

Moderators: adafruit_support_bill, adafruit

Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/
Locked
User avatar
richarduk
 
Posts: 64
Joined: Tue Nov 05, 2013 4:55 pm

PiTFT and with no X11. Just got touch working. :)

Post by richarduk »

PiTFT Mini Kit - 320x240 2.8" TFT+Touchscreen
PRODUCT ID: 1601

Some notes on what I have learnt.

So I'm a bit of an old school c/c++ coder and don't know anything about X11 coding. Give me a framebuffer to write too and I'm off on my own. ;)

So I am working on a little front end for my RPi which is running Octoprint on my k8200 3D Printer. The rendering of my frontend is easy, I'm using SDL for this. The RPi has sdl 1.2 in the repositories and for the most part works well with the PiTFT. Here are a couple things I have worked out about the rendering.

1) One line you may want to add to your code to make life easier is.

Code: Select all

SDL_putenv((char*)"SDL_FBDEV=/dev/fb1");
Do this before starting SDL and you don't need to remember to do it before you run your app.

2) SDL can not synchronise with the VSYNC, I asked about and looked at the docs and looks to me that VSYNC is only available on a pin on the driver chip. The side effect of this is that your app will be running very high frame rates making the display 'tear'

Not got a good fix for this for a game, but for my app I should really be updating the UI based on events anyway. So I will brush that under the carpet.

Now here is the biggest issue I have run into. Taken a while to get sorted as I'm working full time and doing a degree (about half way throw now).

SDL 1.2 has some very poor code for reading the touch screen. It assumes the touch screen is the same orientation as the display and the same resolution. No good for our PiTFT. So over to using 'input_event' and my own code. I wanted to high light this as it took a lot of searching about. The linux 'input_event' is very poorly documented. There is lots of it but it's all duplicated from the header files and is only good for confusing me. ;)
Maybe someone knows of a good tutorial?

So to do this touch input code you need to run it in a thread because it will be blocking on a file read. Also you'll need a little util function I wrote that wraps select() up in something a little more usable.
Retuns <0 for error, 0 for no data and > 0 for bytes read.

Code: Select all

int read_timeout(int fd, void *buf, size_t count,int theTimeout)	//timeout in seconds.
{
	if( theTimeout < 1 )
	{
		return ::read(fd,buf,count);
	}

	// Initialize file descriptor sets
	fd_set read_fds, write_fds, except_fds;
	FD_ZERO(&read_fds);
	FD_ZERO(&write_fds);
	FD_ZERO(&except_fds);
	FD_SET(fd, &read_fds);

	// Set timeout to theTimeout seconds
	struct timeval timeout;
	timeout.tv_sec = theTimeout;
	timeout.tv_usec = 0;

	// Wait for input to become ready or until the time out; the first parameter is
	// 1 more than the largest file descriptor in any of the sets
	int ret = select(fd + 1, &read_fds, &write_fds, &except_fds, &timeout);
	if( ret == 1 )
	{
		return ::read(fd,buf,count);
	}
	return ret;
}
This function was based on a stack overflow post I found.

Here is the main guts of the thread code that reads the touch screen. It auto calibrates so you first touch the four corners and then off you go. This is using a few of my own classes. When I get time I'll write a self contained version with just one header / cpp file. But may be a week or so I have an assignment due on the degree course. :)
I just hope this has help someone in the future because I was a bit lost with this.
You'll see readingData.Enter() and readingData.Exit() this is just a semiphore code. You could chance it and remove it.

Code: Select all

	/*!
		This is the code that is run inside the thread.
	*/
	virtual void Main()
	{
		inputDevice = open(MOUSEFILE, O_RDONLY);
		if( inputDevice == 0 )
		{
			Error("Failed to open touch screen device");
			return;
		}

		while( Quit == false )
		{
			struct input_event ie;
			if( read_timeout(inputDevice,&ie,sizeof(ie),5) > 0 )
			{
				switch(ie.type)
				{
				case EV_SYN:
					break;

				case EV_ABS:
					if(ie.code == ABS_X )
					{
						UpdateX(ie.value);
					}
					else if(ie.code == ABS_Y )
					{
						UpdateY(ie.value);
					}
					else if(ie.code == 24 )
					{
						if( readingData.Enter() )
						{
							touchPressure = ie.value;
							readingData.Exit();
						}
					}
					else
					{
						Debug("%d %d\n",ie.code,ie.value);
					}
				break;
				}
//				Debug("rawPosition(%f,%f)",rawPosition.x,rawPosition.y);
			}
		};
		Debug(config.toString());
		Debug("Closing file");
		close(inputDevice);
		Debug("Returning from thread");
	}
	
	
private:
	CriticalSection readingData;
	int inputDevice;
	Vector2 rawPosition;

	void UpdateX(int value)
	{
		if( config.min.x > value )
		{
			config.min.x = value;
		}
		
		if( config.max.x < value )
		{
			config.max.x = value;
		}

		if( readingData.Enter() )
		{
			float dx = (float)(config.max.x - config.min.x);

			if( dx != 0 )
			{
				rawPosition.x = (float)(value - config.min.x) / dx;
			}
			readingData.Exit();
		}
	}
	
	void UpdateY(int value)
	{
		if( config.min.y > value )
		{
			config.min.y = value;
		}
		
		if( config.max.y < value )
		{
			config.max.y = value;
		}

		if( readingData.Enter() )
		{
			float dy = (float)(config.max.y - config.min.y);

			if( dy != 0 )
			{
				rawPosition.y = (float)(value - config.min.y) / dy;
			}
			readingData.Exit();
		}
	}
many thanks,
Richard e Collins. :)

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: PiTFT and with no X11. Just got touch working. :)

Post by adafruit_support_mike »

That's a lot of good research.. thanks for posting it! ;-)

Locked
Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/

Return to “Adafruit Raspberry Pi® accessories”