The pin contention issue is due to both the DMD and USB Host chip (MAX3421E) using Arduino digital pin 9.
When pin 9 is low the DMD doesn't display anything on the LEDs.
The USB Host chip (and shield) connects pin 9 to its output that indicates when an interrupt needs to be processed. Once a device is connected pin 9 spends most of its time low in this situation.
Thus, as soon you connect the USB device the display goes blank. Not very handy.
According to the USBDroid schematic it's possible to use Arduino digital pin 3 as an alternative connection for
USB_INT with a solder jumper. I may look at doing that--although this will also require modifying the USB Host library. And I've got enough variations of that to keep track of as it is...
According to the MAX3421E datasheet (page 5):
In edge mode, the logic level on INT is referenced to the voltage on VL and is
a push-pull output with programmable polarity.
In level mode, INT is open-drain and active low.
Set the IE bit in the CPUCTL (R16) register to enable INT.
I tried to disable the interrupt but it's actually used in the USB Host Shield library--which I'd thought it wasn't. For some reason I thought the library just polled the chip but apparently it doesn't.
Since I'm not a real EE (and can't really parse the sentence) I'm not sure if "edge mode" would allow us to fix the problem. (Oh, actually, looking at the additional explanation on page 17 it might actually help a bit--it seems it turns the interrupt into a pulse? So, in theory, you might be able to see if you can trigger a pin change interrupt on pin 9 but have the pulse be short enough that it doesn't screw with the DMD. This would require a modification of the USB Host Shield library though--it might be slightly "transparent" though. Either way, too much hassle, it seems...)
(Oh, and here's the MAX3421E
Anyway, as a result of all that I started working an Arduino Mega ADK board instead. This doesn't have the pin contention issue because it uses a non-broken out pin for INT instead of pin 9.
The downside is that the SPI pins are in a different location so you can't use the DMDCON connector board directly. You need to wire it up differently.
[TODO: Add wiring description. In the interim see this.]
I needed to make some modifications to the DMD library also, so first I forked it in the GitHub UI and then cloned it locally with:
hg clone git+ssh://email@example.com:follower/DMD.git
(Oh, yeah, I'm using the
hg-git Mercurial plugin as per usual. :) )
Then I linked it into the Arduino
libraries directory with:
ln -s /<path>/DMD
First change is to make the default "other" chip select pin (in order to avoid clashes) to a Mega appropriate value:
#define PIN_OTHER_SPI_nCS 53
Even with the above change there was still major flickering, even if I modified how the sketch worked.
It turned out this mostly went away by increasing the speed of the SPI clock (which makes sense). Presumably this affects both the DMD speed and the USB host chip communication speed.
Fortunately I didn't need to figure that all by myself, I just cherry-picked the change from (1, 2):
Created a new repository for the
sms-text-scroller project. Amazingly I didn't pick an awesome name like "cinnamon-scroll" for the project. Maybe later.
As an aside: while I was working on this the other day I encountered an error when I tried to build the newly imported Android project:
Error generating final archive: Debug Certificate expired
Apparently this means it's my Android development birthday or something... :)
This is caused by the debug certificate being created with a lifetime of only one year. The solution is to delete the debug certificate to force a new one to be created. (I saw some comment that this means user data associated with the app won't be preserved but I haven't tested this.)
The location of the debug keystore is platform dependent:
Delete your debug certificate under
~/.android/debug.keystore on Linux and Mac OS X;
the directory is something like
%USERPROFILE%/.android on Windows.
Doing this on the command line from my home directory was enough for me on OS X:
Then you need to force a rebuild of the package--doing a
Run > Run from the menu should be enough.
This was considered a bug (Issue: "Debug keystore should not expire or automatically be regenerated") and has apparently been fixed (Patch: "Make debug key expire in 30 years (instead of 1)") but I didn't check to see if this was the case with what I'm using. Guess I'll find out in a year or thirty.
I was working to get things working for the evening of Sat 19th (NZ time) but noticed an issue during the afternoon that stopped much in the way of new feature development.
At a certain point (I think it was when I increased the scroll delay from 10ms to 30ms) I realised there was a point at which the scroll resulted in a "shimmer" that soon made it painful to watch.
I managed to reduce the shimmer by adding this to
stepMarquee just before the bits are moved:
while(bDMDByte != 0);
This causes the movement to wait until the beginning of the "frame".
But while this removes the shimmer, at certain speeds it makes it very obvious that the display is refreshed in 4 steps, as each step is offset by 1 LED (most noticable on an
l for example):
I played around with a bunch of solutions (including trying out the latest code from cjd) but as I hadn't fully grokked how things were working (and was feeling the time pressure :) ) it was a bit hit and miss.
In the end I tried to get some sort of double-buffering working but that didn't seem to have as much impact as I expect. In the end the combination of that code and increasing the rate at which the scan routine was called provided adequate results.
Originally the scan code was called every 5 milliseconds and I reduced the delay to 2.5 milliseconds. Any more frequent seemed to result in long SMS messages losing characters from them as they were read from the phone.
Once I had the the display working okay I added a couple of features:
One permanent message (hardcoded into the sketch) to display.
Four "slots" used to store the last four SMS messages received. When a new message is received the oldest message is overwritten. (The display order doesn't change however--i.e. the message in slot 1 is always displayed after the permanent message, even if it's not the most recent/oldest.)
And, then, I rushed to the venue location. :)
Overall the device was trouble-free on the night. Once things were connected it worked without needing to be fiddled with--which is a pretty good result.
These first two images show the display located on the speaker stack by the side of the stage. This provided good visibility--and to my relief the vibration of the speakers wasn't enough to walk the sign over the edge:
Here you can see the sign to the right of the stage--it was visible but without being in the main line of sight for people looking at the band onstage:
[big] [big] [big]
When the messages people texted were displayed they were preceeded with the last 3 digits of their phone number:
Incidentally, I greatly recommend having project demo photographs taken at a Latin dance evening--it makes them look a lot more interesting than the average. :)
[TODO: Insert construction pictures.]
People who used it seemed to like it but I did wonder if it was not totally obvious that you could actually text to the sign--and not have it cost you anything more than a normal text (which could be nothing for those on plans). (Also, thanks to incoming texts being free in NZ there was no need to do anything other than buy a SIM and chuck it in the phone.)
Then again maybe most people were too busy actually dancing. :)
We'll see what happens next time it gets an outing...
The code on my DMD@7a6cbfb1c2 and sms-text-scroller@c55eb16b97 repositories is what I used but I also used a version of
AndroidAccessory library which is not currently public (and also modified to have
int read(void *buff, int len, unsigned int nakLimit = 1)) so I'm not sure how difficult it would be for people to get things running out of the box...
But it will do for now. :)