[Switch] main filter algorithm analysis of tslib
Tslib Parsing
Author: Jiujin. Hong
Reprint please explain the source: http://blog.csdn.net/hongjiujing or
Www.linuxforum.netEmbedded Linux Section
Tslib Background:
In mobile terminals using touch screens, the performance debugging of touch screens is one of the important issues. Due to electromagnetic noise, touch screens are prone to inaccurate clicks and jitters.
Tslib is an open-source program that provides functions such as filtering, deshake, and calibration for the sampling obtained by the touch screen driver. It is usually used as the Adaptation Layer of the touch screen driver, provides a unified interface for upper-layer applications.
Tslib Plugin:
Pthres is the touch screen sensitivity threshold plug-in provided by tslib; variance is the touch screen filtering algorithm plug-in provided by tslib; dejitter is the touch screen Noise Removal Algorithm plug-in provided by tslib; linear is the touch screen Coordinate Transformation plug-in provided by tslib
.
The Touch Screen driver is directly in contact with the hardware and provides the original device coordinate data for the tslib on the upper layer. The sampling interval and screen sensitivity can be configured. The sampling interval determines the number of samples per unit time.
In this case, the smaller the sampling interval, the larger the number of samples per unit time. This means that the more realistic the sampling, the less likely the sampling information is to be lost, such as the loss of strokes when writing the input method, however, due to noise, the smaller the sampling interval
It also means that the image displayed is less effective.
Tslib is the Adaptation Layer Between the touch screen driver and the application layer. It obtains the original device coordinate data from the driver, through a series of operations such as noise reduction, deshake, and coordinate transformation, to remove noise and convert the original device to the corresponding Screen
Coordinates.
Tslib interface:
In tslib, two main interfaces ts_read () and ts_read_raw () are provided for the application layer. ts_read () is an excuse for normal use, and ts_read_raw () is an interface for calibration.
Under normal circumstances, tslib processes the device coordinates sampled by the driver as follows:
Raw device --> variance --> dejitter --> linear --> Application
Module module Module
In the case of calibration, tslib processes the data sampled by the driver as follows:
Raw device --> calibrate
Due to the impact of various related periods, related parameters may need to be adjusted on different hardware platforms. The relationship between the above parameters is: the larger the sampling interval, the smaller the number of sampling points, the more distorted the sampling, but because of the small amount of information, it is easy to lose strokes.
Information is lost, but the image effect will be better. The de-noise algorithm should interact closely with the sampling interval. The larger the sampling interval, the smaller the de-noise constraint, otherwise, the smaller the sampling interval, the greater the denoising constraint. The deshake algorithm is relatively independent.
In part, the more complex the deshake algorithm is, the larger the computing workload and the heavier the system load will be. However, a good deshake algorithm can better remove the jitter, it will get better results when drawing images. The sensitivity and TS threshold values are Touch Screen
Sensitive Indicators, which generally do not need to be changed. Refer to the reference value.
Filter plug-in analysis:
Variance: Touch Screen Filtering Algorithm
Problem: some touch screen samples are very rough. Therefore, even if you hold a pen, the samples may be different and sometimes increase significantly. The worst case is that the electrical noise interference during sampling can be greatly different from the actual position of the pen. This will cause the mouse cursor to jump up and return.
Solution: delay one time slot for sampling data. If we see that the data read from the final sample is too much different, we mark it as "suspicious ". If the data read from the next sample is close to the data before "suspicious", the "suspicious" data will be discarded. Otherwise, we think that the pen is performing a fast moving operation. The sampling of "suspicious" data and the sampling of "suspicious" data will pass.
Important algorithm analysis:
Static int variance_read (struct tslib_module_info * info, struct ts_sample * SAMP, int nr)
{
Struct tslib_variance * Var = (struct tslib_variance *) Info;
Struct ts_sample cur;
Int COUNT = 0, DIST;
While (count <nr ){
If the sample data is marked as "submitted noise", assign the structure related to the current sample data to the noise status and clear the flag.
If (Var-> flags & var_submitnoise ){
Cur = var-> noise;
VaR-> flags & = ~ Var_submitnoise;
} Else {
If the sample data is not marked as "submitted noise", continue to sample the data.
If (Info-> next-> OPS-> Read (Info-> next, & cur, 1) <1)
Return count;
}
If there is no pressure value, there is no touch or release, but the message is pressed, it indicates that the noise is disturbed,
The queue is cleared immediately when a pen is released. Otherwise, the previous layer will capture the written message, but it is too late.
Info-> next-> OPS-> Read () is blocked.
If (cur. Pressure = 0 ){
/* Flush the queue immediately when the pen is just
* Released, otherwise the previous layer will
* Get the pen up notification too late. This
* Will Happen If Info-> next-> OPS-> Read () blocks.
*/
If (Var-> flags & var_pendown ){
VaR-> flags | = var_submitnoise;
VaR-> noise = cur;
}
/* Reset the state machine on pen up events .*/
Reset the pen-up event status flag
VaR-> flags & = ~ (Var_pendown | var_noisevalid | var_lastvalid );
Goto acceptsample; indicates that the sampling data is accepted.
} Else
VaR-> flags | = var_pendown; notification pen pressed
If the flag bit is different from the "var_lastvalid" status, perform the next sampling.
If (! (Var-> flags & var_lastvalid )){
VaR-> last = cur;
VaR-> flags | = var_lastvalid;
Continue;
}
For a pen-down event
If (Var-> flags & var_pen down ){
/* Compute the distance between last sample and current */
Calculate the distance between the last sampled data and the current Sampled Data
Dist = sqr (cur. X-var-> last. X) +
Sqr (cur. Y-var-> last. y );
If (Dist> var-> delta) {if the error is greater than the default value, for example, 30.
Considering the previous sampling as noise? Suspicious?
/* Do we suspect the previous sample was a noise? */
If (Var-> flags & var_noisevalid ){
However, if the previous sampling is already suspicious, it is considered as a fast pen movement trigger.
/* Two "noises": It's just a quick pen movement */
SAMP [count ++] = var-> last = var-> noise;
VaR-> flags = (Var-> flags &~ Var_noisevalid) |
Var_submitnoise;
} Else
If the previous sampling is not a suspicious status, it is considered as a suspicious status.
VaR-> flags | = var_noisevalid;
/* The pen jumped too far, maybe it's a noise ...*/
VaR-> noise = cur;
Continue;
} Else
VaR-> flags & = ~ Var_noisevalid; the sampled data is normal.
}
Acceptsample:
# Ifdef debug
Fprintf (stderr, "variance ----------------> % d \ n ",
VaR-> last. X, Var-> last. Y, Var-> last. pressure );
# Endif
SAMP [count ++] = var-> last;
VaR-> last = cur;
}
Return count;
}
Dejitter Noise Removal plug-in analysis:
Problem: some touch screens obtain the x/y coordinate sample values from the ADC, and their hidden position carries a lot of noise interference, which leads to the jitter of the screen output value.
For example, if we keep a certain point, we will get a lot of x/y coordinate samples, which are similar but not equal. At the same time, if we try to draw a straight line in a drawing program,
We will get a straight line filled with "glitch.
Solution: we apply a smooth weight filter to the last few values to remove the output "glitch ". We find that the coordinates have changed significantly. We will reset the backlog of PEN positions
Coordinates should not be smooth to avoid smoothing. Of course, it is assumed that all noise has been filtered by the bottom filter, such as the variance module.
Working principle:
The filter works as follows: we have the newest n sample orbit, and we keep track of the newest n samples and calculate the average value based on a certain weight. The oldest data has the least weight and the latest data.
Has the maximum weight. This helps eliminate jitter without affecting the response time, because we output an output sample for each input sample, and the pen movement will become smoother.
Important algorithm analysis:
To make things simple (avoid errors), we make sure sum (weight) is equal to the power of 2. At the same time, when we do not have the default number of samples, we must know how to perform the approximate test.
Static const unsigned char weight [nr_samphistlen-1] [nr_samphistlen + 1] =
{
/* The last element is pow2 (sum (0 .. 3 ))*/
{5, 3, 0, 0, 3},/* When we have 2 samples ...*/
{8, 5, 3, 0, 4},/* When we have 3 samples ...*/
{6, 4, 3, 3, 4},/* When we have 4 samples ...*/
};
Static void average (struct tslib_dejitter * djt, struct ts_sample * SAMP)
{
Const unsigned char * W;
Int Sn = djt-> head;
Int I, x = 0, y = 0;
Unsigned int p = 0;
W = weight [djt-> nR-2]; find the data corresponding to the weight array. For example, if it is the first sample, it does not exist. If it is the second sample, it corresponds to {5, 3, 0, 0, 3}, and so on.
For (I = 0; I <djt-> NR; I ++ ){
X + = djt-> hist [Sn]. x * W [I];
Y + = djt-> hist [Sn]. y * W [I];
P + = djt-> hist [Sn]. p * W [I];
Sn = (Sn-1) & (nr_samphistlen-1); record the serial number of each sampling
}
Samp-> X = x> W [nr_samphistlen]; obtain the average value.
Samp-> Y = Y> W [nr_samphistlen];
Samp-> pressure = P> W [nr_samphistlen];
# Ifdef debug
Fprintf (stderr, "dejitter ----------------> % d \ n ",
Samp-> X, samp-> Y, samp-> pressure );
# Endif
}
Static int dejitter_read (struct tslib_module_info * info, struct ts_sample * SAMP, int nr)
{
Struct tslib_dejitter * djt = (struct tslib_dejitter *) Info;
Struct ts_sample * s;
Int COUNT = 0, RET;
Ret = Info-> next-> OPS-> Read (Info-> next, SAMP, NR );
For (S = Samp; RET> 0; s ++, RET --){
If (S-> pressure = 0 ){
/*
* Pen was released. Reset the State and if the pen is released, reset the state standard, and discard all historical events.
* Forget all history events.
*/
Djt-> Nr = 0;
SAMP [count ++] = * s;
Continue;
}
/* If the pen moves too fast, reset the backlog. */If the pen moves too fast, reset the backlog
If (djt-> nr ){
Int Prev = (djt-> head-1) & (nr_samphistlen-1 );
If (sqr (S-> X-djt-> hist [Prev]. X) +
Sqr (S-> Y-djt-> hist [Prev]. y)> djt-> delta) {if the square distance of X is added to the threshold value of Y, the system prompts that the threshold value is exceeded, discarded, and reset.
# Ifdef debug
Fprintf (stderr, "dejitter: Pen movement exceeds threshold \ n ");
# Endif
Djt-> Nr = 0;
}
}
Djt-> hist [djt-> head]. x = s-> X;
Djt-> hist [djt-> head]. Y = s-> Y;
Djt-> hist [djt-> head]. P = s-> pressure;
If (djt-> Nr <nr_samphistlen) if the number of samples is smaller than the default number of samples, continue to execute
Djt-> Nr ++;
/* We'll pass through the very first sample since
* We can't average it (no history yet ).
*/
If (djt-> Nr = 1) If this is the first sampling and there is no historical or old sampling data, assign a value directly.
SAMP [count] = * s;
Else {if this is not the first sampling, run the average function to obtain the sample value after the average.
Average (djt, SAMP + count );
SAMP [count]. TV = s-> TV;
}
Count ++;
Djt-> head = (djt-> head + 1) & (nr_samphistlen-1); record the sampling sequence number
}
Return count;
}
Conclusion: after analyzing the varience filter module plug-in and dejitter deshake module plug-in, we know the following:
1: varience is the lowest-layer filter plug-in. Variance filter attempts to do the best. It filters out the random noise sampled by the ADC by limiting the movement speed of some samples. For example:
Pen should not be faster than some threshold values.
Main Parameter: Threshold Value Delta
Determine the square distance (X2-X1) ^ 2 + (Y2-Y1) ^ 2) of the previous sampling point and the current sampling point to determine whether the two samples are "near" or "far ". If the distance between the previous and current samples is 'yuan ',
The sample is marked as 'potential Noise' or "suspicious", but this does not mean it will be discarded. If the next sampling approaches it, we will see it as a normal Fast Moving action. At the same time, if the sampling ratio after "potential noise" is higher than the previously discussed
The sampling is "far", and a normal Fast Moving action is also considered. If the sampling after "potential noise" is similar to the sampling before "potential noise", we will discard the "potential noise" data and think it is the noise to be filtered.
2: dejitter de-shake module plug-in
Remove the jitter of x/y coordinates by using a weighted smoothing filter. Recent sampling has the heaviest weight, and early sampling has a light weight, which enables an input-output rate.
Main Parameter: Threshold Value Delta
The square distance between two samples, (X2-X1) ^ 2 + (Y2-Y1) ^ 2), defines the barrier of the 'saved. If the pen moves fast, it is not appropriate to smooth the pen action. In addition, it is not accurate at any time. So if fast motion is detected,
The filter module simply discards the backlog and copies the input to the output.
In addition, some brothers know about the dejitter plug-in. Please explain it in detail. Thank you!
Changelog:
1: Post initial version