Understand the principle and application of S3C2440 touch screen driver

Publisher:灵感之翼Latest update time:2023-01-12 Source: elecfansKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

3. The next thing to do is to implement the conversion of touch screen status and coordinates in two interrupt service programs. Let’s look at the code first, as follows:

/*Define an external semaphore ADC_LOCK, because ADC_LOCK has been declared in the ADC driver,
thus ensuring mutually exclusive access of ADC resources in the ADC driver and touch screen driver*/
extern struct semaphore ADC_LOCK;

/*As a label, The X and Y coordinates are converted only after operating the touch screen */
static int OwnADC = 0;

/* Used to record the converted X coordinate value and Y coordinate value */
static long xp;
static long yp;

/* Used to Count the number of analog input conversions when the touch screen is pressed or lifted */
static int count;

/*Define an AUTOPST macro to set the ADC touch screen control register to automatic conversion mode */
#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN |
                S3C2410_ADCTSC_AUTO _PST | S3C2410_ADCTSC_XY_PST(0))


/*Touch screen interrupt service routine, triggered when the touch screen is pressed or the pen is lifted*/
static irqreturn_t tc_irq(int irq, void *dev_id)
{
    /*Used to record the value after AD conversion* /
    unsigned long data0;
    unsigned long data1;

    /*Used to record whether the touch screen operation status is pressed or lifted*/
    int updown;

    /*ADC resources can be obtained, that is, locked*/
    if (down_trylock(&ADC_LOCK) == 0)
    {
        /*Indicates that the touch screen has been operated*/
        OwnADC = 1;

        /*Read the value after AD conversion. Note that this time the main read is the status*/
        data0 = readl(adc_base + S3C2410_ADCDAT0);
        data1 = readl( adc_base + S3C2410_ADCDAT1);

        /*Record whether the touch screen is pressed down or lifted up this time. This status is saved in the 15th bit of the data register, so it is related to S3C2410_ADCDAT0_UPDOWN*/
        updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!( data1 & S3C2410_ADCDAT0_UPDOWN));

        /*Determine the operating status of the touch screen*/
        if (updown)
        {
            /*If it is in the pressed state, call the touch_timer_fire function to start the ADC conversion. The function definition will be discussed later*/
            touch_timer_fire(0);
        }
        else
        {
            /*If it is in the raised state, this operation is over, so the possession of ADC resources is released*/
            OwnADC = 0;
            up(&ADC_LOCK);
        }
    }

    return IRQ_HANDLED;
}

