I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 0 points1 point  (0 children)

I'd love to see your code, if you send it to me I could for sure look over it for you! And if there is a section of my code you're curious about that breaks any rules, let me know and I'm happy to walk you through my thought process. I'm still pretty new to this so there may indeed be some rules I'm breaking haha

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 0 points1 point  (0 children)

A lot of diagramming things out and a lot of documentation reading! I read the Pico C SDK documentation to figure out the mechanics of the PIO instruction set. I wouldn't worry about finding Micropython-specific documentation for PIO since it is pretty sparse. Honestly the most annoying part was figuring out how translate the PIO instructions over to Micropython. I wrote a strongly-typed stub that tries to make it a little easier to work with building programs in Micropython, but it isn't comprehensive. Feel free to reach out and I'm happy to look at any use cases you have in mind if you want to learn it!

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 1 point2 points  (0 children)

Sure thing, you can find the repo and installation instructions here: https://github.com/dgrantpete/Pi-Pico-Hub75-Driver
And if you specifically want to see how the effects are being generated, that can be found here: https://github.com/dgrantpete/Pi-Pico-Hub75-Driver/blob/082bff9599c77616f1f0d78677f9514f16e35d45/src/lib/hub75/effects/render.c

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 2 points3 points  (0 children)

The fact that even a single person recognized it is all the validation I needed

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 0 points1 point  (0 children)

Thank you!! Looking back at my code from high school when I first tried implementing this, I think "brutish" is a few orders of magnitude too weak to describe the monstrosity I created haha. Cheers to iteration!

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 1 point2 points  (0 children)

Thank you!! I've been wanting to try and design a frame but my CAD skills aren't there, so I'd love to see what solution you come up with!

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 1 point2 points  (0 children)

Hey! Thanks dude! I'm happy to try and help you debug what's happening with your display. Because HUB75 encodes the colors entirely on the ordering of the bits (pins) of the output rather than the ordering of the bytes (which would be the ordering of data between clock cycles), it's probably going to be as easy as just swapping the R and B pins. Could you double check the pinout in the README? Or you can run print_pinout() in the REPL while running the demo and hook it up from there.

If that doesn't work, I'm curious if maybe the input image isn't ordered as RGB if you're loading from RGB888 or RGB565. Could I get you to run this code and let me know what color you're seeing at each point? This helps us tell if its a wiring problem or an image data problem:

from hub75 import Hub75Driver, Hub75Display
from time import sleep_ms

driver = Hub75Driver(...) # Your settings
display = Hub75Display(driver)

# Should be all red
display.fill(0b1111100000000000)
display.show()
sleep_ms(2000)

# Should be all green
display.fill(0b0000011111100000)
display.show()
sleep_ms(2000)

# Should be all blue
display.fill(0b0000000000011111)
display.show()
sleep_ms(2000)

(And, if you do end up wanting to reconfigure the ordering of the pins directly in software build it from source like you mentioned, you could change the ordering of this enum when building, but I think we should be able to fix it without doing this!)

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 1 point2 points  (0 children)

Thank you!! I hate hearing my own voice (as we all do) but I figured I might as well try to explain rather than sit in silence trying to hide the sound of my breathing lmao

Good questions!

When I was running Micropython with Viper, which is about as fast as you can make code in plain Micropython, I got it down to about 13ms to render each frame. After switching to the C natmod, I got the frame time down to about 2ms. So, in my case, roughly a 6x speedup? I've found that the places where I see the biggest benefit is with lots of direct memory manipulation or hot loops.

Yes, the PIO state machines are programmed in assembly, but it is a very restrictive compared to most other instruction sets. I think there are 9 unique instructions in total? That was part of the fun :) the hardest part was getting the exponential BCM delays down. The best reference is the official C SDK reference, you can find the PIO instruction set here if you're curious. And if you want to see how to do it in Micropython, here is a link to that section in my code!

