19.4 Application Example

In CVD Scan of All CVDANx Inputs, the ITC is initialized to perform CVD scans of all CVDANx pins. For each scan, a new CVDTXx pin is selected by DMA.

CVD Scan of All CVDANx Inputs

#include <xc.h>

// All pins CVD results.
// 32 CVD pins scans for 32 different CVDTXx pins settings.
long result[32][32]; 

long* pointer; // Used to store the results.
long cvd_counter; // CVD scans counter.
long tx_counter; // TX settings counter.


// OPTIONAL
// CVDTXx pins selections for each CVD scan.
// Moved by DMA after each scan to ITCTXA register.
unsigned long cvd_tx_pins[32] = {

0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 
0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000,
0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000,
0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1

};


int main(){

 // Initialize Oscillators

    // PLL1 initialization
    PLL1CONbits.ON = 1;
    OSCCTRLbits.PLL1EN = 1;
    while(OSCCTRLbits.PLL1RDY == 0);
    PLL1CONbits.FSCMEN = 1; // disable clock fail monitor
    
    VCO1DIVbits.INTDIV = 1; // 1:2 = 320MHz
    
    PLL1DIVbits.PLLFBDIV = 80; // VCO = 640 MHz
    PLL1DIVbits.PLLPRE = 1;
    PLL1DIVbits.POSTDIV1 = 4;
    PLL1DIVbits.POSTDIV2 = 1;

    PLL1CONbits.DIVSWEN = 1;
    while(PLL1CONbits.DIVSWEN == 1);    
    
    PLL1CONbits.NOSC = 1; // FRC
    PLL1CONbits.OSWEN = 1;
    while(PLL1CONbits.OSWEN == 1);        

    PLL1CONbits.FOUTSWEN = 1;
    while(PLL1CONbits.FOUTSWEN == 1);
    PLL1CONbits.PLLSWEN = 1;
    while(PLL1CONbits.PLLSWEN == 1);
  
    while(PLL1CONbits.CLKRDY == 0);
  
    // clock CPU from PLL
    CLK1CONbits.NOSC = 5; // PLL1
    CLK1CONbits.OSWEN = 1;
    while(CLK1CONbits.OSWEN == 1); 
    while(CLK1CONbits.CLKRDY == 0);
      
    // ADC high speed clock (Generator 6), should be 320 MHz for 80MHz operation
    CLK6CONbits.ON = 1;
    CLK6CONbits.NOSC = 7; // PLL1 VCO divider
    CLK6CONbits.OSWEN = 1;
    while(CLK6CONbits.OSWEN == 1); 
    while(CLK6CONbits.CLKRDY == 0); 

    // OPTIONAL
    // Initialize DMA channel to update CVDTXx pins by
    // ITC interrupt after each scan
    // (optional, may be used for 2D CVD).
    DMALOW = 0; // any address
    DMAHIGH = -1UL; // any address
    DMA0CHbits.SIZE = 2; // 32 bits
    DMA0CHbits.TRMODE = 1; // repeated one shot
    DMA0CHbits.DAMODE = 0; // not incremented
    DMA0CHbits.SAMODE = 1; // take next data each transfer
    DMA0CHbits.RELOADC = 1; // reload counter
    DMA0CHbits.RELOADS = 1; // reload source
    DMA0CHbits.CHEN = 1; // enable channel
    DMA0SELbits.CHSEL = 106; // trigger DMA from ITC list 0
    DMA0SRC = (unsigned long)&ITCTXA; // update pins in ITCTXA register 
    DMA0DST = (unsigned long)&cvd_tx_pins[0];
    DMA0CNT = 32; // 32 CVDTXx pins updates before rollover
    DMACONbits.ON = 1; // enable DMA    

    ITCLS0CONbits.DMAEN = 1; // Enable DMA triggers from List 0
   
    ITCTXA = 0x1; // start from CVDTX0 pin

    // Initialize ADC5 for ITC clock and conversions  
    AD5CH5CON1bits.MODE = 0; // single conversion
    AD5CH5CON1bits.IRQSEL = 0; // each conversion
    AD5CH5CON1bits.PINSEL = 5; // AN5
    AD5CH5CON1bits.NINSEL = 0; // VSS
    AD5CH5CON1bits.SAMC = 0; // small sampling time
    AD5CH5CON1bits.TRG1SRC = 26; // trigger for Touch Controller
    AD5CONbits.ON = 1; // enable ADC5
    while(AD5CONbits.ADRDY == 0); 

    // Use all 16 acquisition commands for one sequence
    SDATAMAPbits.SPLIT0 = 0;
    SDATAMAPbits.SPLIT1 = 0;
    SDATAMAPbits.SPLIT2 = 0;
    SDATAMAPbits.SPLIT3 = 0;

    // List 0 will be processed by sequence number 5
    ITCLS0SEQbits.DATASEQ = 5;
    // Assign sequence to number 5 to be processed by list 0
    SDATAMAPbits.DATASEQ0 = 5;
    SDATAMAPbits.DATASEQ1 = 5;
    SDATAMAPbits.DATASEQ2 = 5;
    SDATAMAPbits.DATASEQ3 = 5;

    // Split 16 math commands in 2 sequences
    SMATHMAPbits.SPLIT0 = 2;
    SMATHMAPbits.SPLIT1 = 2;
    SMATHMAPbits.SPLIT2 = 2;
    SMATHMAPbits.SPLIT3 = 2;

    // List 0 will be processed by two math sequences number 5
    ITCLS0SEQbits.MATHSEQ = 5;
    // List 0 will accumulate result.
    // Each sequence will be executed 4 times per record
    ITCLS0SEQbits.ACCEN = 1;
    ITCLS0SEQbits.ACCCNT = 2;

    // First 8 steps sequence called when
    // SECOND0 bit = 0 in SnMATHCMDx register
    // The sequence will be executed several times per record
    // (accumulation mode)
    SMATHMAPbits.MATHSEQ0 = 5;
    SMATHMAPbits.MATHSEQ1 = 5;
    SMATHMAPbits.SECOND0 = 0;
    SMATHMAPbits.SECOND1 = 0;
    SMATHMAPbits.ACC0 = 1;
    SMATHMAPbits.ACC1 = 1;

    // Second 8 steps sequence called when
    // SECOND bit = 1 in SnMATHCMDx register 
    // The sequence will be executed several times per record
    // (accumulation mode)
    SMATHMAPbits.MATHSEQ2 = 5;
    SMATHMAPbits.MATHSEQ3 = 5;
    SMATHMAPbits.SECOND2 = 1;
    SMATHMAPbits.SECOND3 = 1;
    SMATHMAPbits.ACC2 = 1;
    SMATHMAPbits.ACC3 = 1;

    
    // CVD ACQUISITION SEQUENCE
    // Command 0
    SDATACMD0bits.CHRG = 1; // charge CVD cpasitor
    SDATACMD0bits.PC0 = 1; // drive 0 to discharge sensor on CVDANx pin
    SDATACMD0bits.PCA = 1; // drive 0 on pins selected in ITCTXA register
    SDATACMD0bits.PCB = 2; // drive 1 on pins selected in ITCTXB register
    SDATACMD0bits.LOOP = 1; // wait for timer A in ITCLSxTMR register
    // Command 1
    // break before make, disconnect everything
    SDATACMD1bits.PC0 = 3; // tri-state CVDANx pin
    SDATACMD1bits.PCA = 1; // drive 0 on pins selected in ITCTXA register
    SDATACMD1bits.PCB = 2; // drive 1 on pins selected in ITCTXB register
    // Command 2
    SDATACMD2bits.BAL = 1; // connect CVD capacitor to CVDANx pin (balance)
    SDATACMD2bits.PC0 = 3; // tri-state CVDANx pin
    SDATACMD2bits.PCA = 1; // drive 0 on pins selected in ITCTXA register
    SDATACMD2bits.PCB = 2; // drive 1 on pins selected in ITCTXB register
    SDATACMD2bits.LOOP = 2; // wait for timer B in ITCLSxTRM register
    // Command 3
    SDATACMD3bits.CONV = 1; // start conversion
    SDATACMD3bits.LOOP = 4; // wait for end of conversion 

    SDATACMD3bits.PC0 = 3; // tri-state CVDANx pin
    SDATACMD3bits.PCA = 1; // drive 0 on pins selected in ITCTXA register
    SDATACMD3bits.PCB = 2; // drive 1 on pins selected in ITCTXB register
    SDATACMD3bits.MSTART = 1; // start the first math sequence
    // Command 4
    SDATACMD4bits.DISCHRG = 1; // discharge CVD capacitor
    SDATACMD4bits.PC0 = 2; // drive 1 to charge sensor on CVDANx pin
    SDATACMD4bits.PCA = 2; // drive 1 on pins selected in ITCTXA register
    SDATACMD4bits.PCB = 1; // drive 0 on pins selected in ITCTXB register
    SDATACMD4bits.LOOP = 1; // wait for timer A in ITCLSxTMR register
    // Command 5
    // break before make, disconnect everything
    SDATACMD5bits.PC0 = 3; // tri-state
    SDATACMD5bits.PCA = 2; // drive 1 on pins selected in ITCTXA register
    SDATACMD5bits.PCB = 1; // drive 0 on pins selected in ITCTXB register
    // Command 6
    SDATACMD6bits.BAL = 1; // connect CVD capacitor to CVDANx pin (balance)
    SDATACMD6bits.PC0 = 3; // tri-state CVDANx pin
    SDATACMD6bits.PCA = 2; // drive 1 on pins selected in ITCTXA register
    SDATACMD6bits.PCB = 1; // drive 0 on pins selected in ITCTXB register
    SDATACMD6bits.LOOP = 2; // wait for timer B in ITCLSxTRM register
    // Command 7
    SDATACMD7bits.CONV = 1; // start conversion
    SDATACMD7bits.LOOP = 4; // wait for end of conversion 
    SDATACMD7bits.PC0 = 3; // tri-state CVDANx pin
    SDATACMD7bits.PCA = 2; // drive 1 on pins selected in ITCTXA register
    SDATACMD7bits.PCB = 1; // drive 0 on pins selected in ITCTXB register
    SDATACMD7bits.MSTART = 1; // start the first math sequence
    SDATACMD7bits.SECOND = 1; // second math sequence
    SDATACMD7bits.END = 1; // last command, end of the sequence
    
    // CVD MATH SEQUENCES
    // MATH "-"/Sample B
    SMATHCMD0bits.AIN = 3; // ADC result
    SMATHCMD0bits.BIN = 1; // Accumulator B
    SMATHCMD0bits.F = 3; // "-"
    SMATHCMD0bits.ACCB = 1; // latch result in Accumulator B
    SMATHCMD0bits.WM = 2; // never write record
    SMATHCMD0bits.WMOV = 1; // overwrite WM bits in ITCLSxCON register
    SMATHCMD0bits.END = 1; // last command, end of sequence
    // MATH "+"/Sample A
    SMATHCMD8bits.AIN = 3; // ADC result
    SMATHCMD8bits.BIN = 1; // Accumulator B
    SMATHCMD8bits.F = 2; // "+"
    SMATHCMD8bits.ACCB = 1; // latch result in Accumulator B
    SMATHCMD8bits.WM = 0; // always write to ITCRESx register
    SMATHCMD8bits.WMOV = 1; // overwrite WM bits in ITCLSxCON register
    SMATHCMD8bits.END = 1; // last command, end of sequence
    
    // Set CVD capacitor to 10pF 
    ITCCON1bits.CVDEN = 1;
    ITCLS0SEQbits.CVDCAP = 8;
                
    // Assign CVDANx pins to the records 
    ITCREC0bits.PIN0 = 0; // CVDAN0 pin
    ITCREC0bits.PIN1 = 1;
    ITCREC1bits.PIN2 = 2;
    ITCREC1bits.PIN3 = 3;
    ITCREC2bits.PIN4 = 4;
    ITCREC2bits.PIN5 = 5;
    ITCREC3bits.PIN6 = 6;
    ITCREC3bits.PIN7 = 7;
    ITCREC4bits.PIN8 = 8;
    ITCREC4bits.PIN9 = 9;
    ITCREC5bits.PIN10 = 10;
    ITCREC5bits.PIN11 = 11;
    ITCREC6bits.PIN12 = 12;
    ITCREC6bits.PIN13 = 13;
    ITCREC7bits.PIN14 = 14;
    ITCREC7bits.PIN15 = 15;
    ITCREC8bits.PIN16 = 16;
    ITCREC8bits.PIN17 = 17;
    ITCREC9bits.PIN18 = 18;
    ITCREC9bits.PIN19 = 19;
    ITCREC10bits.PIN20 = 20;
    ITCREC10bits.PIN21 = 21;
    ITCREC11bits.PIN22 = 22;
    ITCREC11bits.PIN23 = 23;
    ITCREC12bits.PIN24 = 24;
    ITCREC12bits.PIN25 = 25;
    ITCREC13bits.PIN26 = 26;
    ITCREC13bits.PIN27 = 27;
    ITCREC14bits.PIN28 = 28;
    ITCREC14bits.PIN29 = 29;
    ITCREC15bits.PIN30 = 30;
    ITCREC15bits.PIN31 = 31; // CVDAN31 pin

    // All CVDANx pins should drive low when idle
    _TRISA0 = 0; _LATA0 = 0; // RA0/CVDAN0
    _TRISA1 = 0; _LATA1 = 0; // RA1/CVDAN1
    _TRISA2 = 0; _LATA2 = 0; // RA2/CVDAN2
    _TRISA3 = 0; _LATA3 = 0; // RA3/CVDAN3
    _TRISA4 = 0; _LATA4 = 0; // RA4/CVDAN4
    _TRISA5 = 0; _LATA5 = 0; // RA5/CVDAN5    
    _TRISA6 = 0; _LATA6 = 0; // RA6/CVDAN6
    _TRISA7 = 0; _LATA7 = 0; // RA7/CVDAN7
    _TRISA8 = 0; _LATA8 = 0; // RA8/CVDAN8
    _TRISA9 = 0; _LATA9 = 0; // RA9/CVDAN9
    _TRISA10 = 0; _LATA10 = 0; // RA10/CVDAN10    
    _TRISA11 = 0; _LATA11 = 0; // RA11/CVDAN11
    _TRISA12 = 0; _LATA12 = 0; // RA12/CVDAN12
    _TRISA13 = 0; _LATA13 = 0; // RA13/CVDAN13
    _TRISA14 = 0; _LATA14 = 0; // RA14/CVDAN14
    _TRISA15 = 0; _LATA15 = 0; // RA15/CVDAN15    
    _TRISB0 = 0; _LATB0 = 0; // RB0/CVDAN16
    _TRISB1 = 0; _LATB1 = 0; // RB1/CVDAN17
    _TRISB2 = 0; _LATB2 = 0; // RB2/CVDAN18
    _TRISB3 = 0; _LATB3 = 0; // RB3/CVDAN19
    _TRISB4 = 0; _LATB4 = 0; // RB4/CVDAN20
    _TRISB5 = 0; _LATB5 = 0; // RB5/CVDAN21
    _TRISB6 = 0; _LATB6 = 0; // RB6/CVDAN22
    _TRISB7 = 0; _LATB7 = 0; // RB7/CVDAN23
    _TRISB8 = 0; _LATB8 = 0; // RB8/CVDAN24
    _TRISB9 = 0; _LATB9 = 0; // RB9/CVDAN25
    _TRISB10 = 0; _LATB10 = 0; // RB10/CVDAN26
    _TRISB11 = 0; _LATB11 = 0; // RB11/CVDAN27
    _TRISB12 = 0; _LATB12 = 0; // RB12/CVDAN28
    _TRISB13 = 0; _LATB13 = 0; // RB13/CVDAN29
    _TRISB14 = 0; _LATB14 = 0; // RB14/CVDAN30
    _TRISB15 = 0; _LATB15 = 0; // RB15/CVDAN31
 
    // Set timers for the acquisition sequences (A and B are used only)
    ITCLS0TMRbits.TMRA = 16; // charge/discharge
    ITCLS0TMRbits.TMRB = 32; // balance   
    
    // One trigger scans all records.
    // One interrupt is generated after scan
    ITCLS0CONbits.MODE = 5; 
    ITCLS0CONbits.WM = 0; // always write to ITCRESx registers
    ITCLS0CONbits.SSRC = 0; // trigger on 1 to 0 transition of SAMP bit
    ITCLS0CONbits.RECCNT = 31; // 32 records are in list 0
    ITCLS0CONbits.TRGEN = 1; // trigger enable

    ITCCON1bits.SIGN = 1; // signed format is required for CVD
    ITCCON1bits.ON = 1; // enable ITC
    ITCLS0CONbits.SAMP = 1; // arm to trigger
    asm volatile(“repeat #128 \n nop”); // at least TAD delay

    while(1){ // scan in infinite loop
        
        for(tx_counter=0; tx_counter<32; tx_counter++){
            _ITCIF = 0; // clear ITC interrupt flag 
            ITCLS0CONbits.SAMP = 0; // trigger scan
            while(_ITCIF == 0); // wait for the scan is done
            ITCLS0CONbits.SAMP = 1; // arm for the next scan
            pointer = (long*)&ITCRES0; 
            // store the results
            for(cvd_counter=0; cvd_counter<32; cvd_counter++){
                result[tx_counter][cvd_counter] = *pointer++;
            }
        }
    }


    return 1;
}