#351469 - 10/04/2012 17:53
Knob speed limitations?
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I'm working on some knob velocity dependant code for my SqueezeSlave impementation. Basically I'd like to skip quickly through the lists if the knob is spun fast. The Squeezeboxes have this funtionality already, so it's just a matter of tweaking it. My issue is that I want to spin it reasonably quickly without jumping through the lists, but when I flick the knob I want it to accelerate.
I basically need a larger range of working knob speed; it seems that the knob misses counts if it's spun too fast. I've replaced the knob with a new one a little while ago because it was flaky. I put the newer Alps one on that looked a bit more robust.
Does anyone know what the limiting factor is for the knob speed? Any way to get more speed from it? I see the Hijack kernel has some added debounce. How is this implemented? Does this debounce limit the speed? How is the encoder hooked up, is it hooked to the PIC chip on the display board? Does the PIC chip do the counting or does the StrongARM?
So many questions... Any insight appreciated.
|
Top
|
|
|
|
#351472 - 10/04/2012 19:51
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 20/12/1999
Posts: 31597
Loc: Seattle, WA
|
Something to consider: That flaky problem you had with your knob is going to come back later. The new knob will eventually develop that flakyness and need to be replaced again. My replacement knob is... hmm... possibly close to 7-8 years old now and it's getting flaky again.
I'm pretty sure the issue is that the debouncing code necessary to smooth out the flakiness is going to limit the knob speed. The more you want the debouncing code to compensate for the flaky, the slower your top scroll speed will be. It's a trade-off.
Someone more familiar with the debounce code should be able to confirm ore refute my statement above...
|
Top
|
|
|
|
#351473 - 10/04/2012 20:29
Re: Knob speed limitations?
[Re: tfabris]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I hope the replacement knob lasts a bit longer... The metal part that supports the shaft is longer, and I believe the rated cycles were higher too. I got a slightly different Alps model than it came with originally.
But yeah I get what you're saying. If it weren't so darned tight in there I could fit a better encoder, but I haven't seen much that will fit.
If the debounce were programmable, perhaps I could reduce it now and then bump it up when the knob starts to wear out.
|
Top
|
|
|
|
#351474 - 10/04/2012 23:24
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
If the debounce were programmable, perhaps I could reduce it now and then bump it up when the knob starts to wear out. It is programmable, probably in two different places within the kernel. First would be in the knob driver code itself. I don't know much about that. Second, is in the "Hijack" kernel enhancements, where I added extra debounce logic for Hijack v96 about a decade ago. So, if you click on the "Hijack" link at the top of this page, and then scroll down to the v95-v96 patch link, and look at that specific patch, you may be able to see how that part works. Specifically pay attention to anything with " delayed_rotate" in the name. Cheers!
|
Top
|
|
|
|
#351481 - 11/04/2012 04:54
Re: Knob speed limitations?
[Re: presslab]
|
veteran
Registered: 01/10/2001
Posts: 1307
Loc: Amsterdam, The Netherlands
|
I'm working on some knob velocity dependant code for my SqueezeSlave impementation. Any hope of having your implementation also run on a rio receiver?
|
Top
|
|
|
|
#351491 - 11/04/2012 12:30
Re: Knob speed limitations?
[Re: tfabris]
|
old hand
Registered: 17/01/2003
Posts: 998
|
Hopefully my recent replacement will last a lot longer since it is rated at one million cycles rather than 15k. Thread - New Encoder Thread
|
Top
|
|
|
|
#351492 - 11/04/2012 12:40
Re: Knob speed limitations?
[Re: Redrum]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Specifically pay attention to anything with "delayed_rotate" in the name. Thanks for the tips! I will check this out when I get time. Any hope of having your implementation also run on a rio receiver? I'm not sure if the Rio Receiver has enough CPU. I see about 50% utilization on the empeg (IIRC) when playing high bitrate stuff. The RR CPU is a lot slower. I remember when I played around with SlimRio that I had to reduce the sampling rate or else it would cut out. The support for empeg is in the SqueezeSlave trunk so you can download the source and give it a shot. Hopefully my recent replacement will last a lot longer since it is rated at one million cycles rather than 15k. I think I have the same encoder as yours, just the through-hole version. I needed to cut down the shaft as you did as well.
|
Top
|
|
|
|
#351497 - 11/04/2012 15:19
Re: Knob speed limitations?
[Re: presslab]
|
old hand
Registered: 17/01/2003
Posts: 998
|
I think I have the same encoder as yours, just the through-hole version. I needed to cut down the shaft as you did as well.
The description says through-hole but that is incorrect and they sent me the surface mount type. No big deal as I just mounted it on the holes. It was actually pretty easy to solder. I can definitely tell the quality is way better than the old one. I would encourage anyone to get this part number for either type of mounting Mine sticks up a little farther than before but it doesn’t look bad and I like it better since it is easier to grab.
|
Top
|
|
|
|
#351498 - 11/04/2012 16:50
Re: Knob speed limitations?
[Re: presslab]
|
veteran
Registered: 01/10/2001
Posts: 1307
Loc: Amsterdam, The Netherlands
|
I'm not sure if the Rio Receiver has enough CPU. I see about 50% utilization on the empeg (IIRC) when playing high bitrate stuff. The RR CPU is a lot slower. I remember when I played around with SlimRio that I had to reduce the sampling rate or else it would cut out.
Ah, yes. Wonder if it would actually have an easier time with wav instead of mp3 - more data to process, but less processing to do.
|
Top
|
|
|
|
#351742 - 23/04/2012 03:42
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 19/05/1999
Posts: 3457
Loc: Palo Alto, CA
|
It does have speed limitations as it encodes knob rotations as pulse trains... All the actions of the front panel buttons and rotary control are sent to the CPU as pulse trains, just as consumer IR is (and on the same pin, in fact). This means there is a limitation on max number of rotation events per second. No idea what that limit might be, though someone with a scope could likely tell you. Sorry
|
Top
|
|
|
|
#351773 - 24/04/2012 18:23
Re: Knob speed limitations?
[Re: altman]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Thanks Hugo! That's the key info I was looking for. I'll probe around with my scope to see what the period is for those IR commands. If it can be faster than what I'm seeing, maybe I could poke around in the kernel driver.
|
Top
|
|
|
|
#360935 - 31/01/2014 21:57
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Well I've decided to do something about the speed limitation. Looking in the kernel source, it accepts a wide range of IR periods. So I figured I could speed up the IR pulse train and see what happens. I don't have the code for the PIC chips, and they're probably code protected so I can't read it out. But I *can* change the clock frequency. They run at 20 MHz, but I see the some newer revisions of the PIC16C54C can go all the way to 40 MHz. These old chips aren't rated to 40 MHz but they use the same fab process, so... It works! The knob is much more responsive, and no glitching. But the display dimmer is fudged up because that same PIC decodes a pulse train for the dimmer function. Running at 32 MHz works fine, however. But at 40 MHz the knob really shines and at 32 MHz, while much better than 20 MHz, still misses steps when going fast. Maybe I can convince Mark Lord to add in a custom feature for me in Hijack to change the timing to work with the button control PIC at 40 MHz. <wink, wink> I could provide a patch...
|
Top
|
|
|
|
#360940 - 01/02/2014 14:25
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Thanks for having a look! Here's the patch, it's untested as my crosscompiler isn't working... But I think it will work, save any typos.
Attachments
hijack_hispeed_button_pic.patch (336 downloads)
|
Top
|
|
|
|
#360944 - 02/02/2014 01:23
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Mmm.. I'd prefer if it didn't needlessly clone/duplicate so much code. Kernel (Hijack) RAM is locked in place, and thus subtracts from that available to the player app. Best to not waste it.
|
Top
|
|
|
|
#360945 - 02/02/2014 01:36
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I couldn't see a better way to do it without affecting the existing timing. Any thoughts?
|
Top
|
|
|
|
#360946 - 02/02/2014 14:13
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Wow.. I see what you mean. That code is soooo sensitive..
It really ought to be redone in assembly, so we can control the timing and be free from the whims of gcc.
|
Top
|
|
|
|
#360947 - 02/02/2014 14:28
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
(EDIT: superseded by v4 further on below)
Edited by mlord (02/02/2014 18:01)
|
Top
|
|
|
|
#360948 - 02/02/2014 14:30
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
It would be most helpful if you could put the before/after for a 20Mhz PIC onto a scope and verify that the timing is (darned close to) the same.
Thanks.
|
Top
|
|
|
|
#360949 - 02/02/2014 14:38
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Sure, if you can send me a kernel with your new code I'll take before/after shots on my scope. I'll need to figure out what pin this is on the ribbon cable, if anyone knows it would save me some time...
Thanks for the help Mark.
|
Top
|
|
|
|
#360950 - 02/02/2014 14:51
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Sure, if you can send me a kernel with your new code I'll take before/after shots on my scope. Great. Here's the zImage (NUKED.. v4 now available below). I think the IRRX data is on pin-10 of the ribbon connector. Not 100% sure though.
Edited by mlord (02/02/2014 18:02)
|
Top
|
|
|
|
#360951 - 02/02/2014 15:33
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
|
Top
|
|
|
|
#360952 - 02/02/2014 16:30
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I've taken some before/after measurements, and it's very close. But in "hispeed" there is a bug, the "high" timing isn't affected, this here:
/* Inter-bit delay */
udelay(15);
and here
/* End of transmission, line low */
GPCR=EMPEG_DISPLAYCONTROL;
udelay( (sendcontrol_busy == 1) ? 5 : 40 );
If you can fix that I'll take the measurements again. Also, to get Hijack to read config.ini I need to start the player. Well with my player replacement it doesn't read config.ini so Hijack doesn't parse it. Is there a way to do this without running player? I tried "cat config.ini" and Hijack didn't bite. edit: I've worked around the config.ini issue. I backed up the original, copied cat to /empeg/bin/player, and put player /empeg/var/config.ini in the init script. :P Thanks!
Edited by presslab (02/02/2014 17:32) Edit Reason: added player workaround
|
Top
|
|
|
|
#360953 - 02/02/2014 18:00
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Okay, try this one (zImage attached).
--- hijack/arch/arm/special/empeg_display.c.orig 2008-06-04 13:17:32.000000000 -0400
+++ hijack/arch/arm/special/empeg_display.c 2014-02-02 14:56:11.467315647 -0500
@@ -879,11 +879,13 @@
static int sendcontrol_busy = 0;
static unsigned long sendcontrol_timestamp = 0;
extern unsigned long jiffies_since(unsigned long);
+extern int hijack_hispeed_button_pic;
-int display_sendcontrol_part2(int b)
+int display_sendcontrol_part2(unsigned char b)
{
- int bit;
+ unsigned char bit;
unsigned long flags;
+ unsigned int inter_bit_delay = hijack_hispeed_button_pic ? 7 : 15;
/* Send a byte to the display serially via control line (mk2 only) */
if (empeg_hardwarerevision()<6) return 0;
@@ -896,30 +898,33 @@
save_flags_clif(flags);
/* Send 8 bits */
- for(bit=7;bit>=0;bit--) {
+ for (bit = 0x80; bit; bit >>= 1) {
/* Set line low */
GPCR=EMPEG_DISPLAYCONTROL;
/* Check the bit */
- if (b&(1<<bit)) {
+ if (b & bit) {
/* High - 15us of low */
- udelay(15);
+ udelay (inter_bit_delay);
} else {
/* Low - 2us of low */
- //udelay(1);
- { int a; for(a=0;a<50;a++); }
+ int a, delay = hijack_hispeed_button_pic ? 22 : 50;
+ for (a = 0; a < delay; a++);
}
/* Set line high */
GPSR=EMPEG_DISPLAYCONTROL;
/* Inter-bit delay */
- udelay(15);
+ udelay(inter_bit_delay);
}
/* End of transmission, line low */
GPCR=EMPEG_DISPLAYCONTROL;
- udelay( (sendcontrol_busy == 1) ? 5 : 40 );
+ if (hijack_hispeed_button_pic)
+ udelay( (sendcontrol_busy == 1) ? 2 : 20 );
+ else
+ udelay( (sendcontrol_busy == 1) ? 5 : 40 );
/* Reenable IRQs */
sendcontrol_busy = 0;
--- hijack/arch/arm/special/hijack.c.orig 2011-07-20 06:22:58.000000000 -0700
+++ hijack/arch/arm/special/hijack.c 2014-02-01 08:12:48.163697927 -0800
@@ -548,6 +548,7 @@
//
static int hijack_buttonled_off_level; // button brightness when player is "off"
static int hijack_buttonled_dim_level; // when non-zero, button brightness when headlights are on
+ int hijack_hispeed_button_pic; // 1 == change timing to work with a 40 MHz button PIC
static int hijack_dc_servers; // 1 == allow kftpd/khttpd when on DC power
static int hijack_decimal_fidentry; // 1 == fidentry uses base10 instead of hex
int hijack_disable_emplode; // 1 == block TCP port 8300 (Emplode/Emptool)
@@ -665,6 +666,7 @@
//=========================== ========================== ========= ======= === ================
{"buttonled_off", &hijack_buttonled_off_level, 1, 1, 0, 7},
{"buttonled_dim", &hijack_buttonled_dim_level, 0, 1, 0, 7},
+{"hispeed_button_pic", &hijack_hispeed_button_pic, 0, 1, 0, 1},
{"dc_servers", &hijack_dc_servers, 0, 1, 0, 1},
{"decimal_fidentry", &hijack_decimal_fidentry, 0, 1, 0, 1},
{"disable_emplode", &hijack_disable_emplode, 0, 1, 0, 1},
Attachments
zImage.pic (435 downloads)Description: faster PIC v4.hijack_hispeed_button_pic_v4.patch (306 downloads)Description: v4 of the patch.
|
Top
|
|
|
|
#360962 - 07/02/2014 19:59
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Well, after using it for a week I think I need to try a different approach. Occasionally it misses keypresses, and worst of all sometimes it misses the keyup code so the buttons "stick". I guess this is because the interrupt jitter is too high due to the non-realtime nature of Linux. The IR decoding is done by the CPU (and not dedicated hardware) and it just can't go that fast reliably. It seems to glitch more when accessing the drive which makes sense. So my next attempt is to read the object code out of the PIC chip. I've desoldered it and I'm waiting on an adapter for my programmer. I've also researched ways to crack code protection, but there's great risk I smoke the chip. I don't want to end up with a bricked empeg. But worse comes to worst I can just code up everything new and replace it with a PIC16F54. Once I have the code, I have some ideas on how to modify it. Like queue up knob codes for one, so the IR doesn't need to go as fast. Or make the knob transmit at the fast rate but not the buttons. Anyway I think there's room for improvement in the PIC.
|
Top
|
|
|
|
#360963 - 08/02/2014 00:31
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Perhaps you just need to make similar timing adjustments inside empeg_input.c? The patches above are just for outbound commands (from ARM to the display), rather than also including timing changes for the IR input stuff?
A starting point for that might be input_buttons_interrupt() inside arch/arm/special/empeg_input.c
|
Top
|
|
|
|
#360970 - 09/02/2014 14:05
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I looked at that for a while, but I didn't see anything obvious that could help. empeg_input.c accepts a range of 50us to 550us IR period. With a 20 MHz oscillator the PIC puts out a 500us period and at 40 MHz it's 250us, still well within range.
I can't tell specifically where it's failing but when I look at /proc/empeg_ir I see the "Missed interrupts" counter increase every time the button glitches.
|
Top
|
|
|
|
#360972 - 09/02/2014 15:24
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Without having looked much at the code, I really doubt that it can reliably cope with a 50% reduction in the bit intervals, not without some timing adjustments to match.
|
Top
|
|
|
|
#360973 - 09/02/2014 15:29
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
I wonder what would happen if you simply tried this brute force approach:
Change this line:
span = interrupt_time - last_interrupt;
into this:
span = 2 * (interrupt_time - last_interrupt);
|
Top
|
|
|
|
#360989 - 13/02/2014 20:14
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Thanks for the idea, but I don't think it will do anything. The unit_time is calculated from the span during the preamble. When it's evaluating subsequent bits, it compares the span to some ratio of unit_time... Multiplying by two would would make span and unit_time both double so it would work the same.
Good news though! I've been able to read the PIC chip; it had no CP. (Thanks, guys!) The chip is pretty much full so I'm going to go with a larger flash PIC. Using IDA Pro I've got a disassembly that re-assembles to identical object code. I've identified most of the interesting bits, too. I'll order some new chips and see if works using the old code.
The new PIC will have interrupts for the rotary encoder inputs. This will allow me to make an interrupt-driven up/down counter. Then in the main loop I can modify it to send the appropriate number of IR pulses to match the internal counter. In this way it will "buffer" the encoder steps.
|
Top
|
|
|
|
#361000 - 16/02/2014 14:47
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
I've got the PIC code modified and tested it in the MPLAB simulator. It uses the TMR0 interrupt to poll the encoder, and can queue up to 64 knob steps (about two rotations). Hopefully this doesn't affect the IR period timing too much; if it does I can convert that code to use a different timer.
The new PIC chips will be here in a couple days and then I can test it for real.
|
Top
|
|
|
|
#361004 - 16/02/2014 18:37
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 29/08/2000
Posts: 14493
Loc: Canada
|
Apart from a replacement PIC, what else is needed?
|
Top
|
|
|
|
#361005 - 16/02/2014 18:54
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
It's pin compatible and uses the same old clock of 20 MHz. Nothing special for the kernel. So yeah just swapping the PIC chip should be all that's needed.
There is the added difficulty of the VFD, it's above the PIC chip. But it's possible to pull it away and solder the new chip under it, and then push it back down with a bit of glue on the foam pads.
|
Top
|
|
|
|
#361009 - 17/02/2014 06:18
Re: Knob speed limitations?
[Re: presslab]
|
carpal tunnel
Registered: 20/12/1999
Posts: 31597
Loc: Seattle, WA
|
So, completely unrelated to SqueezeSlave, does the faster sampling rate fix the glitching that occurs on old worn-out knobs? I mean the general glitching that everyone who runs the stock Empeg software experiences when their knobs get old, as I mentioned at the top of the thread and also here in the FAQ. Does it magically improve the knob sampling so that aging knobs don't confuse the debouncer as much?
|
Top
|
|
|
|
#361025 - 17/02/2014 19:35
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Well, I would think the better sampling would be more immune to noise. The old code was a kind of state machine, and it would be deaf to the encoder when it was transmitting the IR bits. I didn't really analyze all the old encoder code as I was replacing it anyway and it's unusually complex. Not to mention that I am looking at a disassembly of it with no comments. But I suspect that because the old code wasn't always listening to the encoder, it would try to 'infer' the count direction if something happened while it was deaf. The new programming is pretty simple. It compares the 'new' A phase to the old 'A' phase, and if they are different it counts. The direction of counting is determined by which way 'A' changed and also the state of 'B' phase. It's important to note that it doesn't look at the transition of 'B', as this transitions at the detent. If it happens to sample 'A' when there is noise, no matter, as worst case it will be correct a couple milliseconds later. Here's the new ISR code for the curious: http://pastebin.com/0nMEFgAZAs far as I can tell there's no hardware debounce. So it wouldn't hurt to throw a couple small 0.01uF caps across the encoder leads if one has a unit with a flaky encoder. This could actually improve the lifetime of an encoder as the current from discharging the caps will have a cleaning action ("wetting") on the encoder contacts. So in conclusion, it could be a lot better with the improved PIC, and won't be worse, I hope.
|
Top
|
|
|
|
#361059 - 19/02/2014 20:31
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Has anyone noticed "stuck" keys or an ignored keypress with the stock software? I recently put Squeezeslave into the Empeg in my Subaru, but before that it was all stock. I noticed sometimes it seems it wouldn't respond when I pushed the next track button, and very rarely it would get a "stuck" key (in the software sense, nothing with the button itself). In the old PIC code it sends the keyup code twice. I think this is because it was a known problem, and a stuck key is much more annoying than a missed tap. I'm playing around with doing keyup (as well as keydown) codes more than twice, to fix it with brute force. The new PIC is in and it works. It's really nice actually. You can see that it queues the knob rotation, but it's not obtrusive. http://www.youtube.com/watch?v=uB3Is5rhpRwI'm going to play with it this week to see if it needs any tweaks here or there.
|
Top
|
|
|
|
#361082 - 20/02/2014 22:12
Re: Knob speed limitations?
[Re: presslab]
|
journeyman
Registered: 29/07/2008
Posts: 73
Loc: North Bay, CA
|
Well, pin 2 is certainly the pin of interest. It's the one that carries the IR pulses to the StrongARM.
But it doesn't seem like a cold solder joint to me. I've seen it on all three of the empegs I have, albeit two of those have been running Squeezeslave. I suspect the use of the Ethernet port causes more jitter in the IR interrupt. I'll have to wait and see if my "brute force" approach fixes this problem when using Squeezeslave.
So far so good on the commute to/from work today. If anyone genuinely wants a PIC of their own (and promises to actually install it) I could be convinced to throw one in the mail.
|
Top
|
|
|
|
|
|