static void touch_timer_fire(unsigned long data )
{
    /*Used to record the value after AD conversion this time*/
      unsigned long data0;
      unsigned long data1;

    /*Used to record whether the touch screen operation status is pressed or lifted*/
    int updown;

    /*Read this time AD The converted value, note that this time the main read is the status */
      data0 = readl(adc_base + S3C2410_ADCDAT0);
    data1 = readl(adc_base + S3C2410_ADCDAT1);

    /*Record whether the touch screen is pressed down or lifted up this time, and the status is saved In the 15th bit of the data register, so it is related to S3C2410_ADCDAT0_UPDOWN*/
     updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

    /*Judge the operating status of the touch screen*/
     if (updown)
    {
        /* If the state is pressed and the ADC has converted, report the event and data */
         if (count != 0)
        {
            long tmp;
                                                                                                 
            tmp = xp;
            xp = yp;
            yp = tmp;
                                                                                                 
            xp >>= 2;
            yp >> = 2;

#ifdef CONFIG_TOUCHSCREEN_MY2440_DEBUG
            /*Touch screen debugging information, after selecting this item when compiling the kernel, clicking the touch screen will print out the coordinate information on the terminal*/
            struct timeval tv;
            do_gettimeofday(&tv);
            printk(KERN_DEBUG "T: %06d, X: %03ld, Y: %03ldn", (int)tv.tv_usec, xp, yp);
#endif

            /*Report the absolute coordinate values ​​of X and Y*/
             input_report_abs(ts_dev, ABS_X, xp);
             input_report_abs(ts_dev, ABS_Y, yp);

            /*Report the status of the touch screen, 1 indicates that the touch screen is pressed*/
            input_report_abs(ts_dev, ABS_PRESSURE, 1);

            /*Report key events, the key value is 1 (representing that the key corresponding to the touch screen is pressed)*/
             input_report_key(ts_dev, BTN_TOUCH, 1);

            /*Wait for the receiver to reply with confirmation after receiving the data, for synchronization*/
             input_sync(ts_dev);
         }

        /*If the status is pressed and the ADC has not started conversion, start the ADC for conversion*/
         xp = 0;
         yp = 0;
         count = 0;

        /*Set the touch screen mode to automatic conversion mode*/
         writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, adc_base + S3C2410_ADCTSC);

        /*Start ADC conversion*/
         writel(readl(adc_base + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_STAR T , adc_base + S3C2410_ADCCON);
     }
    else
    {
        /*Otherwise it is in the raised state*/
         count = 0;

        /*Report the key event, the key value is 0 (representing that the key corresponding to the touch screen is released)*/
         input_report_key(ts_dev, BTN_TOUCH, 0 ;

        ​
         ​

        ​
         ​

        ​Reset the touch screen to the waiting interrupt state */
         writel(WAIT4INT(0), adc_base + S3C2410_ADCTSC);

        /*If the touch screen is lifted, it means that the operation is over this time, so the ADC resource is released*/
        if (OwnADC )
        {
            OwnADC = 0;
            up(&ADC_LOCK);
        }
     }
}

/*Define and initialize a timer touch_timer, the timer service program is touch_timer_fire*/
static struct timer_list touch_timer = TIMER_INITIALIZER(touch_timer_fire, 0, 0);

/*ADC Interrupt service routine, triggered execution after AD conversion is completed*/
static irqreturn_t adc_irq(int irq, void *dev_id)
{
    /*Used to record the value after AD conversion*/
    unsigned long data0;
    unsigned long data1;

    if(OwnADC)
    {
        /*Read the value after AD conversion this time. Note that this time the main read is the coordinates*/
        data0 = readl(adc_base + S3C2410_ADCDAT0);
        data1 = readl(adc_base + S3C2410_ADCDAT1);

        /*Record the value after AD conversion this time According to the data sheet, the X and Y coordinate conversion values
        ​​are stored in bits 0-9 of data registers 0 and 1 respectively, so here and above S3C2410_ADCDAT0_XPDATA_MASK takes the value of bits 0-9*/
        xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
        yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;

        /*Count the number of AD conversions this time*/
        count++;

        if (count < (1<<2))
        {
            /*If the number of conversions is less than 4, restart ADC conversion*/
            writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, adc_base + S3C2410_ADCTSC);
            writel(readl(adc_base + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, adc_base + S3C2410_ADCCON );
        }
        else
        {
            /*otherwise , start a timer with a tick time, which will execute the timer service program to report events and data*/
            mod_timer(&touch_timer, jiffies + 1);
            writel(WAIT4INT(1), adc_base + S3C2410_ADCTSC);
        }
    }

    return IRQ_HANDLED;
}

We describe the conversion process as a whole:
(1) If the touch screen senses touch, the touch screen interrupt is triggered and tc_irq is entered. After obtaining ADC_LOCK, it is judged that the touch screen status is pressed, and then touch_timer_fire is called to start the ADC conversion;
(2) When the ADC conversion After starting, the ADC interrupt is triggered and the adc_irq is entered. If the number of conversions this time is less than 4, the ADC is restarted for conversion. If 4 times are completed, a tick timer is started to stop the ADC conversion. That is to say, in this Within the time tick, ADC conversion stops;
(3) Why should ADC conversion be stopped before one time tick arrives? This is to prevent screen shaking.
(4) If a time tick arrives, enter the timer service program touch_timer_fire. If it is judged that the touch screen is still pressed, the event and converted data will be reported, and the ADC conversion will be restarted. Repeat step (2);
(5) If the touch screen is lifted If it starts, the release event is reported and the touch screen is reset to the waiting interrupt state.


[1] [2]
Keywords:S3C2440 Reference address:Understand the principle and application of S3C2440 touch screen driver

Previous article:Set-top box media player based on TQ2440 development board
Next article:ARM register analysis and exception handling methods

Recommended ReadingLatest update time:2024-11-23 18:30

STM32F103 uses analog I2C to drive ADS1115
ADS1115 is driven by simulating I2C: (Part of the code was borrowed from several on the Internet, and configured according to the pins, but none of them worked. I spent a day adjusting it today and finally adjusted it in the evening) Note: This part of the code only needs part of the program of ADS1115 (some used arra
[Microcontroller]
Several isolated LED drive power supply solutions
In the context of global energy shortage and increasing environmental protection requirements, countries around the world are vigorously developing green energy-saving lighting. LED lighting, as a revolutionary energy-saving lighting technology, is developing rapidly. However, the requirements for LED dri
[Power Management]
Several isolated LED drive power supply solutions
51 MCU drives ds1302 program (12864 LCD display)
This is the main interface This is the main menu interface This is the sub-interface for setting time This is the setting date Setting the Backlight This is the status icon that appears on the main interface after the key tone and alarm are set.  
[Microcontroller]
51 MCU drives ds1302 program (12864 LCD display)
In-depth discussion of key technologies for electric drive system development
The asymmetry of the parallel-axis electric drive axle geometry significantly increases the angle between the torque shaft and the motor shaft (B1). The torque shaft suspension arrangement is no longer suitable for electric drive axles. Assembly; The motor's low speed, high torque and fast response c
[Embedded]
In-depth discussion of key technologies for electric drive system development
JZ2440 driver compilation, installation and testing
1. Compile the Linux kernel Documents needed: a. Kernel file (e.g. linux-2.6.22.6.tar.bz2) b. Corresponding patch file (for example, linux-2.6.22.6_jz2440.patch) $ tar xjf linux-2.6.22.6.tar.bz2//Unzip the kernel file $ cd linux-2.6.22.6 $ patch -p1 ../linux-2.6.22.6_jz2440.patch //Apply patch $ mv ../4.3-inch LCD_
[Microcontroller]
Implementation of touch screen driver in Linux (1) - based on s3c6410 processor
These articles are mainly about touch screen drivers in Linux, based on the s3c6410 processor. This article is mainly about the implementation of touch screen devices as platform devices, as well as the source code analysis of the corresponding probe function and remove function. 1. Loading and unloading functions o
[Microcontroller]
Implementation of touch screen driver in Linux (1) - based on s3c6410 processor
Design of hysteresis control circuit based on buck-type LED constant current drive [Figure]
This paper designs a hysteresis control circuit for a buck-type LED constant current driver chip. The chip adopts a high-side current detection scheme and uses a hysteresis current control method to perform hysteresis control on the drive current, thereby obtaining a constant average drive current. The design adopts a
[Power Management]
Design of hysteresis control circuit based on buck-type LED constant current drive [Figure]
ON Semiconductor's line driver for smart meter PLC communication applications
Smart meters play a key role in the emerging smart grid applications. Designers need to choose a suitable communication method for the communication between smart meters and data concentrators. Power line carrier (PLC) technology uses power lines as data transmission media and existing power distribution networks
[Power Management]
ON Semiconductor's line driver for smart meter PLC communication applications
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号