Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Looking for a Touchscreen controller driver written in C18 for PIC

Status
Not open for further replies.
Could it be problem in my reading function regarding how i shift MSB and LSB in order to get the 12 bit result ?

I first( shift 8 rows left MSB and add LSB ) then i shift this result 3 rows right, it that correct ?
Code:
return ((msb << 8) | lsb) >> 3;

Once result has been returned, i've tried to convert it to ascii character and display the X and Y positions of the touched point in my GLCD screen :
Code:
// Int table for 10 sample storage :
unsigned short int PEN_position_X[10];
unsigned short int PEN_position_Y[10];

// Buffer for int to ascii conversion :
unsigned char ascii_PEN_position_X;
unsigned char ascii_PEN_position_Y;
...
uitoa(PEN_position_X[0],(BYTE*)ascii_PEN_position_X);
uitoa(PEN_position_Y[0],(BYTE*)ascii_PEN_position_Y);

Here is my reading function :

Code:
unsigned short int ADS7843_read(unsigned char address)
{
	volatile BYTE Dummy;	
	unsigned int msb, lsb; 

	// Configure SPI
	ADS7843_SPIEN = 0;										
  ADS7843_SPICON1 = ADS7843_SPICON1_CFG;			
	ADS7843_SPIEN = 1;										
  
	ADS7843_CS_IO = 0;        						
	ADS7843_SPI_IF = 0;       						

	/*********************************/
	ADS7843_SSPBUF = address;    					
	while(!ADS7843_SPI_IF);ADS7843_SPI_IF = 0;  	
	Dummy = ADS7843_SSPBUF;								
	/*********************************/
   
	/*********************************/
	// Get MSB :
	ADS7843_SSPBUF = 0x00;								
	while(!ADS7843_SPI_IF);ADS7843_SPI_IF = 0;  	
	msb = ADS7843_SSPBUF;      					
	/*********************************/	   
	
	/*********************************/
	// Get LSB :
	ADS7843_SSPBUF = 0x00;								
	while(!ADS7843_SPI_IF);ADS7843_SPI_IF = 0;  	
	lsb = ADS7843_SSPBUF;      						
	/*********************************/

	ADS7843_CS_IO = 1;        						
	ADS7843_SPIEN = 0;										

	return ((msb << 8) | lsb) >> 3; 	
}
 
Last edited:
Could it be problem in my reading function regarding how i shift MSB and LSB in order to get the 12 bit result ?

I first( shift 8 rows left MSB and add LSB ) then i shift this result 3 rows right, it that correct ?
Code:
return ((msb << 8) | lsb) >> 3;

'|' = Bitwise OR. You just need to add them, '+'. Otherwise it should be right.

Try that and let me know how it goes.
 
Last edited:
Yes, it is better now !

Here are the results i get :

Top left : (3939,3618) Top right : (3854,3620)

the middle is approx : (2040,1969)

Bottom left : (3184,4690) Bottom right : (3887,4500)

I've found each touch varies gets a different result every time : it could vary about +-500
I think next steps for calibration will be difficult, can you advice me please ?
 
You are still receiving numbers larger than 4096....
 
You are right, but i now do this calculation at the end of my reading SPI function :

Code:
return ((pen_msb << 8) + pen_lsb) >> 3; 			// Put the 12 bits result in 16 bits format : 0000 MSB LSB

What shouldbe wrong ?
 
I got some help i have been adviced to write this instead :
Code:
return (((pen_msb & 0x7F) << 8) + pen_lsb) >> 3;

I will spend some time to understand why msb has to be 'anded' with 7F
 
If you 'and' your MSB with 0x7F, then your results will be under 4096 but it is not ideal. If anything, you should mask it once they have been added:

Code:
return (((pen_msb<< 8) + pen_lsb) >> 3) & 0x0FFF;

However the need to do that likely suggests a problem elsewhere. If it is working properly you will not need to mask your result to obtain the correct answer. I would still be checking your SPI configuration. Does CKE = 1 and CKP = 0?


Top left : (3939,3618) Top right : (3854,3620)

the middle is approx : (2040,1969)

Bottom left : (3184,594) Bottom right : (3887,404)

