This is the bug/patch tracker for Rockbox. Click here for more information.
Quick links: Bugs · Patches · Rockbox frontpage
FS#6041 - H10 Scrollpad
Attached to Project:
Rockbox
Opened by Holger Winnemoeller (Lazerman) - Friday, 22 September 2006, 00:55 GMT+2
Last edited by Marc Guay (Marc_Guay) - Friday, 12 December 2008, 16:13 GMT+2
Opened by Holger Winnemoeller (Lazerman) - Friday, 22 September 2006, 00:55 GMT+2
Last edited by Marc Guay (Marc_Guay) - Friday, 12 December 2008, 16:13 GMT+2
|
DetailsThe scrollpad on the H10 (20gb, not sure about 5/10gb) has always bothered me with being jumpy, inaccurate, and unintuitive. At the moment (in rockbox) it seems as though it is working as a simple two button device (up/down), with no real dragging capabilities. I am wondering if this is a limitation of the hardware or current software implementation.
The original firmware seemed to work as follows: split slider into upper and lower field. Tapping in either upper or lower half would create click-type event for up/down. Dragging in upper half would produce scroll up, draggin in lower half would produce scroll down events. The problem was that upper and lower halves are really kinda arbitrary and not easily distinguishable. What I think would work nicely: Tapping top and bottom, as before. Remove upper and lower restrictions for dragging, i.e. if dragging down (anywhere on the scrollpad) create scroll down event, if dragging up (again, anywhere) create scroll up event. Drag and hold will scroll in desired direction proportional to the drag speed (as in pushing a puck on ice). Hold (just hold, no tap or drag) on the touchpad creates a sliding value that can be used as a coordinate for different types of continuous input. To implement this, we'd need some kind of knowledge about what signals the actual hardware provides, what resolution the pad has, i.e. what the physical and logical implementations of the device are. I am not sure how the Ipod scrollwheel works, but it seems that some of that code could be re-purposed, maybe? |
This task depends upon
Unfortunately, it looks like we don't fully understand how to use the ADC. The values we read are quite jumpy, so it will be quite difficult to implement your suggestion until we can read stable values from the ADC. Alternatively, it may be possible to implement some sort of filter on the ADC values read?
You can see the signal read from the ADC yourself in the I/O Ports debug screen (note that you have to press Power and Right at the same time to exit that screen). If you feel you can get a working implementation of your idea with these values, then please feel free to submit a patch.
So in short, Output = W1*S1 + W2*S2 + W3*S3 + W4*S4 + W5*S5, where Wn are the weights, and Sn are the samples.
The problem for this type of (linear) filtering is that large differences between adjacent samples can get severely smoothed, but often these differences are important and should be kept.
Bilateral filtering doesn't just take the proximity of samples into account (how close to the center they are), but also how different they are from the center value. This introduces another weight (let's call it vertical; and the other one horizontal) that must be included
V1 = f(S3-S1)
V2 = f(S3-S2)
V3 = 1
V4 = f(S3-S4)
V5 = f(S3-S5)
the function, f, is generally also a Gaussian shape (i.e. exponential, f~e^(-x^2/d^2)). The parameter d changes the width of the Gaussian bell shape. The effect is that if S3-S1 is very large, then V1 is very small and the much different S1 will not influence the output very much.
The new sum becomes:
Output = W1*V1*S1 + W2*V2*S2 + W3*V3*S3 + W4*V4*S4 + W5*V5*S5
Obivously, the output now has to be normalized differently, by dividing the sum by W1*V1 + W2*V2 + W3*V3 + W4*V4 + W5*V5
And that's already it. The smoothing behavior then depends mostly on the kernel size (5 in this case) and the parameters for the horizontal and vertical gaussian distributions. Note that while the horizontal weights can be pre-computed, the vertical weights are data-dependent and therefore need to be computed on the fly.
An implementation should keep a circular array of size 5 or 7 or something, update the latest values and smooth over them using the above filter.
I hope that helps for now. If nobody comes up with an implementation I will provide one after my vacation. Have fun.
I also divided the touchpad into 5 boundings and it worked at least in the plugin API. I gave
it up because of my exams and because it wasnt 100% and i am not a good programmer in C.
I've been playing around with the OF to see if I can figure out what it's doing in the background. Here's some ***PSEUDO-CODE*** for what I've figured out so far
HandleScrollPad:
while no input from scrollpad { do nothing }
wait up to 0.5s for scrollpad change
if changed to no input then
{
send up/down based on previous position
goto HandleScrollPad
}
while not changed
{
send up/down based on current position
wait (repeat_delay) for change
}
if changed to valid value (not open)
{
while not open
send up/down based on direction and size of changes
}
goto HandleScrollPad
It's a bit messy, but I think that gives a basic idea. There's all sorts of ADC settling times and so on missing, as well as some way of checking if a change is heading for the ADC_OPEN state, etc. Someone with more familiarity with the ADC code should be able to fill that in fairly well, and adjust the above pseudo-code to fit in with the way the key drivers work at the moment.
-- Absolute value is not as important as relative values (we want to register up as up, and down as down, but we don't need to be running at full resolution... my fingers are much too thick for that anyway :-))
-- We must filter out noise at the expected noise level, but NOT large jumps (i.e. simple averaging doesn't work)
-- We don't want to filter over too big a time-window. This requires resources and introduces delay
So the solution I came up with are two very simple functions: A smoothing pass, followed by a quantization step. Both only consider the last known value and are trivial to implement.
One caveat is that the system will self-correct over time. While this is a nice feature, it can result in a delayed signal being registered. This really only matter when you keep your finger on the control for a long time. What could happen is this: E.g. you scroll up and the display or cursor moves up, as expected. After you stop and hold for a little bit, another spurious up event is fired. One could possibly fix that by increasing the quantization size a bit, or moving the quantization center in accordance with the current sliding speed, but I would have to see this in action to really recommend a solution.
Smoothing (Smoother.cs): An exponential terms that weights the difference in signal by the amount of difference. Large differences are passed through, while small differences are heavily attenuated.
Quantization (SlidingQuantizer.cs): Only register value changes over a certain threshold
The parameter values for these would have to depend on how noisy the trackpad actually is, somebody would have to test that out, but there are only two values to consider - the smoothing value and the quantization value.
Note that the code is written to demonstrate the smoothing, not for integration into rockbox. Someone would have to take the 10 or so relevant lines of code and put that into the firmware. Then, one would have to work at using those values somehow in the UI. So - Godspeed to whomever takes on that task! Go Team :-)
1. We can't use floating point.
2. I don't think we currently have an exponential function. Maybe we could just get by with a couple of terms from the taylor series? For example 1-exp(-x*x) ~ x*x so maybe we could use max(x*x,1) instead?
I replaced the smoothing and quantization functions with Integer versions. No floating points needed.