imx6ul TSC (4 wire resistive touch screen ) configuration

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx6ul TSC (4 wire resistive touch screen ) configuration

272 Views
ryan_chen
Contributor II

 Now  i am using a chip imx6ull and run the platform without OS, i tried to config  the module TSC following the code "imx6ull_tsc.c" ,  BUT:

    a)  i always got zero when reading register TSC->INT_STATUS.

    b)  i measured the TSC pin by oscilloscope,there only a level change form 0 to 3.3 when i touch the panel 

So, i  doubt maybe something wrong ,Can anybody please review my following code to see what was  the problem ? or does anyone have the sample code(no os code ) to let it work properly ?

by the way, the other modules ,such as UART\GPIO \DDR works properly now.

 

Any help from you will be greatly  apprecitated !

 

 

/*!
 * @}
 */ /* end of group ADC_Register_Masks */


/* ADC - Peripheral instance base addresses */
/** Peripheral ADC1 base address */
#define ADC1_BASE                                (0x2198000u)
/** Peripheral ADC1 base pointer */
#define ADC1                                     ((ADC_Type *)ADC1_BASE)
/** Array initializer of ADC peripheral base addresses */
#define ADC_BASE_ADDRS                           { 0u, ADC1_BASE }
/** Array initializer of ADC peripheral base pointers */
#define ADC_BASE_PTRS                            { (ADC_Type *)0u, ADC1 }
/** Interrupt vectors for the ADC peripheral type */
#define ADC_IRQS                                 { NotAvail_IRQn, ADC1_IRQn }

/*!
 * @}
 */ /* end of group ADC_Peripheral_Access_Layer */



/*!
 * @}
 */ /* end of group TSC_Register_Masks */


/* TSC - Peripheral instance base addresses */
/** Peripheral TSC base address */
#define TSC_BASE                                 (0x2040000u)
/** Peripheral TSC base pointer */
#define TSC                                      ((TSC_Type *)TSC_BASE)
/** Array initializer of TSC peripheral base addresses */
#define TSC_BASE_ADDRS                           { TSC_BASE }
/** Array initializer of TSC peripheral base pointers */
#define TSC_BASE_PTRS                            { TSC }
/** Interrupt vectors for the TSC peripheral type */
#define TSC_IRQS                                 { TSC_IRQn }

/*!
 * @}
 */ /* end of group TSC_Peripheral_Access_Layer */



/* ADC configuration registers field define */
#define ADC_AIEN		(0x1 << 7)
#define ADC_CONV_DISABLE	0x1F
#define ADC_CAL			(0x1 << 7)
#define ADC_CALF		0x2
#define ADC_12BIT_MODE		(0x2 << 2)
#define ADC_IPG_CLK		0x00
#define ADC_CLK_DIV_8		(0x03 << 5)
#define ADC_SHORT_SAMPLE_MODE	(0x0 << 4)
#define ADC_HARDWARE_TRIGGER	(0x1 << 13)
#define SELECT_CHANNEL_4	0x04
#define SELECT_CHANNEL_1	0x01
#define DISABLE_CONVERSION_INT	(0x0 << 7)

/*
 * TSC module need ADC to get the measure value. So
 * before config TSC, we should initialize ADC module.
 */
static int imx6ul_adc_init(void)
{
    	printf("\r\n%s  \r\n",__FUNCTION__); 
	   
	ADC1->CFG  |= ADC_12BIT_MODE | ADC_IPG_CLK;
	ADC1->CFG  |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
	ADC1->CFG  &= ~ADC_HARDWARE_TRIGGER;

   
	/* enable calibration interrupt */
	ADC1->HC[0] |= ADC_AIEN;
	ADC1->HC[0] |= ADC_CONV_DISABLE;


	/* start ADC calibration */
	ADC1->GC |= ADC_CAL;


	if (ADC1->GS & ADC_CALF) {
		printf("\r\n ADC calibration failed\n");
		return -1;
	}

	/* TSC need the ADC work in hardware trigger */
	ADC1->CFG |= ADC_HARDWARE_TRIGGER;

	return 0;
}


/*
 * This is a TSC workaround. Currently TSC misconnect two
 * ADC channels, this function remap channel configure for
 * hardware trigger.
 */
static void imx6ul_tsc_channel_config(void)
{

  	ADC1->HC[0] = DISABLE_CONVERSION_INT;
	ADC1->HC[1] = DISABLE_CONVERSION_INT | SELECT_CHANNEL_4;
	ADC1->HC[2] = DISABLE_CONVERSION_INT;
	ADC1->HC[3] = DISABLE_CONVERSION_INT | SELECT_CHANNEL_1;
	ADC1->HC[4] = DISABLE_CONVERSION_INT;
	
}

