piTFT adafruit tft+touchscreen


I have done some digging and here is what I got so far. Linux has things called framebuffers for controlling the displays. It uses fb0 for the hdmi port, and fb1 for the touch screen. It seems that openFrameworks writes to fb0 and there isnt much you can do about it (something about opengl and the hardware acceleration, yada yada)

My fix is set openFrameworks window size to 720x480 in main.cpp and then use this handy framebuffer mirroring utility: https://github.com/notro/fbtft/wiki/Framebuffer-use

This thread was helpful in understanding (partially) the nature of the problem


thanks for the info!! that just what i need to know

so you use this https://github.com/tasanakorn/rpi-fbcp to mirror the content of fb1 to fb0


My previous post used a separate app to copy the contents of one frame buffer over to another so that you can see your openFrameworks stuff on the touch screen. There are a few problems with this approach. One is that you have to run it separately from your OF app, which is lame. Another problem is that it simple runs on a timer and duplicates the frame buffer every so often. This means that the frame rate is slower than it needs to be. It also means that it is not synced with your display so there is no telling when it will begin the copy. It might start copying while you are still writing the buffer. Though, in practice I never saw this happen, it seems possible for tearing to occur.

To address those problems I have ported the original c based framebuffer copying code into a c++ for use inside OF directly.

Here is how you can use it

Copy and paste this code into testApp.cpp just under the #include statement

#include <stdio.h>
#include <syslog.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <bcm_host.h>