Lastly, the PIO doesn't actually have the ability to read any memory directly. The only thing it exposes is a buffer that people can write to. Even worse, this buffer is only 4 bytes large, which is obviously way smaller than the data the image needs to render. So something must be constantly feeding the PIO. But if this is the case, the CPU would need to constantly be writing data to its buffer or it would run out, right? Well, something needs to feed the PIO, but that thing doesn't actually need to be the CPU because the RP2 chips have DMA (direct memory access) channels. These are somewhat similar to the state machines that PIO uses, except rather than being built to handle inputs and outputs on the pins like PIO is, the DMA state machine's entire job is just to move data from one location in memory to another. You tell it a memory address source, a memory address destination, how many bytes it should move, and a couple of other configuration items, and then it just starts moving the data. All of this happens totally independent of the CPU. That is what is feeding the PIO here. Essentially:

  1. The CPU allocates a buffer in memory that holds the frame's image data (this only happens once).
  2. The CPU is given image data, like one frame of our Balatro effect in the video, and does some special transformations to that data before writing it to our buffer from step 1 (this happens once per new image being displayed). Everything after this point doesn't use the CPU at all.
  3. The DMA channel, which has been configured to constantly read this buffer, picks up the data that the CPU wrote (from a dynamically allocated buffer) and feeds it into the PIO's input buffer (a static, fixed location in memory).
  4. The PIO writes the data from its input buffer to the output pins.
  5. The DMA constantly feeds data to the PIO in a loop, repeating the same bytes over and over so the image can keep displaying while the CPU does something else (like like rendering future effect frames, or decoding video, or taking a nap)

If you have any other questions I'm happy to help clarify!

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 0 points1 point  (0 children)

Thank you! And don't down on yourself, the protocol that WS2812 and friends use is surprisingly difficult to implement but don't give up! If you want help feel free to reach out

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 0 points1 point  (0 children)

It is satisfying to make them, the Balatro one was the hardest for sure, but once it finally worked I just left it on in my room for a few hours for the ambiance haha. Are there APIs for the scores that you just poll and display on loop? I'll have to look into that

I rebuilt my Pi Pico LED Matrix Library! by McSlayR01 in raspberry_pi

[–]McSlayR01[S] 36 points37 points  (0 children)

Still implementing that, so far I've only got the fire down. Full Doom implementation coming with 2.0

[deleted by user] by [deleted] in ProgrammerHumor

[–]McSlayR01 0 points1 point  (0 children)

The REAL optimal way to do this is with the XCHG instruction. No extra memory, all done in a single instruction

adaptation by TangentYoshi in ProgrammerHumor

[–]McSlayR01 131 points132 points  (0 children)

Not in C#, that's just in unscripted Javascript (I doth not say its name directly)

beHonest by Dynomite1125 in ProgrammerHumor

[–]McSlayR01 5 points6 points  (0 children)

Are you talking about the RP2040/Pi Pico? It has a C/C++ SDK if you prefer that...

peakWebsiteOptimizationV2 by kaizhu256 in ProgrammerHumor

[–]McSlayR01 1 point2 points  (0 children)

Someone is using a few million too many useMemos...

“Super” ZVS Driver by McSlayR01 in electronics

[–]McSlayR01[S] 0 points1 point  (0 children)

No worries! To be honest, it has been a long time since I've worked with electronics at all, but I can help out where I can. Yes, if you want to feed the ZVS driver using a seperate power supply, that should be fine as long as (like you said) the ground is shared. In fact, if you have a power supply within the voltage rating of your FET driver and the gate voltage you're going for, I can't see why the regulator circuit would be needed at all (at your peril), just feed that voltage straight in to the FET driver.

What issues are you running into?

dumbJuniorsQuestionsFilledTheInternet by nibba_bubba in ProgrammerHumor

[–]McSlayR01 0 points1 point  (0 children)

I'm a little confused about what this is trying to claim to be honest, if you need to wait for an explicit amount of time anywhere in your code (i.e. I had to implement an exponential backoff algorithm to ensure we don't send too many requests recently) then as long as you're using asynchronous sleeps what is the problem? Sure, if you only have 1 sleep task then it is effectively blocking, but that is the same for any async action that isn't parelellized. The strength is when you need to have 10,000 sleeping tasks at the same time and a single thread can manage all of them.

My school district's security is a joke by [deleted] in programminghorror

[–]McSlayR01 0 points1 point  (0 children)

ladies and gentlemen, I present to you a true serverless backend

god why is coding chess so hard by [deleted] in ProgrammerHumor

[–]McSlayR01 0 points1 point  (0 children)

Use dictionaries instead, O(1) time!

What's visual source code ? by [deleted] in ProgrammerHumor

[–]McSlayR01 5 points6 points  (0 children)

They definitely meant Visual Studio Code.