Hmm... I'm using UCN5821 driver chips from Allegro. They do indeed have a
hardware latch (strobe) which latches the received serial data from the
internal shift register to the outputs.
My write algorithm is (per row):
For state 2, I'd be tempted to do a non-interruptible write to the
display memory (or protect it by a semaphore). You want to interlock
the process so that you have a safe zone to write new data to the
2> If new data is ready in RAM, memcpy it to the real display buffer in RAM.
This should not cause a problem unless the data changes somehow.
3> Serially shift out next row data in the background, but do not latch yet
This may be too fast for you to see, and you don't want it slow.
4> Blank the display - This is not actually working right now. I never see
the blank line move. Hmm....
I'm assuming you have the data for the new row in the buffer, of
5> Adjust the multiplexed row select pins to the next row (A2...A0)
6> Latch the data already in the serial buffers
Problem with blanking and unblanking the whole display could cause
7> Unblank the display
9> usleep until time to update next row
I wanted to spend a little time as possible with the LEDs off, which is why
I'm shifting data while the LEDs are still showing the current row data.
That shouldn't be a problem at all, the chip is designed for it.
Using this technique, I've seen ghosting issues when a mcu is very fast as
the drivers themselves need a little time to switch the state of their
outputs, and also the high-side switching power transistors sometimes need
some time to fully turn off. I don't think that's what I'm seeing here
Let's assume that it is a problem, so you can fix that.
The display artifacts that I see look like stuttering on the display when
the processor gets busy. I suspect that this is due to inconsistent usleep
times (Linux isn't an RTOS) but I'm still trying to catch it with my logic
I've had similar task interlocking problems with an RTOS, but I'd
suggest a slightly different approach.
My basic question is this: Does the Linux kernel "usually" do this kind of
bit-banged driver for other things (I2C, video, framebuffers, audio, etc.)
or does it "usually" pass these tasks off to hardware peripherals? The
question behind the question is: Am I doing this the "usual" way or am I
trying something very specialized.
Not an expert on Linux at all, but it depends on the data rates, and
whether or not there's hardware available to do it.
My goal is to look into the framebuffer devices and see if I can learn
anything there, but kernel programming is very new to me.
Kernel programming (for microprocessors) is not all that bad, but
there are things you probably don't think of when writing kernel level
drivers and code.
1) everything is asynchronous
2) this can be inconvenient
3) lots of mechanisms exist to keep this from happening
I'd be tempted to do the following approach: Divide the scan time
into one slot per digit plus one. Use that time to allow synchronized
refresh to the display itself. You may need to limit the on time
depending on your sink current (per driver's data sheet).
Assuming you use a semaphore, then while actively scanning digits, the
scanning process "owns" it. During the update time, the scanning
process gives it back. The update process can grab that, then can
update all the ram buffers that the scanning process uses. The update
process then gives back the semaphore and the scanning process can
grab it again during the next scan time. Result: display does all RAM
updates while blanked.
Now for the scan itself. Assuming the scan time has just happened,
you may want to disable task switching. shift in the new data, switch
the row drivers off, then latch the column data, then enable the new
row drivers. Since darlingtons are slow, I'd be looking at the
driving waveforms for the darlington outputs to the display for any
overlap. Shouldn't be much, though, if any. Some software delays of
a few microseconds may be needed. At this point, enable task
switching for the OS and you're in good shape.
The problem with multiplexed displays run directly by a microprocessor
is debugging during the scan cycle, where the average display current
can exceed the steady state limits for the display. I'd have been
tempted to put in a small CPLD which appears as external registers to
the processor, and then allow the hardware to do all the work. Xilinx
coolrunner II 32 or 64 cell chips are cheap, 3.3 volt I/O, and need
(IIRC) 1.5 volts. Not too bad and the display stays happy.