Adafruit touchscreen (AR1100)
Chris Mahoney (1684) 2165 posts |
I’ve bought this from Adafruit – it’s a little HDMI/USB touchscreen, and supposedly presents itself as a USB mouse. It’s using the Microchip AR1100 touchscreen controller. Whenever I touch the screen, the mouse pointer just jumps into the top-right corner of the screen instead of following my finger. The same screen works under OS X; admittedly it’s pretty fiddly (detects taps as drags and similar issues) but it does work to an extent. Under RISC OS it’s unusable. Has anyone tried out one of these devices before? Any suggestions on what could be causing a jump to the upper-right corner? |
Jeffrey Lee (213) 6048 posts |
Chances are it’s using absolute coordinates, which USBDriver doesn’t really support (although I guess the limitation is more down to PointerV, since that only allows relative coordinates to be used). I haven’t actually checked what the touchscreen on my displaylink screen reports itself as – i.e. whether USBDriver is currently detecting it as a mouse/pointing device or not. But either way, once one of us finds the time to add general touchscreen support (USB, Pandora, TouchBook, etc.) I suspect we’ll also be able to get screens like the AR1100 working. |
Raik (463) 2061 posts |
Thomas has a driver for a Galaxy-USB-Touchscreen. Maybe it helps but I think not. |
Chris Mahoney (1684) 2165 posts |
Absolute coordinates would explain it; I didn’t even realise that there were two different systems (I figured that a mouse was a mouse!). I suspect that PointerV is going to be too scary for me to look at (I tried one of the other “Vs” a couple of months ago with disastrous results) so maybe it’s just a case of being patient… but that’s not going to stop me from attempting to poke around in there anyway :) Raik, thanks for the link, as you say it may not work but I’ll still give it a try when I get home. |
Jeffrey Lee (213) 6048 posts |
Unfortunately my displaylink screen uses a vendor-specific protocol/interface for its touchscreen rather than a standard HID type, so it doesn’t look like I’ll be able to use that for easily testing any USBDriver changes.
PointerV is fairly straightforward, although it does looks like the behaviour has changed a bit over the years (initially the kernel just polled the pointer using PointerV 0, but now it prefers to have the driver pro-actively call PointerV 3 to notify the kernel of changes?) For handling absolute pointing devices I suspect we’d just want to define a new reason code which allows the driver to give the absolute coordinates. https://www.riscosopen.org/wiki/documentation/show/PointerV (n.b. it looks like there might be a couple of reason codes not yet listed on the wiki) |
Dave Higton (1515) 3534 posts |
I managed to do an experimental USB graphics tablet (absolute coordinates) driver a few years back, so I’d encourage you to have another go. I can’t remember how I integrated it with the OS, though – I assume I would have had to write a little module. (Lest anyone should over-estimate its usefulness: it ran as an application, and it was dedicated to one particular model. So no use in the real world.) |
Chris Mahoney (1684) 2165 posts |
I’ve done a little bit of poking around, and I should probably add a disclaimer that I know next to nothing about assembler, but in Kernel.s.PMF.mouse is a function called ProcessMouseXY… which seems to already handle absolute coordinates if R4 is set to “Abso”. I guess the next step on the agenda is to build my own ROM so that I can try messing with the calls to ProcessMouseXY and drop “Abso” in there (a bit of a hack, but it will at least show whether it works!) |
Jeffrey Lee (213) 6048 posts |
Well spotted – it looks like that does everything we need already.
The bit you’ll want to change is the ums_intr function in usbmouse.c: |
Jon Abbott (1421) 2651 posts |
Daft question, but why do you have to re-compile the ROM to use a fixed point mouse? Shouldn’t there be a MouseType for it? |
Steve Pampling (1551) 8172 posts |
Probably should be, but… As Jeffrey said it looks like part of the job is done. |
Dave Higton (1515) 3534 posts |
I’ve just had a quick look at my graphics tablet module. It looks like the key thing is to use OS_Word 21, (3 and 4). Curiously, my code reads the position with OS_Word 21, 4, then updates the X position with OS_Word 21, 3; then it reads with 21,4 again, and finally adds in the Y position by 21,3. HTH. I’m sure this is a bodge on the part of RO, and that there should be a better way of doing it. |
Jon Abbott (1421) 2651 posts |
Doesn’t sound like much needs adding to support touch screens then, which is good. There’s dozens of very cheap touch panels available that work with the Pi so we’re not far from a RISCOS tablet being possible. |
Chris Mahoney (1684) 2165 posts |
Well, my first experiment/hack has failed. In the “mouse” assembler file, I simply added “MOV r4, Abso” before each of the two calls to ProcessMouseXY. It didn’t make any difference; taps still went to the top-right corner and a regular USB mouse still functioned. |
Jeffrey Lee (213) 6048 posts |
“MOV r4, Abso” will put the address of “Abso” into R4, rather than the value. You want to use “LDR r4, Abso” instead. Also another thing which might throw a spanner in the works is that I’m not sure whether the touch screen will be giving coordinates in pixels, which is what the Abso code expects (or it might be expecting OS units – I’m not sure offhand what the internal coordinates are that the kernel uses for the mouse pos). The touch screen might just be returning values scaled between (e.g.) 0-65535. Judging by CVS history, ‘Abso’ looks like it’s supported by all versions of RISC OS 5. |
Chris Mahoney (1684) 2165 posts |
I did warn you that I don’t know assembler :) Thanks, I’ll give LDR a go and see what happens. Hopefully the screen returns pixels, but one step at a time… |
Tank (53) 375 posts |
The data sheet of the chip says “HID-MOUSE Mouse, absolute coordinates 0-4095” |
Chris Mahoney (1684) 2165 posts |
That’s a bit of a pain. In this particular case I know the resolution and can easily calculate pixels from coordinates, but presumably the same calcs won’t work for other panels :( No news re: LDR yet; I’m stuck at work for the rest of the day. |
Chris Mahoney (1684) 2165 posts |
Success! …ish. With “LDR r4, Abso” I get a pointer that can be moved across the screen with my finger, although as previously noted it doesn’t have a 1:1 relationship between screen coordinates and pixels/OS units. Interestingly I need to drag my finger to about 40% of the way across the screen to get the pointer across to the right-hand side. As it’s 480 pixels across, with the returned coordinates going to 4095 then I’d have thought that 8.53% of the way would do it. Perhaps there’s something else to it! As for vertical, currently the pointer is stuck at the top of the screen. I can move it horizontally without any trouble but it doesn’t want to move vertically. More experimentation is in order :) |
Jeffrey Lee (213) 6048 posts |
I did do a quick test this morning and it looks like the ‘Abso’ mode requires the position to be specified in OS units rather than pixels. Normally there are 2 OS units per pixel, so if the screen is reporting the position in pixels then that would just about explain what you’re seeing. But it wouldn’t surprise me if there are also some values in the HID descriptor which indicate whether any offset/scaling needs to be applied to the touch values in software. Not quite sure what would be wrong with the Y position – there’s some code in USBDriver which inverts the Y delta when dealing with relative devices, so maybe it’s misdetecting the device as using relative positions (I can’t imagine the device returning a negative Y position – unless there is actually some scale/offset hidden in the HID descriptor which we should pay attention to). |
David Feugey (2125) 2709 posts |
Imperfect solution: a calibration tool.
So we have basically a way to get a small RISC OS tablet (or Phone with work from Thomas). Would be funny to pack all of this in a small 3D printed case. More work for CJE :) |
Chris Mahoney (1684) 2165 posts |
Sorry for the lack of updates; I’ve been a little busy. I wrote a little test app that returns the currently-touched coordinates and it seems that 0,0 is in the top-left with 4095,4095 at the bottom-right. On the other hand, ProcessMouseXY appears to expect 0,0 to be at the bottom-left etc, which explains why vertical movement wasn’t working properly. The to-do list therefore contains “flip the Y axis” and “implement scaling” – somewhat frustratingly X and Y have different scale factors but I’m sure that it’ll be salvageable. |
Jon Abbott (1421) 2651 posts |
I’m following your progress closely as I have a Tontec Touchscreen on order. I need to code the GraphicsV driver for it first, which will take some time whilst I figure out the SPI interface. Adding mouse support will be next, so your experience here is going to prove invaluable. Did you end up having to rebuild the OS ROM, or can we get away with a “TabletMouse” module? I’m still not totally clear on what’s required to add support for Abso in RISCOS. If it’s a case of OS_Word 21 returning the correct values, I could assist by coding an SWI intercept module as a short-term measure to avoid bespoke ROM builds. ADFFS already takes over the SWI vector when it loads, so I could shove it in that and provide an SWI to pass the Abso coordinates, for the purposes of quickly testing the theory. Drop me an eMail if I can assist: jon at jaspp dot org dot uk |
Chris Mahoney (1684) 2165 posts |
I rebuilt the ROM, but whether I have to is another story :) I imagine that touchscreen support is something that the OS “should” have, and therefore envisage a new MouseType with support built into the standard ROM (you mentioned something similar last week). But let’s get it all working first! |
Chris Mahoney (1684) 2165 posts |
Wow, I’m an idiot. It’s 800 pixels wide because it’s in landscape orientation, so 1600 OS units, and 1600/4095 = 39% so that explains everything. The other interesting thing is that the specs state that the screen is 800×480, but its EDID reports 800×500 (when connected to a Mac via Thunderbolt adapter; I haven’t tried ReadEDID) and it happily runs at that resolution. There are very thin black bars at the top/bottom when using 800×480 so I wonder why the specs state that resolution. |
Jeffrey Lee (213) 6048 posts |
There shouldn’t be any need for SWI intercepts or kernel changes. Everything you need can be done within USBDriver where it calls PointerV (ums_intr function) Quick and dirty untested code to put in in replace of the “if(dx || dy) { … }” code block: if(sc->flags & UMS_ABS) { static int oldx,oldy; static const int vduin[5] = { 4, 5, 11, 12, -1 }; int vduout[5]; _swix(OS_ReadVduVariables, _INR(0,1), vduin, vduout); int width = (vduout[2]+1) << vduout[0]; int height = (vduout[3]+1) << vduout[1]; dx = (dx*width)/4096; dy = height-((dy*height)/4096); if ((dx != oldx) || (dy != oldy)) { oldx = dx; oldy = dy; _swix(OS_CallAVector, _INR(0,4) | _IN(9), PointerReason_Report, PointerDevice_USB, dx, dy, 0x6f736241, PointerV); } } else if(dx || dy) { _swix(OS_CallAVector, _INR(0,4) | _IN(9), PointerReason_Report, PointerDevice_USB, dx, dy, 0, PointerV); } Possibly sc→sc_loc_x.size and sc→sc_loc_y.size contain the number of bits of precision of the X & Y values, but we’d have to check the HID spec (+ device descriptors?) to make sure (those values will definitely contain the amount of data it reads from the device, but perhaps that doesn’t match the minimum/maximum values we should scale to) |