For the Bottom left and Bottom right corners I have modified your values by 'anding' them with 0xFFF. It seems to me that your Y axis readings are in the ballpark after 'anding' them. But it seems that your X axis values do not correspond much with your position on the screen.

For example for both 'left' touches (top and bottom left) the X axis readings should be fairly similar because they are both in the same position on the x axis. For both 'right' (top and bottom right) then both x axis readings should be similar (which they are).

Hmmm, TBH you have me stumped ;)
 
Last edited:
Yes, my SPI settings are CKE = 1 , CKP = 0 , SMP = 1 , clock speed = 650 khz.
I'm not sure about SMP setting, should it be 1 or 0 ? ( this does not change the results )

I've done a new bank of tests with the MSB 0x7F masked, it appears that X results are ideed outstanding.
Y axis looks better.

I read the X axis with 0x90 and send twice 0x00 , maybe some delays are required somewhere ?
I've check your code : you send straight away the axis register address and 0x00 twice.
 
I'd leave SMP at default (0).

Check Figure 5 in the datasheet, you have to check the busy line and wait until it goes low before you clock the data out of the ADS7843.

It is in my code:

Code:
while(Touch_Busy == 1);					// Makes sure the screen isn't busy

Once you get that fixed up you might be all sorted :)
 
ah , i did not understand the Busy line like you ...

In fig 5, i see that the 2sd serie of DCLK starts 'before' Busy line goes low.
So i did not think i should wait here to send the 2 send the 0x00 series.
The graph, shows that Dout is indeed coming out when Busy line goes low.

So if i understand well your advice,
I should add some delay, or check Busy pin state ( as you did it ) after sending out the axis register address and then wait before sending the 2 sequences of 0x00 ?
 
Last edited:
So if i understand well your advice,
I should add some delay, or check Busy pin state ( as you did it ) after sending out the axis register address and then wait before sending the 2 sequences of 0x00 ?

Yep, that's right. I agree it is strange how in the datasheet the clock starts before the busy line goes low.

You can use a delay, but you are better off just checking the busy line (it will be faster).

