Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
David, William's suggestion of the PRU is a really good one. I know there are examples on the forum for using them - even though I personally haven't looked at them. You should be able to do everything inside the PRU - You only need 144 bytes per buffer (assuming 1 color / 1 bpp). So even having multiple buffers shouldn't be an issue. You should even still be able to leverage the SPI interface if desired. I understand that bit-banging via the PRU is much more efficient than even bare metal inside the CPU. The UNC5821 driver has a much simpler interface than the ws28xx serial lighting chips. It's an old retired chip that is essentially a shift register and a latch. Which makes it quite suitable for SPI as you really only need clk and data to send info to it. It's also not as timing dependent - 800KHz - 1 wire timing. These parts are also forgiving if you get word boundary bound that you can always just push extra data through the chain - leaving valid data in the register behind it. So for instance if you end up having to do 32-bit xfers into a 144 bit chain, you can shift out 160 bits (5 xfers) and just have the 1st 16 bits be don't care. The remaining 144 will remain in register and get xfer'd when latched. This is a fairly high power chip - haven't looked to see if there is a new version for new designs - so I'm expecting that you (David) must be recycling an old display. If not, there are a bunch of similar chips out there - most are 16-bits wide - see TI, ST Micro, Silicon Touch, Macroblock, Toshiba... Good Luck, Matt On Tuesday, March 22, 2016 at 12:12:31 AM UTC-5, William Hermans wrote: > > The way I see it is that you have two options. You could use the PRUs, or > you could use the McSPI hardware module. I would attempt to help you but I > really do not have any experience with the ws28xx style serial protocol > that many seem to use with external lighting of this type. > > I can tell you that a very simple, and cheap msp430g2553 project would be > more that enough to do all this - bare metal. So no needs for a cpld or > FPGA or anything fancy like that. But again as mentioned by Matt above, you > have to design a PCB, + circuit and the costs add up despite the fact that > a G2553 is only about $2-$3 sold as singles. > > Anyway, maybe someone here knows the McSPI module well enough to comment > on "shifting out" data to your matrix ? As in actually knowing what they're > talking about . . . > > How does this buffer work anyhow ? Is this like a bit field in both > dimensions, or what ? Kind of hard to grasp on a simple code glancing ;) > > On Mon, Mar 21, 2016 at 4:36 PM, David Good> wrote: > >> Yes, I would love for someone to give me tips on setting up a periodic >> timer interrupt. What I have might be the only way to really do it, but I >> would assume not. >> >> Thanks for your tips on ghosting. I will use it when I start to see real >> data in the buffers rather than my simple test patterns. >> >> About using SPI. Yes, this is what I was doing on the Raspberry Pi, but >> haven't done it on the Beaglebone yet. I will definitely give it a shot. >> Bit banging the clock and data looks like it's costing me ~1ms per row as >> currently implemented. >> >> On the topic of dedicated hardware offloading the workload, I suppose >> that this is exactly what the PRUs are designed for. Perhaps it's time to >> say Hello World to one of them. Since this is a personal project, there >> aren't any real design requirements, so any option is open to me right >> now. I was planning to layout a PCB to clean things up a bit because right >> now I have a hand soldered perf board with ribbon cables :) >> >> Thanks for the suggestions! Let's see if someone can answer about a >> kernel timer interrupt. >> >> --David >> >> On Mon, Mar 21, 2016 at 6:07 PM, CEinTX >> wrote: >> >>> David, >>> >>> Without seeing your circuit of how you are setting up your rows & >>> columns to be driven, I'll take a blind stab at your issue. >>> To get rid of artifacts / ghosting / etc... >>> 1) Shift out all your data >>> 2) Turn off your drivers and row power if that is available >>> 3) Delay ~20us >>> 4) Latch the data into your drivers >>> 5) Delay ~20us or more >>> 6) Change your row address >>> 7) Enable your outputs and/or row power >>> >>> You must have some dead time between rows or you will get artifacts / >>> ghosting / whatever you choose to call it. >>> You might get away with less than 20us but also you might need more >>> depending on your circuit. >>> Too much dead time and you will get flicker - not enough and you guessed >>> it - artifacts/ghosting. >>> >>> For what it seems like you are doing, I'd use the SPI interface to shift >>> out your data in blocks of 16-bits - 9 xfers gets you 144 bits out. >>> You obviously could bit bang this but why when you have built-in >>> hardware that will do it for you. I'd think it
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
The way I see it is that you have two options. You could use the PRUs, or you could use the McSPI hardware module. I would attempt to help you but I really do not have any experience with the ws28xx style serial protocol that many seem to use with external lighting of this type. I can tell you that a very simple, and cheap msp430g2553 project would be more that enough to do all this - bare metal. So no needs for a cpld or FPGA or anything fancy like that. But again as mentioned by Matt above, you have to design a PCB, + circuit and the costs add up despite the fact that a G2553 is only about $2-$3 sold as singles. Anyway, maybe someone here knows the McSPI module well enough to comment on "shifting out" data to your matrix ? As in actually knowing what they're talking about . . . How does this buffer work anyhow ? Is this like a bit field in both dimensions, or what ? Kind of hard to grasp on a simple code glancing ;) On Mon, Mar 21, 2016 at 4:36 PM, David Goodwrote: > Yes, I would love for someone to give me tips on setting up a periodic > timer interrupt. What I have might be the only way to really do it, but I > would assume not. > > Thanks for your tips on ghosting. I will use it when I start to see real > data in the buffers rather than my simple test patterns. > > About using SPI. Yes, this is what I was doing on the Raspberry Pi, but > haven't done it on the Beaglebone yet. I will definitely give it a shot. > Bit banging the clock and data looks like it's costing me ~1ms per row as > currently implemented. > > On the topic of dedicated hardware offloading the workload, I suppose that > this is exactly what the PRUs are designed for. Perhaps it's time to say > Hello World to one of them. Since this is a personal project, there aren't > any real design requirements, so any option is open to me right now. I was > planning to layout a PCB to clean things up a bit because right now I have > a hand soldered perf board with ribbon cables :) > > Thanks for the suggestions! Let's see if someone can answer about a > kernel timer interrupt. > > --David > > On Mon, Mar 21, 2016 at 6:07 PM, CEinTX wrote: > >> David, >> >> Without seeing your circuit of how you are setting up your rows & columns >> to be driven, I'll take a blind stab at your issue. >> To get rid of artifacts / ghosting / etc... >> 1) Shift out all your data >> 2) Turn off your drivers and row power if that is available >> 3) Delay ~20us >> 4) Latch the data into your drivers >> 5) Delay ~20us or more >> 6) Change your row address >> 7) Enable your outputs and/or row power >> >> You must have some dead time between rows or you will get artifacts / >> ghosting / whatever you choose to call it. >> You might get away with less than 20us but also you might need more >> depending on your circuit. >> Too much dead time and you will get flicker - not enough and you guessed >> it - artifacts/ghosting. >> >> For what it seems like you are doing, I'd use the SPI interface to shift >> out your data in blocks of 16-bits - 9 xfers gets you 144 bits out. >> You obviously could bit bang this but why when you have built-in hardware >> that will do it for you. I'd think it would be fast enough in an ISR. I >> should think less than 250 us. >> Use the gpio for toggling your latch and output enable and addr/row >> select - these are low speed signals - so no problem >> There are definitely easier ways to do this with external hardware, but >> for this size matrix it would be a waste of $. Yes, a $1-2 cpld will do the >> trick - but then you need a pcb etc... >> Setup a periodic timer interrupt to sync your shifts / rows of data - >> take your refresh rate (suggest 55-80Hz to avoid flicker) & divide by # of >> rows (timer => 440 to 640 Hz / row) >> Use the time between interrupts to setup your next buffer for display >> >> Get someone here to help you with the timer/interrupt under Linux - I >> have no idea on that one. Would like to though - so maybe someone will >> respond with how to do that. >> >> Hope that helps. >> >> Good Luck, >> Matt >> >>> >>> -- >> 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 beagleboard+unsubscr...@googlegroups.com. >> 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 beagleboard+unsubscr...@googlegroups.com. > 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
Yes, I would love for someone to give me tips on setting up a periodic timer interrupt. What I have might be the only way to really do it, but I would assume not. Thanks for your tips on ghosting. I will use it when I start to see real data in the buffers rather than my simple test patterns. About using SPI. Yes, this is what I was doing on the Raspberry Pi, but haven't done it on the Beaglebone yet. I will definitely give it a shot. Bit banging the clock and data looks like it's costing me ~1ms per row as currently implemented. On the topic of dedicated hardware offloading the workload, I suppose that this is exactly what the PRUs are designed for. Perhaps it's time to say Hello World to one of them. Since this is a personal project, there aren't any real design requirements, so any option is open to me right now. I was planning to layout a PCB to clean things up a bit because right now I have a hand soldered perf board with ribbon cables :) Thanks for the suggestions! Let's see if someone can answer about a kernel timer interrupt. --David On Mon, Mar 21, 2016 at 6:07 PM, CEinTXwrote: > David, > > Without seeing your circuit of how you are setting up your rows & columns > to be driven, I'll take a blind stab at your issue. > To get rid of artifacts / ghosting / etc... > 1) Shift out all your data > 2) Turn off your drivers and row power if that is available > 3) Delay ~20us > 4) Latch the data into your drivers > 5) Delay ~20us or more > 6) Change your row address > 7) Enable your outputs and/or row power > > You must have some dead time between rows or you will get artifacts / > ghosting / whatever you choose to call it. > You might get away with less than 20us but also you might need more > depending on your circuit. > Too much dead time and you will get flicker - not enough and you guessed > it - artifacts/ghosting. > > For what it seems like you are doing, I'd use the SPI interface to shift > out your data in blocks of 16-bits - 9 xfers gets you 144 bits out. > You obviously could bit bang this but why when you have built-in hardware > that will do it for you. I'd think it would be fast enough in an ISR. I > should think less than 250 us. > Use the gpio for toggling your latch and output enable and addr/row select > - these are low speed signals - so no problem > There are definitely easier ways to do this with external hardware, but > for this size matrix it would be a waste of $. Yes, a $1-2 cpld will do the > trick - but then you need a pcb etc... > Setup a periodic timer interrupt to sync your shifts / rows of data - take > your refresh rate (suggest 55-80Hz to avoid flicker) & divide by # of rows > (timer => 440 to 640 Hz / row) > Use the time between interrupts to setup your next buffer for display > > Get someone here to help you with the timer/interrupt under Linux - I have > no idea on that one. Would like to though - so maybe someone will respond > with how to do that. > > Hope that helps. > > Good Luck, > Matt > >> >> -- > 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 beagleboard+unsubscr...@googlegroups.com. > 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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
David, Without seeing your circuit of how you are setting up your rows & columns to be driven, I'll take a blind stab at your issue. To get rid of artifacts / ghosting / etc... 1) Shift out all your data 2) Turn off your drivers and row power if that is available 3) Delay ~20us 4) Latch the data into your drivers 5) Delay ~20us or more 6) Change your row address 7) Enable your outputs and/or row power You must have some dead time between rows or you will get artifacts / ghosting / whatever you choose to call it. You might get away with less than 20us but also you might need more depending on your circuit. Too much dead time and you will get flicker - not enough and you guessed it - artifacts/ghosting. For what it seems like you are doing, I'd use the SPI interface to shift out your data in blocks of 16-bits - 9 xfers gets you 144 bits out. You obviously could bit bang this but why when you have built-in hardware that will do it for you. I'd think it would be fast enough in an ISR. I should think less than 250 us. Use the gpio for toggling your latch and output enable and addr/row select - these are low speed signals - so no problem There are definitely easier ways to do this with external hardware, but for this size matrix it would be a waste of $. Yes, a $1-2 cpld will do the trick - but then you need a pcb etc... Setup a periodic timer interrupt to sync your shifts / rows of data - take your refresh rate (suggest 55-80Hz to avoid flicker) & divide by # of rows (timer => 440 to 640 Hz / row) Use the time between interrupts to setup your next buffer for display Get someone here to help you with the timer/interrupt under Linux - I have no idea on that one. Would like to though - so maybe someone will respond with how to do that. Hope that helps. Good Luck, Matt > > -- 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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
Now here's where kernel space gets really weird. I did actually mean 20milliseconds. My first version of the LKM tried to use msleep(2), but only got 6Hz total image refresh rate. I measured the signals with a logic analyzer and found that I was waking up every ~20ms. Totally confused, I searched and found the answer here: https://www.kernel.org/doc/Documentation/timers/timers-howto.txt It turns out that msleep doesn't work for very low values of 'm' because they use legacy timers rather than the new high resolution ones. The GPIO can be toggled through back to back function calls at about 2us. About waiting on "the buffer". There are two buffers: 1> active row data 2> temporary buffer that is filled by dev_write calls from user-space. The active row data buffer is never touched by user space, so no one ever waits for it. The temp buffer is only used to get new image data from user space and once filled, is consumed by the update_row task. Again, unless I missed something, the update_row task is not affected. My driver should be getting multiple time slices of the CPU asynchronously during the time that the dev_write routine is waiting. But in actual use, I've never seen that this wait ever happens since it is only triggered if user-space is somehow able to write faster than my kernel thread can update the active row data. My test pattern application only writes a new pattern every 1 second, so I have been treating the LKM gently :) I definitely will check out flattening the two dimensional array. I didn't think that it would really impact performance since I'm not dereferencing it with multiple subscripts, but rather just passing buf[row] as a pointer into the serializer function. It probably would be easier to do effects and transitions on a linear array, but I probably won't do too much of that in the kernel module itself. If the performance of writing to a character device is good, I would prefer to do all image processing and buffer manipulation in user space. But, experimentation will have to guide me there! --David On Mon, Mar 21, 2016 at 4:08 PM, William Hermanswrote: > >> >> *Hi William!* >> >> >> *Good eyes, but I don't know if that will affect the row updates. This >> will affect user space programs trying to write to the character device and >> introduce a delay returning from write request, but since the row updates >> themselves are happening on a separate kthread, it shouldn't be possible to >> disturb the critical timing.* >> *I think that the delay actually produced by this call will be 1 "jiffy" >> which I think is ~20ms or more, but I didn't think it mattered to make >> user-space wait this amount of time.* >> > > Hi David, > > About the only way I can think of to "accurately" test this. Would be to > write a similar LKM that toggles a single GPIO, and watch the results with > a scope or logic analyzer. So when you say ~20ms" be wary that "ms" > typically means milliseconds, which you probably meant to mean microseconds. > > Again, I'm not sure of msleep() but it seems to be called every time the > driver is waiting on the buffer. And I do not know how often this method in > your module is called, but that potential for latency from the sleep() and > the big O nested loop situation . . . is your buffer really a two > dimensional array ? I'd definitely look into changing that into possibly a > linear field that can have bit ops done on it effectively. > > > > On Mon, Mar 21, 2016 at 1:55 PM, David Good wrote: > >> Hi William! >> >> Good eyes, but I don't know if that will affect the row updates. This >> will affect user space programs trying to write to the character device and >> introduce a delay returning from write request, but since the row updates >> themselves are happening on a separate kthread, it shouldn't be possible to >> disturb the critical timing. >> >> I think that the delay actually produced by this call will be 1 "jiffy" >> which I think is ~20ms or more, but I didn't think it mattered to make >> user-space wait this amount of time. >> >> --David >> >> On Mon, Mar 21, 2016 at 3:44 PM, William Hermans >> wrote: >> >>> So, I'm just now getting back to you, and I see you all have been >>> discussing things I have not fully read about yet. Anyway I will say that I >>> have zero hands on with LKM's, but I do have a decent amount of hands on >>> with C in userspace. One thing that sticks out to me . . . >>> https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359 >>> >>> msleep(n) where n is a value in microseconds. I honestly do not know how >>> responsive timers are in kernel space, but in userspace high resolution >>> timers do not work. It does not matter if one uses an RT kernel or not. So >>> system API calls such as usleep() really do not work, as there is some >>> system call overhead involved. In kernel space . . . again I have no hands >>> on personally, but I'd be
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
> > > > *Hi William!* > > > *Good eyes, but I don't know if that will affect the row updates. This > will affect user space programs trying to write to the character device and > introduce a delay returning from write request, but since the row updates > themselves are happening on a separate kthread, it shouldn't be possible to > disturb the critical timing.* > *I think that the delay actually produced by this call will be 1 "jiffy" > which I think is ~20ms or more, but I didn't think it mattered to make > user-space wait this amount of time.* > Hi David, About the only way I can think of to "accurately" test this. Would be to write a similar LKM that toggles a single GPIO, and watch the results with a scope or logic analyzer. So when you say ~20ms" be wary that "ms" typically means milliseconds, which you probably meant to mean microseconds. Again, I'm not sure of msleep() but it seems to be called every time the driver is waiting on the buffer. And I do not know how often this method in your module is called, but that potential for latency from the sleep() and the big O nested loop situation . . . is your buffer really a two dimensional array ? I'd definitely look into changing that into possibly a linear field that can have bit ops done on it effectively. On Mon, Mar 21, 2016 at 1:55 PM, David Goodwrote: > Hi William! > > Good eyes, but I don't know if that will affect the row updates. This > will affect user space programs trying to write to the character device and > introduce a delay returning from write request, but since the row updates > themselves are happening on a separate kthread, it shouldn't be possible to > disturb the critical timing. > > I think that the delay actually produced by this call will be 1 "jiffy" > which I think is ~20ms or more, but I didn't think it mattered to make > user-space wait this amount of time. > > --David > > On Mon, Mar 21, 2016 at 3:44 PM, William Hermans > wrote: > >> So, I'm just now getting back to you, and I see you all have been >> discussing things I have not fully read about yet. Anyway I will say that I >> have zero hands on with LKM's, but I do have a decent amount of hands on >> with C in userspace. One thing that sticks out to me . . . >> https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359 >> >> msleep(n) where n is a value in microseconds. I honestly do not know how >> responsive timers are in kernel space, but in userspace high resolution >> timers do not work. It does not matter if one uses an RT kernel or not. So >> system API calls such as usleep() really do not work, as there is some >> system call overhead involved. In kernel space . . . again I have no hands >> on personally, but I'd be leery of any sleep() type call until I actually >> tested it on the specific platform I planned using it on. >> >> On Mon, Mar 21, 2016 at 1:23 PM, Harvey White >> wrote: >> >>> On Mon, 21 Mar 2016 14:31:56 -0500, you wrote: >>> >>> >So, let me see if I understand your idea: >>> >My display looks like this: >>> >R0 >>> >... >>> >R7 >>> >>> Ah, ok, dot matrix then. >>> > >>> >Data is written to the LED drivers while power is applied to one row. >>> >Then, new data is written and power is applied to the next row, etc. >>> > >>> >"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." >>> > >>> >When you say "digit", I assume you are thinking in terms of a >>> multiplexed >>> >7-segment readout style display, which in my case would be the same >>> thing >>> >as a row. My driver operates on one row at a time before going to >>> sleep. >>> >Are you suggesting that I scan through all 8 rows and then have a >>> special >>> >9th "row" time where I do things like the memcpy? This would be pretty >>> >close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't >>> have >>> >to wait a full row time, but could schedule the next row sooner. >>> Hmm >>> > >>> >>> Exactly, VSync or Hsync depending on what analogy you want. In this >>> case, Vsync would be right. >>> >>> If you're doing an operating system, then your timing is really >>> generated by interrupts, so I'd be using a relatively high priority >>> hardware interrupt from a timer here, or if you want to do an >>> operating system, then just give the remaining time back to the OS so >>> it can pick the next task. No need to chew up one tick period. >>> >>> In my OS, tasks suspended or delayed check the time (or semaphore) or >>> yield back the time, then the OS simply looks for the next active >>> task. >>> >>> >>> >>> >You are totally right about MCUs and burning the LEDs. This particular >>> >display is safe because the LEDs are not being over-driven. Your idea >>> >about a CPLD is a good one. I've never used them, but have know about >>> >them. I found this XC2C32A for
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
Hi William! Good eyes, but I don't know if that will affect the row updates. This will affect user space programs trying to write to the character device and introduce a delay returning from write request, but since the row updates themselves are happening on a separate kthread, it shouldn't be possible to disturb the critical timing. I think that the delay actually produced by this call will be 1 "jiffy" which I think is ~20ms or more, but I didn't think it mattered to make user-space wait this amount of time. --David On Mon, Mar 21, 2016 at 3:44 PM, William Hermanswrote: > So, I'm just now getting back to you, and I see you all have been > discussing things I have not fully read about yet. Anyway I will say that I > have zero hands on with LKM's, but I do have a decent amount of hands on > with C in userspace. One thing that sticks out to me . . . > https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359 > > msleep(n) where n is a value in microseconds. I honestly do not know how > responsive timers are in kernel space, but in userspace high resolution > timers do not work. It does not matter if one uses an RT kernel or not. So > system API calls such as usleep() really do not work, as there is some > system call overhead involved. In kernel space . . . again I have no hands > on personally, but I'd be leery of any sleep() type call until I actually > tested it on the specific platform I planned using it on. > > On Mon, Mar 21, 2016 at 1:23 PM, Harvey White > wrote: > >> On Mon, 21 Mar 2016 14:31:56 -0500, you wrote: >> >> >So, let me see if I understand your idea: >> >My display looks like this: >> >R0 >> >... >> >R7 >> >> Ah, ok, dot matrix then. >> > >> >Data is written to the LED drivers while power is applied to one row. >> >Then, new data is written and power is applied to the next row, etc. >> > >> >"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." >> > >> >When you say "digit", I assume you are thinking in terms of a multiplexed >> >7-segment readout style display, which in my case would be the same thing >> >as a row. My driver operates on one row at a time before going to sleep. >> >Are you suggesting that I scan through all 8 rows and then have a special >> >9th "row" time where I do things like the memcpy? This would be pretty >> >close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't >> have >> >to wait a full row time, but could schedule the next row sooner. Hmm >> > >> >> Exactly, VSync or Hsync depending on what analogy you want. In this >> case, Vsync would be right. >> >> If you're doing an operating system, then your timing is really >> generated by interrupts, so I'd be using a relatively high priority >> hardware interrupt from a timer here, or if you want to do an >> operating system, then just give the remaining time back to the OS so >> it can pick the next task. No need to chew up one tick period. >> >> In my OS, tasks suspended or delayed check the time (or semaphore) or >> yield back the time, then the OS simply looks for the next active >> task. >> >> >> >> >You are totally right about MCUs and burning the LEDs. This particular >> >display is safe because the LEDs are not being over-driven. Your idea >> >about a CPLD is a good one. I've never used them, but have know about >> >them. I found this XC2C32A for $1.8USD. I will probably try this out at >> >some point just for educational purposes :) >> >> You would want the Xilinx free version of their web support (ISE), >> which works fine those chips. You'll need to find the USB programming >> cable as well, I got mine from Amazon. >> >> There are times when it's nice to be able to throw hardware at a >> problem. You have the driver done well enough, but IIRC, there are >> some subsystems out there that do this. A simple Atmel Mega processor >> would work well for this, if you wanted. >> >> The nice thing about the XC2C32A and the Xc2C64A is that they have >> exactly the same footprint. Once you get to 128 or 256 cells, you go >> to a TQFP-100 package. >> >> I'd recommend VHDL (simply because I like it) for the design language. >> Remember that in VHDL you do not have to design components like chips, >> but you can tell the chip "I want a divide by 37 counter" by >> explaining how it counts, and then let the program built it. This >> makes it an easier design process than designing the counter with >> logic by itself. >> >> Harvey >> >> >> > >> > >> http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030 >> > >> >--David >> > >> > >> >On Mon, Mar 21, 2016 at 12:28 PM, Harvey White >> >wrote: >> > >> >> 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 >> >>
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
Additionally just below the call to msleep() linked to above you have nested loops two deep so . . . http://stackoverflow.com/questions/24643432/big-o-nested-while-loop On Mon, Mar 21, 2016 at 1:44 PM, William Hermanswrote: > So, I'm just now getting back to you, and I see you all have been > discussing things I have not fully read about yet. Anyway I will say that I > have zero hands on with LKM's, but I do have a decent amount of hands on > with C in userspace. One thing that sticks out to me . . . > https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359 > > msleep(n) where n is a value in microseconds. I honestly do not know how > responsive timers are in kernel space, but in userspace high resolution > timers do not work. It does not matter if one uses an RT kernel or not. So > system API calls such as usleep() really do not work, as there is some > system call overhead involved. In kernel space . . . again I have no hands > on personally, but I'd be leery of any sleep() type call until I actually > tested it on the specific platform I planned using it on. > > On Mon, Mar 21, 2016 at 1:23 PM, Harvey White > wrote: > >> On Mon, 21 Mar 2016 14:31:56 -0500, you wrote: >> >> >So, let me see if I understand your idea: >> >My display looks like this: >> >R0 >> >... >> >R7 >> >> Ah, ok, dot matrix then. >> > >> >Data is written to the LED drivers while power is applied to one row. >> >Then, new data is written and power is applied to the next row, etc. >> > >> >"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." >> > >> >When you say "digit", I assume you are thinking in terms of a multiplexed >> >7-segment readout style display, which in my case would be the same thing >> >as a row. My driver operates on one row at a time before going to sleep. >> >Are you suggesting that I scan through all 8 rows and then have a special >> >9th "row" time where I do things like the memcpy? This would be pretty >> >close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't >> have >> >to wait a full row time, but could schedule the next row sooner. Hmm >> > >> >> Exactly, VSync or Hsync depending on what analogy you want. In this >> case, Vsync would be right. >> >> If you're doing an operating system, then your timing is really >> generated by interrupts, so I'd be using a relatively high priority >> hardware interrupt from a timer here, or if you want to do an >> operating system, then just give the remaining time back to the OS so >> it can pick the next task. No need to chew up one tick period. >> >> In my OS, tasks suspended or delayed check the time (or semaphore) or >> yield back the time, then the OS simply looks for the next active >> task. >> >> >> >> >You are totally right about MCUs and burning the LEDs. This particular >> >display is safe because the LEDs are not being over-driven. Your idea >> >about a CPLD is a good one. I've never used them, but have know about >> >them. I found this XC2C32A for $1.8USD. I will probably try this out at >> >some point just for educational purposes :) >> >> You would want the Xilinx free version of their web support (ISE), >> which works fine those chips. You'll need to find the USB programming >> cable as well, I got mine from Amazon. >> >> There are times when it's nice to be able to throw hardware at a >> problem. You have the driver done well enough, but IIRC, there are >> some subsystems out there that do this. A simple Atmel Mega processor >> would work well for this, if you wanted. >> >> The nice thing about the XC2C32A and the Xc2C64A is that they have >> exactly the same footprint. Once you get to 128 or 256 cells, you go >> to a TQFP-100 package. >> >> I'd recommend VHDL (simply because I like it) for the design language. >> Remember that in VHDL you do not have to design components like chips, >> but you can tell the chip "I want a divide by 37 counter" by >> explaining how it counts, and then let the program built it. This >> makes it an easier design process than designing the counter with >> logic by itself. >> >> Harvey >> >> >> > >> > >> http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030 >> > >> >--David >> > >> > >> >On Mon, Mar 21, 2016 at 12:28 PM, Harvey White >> >wrote: >> > >> >> 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
So, I'm just now getting back to you, and I see you all have been discussing things I have not fully read about yet. Anyway I will say that I have zero hands on with LKM's, but I do have a decent amount of hands on with C in userspace. One thing that sticks out to me . . . https://github.com/davidgood1/ledmsgchar/blob/master/ledmsgchar.c#L359 msleep(n) where n is a value in microseconds. I honestly do not know how responsive timers are in kernel space, but in userspace high resolution timers do not work. It does not matter if one uses an RT kernel or not. So system API calls such as usleep() really do not work, as there is some system call overhead involved. In kernel space . . . again I have no hands on personally, but I'd be leery of any sleep() type call until I actually tested it on the specific platform I planned using it on. On Mon, Mar 21, 2016 at 1:23 PM, Harvey Whitewrote: > On Mon, 21 Mar 2016 14:31:56 -0500, you wrote: > > >So, let me see if I understand your idea: > >My display looks like this: > >R0 > >... > >R7 > > Ah, ok, dot matrix then. > > > >Data is written to the LED drivers while power is applied to one row. > >Then, new data is written and power is applied to the next row, etc. > > > >"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." > > > >When you say "digit", I assume you are thinking in terms of a multiplexed > >7-segment readout style display, which in my case would be the same thing > >as a row. My driver operates on one row at a time before going to sleep. > >Are you suggesting that I scan through all 8 rows and then have a special > >9th "row" time where I do things like the memcpy? This would be pretty > >close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't have > >to wait a full row time, but could schedule the next row sooner. Hmm > > > > Exactly, VSync or Hsync depending on what analogy you want. In this > case, Vsync would be right. > > If you're doing an operating system, then your timing is really > generated by interrupts, so I'd be using a relatively high priority > hardware interrupt from a timer here, or if you want to do an > operating system, then just give the remaining time back to the OS so > it can pick the next task. No need to chew up one tick period. > > In my OS, tasks suspended or delayed check the time (or semaphore) or > yield back the time, then the OS simply looks for the next active > task. > > > > >You are totally right about MCUs and burning the LEDs. This particular > >display is safe because the LEDs are not being over-driven. Your idea > >about a CPLD is a good one. I've never used them, but have know about > >them. I found this XC2C32A for $1.8USD. I will probably try this out at > >some point just for educational purposes :) > > You would want the Xilinx free version of their web support (ISE), > which works fine those chips. You'll need to find the USB programming > cable as well, I got mine from Amazon. > > There are times when it's nice to be able to throw hardware at a > problem. You have the driver done well enough, but IIRC, there are > some subsystems out there that do this. A simple Atmel Mega processor > would work well for this, if you wanted. > > The nice thing about the XC2C32A and the Xc2C64A is that they have > exactly the same footprint. Once you get to 128 or 256 cells, you go > to a TQFP-100 package. > > I'd recommend VHDL (simply because I like it) for the design language. > Remember that in VHDL you do not have to design components like chips, > but you can tell the chip "I want a divide by 37 counter" by > explaining how it counts, and then let the program built it. This > makes it an easier design process than designing the counter with > logic by itself. > > Harvey > > > > > > > http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030 > > > >--David > > > > > >On Mon, Mar 21, 2016 at 12:28 PM, Harvey White > >wrote: > > > >> 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
On Mon, 21 Mar 2016 14:31:56 -0500, you wrote: >So, let me see if I understand your idea: >My display looks like this: >R0 >... >R7 Ah, ok, dot matrix then. > >Data is written to the LED drivers while power is applied to one row. >Then, new data is written and power is applied to the next row, etc. > >"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." > >When you say "digit", I assume you are thinking in terms of a multiplexed >7-segment readout style display, which in my case would be the same thing >as a row. My driver operates on one row at a time before going to sleep. >Are you suggesting that I scan through all 8 rows and then have a special >9th "row" time where I do things like the memcpy? This would be pretty >close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't have >to wait a full row time, but could schedule the next row sooner. Hmm > Exactly, VSync or Hsync depending on what analogy you want. In this case, Vsync would be right. If you're doing an operating system, then your timing is really generated by interrupts, so I'd be using a relatively high priority hardware interrupt from a timer here, or if you want to do an operating system, then just give the remaining time back to the OS so it can pick the next task. No need to chew up one tick period. In my OS, tasks suspended or delayed check the time (or semaphore) or yield back the time, then the OS simply looks for the next active task. >You are totally right about MCUs and burning the LEDs. This particular >display is safe because the LEDs are not being over-driven. Your idea >about a CPLD is a good one. I've never used them, but have know about >them. I found this XC2C32A for $1.8USD. I will probably try this out at >some point just for educational purposes :) You would want the Xilinx free version of their web support (ISE), which works fine those chips. You'll need to find the USB programming cable as well, I got mine from Amazon. There are times when it's nice to be able to throw hardware at a problem. You have the driver done well enough, but IIRC, there are some subsystems out there that do this. A simple Atmel Mega processor would work well for this, if you wanted. The nice thing about the XC2C32A and the Xc2C64A is that they have exactly the same footprint. Once you get to 128 or 256 cells, you go to a TQFP-100 package. I'd recommend VHDL (simply because I like it) for the design language. Remember that in VHDL you do not have to design components like chips, but you can tell the chip "I want a divide by 37 counter" by explaining how it counts, and then let the program built it. This makes it an easier design process than designing the counter with logic by itself. Harvey > >http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030 > >--David > > >On Mon, Mar 21, 2016 at 12:28 PM, Harvey White>wrote: > >> 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
So, let me see if I understand your idea: My display looks like this: R0 ... R7 Data is written to the LED drivers while power is applied to one row. Then, new data is written and power is applied to the next row, etc. "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." When you say "digit", I assume you are thinking in terms of a multiplexed 7-segment readout style display, which in my case would be the same thing as a row. My driver operates on one row at a time before going to sleep. Are you suggesting that I scan through all 8 rows and then have a special 9th "row" time where I do things like the memcpy? This would be pretty close to a VSYNC idea, right? I suppose that this 9th "row" wouldn't have to wait a full row time, but could schedule the next row sooner. Hmm You are totally right about MCUs and burning the LEDs. This particular display is safe because the LEDs are not being over-driven. Your idea about a CPLD is a good one. I've never used them, but have know about them. I found this XC2C32A for $1.8USD. I will probably try this out at some point just for educational purposes :) http://www.digikey.com/product-detail/en/xilinx-inc/XC2C32A-6VQG44I/122-1704-ND/1952030 --David On Mon, Mar 21, 2016 at 12:28 PM, Harvey Whitewrote: > 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
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>wrote: > >> On Mon, 21 Mar 2016 01:20:34 -0500, you wrote: >> >>
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
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) 2> If new data is ready in RAM, memcpy it to the real display buffer in RAM. 3> Serially shift out next row data in the background, but do not latch yet (background) 4> Blank the display - This is not actually working right now. I never see the blank line move. Hmm 5> Adjust the multiplexed row select pins to the next row (A2...A0) 6> Latch the data already in the serial buffers 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. 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. 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. 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. 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. Thanks for your feedback! --David On Mon, Mar 21, 2016 at 9:40 AM, Harvey Whitewrote: > 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 > 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
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 Hermanswrote: > >> 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 >> wrote: >> >>> Show us some code. >>> >>> On Sun, Mar 20, 2016 at 6:28 PM, David Good >>> 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
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
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 Hermanswrote: > 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 > wrote: > >> Show us some code. >> >> On Sun, Mar 20, 2016 at 6:28 PM, David Good >> 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 beagleboard+unsubscr...@googlegroups.com. >>> 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 beagleboard+unsubscr...@googlegroups.com. > 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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
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 Hermanswrote: > Show us some code. > > On Sun, Mar 20, 2016 at 6:28 PM, David Good 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 beagleboard+unsubscr...@googlegroups.com. >> 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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [beagleboard] Driving a Multiplexed LED matrix directly from gpio
Show us some code. On Sun, Mar 20, 2016 at 6:28 PM, David Goodwrote: > 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 beagleboard+unsubscr...@googlegroups.com. > 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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[beagleboard] Driving a Multiplexed LED matrix directly from gpio
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 beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.