1 /*********************************************************************
  2     FileName:           Touch.c
  3     Dependencies:       See #includes
  4     Processor:          PIC32MZ
  5     Hardware:           MainBrain MZ
  6     Complier:           XC32 4.40, 4.45
  7     Author:             Larry Knight 2024
  8 
  9     Software License Agreement:
 10         This software is licensed under the Apache License Agreement
 11 
 12     Description:
 13         I2C code for capacitive touch display with FT5436 controller
 14         SCL frequency = 400KHz
 15         Address 0x38 (7-bit) or 0x70 (write) and 0x71 (read) (8-bit)
 16         5 touch points
 17     References:
 18         Understanding the I2C Bus - https://www.ti.com/lit/pdf/slva704 
 19         FocalTech Application Note for FT5426 - 5526 CTPM
 20         https://github.com/crystalfontz/CFAF320480C7-035Tx/blob/main/CFAF320480C7-035Tx/CFAF320480C7-035Tx.ino
 21         https://github.com/Bodmer/Touch_FT5436/blob/main/Touch_FT5436.cpp
 22         https://www.antimatter.me/
 23  
 24     File Description:
 25 
 26     Change History:
 27 
 28 /***********************************************************************/
 29 
 30 #include <xc.h>
 31 #include <p32xxxx.h>
 32 #include <proc/p32mz2048efh100.h>
 33 #include <sys/attribs.h>
 34 #include <sys/kmem.h>
 35 #include <stdint.h> 
 36 #include <stdio.h>
 37 #include <stdlib.h>
 38 #include <string.h>
 39 #include <stdbool.h>
 40 #include "MainBrain.h"
 41 
 42 /* ============================================================
 43  * FT5426 / FT5526 CTPM Register Map
 44  * Working Mode
 45  * ============================================================ */
 46 /* --- Mode / Control --- */
 47 #define FT_REG_MODE          0x00   // Device mode: 000b = WORKING, 100b = TEST (bits 6:4)
 48 #define FT_REG_GEST_ID       0x01   // Gesture ID (RO): 0x10 up, 0x14 right, 0x18 down, 0x1C left, 0x48 zoom in, 0x49 zoom out, 0x00 none
 49 #define FT_REG_TD_STATUS     0x02   // Touch Data status (RO): number of detected points, max 10
 50 
 51 /* --- Touch Point 1 --- */
 52 #define FT_TOUCH1_XH         0x03   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 53 #define FT_TOUCH1_XL         0x04   // X position [7:0]
 54 #define FT_TOUCH1_YH         0x05   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 55 #define FT_TOUCH1_YL         0x06   // Y position [7:0]
 56 #define FT_TOUCH1_WEIGHT     0x07   // Touch pressure value
 57 #define FT_TOUCH1_MISC       0x08   // [7:4]=touch area, [3:0]=reserved
 58 
 59 /* --- Touch Point 2 --- */
 60 #define FT_TOUCH2_XH         0x09   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 61 #define FT_TOUCH2_XL         0x0A   // X position [7:0]
 62 #define FT_TOUCH2_YH         0x0B   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 63 #define FT_TOUCH2_YL         0x0C   // Y position [7:0]
 64 #define FT_TOUCH2_WEIGHT     0x0D   // Touch pressure value
 65 #define FT_TOUCH2_MISC       0x0E   // [7:4]=touch area, [3:0]=reserved
 66 
 67 /* --- Touch Point 3 --- */
 68 #define FT_TOUCH3_XH         0x0F   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 69 #define FT_TOUCH3_XL         0x10   // X position [7:0]
 70 #define FT_TOUCH3_YH         0x11   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 71 #define FT_TOUCH3_YL         0x12   // Y position [7:0]
 72 #define FT_TOUCH3_WEIGHT     0x13   // Touch pressure value
 73 #define FT_TOUCH3_MISC       0x14   // [7:4]=touch area, [3:0]=reserved
 74 
 75 /* --- Touch Point 4 --- */
 76 #define FT_TOUCH4_XH         0x15   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 77 #define FT_TOUCH4_XL         0x16   // X position [7:0]
 78 #define FT_TOUCH4_YH         0x17   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 79 #define FT_TOUCH4_YL         0x18   // Y position [7:0]
 80 #define FT_TOUCH4_WEIGHT     0x19   // Touch pressure value
 81 #define FT_TOUCH4_MISC       0x1A   // [7:4]=touch area, [3:0]=reserved
 82 
 83 /* --- Touch Point 5 --- */
 84 #define FT_TOUCH5_XH         0x1B   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 85 #define FT_TOUCH5_XL         0x1C   // X position [7:0]
 86 #define FT_TOUCH5_YH         0x1D   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 87 #define FT_TOUCH5_YL         0x1E   // Y position [7:0]
 88 #define FT_TOUCH5_WEIGHT     0x1F   // Touch pressure value
 89 #define FT_TOUCH5_MISC       0x20   // [7:4]=touch area, [3:0]=reserved
 90 
 91 /* --- Touch Point 6 --- */
 92 #define FT_TOUCH6_XH         0x21   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
 93 #define FT_TOUCH6_XL         0x22   // X position [7:0]
 94 #define FT_TOUCH6_YH         0x23   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
 95 #define FT_TOUCH6_YL         0x24   // Y position [7:0]
 96 #define FT_TOUCH6_WEIGHT     0x25   // Touch pressure value
 97 #define FT_TOUCH6_MISC       0x26   // [7:4]=touch area, [3:0]=reserved
 98 
 99 /* --- Touch Point 7 --- */
