 Hello, hopefully we'll have better internet weather today. And our weather. We're gonna take a couple minutes just to let people come along. I'll pause my video streams. Good afternoon, David. Good afternoon. Well, morning for unexpected maker. Evening for Johnny, I think. And hello, Michael. I've got a lot of like sunshine on me today. I think I'm gonna go for a run after the street. Get some exercise. It'll be good. I really want to try to run twice a week. It's hard to find the time. Hello, Dishapu. Hello, Dave. I tidied my workspace. I kind of did. Not since the last stream, though. I now have a shelf over here, too. That has been... I had a bunch of stuff on the floor. So at least, like, literally just like took the things that were on the floor and put them on the shelf over there. It's been worse. This is kind of how my brain operates anyway. Let's be real. I have all sorts of things in my mind and brain and then I'm working on. So, yeah. Beata says, sleepy morning. Dennis went well Monday, but it's still going well. Oh, sleepy morning. Hi, Ali Khan from Kazakhstan. Hopefully I said it okay. Alright, let's get going. Hello, everyone. My name is Scott. I work on CircuitPython for Adafruit. Hi, Tim from Woodland, California. We don't take ourselves too seriously. I don't take myself very seriously during this stream. If you don't know, Adafruit is an open source hardware and software company based out in New York City. So if you want to support me and or them, I work for them. You can go to Adafruit.com and purchase some stuff there. I work remotely for them and I have for what, seven years now, which is kind of wild. And I work on CircuitPython. So CircuitPython is a version of Python, which is a programming language designed to be easy for beginners and really fast to iterate on microcontrollers. And microcontrollers are little tiny computers. Here's a good one actually. Like this, this chip here is an expressive ESP32S3. And it can do things like drive a display like this. So microcontrollers are really tiny computers and they're great at doing one thing. And you can have lots of them doing single tasks. So and they're commonly used to drive displays and re-sensors and things like that. So CircuitPython is a goal is to make it easy for people to use. Now this is a deep dive and deep dives are and I just realized I can click into the eye tracking. Focus. I'll say hi to you. Yeah, I guess Johnny and Dave, I said hi to him beyond I said hi to as well. And Tyeth is in the Discord chat as well. Oh, Discord. Up here is the Discord chat. I recommend it because it doesn't disappear at the end of the stream. If you want to join it, you're just on YouTube and you want to do that. It's the URL, a-d-a-f-r-u dot i-t slash the Discord. That'll get you into the Discord chat there. This ship is asking about pronunciation. I thought I thought it was Biata like Miata. I'm sorry if I've been saying it wrong, Biata. And feel free to correct me. What else was I going to say? So deep dive, tangents are welcome. So questions, if you have questions about Circle Python embedded, anything I can help with, feel free to ask them in the YouTube chat or the Discord chat. I do have kind of an aggregate of the Twitch chat as well. So I should see those. Twitch and LinkedIn I think do come in as well. So if you have questions, feel free to ask those. I'm happy to try and answer them. I make no promises about my ability to answer them. But yeah, so hi, SuperRyu. Welcome. The other bit of housekeeping, hi, Crystal Monolith. Welcome to you as well. So Circle Python 2024 wrapped up this week. I drafted the post and intended on pushing it out yesterday. And then I was looking through my tabs this morning, realizing I hadn't actually posted it. So Circle Python hashtag the year or hashtag Circle Python the year is our kind of annual planning where we're trying to kind of come up with a community or a community plan for what we want to get going, what we want to do in the coming year. It's a great way to see like bigger picture of stuff from folks. And we ran that all through January, although most of our participation was at the end. And we got a bunch of different responses. So maybe I'll just go, this is kind of like a brief summary. Tyeth said on Wednesday wanting support for the parallel display and this board here. The reason I have this is I was testing it and it's got the display is connected in parallel. So there's like 8-bit signals. So it's 8-bit bus, which is more than like a normal spy buses. So I was getting that working on the ESP32S3 and then they also requested long range Wi-Fi in the ESP, which I don't know much about, but yeah, I've heard of it. Todd Bott had wanted dynamically loaded data modules. It was really tricky and he says it would not be easy. So I would say that's probably not going to happen. I understand the reasoning. So Todd Bott's reasoning is that we don't have to worry about flash space as much if we're able to load native code when we need it. Sunnice had requested something to make disks not ejected properly. Warnings don't happen as much and I suggest looking up above in the live broadcast chat. Todd Bott had a suggestion. SuperU says don't have 16-bit parallel. It's faster. I think 16-bit will work, but the hardware that I have to test with is 8-bit parallel. Let's see, what else? SL0 asked and hoped for being able to easily test their code. Dexter emailed wanting or saying they're interested in plan 9 style synthetic file systems and ferroelectric RAM. Sanka wrote a blog post kind of a tutorial about the TM1637 LED driver. John Hind was interested in IP over USB. Jeff talked about supporting things like USB host and really documenting them so people would actually use them. And then actually also talked about maybe it's time that we actually stop supporting certain boards so that we don't have to worry about code size so much. Some of the SAMD21s are really full and he kind of posed the question of should we declare circuit Python 9 being the last one for those boards? And I think my answer is no. It's a huge pain to keep them up to date, but I think it'll be more pain if we have to say you can't use new code on the old boards. Mark, who goes by Gambler on Discord as well, was interested in picking up some tests that were high priority for Adafruit-funded folks but sounded interesting to them. I think SynthIO and some graphics display IEO stuff was on this radar. And then just continuing to hang out and be helpful. Liz talked about increasing their involvement in circuit Python including writing libraries and also like I think straight up saying like she wanted to help me document features as I add them so that people actually know about them and can use them, which is awesome. And I think somewhat of what came into my circuit Python 2024 as well. And wrote on X a wish list which centers around interoperability with old IBM PCs including the idea of running circuit Python or micro Python from within like on the PCs themselves. Which I actually mentioned to Jim who works on micro Python and he said they actually had a free DOS port that they removed. So it's possible, I guess. Wave Sailor posted on the forum particularly about wanting a reference card for migrating between micro Python and circuit Python which I think is an interesting idea and something that we could do better. Like somebody had pointed me to Arduino language reference. So like this is a really handy page for Arduino folks. And we don't have kind of an equivalent for circuit Python which could be potentially really useful. But then you know there's overlap between like what a Python reference would include and like a circuit Python reference would include. I talked about in my post mostly about the BLE workflow and the kind of USB host workflow where you have a display and you have a keyboard all plugged in. Like even foamy guy who plays pretty good attention didn't understand that if you plugged a keyboard in with USB host active it would like automatically convert it into characters for you. Incredible little bit on the forums wanted some Blinka motor kit support stuff and the first person was DJ Devon 3 who had thoughts about supporting more displays and the ESP32S3. So that's kind of a quick recap of circuit Python 24. All these links here are links to the like full posts. And if this is interesting to you I'd encourage you to click through and read all about it. Be honest as I would like seesaw on the Sandy 21 had been inactive. This heart is right over like the first the last word in the line. I had been inactive a while so I went on to other projects. I don't know what you mean by seesaw on Sandy 21 because you shouldn't be able to use iSquared C to talk to a seesaw device. But maybe that doesn't maybe the library is too big. Mark had said would be interesting to know the sales on the Sandy 21 stuff. It's hard to know. I mean I used to have access to the charts. But the last couple of years have been really screwed up by just availability. And I think we sold a lot of Sandy 21s and like we still sell like circuit playground expresses our Sandy 21s. I don't think it's I don't think it's time yet. We're just going to deal with it. David says I don't see my circuit Python 2024 post. Did you email me? Did you email it to circuit Python 2021? It's 2021 2024. I might have missed it. Sorry. Email me and I'll add it. I can edit this post so it's in there. Taya says I prefer to have features turned off than drop support for the boards. Ideally still turn on a bowl maybe a simple CI workflow that allows toggling some build options and feature flags. So the simple CI workflow exists micro dev out of it. I don't think anybody uses it. But yeah, that's generally our approach is that, you know, we partitioned most of our functionality by module and they're easy to turn off and on. And so new modules just don't end up in the Sandy 21 build. Now that's not entirely true for like I ran out of space when I changed the way storage dot mount worked. Right. And that's something that's already in the Sandy 21. Not super simple, but yeah. Unexpected maker says I also think maybe nine should be long term support version than the last for flash constraint boards. I mean, we're always going to have flash constraint boards though. Like there's even like the ESP 32 s threes with the like four megs flash. Like we have a smaller partition for circuit Python than on the bigger flash chips and we're like running out of space there too. Like it's going to happen. Yeah. And Mark points out that changing existing stuff is. Oh, it was on X. I'm not on X anymore. Sorry. But yes, I will add it and I will even open it in browser. Let's look. Let's let's let's live live review. David's post here. Not doing a lot of circuit Python projects right now. Then doing neo retro computing home assistant. And not as a NASA and NVIDIA shield as blacks and building a homelab server. So that's distracted away from circuit Python. But I still have circuit by the dreams ideas for the future and suggestions a different let's build a random list of nine ideas. Okay, number one circuit by the first. There are a few a different boards board sensors that do not have support in circuit Python. I keep keep acquiring these by mistake with the secret hope of future support and circuit by them. But a different should force themselves not to release a product until it's clear that support and circuit by them is guaranteed to be possible in the short or medium term. That's a good point. I know one example is the USB host. The USB host feather wing is not supported and that's been my intention but as you know my life kind of got clobbered by. Some family personal stuff so did not did not happen. But yeah, if you have a list, feel free to open issues on circuit Python. We do have a library's milestone so we could track it there and generally we do want. We do want everything that's a different releases to be supported in circuit Python so feel free to bug us about those. Support for the Raspberry RP 2040 successor is written in the stars. Raspberry Pi is working on an evolved version of the RP 2040 microcontroller. Maybe it'll have more cores, more memory, more storage or whatnot. Adafruit should be in the starting block as soon as they have access to hardware. CP support should be better and more user friendly than what NP can offer. Hopefully, hopefully I will tell you I did have the RP 2040 a little bit before it was announced. So my hope is that the Raspberry Pi folks will give us a heads up as well so that we'll be able to support it when and if it comes. Let's see. I'm sure all I've migrated to Wayland before everyone has been comfortably on X. I moved my laptop to Wayland and it's been okay. Okay, let's go down this list. I'm liking it so far and we're only one, we're through two of nine. So three excellent Bluetooth support. It's near perfect on NRF but it's limited on the S3 and the PicoW. We agree to bring all plants platforms of the same level. I agree, especially for ESP32 S3. I have a love-hate relationship with the external chip on the PicoW. So S3 is far more interesting to me and kind of pretty high on my list. So I'd like to do that. Oh, number four. This is a theme too. More marketing for the software features. But if it's not from an individual or not linked to its new product, the feature might go totally under the radar. And I'll tell you, I do feel like a little bit like we're actually a bit backlogged. So we have features that we've done for future products that just haven't been released yet. So you might see, yeah, this will come. Better indexing of the CircuitPython YouTube content. There are a lot of episodes of CircuitPython Parsec, Product Pick of the Week, Over time, they become harder to find as there are no searchable index of the episodes. They should be listed somewhere so that newcomers can find them and others can find them again and revisit them. Do we even have an index of all the great search CircuitPython Parsec and all the presentations and show and tell? I would check the playlists. I know that when I do deep dives, I add them to the deep dive playlist. So they are at least separated on YouTube in that way. Hi, FedE2. Maybe a series when 9.0 is really showing more details about the new features. Yeah, that's a good idea. We should do that. We could have a video about 9.0. A lot of the changes are internal, but one thing I was just, so we just changed the storage dot mount behavior and a lot of folks are hitting that. So one thing I want to do with the next release, the next beta release, and Dan does basically all the releases now, and he's back next week. So I think we need to split out. There's all the new features on 9.0. We actually need to say the breaking changes separate from all of the changes. Let's see, improve USB host support. Yeah, more learn guides. So FOMI Guy is actively working on a learn guide for USB host. So that is kind of an avenue we're hoping to send FOMI Guy down is the USB host rabbit hole and get some really good learn guides. And as he does the learn guides, he'll test it and find issues as well. The support cannot be limited to one board. We need the feather ring first class, too. Yeah, I know. I know, sorry, that it was on my radar. I got one early and the support is in tiny USB. It was on my radar and I just lost a bunch of time to my family stuff. Yeah, it's on my radar, too. I want to get 9.0 out of the door. That's an example of something that we can do after 9.0 is stable. And there's a lot of good stuff in 9.0. And when people have issues, we're just like, use 9.0. 9.0 is kind of like what I'm really trying to be laser focused on. Now, the work that I've been doing the last couple of days is not super laser focused, but it's still good work to do. We'll get into that. 7. Create and support products with multiple CPUs. The quest for a circuit by the computer seems difficult if attempted on a single MCU. It would be more easy having multiple R2040s or other boards collaborating to produce a result. Yeah, multiple MCU stuff is really hard. But then again, I've always had this idea of the Stemma G0, which is a different STM32 over Stemma sort of thing. Unified network stack today, doing network with, it's different depending on airlift ESP32 or Wisnet or native. Or yeah, ESP32, yeah, airlift, right, yeah, ESP32 spy. Yeah. Yeah, it's, this is definitely an area where I'm not like super like, got it all right that I want to do. 9. Change of things over USB. Circuit by the gun already do a lot of USB pretending to be a network adapter or presenting USB master or independent from circuit by pretending to be a Milman printer sound card. Yeah. So Jeff is working on video. So it's that that's merged in. And I think it might be after beta zero as well. But Jeff did merge in the ability to have a frame buffer that is rendered to from display. I owe that then go, the video goes up the USB link, which is cool. I think we should do audio too, but audio is also complicated. I don't network adapter is like something that John Hind pointed out, but I don't know what that involves and it's not super interesting to me. Presenting a USB mass storage independent from circuit by that is. Yeah, some work that we spent for a while and then it got stalled out. It got stalled out because different operating systems were like having different issues. Like it's kind of weird. Yeah, the the mass storage thing is like that it has a concept of logical units or LUNs and we were trained to have multiple LUNs support it. And those are. Yeah, they work differently on different OSes. And so that's been kind of tricky. We don't have a great solution for that, unfortunately. Very to says I have in the mail 10 USB host feathers for making Henry mappers. They'll be used to test the cookery Costa Rica keyboard. Nice. Yeah, those should those should work. It's the feather wings that we don't have circuit by them support yet. Someone is already working on it. Mark says I was having lots of fun with the USB hidden stuff lately. Got some new encoders from DigiQ to do more with it. Writing custom USB descriptors is a bit less fun. My hope with custom USB descriptors is that we could have libraries for doing more oddball stuff. So like you write it once and then hopefully we can share it afterwards. Jonathan Rodriguez says fat 32. I'm not exactly sure what you mean by that, but we do support fat 32. In our like the library we use supports fat 32 and X fat as well. In some boards, I think on the small boards we limit it. But on all the new stuff it's there. I'm going to stash this tab back down in my off screen. My off screen browser. I really think that I'm I'm really interested in doing the IMX 1060 on 8 8 of fruit boards or multiple 8 of fruit boards because it has dual USB. So there's a lot of stuff that you could do that is is kind of like you can do host natively, which would be nice. Mark says if time and brainpower permits and may write up a quick tutorial. There's a tool to help you write the descriptors from Tamil files. Okay, so that was circuit by them 2024. I'll also note one project that I've been doing is I've been digging into LLVM a little bit. So if you don't know what LLVM is, it's a it's a project for compiler tools and the like C front end is called clang. And there's a linker called LLVM. And one of there's this problem that we hit a lot, which is parts like the ESP 32s, the RP 2040s and the IMX chips. They all store the bulk of the code on an external flash chip. And then they have a cache in front that makes it faster, basically. And because we store circuit pi on that same flash chip, there are times where codes not available. And so what you can do is you take all the code that needs to run when that is happening and you put it in RAM so that you can run it still. But it's really, really prone to getting it wrong because anything that that function calls also needs to be put in RAM otherwise it'll crash. And there's no good way of knowing that. So I've been prototyping a feature to LLVM that allows us to set an attribute on a function. And the compiler and linker will work together to make sure that everything this function uses ends up in the RAM with it. So I've been dabbling in that. That's been something I need to get back to. It's been a couple of days, but I think it's kind of a killer feature, especially as I suspect that a lot of the new chips will have that as well. Hi, James. Welcome. Let's see. Johnny says I would add that the Adafruit Arduino libraries would need some love as well. There are loads of pull requests that are years old already. I had to fix two bugs in one library when developing the JB Whopper library, but there isn't even a Discord channel for that. Besides help with Arduino, I don't think we really have, like, more is kind of the person that maintains their Arduino libraries. I don't think we currently have anybody else. I know TAC does some of them, but I definitely do not. That is outside my boundary of what I do. David says I think it's possible to do USB hidden provide a web interface that works on Chrome to control your board. Imagine a web server running on your MCU and accessing it via browser over USB without Wisnet or Wi-Fi. Yeah, that sounds like John Hine posted to that as well of IP over USB. Fed-A2 says there's a new version of the Milk 5 Duo, still 700 MHz core, plus a gigahertz core. And the new one you can run Arduino on the slow one and Linux on the fast one. And again, way faster and cheaper than IMX6 chips. But the ones from Milk 5 don't have Bluetooth or Wi-Fi that have to be a separate chip. I'd be curious, has anybody gotten tiny USB running on those already? It depends on what the USB IP is, but that would be a prerequisite to bringing CircuitPython to it is having tiny USB USB support. So consider that your challenge if you want to see CircuitPython running on it. I think that's it. Are there any questions before I change topics again? Yeah, look at these. I'd love to get to the part of the the other reason I'm interested in the clang stuff is like code size is really important for us. And I'd love to be able to like hack the compiler to figure out if I can actually make code size smaller. Which is like super nerdy of me. But yeah, I'm interested in that. Starting from $5 architecture, video subsystem, boot select. What is the SG202? Milk 520 has Ethernet. Hidden remapper uses webhead and it's very nice interface. You download the XML from the board from the web interface and every change you make is very fast to send to the board. Hidden remapper would be really interesting to figure out how to do that from CircuitPython. Like ideally with a custom USB descriptor you could probably do that. David says he's been using it too. Or do you need to get a separate board with the Ethernet inductors? So what are these different? All chip data is open source. Interesting that the RP2040 is like their main competition. Duo S. Oh and it's got an ARM A53 in it too. USB Type-C for power and data or one USB 2.0 port, host port. What is this chip storage? In package DRAM. Micro Semi. Do they make the chip themselves? In-house TPU. Boot select. Does this mean you run the RISC 5 core or the A53? ARM core and the RISC 5 core are exclusive. You decide what you want to use at the boost process. That's kind of weird. A53 USB 2. MCU subsystem. That's separate from the CPU system. But the MCU system does not have USB. I know that the A series is like harder to run on for sure. So maybe this, I don't know this RISC 5 core either. I don't know. The other thing about Clang is that's what I would use for RISC 5 too. SOFON.AI makes the chips. 2042. TPU processors, RISC 5 processors. They only have one processor listed here. Maybe the ones in the Moke 5 are all the ones they're done with. 2 gigahertz. PCIe, wow. Huh. Alright. Enough dev board shopping. Although I do love pulling up the Digikey new dev boards page. I don't see any questions. So let's move on. So the title I called for this video is the Circuit Python Implementers Guide. And so I kind of want to commit myself to finishing this guide. I literally started it a year ago. But LaMour had asked me, you know, suppose somebody comes to us and says, hey, we want to add our chip family support, right, to Circuit Python. Like, what do I need to know, right? So what do I need to know from a developer's perspective? And this is kind of like, kind of what deep dive does too, but like a guide form of that. So I kind of wanted to like tell people I'm working on this or I had worked on it. And the work that I was doing is there was issues, there was a crash. How did I get down this rabbit hole? There is an issue. So I'm trying to get all of the 9.0 issues out of the way. There's still 39 of them, which is unfortunate. But there's one assigned to me for some of these I have PRs out already for. Like the parallel bus one, like Jeff's been out, Jeff's out the rest, like starting the end of this week, Dan's out all this week. So I'm quite backlogged on like PRs that I have out that haven't gotten reviewed yet. And maybe we should just go over those. But the thing that started us all, there was a guide for adding a board. Now you want a guide to add a family. Yes, yeah. Yeah, that's the basic idea. So there's this bug where frequency in is causing crashes. And as Microdep pointed out that like the P count peripheral is a pulse counter peripheral. And GP timer stuff, they're deprecated in five IDF five, which is what we moved to. So I kind of like said screw it. I'll just update to the new drivers because actually that I, as I've been doing this, I realized like the new drivers in ESP five are much nicer than the ones in four. Like there's a reason the reason they they had good reason to redo them. They're they're much nicer now. So and when you migrate over, you have to use you have to switch all the places to the new driver. One of the things that has been really nice in the new new drivers is that the new drivers in the IDF keep track of who's using what resource. So that's something like circuit pythons done already of like on Sandy 21 and you want I squared C, which hi-hams labs like which circum goes with what pins sort of thing. And the the ESP has more flexibility for wires, but they still have finite resources. So the ESP IDF and five and these new drivers, they track all of that resource usage for me for us, which is really awesome. So in general, these APIs have been improved. But when we switched them over, we were getting three as a in main right now. There's three warnings we're getting. We're getting GP timer or timer. We're getting P count warnings. And then lastly, we're getting RMT warning, which is like a remote control peripheral sort of thing. So there's this crash for frequency in that's marked as 9.0. And I was like, you know, I'll fix this by just switching over to the new driver. And it looks like what was happening is that and I was talking about this earlier where if you're writing flash, you can't access the flash. You need to make sure that all the code that you run while the flash is disabled is in RAM. And furthermore, it's not just the code that's running, but it's all the data that it needs as well. And when you're writing flash that the cash that is on ESP, the cash that's in front of flash and RAM is shared between flash and RAM. So you also not only when you're writing or when you're erasing or writing flash, you lose access to PS RAM as well as the flash. So I think the the cause of this frequency in crash is that the way frequency in works is that it sets a timer says, hey, every however many milliseconds call, like, call me back. We'll see how many pulses we counted and we'll figure out their frequency from there. And that runs kind of freewheeling so that in in Python, all you see is dot frequency and it changes over time. So what has happened is that like, oh, you know, if I run this code, and then I try to write code that pilot again, while it's running, which is a flash, right, a race and then a right, I might cause a crash. And so that's the what was happening is that even though the function callback was marked for Ram, it was trying to access the circuit Python self like the circuit Python frequency and object, which is the action in PS RAM and not actually available. Anyway, so I'm, I decided to redo frequency in to upgrade it to the new API turns out that count IO and rotary IO also use this P count driver, the pulse count driver. So I've updated those two as well. And then since I upgraded to the new timer one and the new pulse count driver, I was just like screw it. I'll just do the RMT one as well. So the RMT one is it's a remote remote control like peripheral and it's used for a new pixel pulse in and pulse out, which are in the pulse IO modules. So I've been redoing all of the code for these like five modules, pulse, pulse IO, neopixel, right, rotary IO, frequency IO and count IO are all going to be new implementations basically. So that, so yeah, I'm in the middle of getting that all working. And then I what I realized is that I had this old learn guide that I had started where the idea is that there's like general tips and tricks about implementing circuit Python and then kind of per module notes. And in particular per module testing. So I was like, let me dust this off. So for frequency IO, here's a link to the documentation and oh, by the way, here's the test code that I was using to test it. You can see that I've added a pulse IO one, because that's kind of like the next stuff that I'm working on. So I've actually, well, yeah, I've updated count IO and rotary IO, but I haven't tested it yet. So I'll go back to these, these things and and edit those. Yeah, I see a question from David who asked, who wrote the present support? Is it you or is it people from Sony? Or did they know how to add an MCU family to circuit Python? So it was folks from Sony, or at least one person like the cam tom 480 person works for Sony, I believe. And yeah, they did add the MCU support like they figured it out on their own. Yeah, it's the structure of circuit Python lends itself well to being able to do it. Because we have like the shared bindings factored out and then it's all just C functions. But there's a lot of kind of behavior that's not well documented potentially that or caveats that need to be kind of kind of called out that this guy is going to do too. And then the other the other port that was done by manufacturers, the Sylab support, so credit to Sylabs as well. They added the support for their chips in the circuit Python all on their own basically, and they do support it. They've been pretty active like fixing fixing stuff that's come up, especially in like the Bluetooth land, which has been awesome. So let's just I like brain dump this over three days. The other thing that I kind of need to kind of one of the reasons I want to release is because I've actually cited some some of these charts. So I last year I worked on performance for the IMX because the pitch with IMX parts is that they're really fast. So I talk about it here and I measured some stuff so you can actually see like this is these numbers are from whenever I worked on this. And I should definitely call those out that you can see like the different blink speeds that you can get with this basic blink test. And then, oh yeah, so March of last year is when they're so good. I marked that down. And then there's also performance benchmarks that we have inherited from micro Python. And this is for eight. So these I'll have to update these. But there is actually like some performance numbers that I took at the time as well. When Adafruit or Freelance offer add a new board as a service or add a new MCU as a service. I don't know if we do add a new board as a service because generally like Adafruit makes the makes making like a new board deficit really not that hard. Adding a new MCU as a service is kind of it's not explicitly done. But it is done through a like, like we put our effort towards the MCUs that we know we're going to have products on. And some of our products can be influenced by like pricing deals that potentially Adafruit can get. So it's not direct. But yeah, like there is ways to influence the MCUs that we're going to add. Let's just go back and see how much I wrote into the overview. Okay, so this is talking about, yeah, and this is when I was doing all the PySigRock stuff. So it's using the PicoSigRock things. These are gotchas, research using resource usage tracking, code structure, micropython basics, argument exceptions, getting started on a module, port reset, never reset. Like I said, this is kind of like I need to get this. I need to publish this because I really like wrote a lot of stuff about it. So it has test cases and talks about things that were, do you have sleep slash alarm in my list? I don't. That's a good request though. But I think this is part of the problem and I need to figure out. I need to figure out a minimal set of things to do is because like there's valuable stuff in here and I shouldn't wait until I've written it all. Like instead I can, I can upgrade it or update it over time. But I think what I will do is like I'll add alarm in here because you're right. And I will probably do some work on that later this year too. Correct. This guy does not public yet. Although I think, I think I might be able to, if I send you this link, I think I can send preview links even though it's not public. Maybe you should write a list of priorities and features that can be done software bit bang and implement later in the kernel. Yeah. So that is this left hand side is definitely like it is try to do it in order that you should implement them. Because I talk about like you have to do it once you do bus IO, you can do display IO and things like that. And I didn't do the bus IO testing yet. Maybe I did, but I'm starting to work on it. I have to go back and do more of the testing stuff. Like some of these are just empty placeholders. Like rotary IO, but so I'm redoing the rotary IO implementation on the ESP and that gives me a chance to circle back here. I was reading some through some of the issues for pulse in and there's a lot of them. So there's like definitely cases where we like need to better specify the behavior and then make sure that all the ports fit that behavior. So like our APIs are more uniform because at the Python level, but there's nothing really stopping the implementations from varying under the hood in terms of like some details. So that's kind of like those are kind of what we want to capture. Are there dependencies like to do ABC IO, you need XYZ IO. Yeah, sometimes right, like so display IO just depends on display IO depends on digital in out, for example, to do like chip select lines and PWM to do backlight brightness. So yeah, they're not completely independent. But yeah, as I'm doing these other ones that I kind of have to do that too. So like neopixel right, I think I wrote all the way down. Blinky tests and pictures and stuff. And then I kind of say like once neopixel right works boards can set Microfi hardware neopixel and MP config board to the pin object can use to do it and then like circuit by phone will use it natively. The PWM and display is optional. I think it's optional, but do we have it pound to find out so it works if you don't have it implemented? I'm not sure. I don't know. It's it should be done earlier than pulse IO pulse IO is complicated too. I was just doing pulse in. I'm like, oh my goodness. Pulse in is a little complicated. All right. Well, yeah, so I'm going to this is like more has mentioned recently that I should get back to finishing this guide. And I can. Like right now, all of these pages are not published, but it is also possible in learn to have like I can keep I can have more under here that I haven't done yet once like the core is done. But like bus IO is not completely done. And I've been meaning to actually like do some proper testing on bus IO. If you are a person that loves to do detailed testing stuff like basic scripts for doing functional functional testing and you want to help me because it is not a strong suit of mine. Just ping me on discord and I think if you have if you have a learn account, then I can share like authorship with you. And maybe that's what I should do is I should talk with Carter because Carter is really thorough about the sort of stuff to like kind of collaborating on it. Because obviously like doing it by myself, I lost. I like got really into it for a few days and I lost steam. But I also think that like with the work that I'm doing right now where I'm changing the implementation on ESP, like I'm thinking about details and that's a good time to come back to this. So with that, let's get compiling. Sorry for the car sounds. My windows open. So I did just do a restart. So I'm going to get my IDF set up. I have an S2 here. And actually do have the overhead if we get to testing anything. I did test frequency IO. And so I know that's working. But I was I was like doing the RMT updates. That's where I left off. So I'm just doing I'm just updating it all. So basically I'm updating it all and then I'll go back and test it. I'll get a compiling because compiling is a good way to know what you have to update. So it shouldn't it shouldn't. Yeah, I should have lots of errors. I haven't updated pulse out yet. I've done the O pixel right. I did pulse in and pulse out shouldn't be as hard as pulse in because I I've already done the RMT transmit stuff once. Oh, I don't even have my editor open because I updated my I updated my computer to hopefully like, you know, I was having this frame dropping last week and I didn't know if I'd updated it at all. So I updated the computer and then I like deleted the wrong package and it didn't boot up. So it took me longer to get back into it. Luckily, I did it with enough time to like fix it before the stream started. So I was on time, but I did cut it a little close. Okay, so we are in and maybe I should set it up. It might be more worthwhile. I do have a way of project build system is considering using the built in builder, but I'm not going to do that. All right, so pulse out. I haven't converted anything. So it really is going to be a matter of switching between we'll just start with new pixel right and then we'll pull up the pulse out source. So we want pulse out and we want new pixel right. In fact, maybe we should buy Dave. Sleep well. Thanks for stopping by. So let's just go update. I really like I wish I could hit a back. I wish there was a back but new pixel right. Okay, so they're next to each other now. So there was this peripherals.Rmt.C that microdive added, I think, or maybe Lucian did. But basically with IDF for we had to do all the resource tracking ourselves and do resetting. But one thing that I wanted to do is like you can when you allocate when you allocate Python objects, you can say whether they have a finalizer. And so I'm moving more things to having finalizers so that we don't have to do bulk resetting. We just when you initialize something when you construct an object, it always will have d and net called and revert back, even if that happens when the VM is done. The original approach we took is like kind of like we set everything up and then it can be torn down. But if it's not torn down when the VM is done, we'll just blank it reset everything. And that's just not super easy to reason about. There's a lot of tracking you have to do to do that sort of bulk reset. That's part of the reason there's never reset, which actually I guess if we completely got off that we could actually get away with it, not doing it. We'd risk leaking stuff but the new API is an expressive. They are doing memory allocations under the hood. So it's really important to kind of like construct or create and delete things as you need them. And they have these opaque handles. So actually let's copy this whole thing. So now here's an example of what we were replaced. So previously we had this find and reserve RMT thing. And now that kind of gets done under the hood in the IDF by this new TX channel. And in fact, we don't want, did I switch it already? Yes, I did. So we're going to have it stored in self channel, Neopixels of a funny case. And then it's just going to be pin number that it takes in. And then we haven't set up the carrier yet, but there is this clock divider, which is super. Here's an example of how the IDF API has gotten much better. So where previously you got a clock divider and you didn't, you wouldn't know. Clock divider doesn't tell you what clock it's running at because it's just a division of some clock that they're not telling you about. So the new one says what do you want your resolution and Hertz to be, which is quite nice. So clock divider 80, I was thinking it might have been. Yeah, maybe this tells us the frequency. Oh, well, pulse out pulse it pulse out has resolution of a microsecond, which is mega Hertz. So our resolution is going to be a mega Hertz. So this must be clock divider 80. And the other reason that this resolution hurts is the way to go is because, especially now that they have a lot more chips that they support, they have different clock frequencies that they run at. So by telling the IDF that we wanted a mega Hertz, like there is. It should work like it's more portable that way rather than doing the clock division as the as the request. Okay. And then we're going to need to do carrier frequency as well, which is, let's pull it up our X carrier config TX carrier config. So originally when we when I designed this API, you had to like pick a PWM resource and kind of like you had to pick a PWM out that you passed into pulse out, because that's under the hood how Sandy used it. But then this peripheral in the ESP chips kind of does it all on its own. So interesting duty cycle carrier duty percent times 100. Oh, but now this is a float. We want to make this a float. Your frequency is passed into us. Taya says, does this mean in 2024 we could have changing frequency while code was running like save battery and clock down assuming you can't sleep and back up to analyze something. We started we start to have that so the the RP 2040 port actually does allow you to change frequency. But it tells you it has the caveat that you have to anything that you instantiate or or or create you need to you need to do after you've set the frequency. So it's like and that's because like it's doing all the under the hood all this clock divisor stuff is happening. And if you change the like incoming clock, the divisor is not going to get updated automatically. So no, not really sleep is still your best bet unless you just wanted to always run it at slow speeds. Carrier should be modulated to high level. I think that's right. So like this config and driver stuff goes away. So I think we do need to do RMT enable. And I haven't actually tested NeoPixel, but I think that's true there too. NeoPixel has this cool encoder thing. So the the nice thing about the encoder is that you can convert individual bits to certain pulse values, which is really neat. And then RMT transmit is what it's going to be the body of our pulse out. So now channel is going to be null when we're done with it. So we're going to do RMT Dell channel. And then we'll set it to me and it. And then here we're not going to loop. We're going to have a low end of transmission level. I don't think we want to code or we'll have to look. We don't have any memory that we need to delete if this fails. So we can say check ESP results. Check ESP results is a macro that will raise an exception if it's not okay, which is very handy. And then wait all done, we could actually make smarter. Because this hundred is milliseconds to wait, I think, and we could actually compute that so that we know how long it should take if it's working. Oh, and you know what? Maybe we don't want wait all done because run background tasks. So let's let's actually see what wait all done does. How is that documented? Ah, so so we don't actually want to use the time out here. Otherwise we won't run background tasks. So what we want is we want while wait all done is equal to ESP. What was an error time out? Like so while it's timing out, that's fine. We'll run background tasks. And what we can actually do is we can do it this way. We can say ESP error T result equals ESP error time out. And then we can run background tasks all this. And it says forever this timeout milliseconds has to be minus one to wait forever. So maybe if we give it zero, it won't wait. But it will tell us whether it's done result equals. And then then we do ESP check error check ESP results. So we'll raise an exception if it's not okay. Otherwise we're done. And we don't want to wait all done. And actually do we did I delete that in neopixel? Or do we want to run background tasks here as well? So you couldn't have neopixels running and not to give a beat. You'd have to DN it and rein it. Not sure what you mean. But yes, the neopixel right is a blocking call. So you can't do anything else while you're transmitting neopixels. And this is the code that that will block is the wait all done here. But I think that's what I did. Oh, is that my bug? So I have big long strands of neopixels around my front windows that I put up for the holidays. And there's issues where it starts it like flicker. It's supposed to be white or red only and it flickers to green sometimes. And I wonder if I don't know how long it takes per bit. But I wonder if this wait tx all done is too low. Urge and what the old implementation was neopixel right. It did all the conversion itself. And yeah, RMT wait tx done. So it waited 100 milliseconds with this blocking. So it wasn't running background tasks when I did that. Which is probably a bad thing. So let's lift that pulse out check that I just did. And we'll put it in neopixel right as well. So now we'll run background tasks while neopixels are transmitting. Which should be okay because it's yeah, it should be okay. We should be able to keep the RMT buffers full because we're not pushing it out here. So the RMT is going to have an interrupt that is like still going. So as long as the background task doesn't turn off all interrupts, it should be okay. Although run background tasks will run. Run background tasks will run flash writes probably. It's not the end of the world. And in fact what we can do here is I'm just thinking through this. If result raise error. Trying to think if I can let it fall through. So let's go back to pulse out. So it's allocated on the stack pulse out send. 16 bit pulse values while ESP only allows 15 bits. Thus we use entire items for one pulse rather than switching inside each item. Interesting, interesting, interesting, interesting. Because the other way that I did it in pulse in is I just ran the output. So it would have two microsecond resolution instead of one microsecond resolution. Which makes it interesting. So I wonder how it works with the encoder. It has this encoder stuff to it. That I sound the encoder I wanted for multiple times. It's just a duration new copy encoder. All right, so this new bytes encoder. So I think what we want is this copy encoder. And we can do that in here as well. RMT new copy encoder. Encoder config and self encoder. We'll do RMT encoder handle. We'll put that on our pulse out objects. It's interesting they're called handles but they're actually like pointers into their memory. I think the reason they're called handles is because they don't want you to look inside of them. Like it's all internal state. It's really interesting I've been really interested in how they've done it. And I expect copy this. This is actually empty. I should probably turn my lights down. The sun went away so like the ambient. Yeah, it's empty. It's an empty struct. New copy encoder. This is the annoying part and if somebody has recommendations on how to... Because they're doing memory allocations you want to say if result is not equal to ESP OK. Something's wrong and we can't go on. So we need to then do the tear down stuff. So we need to say like RMT Dell channel. Self channel. Self channel is equal to null. And then raise ESPR. Results. So it's kind of annoying. There's a couple spots in here where it's like three different allocations I have to do and every time you have to... If you fail it you have to do that. Empty struct on the public side but internal struct stuff is private. The empty struct for the copy encoder I think is actually empty. It's empty empty because they have this comment that says... I thought there was a... We're going to expand it in the future even though it's empty right now. And so then when we do tear down we also want to do RMT Dell encoder. Which are we doing in NeoPixel? I'm sure I'm not going to get this all right. Manual memory management. Okay these are a little... See that looks okay and I'm not being blasted in the face of light now. Okay so I didn't do the copy encoder. I could do a custom encoder. That could be kind of nice because I already have a buffer pulses. It'd be neat if I could use it. Like they're almost right. They're almost in the right format. I could destroy the buffer as I did it but then I can't modify that buffer. Which is why this is a separate allocation here. Or if I do a custom encoder... They have an example for a custom encoder. If I did a custom encoder I may not need to create that intermediate buffer. They might hand it to me. RMT encoder. Some commonly used encoders are provided out of the box. They can either work alone or be chained together into a new encoder. Contains the following functions. Encode. Might be called multiple times within a single transaction. The encoder should return the state of the current encoding session. Supported states are listing in RMT encode state. If the result return contains RMT encoding memful, the program needs to yield from the current session as there is no space to save more encoding artifacts. Battery IO? Well, that's what alarm is doing. Reset should reset the encoder back to the initial state. This function is also called implicitly an RMT disable. And then dell should free the resources allocated by the encoder. Customize RMT encoder. How does this work? Base class declares the standard encoder interface. And instantiate two other encoders. Leading symbols and recording the internal state. Except they don't actually show how to call it. You get the encoder state. You get the channel. You get primary data and it's data size. And then you get RMT encode state. How does it... I guess I don't know what encode state is. Return encoded symbols. It's returning a size. Hmm. I don't know. I don't know. This is not clear to me. RMT one wire. Customize encoder for neopixels. I wonder if that looks like my neopixel example. High test LED strip. This encoder stuff is complicated. Like encoded symbols, bytes encoder. It's using a bytes encoder and a copy encoder again. Can I not actually make my own new encoder? Like that is complicated. I think what I should do is just deal with it. Like the current implementation allocates to the stack. I can do that too. So instead of RMT item 32. We're doing RMT. Oh, you are something. Simple word. I think that if you... If you had a zero length pulse. So neopixels and remote control are similar. I didn't realize that. They're... Yes. They're similar in the sense that zero ones are encoded in pulse length. Right. So neopixels, it's like a 800 kilohertz signal where zero is a third duty cycle. And the one is two thirds duty cycle. Something like that. And then I think that something very similar is for infrared remotes as well. Infrared remotes have this additional thing where they have a carrier frequency as well. So that's what the carrier thing is. Okay. So setting the RMT duration in zero has undefined behavior. I feel like if it's zero, we should just skip it. This is a weird... Is that because we can't do an initialization thing? I don't know why there's three... We can keep the... This is just duration zero equals that. Level zero equals that. It's useful for lots of stuff where you want to send or receive arbitrary pulse lengths. Right. So that's what pulse out is doing. Pulse out is meant to be uncrustifiable. This is kind of clever. So this is saying if the top bit is set, then also set this. Is that right? I think that's right. Otherwise it's one. Because you can't give it zero. Right. NeoPixel is like three bits per bit, a start and end bit with the value in between. Right. Yeah, so that's the one-third, two-thirds. A lot of our implementations use actually disable interrupts and just bit bang it out. Because the problem with using P2M or SPI is that you really limit the pins that you can do it on. The nice thing about ESP is that the RMT is connected through that like full blocks. So as long as you have the resources available, you can do it. Yeah. Level one. Thank you. Right. So this is putting half at the front and then the remainder at the back. And that's okay. Since we're waiting for it to all be done, then it's okay that it's in... Like the stack is going to be an internal memory, which is what we want. And num bytes is going to be the length times the size of that. The channel encoder, self encoder, self channel. Symbols, length times the size of a symbol. Give it the transmit config. Return to zero. That's what we want. Okay, let's see if it compiles. You probably won't. All right. We got about 20 more minutes. Any folks have questions? I know I've like gone into the weeds here. The two levels are zero and one usually, but we're hacking it. So it's not... So the RMT gives you 15 bits of resolution and you can get 16 if you use two sessions of... If you use two segments of a symbol for the same value, then you can get 16 bits out of it. Sleep tight, David. No problem. And you know, if we really wanted to be precise, we could have it subtract one if... Let's see, these are down to the microsecond. The same level was intentional and I didn't come up with that. That's what the existing code did. Like I just... See, that is one thing is like the APIs are going to be super different because the underlying hardware is the same. It's like they renamed things, but ultimately, like it works pretty similarly. So yeah. And yeah, there's a comment that's already here. It says, well, ESP only allows 15 bits for one pulse. We just use two... Each symbol has a level zero and a level one. And there's a bit in there that says whether it's high or low. So you can just use two... Like the two things within a single symbol word to do the same level. Right? And wait to finish. All right. So we're in pulse out, but it's not seeing that these things are declared. So I think I'm just missing some. Includes. Like include, bindings, ESP IDF, and knit H. That has the check macro. And then include, driver, RMT, TX. Good night to Shippu. It's a great deep dive for sure. I'm glad... Yeah, I found my audience. Hey, we have less than a page of results. And it's not ESP result. It's ESP error. I always call it result type of error. Expected expression before token. So I think this is what? Unused variable level. Right. So that's a fluke. So when you're doing error messages, you always usually want to do the first one because it can cause subsequent error message issues. So if we... What? This doesn't mean that you can do a full duty cycle. Like it's all these quarter cases where it's like it would be good to have them were like written down and documented. Oh, what was I fixing this instantiation thing? Yeah, so I think that it might be like a C-ism. If we can say like the when you can provide this instantiation. Because now we've told what type it is. Yeah. Okay, 102. It's not size and size of, you know, small things like that. Oh, you know what? I thought about even yesterday was like, I got to find my rotary encoderies so I could test things today. And I haven't. It'd be nice to test without the carrier. Okay, so it compiled and then it aired out because I don't have the test board and boot litter mode, which is good. Now it's on to testing, which getting me to thoroughly testing like getting me to pull teeth. So, and it's Friday afternoon. Mark says my new order of dual rotary encoders showed up this morning. Nice. I think I'm, I think I might procrastinate on testing this all until next week. I do think that like if I, if, if duty cycle is equal to zero X F F F F F. Then do it. Adam text editor. Nope. This is sublime text. I find it. I tried, I tried Adam ages ago and I tried VS code, but I found them pretty slow. So I, I paid for sublime text. It's not that much and it is. Did you just say rotary encodery? Probably. That sounds like something my toddler would say. Um, duty cycle is not. So this is, this is saying that like if you're at the highest, like 16 bit duty cycle, then it'll be solid. And I don't know if we document that. I found, I was looking at the pulse IO docs again and I was like, this is not very explicit. Maybe that's what I should do right now is just write that up as a. Yeah, maybe that's what I'll do. So like pulse IO doesn't tell you that it's base unit is microseconds. It pulse in doesn't tell you what happens. Oh, it does. When there is no room room, the oldest pulse pulse like this removed. I, somebody filed an issue to change this and I agree with them. Because the oldest pulse link is, um, it doesn't make any sense. Because then you, like we don't tell you. It doesn't make sense. No, we don't tell you. So, so the structure that you get from the RMT is you get duration and level. Um, but in pulse in, we don't tell you level. Um, so if we have this behavior where we overwrite the oldest. That means that when you get the next value, you'll have skipped one. And now you're in your, your polarities wrong. If you're keeping track of it. Um, so that's just like something I want to change. Like it's just bad behavior. Cause it's like you, you'll be all out of sync once you do that. So when there is no more room, length equals max length. Any newer post, any newer pulses is paused and any other coming pulses are ignored. Okay. So that's a, a breaking change potentially, but it makes so much more sense. Pause pulse capture resume in microseconds. When length is equal to max length, it is unclear which pulses are active and which is our idle. So that's like a functional thing or an error during capture, such as a signal that is too fast. This is a case where we're going to have to like audit. Oh, I have a question for folks who are still watching. Do you ever use the context manager? So like with pulse IO dot pulse in as pulse in and then like nest everything. Because I was thinking we could probably save a non-trivial chunk of code by just deleting the enter and exit ones, which are the things that make it happen. I might, you know, you know what? I'm going to put this in the weeds here next week. Like we're already in betas for 9.0, but this is sort of thing that could get us some space back. And I don't think anybody uses it like people you will use DN it, but they don't really use the context manager. Jeff, yes, you mentioned last week that you got laid off. That's, I'm sorry to hear that. And I don't think the job sport is going right now, but feel free to like post a little blurb about what your experience is and what you're looking for in the discord server in case somebody else has noses and positions open. So yeah, let me click off here just a little bit. Let me pull up the notes for next week. So I went into the circuit that circuit Python dev channel and I clicked the meeting notes. So I want to do in the weeds, remove context manager functionality of core classes. I don't want another bullet point with pulse.io. Oh, come on. Just pulse in blah, blah, blah, blah, blah, as P, P dot, whatever, unset. Oh, look at that. That way it detected that I was doing a code block. I have like the markdown meet. That's pretty cool. I guess I got to use tabs in the weeds as part of the circuit Python Monday meeting. Yes, that's a good, the good chance to talk about that. So we have a weekly meeting. It is Mondays at 11 am Pacific TPM Eastern. It's in five sections. We have community news, state of circuit Python libraries in Blinko, which is a bunch of numbers dump hugs, hug reports. So thanks. It's like a chance to say thank you for other folks. And then status updates is what you've been working on in the previous week, what you're working on in the coming week. And then in the weeds is a longer form section for any sort of discussion. And this court kind of like, I need to ask a bunch of people, can I remove this is a perfect place for that. Moving it would save enter and exit entries in local sticks and the corresponding function. I don't think anybody uses this. I was meaning to look through, I think it's used like the bus device has a similar pattern and it's used there for transactions. But I don't think I don't think it's actually used in practice for for a lot of the stuff. So removing that could simplify things and kind of like, yeah, give us more code space and simplify the reality of like nobody does that. So yeah, if you have any comments, what you could do is you can go into this note stock. So to find the note stock, if you go into the circuit by the dev channel on discord, which you can join by going to the URL adafru.it. It's circuit by the dev and then at the top hit the pin, like the push pin icon. And it's it's pinned pinned there. And so when we do a meeting after the meeting, the host of that meeting creates a doc for the next weeks. And so you can collect like hug reports and status updates ahead of time if you want. If you're unable to make the meeting, you can still give hug reports and status updates. Just in here you can say like, I don't know why it's there like you could say like your username and text only is one thing we say but like add a note there that like you want it read off like please read. So and then the host will read your your updates there. And you're feel free to put notes down here as well. It should be open so folks can add comments and stuff. Yeah, so that was a brain brain thing. I think actually, you know, maybe I'll just add my notes about updating pulse IO frequency. What did I say can I owe and neopixel to IDF five apis in order to pulse in will be switched causing reception. I wonder, isn't it with both sides? I see used for drivers like sensors seems not totally unused with pulse IO. Oh, here we go. Okay, so it is it is used. I mean, we can run all these down. But yeah, that seems like a good reason probably not. I'm going to add that to the notes or tie it. You're welcome to add it to the notes too. I'll give you credit for it. Like we could do it in a limited fashion with is normally just a context for not having to type as much plus maybe a lot of resources. Yeah, so the with context, it's used to de-initialize their like it's because these native classes tend to grab resources like particular peripherals. The with the with box like all will automatically de-init when you exit it. So that is how we're using it. Yeah, it's a nicer try family. Huh. And Yanni's pointing out a web assembly for microcontroller thing. That is way out of my wheelhouse, but somebody might be interested in it. All right. Well, it's four o'clock. I was going to go for run before finishing up. So thank you all for hanging out. I will commit my changes and I'm going to procrastinate on the testing part until next week. But I think I do want to get back to that guide and get it get it released because I think there's a bunch of useful stuff in there. And I'll come up with a plan and how to do that without having to have everything complete. Maybe I'll just go over what I've written and publish it and then say this will be updated. So come back and check. I do kind of want to run the performance numbers again because we've updated a micropython since then. Anyway, yeah, the good, good advertisement for the weekly meeting as well. Thank you all for joining me. If you missed the intro, my name is Scott. I go by tannewt online and I work for Adafruit on CircuitPython. Adafruit pays me to work on CircuitPython. So if you want to support me and them, or if you want to support me, do it by paying them. So go to Adafruit.com, purchasing some hardware. That's a lot of cool stuff. And learn.adafruit.com has examples that you could find for projects that you want to do. If you want to join the Discord, I'll give the URL again, adafru.it-discord. I do these deep dives, 2 p.m. Pacific, typically every Friday, but I have a toddler and things come up. So FOMI guy fills in for me, so thanks to FOMI guy as always. DCD has one last question, which is, do guys take pull requests? And the answer is no. I did try to convince other Adafruit folks that we should store all the data on GitHub so that people can do pull requests. I wonder if that's a reason enough to move it out of a guide, honestly. That would be another way to collaborate where I don't have to do it myself. So I'll run that past one more and see what she says. But generally she likes guides. Guides are the thing. So maybe we could just do a placeholder or something. But yeah, I think because I'm so bad at testing, it would help me to have somebody to collaborate with. And it's going to be easier to collaborate on pull requests. Especially if other implementers come along and have tweaks to it. That could be more useful too. So yeah, not currently, probably not in the future. Although if there's a lot of stuff you want to be involved in, we can get you a learn account as well. Yeah, food for thought. Maybe I'll talk to the internal folks next week as well, if I remember. Yeah, other than that, I think normal schedule next week. Yeah, keeping the guide up to date. Well, if you've looked at the debugging with GDP guide, it's not up to date either. And that's another one I wrote. The extending circuit by the one is out of date, unfortunately too. So if you're interested in doing that and you say if it was in GitHub, I would do that, then that would be super helpful too. All right. I think that's it. So thank you all. I'll see you next week. Support Adafruit, adafruit.com. Join the Discord, adafruit.com. Try circuit Python if you haven't. Come to the weekly meeting if you haven't and you can on Mondays. Otherwise, we'll see you on the Discord.