class FrameBufferCopier
		int display;
		DISPMANX_MODEINFO_T display_info;
		//DISPMANX_RESOURCE_HANDLE_T screen_resource;
		int screen_resource;
		uint32_t image_prt;
		VC_RECT_T rect1;
		int ret;
		int fbfd;
		char *fbp;

		struct fb_var_screeninfo vinfo;
		struct fb_fix_screeninfo finfo;
		int Initialize()
			fbfd = 0;
			fbp = 0;

			openlog("fbcp", LOG_NDELAY | LOG_PID, LOG_USER);

			display = vc_dispmanx_display_open(0);
			if (!display) {
				syslog(LOG_ERR, "Unable to open primary display");
				return -1;
			ret = vc_dispmanx_display_get_info(display, &display_info);
			if (ret) {
				syslog(LOG_ERR, "Unable to get primary display information");
				return -1;
			syslog(LOG_INFO, "Primary display is %d x %d", display_info.width, display_info.height);

			fbfd = open("/dev/fb1", O_RDWR);
			if (!fbfd) {
				syslog(LOG_ERR, "Unable to open secondary display");
				return -1;
			if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
				syslog(LOG_ERR, "Unable to get secondary display information");
				return -1;
			if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
				syslog(LOG_ERR, "Unable to get secondary display information");
				return -1;

			syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

			screen_resource = vc_dispmanx_resource_create(VC_IMAGE_RGB565, vinfo.xres, vinfo.yres, &image_prt);
			if (!screen_resource) {
				syslog(LOG_ERR, "Unable to create screen buffer");
				return -1;

			fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
			if (fbp <= 0) {
				syslog(LOG_ERR, "Unable to create mamory mapping");
				ret = vc_dispmanx_resource_delete(screen_resource);
				return -1;

			vc_dispmanx_rect_set(&rect1, 0, 0, vinfo.xres, vinfo.yres);			
			return 1;
		void Dispose()
			munmap(fbp, finfo.smem_len);
			ret = vc_dispmanx_resource_delete(screen_resource);

		void Copy()
			vc_dispmanx_snapshot(display, screen_resource, (DISPMANX_TRANSFORM_T)0);
			vc_dispmanx_resource_read_data(screen_resource, &rect1, fbp, vinfo.xres * vinfo.bits_per_pixel / 8);
FrameBufferCopier fbcp;

Then in your draw method add this code after all drawing commands have been completed


I included the #ifdef’s so that you can commit out the #define USE_FRAMEBUFFER line if you want to work with the project on your computer and not get all the compiler errors. There is probably a more elegant way to achieve this, but I don’t know about it.


@greengiant831 thanks for that! Works like a charm.

What about the touchscreen? I have the event register on the OS… anybody have a clue about how to read mouse events from that?


igual this helps


grande nacho!


Hi all, I’m putting together both the framebuffer copy and the touch events in an addon.

Let me know if you want to help


I’m stock porting this code from https://github.com/mwilliams03/Pi-Touchscreen-basic/blob/master/touch.h that seams not to compile under linux. Any idea?

char *events[EV_MAX + 1] = {
	[0 ... EV_MAX] = NULL,
	[EV_SYN] = "Sync",			[EV_KEY] = "Key",
	[EV_REL] = "Relative",			[EV_ABS] = "Absolute",
	[EV_MSC] = "Misc",			[EV_LED] = "LED",
	[EV_SND] = "Sound",			[EV_REP] = "Repeat",
	[EV_FF] = "ForceFeedback",		[EV_PWR] = "Power",
	[EV_FF_STATUS] = "ForceFeedbackStatus",

@patricio you doing this?

extern "C" {
#include "touch.h"
1 Like

also from the readme it looks like it requires wiringPi so make sure you are linking that - here is how I did it


I’m still getting:

../../../addons/ofxPiTFT/src/touch.h: In lambda function:
../../../addons/ofxPiTFT/src/touch.h:343:30: error: expected ‘{’ before ‘=’ token
../../../addons/ofxPiTFT/src/touch.h: At global scope:
../../../addons/ofxPiTFT/src/touch.h:343:30: warning: lambda expressions only available with -std=c++0x or -std=gnu++0x [enabled by default]
../../../addons/ofxPiTFT/src/touch.h:343:32: error: no match for ‘operator=’ in ‘{} = leds’
../../../addons/ofxPiTFT/src/touch.h:343:32: note: candidate is:
../../../addons/ofxPiTFT/src/touch.h:343:28: note: <lambda()>&<lambda()>::operator=(const<lambda()>&)
../../../addons/ofxPiTFT/src/touch.h:343:28: note:   no known conversion for argument 1 from ‘char* [16]’ to ‘const<lambda()>&’
../../../addons/ofxPiTFT/src/touch.h:344:3: error: expected identifier before numeric constant
../../../addons/ofxPiTFT/src/touch.h:344:9: error: type ‘<lambda>’ with no linkage used to declare function ‘void<lambda>::operator()() const’ with linkage [-fpermissive]

It looks odd to me because of the extra commas at the end of each array but I guess gcc is fine with this but g++ is not

For instance if you try and compile his project with

$ g++ -g -o buttonExample buttonExample.c -l wiringPi

instead of

$ gcc -g -o buttonExample buttonExample.c -l wiringPi

you will get the same errors


Hello! I have managed to have my animation program run on the PiTFT screen as a copy of the HDMI output as described here. But the framerate is very low, 30fps instead of 60fps. It doesn’t look good. Is it possible to run an openframeworks program on the PiTFT only, to get higher framerate? Maybe make the PiTFT the main display for the entire operating system?


I think that its not possible, maybe you can use an small hdmi display


It looks like the reason it isn’t possible is because the PiTFT is not connected to the GPU like the HDMI and RCA connectors are. And openGL works on the GPU. I have decided to use this screen instead: https://www.adafruit.com/products/913 which uses the RCA connection. A little bit blurry on text and thin lines, but smooth and fast and very easy to use. I haven’t found this small screens with HDMI connection. Probably expensive to make, since the pixels then have to be very tiny.


Have anyone tested this screen:


Says it operates as primary display. Maybe it utilizes the GPU?


I just received that sparkfun screen, and sadly it does not work with openFrameworks out of the box. At first glance it looks like it does the alternative framebuffer thing too.


im not an expert but any screen that uses the gpio to connect with the rpi its going to use the framebuffer way. Only a hdmi or composite its going to work as you expected


Just for reference, I got touch events working with ofxPiTFT. I’ll push changes soon. Sooner if it’s urgent for anyone :smile:

1 Like

That´s super!!! Im curious to see how did you do it