All right. Hello, everyone. Happy Friday and happy Thanksgiving from yesterday to everyone. Let me shuffle around a couple of windows here. Looks like I've got sound going to OBS, so I think we're probably good there. I did remember to press the start thing for YouTube today, so I think we're good on that. Ooh, I can hear myself. That's not what we want. Let's hear out where that's at. I'm trying something different with the chat this time around, so we'll see We'll see how the chat goes. Times have trouble where, whoop, where the YouTube chat window that I used in the stream was Adafruit account, which is the moderator, which sees all the messages that are held for moderation. And it defeats the purpose if we got it on the screen. So we're trying something new on that front today. Hopefully we're not going to be bombarded with any weird chats in the YouTube today. And we're almost there, so okay. Let's see. Who do we got? How's it going? DJ Devon, thank God. It's Friday. Seconded on that. Agreed there. Audio's okay. Thank you. I appreciate the heads up. How's it going, Paul SK? Dgrover, how's it going? Hi, Tim. And present on this dark. What do I say? Black Friday? Yes. Happy, happy Thanksgiving to everyone. Happy Black Friday, if Black Friday is your thing, or just Friday in general. Fridays are pretty sweet. All things considered. How's it going, Jack in the shop? Over there on YouTube and Discord. Beata, happy Friday. How's it going? And Deanna Bell. De- excuse me, Diane-a-bell. Diane-a-bell. How's it going, folks? Thank you for tuning in. Happy Friday to everyone, and of course, happy Thanksgiving from yesterday as well to everyone. So my name is Tim. This is the deep dive program. This is a weekly stream featuring CircuitPython, and in particular, we're getting into kind of the nitty-gritty of CircuitPython diving right down into the depths of the ocean, so to speak. In particular, we're working on libraries. We're working on complex projects. We're working inside the core, changing APIs, working on infrastructure for the project, that sort of stuff. And that's what this stream is all about. I will take just a moment, though. Let's take a quick step back in case anybody is new. Let me find my browser here for anybody that might be new. If you don't know what any of the things I was just talking about are, this is a good place to start for you, CircuitPython.org. Basically, what we are working on, though, is a version of Python. It runs on these tiny computers called microcontrollers. There are all different shapes and sizes of them. You can see a bunch of pictures of them here on the downloads page at CircuitPython.org. These devices all have a tiny computer like this main chip here. This tiny computer can run Python code on it that interacts with other stuff that is plugged in, so RGB lights, keyboard, key switches, in this case, alligator, clip, pins, and some more RGB lights. This has a speaker and a gyrometer, accelerometer device on it, has a temperature sensor. All different shapes and sizes of these things, and we're writing Python code that interacts with different peripherals that are either built into the board or connected up through one of the many available IOPins, what they call IOPins for input-output pins. We can connect stuff there, then write our Python code to talk to, so to speak, whatever is connected, interact with it, read values from sensors, interact with buttons to determine when they're pressed, set RGB lights to whatever color you want, that sort of stuff. I must say thank you to Adafruit. Oh, first thing, we did not get the home page today. Let's see. Must two-factor write this moment before we can see the front page apparently. I don't know if there's a kind of special Black Friday thing going on, perhaps? Maybe that's the reason why. One moment while I get logged in, I mostly just want to see the front page, but that's not letting me there, so let's do this bit. What's going to change? Come on, there we go. Home page, there we are. Okay, I don't know what was going on there. Home page, we're there. Feather Friday apparently is what it is today. Does that include TFTs? Although I have a fair amount of Feather TFTs at this point. Anyway, though, where I was really trying to go with that is thank you to Adafruit. This is their website, Adafruit.com. Adafruit is the company that primarily sponsors the Circuit Python project, so I was telling you about Circuit Python. It's this version of Python. It's an open source project. It's free to use. It's free to port your own hardware to run Circuit Python. All of that sort of stuff. It's free to extend if you want to make it do other stuff. All of that sort of stuff. It is an open source project. You can do all of that. It is funded, though, by Adafruit. They're paying the team who works on the project full-time. They're paying some folks who work on the project part-time, like myself. They're paying us to work on the project itself, but also all the peripheral stuff. Guides, documentation, streams, fostering the community, the weekly meetings, all of these kinds of things. Adafruit is paying for our time to work on this stuff. So thank you, of course, to Adafruit for doing that. And thank you to anyone who wants to purchase hardware from Adafruit in order to help support the project and all of the other fun stuff that Adafruit is working on. And with that, let's talk a little bit more about specifically what I'm going to work on today. Let me catch up on a few of the chats, though. We can definitely do Weird if you want.  All store items this weekend. Yeah, thank you. Devin's Workshop, I'm guessing. Is that probably DJ Devin? Either way, thanks for the heads up there in the chat. And yeah, that looks like what the deal that's going on today. 20% off all Feathers. And is that Mainboard Feathers or Feather Wings as well? But either way, it's 15% off all items. So you'd only be a 5% difference there, even if it's not. So definitely a good day to grab yourself some goodies, some toys from Adafruit. And while you're doing so, you're helping support Circuit Python by purchasing that stuff from them. So more specifically today, what I want to get into have grown an extra browser. Okay, that's right, because I pulled this one out as it was making me log in. Today, though, what I'm working on today are a couple of different things inside the core. Well, we'll start with one, we'll see how far we get. If we get the first one done, kind of to my satisfaction for the time being, then I'll move on to the next one, but we'll play it by ear on that front. So I'll introduce the first one, and then we'll get into the other one later on, if so. If you watched last week's program, though, you'll be familiar with these a bit. Last week's program, we worked on display IO core changes, which is what will be my second topic that I get to today, if we get the first one done. The first one, though, will be this pixel map stuff, which is what I have been working on the last day or two. This is some changes inside the core that Jeff was working on originally. Basically, this is a version of a helper class called pixel map. As of right now today, this class exists inside the LED animation library. What this class does is it allows you to map multiple RGB NeoPixels together to act as one for the purposes of an animation. Let's say you have a device such as, for instance, this NeoTrail is right here, which has four by eight grid of NeoPixels. In this case, the NeoPixels are underneath these little rubbery buttons. Let's say you have a grid of that four by eight NeoPixels, or same grid on this NeoPixel feather wing here. Let's say you want to turn on all the pixels in the first column, for instance, and you want to be able to treat all four of those as a single NeoPixel for the purposes of running an animation. You want to set them all to green, and then change them all to blue, and change them in purple, whatever. You want them all to behave as one unit. That is exactly what the pixel map class helps you do. You can define which pixels you want to be grouped together. It will then allow you to access those groups of pixels as though they are individuals and set their color all at once. You can build on top of it. You can feed it into an animation so that it can, of course, change the color of those pixels over time, animate something across them, or change the colors, pulsate different things or whatever. All that fun stuff. Catch up here again. Don't know about feather wings, maybe feather mainboards only for the 20% off, but it still looks like 15% on other stuff, so you're still pretty good to go, truthfully. I'll chat on YouTube if it's on the tablet so I don't have to switch back and forth. Nice. I've been meaning actually to find a tablet or maybe try my phone or something to get an off-screen chat. Right now I've got the chats on my other screen over here. It might be nice though to offload that to a different device, I think, and have that screen for other stuff. That's neither here nor there. I'm a lot on the make this little tweak and re-spin lately, both with my own stuff and with some of the breakouts nice. Always fun to make little tweaks and iterations on stuff. One of the things about software and hardware design is there's always something that comes up that you want to do better. Every time you make a thing and get it done, so to speak, as soon as it's done, so to speak, you're already coming up with ideas for things you want to change and do differently. That's always a fun time as well. Super fast iterations on CircuitPython. Yeah, that's definitely true. If you code with live trial and error on CircuitPython is amazing. In the REPL or just looking at the stack traces from your code, being able to debug that right away just by saving your code file and re-running your code file, really, really nice. One of my favorite things about CircuitPython, truthfully, is the iteration cycle of being able to edit your code, run it, get the output from it, and then make another change and save it and do it all over again really, really fast. Pixelmap, that's the class that we're working on. It used to be, or I should say it is currently inside the LED animation library. What has happened, though, is that Jeff, one of the core developers that works on CircuitPython, has implemented it inside the core. He added a Pixelmap class that is inside the core that does the same thing. It serves mostly the same purpose, but the parts that were the slowest of the original implementation are now much faster because they are inside the core. The core executes C code much faster than CircuitPython itself executes Python code. It's still plenty fast to do the vast majority of stuff you want to do, but there is no doubt that actual code inside the core is still much, much, much faster. So, Jeff has moved some of the slowest stuff into the core to speed it up. I am working on finishing up some of the changes to get it ready to actually merge in, and specifically what I'm working on is the Python layer that is built on top of the core class that will basically reimplement all the same interface, all the same API that the original helper inside LED animation had. So, to give you an idea of where we stand right now in this process, we currently have Pixelmap. It's inside the core. I have moved it to underscore Pixelmap, which I think I did off stream. I worked on this on stream a little bit last week, I think. I want to say I don't remember which day, but I think I did some, but off stream I have now moved this over to underscore Pixelmap, so we have that. And the other thing that I've done, which I also did off stream was work on the Python layer, work on the class that uses the core class that the user code will actually interact with. So, the user code, your code, your projects, your examples, stuff like that, that stuff will use the class from the Python layer, either in LED animation, possibly will make a different library for it with a different name, that part I'm unsure of, but your code will use that class and then internally it will use this core class, which is now in this underscore Pixelmap. The underscore, of course, actually the way to sort of show the intention that it's built in. It's not meant for most code to actually use this. It's really only meant for the one Python class here to use it. Maybe this moves to a different library or whatever, but this is really the main thing that should be making use of underscore Pixelmap. Everything else should be using this, and it kind of hides the internals from you, adds a couple of extra features that are not there by default. Let's see how we catch up on the chat here. So true, yeah, with the iterations. What's the difference between Pixelmap and RGB matrix? What did they do about the same kind of thing? I cannot, well, so I cannot say for sure, because I don't really know that much about RGB matrix. I think what I think the difference is is that RGB matrix helps you filling in like matrix portals, for instance, those big panels of LEDs, which I think of as a matrix portal, although the matrix portal itself is actually just the device and not the panel. But RGB matrix helps you fill in these panels, which we can't actually see a still shot of, I guess, but we get the rotating one here. So RGB matrix helps you fill in these things, helps you draw stuff on them, pretty much as though that it's a display. And then Pixelmap is for basically combining multiple pixels to behave as one. So being able to make all four of these pretty much behave as one pixel, or being able to make all eight of these in this row here all behave as one pixel. So you could just set a single value to red, and all eight of these will turn on at once. You don't need multiple sort of lines of code to say, like, set this one to red, set this one to red, this one, this one, this one, you don't need a for loop, you don't need any of that stuff. You set up your map, and then you just tell your map, you know, set index zero to red, and it will do all the rest for you. That's my understanding of the difference. But bear in mind, like I said, I don't know that much about RGB matrix. So yeah, that's what I got. How's it going? Kiyoshi over there on Discord. Thanks for tuning in. Happy to have you. So right now we have this stuff mostly working. The place where I'm going to jump in is some of the helper methods that generate kind of special kinds of these maps, basically. Oh, I don't have the device plugged in. Let's do that plug in the device. I am just going to be using the Neo Trellis for right now, and then we'll also test this out on the Feather Wing there that I've got on the Feather TFT. We'll get to that here in a bit. Let's refresh this, refresh, reload, reload. One works with addressed LEDs, the other works for matrices of LEDs. Yeah, that's a good point as well. So you get a good difference between the two. So the specific place where I'm exactly jumping in is in what I'm going to refer to. I'm probably going to say this over and over again. I'm going to say the old version of Pixelmap, and really what I mean is the currently released version, but it will become the old version if and when this new stuff comes in. So just a heads up, when I say the old version of Pixelmap, I mean the one that's going to become old when we get the new one in. It's actually technically the current one still right now, but I'm going to be calling it the old one because I'm working on the new one. In the old version of Pixelmap, there were these helper functions called like vertical wing or vertical lines, and there's a horizontal one as well, horizontal lines. And these are basically, they're like special constructors. They basically, they take different arguments than the constructor. As we go back up here, the constructor, it takes a strip, which is a neopixel object. It takes a pixel ranges, which is a tuple or list of tuples or lists. And then it takes a Boolean individual pixel. So that's what's in the constructor. These ones here though, vertical lines, it takes a pixel object. That part's the same, but then it's a bit different. It takes a width and a height and a grid map. And then horizontal lines is a similar kind of signature. It takes a pixel object, takes a width and a height and a grid map. And these will like, these are like helper functions that generate maps for kind of like well-known, I guess, well-known grids or commonly used grid patterns. So basically, there's a real easy way you can use one of these helper functions to generate the map for this eight by four grid that we have on the NeoTrailers, for instance. That being said, I don't know the code. We're going to have to look in the example to find it, but we may as well grab it because that's the code we're going to be working on, which means that's the code we're going to want to test. Example, I think, where could be this one maybe map, LED animation map. So this sequence, yeah, this uses it. So vertical lines, this has given it eight by four. And it has given it, okay, for the grid map, it's actually called another helper function. And it's done horizontal grid map, eight, and then alternating false. Let's go look at horizontal grid map also. Horizontal grid map. So that was down here. Okay, so we have horizontal lines, and then we have vertical lines. And then we have one of each vertical strip grid map and horizontal strip grid map. So this takes a height and then an alternating returns of function that determines the pixel number for a grid with strips arranged vertically. Alternating is whether or not the grows in the grid alternate directions in a zigzag. And the reason why that exists is because some grids are wired like this, where they would sort of grid zigzag back and forth. In fact, I think maybe this one is. We'll see when we initialize it. But this alternating allows it to work with those ones that snake back and forth. Addressed LEDs have built-in pixel memory. Ah, okay. And then the matrix, they don't, right? The matrix, you have to keep sending it over and over the color you want it to be. Is that the idea there? Um, so to start with, I assume, I'm almost certain this will just not work, right? Like, if we go pixel wing vertical and we're already making a pixel wing, well, we're only making the horizontal one these days, actually, I guess. I say these days, I've cut some of the code out. This example came from probably the same place. I've been tweaking it as I've been working on this stuff, though. We will try this. That should be fine. Probably Helper is not imported the right way, I'm guessing. We can maybe go, oh, we got this down here. Weird to import this also. You probably wouldn't want to do this for real, but or is that, oh, that doesn't, is that not working? Helper still doesn't see it. Interesting. Okay, so we would need to be, like, as Helper, or I assume this will not work? I suppose I don't know. It actually might, it may have worked. We might have, like, lucked into it just does work because of the instructor we have. I was kind of assuming this would need to be changed. And maybe it still does, but we'll see, I guess, right? Maybe this just works. Let's see if it actually did what, what, you know, let's see if it actually did what it should. You know, what's probably gonna be a good thing to be able to do here is be able to change back and forth between new pixel map and old pixel map. So I'm gonna, here's what I'm gonna do actually is I'm gonna go into my lib folder. I'm gonna, yeah, I'm gonna change this to be new. And then we're gonna get a copy of the current existing one. I want a Python copy or should I just get, I think we just could get MPY, right? Let's just use Circope. Circope, install, Adafruit, LED animation. This way we could switch back and forth and make sure they do the same thing. While that's working though, let's take a look and see if it did actually do something that makes sense. So set up pixels, we set up horizontal wing, we told it eight by four, we gave it this helper for eight, set alternating false. And then we told it negative two. So this is one of the things that's now working with the new Python layer implemented as we can now use negatives for anybody that did see the most recent stream I did, which would have been on my own channel, not last week's deep dive, but the most recent stream I did. I was working on, or maybe we didn't work on it on stream, but I was talking about the negatives not working. That was one of the things we noted that it'd be nice to have. These now do work. And it is, yeah, I do think it's doing the right thing, right? It's got horizontal lines, and it has set the second from the last horizontal line to yellow, which in this case, we ended up with four horizontal lines. We should be able to say something like print length, this and it should be four, I think, right? Yeah. We got our four lines. We are saying the second from the last, which is this one, the last one, of course, would be down there. So that part is actually seems to be working just fine. Let's do the vertical ones as well, just to test them out. And then we'll try out some more of the examples. One of the cool things about the way these maps work also is you can create multiple maps, and then just arbitrarily choose which one you want to set pixels on. You can set up the same grid of pixels with multiple different contexts or whatever, and then within those contexts, you can set those groups of pixels however you want. So it makes it very easy to switch to entirely different sort of displays on the pixels by having different maps that associate with different sort of visual outputs. The code here is pretty much the same. It's just vertical lines instead. This is interesting that it is horizontal. You'd think that would be vertical, right? Let's try it like this, and then we'll maybe also try changing it and see what it does. So that makes sense, I think. What would happen if we did vertical here? Would it be wrong? Would we need to change this to four? The thing is I don't actually know exactly how this stuff works, and I am a very visual, like, just changing it and running the code and seeing what it does is really the best way for me to learn. Guessing that we probably need to take that down to four. Interesting. We have eight things. We have two stacks of four by rows. Let's loop through them. So we'll go, let's just go time dot sleep. I will just say wait a second. We'll say four, eye and range of, can you loop over four group, pixel group in? Can you loop over them like this? That would be pretty cool. I don't know if this works, though. I guess one thing is that we'd want to turn them back off before as well. That's also, that's probably way too fast, right? That's going to just go so fast so we can't see it. I think this syntax works. I think we need, there might be a way to do it, but I think this is probably wrong. I think for now I'm going to just use an index. So let's say range of length, this, and then we go vertical, eye. It'll still be too fast, though, right? It doesn't seem like it does anything, though, because I would expect it, I would expect it to change to the last one, which I would assume would be over here. Should maybe fill also before we loop? It's already done. This is how I code most times through. Just throw stuff out and see what works. Yeah, totally with you there. Didn't know that. Yeah, dot collect displays versus RGB. Makes sense. Thanks, C Grover. Yep, definitely agreed. Press the color and brightness setting, not requiring continuous refresh from the microcontroller. That's the address, address LEDs are the ones that don't require the continuous. So it's interesting. I feel like nothing is changing when we do the loop, right? We're supposedly looping and it is super fast. I will give you that. It's super fast. We probably wouldn't see it live, but I would expect to be in a different position when we're done, because this is minus two is yellow, which is second from the end. So I assume this is the last set in this particular mapping, but this one doesn't turn on and this one doesn't turn off. Anything turns on. They're just not changing. In fact, even this fill doesn't work. We have auto show off, which you actually wanted that open. Can you not do auto show? I guess maybe after you create it, you could do it. It's like you can't do auto show in the, in these special constructors. Where's helper? It's old too though, right? So also worth noting at this point, we would be back to the current or old version of the helper. Just I think it is show, right? It's got to be show. And we don't have a way to pass it through these special, what I like to call these special constructors, these vertical lines like this. This is just a, it's a class method, but it's truly it's kind of more just like a special constructor. It creates an instance of the class. This creates an instance using a different method signature using different arguments. And it doesn't have a auto show. Yeah. So we could, we could just set auto show after we create it though. Not doing anything. Oh, we can't, oh, I didn't save it. Why it re-ran? No, it's still not doing anything. Maybe auto show does not work like that. Auto show equals true. Auto write. I called auto show in the constructor. It doesn't, it actually doesn't exist in the constructor. Where am I? It just, one thing is auto show. Auto show. Right? So right. Yeah, everything's auto write. Love show. No idea where I got that from. Auto write though. It's weird that auto, it's weird that if auto write is true, then the function you don't need to call is called show. This should either be called write or this should be called auto show. I think one of the two. I don't think I have a strong preference either way, but I think having one be write and one be show seems odd, right? Now we're going. That is what I was expecting totally. Okay, so really the thing we were trying to visually see here, which we now can, is what this did when we changed our thing to vertical. And basically it made it so that we could get these columns of half-sized instead of what we had before, which was full-sized rows. Oh, no, full-sized columns happened to be four. Horizontal strip. So it's kind of, it's defining the, finding the direction that your grid is going to go, although grid's going to go both directions. So which, let's see, where do I start to learn to code? Kerry James, where do I start to learn to code? Devon says, which languages do you want to code? Yeah, I would say even more broadly, what do you want to code? Like, is there a specific project you have in mind? Is there a specific thing you want to be able to do? Are you trying to play with microcontrollers like these devices? Are you trying to make like Minecraft plugins? Are you trying to make a game? Are you trying to make a plugin or an add-on or a mod for an existing game? Are you trying to get a job? Like what, what is your goal? Like what, what, what is the actual project or a thing you want to do? And then from there, you kind of can narrow down what type of programming stuff you would want to start learning first. And then from there, you could start thinking about how is the best way to learn that stuff. But a couple of steps, I think, that are important to understand before I could really suggest much of anything. Okay, so let's run the full, let's run the full example of pixelmap thing here for a job, for a job entry, for a job entry. So I would say, I mean, it's going to depend a lot on maybe where you're at geographically a little bit, like different companies, you know, hire different kinds of developers in different geographical places. You know, web development, there's certainly a lot of people who are employed for web development. I would say web development is probably a pretty solid thing to start learning if you know no other programming. And if your goal is to try to get a job programming, I would say like web developments one of the things that might be good to learn. Another one possibly would be like Python and writing tests. I mean, these are some of the sort of like entry level things that you might be doing at a, if you get a job at a larger company is like starting by writing tests or by making like basic web pages, stuff like that. Those are two kind of different worlds, web development and sort of like Python testing back in stuff. But I mean, they're both like fairly entry level as far as jobs go. Truthfully, my best advice would be to come up with something that you are interested in and passionate about. So think of a program that you can make that interests you. If that means that it's a website, you know, a website is pretty much a kind of a program.   Make a program that deals with that. So, you know, maybe make a website about one of those things. If it's like a thing you could do, like, you know, if you like playing Dungeons and Dragons or some other game or something, make a program that helps you play that game, like it rolls dice for you or it stores your characters or it just does whatever right makes something that is kind of like works along with something that you care about and are passionate about. Because if you make programs about the things that you love about the things that you're interested in and care about and just do like occupy your time with, then you'll get more practice and the really like king of king of advices, the best advice I could give anybody wanting to learn to program is practice, practice, practice, practice, practice a lot, write a lot of programs, read back through your programs, change your programs, modify them to do other stuff, practice a lot. The more you can practice, the better you are going to be and it's easier to practice, it's easier to be motivated to work on stuff that you find interesting and care about. So, that would be kind of probably my best advice that I could give is find something that you're interested in, make programs that deal with that and that's kind of what I think is probably the best way to learn. For web development, think you can't go wrong with JavaScript? Yeah, JavaScript makes a really great language for learning how to code. It's relatively basic. The syntax is not too bad. There's lots of basic, there's lots of really good resources these days for learning JavaScript at a basic level. Yeah, like Devin says, pretty much everything on the web runs in JavaScript. So, if you learn that, you definitely open up a huge world of possibilities as far as different kinds of things you can program if you learn JavaScript. I have a saying for coding, if you're not frustrated, you're not learning. Yeah, that's probably true. Read lots of code, especially read code written by coders you respect. That's really good advice. Yeah, reading code is, you know, half of if not more of the job, right? It depends on this specific place where you find yourself working, but like reading and understanding code is not, it's not the thing that comes to mind when people think of a job being a programmer, right? When people think of a job being a programmer, I think most people are imagining the writing of the code. But a huge portion of the job is reading and understanding code, whether it's code you wrote, you know, a year ago and you no longer remember it as familiar familiarly, or it's code that somebody else wrote, you know, it's open source code or it's code that a coworker wrote or whatever, right? It's just company code like reading and understanding code and then being able to take what you've understood and implement it to do something, you know, in some other portion. That is a huge skill that doesn't like, it's not, it's not showy or flashy or whatever. It's not maybe as cool or as interesting sometimes as writing code, but it is a huge part of the job. For sure. Watching coding streams like FOMA guy helps. I can code and still learn from other coders. Learning never stops. Yeah, 100% agree with that. The loading never stops. Learning never stops. Websites can lead to anything and everything. Circuit Python website, yeah, for sure. I mean, if that's, if Circuit Python is the thing you're interested in and you're looking to get started with web development, you know, make a device, make a page that's about your favorite device that shows maybe sample code and pictures. If you're looking for kind of like the next level up, right? If you're trying to level up and make something even more kind of complex or whatever, you could make a web page that interacts with the Circuit Python device. Maybe it connects over the network and sends HTTP requests back and forth to the device or maybe it connects over USB or connects over Bluetooth. That's kind of a next level thing where you could make a page that interacts with the device directly. Just a whole world of stuff that you can do with web development for sure. Also remember that computer used to be a job for a human and it's, and it still is a little. Yeah, there's a lot I think of human element. We're doing a lot with computers for sure, but it's a lot. At the end of the day, like humans are still a huge part of the loop, I think for sure. Lots of Pico W web server. Yep. Yep. We did a, did a trivia project a couple of weeks back that was a web server that ran on the Pico W and I did not make a fancy web front end, but I did have a front web front end. I agree with FOMI a lot of times, spent reading existing code, found working effectively with legacy code. Feathers, Michael, very helpful. Nice. I'll have to look into that. Working effectively with legacy code. Feathers, Michael. Okay, so we're going to take the larger example here, which is this whole example. We're going to basically run all of this. I will keep, I guess I'll keep what we have here. Let's just go, go copy, paste, code pie, and let's call it, so map testing. I do, I already have that. We have pixel map tests, so map helper in it testing. This is kind of a long name for a file, but you watch my streams a fair amount. One of the things you'll learn is that I like to keep the files I work on a lot of the times, and I like to give them descriptive names even if they get kind of long. You guys are awesome. Thanks for the depth of information you all have offered. Yeah, for sure. Let's see here. I have no idea. I may be missing some stuff we need for this. I'm sure there's some reason why it's not going to work. We're not setting up the pixels correctly for one thing. Okay, so first of all, brightness, let's chunk that down. Neopixels are bright as heck. I don't, anybody is not familiar with using neopixels. Like even this was on 0.5, which is half brightness, and these are diffused by the little rubber things here. That's still probably going to be pretty bright. 10% will be plenty, plenty bright. When it comes to neopixels, you know what I always think of when I think of neopixels and setting the brightness is that scene in Iron Man where Tony Stark is first getting the launchers on his feet or whatever, and he's testing certain strengths of Rocket or something, and he tells the computer to go at, I don't know, 10% or whatever, and it shoots him through the ceiling or something. This is how I feel about neopixel brightness. I'm always just a little bit, we want it real, real dim, just barely, and they are still bright as heck. Anyway, let's see. We want to go to just board.neopixel, it should be wherever, where is it? Oh, okay, here it is. Neopixel, I think. Neopixels. Okay, this is a good, perfect example of why we save our code sometimes, just copy paste it. 0.5% is plenty bright. Yeah, they are very bright. Very, very bright. I guess it didn't rerun because it was crashed, or I didn't save it, okay. If I didn't rerun, I didn't save it. Ah, there we go. So, this uses the pixel map for a few of the animations. This is one of them. Pretty much any of them where multiple lights are doing the same thing at once. Like this one, it's using it for, I'm pretty sure. This one, I think, probably, yeah, because the columns are mapped. This one, yeah. Most of them, except for, like, maybe the first one. The first one where it was just, like, all of them on, like this, this, I think, is probably not using a map. This is probably just individual pixels, but then all of these, basically, all the ones where there's lines, that's probably a better way to say it. All the ones where there's lines, either vertical or horizontal lines, that is the responsibility of the map, is making those lines work. And so, right now, we are importing the old version of the helper. What I'm going to do is I'm going to keep the rest of the imports on the old version, because none of the rest of that stuff's going to change, I think, but I'm going to change the helper to the new. And so then we'll be creating the new type of pixel map, which is using the new core object, and we'll be able to see if it crashes, or if everything works the same, or what. So far, so good, actually. I think we're good. I really was thinking that these functions would need to change, but it appears they don't. I mean, I guess it, I mean, it does kind of make sense. Yeah, I was, I mean, the main thing I was thinking is like this would probably need to change to be the core object, but in hindsight, that doesn't, that doesn't really make sense, right? We would want this to still be the Python object. So we would want this to still be what I'll call helpers.pixelmap, not the core pixel map. And then this helpers.pixelmap, this one holds an instance of the core pixel map here. It basically wraps that instance of the core one. It adds a few bits of functionality, like these helper initializer functions, also the individual pixels false. Portion of the API, like, where is that document that up here? Individual pixels here. This is true false, whether the pixels are ranges or individual pixels when you create the map. The core one doesn't have this functionality. So that's like the Python one, the helpers.pixelmap keeps this functionality and it will just handle it and send the right stuff to the core one. So we might be good. Honestly, the only thing really that might be left here is, and I probably need input from somebody else. Because I was thinking these would have to change, but now that we're here, it doesn't look like they do. So we're actually further along than I thought. Yes. Yeah, this Iron Man here, where he's, yeah. Or, oh, this is a different one though, but this one does accurately depict the brightness of the NeoPixels as well. If you aren't digging into someone else's old code, you're doing it wrong. Definitely agree there. Looks, let's see.  It might sound weird, but I actually wanted a way to make the goggles brighter. Thank you for the idea, for sure. See now why the lines are special helpers? They're great. Yeah. The lines, if you're interested in doing, like, if you have a grid and you're interested in doing more complex things where you have multiple pixels behaving as one, the lines, and I'll say currently the current helpers that exist, the current classes that are made for this are lines, it could actually be different things too, though, right? Like it could be a diagonal one or it could be the outside row, you know, the outside entire loop around is one group and the inside is another. You can make the groups arbitrary as well. Lines are a good example of what to do with it with one thing to do, but yeah, you could totally have arbitrary things as well and treat them all kind of individually or treat them as groups and as an individual pixel. You can do some fascinating stuff. When Jeff was showing the letter stuff that he's working on, it was making me think like you could have a map that represents where each index is one of the letters. That would be like a primitive way of doing text. I think what he came up with is probably better than that for lots of reasons, but it was one of the ideas I had is like you could actually make maps that instead of representing rows or columns, each index represents a letter that's like made with the dots in that letter or whatever. Okay, so honestly, really the open questions I think are should this be in its own library or should it stay inside LED animation? That's an open question. I don't necessarily have the answer or a particularly strong opinion. I could see I could see upsides and downsides both ways. I don't think it necessarily matters too much, but that's an open question. The only other thing I think is the get range. So right now we have the ability to get the range. I could do something like pixel wing vertical. Let's do it inside of here so we'll actually see it change sometimes. Pixel wing vertical, print a range, let's say just zero to three for nice and easy. This will print the colors of these items in the in the map. So sometimes they're all black, you can see it goes to black when they turn off, when they turn on that goes to colors or whatever. This is allowing us to basically check the colors of the neopixels and specifically to check those groups, which in this case are those vertical lines inside the grid. The ability to get as a slice like this currently comes from the Python code right here is the code that is right now responsible for handling that. Conversely, on the set items, if you're setting a slice, it actually is not handled in the Python code. It actually does go straight into the core code. So the core code is able to set slices, but not get slices. And so that's the question is should the get slicing be implemented inside the core? Or should it stay inside the Python layer? And I don't know what difference it makes. I don't know if this is a slow thing to do or not. If it is, then I would assume we probably want to move it to the core. If it's not that slow, then it probably doesn't matter. And we just leave it in the Python layer, but I don't necessarily know the answer. So I think what we'll do is let's look for any other tests, first of all. Let's look for any other examples that use Pixelmap so that we can actually keep trying them out, make sure all of the examples are going to keep working. Just the one right now. Yeah, just the one. Do I have the learn guide repo yet? I don't know if I do. I do. Let's check the learn guide repo also. Quite a few that use it here, but are there going to be any that we can do anything with? Like a Python eco PO? It would be fun. I've never, I have not played with PO really at all yet. Can't do that. Yeah, no, yeah. The NeoTrails isn't quite as quite big enough. Some letters need a fifth row. Yeah, you can't express every character very well. There's some characters you can get away with, but some of them you can't really. I want some Brandolene's LUMOS stick. Benchmark a lot of LEDs. Brandolene's LUMOS stick. I don't know if I'm familiar with that. So there are a couple others, but I'm wondering what the hardware? NeoPixel, Crystal, Chandelier, Minora, the PO. I'm actually, I'm interested in PO. I have not done anything with POs. There's a snowboard, back to the Minora, Chandelier. I think I got two copies of everything, honestly, in the ukulele sunflower. Let's look briefly for those real quick. I don't know that I'll be having the right hardware to do any of them, but oh, Brandon, Brandon Lane, excuse me, Brandon Lane is the PCB designer, I gotcha. I'm curious to try this one of these days. I don't have enough, I don't have that many strips though. I have one. I don't know that today's the day for that though.  Just strands or, yeah, oh rings, actually rings, and then individuals. Erin's got some really cool NeoPixel stuff. I was interested when Erin pops into show and tell to show the latest, the latest stuff she's working on, stuff. Here we got a couple. We got a Minora sweater as well as a 3D printed Minora, sunflower mobile, probably is rings. Oh, that one's a strip. Okay, so maybe it would be worth double checking them at some point just to make sure we don't break anything. I can't imagine we would now that we've seen it run both ways, but Talgrid, good to Talgrid with a bunch of common settings. Oh, okay. Erin's stuff is amazing and beautiful, yeah, for sure. So glowy, glowy and fun. Okay, I think we're good. They're really the main thing. I'm just going to leave a comment to make sure that this PR here is up to date with kind of my latest, where I think it's at. So jellyfish, Wi-Fi mesh is really neat. Jellyfish, a lot of applications. I haven't seen that one actually. Mesh, I'll have to check that one out. Maining open items for consideration are, is it helper or helper? I think it's helper, isn't it? It's an S. The get slice. Anality is currently implemented. Python code only. Two or should be moved. And here I think we asked Jeff. And then one other thing that I'll mention is negatives. Right now, negative indexing works because of the Python code. The core, itself, raises an exception. And then I'll say, speaking of exception, I'll say possible out of range exception. If there's a resident legacy keyboard deity, yeah. Not Wi-Fi, but mesh Bluetooth. Haven't looked deep into it. This is wide. U-A-E-D never used that before. Not sure. All I know is microcontroller lights sync together. Very cool stuff. Nice. Oh, you know the jellyfish. I do remember seeing the jellyfish actually. I think she showed this on show and tell. I do remember because she talked about, she showed one and, and I think made a guide to show the process and then talked about having made like 20 or something. Like she made a lot of them. Kind of perfected the process. I do remember that now. Let's see. Possible out of range exception mentioned by Gambler. Hanging lights. Yeah. Kind of like Japanese lanterns with iridescent material. Look like a jellyfish. W-L-E-D. W-L-E-D. Not W-I. Could we maybe, let's test one more context as well. Since I've done literally everything on one device, we should probably just double check that we can recreate everything on a different device as well. So I'll use this one also. Bitch. These recent streams have me thinking about writing Circopath and Helper to add slicing functionality to display IO pallets in group. That would be pretty sweet. Yeah, I was looking around. So the idea of implementing the get slicing inside the core had me looking around in the core to see if I could find anything else that had that functionality. I came up empty, but I was looking into pallet and group and I think it would be cool if we had slicing for that. If it can help when using microlab, thinking that it could improve performance for managing animated display objects. I have a hardware project to complete first though. Yeah, slicing would be pretty cool on pallet and in group. I was looking for negative actually as well. I meant to check. Does anybody know if pallet supports negative? That's probably easy enough. We could do that real quick, couldn't we? Yeah. So maybe I could go look at pallet internally to see how it handles the negative if we do want to implement the negative handling inside the core rather than inside of Python layer like it is now. In the meantime though, this has compiled. We'll get to the bootloader. I think these very tiny buttons. Probably this has got my, yeah, the time stamper on it. Backup already exists. Is that in there? And we might even be on pin D6 now. Oh, that is so bright. Oh my goodness. See, I was talking about it earlier. I even set it. I set it earlier and I still did it. I'm like, mind now. Even that's quite bright in real about. That is like nice. This I can like comfortably look at and it does not hurt my eyes. Does look like we're doing good though. I know it's kind of washed out here. Maybe I could turn this off. It would maybe not quite as washed out, but it would also be more blurry. So I suppose it's still kind of washed out anyway. The brightness is much for it. You can at least see the color from the sort of glow effect though. We'll face start to change colors nice. These eyes, yeah. Okay. Yeah, I can't believe I'm usually I'm usually honestly pretty good about that. Like, I've gotten to the point where I instinctually lower the brightness before I run the code most times. But no, I definitely went face first into that one. Turn this back on so it'll wash it out kind of and make it not quite as overwhelmingly bright. Well, it's actually not too bad now that we're on to the low percentage, but everything does look good to me as far as that. So we did test it on also a different port and a totally different grid of neopixels and so far so good. Oh, well, I guess though right now though, yeah, hold up though, because now we are not running currently what we're running is the real version of the library. So we'd actually want to delete that. We'd want to get our modified one. So of course everything worked the same for there. What we want is our modified one. We are going to put that inside lib. And then what we'll do is we'll change the import of helper with the same way as before where we could go through and change all of them. I mean, I guess there's no reason not to, right? Let's do that. Oh, well, actually no. Yeah, we don't need to change it here now because I just pasted the new one. I'm thinking the other device where I renamed it to new, but no, we just pasted the new one on here. This is already the new one that does use underscore pixel map. Yeah. And it does seem like it's running fine. Keep my neopixels either turned away or covered up. Yeah, covered up. I do a lot of times I'll throw paper or something. I don't have one of the acrylic things. I should get the little acrylic ghosty thing that makes them look real nice. But I will, a lot of times I'll put a sheet of paper over it. It's plain white paper kind of diffuses it pretty well. Okay. So we, yeah, we're good on the new version on this device. Everything seems to be going fine here. Okay. Put that there. This contains all of our latest updates. We actually were farther along than I thought because I was thinking we still needed some code changes. But it turns out at least as far as I know for now, we don't unless we want to do the get slicing inside the core, or we want to handle the negative indexing inside the core. Those would be two changes possible. But I was expecting to have to change the Python class tonight, and we actually didn't. So we do have time to get into my next thing, which is also in the core. And this is in DisplayIOland. Frequent viewers of my streams will know that I spent a fair amount of my time in DisplayIOland. That's one of the things I'm kind of naturally drawn to about Circuit Python. This is interesting. Why do we have, oh, okay, I thought this was, okay, this is not the core. Like why do we not have the rest of the PRs? I know there's more PRs than this. So in the core in Circuit Python land right now, the thing that's in motion is changing the API for display.show. I was about to start an Instagram API, but it was trying to force me to make a Facebook developer account, and I was like, um, yeah, no, yeah, I am with you there. Facebook is, let's just say, not very high on the list of things that I like. Gotta leave it at that. So on this effort, this is something that we did actually stream about last week. And the idea here, which we can't actually just keep using the Feather TFT for, the idea here is that we want to change the API that is used when you show something on a display. So let's take like one of the most basic examples we can, which is just maybe the display text sort of simple test. Oh, wow, I don't have that one in my Facebook yuck. Yeah. That pretty much sums up my feelings as well. Bitmap label flicker. I haven't actually looked at this 10 days ago. I missed this one. Take a quick look at this. Bitmap label has varying degrees of flicker when used with a display frequently changing data. It's very noticeable and occurs regardless of the BOD rate, switched from a regular label to save memory, but immediately notice the difference. The regular label has no perceptible flicker during updates. Interesting. We'll have to try this out. I think this will be a different, I think this will be a different day's activity, but I am curious about this. This is odd. So it's basically just changing the text flickering. I have not personally noticed any additional flickering of bitmap label as compared to label. I can't say as though I've like looked super closely for it. I will say like, our display system is not perfect. It is still running on a microcontroller and it is still relatively new and stuff as well. Display IO itself only started with Python 4 or whatever. It's definitely not as sophisticated of a display as if you're expecting a mobile interface type experience or something. It's not quite there yet. In terms of the snappiness and the ability to move things around quickly without artifacts and stuff, we're not quite there. It's pretty good. It's getting better all the time, but it's definitely not, you know, it is still a microcontroller. That's what I try to keep in mind is it's running on a microcontroller with like a 100 megahertz computer is like on the fast side. So really what we want is just the simple test I will look into that though because I am even I'm always fascinated with display IO stuff and then even more specifically label is actually one of the first things that I ever did in Circuit Python. So label is actually one of the things I'm most in tune with. One of the things I'm most familiar with is the label library display text. Some of my first contributions were inside the label library. I will reset this just because it will turn the LEDs off, I think. I will unplug this and replug it in because it will turn the LEDs off, I think. Okay, this is very tiny. It doesn't really matter for the purposes of this. I could scale it up. Sure, we can do this. That's cool. The truth is though the size of this doesn't really matter. The main thing that I'm talking about here is the way that we're changing the API for showing stuff on the display. The old API, I'll go back to this terminology where the thing that I'm saying that's old is actually current. The thing that I'm calling new is what it will be if this stuff gets merged. This is the old way of doing it. The new way would be board.display.root group equals text area. Instead of calling show passing in text area, you're setting text area into this property root group. This would be the new way for showing stuff onto the display. Functionally, it's pretty much the exact same. You're still taking the group you want to show and giving it to the display. It's just that you used to give it to the display by calling show. Now you give it to it by setting it as a property of root group. This is more closely aligned with the intent. When you're calling show, you're setting the group that will be shown. You're setting it as a property. We try to use properties when the verb is that idea of setting a group into something, setting a thing into something. We try to use properties to express that throughout CircuitPython in the libraries to try to keep things similar. This was an idea that popped up a couple weeks ago in the meeting. I'm working on implementing it. Right now, we don't have the version of code that has this new thing in it. We need to get that. Let's get tricky here. I think, though, I'll go here first. Then I think the none stuff one is where I started working. We'll probably be going over to that here in a minute. I'm going to do a clean on this just so we flush out the stuff from our old build. Then we're going to make a new build. Of course, now we're on a different branch. Technically, we're building the same device, but we're not building the same thing. Now we've got different code with display.io stuff. Only happens on bitmap label and not the entire display. I haven't seen that before. That's what the issue was saying, the bitmap label, and specifically the bitmap label and not the regular label, which is the part that's ultra weird. They are different, but they are not that much different, really. I would be surprised if there were significant artifacts in one and not the other, but it could be. Bodrate has a max clock and will flicker if you're trying to overclock it. Yeah, one of the first things I noticed about that was that it was an external display. I'm curious if the same thing is exhibited on an internal or one with the Pi portal, which I think connects via the parallel connection instead of spy. I think it has more wires. It connects with eight wires instead of four or something. It can send data faster, I believe. I wonder if those types of displays work the same as well. Is root group really a group or just a layer? I'm not sure if I understand the question all the way. Layer, I don't think there is a specific thing that is called a layer. Conceptually, the idea of layering things on top of each other, I think I'm with you. I know what you're talking about, but there is not a thing in display that is called layer. There's no object by that name. Root group is just a group. Root group is a regular group, just like any other group. To be more specific, root group is the instance of the group object that is currently showing. Here, we're making a text area and we're setting it into root group to say this is the group that we would like to be showing. What we could do if we were to access it before that, obviously printing it doesn't do a whole lot, but just to show you what I'm talking about. If we were to access it before this, root group, it will look up the currently showing group, the same thing that it was going to be doing before. In this case, it doesn't tell us anything useful about it, but this would actually be this group right here, the group that has this tile grid or this terminal IO, this grid here that allows it to print the serial stuff and it has its little blinker. That's what would be inside the root group before you set it to anything else. You can get back to that as well. Part of the same API is making it so that you can get back to that terminal serial out. Try saying, yeah, I'm failing at saying it one-time regular speed, so I don't think I'm going to make it very well for 10 times fast, unfortunately. It's quite the tongue twister. Can you append to the root group you can? You can append to it after you create it. If we instead said main group equals group from playo import group, we said main group equals group and then if we said main group dot append, no actually we could say main group equals group and then you could go now we're going to set it here. Let's get rid of this for now. Let's get rid of this for now. Let's say we're going to set this, but we're going to go main area, I mean main group rather, and then now that you have it on root group, you could actually go like this, board.display.rootgroup.append text area. You could add it now that once it's in. Although none of this matters if you're still on the old version of Circuit Python that doesn't have this functionality yet. Let's actually install the version that we just built.  That was so weird. Oh yeah. In my browser, if I click on an image and drag, it will drag as though I'm going to drag and drop the image even if there's no valid place to drag it to or whatever, and I do. I use that to point at stuff. Sometimes I'll click and move around it like that. Okay. We can see that one works. Once you set it to root group here, you can append to it theoretically. If you wanted to, you could even just append to the existing one. This would add your label on top of the serial out. Obviously, this makes it difficult to see the serial and stuff. You're just writing over the top of it or whatever. But the terminal group, the Circuit Python terminal group, is just a plain old group. You can add stuff to it the exact same way that you can any other group, and you can access it. One way is just by accessing root group before you have set anything else to it. The other way to access it is by it has a new constant. Let's change this up a bit. Let's say we did do this, so we would now be showing only our label. Only our label. The hard fault crashed. All right. Well, we want to figure out why that happened. I think it not happened, probably. I think maybe this is partially, I don't actually know. Anyway, though, so right now we're showing main group. If we wanted to, we could go wait for a little bit. Circuit Python terminal. This will now show our hello world group for three seconds, and then switch back to the terminal. This is the second way for accessing the terminal. You can either just access root group before you change it, and that will give you the terminal group. Or you can always say display IO dot circuit Python terminal, that will get you the reference to that group that has the terminal output. It's confusing to call it underscore group if it doesn't act like a group. No, it does. It does. It is literally a group, and it does all the same things that groups do. It is in fact a group. It's really just a container for the currently visible group, if I'm understanding it properly. I mean, it is the currently visible group. The property, I guess you could say, setting into the property. I mean, I'm not sure if I understand, I guess, the distinction. But in my mind, it is a group. It does behave just like a group does. It just on a display object, this is the group that is being shown. But it is still a group, right? It's not a different kind of concept than a group. It is still a group. It's just the one that's being shown. You can get it if you want to know which group is being shown or get a reference to the one that's being shown, or you can set it if you want to change the group that's being shown to a different one. And either way, you can access it and manipulate it just like a group. So append, slicing, whatever. I forget. There's other functions. I think there's like a dot index function, maybe a couple of different functions in group that allow you to do stuff. I'm not remembering all of them off the top of my head. X, Y, all that kind of stuff. You can all do all of it by accessing group. And so the next thing that I was working on with this was what happens when you want to set it to none. So the way it works today is actually none is kind of a special value that pretty much means the same thing as this. So when we ran this code, it showed our main group with our label, it slept for three seconds, and then it went back to the serial. You know, if we didn't go back to the serial, if we just let it go like this, then it will show our label and it will stay there forever and ever and ever. But the old way to do things is if you wanted to go back to the serial group, this did not use to exist. So the way that you would do this before is you'd actually call show, but analogous to calling show in the new way is setting root group and you would set it to none. And by setting it to none, you would be telling it to go back to the serial thing here. So now we get back to our serial output. But what we actually want to do is make it so that none will display nothing. And so that is kind of the last bit that I am working on this so far right now is making it so that when you set this to none here, that it would actually show nothing on the display. Conceptually, it appears to be the pointer to the group you want to the display. Yes.  So like in my mind, it just is the group that I want to display. But I can see how the distinction between a pointer to that group versus the group itself could be important. And maybe I'm not the best person to like say one way or another on that since I have only a loose understanding like I know what they are and kind of how they work, but not like I don't have a fundamental conceptual understanding of it. Truthfully, I kind of can use them in code and I know the syntax a little bit and that's about the level of understanding I have. But I think of it as the group like it just is the group. Like after you have done this, then accessing it like this board dot display dot root group this once you have set it like this, this is exactly equivalent to using main group. So anything where you could use main group the variable, you could instead now just use this and it would be the same the code would do the same thing. So it's like a variable that holds that group, the group that's showing new none for power saving. I don't think it will affect power saving. Yeah, I don't I can't say for sure because I don't know hardly anything about the powers, the low power stuff truthfully so I can't say for sure on that front my understanding though is I don't think it would affect that really what it's for is just making the API match expectations. If you didn't know any better and you just read this code, set the root group to none or if you read the old version of the code right board dot display dot show none if you don't know any better and you just read this code here like what do you assume it's going to do right like the most basic assumption what I think most people would assume is that this is going to you know show nothing right it's going to make it so nothing is showing on the display and so what we would like is for that to happen right we want to meet those expectations if a person is going to assume that this is going to show nothing it would be nice to meet those expectations and have it actually do that in the past we didn't have this constant here circuit python terminal so we used none as like a special value to indicate the circuit python terminal now we have a constant for it we can then we don't need the special value for it and so what we want to do is update it so that it actually behaves like it reads you know so it does what it seems like it should or seems like it would can you show the properties of dirt board yeah I can it will be the same things as if it was well I should I shouldn't say with confidence I haven't tried it my guess is though my hypothesis before running it is that it will be the same output as if we just create a new group with like group like this we'll try both ways though so right now we're in the REPL technically I guess root group would have been set to none here I'll tell you what we'll take this one out we'll take this one out honestly we'll just take all of these out we'll save this this will rerun if we let it um technically it made a hello world label but it's not showing it because it didn't call show or set root group right I'll reset it once too I don't think it matters but just because displays are weird right they live long so I'll reset it by unplugging replugging just so we get a fresh like never have set root group ever on this instance then we'll go to REPL we'll go dirt board display group group aim board is not defined because we didn't import it which makes sense so we have append index insert pop remove sort hidden scale x y which are all the properties of group so they would be the exact same list as if we go g equals new group if we import it from display or group g equals new group or g this will be the same list and so I did start working on this but I don't think I definitely did not get it working in fact I think it doesn't I think I have like extra prints left in and I think it not only that but it just doesn't work anyway so fortunately though I do not call for certain like where I'm at here okay yeah yeah so to start with let's make a build of this version get this installed so what I was trying to do was I think that I think that something calls display.show and passes none when the board boots up because I started trying to change this over to you know essentially this is inside set root group this is when the root group is null which is basically none in python land so this is the code that literally handles when we set the root group to none and so right now today it's doing this stuff which is switching back to the terminal and I tried setting it to none or null and it was not working I was crashing and really what I was thinking is that I think that the initialization when this board first boots up something connects to the display and something calls show and I think that it calls show with none and so I think what we need to do is find that part find whoever's responsible for initializing the display to begin with and I suspect what we'll find is that it's calling display show none and we need to make it do this show the circuit python splash and start the terminal instead it should be doing this stuff wherever that initialization occurs rather than that initialization calling this with none or null and therefore causing this stuff to happen I think that's where we're at roughly I need to get this installed and see means we need to get back to bootloader means you can append a bunch of groups in there thanks for indulging my curiosity yeah for sure I'm happy any thanks for having questions and being interested I'm happy to help shed light on anything I can for sure and yeah you definitely you could just append to it so yeah you could as like a new way of doing stuff instead of just changing the group altogether you could append your stuff on top of the serial and then you could like within your same program be hiding and showing your own stuff to go back and forth to the serial if that's something you're interested in kinds of stuff like that so we are currently connected we're currently just showing output because we took all the shows out everything is fine there what we do want to do though is oops oh I might have left some mildly not quite a curse word but pretty close in the print statements let me go fix that I will say I was getting slightly flustered when I was working on this last because I was really trying to figure out like how to check if the thing was null and I was not understanding very well how to check if the thing was null and I tried a few different things and none of them were working and I sometimes when you're debugging I don't know if it does anybody else have this sometimes when you're debugging though and something you're not understanding it you're not working sometimes it's just nice to put some amusing print statements that amuse you right something that just makes you laugh and that's what this was for me I will go find it and change it though I'm not nearly as frustrated by it right now because I just started in display c shared module as I say you're not kerfluffled you're not learning yet shared module display c will make it more useful it's null inside display.show start naming functions bad things yeah adding soul to the machine yes definitely true oops profane comments yep happens to the best of us I think I'd like to think it certainly happens to me I won't speak for anybody but myself but it definitely does happen to me once you're in that mode though like once you're once you're into a problem to the point where like you're really really trying to solve it to the point where you're getting flustered a bit anything you can do to just get amusement out of it is helpful I think because the truth is like the main thing you need to do is just get calmed down probably the solution is not going to be any easier to find if you're flustered so amusing yourself in some small way is helping you solve it believe it or not I think and so what we're finding though is that it's null it's null in an instance when I did not quite expect it to be I think and so one of the challenges with this is when it first boots up we can't actually see it right because it's not connected yet the good news is we could actually see it on the display this device has a display so even though we didn't get connected fast enough you see it in our terminal soul blood for the soul blood god yes at my worst I think I held a key down for five minutes out of spite nice me uh where's my camera do I have have camera I can't see it okay so what we see is when it booted up we did get this it's null inside display show and then also inside set root group null it was null in here and then it was also null inside of here and because it was null inside of here that is what caused the terminal to get shown if we got rid of all this code except for our print we might as well leave our print but if we got rid of all this stuff and ran it again it just won't show anything because nothing will ever start the terminal and so this time it will reboot but we just don't oh actually we got it stuck in a boot loop that's not good yeah that's not ideal it's just continually rebooting over and over good news is trigger pattern is very forgiving pretty sure we can get back to bootloader mode be fine but that's actually weird I'm I am a little surprised that it loops oh I boot loops I wonder if we start the terminal but don't do anything else will that work yeah I guess let's try to find if there's like one specific part of this that allows it to work right allows it to not boot loop I guess I mean it would make sense maybe if we start the terminal but don't show anything or rebooting see and the thing is we don't it doesn't get it doesn't get alive enough to even connect so we don't get any kind of like output about what happened slash in group false so yeah unfortunately here though this is where like there's gonna be a lot of this like I basically just need to keep trying different stuff and then rebuilding and rerunning so it will be a bit slow because while the iteration loop of developing circuit python projects and circuit python library python code is really really fast the iteration loop of core changes like this is a bit slower albeit still pretty fast on this computer I have nothing to complain about the speed of of it here so that got us that got us all the way to here so basically because so so basically if we don't set root group here then we go to a boot loop oh if we do it this way and then I do also I'm gonna try it out this way because I'm curious but then I do also want to go look at scott's comment because scott has got the voice of wisdom here I think he pointed us where we need to look next we try to actually solve this rather than just poking around to try to understand it I was not expecting us to see all the same stuff I was expecting us to get I guess probably like a blank screen or maybe a blank screen with the status bar only so even if you don't call start terminal you do actually get to still see the terminal which is odd okay so we need to figure out what we can put here that won't cause a boot loop and and truthfully I think it's not so much that we need to figure out what we can put here that won't cause a boot loop it's that we need to find the code that when the device first boots up calls this and we need to make it not call it with none or null or whatever it's calling with and I think that's where hopeful that's where the wisdom of scott comes in I think the first time is in common how display or display construct which board in it calls it so board in it would be when the board is first booting up each board has its own like board make file or whatever that's where the display is defined the way that it that it initializes the display at least board in it must be what's doing the actual constructing and so inside of there hopefully we're going to find some kind of setup stuff that is setting this to null that we can change and that's going to be play construct so I guess that would be probably is that going to be in shared module display this calls core construct we might need to be looking in there as well scott did say display construct but it's worth noting that the core there's almost like two layers inside display itself as well there's like this display core which is not an object it's a bunch of functions and then the actual object like display object calls into those functions in display core so we'll maybe look in there um basically though what we're looking for is like something that's calling show or something that's calling set root group with none or null or something like that which is I think my hypothesis is this is how the terminal gets shown the first time basically when you first boot up time delay backlight stuff backlight set brightness okay so I added this okay and I yeah see here that we're getting back through some of the layers of some of the stuff I tried so interestingly too we're not getting this right we're not seeing this are we oh no we are inside display make new okay okay we're in here but and see this is where it gets weird right so I tried to say so the one of the what I was working on the last time I was working on this was I want to know if this is null or not inside of here this has an if statement if root group equals null but I was having a beast of a time trying to figure out how can I check circuit python slash splash here to see if it's null what I ended up with was this where I have this function is null does root group if root group is equal to null then it says root group is null it'll print that out and in our case it did not print it out it said inside display group make new that came from here the next line called this presumably it went inside of here presumably this was false therefore it did not print let's verify I'm gonna I'm gonna verify kind of a mode on this since I'm not I definitely know that I don't know all of what's going on and in that kind of situation it's always good to just verify stuff that you think is true because maybe it's not and maybe that's part of the stuff that you don't know that's going on so let's say root group not null I'm gonna make these shouty as well since this one here is shouty word init dot boot loop equals false that would be that would be convenient if we could just set that one set that one back to false silly me we just got to set the boot loop parameter that would be that'd be really funny actually I kind of want to make I kind of want that you know honestly that might be I mean it's it's certainly for amusement only it's obviously not a thing that a real user would want probably as an exercise in learning how to build a custom circuit python that has variables in boot pie that might actually be kind of fun like if you could make it so that you build a custom version where it checks boot pie and then in boot pie you have a boot loop true false and it just loops itself it might be kind of a an interesting way to see if you like understand how to make that layer that will check for variables and act accordingly which could be kind of cool I mean the boot looping specifically most people don't want but it'd be a fun way to learn it and the larger the broader concept certainly has lots of interesting uses for sure although boot looping can be interesting in and of itself sometimes okay so we are here we got okay so we uh unfortunately we have such a small screen that it actually had to scroll but it does say root group not null and then it it did have to scroll the other thing off so we can only see root group not null we cannot see inside display make new anymore so root group not so so but yeah this this is where it gets paradoxical so we checked right here and and it's not actually in this case it's not root group it's actually splash or that's what I'm trying to check but we called it root group here I guess really it should it should just be like a group right it's not where this function can get past any group and it's supposed to be checking if it's null but anyway aside from it being named weird honestly this is a function that doesn't need to exist it was just me trying to check if this thing was null or not it's it's paradoxical because we get to here we said root group is not null so inside of here this got printed that means that root group is not equal to null but if we just look a few more lines down uh it's null inside display show so right in here root group was null so like we just we just checked it here before we called show here's where we call show right here we just checked it it's not null we go inside of show we're inside here now a few more lines down right there inside uh it's null inside display show it's null inside display show so I don't understand how we went from not null right here we called it right here we passed in the same thing by the time we got to here here now it is null my guess is that I'm not doing this right my guess is that I have done something wrong with pointers or with accessing this variable somehow would be nice if it could break itself out of a boot loop the way the pc can break itself out of a boot loop from bad overclock it can actually do a pretty good job because circuit python has safe mode and inside safe mode it won't launch code pi um so if your code pi causes a boot loop then safe mode will save you from that now if you modify the core to make a boot loop then that might exist outside the bounds of safe mode and so you got to be careful in that situation but um under normal circumstances the safe mode should save you although I don't know that it had I don't know if it will like kick on after x amount of loops or whatever I guess that's only if it really like hard faults or if you reboot it with the right cadence could it be coming from at circuit python splash because of the ampersand possibly so the truth is I don't understand the syntax um so I'm kind of poking around in the dark a bit with regards to that meaning something else injecting it into the splash than the thing you're expecting yeah it's possible it is definitely that is 100 a possibility um expected a group but argument is of type okay expected a group star but argument is of type group so I did I tried once without this I mean we could try without root group here but I think we probably want the star there because this one does have the star and that's how this one checks here so the way that I settled on using the ampersand is because when this calls show it passes ampersand circuit python splash and then once it gets inside a show it has root group with star so that's the name of our argument that gets passed in root group with a star and then when we access it here we go no star if root group equals equals null no star which I basically stole from here right I made that function basically the same this one has star root group and it checks with root group equals equals null so I think that you're probably right I think the fact is that I'm checking this for null here and I think you're probably right that it's not I'm not checking the thing I think I'm checking the thing I think I'm checking is the terminal group somehow I'm not actually checking that or the other possibility is that no actually I think that's it somehow I think I'm just not checking it I'm gonna say there the other possibility but I what I was about to say I don't think it's possible anyway so this is where I am quite confused and this is where we started with the the print statements and such from before because we are basically we're in this weird paradox where the thing is not null before we call show and then by the time we get inside show just literal milliseconds later somehow the thing has now become null so I did actually find this so unfortunately I'll say the wisdom of what Scott pointed us to was a place that I had made it to before and I am not quite quite understanding it from there you know what's worth doing though what we need to do is I should be looking at main real quick because this is my branch I made attempts at changing it I did all kinds of stuff Lord only knows what I deleted or didn't delete I do not know certainly so let's take a quick look back at main if anything which is our eye here so construct is here though we will I'll go look inside this also no this code was here yeah okay so we didn't change I didn't change any of this set the group after initialization otherwise we may send pixels while we delay in initialization so let's test a hypothesis if we comment this out will we not see the serial will this even build I guess is one thing yeah I mean there's several layers to this question will this build if it builds will it boot loop if it doesn't boot loop will it show us the terminal and I think my theory my hypothesis is no I think this should not show us the terminal anymore right because we're not calling show circuit python splash interesting so something else something else sets the group something else calls show basically not know yeah something else has to call show right because if we don't call it here oh else would it get inside of show and it's still still getting inside of show and it's still having root group null so there has to be somewhere else calling show with none or null I think right well I see 451 reset display oh reset display which do we call reset display actually looping back around to the wisdom of Scott he did mention that we set auto refresh but not reset display so I don't know how we get into here but something is calling this and then this is calling show this is passing null and really this should be calling this should be not passing null instead it should be circuit python splash but the trickiness there is that it used to get initialized when you passed null to show and ultimately we're going to take that back out and so somewhere we do need to actually initialize it or we do need to call start terminal or something reset display only one in here there's a definition an h file definition and then shared module inside a knit something has called that display okay so in here we have inside display make new we have root group not null we actually don't have a couple of the lines that we used to have because we didn't pass null of course right yeah our other the lines we used to have were the lines saying this thing is null we no longer have those lines because this thing is no longer actually no now we are correctly setting a circuit python splash so do we go back to boot looping if we get rid of this somewhere else yeah get I will say get grep is a super super useful utility for finding stuff inside your code like finding out who's calling a function or who's calling it passing a certain value or whatever or where a function is defined get grep is like I have no idea what I did before I discovered get grep because I use it like all the time now honestly if we do boot loop here uh let me catch up also right here yeah I'm behind a bit circuit okay so it's ampersand meaning something else yeah my understanding of ampersand and C is it's breaking out a variable to be used in another function I'll watch this and see if also if it does I'll stop it from looping got a single loop in here single run I should say and not not looping so that's good my understanding of ampersand and C is it's breaking out the variable to be used in another function it can be dangerous if it's being used elsewhere and now you've got multiple things going into it usually you'll get some errors for unexpected arguments or stuff like that you're not getting that though so either it's a really sneaky it's really sneaking in there somehow uh or is that not even an issue at all there you go it's actually sneaking in there from somewhere else yeah the null was somewhere else okay so it's kind of it's like a construct that's kind of allowing that variable to be used from external places as well ampersand kind of your understanding of it okay just good that's that's more more than I had so every every little bit that we learn each time we mess with this so so we're actually good here so now I guess the question is what happens if I set it to none wasn't oh hard fault well let's look a bit at this code and see if we can and what might have happened so we got into here root group was null we know that because this printed we have all the rest of this commented out nothing else happened all we did in here was print there's no return or anything so we would have just gone on so the next thing that would happen is root group so if root group is equal to self-current group then just return true in our case I would assume that that's going to be false because root group is null I would assume current group is circuit python splash and so that should not be null therefore these are not equal this should not happen and return true maybe we should be just returning true from in here though or false even perhaps maybe that's all we need is just so if we get to here we return we don't go on that might be what we need but let's read on a bit so our next one here if root group is not equal null it's not equal null and if root group is in a group then return false the root group is not null but it is in a group then we just return false false here basically saying like false we were not able to set that group because it's already in a group you can't put it into the display if it's already in a group a group can only be in a single thing in this case that means it can either be in another group or it can be in the display in the root group of the display and that does just return false so I'm thinking that we do probably just return false here and that I think that might get rid of our hard fault because my guess would be our hard fault comes from the fact that root group is null and that we're still executing all this code so far we haven't really run across anything too problematic but my guess is something in here will be problematic so had that we had that if the current group is not null then set the current groups in group property to be false so take the current group and tell it that it's no longer in a group it's now eligible to be put in another group since we're removing it from root group here we're we're putting something else there if root group is not null so this we have a couple of these here's another one if it's not null we go in here we do update transform we say root group is in group equals true so set its property to true we say current group equals root group we say self dot full refresh equals true we say return true so my guess is that my guess is so root group would be null we're setting root group into current group my guess would be is inside what is basically the refresh function wherever that's at it's probably accessing current group and it's probably trying to like loop through it and do stuff start refresh let's find stuff that's using current group 11 places release display core so this checks it for null which is interesting I mean this implies that null is a fair value or whatever right a legal value that it could be see collect pointer fill area the stuff we saw this this is also checking it for null which also kind of implies that null is a legal value for this however what we see is that when we are setting it to null we're actually hard-faulting so for one reason or another it's not actually a legal value so to speak it's not a thing we can actually do I'm sure I don't know where it would be but something must be trying to access finish refresh this also checks it for null and then here so what is after start refresh what happens after start refresh so bus free refresh in progress set that to true last free fresh equals this and then it just returns true how does this actually like go what is in here that causes it to like do the refresh hmm I don't know finish refresh this one will call finish refresh but only if that was not null let's look inside core or this is where we were already get root group get refresh areas here's another thing checking it for null checking it for null calling update transform there's a lot of stuff checking it for null so it would think that it's okay but there must there's got to be at least one place where it's not started against null that's my best guess here is like I don't know how do we know see it's been a while since I did a hard fault thing I think what we need to be able to do though is we need to be able to try to see the core the dump of like the next level handler here which I don't remember remember how to do and truthfully we are probably we're over two hours already I'll probably be heading out here pretty quick this evening so if anybody has any last minute questions or anything you want to say or ask or anything like that now it's definitely the time to get in I'll be wrapping it up here in just a few minutes um I will be back tomorrow morning for my normal stream at 10 a.m central time I'll probably be back to working on this stuff because yeah this is kind of just what's on my plate right now what I'm interested in what I'm trying to plug away at so if you are interested in this um feel free to join me again tomorrow morning on my own Twitch and YouTube I'll put links in the the discord here when I get started um let's look at one more thing though before I go tonight let's look at where's our browser what would you do there uh do else for everything and give them unique else prints uh dinner time uh nice yeah I have enjoyed dinner hope you have a nice dinner Kyoshi thanks for hanging out for a bit I hope you have a nice night and nice weekend and all that stuff as well what would you do there do else for everything and give them unique else prints we could I mean I'm thinking that we feel like my first inclination is to just like return false from here and that maybe this would cause it not to hard crash but I also think this is not likely to be the correct thing to do because if we just return false here that means we'll never update current group to be none which means I guess whatever used to be showing just stays showing I think that's what I would assume happens but I do think it shouldn't hard fault so step in the right direction just not functionally what we want if my guess is right which has got to be well so group already used done okay we did it did not hard fault but it gave us a group already used when we set it to none already used right here set root group okay this well yeah fair enough this is just checking the true false does that make sense I mean would we return true instead of false I guess I mean yeah turning false with it without understanding if that's actually the problem is a shot in the dark not the best way to go about it for something as severe as a hard fault that is true I would agree with that statement but it is also about the only way I can do it because I don't have the necessary understanding to know anything else to do so definitely agree but this is where we're at luckily though what I will say is like and I will say this comes with the caveat of like I'm not telling you that you should do this but don't take this as like an endorsement of things you should do you could still mess up your device what I will say though is circuit python is pretty resilient so while this is pretty ham-fisted to be just going around inside the core changing truths to falses when you're getting hard faults it is pretty ham-fisted and it could certainly lead to more hard faults luckily circuit python is relatively resilient and even though it's hard faulting I'm not actually like losing access to my device I'm not getting locked out it's not getting bricked I can still easily just get back to boot loader either put it back into a known good circuit python without any of these troubles whatsoever or put it back into the next build of my janky one where I'm flipping stuff around internally this time we did not hard fault or raise the exception we did set it to none and so everything like nothing crashed but our functionality is not there we set it to none and we're still seeing all the stuff so I assume that's not really what we want either my guess is that we don't really want to return here my guess is that we want to let the rest of this happen we want to let this get set to null but we need to track down all the places where this gets used and I'm thinking there's probably somewhere where there's not a check like this there's something that's trying to access part of it even though it's null and that's leading to the hard fault that's my guess we'd have to like get the output from the hard fault which that will be the last thing I'll do is I'm going to head over to learn guide what exactly is a hard fault I don't I probably cannot answer at least correctly what exactly is a hard fault I can give you my take on it and in my layman's terms it's basically a crash that circuit python is not coded to handle so normally in circuit python when you do a thing that's like not allowed or whatever it will raise an exception your python code can catch that exception you know you could try again you could tell the user what happened you could do whatever you want your code as long as you catch that exception it can continue running everybody's more or less happy the specific thing you try to do didn't work it raised the exception but like as long as you caught the exception you can continue going on doing your stuff a hard fault is like the next level up of a crash it's not raising an exception your codepie cannot handle it at all there's nothing your codepie could do to try to catch that exception and like show a message to the user or anything like that this is the circuit python program itself the program that runs inside the microcontroller that interprets the python code that reads this codepie file and executes the code in it one line at a time that program crashed it's no longer running so it's no longer able to execute any python code it can't catch exceptions it can't do anything else it has like crashed all the way crashed it's no longer even trying to run python code anymore that's my interpretation that's my view on it that's how i think about it i don't know if that is like technically accurate i mean i would imagine it's not too bad since i tried to not get too technical with it but um yeah that's how i think of it that's kind of my understanding um there is a guide what is the name of this guide it's like is it just debugging debugging debugging this is what we need to do i think i think maybe this is what we need to do but i will say a few things it's been a while i have not done it in quite a while i don't remember exactly how and i have no idea on this feather device that i'm using here if the pins to do this are broken out or not my guess is honestly they're probably not but we'll have to look so you might need to find a different device oh man we were so so close we're so close we're so close like if i would have ended on time if i would have ended on time we would have made it through the whole program without any of this they don't go away they don't go away they don't go away youtube oh my goodness this is i don't even know i don't even know don't even know how we're supposed to do this anyway this is my problem i will not just sit here and dwell on this in front of everybody um i believe that so i tried switching the i tried switching to the chats this time i switched to my own chat and said the ate a fruit one so that we would hopefully not see those but obviously that failed we still see them so youtube is awesome i really like the youtube chat i think that they don't need to spend any time improving their filtering of obvious spam that's true i endorse that message but not really the opposite is actually what i think anyway that's neither here nor there um i think we need to do this because i think this will let us try to see the actual stack trace from the hard fault but this guy's pretty outdated it's for samd21's we'll have to try to follow it as best we can it's been a while maybe i can look back through one of my old videos i don't remember if i did this on stream or not if so then we might look out and maybe i can watch how i did it before but we'll basically need to go in and try to like get all this stuff set up and see the output of the hard fault if we can to try to figure out which line of code is actually causing it um but that's going to be tomorrow's exercise is doing this or we i'll probably try some more print debugging first i'll probably try adding print in a few more places and see if i can narrow it down without the debugger if i'm not getting anywhere with that though we'll get out the debugger and i'll try to figure out how to use it um but fair warning like i said it's been a while i don't have that much experience with it so it might just be a bit fair bit of me kind of fumbling my way through it so that sounds interesting to you then come back tomorrow morning at 10 a.m central time i'll be in the same chat room here on discord i'll drop links and we will get back to it and work on this let me catch up on the chat and then i'll be heading out here for now so uh yeah it looks like i'm actually quite a ways behind so that okay there's the last one we did yeah circuit python is pretty amazing for that it could basically set it on fire hit it with a hammer and it resets just fine um the equivalent of the blue screen of death would be like the hard fall yeah yeah and it's and it is very resilient i would keep hammers away but it's pretty resilient for our software stuff for sure uh how nice it would be if other operating system environments whereas bulletproof as circuit python haven't completely bricked anything yet and i've been trying yeah i'll agree with that as well yeah i have so part of what makes me so i guess um brave if you will with running weird stuff and just changing truths to false and stuff like that is that i have done a lot of questionable stuff to devices and just like you i have not managed to completely break anything yet every single time i have ever gotten into a bad state i've managed to get uh back out of the bad state the vast majority of those times with help from dan h so hug report to dan h for helping me i think at least two or three times get my devices unbricked um and also obviously for all the work in the core that makes it so resilient in the first place i have 20 boards i'm a horrible coder haven't been able to brick a device plus one for circuit python yeah sounds like an exception uh sounds like exception is like blue screen of death but hard fall is like an outright black screen or a crash reboot yep that's that analogy uh tracks yeah i think so the exception is like the system is still more or less there it's telling you hey that thing you tried didn't work um trying to tell you why which the blue screen of death tries to tell you why sometimes it's more or less legible but now that goes whereas the hard fault is like blink we're gone no more this program no longer exists i too have failed to break a circuit python device via software even tinkered with my own circuit python builds uh what did we see now i feel like i missed something uh we saw maybe the guide i'm not sure when exactly i got behind a bit on chat so i'm not sure what was showing when you asked that looking forward to picking this back up tomorrow morning do enjoy coffee with foamy guy yep i will definitely be having some coffee thanks for the stream good night foamy dan h is a legend totally agreed with that yes so good night everybody thanks for watching i hope everybody has a nice night and a nice weekend and all that again in case we missed anybody at the beginning happy thanksgiving to everyone belated uh that was yesterday here in the u.s celebrating thanksgiving so hope everybody had a nice day ate some yummy food hope everyone has a good night tonight and a good weekend i'll be back at tomorrow morning 10 a.m central time until next time i will see you later thanks for watching