 Hello. Hello. We'll get going here. I'll say hello to people. Hopefully it looks better. I changed the encoding profile and he went home. Oh, it looks like I am getting some dropped frames unfortunately. I don't know why that is. I'm getting some dropped frames. I wonder if I'm trying to push too many bits through or it's just a bad internet day today. Hello, Jeff. Hello, Michael. Hi, DVD. Hi, Charles. Hopefully I'm not dropping too many frames. Kind of bad, but I don't know. We'll go with it. I think it's my internet. I don't think it's my computer. I guess we'll just go with it. I think it's fine. I don't move that much. I don't move that much as long as the audio is okay. It'll be fine. Okay, let me just shrink this window. Restream looks fine and YouTube looks like it's happy. Don't look too closely. Andrew says no dropped frames obvious here. Great. OBS is reporting like 18% and it gives us like little signal bars, but I'm not sure. I don't know what that means. I don't know. I feel like even though I'm on fiber sometimes it's unhappy with me or it could be like I send the signal to restream and then restream sends it on. Maybe restream is having problems. So yeah, don't look too close and it should be fine. Hopefully as long as the stream keeps going, hopefully it'll be okay. Jeff says they are seeing a few freezes. That's okay. Welcome, welcome, welcome. Andrew says until I send that and then a few freezes. Yeah, it looks to me like it's bouncing a little bit back and forth. Sorry about that. I don't actually know if there's anything I can do. Mark says freezing here and there, audio seems fine so far. Andrew says pretty good. I don't think there's a lot I can do about that, honestly. I have symmetric fiber internet. I don't know why it's not happy with me, but I feel like what the last two weeks have been fine, but the previous week was bad again. Hi, DCD. So we'll just go with it and most of the time I'm showing my screen and I'm not changing all that much stuff anyway. DVD says audio is good. Good. As long as the audio doesn't hiccup, I think it's, I don't actually expect a lot of people to be watching, watching in detail. So yeah, it should be all right. Let's get started. We're after two and it's going well enough. I think we can get, I'm not going to restart or anything. So hello everyone. Welcome. If you don't know, this is a deep dive with Scott. I am Scott. Tim, aka foamy guy also does deep dive. So it's nice to kind of say who it is. I work on circuit Python for Adafruit. Adafruit is an open source software and hardware company based out of New York City. I do, yeah, so I work for Adafruit. You can support me and them by going to Adafruit.com. This is their channel. And I work on circuit Python, which is a version of Python designed for tiny microcontrollers. Here's one example that I got out. Here's a feather switch to presentation mode. So this is a feather RP2040 with a USB host on it. So we might get to some USB host bugs. And so I am, I kind of snagged that so that I would have it if I decided to work on that. So this black chip here is the microcontroller. They cost like under a dollar and they're little tiny computers that are good at interfacing with the real world. And they're also great for like just doing a single task. They're not going to run your web browser, but they are handy for checking a button and making it something light up if that happens. So deep dives, I'm going to switch back to eye tracking focus mode. So deep dives are something that I tend to do Friday afternoons. I'm in Pacific time. So Friday at 2pm Pacific is when I usually do it. They go for about two hours and it's kind of all a smattering of topics related to the internals of circuit Python. So generally I will kind of just work on what I've been working on throughout the week on the deep dive and I'll also take questions. And these questions can be all sorts of technical questions or whatever. I'm just super open to them and also happy to go on tangents. Get kind of really deep into the topics that people bring up, even though I haven't hadn't been playing planning on it particularly anyway. So I'd like to start with questions if folks have them otherwise I'll kind of like tell you what I've been working on. Let's say hello to Ham's Labs who says, I hope all is well or even better than all is wonderful. Yeah, it's getting pretty good. I feel pretty good. The family is not too sick. I have a one year old in daycare so it's all relative. Hello, Beata. Howdy hi. Do all controllers come with bent pins? They don't but if you have them you can give yourself some bent pins if you really want to. Jeff noticed I was like bending one of them back. These are the stacking headers and the stacking headers tend to be particularly bad. Stacking headers tend to be particularly kind of flimsy in this direction so you got to be a little bit careful with them there. Hello to Shippu. All right, so if folks have questions feel free to ask them otherwise I will. Maybe we should look out the window for a bit. It was actually quite nice and sunny but the clouds are rolling in. Sorry I went for a walk which is good. I've got bench cam here working and actually one thing I did this week is I tuned neopixels so if people are curious about that that's what this strip here is for is neopixels testing if you want to talk about that. Although I'm not working on that anymore it's done. I still have that. You might see here I got a humidifier because I've been zapping things so I got a humidifier. You can see the steam here. It's doing its best to keep up but I opened the window and now it's quite dry. I just zapped my microphone and I reset the audio interface which is not good. It's been good until I opened the window and then the humidity dropped. So yeah we have desk cam. Overhead cam is unplugged so we're not going to have that today. Let's go to the desktop. Again if folks have questions feel free to ask them otherwise the thing I was actually doing was what we've been working on is getting 9.0 stabilized so that we can do a 9.0 stable release. And so we have a release list or an open issues list. So if you go to it if root circuit python issues and then go milestones 9.0 you'll see everything that we kind of have on our radar to do before 9.0 is stabilized. And there are 17 open issues which I think is what we had earlier today too. But this is down from like 38 at the start of the week I think. So Jeff Dan and I have a really hammering on this. So we could go over the ones that we want to do but actually I just realized that I was fixing. So you'll see here this is the column of assignees and I have this one listen slash accept race condition ends up losing clients. I was looking at this earlier today and I have a change that it doesn't like it doesn't actually tickle a bug as far as I could tell but it does kind of highlight a difference between the way circuit python and see python work and so I wanted to change that. Jeff says do you wind up having to deprecate older boards or say version X is the last for this controller. We've had a little bit of discussions for that but we've never actually we have done that but only so early on in versions like two in version two we supported the ESP 8266. And then I think right before three I might be off by one but we decided that we would deprecate the ESP 8266 support because it didn't have native USB. So that was the point where we really kind of refocused on like the circuit pie drive experience. So the only boards that we've ever stopped supporting are ESP 8266 ones. There was a little discussion during circuit python 2024 about maybe deprecating some that are like perpetually too full in terms of code size but we came to no conclusions of that and I really not like to do it. I'd much I'd rather keep supporting the boards that we that we expect to support under the idea that like those boards that are full just don't get new features right like features are used almost always a function of a new module. And so you just omit the module from the old thing and then in theory it stays the same size. Now there are a few things that do wiggle that a little bit and those are the things that cause trouble but generally generally no we want to we want to keep supporting everything. It does look like the drop frames is still about the the same amount unfortunately but I'm also not moving it anything. And closed captions are off I think somebody I think somebody turns them off or or you or you have to yeah I can turn them on now. No I cannot turn them on anymore but it looks like they're off. Sorry I I had to explicitly turn them on last time here I'll add them to my streaming checklist. Set YouTube to auto start and auto caption I meant to I had to do it automatically last week and then I forgot to do it this week. But my intention is that they're on I don't know why they get turned off but I also share a share I share the YouTube settings with like the other eight of fruit streamers. So maybe somebody else and who uses this account turns them off. So sorry about that I do like having them on I don't know why they get turned off. If I'm good I'll remember to bring that up in internal meetings next week. Okay so that's the story about deprecating our boards basically I really don't want to. And the thing that I was working on is this race condition thing. Let's also just take a quick peek at pull requests that I have merged or that were merged in if people have or if these are interesting to any folks. So I just merged in updated sub modules blah blah blah out of range USB fixes new board. There was this issue that I did yesterday where if you typed a single character in the IMX boards you wouldn't be able to control see it anymore. And I figured out that we needed like a bigger CDC buffer from for tiny USB. So that's what this PR is. I also did your updates on the IMX and I updated the SDK. There were some reports of like MIDI networking on the IMX so hopefully that should be fixed. I simplified simplified how it worked because it was a little more complicated than it needed to be. And hopefully that'll make it more reliable. There was also an issue around yeah this this one I fixed like four bugs with. You can see they're all marked as as fixed now. There is also a read memory error where it tried to like allocate 800 K of bytes or something. It was like some like miss like some math that was happening internally that gave you like a bogus number. So yeah did that. Jeff did this really cool thing where he unified the SSL support between between the Raspberry Pi or the Pico W and the in the expressive ports. So the expressive stuff was implemented on top of the ESP TLS and Jeff basically removed that and circumvented it straight to embed TLS again, which is awesome. So we share the SSL side of things now between Pico W and Espressif, which should hopefully enable HTTP server as HTTPS servers was one of the reason to do that. Dan found an issue with TLS or Dan fixed an issue with TLS access to api.github.com some setting in the SDK config and he revamped some of the settings for the S3 in particular. So all S3s that have four megabytes of flash will no longer have BLE, which is incomplete anyway. Jeff fixed a problem where you to try to mutate a group that you shouldn't be able to mutate. PIO allocation to USB host was switched so that hopefully Pico W USB host will work. Deshipu who's in the chat found this issue where the dunder file was no longer available and Jeff found a piece of code that added that they got like accidentally dropped during emerge. I improved NeoPixels on the ESP chips. This involved moving, so CircuitPython will now run on the second core on the ESP32, which is awesome. We already did that on the S3, but I hadn't set the setting, so the ESP32 did that as well. So that helps NeoPixels on the ESP32 and then the S2 is kind of the trickiest of the three, the S3, the S2 and the ESP32. And I figured out that I can use more RMT RAM so that the transmission is smoother. So that improves NeoPixel transmissions on S2s, which is why I had the desk thing set up here. And I showed it on show and tell on Wednesday, like the difference between the two. So I'm really happy with that. This disabled variable length SSL buffers was causing, Jerry had found that the IoT doorbell example didn't work. And it was caused by this variable length SSL buffers for some reason. So I just turned it back on. I merged in A2X changes. We merged in all of the driver updates that I had been working on, which I think is what I did on this stream last time, which was testing and fixing for that. So that's merged in as well. So yeah, we've just been hammering on bug fixes. Catney did a board def, which is awesome. I boosted last week. I don't know if I talked about this, but I boosted the flash and ram speeds on all of the ESP boards. So if you have an ESP board that doesn't work very well anymore, we might have to turn the speed down, but I think generally they should be okay. Yeah, I think that's about it for the overview of what we've been doing, lots and lots of bug fixes. And I know somebody had mentioned, I think it might have been Tyath asked about doing IMX stuff on the stream, but I'm kind of through that. There's only one more IMX bug and it's kind of like the file system doesn't work very well. So Dan was going to take a look at that because he's the one that was seeing issues. Yes, we're in quite good shape. We have 17 left and a lot of these are kind of like a bit wait and see, so we'll see. Some that I have on my radar is one, I want to finish this IDF 5 race condition thing, so we'll definitely do that. Jeff has a PR for this USB host 5 volt power thing that we should also, that I can do the review on the stream for. Pulsing crosses hard crashes would actually be probably pretty easy to do if we wanted to do that. This memory error with simple imports on Pico W, I also had my eye on and then maybe these USB host keyboards as well, or these USB host fixes too. Any preferences or should I just keep going? Still dropping frames for some reason. I wonder how we debug dropped frames. Okay, so here's a simple one that Dan did and just had a build issue that I poked it for. So he just added another root certificate. Somebody found like Flight Aware didn't work or something. So just adding another root certificate fixes it. We'll merge that. Dan quickly found that, so that was great. And then let's take a look at this 5, allow 5 volt power to be controlled from user code on USB host feather. The pad state can no longer be used for whether it's in use or not. And this is useful for being able to turn off and on USB devices that you're connected to on the host feather. So Atmel Sandy, this has changed. You have this in the different. Let's see what it looks like separate. Ah, I see. That looks like a bug. What is separate? Let's just be a bug. So that looks good. And now USB host board reset. No glitch on the pin was already configured as high. Okay, so YouTube says it's lower than recommended current bitrate. OBS looks like it's okay. It might just be restream cause and issues. So this allows the host port to automatically turn it on. And then now now he's just doing separate pin claiming pretty standard stuff. Oh, okay. I should switch it back before I get confused. All right. So we're caught up in terms of reviews. We're actually doing quite well in terms of you might want to just, yeah, some things are tricky. I'm feeling it coming on that I'm going to end up going through these PRs and just closing and saying when you have this done come back. Open a new one. Otherwise it's just sitting here. Okay, so the issue that I was working on is this one from bill. And they filed a really good. I made this post of can you quickly reproduce this issue? It's hard to fix something that cannot be easily and quickly reproduced. So bill wrote a really good comment. So I should thank them and say and highlight it. So they say, okay, in circuit by thumb put this code up high. There's no other libraries. It's just this code here and see Python from your computer run this thing. And then here's kind of the sample output and why it fails. Which was great. Great for debugging. I found a couple issues with the test code that I thought. But I also found that part of the reason they're not closing. One of the sockets that is accepting things. And they got no error because in circuit Python, we would just kind of like implicitly allow you to reuse a port. But the problem with that is that you can leave another socket kind of hanging. And basically run out of sockets and you have to then wait for everything to time out and reset. So I have some work here that I want to get finished. If we get status. Actually, I'm in the wrong place. I want to be in here. So this is where all my test code was happening. So you can see that I've made some changes to socket. So let's take a look at what those are. And I have some prints and stuff that we'll have to take out. But I basically want to get this sent out for PR before the weekend. And it's a long weekend. We have a holiday on Monday. So the chances of my brain understanding all this come Tuesday or like not 100%. And in fact, I think we're going to we're planning on starting potty training for the one year old soon to be two year old. So I'm going to be absorbed and clean up from that. So be fun. Hopefully it'll work out. Okay, so I'm going to remove all the prints because I think I've figured out what I want to do. So these first two changes are just to get the debug builds fitting. So I'm just going to ignore those for now. Remove the debug prints and the Sublime Merge is great for that. This one's a little tricky where they have there's a debug print within code that I actually changed. So this is what I'm changing is that if you called socket.bind in circuit by them before we would actually allow you to reuse the address without you having to ask to do that. We're in CPython. You actually have to do that yourself first. So what I'm doing is I'm removing it the implicit nature of it and I'm I'm switching it to allowing you to do it. So we didn't have the ability to do it before but now you'll be able to do what you would have what you would have done in CPython. So let's edit this file. No questions. I guess we could do the quiet chat today. I wonder if that's because it is before a holiday weekend. So I'm returning error codes now so that we can get the right error message back. I'm changing the way that Raspberry Pi does it as well. This is a red herring. This is just me testing something and now we're raising. So it used to raise value error which is not not what not what CPython does. So now it'll do an OS error which is more correct. And actually I need to make sure that the PicoW build works. I'm adding two magic numbers that allow you to set the option. I don't know really why they're enums. I renamed this so that it wouldn't conflict with a other like debug define explicit. So oh I need to test that the Raspberry Pi Pico works because I don't think it will. Which I think I just did. See if this works. It may not. I think that I didn't. I didn't necessarily do the right. Yeah, I didn't update the return. So let's take a quick peek at that socket socket. Oh interesting. Look at this. So it raises OS error directly from it. Oh and it returns const none. That is not right. That is not right at all. So this is good. So if error is not equal error okay then we return. We don't need to raise anymore. We'll return the lookup. Otherwise we'll return zero. And that should be correct. Hopefully. Okay they compile now. I already tested the shared binding side of things. So I don't feel like I actually need to test it on the PicoW at this point. So let's just go here and we'll stage that as well. These two things we don't want to stage because that's just for debugging. So we'll get status and we'll do like that. Oh yeah and I have this problem that my uncrustify is too new. I tried. I spent some time trying to. We really need to update the version of uncrustify. I couldn't make a new version of uncrustify produce output that matches the old version. Uncrustify UN. It's the C code formatter that MicroPython picked and therefore we inherited. Another popular one that I would have picked is Clang Format. But I don't know the reason that they picked uncrustify but they did. Explicit. Actually require explicit socket for it implicitly mistaken. It now matches. Yep uncrustify. That's right. And I'm going to I'm just going to say that it fixes this bug even though it may be that it doesn't. That is this is a breaking change. It just prompted me for my. Let me type my password on camera. It's prompting me to unlock my key chain so it can sign the commit. All right. Get pushed. ESP accept. So push that and let's make a PR and well so once I push it it should show up here. And I can do a pull request and I'll have to actually maybe I should have checked because I think he did that. Market as nine is a breaking change changes the way that bind works. But it also breaks it from circuit by thumb behavior to see Python behavior. And if I was asking Michael Picoosa about it and they had to add this try finally block to the Adafruit circuit Python HTTP server. Whereas if we had done that this way before then they would have not needed the exception block because it wouldn't work like see Python. So this is a this is the right change I think in my book. Okay. So there's that. I don't know why my frame rate is still unhappy. Is there like a restream status system status 100% uptime some other partial availability. Okay. So now let's go back to issues and let's see if we can pick one that we can finish in an hour and a half. Now there's 15 open awesome pin naming Dan's going to do facets and flaky Dan's going to look at memory leak for Billy Dan's going to look at I just did something for this. Web workflow deletes a chunk of code on save is like it's bad but it's also hard to reproduce there's no like clear like do this and then this and then this to cause it. This intermittent delay while reading a cap touch is really just a tuning of the split heap thing. Pulse in hard crashes actually is probably pretty doable in this amount of time. So maybe we should just do that like that's the sort of one that like we it's a simple reproduction case. If it were if it crashes will be able to fix it pretty easily. Otherwise not memory air with simple imports is the other one I was looking at or thinking I could do this version has a PR hard fault on serial disconnect is a tiny USB problem. How do the connectable Billy stuff is Dan was going to look at web workflow and S3 Melissa's going to look at and then these two this unplugged replugged USB host Jeff thinks is fine. And then no audio artifacts good thanks DJ Devon three. Yeah DCD says you've been testing pulsio the other week right yes I was doing pulsio testing. And I guess I didn't do the carrier wave testing yet. But if I pull up the guy that I haven't released yet and maybe I should do spy and I could see testing. I have another secret browser with all my work tabs. So I added your testing here. I didn't add and maybe I should I did some like stress testing using MIDI and found more issues. But then for pulsio I did free running which I think is what we were doing where we had to like get the right first pulse. And then pulse out I did just on off we did that as well but then I tested the carrier and I did the carrier with like a pretty low like 10 kilohertz frequency. So it was low enough that like pulse in could actually measure it so it was getting all of these 50 microsecond pulses in. So I was able to verify the carrier via via pulse in which is cool. And that was kind of the last thing I did before I was done. And it was interesting that the carrier doesn't necessarily line up with the pulse. So it got like eight microseconds and then blah blah blah and then 42 at the end for a total of 300 which is what it was 300. 300 on 100 off and 300 on again. And the off that was 102 so it was like very close. But the carrier shouldn't apply shouldn't apply for the. Yeah right. The carrier shouldn't apply for the off period and the this two extra will know two plus six plus 50s plus 44. Yeah so I don't know why there's an extra two there but it's like well it's it's good enough for me. So yeah I did that. I guess I didn't do did I show count IO so I did count IO where I use pulse out and then just verify that the number of edges matches. So I did that. I had to fix something with frequency IO and then I did rotary IO as well. Yeah so I did all that testing and I did like dump all of the test code in here so I need to go back in. I think this is probably pretty close to at least having like the first bits already to be published. But I'm kind of like thinking the same debug if I could reproduce it would be kind of an easy win to do. So it's just a hard fault on Metro M4 Express so it's a sandy 51. Do I have any of those with an arms reach or do I have to take my mic off to get that I didn't actually think I was going to do this but now that like I have this constraint of like something I can do pretty quickly. This is a sandy 21 but I want to do a 51. I don't think I have a 51 on my desk. This is also an M0. Sandy 21. I actually put them away and I didn't foresee just knocking this one out. So let me get a Metro and then we'll do this bug and get it down to 14 issues. Pulse in is crashing. Oh and I zapped it again. Definitely the humidity in here is dropped. That's a great thing that your filing system is working well. Yeah, I'm quite happy with it. I have more stuff that I need to do that for and I do tend to collect like I have all this desk space now. So I do tend to collect boards here but I'm trying to be better about putting them back slash putting them away. Okay, so let's just get this. I have an ESP board here but I'm not going to need that anymore. And I have a Pico W for that memory one. But let's just take this Sandy this M4 Express. And it doesn't look like it's working. Maybe I broke this one. I get the green LED but I'm not getting anything else. So maybe I actually destroyed one. It's probably all this savage. I should have grabbed it. There's another one in there. I should have grabbed it too. Static file. Did you staticify myself before I grabbed the mic again? Okay, so maybe since I'm going to be fussing to my left let me switch to desktop with overhead which is not what I want. Great. Okay, so I grabbed two more metros and I also grabbed a Grand Central. Sorry, I couldn't see those. The reason I grabbed these is because they have SWG connectors on them. Is that the same one? Oh, you know what? There is a, oh that's for the, there's a switch on it. This one's not doing anything either. Is that the one? Let's see if this one works. What world? I have two metros that don't work. What world is this? Like I'm expecting the boot loader at least to come up. And power. Maybe I destroyed the boot loader on those. This one works. Oh man. Can you, I don't know if you can see the LED blinks. It's blinking like it's like old enough circuit python where it's like trying to give me the line number. I don't think those metros go in the boot loader which is weird. You like seeing me text my partner. Anyway, this is old circuit python so let's, it's also a SAMD51. So let's update it. So I just double click to get into the boot loader. And let's build a Grand Central M4 Express. Let's clean in case I have done it recently. Where is the decode line number algorithm? That's why we got rid of it. Because nobody actually used like what line number it was. It was like certain colors were like different 10s places. There's a reason we got rid of it. Nobody used it. Nobody used it. It was too complicated. I'm much happier with it now. We used to keep the LED lit as user code was running and now we don't which is nice. The old beep codes don't miss those at all. Might be nice for breading but if they're in enclosure then they're pointless. Yeah, they're not useful. The simpler system of just like green means it worked. But it's also done versus red means it erred. Yellow is safe mode. Very happy with that point or that choice. You just control... There's a way to mount. Can't really see it. Except it's GCM4 boot. This is a kind of neat one liner that allows me to mount and copy over the UF2s without having to like go into my thing and drag and drop it. Yeah, yep, exactly. The serial link is much better. Alright, so we got a circuit pie drive. There's all sorts of stuff on here. So what I'm going to do is I'm actually going to just copy it and I have this folder called the random backups. Create a new folder with today's date. Like I don't know what codes on here or if I backed it up. So I just copy it all off before I mess with it. Go back here. I don't even know what this code is. Oh, it's a BME680 test. You know what? I didn't test... What I've started to do is... So now I'm going to code that pie. What was I going to say? There was a thought there that I didn't finish. Oh, it's just printing the time. It's not crashing. Retired wizard says I've got one of those backup folders on my desktop. I never ever go back to it. I do sometimes. I'll like search it. So this is just printing time. And they said that they didn't have anything actually connected to it. They're using a Metro M4. Which pulls in board D2. But it seems to be working okay for me. I wonder if I... Let's like... One thing is if D2 is like floating, it might just cause some... Maybe those are analog. Hey, there we go. Alright. Alright, so we hard crashed it. So it crashed when I just plugged in the wire. Which is good. So now what I'm going to do is... I have a J-Link here. That is connected to this IMX Metro that I was working with. And I'm just going to plug it right into my Grand Central. And here I'm going to do... J-Link but with a... At Sam E51. J19. I don't know if that's a J19. I think it's something... Yeah, it's a P20. So what I'm trying to do is... I want to get the debugger connected. Can I make the desk camera primary? Sure. This. So here's my setup. I've got a J-Link here. It's got the FAT cable. Gets converted down to the shorter cable. And then here's the... Here's the Grand Central. And all I did to cause the crash is like, dangle this wire off of it. So because it's... Pulse-in is going to look for edges. And I suspect what's happening is that... The fact that it's just like a floating wire, like there's no set kind of value for it, which is causing like maybe a lot of edges to happen or something like that. So now what we're going to do is we're going to do GDB with a Grand Central firmware, ELF, and then we're going to do Clean and Reload Debug. So that was a non-debug build. So we have all the code running on there. So now what I can also do is I can... You can't quite see it here. So I have a USB cable with a switch that allows me to only power the device and not have the data connection come up, which is really helpful when the debugger's running just to insulate your computer from like the USB coming and going and coming and going. Okay, I think I'll switch back to the desktop if that's okay, but let me know if you need to want to see the bench again. Floating edge is causing a hard fault. That's a bit weird. Oh, and you know, the other thing I should do is I should accept, assign myself, and I will remove the needs retest because we managed to... because we did manage to reproduce it. Okay, so we just loaded that. And now we should do MonReset. We should break. So this is good. This is how I usually will debug SafeMode errors like this. So there's a reset in the SafeMode function that I break on. So now I hit Continue. It's going to start up and hopefully run the code, which I can't tell because I don't have USB. Let's just kind of plug and unplug it. So what I'm going to do is actually just go across the way and you can kind of see this. So I'm going to hit ground and then I'm going to like manually do some pulses. 3 volts, ground, 3 volts. And we're not hitting that bug unfortunately. So let me... I'm going to remove the wire trace. So we are in... We're in built-in print. So it looks like it's running. Let's just keep it going. Maybe add a blink into the code to be sure it's running. Yeah, that's a good idea. But that involves turning the USB back on. I wonder if I just need to give it like too many edges or something. I'm trying to like rub it. Was any information from the crash captured? Oh, batteries. Not that first time unfortunately. That's what hopefully having the debugger on will catch. But that involves like being the speed that it needs to be. I mean it was running kind of a while. If it's floating, I don't know. What was the bug verified by second person? Like I managed to do it. That's why I said it didn't need a retest. Bummer. Maybe we... Because we didn't crash, let's do what retired wizard is saying and just... Let's turn our data on. It could be USB related, I don't know. So if we do crash, we'll still be okay. Let's do what the retired wizard was saying. Let's just let it run for a little while longer. We could also do... If this doesn't work, we could also turn on a PWM out on a neighboring pin that we could just jam it in there and get a bunch of edges to try to just overwhelm it. Oh, there we go. Look at that. I'm going to flip my USB thing because the USB is going to be unhappy. Alright, we've got a back trace. So maybe it is related to pulse in and auto reload. So we're in format float. We get a signal handler. Pulse in interrupt handler. Pulse in 93. Okay, so let's pull that up. Be what we're looking at. At mail sandy. Common hell. Pulse IO. Pulse in TC. So 93 TC. So this TC must be null. So if we go... We want to be in frame three. Info locals. TC is not null. It is 202038E. But my guess is that's wrong. So 01, 2, 3, 4, 5, 6, 7. So these are the valid ones. And pulse in TC index. What do you think that is? 255. Right, so we're... It's being set to 255. It's indexing too far and it's getting the wrong... The wrong value out of it, which is causing a crash. So pulse in TC index. This timer is shared amongst all pulse in objects as a higher resolution clock. So one way to protect against... A ruin, I see your question. I'll get that in just a bit. So maybe pulse in reset was called. Or DNIT was called. But the easy thing is to check that this is not... That that's not the value. But if pulse in reset's called, it doesn't actually turn anything off. I wonder if that's what it did. But that's not where we are and we're still running according to this. So how did it get set to... How does it get unset? I'll take Aaron's question so I can let my brain decide how I want to do this. Appreciate these deep dives you do every week. I have a question that is off topic but still certified and related. That's what I want best. I'm happy about that. Oh, let me switch to... I'll switch here. Hope it's okay to raise it in here in the chat. I noticed that the ESP C3 modules don't have the alarm module implemented. And hence things like deep sleep is not possible. Is there a particular reason for this? Or has it just not been ported yet? Yeah, I think we just haven't turned it on and tested it. So I would try it. Try turning it on and see what happens. Yeah, I just haven't spent the time on it yet. I don't know of any particular reason that it would be a problem. I also haven't tried to do it so I don't know what the hurdles are. So yeah. No reason except the C3 hasn't just gotten... We haven't done a lot of work on it yet. So yeah, if you want to try the CircuitPython dev channel on Discord is the best place to get help with it. And we'd be happy to merge changes that allow that to work. Like, yeah, whenever you get to it, that would be great. I do intend on circling back to... I have this implementer's guide and I do want to do the alarm module, but I haven't gotten there yet. It'll depend on if the alarm module implementation uses the IDF and the IDF works across all the boards or what. Yeah, it's a great task. If you don't have one already, get a PPK too. So don't do any power deep sleep stuff until you have a way to measure the current. It's not worth your time. So get one of these if you don't have them already. The power profile kit too, they're like a hundred bucks. I think they're probably in stock at Digikey. If you're going to do alarm stuff and deep sleep stuff, start by getting one of those. In fact, let's just look at Digikey right now. I think we stock them too actually. Yeah, we have 83 in stock, they're a hundred bucks. They will save you a lot of time. So they're not in stock at Digikey. They're $90 at Digikey, but we have them for a hundred. And you did get one of them recently. Perfect. That is probably something that's worth doing a deep dive if I've not done it already is doing alarm testing. We'll see. I don't know what the lead time is on it. But yeah, we have a hundred. They haven't had them for a while. They're great though. Like I have this other one that was kind of open sourcey and good, but it was like 600 bucks. So like the power profile kit too is just, it's like I have this jewel scope. I got this right before the PPK2 came out, but the PPK2 is the way to go. A hundred bucks does everything you need. Okay, so going back to this problem of the, this crash, I don't know how it's getting or why it's getting set to SS. Like one thing we can do is we can just take all the places that it's set to FF. TC index. Pulse in timer interrupt handler. This is not the one that's crashing. It's this, this pulse in interrupt handler is crashing. So this is where we can guard against it. But the question is, is why is this being called when it's invalid? So what, let's just do it since we have. So this is how you can do debug prints that are effectively like go out the same way that like a normal Python print would go. So this NP plat print is the simplest thing. And let's do other place. It happens is here as DNA. Although we might crash before the flushes out, which is maybe a reason to, okay. Well, let's try it. Must be calling pulse and reset without a subsequent construct. Well, reset is it really should be tearing down the timer. That's like very fast and loose. It's very fast and loose. Like it leaves, it leaves that like other timer running. Although when we did the same deport, we were pretty fast and loose with like, I think it's cleaned up later. Like I don't need to tear it down correctly, which I am having. I'm moving us away from that. Okay. So it started up. I never did get to the blinking code before I crashed it. So I'm going to flip the switch again and I will switch to my small desk cam. Okay. So there's that. And now let's open circuit pie drive. We still have our break point. We'll open the code. Digital IO. Oh, and we're still going fast. So let's hit save and we crashed again. Okay. So, so we're in reset to save mode. We've actually looped all the way around. So, so we had the reset. We had the reset. Pulse and interrupt handler was called. We're in the time sleep. So, and we're, we're in the time sleep, which means we called it again. So I wonder if it happens. Like it should find it again. Like we did the reset, but we started over. It should have constructed it and it should have said it. Then again, but maybe well, ref count was also set to zero. And I'm okay with it crashing. It should be zero. Like, uh, the fact that we're doing the blanket resets is like, I don't think that's the best way to go about it. But the problem is that like when things are sharing it can get hard to do specific resets. Maybe we're failing later on. So we're like partially initializing. But then we would be an exception state. Let's get it with a new print. So it, so it's not that pulsing is a problem. It's that writing during the pulse in is the problem or reloading once pulse in is going as a problem. So we can, we can now effectively reproduce it, which is good. I think. And like, I know how I could fix it by just saying like, if it's this, then bail. But like the question is, why is it that in the first place TX index? No, it doesn't. It's just for the print. It doesn't really matter. Yeah, it's wrong, but it's just printing. Okay. So let's pull up the drive again and the code again. Let's say reset and we didn't get to where we were. Even though we should have gotten to ref count zero. I think it kind of feels like we're like, but there was no exception, which is weird. No exception, but we did print time monotonic. Like it probably printed that before we did it. Yeah. Let's just print here like any of these should have caused problems and ref count. Actually, let's print ref count. It should be zero because it's being set to zero right here. But maybe ref count is getting messed up or something. This is good. This is a bite size debugging thing. And this is something that's pretty common of like, I'm getting safe mode. Like the process is different on ESP, but not that much different on ESP. You would do a debug build and then it would print the backtrace when it happened. I think this is worth covering. If two dnits are called in a row. I'm printing on dnit. Did I destroy my Linux USB? Ella's blinking now, which I don't think I, I never finished that. Did I? Oh, I hit reset and now everything's screwed. Ella's blinking. You know what? I wonder if Ella's meant to be TX. Semicolon says, I was going to comment a random obvious troll comment like write a loop with a condition true. But working as a DevOps engineer where my work is like 99% ops. I had no idea about coding. I think the, I think the wrong LED is blinking on this. Like I have a blinking LED. It is marked L, but it really should be the TX one because there's this board has TX and RX as well. Which is silly too. Okay. Well, it's going again. USB connected, which is good. Let's just crash it. Ref count is 255. That's not good. That's not good at all. So how is ref count being set? Did I, did I print the wrong thing? Wrong thing. No. How is ref count being set to 255? That is weird. That is really weird. I'm signed. I'm signed 8 bit. Am I setting it to minus one? No. I'm setting it to zero. New pulse and ref count. Zero decrement it is 255. But we're not plus plus. Are we calling DNA incorrectly? Oh, let's see. We're on M4. If on M4s, I think what you can do is you can do ASM breakpoint. Yeah, I think this will work on it. So this will say if ref count is zero and we're doing this DNA, which we, let's try that. That's a good point, retired wizard. And I feel like we should fix the TX pin as well. What was my, my bench camera is frozen. You're not seeing me move. Bench camera is useless. Useless. Here we go. You can see it again. I think I really hammered on my USB bus. I think that's part of the problem. Huh. That's not good. It didn't even start up. OFS entry equals zero. My file system is unhappy. This is why I backed up all the things. All right. Well, now it's going. I don't know why that happened. I couldn't only fix so many crashes. All right. We're going circuit pie code up high. Safe. All right. Here we go. So we hit that breakpoint that I had put in. So this is probably in the finalizer stuff. Yeah. So we're in GC suite. We're stopping the VM. We're calling DNA. But we're calling DNA in a case where as retired wizards talking about our ref count is zero. But ref count should be one here. Unless unless it's calling it twice. Unless we're pulsing DNA twice, which is exactly what retired wizards talking about. But it should be guarded by like if it's if the object is de-nitted, let's just do another. I could do a watch point. It's an option too. Okay. So we know our ref count is getting zero. It's possible that it's being overwritten to zero. Oh, you know what it could be. Oh, I know what it is. So pulse and reset. So maybe this code was written before all the DNAs were called. So pulse and reset. And then pulse and reset setting it to zero. And then later the heap goes away. And when the heap goes away, it calls DNA, which does the decrement. So I think what we want is we just don't want a pulse and reset. And I wonder it's probably pretty old. It might predate the finalizer stuff. So when you allocate a Python object, you can say this has a finalizer. And when it does the heap cleanup, it'll delete it all. So this is a weird interaction between those two things. Where we're setting ref count to zero. And then we're doing the DNA. And the DNA is subtracting one, as retired wizard was talking about. Common how pulse IO, pulse in. Hey, look, four years ago, I fixed Sandy 51 pulse and reset pulse in. So I added the pulse and reset. This could have been a bug for that long. So there's the ref count stuff. rework sleep typing. So this is where I add pulse and reset. I don't know why this doesn't make any sense. Like this commit message makes no sense to what it's doing here. It's all I guess this stuff is pulsing stuff. Like this is all pulses. This is garbage. Thanks for tired wizard. The other thing that I should check is that this was in 5.40 beta zero. Low power, hopefully fixed pulse in. This is a much bigger change. Yeah, talk about low power stuff 197 files. And we've been doing low power for four years now. I did pulse and changes everywhere. So I think this is just wrong. Okay, so I added the pulse in timer stuff. But I also added this reset and my view file pulse in this thing. I'm wondering if shared bindings, pulse IO, pulse in use the finalizer already. It did not. Okay. So it didn't use to use the finalizer to do the DNA automatically. That's probably something that I recently did. I feel like I just did that, which is why it's a new bug, which somewhat brings up, somewhat brings up the question of like, how many things did I break? How many things did I break when I switched that? See, now it's new object finalizer, which Jeff added it in March of last year. So this bug has been around since March of last year. Here's an old one for those of you who are like historians and circuit pipe on all of our hardware APIs originally were in one big module called native IO. And right before our 1.0 release, we decided to split it up into smaller modules, which was very much the right thing to do. Says, for example, this way pulse IO can be omitted to allow for something else such as touch IO. And we've actually split pulse IO further more since then. Okay, so this has been a bug since the finalizer. And I think the right fix is to just remove it because DNA is smarter. It actually will reset the TC. Yeah, so let's just remove that. Pulse in and then its call is in supervisor here. I wonder we probably need to do an audit around this. Although this is like a specific bug, but like if pulse out pulse out reset is doing the same exact thing. I wonder if we can I wonder if we have the same bug with pulse out. Like it's it looks like the same code. I think that's probably the same problem. I wonder if anybody's bonus points if you can do it. So it seems like we really need to either you either have a blanket reset or you or you don't need to do the DNA. You can't do both. I'm pretty sure that pulse in not working as expected on Sandy. Clear resume. Note how the active slash idle positions sometimes get swapped. Yeah, this is exactly what we just fixed on ESP last week. Is this bug. I wonder since I'm in here whether I should just do it. I can't just do it. I can't just do it, but I wonder if I can cause the same like the same code with pulse out should literally crash the same way. Right. Like if we just do the same thing but with a pulse out, I bet we'll we could crash it as well. Okay. So let's we can leave that break point in there because it shouldn't hit it anymore. But now let's actually we'll reload it here and we'll do the same thing here. I'm pretty sure pulse out is also rough counted in the same exact way. I wonder if we could have a way to guarantee that like one way or the other is done. All right. I'm going to load it again because I added that other break point. Good. Good. Good. I love fixing bugs. It is very satisfying. I guess I should verify that I fixed that bug too. Do that first. Oh, and we should fix the light. The pin, the TX pin is wrong. It's the L one. It's blinking, but our USB hasn't come up yet. USB is unhappy, which is the camera is still working reset. Oh, and I that means I have to do that. When I hit the reset button, the J-Link comes unhappy. I gotta restart it and reconnect. Come on USB. I bet my Linux USB stack is very unhappy with me. That is my guess. That is my guess. It looks like it's working, but like we're not seeing it show up on the TTI or the, I'm just going to power cycle and see if that helps. Oh, you know what the reason is? I had the switch flipped. Simple problems. Oh my goodness. Yeah, I've done that before. Let me switch to the USB flip. That's the downside of having the data switch on your USB cable. Oh, now it's blinking and it still didn't show up. Got the switch right. All right. So circuit pi code.pi save and it worked. Okay. That count was, oh, that's new TC index. Okay. That looks good. Now let's see if we can't do a pulse out and save it again. And we crashed. So pulse out has the same problem. So let's just fix that by doing the same thing and relying on DNA to do the right thing. So DNS should be correct. It's the bulk resets that are not right. Nice. Didn't I delete it once already? So this is like a whole class of bugs. Like we switched to finalizers, which are helpful, but they may not work right with resets, the bulk resets. This makes me think that like maybe in 10.0 we should really just completely get rid of bulk resetting. It's kind of annoying, but you already have to have dnet dnet work right because the user code could call all the dnet dnits anyway. It flipped the switch. Now I know to look for that and it is input output error. I wonder if that's a file like file system corruption. Yeah, it might have been file system corruption. I mean, it's problematic that I'm crashing due to a file right. Like it's kind of like not good. So my yeah, that's how your file system gets corrupted. Okay, so it's working. And now if I hit save again, oh, it's right protected read only file system. Yeah, my file system is not good. So I'm going to eject it. And then here I'm going to go import storage storage dot erase file system, which I wonder how many how many of these file system errors are caused by this bug. Like if you if you have a bug that happens during reset, it's possible that. Yeah, it's possible that you're not flushing the file system first. So I wonder if we could flush the file system before we run all the resets. Yeah, interesting. Interesting. So I'm glad I backed up all my files. I can open this, but then I can control Z and save the new version and save it again. And I don't crash. Oh, internal resources in use. So with that reset, with that reset, I'm not freeing everything I need to be freeing. There's all timers in use. Where am I getting this code up high pulse out line six is pulse out. And it's telling me here's result. Common how PWM out construct is raising this error. So that's what must be. But this PWM not DNH and handle that. So that's my guess PWM result. PWM I'll PWM construct and then PWM out DNH. So that should be like one for one, but I must be leaking something else. All right, we're just about out of time. It's not this all timers in use. We're not even getting that far. So maybe we need to look at PWM out is having the same problem. I'm pulling on a thread and I don't know how long it is. Unexpected maker sorry and late we having fun squishing those bugs. Yes. And you will be very excited that I fixed a neopixel issue on the S2. So you should try absolute latest because I think you have an S2 neopixel board. And if you've seen it flickering when Wi-Fi is on on circuit Python, it should be better now. So check that out. I did not talk about that in the stream, but I did that this week. And I thought of you. So let's just take a quick gander at PDF or add some prints to PWM out. So we have a PWM out reset. So MP print out. I wonder if this is also has those. I don't think PWM outs are automatically reset though. I care about the index. So here's the internal resources in use. New timer. Num timers to per pin. Timer equals T. Pin timer. Then what I care about is the DNA. Pulse out is complicated. Turns out, how does that work? So this just resets tracking. It doesn't actually reset the resources. Oh, and it reset for some reason. T and declared. Timer. I will get to the bottom of this. I will go for a run. Do, do, do, do, do, do. Any other questions? How close do you think nine releases? Oh, I hope a week or two. A couple of weeks. Dan's planning on doing another beta beta one this weekend or early next week. But then I think probably after that. So maybe not next week, but the week after we'll have a release candidate. Hopefully. There's a few other things that we need to do next week before we do release candidate. So yeah, hopefully a couple of weeks before it's at least in release candidate mode. Generally, once it's in release candidate, we're basically done. Kind of like see if anything crops up over the next week. And if it does, we'll fix it and do another release candidate. But if like nothing happens for that week, then we'll just make that release candidate the same as the same as the main stable version. So yeah, not too far away. We're a lot closer. We're down to 15 issues, which is awesome. Continuing with my USB switches. Still going, but my J-Link is unhappy for some reason. I want to start flashing nine onto my boards as my test jigs as I'm split between 8 to 10 and 9x because a tiny C6. It would be nice to be flashing nine on all of them. I don't think there are any outstanding ESP issues. I knocked all those out in the last week or so. There is one about the Web workflow not working, but I think that's actually a JavaScript fix on code.circuit.com. So it should be in pretty good shape. Let's see what's happening here. New timer zero. Internal resources in use. AWM out reset. And then we crashed. And we crashed. Pulse out the unit. Pulse out 180. I know C-Core Pride that doesn't support user code in RB2040 Core 1, but have you had to debug C-Code with GDB in Core 1? I have. I did a little bit of that when I was doing like the Pico DVI and the USB host stuff. Yeah, it's not fun. Like basically you just like that command I'm running to connect via J-Link. You just do the underscore one instead of it, underscore zero. Like kind of after you've already crashed to connect to it. So it's a little interesting. I just want to ship a beta on all my boards if I can avoid it. Even a stable one. Last time I did that with 7x, folks were just re-flashing previous stable. Yeah, it was interesting. It is interesting to me that so many people really want to be on the stable release. Yeah, so we're a few weeks away, I think. So definitely test it so that we feel pretty confident about it. But generally it's pretty like we're pretty happy with it. And this beta one should be even better than beta zero. Yeah, so I don't know why pulse out pulse IO pulse out DNA. That seems very weird to me. Now this is LTO'd. Oh pulse IO pulse out DNA is the is the the shared bindings portion. But ref count shouldn't be crashing. Let's finish. I don't know why it's resetting like that. It shouldn't be. Oh, you know, maybe my USB port is turning off back on again. Probably didn't have to run two GDBs at the same time. No, I was kind of like switching back and forth. But yeah, it's really annoying because like getting them going at the same time is tough. I don't know why this is causing a problem. It shouldn't unless that is not on the heap. I know, I know, I'm running out of time, but I'm not about to like leave this for next week. I have more projects that require stability that I'm still working on daily. It's big into experimenting with 8x, alphas and betas, but not as much for 9x this time. Yeah, you can wait till release candidate or till stable. Did that work? Well, yeah, I think the my host operating system might have been like, hey, this USB device isn't working. Let's reset the power, which breaks my debugger connection. I know it's four o'clock, but I mean, I could stop the stream, but I'm not about, I'm too into it to get up. It's real tempting to go running. I'll tell you, especially because this, I mean, it's still not too bad. It's not raining, but I think it's cloudier than it was. So, okay, so our USB is switched off. Flip USB on. New timer, zero. And then we crash. And we're in DNit again. Pulse out 181. Ah, now we're in the breakpoint. But how are we decrementing ref count more than once? PwMount reset. Throw an exception, PwMount reset. Ref count here, zero. Spare timer plus plus equals zero. Oh, are we DNitting? Yeah, that's what we, that's what we must be doing. So I think what's happening is we hit construct and we try to do this, but it fails. And so it raises an exception and then on cleanup, it still calls DNit. I think what we need to do is we need to gauge self pin. We need a different way to know that it's already DNit. So instead of, see, right now we're doing it based on whether PwMount is DNitted, which it should be given that it failed. Like if it raised an error, if it gives a bad result, PwMount, how does PwMount know it's DNitted? If self.pin is null. So we want to make sure that self.pin, so self.pin is assigned at the very beginning. So it will be considered that it's, it's, we want to be at the very, very end to it down here. All right. So that should fix it. Hopefully it did mean that we're here for you. Thanks DCD and thanks to DCD for usually taking notes. I don't want to assume you are, but you usually do. And let's see if this load works. Looks like it did. Continue. We've got a blinking light we still need to fix because it's a wrong light blinking. We've got USB, circuit pi, code, save. And it started again. We run again. We still ran out of resources, which is not, not correct. Like we're not giving back this, like there's this new timer zero. We're not giving it back, which is weird. So pulse out DNit new timer and then PwMount DNit. This stuff is so hard to reason about. So DNit, is there going to be a test? And then we should get down here. I don't know why PwMount DNit and like it should get down here. And it should do it. Should do PwMount reset. It should be okay. Or the TCC reference account is not right. Let's be friendly to our USB. Welcome to the world of circuit python. I do want to be able to go for a run though. I'm not much time. I feel like I'm like not that far away. It's just like all this reset logic getting it right. It's hard. Okay. We're blinking. Turn on our USB. Still in use. Still in use. So, so timer zero and use still potentially okay. But why don't we, why aren't we able to use it a third time? Channel. Num timers per pen. Channel okay. Plane channel. TCC channel. Like maybe there's two channels. So we went on the channels. Timer and use. I don't know what else it would be used for. Unless we're also using it for the pulse out. Or we're doing the same mistaken ref count again. Eject our drive before we make it all go. Thanks for sticking with me. Anybody who's still out there. Even though I've been dropping frames this whole time apparently. I don't know why. I'm on the stuff though. I'm on the bugs and bugs that happen when your file system's in the bad state. I think do we flush when we do reset in the safe mode? I don't even know. Probably should. Okay. That light is still wrong. That would be like the benefit. Get the right TX light going. Assuming that I don't have a prototype board. Oh look. Ref count 255. So we're having the same problem. Where I think. Ugh. PWM out doesn't use DNA. It uses the bulk reset. But. Resources in use is. Like ref counts not right. Because of the same problem. Ref counts not right. Because PWM out is bulk reset. Like if I look at PWM IO. PWM out is not a finalizer thing. I think I have to change PWM out. I should probably do that. The bulk resetting is just a pain. The other nice thing is that. If we move away from bulk resetting. We don't need the. If we move away from bulk resetting. We don't need never reset. Like only direct DNA's matter anymore. And so if you need something that's never reset. You just don't. You just don't DNA it. Which I think is like. I didn't want to do this now. But it's probably for the best. If we just got rid of bulk resetting completely. And just made everything with a finalizer. But that's a lot of work. But like this is that thread. Like this is like one thread that's just like. Spaghetti. I guess the problem is like. If. There's anything relying on bulk reset. That doesn't do a property in it. That's a problem. I think this is a good time for me to wrap up. And take a run and see what I think at the end of it. At least I think at least I have to do PDA by amount to be. Dean itting. Which really shouldn't be that. Big of a deal. Like I think finalizers are the right way to go. Yeah spaghetti for sure. Okay well. This has been deep dive. Welcome to the depths of circuit python. We definitely went there today. If you haven't yet, please do try the absolute latest. Hopefully beta one will be out this weekend. But yeah, let us know if there are any show stopping bugs. Not the minor things that you could live with, but the things that like really prevent it from working. My name is Scott. I go by tan newt online. I work for Adafruit. Adafruit does open source hardware and software. If you want to support me in them. Oh and did you see I have a 9.0 poster here too. You can go to Adafruit.com support them. If you want to join the discord, the chat on the middle over here is the URL, adafru.it slash discord. And yeah, if you're in the US, have a great three day weekend. I will. Oh yeah, and I missed that. Missed the unexpected maker already left. Anyway, thank you all for hanging out. Thanks preemptively for to DCD for the time codes. And I think that's it. I'm going to go take a run and think this over some more. And how to deal with it, but especially because we're seeing this corruption. It's just like, oh, like crashing at that point is really bad. So yeah, I'm going to go think about that. And probably won't PR till next week. We'll see. But maybe all maybe what I'll do is I'll write a comment on this. You'd say like I found this and it's this like big long spaghetti string of things. Anyway, have a great weekend. I'll do a little bit of window cam to end it. At least the sun is up still. And it's not raining. Right.