/* TSC registers */
#define REG_TSC_BASIC_SETING	0x00
#define REG_TSC_PRE_CHARGE_TIME	0x10
#define REG_TSC_FLOW_CONTROL	0x20
#define REG_TSC_MEASURE_VALUE	0x30
#define REG_TSC_INT_EN		0x40
#define REG_TSC_INT_SIG_EN	0x50
#define REG_TSC_INT_STATUS	0x60
#define REG_TSC_DEBUG_MODE	0x70
#define REG_TSC_DEBUG_MODE2	0x80

/* TSC configuration registers field define */
#define DETECT_4_WIRE_MODE	(0x0 << 4)
#define AUTO_MEASURE		0x1
#define MEASURE_SIGNAL		0x1
#define DETECT_SIGNAL		(0x1 << 4)
#define VALID_SIGNAL		(0x1 << 8)
#define MEASURE_INT_EN		0x1
#define MEASURE_SIG_EN		0x1
#define VALID_SIG_EN		(0x1 << 8)
#define DE_GLITCH_2		(0x2 << 29)
#define START_SENSE		(0x1 << 12)
#define TSC_DISABLE		(0x1 << 16)
#define DETECT_MODE		0x2
/*
 * TSC setting, confige the pre-charge time and measure delay time.
 * different touch screen may need different pre-charge time and
 * measure delay time.
 */
static void imx6ul_tsc_set()
{
	int basic_setting = 0;
	int start;

     	TSC->BASIC_SETTING |= 0xFFFFU << 8;
	TSC->BASIC_SETTING |= DETECT_4_WIRE_MODE | AUTO_MEASURE;

      	TSC->DEBUG_MODE2 |= DE_GLITCH_2;
      	TSC->PS_INPUT_BUFFER_ADDR |= 0xFFFFU;

      	TSC->INT_EN |= 0xFFFFU;
 	TSC->INT_SIG_EN |= MEASURE_INT_EN;                       				/* 测量信号使能 */
  	TSC->INT_SIG_EN |= MEASURE_SIG_EN;                       /* 有效信号使能 */	  
	TSC->INT_SIG_EN |= VALID_SIG_EN;                       /* 有效信号使能 */	  


	/* start sense detection */
  	TSC->FLOW_CONTROL |= START_SENSE;                    /* 启动触摸检测, 当检测到触摸时,开始测量 */
  	TSC->FLOW_CONTROL &= ~TSC_DISABLE;                   /* 使能TSC */
}

static bool imx6ull_tsc_gpio_init()
{
	IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01,0);	
	IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_GPIO1_IO02,0);	
	IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);	
	IOMUXC_SetPinMux(IOMUXC_GPIO1_IO04_GPIO1_IO04,0);	

	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01,0xB0);
	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_GPIO1_IO02,0xB0);
	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0xB0);
	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO04_GPIO1_IO04,0xB0);
}


/* Delay some time (max 2ms), wait the pre-charge done. */
static bool tsc_wait_detect_mode()
{
	unsigned int count = 0;
	unsigned int state_machine;

	do {
		if (count > 10) // 10 * 200 Us 
			return false;
		delayus(200);
		count ++;
		state_machine = (TSC->DEBUG_MODE2 >> 20) & 0x7;  /**/
	} while (state_machine != 0x02);                          /* */
	delayus(200);
	return true;
}

void imx6ull_tsc_get_tsc(int *nX, int*nY, int* event)
{
	int status;
	int value;
	int x, y;
	int start;

	status = TSC->INT_STATUS;
	printf("\r\n%s, status[%x]\r\n",__FUNCTION__, status); 

	/* write 1 to clear the bit measure-signal */
	TSC->INT_STATUS |= MEASURE_SIGNAL;
	TSC->INT_STATUS |= DETECT_SIGNAL;

	/* It's a HW self-clean bit. Set this bit and start sense detection */
	TSC->FLOW_CONTROL |= START_SENSE;

      *event = 0;
	if (status & MEASURE_SIGNAL) {
		value = TSC->MEASEURE_VALUE;
		x = (value >> 16) & 0x0fff;
		y = value & 0x0fff;

		/*
		 * In detect mode, we can get the xnur gpio value,
		 * otherwise assume contact is stiull active.
		 */
		if (!tsc_wait_detect_mode()) {
		      printf("\r\n %s touch on x[%d] y[%d]\r\n",__FUNCTION__ ,x ,y );
			*nX = x;  
			*nY = y;
		      *event = 1;
		} else {
			printf("\r\n %s touch off \r\n",__FUNCTION__ );
		}

	}

}

int imx6ull_tsc_init()
{

	int err;

      	imx6ull_tsc_gpio_init();
	err = imx6ul_adc_init();
	if (err){
		printf("\r\n%s  init fail\r\n",__FUNCTION__); 
		return err;
	}
	imx6ul_tsc_channel_config();
	imx6ul_tsc_set();

	return 0;
}

 

 

 

0 Kudos
Reply
0 Replies