100 #define FT_TOUCH7_XH         0x27   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
101 #define FT_TOUCH7_XL         0x28   // X position [7:0]
102 #define FT_TOUCH7_YH         0x29   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
103 #define FT_TOUCH7_YL         0x2A   // Y position [7:0]
104 #define FT_TOUCH7_WEIGHT     0x2B   // Touch pressure value
105 #define FT_TOUCH7_MISC       0x2C   // [7:4]=touch area, [3:0]=reserved
106 
107 /* --- Touch Point 8 --- */
108 #define FT_TOUCH8_XH         0x2D   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
109 #define FT_TOUCH8_XL         0x2E   // X position [7:0]
110 #define FT_TOUCH8_YH         0x2F   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
111 #define FT_TOUCH8_YL         0x30   // Y position [7:0]
112 #define FT_TOUCH8_WEIGHT     0x31   // Touch pressure value
113 #define FT_TOUCH8_MISC       0x32   // [7:4]=touch area, [3:0]=reserved
114 
115 /* --- Touch Point 9 --- */
116 #define FT_TOUCH9_XH         0x33   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
117 #define FT_TOUCH9_XL         0x34   // X position [7:0]
118 #define FT_TOUCH9_YH         0x35   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
119 #define FT_TOUCH9_YL         0x36   // Y position [7:0]
120 #define FT_TOUCH9_WEIGHT     0x37   // Touch pressure value
121 #define FT_TOUCH9_MISC       0x38   // [7:4]=touch area, [3:0]=reserved
122 
123 /* --- Touch Point 10 --- */
124 #define FT_TOUCH10_XH        0x39   // [7:6]=event flag, [5:4]=reserved, [3:0]=X pos [11:8]
125 #define FT_TOUCH10_XL        0x3A   // X position [7:0]
126 #define FT_TOUCH10_YH        0x3B   // [7:4]=touch ID (0x0F=invalid), [3:0]=Y pos [11:8]
127 #define FT_TOUCH10_YL        0x3C   // Y position [7:0]
128 #define FT_TOUCH10_WEIGHT    0x3D   // Touch pressure value
129 #define FT_TOUCH10_MISC      0x3E   // [7:4]=touch area, [3:0]=reserved
130 
131 
132 /* ============================================================
133  * Field values / bit definitions
134  * ============================================================ */
135 /* DEVICE_MODE (0x00) bits [6:4] */
136 #define FT_MODE_WORKING      0x00   // 000b working mode
137 #define FT_MODE_TEST         0x40   // 100b test mode
138 
139 /* Event flag (XH bits [7:6]) */
140 #define FT_EVENT_DOWN        0x00   // 00b press down
141 #define FT_EVENT_UP          0x40   // 01b lift up
142 #define FT_EVENT_CONTACT     0x80   // 10b contact
143 #define FT_EVENT_NONE        0xC0   // 11b no event
144 
145 //Register addresses
146 #define FT_REG_MODE 0x00                //Device mode, either WORKING or FACTORY
147 #define FT_REG_NUMTOUCHES 0x02          //Number of touch points
148 #define FT_REG_CALIBRATE 0x02           //Calibrate mode
149 #define FT_TP1_REG (0X03)
150 #define FT_TP2_REG (0X09)
151 #define FT_REG_FACTORYMODE 0x40         //Factory mode
152 #define FT_REG_THRESHOLD 0x80          //Threshold for touch detection
153 #define FT_ID_G_CTRL 0x86               //Power control mode
154 #define FT_REG_POINTRATE 0x88           //Point rate
155 #define FT_ID_G_LIB_VERSION (0xA1)
156 #define FT_REG_FIRMVERS 0xA6            //Firmware version
157 #define FT_REG_CHIPID 0xA3              //Chip selecting
158 #define FT_ID_G_MODE (0xA4)
159 #define FT_REG_VENDID 0xA8              //FocalTech's panel ID 
160 #define NVM_ADDR_DATA_WR (0xD0)
161 
162 //FocalTech ID's
163 #define FT6234_VENVID 0x79  // FocalTech's panel ID
164 #define FT6236_VENDID 0x11  // FocalTech's panel ID
165 #define FT5436_VENDID 0x79  // FocalTech's panel ID
166 #define FT6206_CHIPID 0x06  // FT6206 ID
167 #define FT6234_CHIPID 0x54  // FT6234 ID
168 #define FT6236_CHIPID 0x36  // FT6236 ID
169 #define FT5436_CHIPID 0x54  // FT5436 ID
170 #define FT6236U_CHIPID 0x64 // FT6236U ID
171 
172 uint8_t Event_Flag_1;
173 uint8_t Touch_ID_1;
174 uint8_t Touch_Area_1;
175 uint8_t Touch_Weight_1;
176 uint8_t address;
177 uint8_t reg_data_buf;
178 uint8_t read_buf[180];
179 int wait_time = 10000;
180 uint16_t scn_pos_x;
181 
182 uint16_t scn_pos_y;
183 
184 uint8_t MenuLevel = 0;
185 uint8_t ButtonNum = 0;
186 bool ExitButton = false;
187 bool isActive = false;
188 
189 uint8_t FT5436_Write_Reg(uint8_t reg, uint8_t reg_data);
190 void FT5436_Read_Reg(uint8_t reg);
191 void FT5436_Read(uint8_t num_bytes);
192 void I2C_wait_for_idle(void);
193 void I2C_start(void);
194 void I2C_stop(void);
195 void I2C_restart(void);
196 void I2C_ack(void);
197 void I2C_nack(void);
198 
199 
200 bool I2C_init()
201 {    
202     //FT5436 Device Address
203     address = 0x38;
204     
205     //Touch Controller Reset
206     TRISBbits.TRISB13 = 0;
207     PORTBbits.RB13 = 1;
208     
209     //INT pin 
210     TRISDbits.TRISD0 = 1;
211     //PORTDbits.RD0 = 1;
212     
213     //RA2 - Pin 59 - SCL2
214     TRISAbits.TRISA2 = 1;
215     
216     //RA3 - Pin 60 - SDA2
217     TRISAbits.TRISA3 = 1;
218      
219     //Disable Slew Rate Control bit
220     //I2C2CONbits.DISSLW = 1;
221     
222     //BAUD rate - 400KHz
223     //set with the scope where one clock period is 2.5uS (400KHz)
224     I2C2BRG = 0x0069; 
225     
226     //I2C-2 Interrupt
227     IFS0bits.IC2IF = 0; 
228     IEC0bits.IC2IE = 1;
229     
230     //Master
231     IPC37bits.I2C2MIP = 4;
232     IPC37bits.I2C2MIS = 3;
233     
234     IFS4bits.I2C2MIF = 0;
235     IEC4bits.I2C2MIE = 0;
236     
237     //Slave
238     IPC37bits.I2C2SIP = 4;
239     IPC37bits.I2C2SIS = 2;
240     
241     IEC4bits.I2C2SIE = 0;
242     IFS4bits.I2C2SIF = 0;
243             
244     //INT0 
245     IPC0bits.INT0IP = 4;
246     IPC0bits.INT0IS = 1;
247     
248     IFS0bits.INT0IF = 0;
249     IEC0bits.INT0IE = 1;
250     
251     
252     //SDA Hold Time 0 = 100nS, 1 = 300nS
253     I2C2CONbits.SDAHT = 0;
254     
255     I2C2CONbits.PCIE = 1;
256 
257     //Enable module
258     I2C2CONbits.ON = 1;
259     
260     //RESET Touch Controller
261     //Should be low for 10mS
262     for(int i=0;i<1000000;i++)
263     {
264         PORTBbits.RB13 = 0;
265     }
266    
267     PORTBbits.RB13 = 1;
268     
269     for(int i=0;i<1000000;i++);
270     
271     // Initial settings
272     FT5436_Write_Reg(FT_REG_THRESHOLD, 20);         // THRESHOLD (actual = 4x value)
273     FT5436_Write_Reg(FT_REG_POINTRATE, 12);         // POINTRATE (range 3-14, default 6)
274     FT5436_Write_Reg(FT_ID_G_CTRL, 0x01);           // ID_G_CTRL — disable auto-jump to monitor
275     FT5436_Write_Reg(FT_ID_G_MODE, 0x01);           // ID_G_MODE — INT enabled (default is on)
276 
277     //Prove presence by reading the vendor ID which must be 0x79
278     FT5436_Read_Reg(FT_REG_VENDID);
279     if(reg_data_buf != 0x79)
280     {
281         return false;
282     }
283     
284     return true;
285 }
286 
287 //INT0 Interrupt handler
288 void __attribute__((vector(_EXTERNAL_0_VECTOR), interrupt(ipl4srs), nomips16)) INT0_Handler()
289 {    
290     //Reads specified number of registers into an array 
291     FT5436_Read(180);
292     
293     //This is for 90 degree screen rotation
294     //process touch data
295     //first get the event flag 
296     //0-Press Down 1-Lift Up 2-Contact 3-No event / reserved
297     Event_Flag_1 = (read_buf[3] & 0xC0) >> 6;
298     
299     //Now get the touch ID
300     Touch_ID_1 = (read_buf[5] & 0xf0) >> 4;
301     
302     //Get the touch area
303     Touch_Area_1 = read_buf[8] >> 4;
304     
305     //Get the touch weight 
306     Touch_Weight_1 = read_buf[8];
307     
308     scn_pos_x = read_buf[5] & 0x0f;
309     scn_pos_x = scn_pos_x << 8;
310     scn_pos_x = scn_pos_x + read_buf[6];
311     
312     if (scn_pos_x > 480)
313     {
314         scn_pos_x = 480;
315     }
316 
317     scn_pos_y = read_buf[3] & 0x0f;
318     scn_pos_y = scn_pos_y << 8;
319     scn_pos_y = scn_pos_y + read_buf[4];
320 
321     if(scn_pos_y > 320)
322     {
323         scn_pos_y = 320;
324     }
325 
326     scn_pos_y = 320 - scn_pos_y;        
327     
328     IFS0bits.INT0IF = 0;
329 }
330 
331 bool Device_Present(void)
332 {
333     int i;
334     //******************************************************
335     //Now we have to determine if there is a device present
336     //The display is optional and should not be required
337     //******************************************************
338     I2C_start();
339     
340     //write to slave
341     I2C2TRN = 0x70;                         // Send slave address with Read/Write bit cleared
342     while (I2C2STATbits.TBF == 1);          // Wait until transmit buffer is empty
343     I2C_wait_for_idle();                    // Wait until I2C bus is idle
344 
345     //wait a finite amount of time then RETURN if not acknowledged by device
346     for(i=0;i<wait_time;i++)
347     {
348         if(I2C2STATbits.ACKSTAT == 0)
349         {
350             return true;
351             i = wait_time;           
352         }
353     }
354     if(I2C2STATbits.ACKSTAT == 1)
355     {
356         return false;
357     }   
358     //******************************************************
359 }
360 
361 //Writes a byte to the specified register
362 uint8_t FT5436_Write_Reg(uint8_t reg, uint8_t reg_data)
363 {
364     I2C_start();
365     while (I2C2CONbits.SEN);
366 
367     I2C2TRN = 0x70;
368     while (I2C2STATbits.TRSTAT);
369     if (I2C2STATbits.ACKSTAT)
370     {
371         I2C_stop();
372         return 1;   // NACK on address
373     }
374 
375     I2C2TRN = reg;
376     while (I2C2STATbits.TRSTAT);
377     if (I2C2STATbits.ACKSTAT)
378     {
379         I2C_stop();
380         return 2;   // NACK on register
381     }
382 
383     I2C2TRN = reg_data;
384     while (I2C2STATbits.TRSTAT);
385     if (I2C2STATbits.ACKSTAT)
386     {
387         I2C_stop();
388         return 3;   // NACK on data
389     }
390 
391     I2C_stop();
392     
393     return 0;
394 }
395 
396 void FT5436_Read_Reg(uint8_t reg)
397 {
398     I2C_start();
399 
400     I2C2TRN = 0x70;
401     while (I2C2STATbits.TBF == 1);
402     I2C_wait_for_idle();
403     while (I2C2STATbits.ACKSTAT == 1);
404 
405     I2C2TRN = reg;
406     while (I2C2STATbits.TBF == 1);
407     I2C_wait_for_idle();
408     while (I2C2STATbits.ACKSTAT == 1);
409 
410     I2C_restart();
411 
412     I2C2TRN = 0x71;
413     while (I2C2STATbits.TBF == 1);
414     I2C_wait_for_idle();
415     while (I2C2STATbits.ACKSTAT == 1);
416     
417     // ACK the first byte
418     I2C2CONbits.RCEN = 1;
419     while (I2C2CONbits.RCEN);
420     while (!I2C2STATbits.RBF);
421     reg_data_buf = I2C2RCV;
422     I2C_ack();          // <-- THIS is what you were missing
423 
424     // read one extra, NACK it (same as your working function)
425     I2C2CONbits.RCEN = 1;
426     while (I2C2CONbits.RCEN);
427     while (!I2C2STATbits.RBF);
428     (void)I2C2RCV;
429     
430     I2C_nack();
431     I2C_stop();
432 }
433 
434 //Reads [num_bytes] bytes from the device
435 void FT5436_Read(uint8_t num_bytes)
436 {
437     int i;
438     
439     //read at least 1 byte
440     if(!num_bytes)
441     {
442         num_bytes = 1;
443     }
444     
445     //Send start condition
446     I2C_start();
447     
448     //write to slave
449     I2C2TRN = 0x70;                         // Send slave address with Read/Write bit cleared
450     while (I2C2STATbits.TBF == 1);          // Wait until transmit buffer is empty
451     I2C_wait_for_idle();                    // Wait until I2C bus is idle
452     while (I2C2STATbits.ACKSTAT == 1);      // Wait until ACK is received  
453 
454     I2C2TRN = 0x0;                            // Device mode
455     while (I2C2STATbits.TBF == 1);          // Wait until transmit buffer is empty
456     I2C_wait_for_idle();                    // Wait until I2C bus is idle
457     while (I2C2STATbits.ACKSTAT == 1);      // Wait until ACK is received
458     
459     I2C_restart();
460     
461     //Read from slave
462     I2C2TRN = 0x71;                         // Send slave address with Read/Write bit set
463     while (I2C2STATbits.TBF == 1);          // Wait until transmit buffer is empty
464     I2C_wait_for_idle();                    // Wait until I2C bus is idle
465     while (I2C2STATbits.ACKSTAT == 1);      // Wait until ACK is received  
466 
467     for(i=0;i<num_bytes;i++)
468     {
469         I2C2CONbits.RCEN = 1;                   // Receive enable
470         while (I2C2CONbits.RCEN);               // Wait until RCEN is cleared (automatic)  
471         while (!I2C2STATbits.RBF);              // Wait until Receive Buffer is Full (RBF flag)  
472         read_buf[i] = I2C2RCV;                 // Retrieve value from I2C2RCV
473         I2C_ack();
474     }
475     
476     I2C2CONbits.RCEN = 1;                   // Receive enable
477     while (I2C2CONbits.RCEN);               // Wait until RCEN is cleared (automatic)  
478     while (!I2C2STATbits.RBF);              // Wait until Receive Buffer is Full (RBF flag)  
479     read_buf[num_bytes] = I2C2RCV;                 // Retrieve value from I2C2RCV
480     
481     I2C_nack();
482     I2C_stop(); 
483 }
484 
485 //DRIVER FOUNDATION 
486 //Waits until the I2C peripheral is no longer doing anything  
487 void I2C_wait_for_idle(void)
488 {
489     while(I2C2CON & 0x1F);      // Acknowledge sequence not in progress
490                                 // Receive sequence not in progress
491                                 // Stop condition not in progress
492                                 // Repeated Start condition not in progress
493                                 // Start condition not in progress
494     while(I2C2STATbits.TRSTAT); // Bit = 0 Master transmit is not in progress
495 }
496 
497 //Sends a start condition  
498 void I2C_start(void)
499 {
500     I2C_wait_for_idle();
501     I2C2CONbits.SEN = 1;
502     while (I2C2CONbits.SEN == 1);
503 }
504 
505 //Sends a stop condition  
506 void I2C_stop(void)
507 {
508     I2C_wait_for_idle();
509     I2C2CONbits.PEN = 1;
510     while (I2C2CONbits.PEN == 1);   // <-- wait for stop to complete
511 }
512 
513 //Sends a repeated start/restart condition
514 void I2C_restart(void)
515 {
516     I2C_wait_for_idle();
517     I2C2CONbits.RSEN = 1;
518     while (I2C2CONbits.RSEN == 1);
519 }
520 
521 //Sends an ACK condition
522 void I2C_ack(void)
523 {
524     I2C_wait_for_idle();
525     I2C2CONbits.ACKDT = 0; // Set hardware to send ACK bit
526     I2C2CONbits.ACKEN = 1; // Send ACK bit, will be automatically cleared by hardware when sent  
527     while(I2C2CONbits.ACKEN); // Wait until ACKEN bit is cleared, meaning ACK bit has been sent
528 }
529 
530 //Sends a NACK condition
531 void I2C_nack(void) // Acknowledge Data bit
532 {
533     I2C_wait_for_idle();
534     I2C2CONbits.ACKDT = 1; // Set hardware to send NACK bit
535     I2C2CONbits.ACKEN = 1; // Send NACK bit, will be automatically cleared by hardware when sent  
536     while(I2C2CONbits.ACKEN); // Wait until ACKEN bit is cleared, meaning NACK bit has been sent
537 }
538 
539 //Master Interrupt Handler
540 void __attribute__((vector(_I2C1_MASTER_VECTOR), interrupt(ipl4srs), nomips16)) I2C_Master_Handler()
541 {
542 
543     IFS4bits.I2C2MIF = 0;
544 }
545 
546 //Slave Interrupt Handler
547 void __attribute__((vector(_I2C2_SLAVE_VECTOR), interrupt(ipl4srs), nomips16)) I2C_Slave_Handler()
548 {
549     
550     IFS0bits.IC2IF = 0;
551 }