On Mon, 21 Mar 2016 11:16:49 -0500, you wrote:

>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):
>1> set_current_state(TASK_RUNNING)

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
memory.
>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
>(background)

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
course,

>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
flicker.
>7> Unblank the display
>8> set_current_state(TASK_INTERRUPTIBLE)
>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
>though.

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
>analyzer.
>

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.

Harvey
 
>
>Thanks for your feedback!
>
>--David
>
>
>On Mon, Mar 21, 2016 at 9:40 AM, Harvey White <[email protected]>
>wrote:
>
>> On Mon, 21 Mar 2016 01:20:34 -0500, you wrote:
>>
>> I've often seen artifacts in LED displays where the write to the
>> display process (which should be amazingly short for each digit) is
>> interrupted.  You might be seeing some differences in digit brightness
>> as well.
>>
>> Once you have the pattern in Ram, ready to be written, you would
>> ideally update right at the beginning of each scan for each digit. You
>> want to make sure that the pattern is not updated during the active
>> strobe to display process as well.  (I'm assuming that there's a
>> hardware latch in there that you write, and you're not depending on
>> the output pins to be constant, that strobe to activate the display is
>> also a latch).  This approach would minimize the critical time where
>> the display data cannot be interfered with.  This would ideally be in
>> the microsecond range (i.e. turn off previous strobe, load next data,
>> turn on this strobe).  That part of the code cannot be interrupted and
>> should ideally protected by turning interrupts off during those few
>> instructions.
>>
>> So the first question to ask is "what's going on with the strobes and
>> data?"
>>
>> Harvey
>>
>>
>>
>> >Ok, I posted the full source code here:
>> >https://github.com/davidgood1/ledmsgchar
>> >
>> >I'm not sure that userspace has much to do with what I'm seeing right now.
>> >I'm using a kthread that runs until a flag is set indicating that there is
>> >a new buffer of data ready from user space and my task (update_row) copies
>> >the buffer, so no one should be waiting on slow user space operations, but
>> >maybe there's something I don't see.
>> >
>> >I didn't know if I was getting interrupted in the memcpy call in
>> >update_row, so I am going to try to copy the buffer by rows one call at a
>> >time rather than copy the whole buffer at once.
>> >
>> >Also, I notice that I see visual artifacts whenever anything else is going
>> >on, such as ssh, typing on the terminal, etc.  The CPU usage is ~3% using
>> >the timing in the file right now.  BTW, the update_row task regulates its
>> >timing by calling usleep_range() which is supposed to be backed by high
>> >resolution timers.  I am using the same number on the upper and lower
>> >bounds to try and force stricter timing and because when I did +/- 10% you
>> >could definitely see more visual artifacts.
>> >
>> >Also, you will notice that the strobe pin is toggled high and then
>> >immediately low, which I've measured to be about 2us.  So, that seems to
>> be
>> >the best the gpio interface can do.
>> >
>> >Thanks!
>> >
>> >--David
>> >
>> >On Sun, Mar 20, 2016 at 11:03 PM, William Hermans <[email protected]>
>> wrote:
>> >
>> >> OK so yes, seeing your code would help us understand what you're
>> >> bottleneck but I've a pretty good idea why you're LCD matrix refresh is
>> so
>> >> slow. It has to do with userspace communicating with kernel space, and
>> >> you're either invoking some system API calls ( which are notoriously
>> slow
>> >> ), or you're copying data from userspace to kernel space, which again is
>> >> slow.
>> >>
>> >> The reason I said to show us some code above however is that I think it
>> >> *should* be possible to use /dev/mem/ + mmap() to access whatever you're
>> >> controlling. Using mmap() in this manner gives you no userspace to
>> kernel
>> >> overheard . . . but again I need to see some relevant code to give you a
>> >> better idea how that might work.
>> >>
>> >> On Sun, Mar 20, 2016 at 8:58 PM, William Hermans <[email protected]>
>> >> wrote:
>> >>
>> >>> Show us some code.
>> >>>
>> >>> On Sun, Mar 20, 2016 at 6:28 PM, David Good <[email protected]>
>> >>> wrote:
>> >>>
>> >>>> Hi All,
>> >>>>
>> >>>> I've been experimenting with embedded linux and matrixed LED displays.
>> >>>> I started on a Raspberry pi user space program, but could see visual
>> >>>> artifacts on the display due to inconsistent timing of my sleep
>> command.
>> >>>> So, I figured that moving the basic row scanning into the kernel
>> would help
>> >>>> out.  After failing to get the right kernel headers for the pi, I
>> switched
>> >>>> to a BeagleBone White.  I've now got a working character device LKM
>> which
>> >>>> takes new images by writing ASCII formatted hex strings to the device
>> in
>> >>>> /dev.  The performance is pretty good, but not great.  I still see
>> visible
>> >>>> artifacts, but am playing with things.
>> >>>>
>> >>>> My basic question is this: I know that Linux is not a RTOS, so timing
>> >>>> will never be guaranteed, yet linux does a lot of things very quickly
>> >>>> (video, audio, i2c, etc).  My driver is bit-banging a spi like stream
>> over
>> >>>> 8 rows at a rate of ~3ms per row (333Hz row scanning or ~41Hz per
>> complete
>> >>>> frame) and is really struggling.  How does linux usually get large
>> smooth
>> >>>> video at over 60FPS while doing other things???  Is it simply taking
>> >>>> advantage of special hardware resources?
>> >>>>
>> >>>> The obvious solution for this display is to use a little 8051 or M0
>> >>>> microcontroller (or PRU!) and let the Bone feed it over uart or
>> something,
>> >>>> but I really thought I could do better with the LKM.
>> >>>>
>> >>>> Am I just doing something totally wrong?  Any other ideas?
>> >>>>
>> >>>> Thanks!
>> >>>>
>> >>>> --David
>> >>>>
>> >>>> --
>> >>>> For more options, visit http://beagleboard.org/discuss
>> >>>> ---
>> >>>> You received this message because you are subscribed to the Google
>> >>>> Groups "BeagleBoard" group.
>> >>>> To unsubscribe from this group and stop receiving emails from it, send
>> >>>> an email to [email protected].
>> >>>> For more options, visit https://groups.google.com/d/optout.
>> >>>>
>> >>>
>> >>>
>> >> --
>> >> For more options, visit http://beagleboard.org/discuss
>> >> ---
>> >> You received this message because you are subscribed to the Google
>> Groups
>> >> "BeagleBoard" group.
>> >> To unsubscribe from this group and stop receiving emails from it, send
>> an
>> >> email to [email protected].
>> >> For more options, visit https://groups.google.com/d/optout.
>> >>
>>
>> --
>> For more options, visit http://beagleboard.org/discuss
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "BeagleBoard" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to