> Send Address.
> Wait till Busy clear.
> Clock Data Out (Send 0x00's).
 
Last edited:
I'm back with good news !

I get correct values without 0x7F mask, you was right issue was coming from SPI settings.
It looks there is no need to wait Busy line either, i've verified with my logic analyser its state comes down only when the first sequence of 0x00 is being sent.
The axis register address and twice 0x00 sequences can be sent straigh away.

After many tests i confirm that Gobbledok was right : SPI settings are CKP/CPOL = 0 ; CKE = 1 ; SMP = 0; tested working with SCK clock frequency at 650 khz and 2.5Mhz.

---

Here are the raw values i get with a 128x64 panel :

Top, left : (325,3652) Top right : (3916,3640)
Btm, left : (347,494) Btm right : (3877,504)

Center ( 2104,2019)

So offsets are about :

+-22 from Top Left to Bottom Left X axis.
+- 10 from Bottom Left to Bottom right Y axis.
+- 39 from Bottom Right to Top Right X axis.
+- 12 from Top Left to Top Right Y axis.

I now have to calibrate these raw values to friendly values from Top Left (0,0) to Bottom Right (127,63)

Gobbledok, can you advice me for next steps in order to rescale my values, i've found offsets differents for each axis . :rolleyes:
 
Nice work crocu, glad it's finally working :)

To scale your results, use the defines discussed earlier in the thread. I have added your values for you.

Code:
// These are measured calibration values
// Place your own measured calibration values here
#define Xmin 325
#define Xmax 3916
#define Ymin 494
#define Ymax 3652
#define Xrange 0.0354	// =(num of x pixels/(Xmax-Xmin))     = 127/(3916-325)
#define Yrange 0.0199	// =(num of y pixels/(Ymax-Ymin))      = 63/(3652-494)
//

Here's an example on converting your ADS7843 reading into pixels using the above defines:

Code:
Lets use your middle of screen values above to work out the actual pixel that represents:

Reading from ADS7843 = 2104, 2019.

X Axis = (2104-Xmin)*Xrange
X Axis = 63

Y Axis = (2019-Ymin)*Yrange
Y Axis = 31

Therefore the ADS7843 result of 2104, 2019 is equal to the pixel value of 63, 30.

Then if that's working properly (and you have a PutPixel function) you can do something simple to test it out, like:

Code:
void main(void){
         while(1){ 
                 ReadTouchXY();
                 PutPixel(TouchX, TouchY); 
        }
}

That will draw on the screen as you touch.

Hope that made sense crocu, if you have any other hassles let me know.
 
Last edited:
It is almost working fine :

I've tried, as you suggested, to use the plot function to point on the screen where the pen is.
When i click the top right hand side, the lit pixel is the one on the bottom right hand side

It looks working as a mirror.
 
Hi Crocu try inverting the y axis result:

Code:
Y Axis = (2019-Ymin)*Yrange
Y Axis = (63 - 31)
Y Axis = 32

When you do 63-(result), it inverts the result. For example, if your original value was 63, when you do 63 - 63, it will = 0. Inverted.

You probably want some basic error checking also, to make sure that your touch screen result (once converted) is no larger than the number of pixels on your screen.

For example, place something like this somewhere after you have done the maths on your result:

Code:
if(TouchX > 127){ TouchX = 127; }
if(TouchY > 63){ TouchY = 63; }

That's based on your 64x128px screen.

Take note that in post #33 I have edited it and changed the values of Xrange and Yrange slightly. I incorrectly used 128*64 to calculate it when I should have used 127*63.
 
Last edited:
I would like to thank you very much Gobbledok, it works perfectly now.

Could it be also possible to invert Y+ / Y- pins on the hardware in order to invert the result ?

My next step is to create buttons with my GLCD library, i'm thinking about how to check if a touch is within ('inside') or not ('outside') the area of the button's coordinates ?

Is the best way to proceed to test with 'if' tests ?
ie :
Code:
if (PEN_X > 30) && (PEN_X < 80) && (PEN_Y > 20 && PEN_Y < 50)   dosomething();
I think this kind of check uses lot a memory, isn't it ? ( my 18F97J60 is almost out of memory, i should not be able to create lot a buttons if go in that way ) :(


By the way, my GLCD library is not rich and hasn't lot a features, i've seen here :
https://www.electro-tech-online.com...n-tutorials-code-and-info.123514/#post1023384
you have shared a ILI9325 TFT Colour LCD Controller library, can you tell me where to get it ?
 
I would like to thank you very much Gobbledok, it works perfectly now.
Good to hear! You're welcome.

Could it be also possible to invert Y+ / Y- pins on the hardware in order to invert the result ?
Yeh I don't see why that wouldn't work. Mine was an all-in-one module so pretty hard to do that.

My next step is to create buttons with my GLCD library, i'm thinking about how to check if a touch is within ('inside') or not ('outside') the area of the button's coordinates ?

Is the best way to proceed to test with 'if' tests ?
ie :
Code:
if (PEN_X > 30) && (PEN_X < 80) && (PEN_Y > 20 && PEN_Y < 50)   dosomething();
I think this kind of check uses lot a memory, isn't it ? ( my 18F97J60 is almost out of memory, i should not be able to create lot a buttons if go in that way ) :(
Yeh that's how I've done it, can't really think of a better way.

By the way, my GLCD library is not rich and hasn't lot a features, i've seen here :
https://www.electro-tech-online.com...n-tutorials-code-and-info.123514/#post1023384
you have shared a ILI9325 TFT Colour LCD Controller library, can you tell me where to get it ?

I haven't actually shared it yet, it's still a work in progress :)

Which controller do you use on your screen? I was under the impression you use a mono-colour screen in which case the ILI9325 driver wouldn't work for you. However I could probably share some line and circle drawing routines or something if you want?

If I remember correctly I pinched the circle drawing routine from here (and possibly the line drawing routine), it was written by Pommie and should be floating around here somewhere.
 
hello, I wanted to know what are the function that work, I tried to follow the changes that were you doing but it did not work properly. I'm using ads7846 that is fully compatible with ads7843 and a pic18f47j53. Thank you very much and sorry for my poor English, I'm using the google translator.
 
Hi your english is fine and easy to understand.

What specifically doesn't work on yours? Have you seen the original one here?

Maybe crocu can post up his completed working result?
 
Status
Not open for further replies.

Latest threads

Back
Top