 All right, so I think I'm gonna get started. It's 11.30, a few people might end up walking in, but that's all right. So I just wanna introduce myself to everybody. I'm Sterling. I'll be giving this talk with Will, who wrote the Nimble Controller. So we're both developers on the Apache Minute project, which is an open source operating system for MCUs. And I'll give a little bit of context on Minute here, but just by way of my background. So I'm CTO and a co-founder of a company called Runtime. And what Runtime's mission is, is to develop open source software for embedded microcontrollers. So not just Cortex-Ms, but think processors like Cortex-Ms, which traditionally haven't had operating systems or really a lot of good quality open source software that companies can adopt. Runtime was kind of founded to modernize development for the Cortex-M style of processor. So that includes MIPS and RISC-5 and a number of other architectures. And we started a project in the Apache Software Foundation called Apache Minute. Prior to working at Runtime, I worked at a company called SilverSpring Networks, which did large scale wireless mesh networking. So we networked power meters and street lights and distribution automation controllers. And we developed a completely proprietary networking stack that was layer one through layer seven on what was originally AVR at Mega Processor. So at Mega 128, we fit an IPv6 stack on there and then grew to be ARM7s and eventually Cortex-Ms. And what we found is, and kind of the background on Apache Minute, what we found was that every single company was building their own operating system. And so we started Apache Minute within the Apache Software Foundation to help address that. Since then we've also become members of the Zephyr project. So we're silver members on Zephyr. We're collaborating on LWIP and a number of other open source projects. So our vision and our goal in the space is really to get good quality open source software that companies can use and adopt. But, so this talk is on the Bluetooth stack within the Apache Minute operating system. Apache Minute is Apache Software Foundation project, which means it's not run or controlled in any way by Runtime, but rather it's a community-driven open source project. And the way that works is it's not corporations who control the direction of the project but it's individuals. So it's the people who commit code, who elect other committers, and then the project itself is run within the Apache Software Foundation, which is a 501C3 charity. And so there's really no corporate control, control is given to the individuals. And we decided that this was the right place to develop an operating system effort because what we saw in too many cases is you'd either have something like FreeRTOS which was owned by an individual company and licensed GPL or dual licensed, which made it really hard to build a large ecosystem around it. Or you would have other projects that were just a little too GPL'd for the space. So Riot would be an example of that where it was hard to adopt it into products because in the kind of sub-linux world, everything gets linked into a shared binary. So your application and your proprietary software would have to be GPL'd if it relied on efforts in the space. So Apache Minute was started about a year and a half ago and the idea is a completely open source operating system for these Cortex M devices. It's a real time operating system but it's more than what you would think of as a traditional operating system which is just the core of the RTOS. The idea is to give a Linux style effort for these Cortex M systems. So at the very base level, there's a secure bootloader and flash file systems and flash access mechanisms. There's a real time OS and a hardware abstraction layer. There's driver infrastructure and power management. There's a whole bunch of debugging data there and then kind of most remain to this talk, there's a completely open source Bluetooth stack in there called Nimble. And Nimble is both an open source controller that works on the Nordic NRF 51 and the Nordic NRF 52 as well as a completely open source Bluetooth host stack. And that's built directly into the operating system itself. So this talk is primarily focused upon Nimble but it's within the context of the Apache Minute project which is really designed to basically have completely open source software for Cortex M style microcontrollers. So why an open source Bluetooth stack? This was actually surprisingly one of the most common question we got when we started developing Nimble. And it was primarily asked to us by chip vendors but pretty much everybody in the space was like, well, you already have stacks from the various chip vendors themselves. So Nordic has a soft device which is stable and tested and everybody uses. So they wondered why an open source Bluetooth stack? Other vendors similarly buy stacks from companies like Mindtree and they license those stacks with commercial support. And so the big question we got was kind of why do your own stack when there's already a Bluetooth stack out there? And there's kind of a couple of reasons that we thought of doing it. One is in a lot of cases people who develop software for these Cortex M microcontrollers they don't actually have access to the source. So you're developing your Bluetooth application on a Nordic processor and you have no visibility into what's actually happening when you use the soft device. You have no source code for it. In addition to that we were working on a project it was a customer who was looking to use Minute was looking to use an RTOS and they were trying to figure out what the problems were using the soft device and the CPU would just mysteriously disappear because you have the Bluetooth stack is the highest priority thing running on that chip. And so if you're running your real-time operating system or you're running your application suddenly you lose the CPU. Now is that causing a bug in your system? Maybe, probably not but you're constantly wondering what's happening on the chip and that's really a artifact of the fact that if you look at kind of the early series of Nordic processors they were designed more as controllers or more as very simple application processors they weren't really designed to write complex applications on them so the NRF 51 has a Cortex M0 microcontroller M0 plus microcontroller on it and it has 128K of flash and 16K of RAM. Maybe you were blinking an LED or controlling a very simple motor but what you've seen over time is that as the kind of the process sizes for these chips have gone down they've been able to bundle in more complex processors and more RAM and flash into the chip itself. So the current generation of the NRF series has 512K of flash and 64K of RAM which for the Linux people here is like nothing but for us is more than you could ever need. And then if you look at Nordic's next generation processor it's about a mega flash and 256K of RAM and you're starting to see the chips in this space get to that kind of mega flash, 256K of RAM space and now you have a fairly complex application that you're developing within that footprint but you actually still have no access to the highest priority thing on the chip which is the Bluetooth stack that's running. So it's very hard to debug these stacks and that was one of the major reasons we decided to write an open source one. But then it also, what we found is it also became a real benefit to have a more flexible architecture. If you look at people who are developing these applications and you look as an example for the soft device, the challenge that people who are developing the soft device have is because they're shipping you a pre-compiled binary without source code access, they have to compile it for 90% of their users, right? So everybody who is using the Nordic platform or any of these platforms whether it be the KW41Z or another platform like that, they have a support issue which is they need to compile one binary that works for 90% of their users and so the 10% of their users it doesn't work for are kind of stranded and without luck and in addition, it kind of restricts what you can do with the stack. So as an example, Bluetooth 4.2 is something that our customers sometimes wanna run on NRF 51s. They wanna be able to compile out certain features but add other features so they might wanna run with data length extension but not with security. If you have an open source stack and it's configurable, it gives you the flexibility to choose what you wanna put in there. The other side of that, so we can get really small and we'll show you some of the code size numbers that we've gotten on the NRF series but the converse of that is also performance. So we support 32 simultaneous connections in our Bluetooth stack and the reason that a lot of proprietary stacks don't support that is not because they don't have the CPU or processing or ability to write that software but because it takes a lot of RAM. So people who often do applications like real-time location services where you're a lock or a light where you wanna track people or a lock where you wanna see where people are, it helps to have a lot of connections because you can constantly be connecting to people, seeing how far they are and tracking them in a place before you decide to open a door. So having that flexibility to either compile down to really, really small software sizes where you don't want certain features or increase the RAM and increase the code for more complex use cases is another big reason. And then finally, it just ends up being a more efficient process when it's open, right? We can have a unified buffering scheme, for example, across IP, today if you were to run an IP stack, there would have to be copies in and out of the Bluetooth stack itself whereas if you have it all open, you can have a unified buffering scheme that you manage and you can have zero copy from the controller all the way through your application. So it ends up being less wasteful. And then the last thing and this is one that's starting to become more of a big deal now that we're starting to add more platform support is that you can migrate your application across processors without having to retest and recertify the entire thing. So today, if you're using a Bluetooth chip from Nordic and you want to eventually switch to NXP's chip, for example, you would have to use a completely different Bluetooth stack on NXP than you would use on Nordic and you would have to completely retest your application when you make the switch between chip sets. If there are bugs that you've worked around on the Nordic chip, you would have to work around different bugs on the NXP chip and so it becomes very hard to switch between chip sets and choose the right chip set for you based upon power, performance, and price. And so by having an open source Bluetooth stack that works across platforms, it allows you to migrate between chip sets without having a massive software porting effort. So that's one of the reasons. So some of the highlights of Nimble. So it's a fully Bluetooth 4.2 compliant. We is runtime, show up and unplug Fests. We test with all of the other vendors. We've run PTS across the entire host and it passes all of the PTS suites in the next month or two where we'll be going for certification on the stack but it fully complies with PTS. It has a constrained footprint so we'll give you a bit more of the sizing numbers but on the NRF 51, we're able to fit the entire Bluetooth stack into about 80 K of code. As a comparison, the Nordic stack is 108 K of code. So it gives you a significant amount of code back. It's high performance. So when it comes to throughput numbers and throughput were 5x faster than Nordic in some cases. In addition to that, we support about 10x the number of connections from the Bluetooth. You have all the source, as I mentioned. We support low power operation mode. So it ties within our minute RTOS, has the concept of a low power mode and system states. The Bluetooth stack actually ties into those system states and there's now been a little bit more work to actually leverage low power timers on the Nordic chip and things like that. It's configurable. There's lots of different options that we've added to the stack that are all changeable through our system configuration interface. And then finally, it's debuggable. And by debuggable, A, you have the source, which is really the ultimate in terms of being able to debug things. But also, a large part of the effort that we've put into minute is to make things very easy when you have a device in the field to understand what's going on. And that was based on our experience at Silver Spring where we had to manage 22, 23 million devices. So everything in minute has a unified logging infrastructure that can go out to the console when you're debugging things, but that you can either write to multiple flash buffers or multiple RAM buffers when you go to production, you can control what gets logged on a module basis or on a level basis. And all of that is remotely accessible. Either you can pull that back over Bluetooth or any of the transports we support. There are also extensive statistics that we keep on the operation of a system. And we support core dumps within minute. So when things crash, we actually write those to flash and you can pull those back, which are not things that you have with any of the existing proprietary stacks. So there's really been a lot of effort put into making the minute stack very easy to debug and easy to debug remotely. One of the biggest things we hear from customers is I'm out in the field and an Android doesn't seem to work with this or even worse than that. In a lot of cases, it's not just Android, but it's a specific version of Android that's tied to a specific controller. So how do you understand what type of devices you're interacting with, what type of errors you're seeing in the field and how do you bring that back remotely? A lot of that effort has been put into Nimble. So I'm gonna let Will get up here. Will has been built the controller for our Bluetooth stack and has been one of the core developers of the Bluetooth stack. He's gonna talk a little bit more about the layout of the stack, the source code layout. I'll give you some examples on the details of it. So I'll hand it off to Will. You'll have to excuse me a bit. I think my voice is a bit out from talking at the booth a lot. So let's get over to the next slide. So a little background on myself. My name is Will. So I worked with Sterling at Silver Spring Networks and before that at a company called Metricom. We did sort of like the Ricochet wireless data network. So I pretty much spent most of all my time doing wireless frequency hopping MAC protocols and embedded firmware. So the Bluetooth stack was a good fit. So what we are not showing a lot of or talking about here is the package management tool called Newt that allows you to see a lot of configuration options that you choose, choose what build packages you want for your application. We'll talk a little bit about some of the sample apps that we have that do some things that folks can use as examples to do their own applications. So the basic layout of this and if you go to the source code and download it you can see the directory structure. We build a host only, controller only and a combined controller host. The way you sort of glue the two together are the transport layer and the Uarts and HCI transport layer and the RAM one is the combined host controller transport layer. And yeah, so the code's located if you go, it's all in a network directory. So we go to net nimble host, you'll find the host source code. We have services separated out in a underlying directory under there. And these are all packages, which is a good thing. So let's say you don't want to do, let's go back to, that was gonna happen. Let's go full screen, I don't know. Okay, it's good, okay, good. So you can choose what packages you want in the build like Sterling said, it's highly configurable. So if you want certain services, you can bring them in. If you don't, you don't have to include them. To the next slide here. So what we're showing here is sort of a sample configuration file. These are all in these files called sysconfig.yaml files and they're package based. So when you go to a certain package and you'll see there's like a package.yaml file which describes things about the package. You'll see this file in the directory as well. And you can go in there and it's text based. It's pretty easy to go in there and modify and see what configuration options that you want to include. And obviously these are all for saving code and RAM. And if you only want your device to be a peripheral, you'd choose peripheral. If you don't want it to, if you want it to be a central and peripheral, you would define both and that code gets included. And the package management tool also allows you to pretty easily view the configuration settings for your build. I don't have any examples of that, but it's a simple command line tool that you can use to display all. It's pretty, very easy to use. And after using make files for most of my life, this package management tool is actually really cool. I like it much better. And I guess, yeah, so some of the options here, if you only want a connection, you can choose one. I showed 16 here, but you can go up to pretty much, it's configurable. So if you have a lot of RAM, you can go to more than 32. So you just have to set it up and see what's right here. And yeah, and multiple roles can be supported simultaneously. We'll go a little bit more into that, but you can be a central and a peripheral at the same time and have multiple connections for each type. So this is a little bit about the code size for various features in the OS. So the boot loader is, there we have a secure boot loader, which is around 12K. And these are pretty much based on the Nordic platforms. You don't get too much different with others. The core RTOS is really small, it's about seven K bytes. So the controller base is around 20. And if you were to go to the controller package and look at the configuration options, you can choose things. If you look at 4.2 features, let's say you don't want data length extension, you would take that out and your code base will get smaller. There's encryption privacy. All the features are separately configurable through this file and you can decide which ones you want. We definitely still have a little bit more work to make it a little bit better. If you were to choose central and peripheral, not everything gets compiled out and we're gonna be working a little bit more on that. So we'll be able to better these numbers in not too far just in the future. The host base is not that much more. Actually the host can get quite large, like when we say the complete host that contains a whole bunch of debugging, statistics, logging, a lot of extra code to make it sort of like really easily testable. And we'll talk a little bit about the application that we have for that. So it's a, yeah, PTS testing was done with this app. It's a nice little command line tool that you can do quite a bunch of the Bluetooth stuff with. And I think when it all adds up, you can fit this anywhere like Sterling said, even 70 to 130, 140K. So for most processors these days, that's good. For some of the smaller ones, it's a little bit tricky, but a lot of times it's RAM. That's what you really have to optimize for. And we still have a little bit of work I'd say to do to optimize the connections for if you're doing just central or peripherals, but we feel pretty good about the total RAM usage for the stack. So supported platforms. So the host can run on a number of the different processors that we support. We plan to add a lot more processor support as we go along. And hopefully that's why we also have a community and anybody who wants to add process support, it'll be great. We love people contributing to the project and we have a few of them, like some of the major ones. And an upcoming one is gonna be some of the NXP chips, which we're gonna port the controller to. And the host pretty much just ports. That's pretty non-platform specific code. And yeah, so we have mentioned here for the controller, it's the NRI 51 and 52. We've also been playing around with their new chip, the 52840. So we have the stuff basically up and running there, but there's a number of features that processor that we'll start adding to as we go along. And the NXP KEW41Z is a work in progress. And we plan to add more as time goes on, but we'll see which ones get picked. And again, people who wanna add stuff to the community were totally psyched about that, so. So this is a little bit more about the controller specifics themselves. So this is, you know, most of my effort in the project has been doing the controller. And so we have, like I said, it is the only HCI interface we have currently is the UART one. We're planning to add some USB support upcoming, so there'll be a USB-based one fairly soon. And you could also run it combined with the Nimbl host. It supports all the 4.2 features. And I don't think there's anything that's not there. And if you wanna go a little bit more into how the code is sort of laid out and what we've done, so basically we have the basis of myNUDE is an RTOS, multitasking, preemptive, task base. You get to write your own tasks, choose priorities. Generally we want the link layer task to be the highest priority. You could not do that, but I don't know if I would suggest that. But it gives you the option to do that. And sort of the host and application use a task and the link layer uses a task. So in its smallest form, there's really only two tasks in the system. And for those of you who use to do this stuff, that stack, test, stacks can take quite a bit of RAM. So it's up to you, you can have other application tasks doing things if that's what you want, but we try to really make it so that, when it's very basic form, we're only using a couple of the OS tasks. As far as state machines go, we do have multi-advertising. So you can, there's a configuration option. You can choose how many advertising state machines that you want. There's only currently one scanning or initiating state machine. We may add to that as time goes on. And certainly we have multiple simultaneous connections. So you can configure the device to sort of try to tune it for your application. Do you want something that does a lot of connections very quickly and not a lot of data? Do you wanna just run one or two connections and you wanna push a lot of throughput through them? The scheduler is sort of configurable in a way and how you sort of allocate the base amount of time that gets scheduled for connections. And what you're trying to do is try to determine like how many connections I think I want, how much time do I wanna allocate them and you configure the system and hopefully it'll sort of optimize for your scenario. And it's a, the scheduler does sort of use this loose time slot-based approach. It's not, there's not fixed time slots for let's say advertising scanning connections. And there's a reason why we went about doing this. We think it's a little bit more flexible. You can have overlapping connection events because sometimes you really, if you're the peripheral you don't really get to decide. When you're gonna be scheduled for connection events. So in that case, what it'll do is it'll use a least recently use approach and it'll just round rob in the connections and hopefully pick the one that's not gonna time out on your supervision time out sooner. And it also uses a sort of, we took a sort of priority approach to it and if any, this is something that you wanted to change you could go in and change it but connections take priority over advertising events and over scanning events. And so, what obviously the schedule tries to do is tries to put advertising events where connection events are not and tries to move connection events so that if you're trying to do many of these it tries to schedule them all in such a way that all can work. And if they can't, one takes priority and the other one just gets round robbing in later. I think I've covered most of that stuff there. So now we're gonna move on to the host. So like I had said before the host and application share a task and you can split these up into many tasks as you want. Generally most applications probably don't need their own tasks to run it but if they do, you know, you can do that. And if you went in, so we don't have an example of this but it's a pretty simple approach. Basically the host uses this table-based approach to define services. And if you look at this service table, what you'll see is there's an easy way to define characteristics and descriptors. You have a user-defined callback if you want for every single, you know, each characteristic descriptor or service can have its own individual callbacks. You can wrap them all into one, deal with them that way. So you have a lot of flexibility there. And now GAP procedures are, there's a set of API to do most of the GAP procedures and I think this is common through most Bluetooth stacks. You know, we just chose a set and you can see a couple of the examples there. And again, with most of these, you have callbacks that you can, you know, your application can do what you want. If you sort of look, it's pretty easy to see, the VLE GAP event function callback and argument. We have a set of defined events for these things. So you register your function. You know, the function gets called with the various events and contexts, you know, for the attributes and the services you write your code to, you know, based on what you want to do for the reads and writes for that. It's pretty simple. And if you look at the examples, we do have a fair amount of examples to go through so you can look at the code, see the examples and it should be really pretty quick to get an application up and running if you're familiar with the spec. So I guess, yeah, and you know, we support most of the features, you know, pairing, bonding, you know, we have persistence of the information so that you can bond. And, you know, it can always go to the documentation. There's a fair amount of documentation on the API and you can look and it describes it and it's pretty easy to use. So yeah, we have documentation. You could go check that out on the website. And, you know, we have a community and it's the Apache Minute community. And we're, you know, people are, I would say, extremely responsive. This is my first open source project. So I don't have a lot of familiarity with these things but, you know, there's really good support. So you can go there, ask questions. It's usually answered pretty quickly and thoroughly. And, you know, we love committers. We love people, you know, contributing to the project. So, you know, it's definitely something we're looking for. And you can also contact Runtime about consulting and commercial support for the OS and the stack. So, you know, we're available for that. And then, you know, if you go into the apps directory and it's pretty easy to see, you'll go through the tree and we have a sort of basic set of apps. You know, BLE perf is a peripheral. So it shows how to stand up a peripheral and do some basic services with it. BLE Tiny is now somewhat of a misnomer. It's not so tiny but it's sort of like a really good sort of command line test tool to test all aspects of the Bluetooth stack. So you can set up connections, advertise through its scan. And it's a pretty powerful command line tool to do a lot of testing and debugging with. You know, to sort of get yourself familiar with the stack and the code. BLE Cent is a central. So it gives a good example of a central. And BLE HCI is the controller only HCI. So, you know, we've run it with, you know, Bluezy. It's great. You know, stick it on there. You know, you can use that as your controller to do testing with. And I think that's pretty much most of the presentation. Do you have any questions about the community, the stack or anything about runtime? Are you happy to, you know, answer them? Yeah, so I'm sorry about that. Yeah, so Newt is a build and package management tool. So it actually bundled, it's the build system we use with our OS and project. There is the ability to run Newt. So we're all, I mean, I think Will is, uses SlickEdit. The rest of us are Vi and Emacs for the most part. So Newt does actually build in, so for example, for every board and processor that we support, we include the debug scripts for download and debug and run and programming. So anybody who writes a BSP makes sure that they actually bring up Jlink or OpenOCD or any of those things. One of the things you can do is you can take Eclipse and there's a blog post that a company called CodeCoop wrote on this, we can send it out. And you can fire up Newt and then use it as a GDB remote. And then you can debug with an Eclipse and you can call out to the build system with Eclipse. So there's a whole set of instructions for configuring it on Eclipse. Actually, one of the nice things that we didn't really realize going into it about this approach is that often you have teams where some people use Eclipse, some people use Visual Studio, some other people use just VI and Emacs, and having been the guy who uses VI all the time, the problem you often get is that the make system is some Eclipse studio mess. And so the nice thing about having Newt build in package management and debug is that it works for people who use Eclipse, but there's also a very nice command line interface for people who are just VI and Emacs users, which is me. Yeah, the talk was mainly about the new tools, like a big part of what we're doing. You're in like a lot of people. There's a talk at 2 p.m. tomorrow on Newt. So if you want to come learn more. So yeah, that's a great question. We can always get better and we know we need to get better, especially as an open source project. But some pointers that I'd give you is the minute documentation. So that there has a tutorial on building a sample BLE application and it's a very basic one. There's also an example on how to hook in an air quality sensor and make the results of that CO2 sensor actually make the results of that CO2 sensor available as a BLE peripheral. So you actually go through the process of there's an iOS app along with it. All of that is in the core minute documentation itself. So there are some tutorials and then a bunch of detail in the documentation itself. And then there are, the sample apps are a really good way of getting that up and running as well. So BLE sent and BLE Perif and they work together. So you can, one of them starts up as a central, the other starts up as a peripheral. I don't know, Will, if you want to. I think also, I think something to add with, we wanted to get to the basics and we'll start adding a lot of profiles to the system. And so if you just want to use standard profile, don't want to do anything tricky, that will all be just right there for you. I mean, right now we have, I think there's only one or two profiles that we've added, but that's something we plan to start adding quite a bit more. So I think that would address a lot of concern. It just does it right out the box. You don't have to worry about anything unless you want to do something different. That's absolutely fantastic what you're doing and you just don't find coming in, you know, at the top and parachuting in. You know, what do I have to learn about? Even though it seems kind of crazy. Yep, no. I'm completely unfamiliar with Bluetooth when we, I think we were both unfamiliar with Bluetooth when we started and it's its own world, right? Like, Will had written wireless Macs for like 20 years and then you got a Bluetooth and it's not IP and it has all of its own terms and there's like a whole set of profiles that nobody who's developing connected products actually really even uses. It's mostly for keyboard guys and headphone guys. So there's really a, it's definitely a learning curve coming to it. So I totally agree. Well, so they have their own controller that was actually, the long story on that is that was actually contributed by Nordic slightly after we wrote our controller. But we also can interface with the Zephyr. So Zephyr has its own host stack that was developed by Johan right there. And he'll talk about it tomorrow. Zephyr can work with either the Nimble controller or the one contributed by Nordic. The one by Nordic is Nordic only, whereas we are moving to support the KW41Z from NXP as well. Yeah, I have a radio abstraction there. Yeah. The other thing you do is support the other radio. Yeah. Yeah, yeah. And the question is like more, yeah. Yeah, I mean, you know, from our perspective I think more open source options are good. We like Zephyr, so this is more of a runtime perspective. I can't speak for minute because we're runtime and we're involved in both Zephyr and in minute. So from our perspective, like, you know, the great thing about having a bunch of open source code is we can go look at it and steal it and vice versa. So for example, in my new, I don't know how much Zephyr has taken from us, but we certainly, a lot of the security manager, we took the implementation and the code, you know, we attribute Zephyr, it's pretty much all there from Zephyr, right? And if you look at the controller stuff, I'm not sure there's a lot of code sharing there. We like having our Bluetooth stack for a number of reasons within the My Newt project. One is we have a fair amount of customer usage on our stack. And so as runtime, you know, we came out with My Newt and it was a little bit, I'd say earlier, especially on the controller side than the Zephyr support came in. And so a number of customers have actually deployed this in production and we have a whole set of unit tests for that and a whole set of use cases that customers are using it on. So I think, you know, what you're gonna see in this space is going to be a lot of projects that hopefully over time will collaborate and hopefully coalesce. But it's actually compared to where it was, because I've been, you know, in embedded microcontrollers and then maybe that's caused brain damage for over 10 years. And everything was proprietary and if you wanted to do something, you had to do it yourself. So we, for example, at Silver Spring, we bought an IP stack. We spent probably two to three years of engineering effort on that IP stack and really, really good engineers that has never seen the light of day, right? And it's implementing things like IPsec, which are completely commodity, but we had to implement, you know, ICV2 and all of these things that were code that we just had that we try to upstream with a proprietary stack vendor that we worked with that was just actually absolutely a nightmare. So from a user perspective, I mean, I encourage you to download them, compare a number of connections, compare power usage, compare throughput, RAM and code sizes, all of those things that really, I think, go into your decision as well as community and all of those things. But in general, I think having a lot of open source code out there and it's all Apache licensed that we can share and collaborate on is actually a fairly good thing. We are actually working to break it out of minute and making it more useful for other people. So we've been working with other, we can't really say too much, but we essentially designed a build and package management system into minute. The problem is when you're kind of developing an operating system, it's really hard to change your OS APIs and have the separate Bluetooth stack that's constantly being developed and having to evolve those two at the same time is actually a fairly painful effort, especially for a small team, which we were. But the goal with Nimble is actually to eventually break it out of minute and have all of the operating systems in the space be able to use it. So that is certainly something that's been designed into minute itself. There's actually a talk tomorrow on something called MCU boot, which is one of the first things we've broken out of the minute operating system and it's a secure bootloader that works across both Zephyr and minute. So that's an example of where we are taking a component that's in minute and looking to share it. It's a little bit trickier on the Bluetooth stack side because Zephyr has one and we have one and we have customers on ours and so we need to support it and those type of things. So there it's more of a sharing in code access, but we certainly are looking to break Nimble out and make it cross OS. We think more sharing is better. Any other questions? All right, thank you very much. Feel free to come up to us. And. Thank you.