BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Presentations MakeCode: Types, Games and Machine Code

MakeCode: Types, Games and Machine Code

Bookmarks
40:18

Summary

Michal Moskal talks about the MakeCode platform, an open source platform and accompanying web app for building educational programming for small, cheap embedded devices. He gives some technical details about the STS compiler, and discusses MakeCode Arcade - an editor for retro-style games that run in the browser and on dedicated hardware, and can be programmed easily using modern, high-level APIs.

Bio

Michał Moskal works as a Principal Research Software Development Engineer at Microsoft Research in Redmond on programming languages and related topics. In the past he has worked on software verification (including VCC – a state of the art formal verifier for C programs) and automated theorem proving.

About the conference

Software is changing the world. QCon empowers software development by facilitating the spread of knowledge and innovation in the developer community. A practitioner-driven conference, QCon is designed for technical team leads, architects, engineering directors, and project managers who influence innovation in their teams.

Transcript

Moskal: Hi, my name is Michal Moskal, I'm at Microsoft Research, and we work on this platform called MakeCode. Yes, there's quite a few people behind it, not only me, I'm just giving the talk. Microsoft MakeCode is a platform for building educational programming experiences, so think of it as something like an IDE for kids for programming a specific thing. It's not like a general-purpose - maybe the platform itself is general-purpose, but usually you target it towards a specific experience and usually, we program different hardware devices like this. The main feature from the technical side of it is that it all works everywhere as a web app, so you just need a web browser, which is actually quite unusual when it comes to programming those devices. It's an open-source platform that can be extended by others, so we have several editors that people use and other people can build their own.

The other thing about it is that we try to make the barrier to entry as low as possible. You should be able to get started in a minute, but we also try not to limit what you can do within the platform and I'm going to show that in a second. It's also quite a big project as far as the education initiatives goes. It was first deployed on the BBC micro:bit. It's a new device like this one, and there was 4 million units of that one. It's also fairly cheap, so you can buy and try it for yourself.

Demo: MakeCode for micro:bit

I'm going to show you how it looks like so you get an idea. If you go to makecode.com, you will see a bunch of cards for different editors. This one is for the micro:bit, this device that I was showing you. Most of them are for different hardware devices, including the Lego Mindstorms, including Wonder Robot. This one is for Minecraft so we can also program different agents onto Minecraft. We have a new one called Arcade, which I'm going to show in the second half of the talk, which is for building this retrostyle games that you can then run on hardware devices like this one.

Let's go to the micro:bit. When it comes to the site, what you can see is that those are your projects but actually most of the site is about different tutorials and different projects that you can do with the device. This is essentially for the kids to get started, though, we mostly see usage of MakeCode in the classroom and that's what we optimize for, so there isn't really so much of this self-guided material for someone who's just starting it, we really reliant on the teachers here still.

Ok, so let's start a new project. Now, I'm loading the editor here and what you can see is the primary interface that most of our users use is this block interface where you just snap together with blocks, so let's see how it looks like. We go to this basic category and, for example, we get an icon, we get it up in here. You can see the simulator here on the left already reloaded and run this program. Let's say we take another one and then we change the icon to something else. What will happen now? It will now be animated because this is a loop that will run forever and there is a delay built into the show icon of, I guess, about half a second so that you see them. Yiu can also do it once at the beginning of the program and, of course, then you get the expected result.

The way most of those things are programmed is using events. For example, when I press the A button, I want it to do something. I go to the "Basic" and say I want to show "Hello" on the screen. It runs my program, I press the button, I get Hello. If you're wondering about the resolution of the screen, this is because that's how the device look like. It's HD five by five. Now, buttons are great but actually there are some sensors on this device. This is actually what we found quite important, there are many electronics platforms where you can build stuff but usually, you have to connect a bunch of sensors to get anything running. In classroom, this is really difficult especially with younger kids; the cables are a mess and so forth.

We actually are working mostly with the devices that are much more integrated that have some sensors and some actuators build-in. This one has this screen and it also has a bunch of sensors, including accelerometer, so I can, for example, react for a shake. When I shake it, I want to show a number or whatever. Because I am using the shake block, it's simulating accelerometer with the mouse. If I was on the phone, it would actually used the phone accelerometer but here on the computer, it's simulating it with the mouse so if I shake it, I get zero. If find it hard, we also give you this button for doing the shake but it's just fake.

Now how do we get it on the device. I hit "Download" here and that gives me a file. This file shows here and the micro:bit itself shows up as USB drive, so I just need to drag this file to the device and it's flashing the device. I mean, it's actually flashing LED, which means that it is programming the device. Actually, this dragging the file is usually the most difficult part of the process. I mean, this is easier. We get the heart, we get the other thing. If I press A, we get Hello. Once we get to the end of the Hello, if we shake it, we get zero. Ss I told you, the median time to blink is quite quick here.

The other cool thing about the micro:bit is that it has a radio. That radio can be used for Bluetooth, but we usually don't use Bluetooth because Bluetooth is very difficult to set up in the classroom because you have to do all the pairing and it will pair with your phone or it won't and so forth. Usually, what we use the radio for is for communicating between micro:bits because we have a whole classroom of kids with those devices. What can we do? We go to the "Radio" here and then we say we want to send a number and we take the acceleration on the x-axis and we keep sending that number.

Because I'm using the radio block, I'm getting two micro:bits in my simulator so I can see how it would work. I go to my radio and I get an event when I received a number. Then what I want to do is I would want to plot that number on the screen Now, if I'm moving this micro:bit, it's sending the number to the other one and the other one is plotting it on the screen. Similarly here. We can now drop this file on the device. I don't know what it's doing. Antivirus scanning, I suppose. It's usually fairly immediate. I have another one here. micro:bit comes with the battery, so you can actually see that it works.

I'm going to flash the other one. We're going to flash the same program on it. After a few seconds, I'm moving this one and you see the other one is displaying the numbers. The cool thing about it is that, for example, with this you can do like a remote-control car because you have this connectors here so you can connect different things here. They are so big so you can put these big crocodile clips here. I go to "Advanced," and I find my Servo here. Se have this block called "Map," I want to map the received number, which is in this ranch and then I want to map it 0 to 360. Now, I connected this over here, it's actually showing it to me on the screen. When I moved this one, I would get the little remote-control car.

I was showing you the blocks all the time and this is because that's where most of our users are, but really what happens under the hood is that we have a TypeScript program here, so let me hide that so that you can see it. The TypeScript program corresponds pretty much one-to-one to those blocks. What you can do actually is you can even go to the TypeScript and change it a little bit. There is like a full IntelliSense, this is Monaco Editor that's using JS code. You can go ahead and change it, go back to blocks, and it will update the blocks. If you say something here that is not supported on the block site, then you'll get these grey blocks that you cannot edit.

The idea here is for the users that they can get started with those blocks and they can upgrade themselves to TypeScript. This TypeScript here is labeled JavaScript because teachers have absolutely no idea what TypeScript is, we are lucky if they know what JavaScript is, so it's to keep it simple. Also, when you look at these programs, they actually are JavaScript, there is actually not a single use of Types here. You can use Types but most of those programs are quite simple and the users don't even use Types. This class syntax, for example, that's the same in the new ECMAScript 6.

If you look here on the left, on the, under the full simulators, there's suddenly a file explorer and that lets you look under the hood of the platform. This is again, what I was talking about - the barrier to entry is very low but where you can go is actually quite high. You can go ahead and write all those classes in TypeScript and so forth and you can even go ahead and look how did we implement all of that. Most of the runtime for the micro:bit, actually, you will see it here.

If we go to the core library, for example, you see all the files that we use. For example, we use this showNumber block and here it is implemented, it rounds the number to two digits after the dot, and shows it as a string. Here, there is a bunch of comments that describe how the blocks look like. They describe the color, the shape, and so forth. This is actually how you define the blocks for the users, so it's just define the TypeScript API, if you just say block on them, it will show you some block. It will try to split the API into words and so forth, but you can also go ahead and modify it so that it's more readable for the users.

This simulator is, of course, run in JavaScript so you can even go ahead and look at the JavaScript that we generate from that code. One thing that you note here in this program is that these things, for example, they blocked for half a second but there's no await or anything like that. We essentially adopt a single threaded execution and at the lowest level, the API blocks for a given amount of time that waits for event, it just blocks and during that time, other events can run. Otherwise, you cannot be interrupted, so it's not really like multi-threaded program where we really have to be worried too much about other threads changing your data. It's more well-defined in that sense.

The other thing is that this is an extensible platform where you can add different extensions which are just libraries or packages. We can load a bunch of popular extensions here, and you can go ahead and search for "Robot," and you get different extensions for different robots. Usually those extensions are provided by hardware manufacturers that manufacture different accessories for that thing but they could be arbitrary pieces of code. Let's say that we add one of those, like this gigglebot here. When we add it, we get a new category of blocks here that's what this robot does and we can also look at it here.

If we go back to JavaScript, we can look at other extension here, it's added, it's localized in French. Localization is actually quite important in schools as you can imagine. There is also another package that it depends on, these giggle sensors. When you look at some of those things, you see that these are maybe not the greatest programmers. It doesn't matter, it still works. The most important thing is that they expose this low-level APIs to those blocks in a much higher level way. I think it's so much for the micro:bit demo, let's go back to the talk.

Why Should You Care?

People do different projects with it. It's not just the device but you embed it in a project. That actually makes it much more accessible because this is something that they know how to do, so that you combine the skill that you know how to do like how to build this cardboard robot and put the thing inside and do stuff like that. You combine that skills that you know how to do with the skill that you don't and that makes you feel more empowered at the one that you don't know how to do, which is programming, which is what we really want them to. There are gazillions of projects. For example, down there, it's a step counter and you put it on your leg and it detect the shake event, that's your step counter. It's very simple. People do drones and also stuff like humidity sensors, weather sensors, and whatnot for different science project.

Why should we care? One answer to that is that the IoT is coming for real this time, apparently. Arm expects 1 trillion devices in 15 years, there is now maybe 5 billion of them, maybe 20, it's hard to find the exact data. Someone have to program those things. Nowadays, most of those devices are programmed using C and C++ and there's probably at least 10 times as many web programmers than there are embedded programmers. The other thing is that those MCUs are getting cheaper and cheaper.

People used to use these 8-bit MCU or 4-bit MCUs, but the 32-bit ones that we run on, they are getting cheaper and cheaper. Because of that, the high-level languages are entering this level of embedded programming, so this includes us but also Python using CircuitPython and MicroPython. There's also plain JavaScript interpreters like Espruino, iot.js, and so forth.

Not Convinced?

I know you're not convinced, so who thinks that it's easy to hire a developer today? That's essentially because there isn't enough of them and there are all those boot camps in universities training camp for graduates, not enough. Moreover, in the future many jobs will involve programming, even though those won't be just like straight programmers, they will just do some other things and have some programming on the side.

When you think about it, this is maybe a bit much. This high-level APIs and this high level way of programming where you layer those abstractions, this is how the programming will look more and more like in the future. Think about it, it's much easier to teach people how to put those blocks together. Then it's also quite important to not limit them. You have to let them actually do what they want in the same environment and lay a little abstraction on top of each other. Here, you could see that you could go from those blocks down to TypeScript. I actually going to show it to you but you can even go and look that and edit the C++ files that run on the Runtime C++ files. When you think about it, you have this progression where we program at higher and higher level of abstraction. People started to program with machine code, they were punching the cards, they went to Assembly, then they went to languages like Phyton and C, then they went to C++, then they introduced to Garbage Collection.

That's maybe Java, then you have more of this dynamic programming with JavaScript. Nowadays, you mostly program using even higher level of abstraction, you just go to npm which, whatever, half a million, a million packages, and find the one that you need. If you extrapolate, of course, at some point, you see where this is going. In some of those transitions like between the machine code and Assembly, between C and C++, between JavaScript and npm, you can actually go to the lower level. You don't actually lose any performance because you can always go to the lower level. In some of them, you do lose some.

Here we're talking about this very low floor to start and reasonably high ceiling, so this is actually what my code is about. We pay usually for all those abstractions with some performance but the question is how much do we pay.

Richard's Benchmark

This is a benchmark, it's called the Richard's benchmark, it moves stuff between these and so forth. When you look at these numbers and what they are, this is how much slower than the C implementation of that benchmark. This is on the embedded system, I think on this one. The MicroPython is 300 times slower than C and duktape which is a JavaScript template is 600 times slower than C. That's seems quite a bit slower, how much people are willing to pay?

If you try with node, it's about nine times slower than C on this particular benchmark. It seems that this is how much people are willing to pay because they're using all of this. Static TypeScript, which is the one that we use here is 16 times slower than C, which is actually quite a lot when you think about it, at least I feel like that. The other thing is that MicroPython is actually not so bad because if you run the CPython, it's about 1,000 times slower than C, which is probably why most people don't really use Python for performance-sensitive areas unless, of course, you distribute it off to a GPU, that's different.

It's not always that great. Here, for example, this is a different benchmark where we start to just move stuff in an array. Here, node is only three times slower than C and if you get the benchmark simple enough, you can get node pretty much on the level of C. This one is 3 times slower than C, we have 21 times slower than C, but still, an order of magnitude faster than those interpreters.

Static TypeScript

How do we do it? We cheat a little bit. We don't really run a full-fledged JavaScript engine on that thing because this little device here has 16 kilobytes of RAM and if you also try to run Bluetooth on it, you are left with 3 kilobytes of RAM. You could pretty much forget about a full-fledged JavaScript engine.

What we do is we compile the JavaScript or the TypeScript into machine code directly in the browser. It all runs as a web app and we actually don't go to the cloud to compile, we compile inside of the browser. This is critical, again, in the schools because the internet connection goes up and down, there are limits, and also, if you compile it in the cloud, you have to pay for the cloud and with millions of users, that becomes difficult. What we do is we move eval because we compile and we also don't do prototype inheritance, we start to do classes just like you would do in Java. You just define a class like you can in ECMAScript 6 but in ECMAScript 6, it just translates to prototype inheritance, we actually treat class as a class.

You can still do higher order functions like closures, you may have a Garbage Collector, you may have the "any" type so it's not like we follow some very strict type discipline on this. The control flow is static in the sense that there is no eval and there is no prototype inheritance but there are still visual calls, for example, and interfaces. Data handling is often dynamic, meaning that there is only one number type, and it's the double number type, but usually in those devices, you don't really want to compete with doubles all the time because they have no FPU. If you try to do double addition, that's like 400 cycles, which is a bit slow. It's one [inaudible 00:25:29] machine without an FPU.

What we do is we would use 31-bit integers. If they overflow that, then we go into the box doubles, those are typical optimization techniques used in things like that. Yes, we mostly target this 32-bit ARM Cortex-M microcontrollers with about that much of a RAM. We get decent performance, as you've seen on those slides, we have some more data, and sometimes it's close to V8. It's always slower than V8 but then again, forget about any V8 on that thing. We are always much faster than the interpreters that are usually used for those things on the platforms. It's an open source compiler and assembler, all implemented in TypeScript and it's all runs inside of that web app.

TypeScript here was actually really critical to get all of that project running because this is quite a complex web app. That actually is what allowed us to build a complex application, including the compiler, including all of that, but also including all the UI and then we could also pull in the components like the Monaco Editor, which is also written in TypeScript. This is really something that enables this static typing, and this ability to refactor is something that makes it possible.

We do have a custom runtime. As I said, it's more Java-like classes, not the prototype inheritance, I was talking about that already. We do support UTF-8 because many of the companies that make those things are Chinese and they actually quite interested in UTF-8 or Unicode.

Does Performance Matter?

Does performance actually matter on those things? Well, eventually. When you look at these programs that I was showing in the micro:bit, it doesn't really matter how fast it blinks, it's fast enough. Given enough time and enough users, you will eventually find someone who hit against those limits that you have there and they're actually a power user and they will complain loudly.

Moreover, if you think about IoT devices, most of the time, those devices sleep and then they wake up and they do something. The periods in which they wake up is what the time is your power usage, your energy usage. Actually, the performance matter for that as well, the performance is really the battery usage in that case. For micro:bit in particular, the memory consumption matters because you have very little of memory, the speed not so much. In some places, the faster is the better and then this is why I show you the gaming thing.

Arcade

I think this is the coolest feature that we ever made. It's here, it's called Arcade. Arcade is this system for writing these games that are retro-looking. They use hardware specs of that thing, so this is 160 by 120 pixel screen - again, really HD compared to the micro:bit. We let you do 16 colors but we let you change the palette. The screen is really capable of like 80-bit color or something but we don't have much memory, so we limit it to 16 colors and it also gives the games this old school look. Here you can see different tutorials, different example games, little performers, little shooters, and so forth.

Let me just show you quickly how we write those games. You can go ahead and create a little sprite here. Kids love doing the sprites. You can also go ahead and find one from the gallery, let's take the beautiful duck, but then you can also modify it and put makeup on the duck. Again, we can save that. You get a little duck here and then the other thing that we can do is, for example, set the acceleration in the y to 100 and that should have the duck fall down. The basic programming model is the same, it's event-based, so we get the event when we press the button. Let's take our sprite and we set the velocity in the y to minus 100. Now I can have the duck fly. Then you have the things that come under it and then eventually, you end up with a game like that. All within blocks.

When you look at the actual code of this thing, it's about 60 lines and most of it deals with the duck flapping its wings. It's actually not critical for the game so you can actually get that game run in 20 lines of code. Again, very high level, but if you want to, you can go all the way down to the pixel level and change the particular pixels.

You can actually go and do something quite evolved. This is JavaScript, no blocks anymore. You get a little Wolfenstein game and it runs on the hardware as well. Actually, on this one, 27 FPS. I know because this is the version that really does every single pixel in TypeScript, then I added a new API to draw a line of pixels and scale it and that makes it run on 14 frames per second. Here, when you think about those games, the performance actually matters. If you now try to run them 10 times slower, the 14 FPS becomes 4 FPS and it's not fun anymore. That's an example where it actually matters.

If I hit download here, it shows me the different hardware devices that are supported. All of those things that you see here, you can buy. They are between $25 and $50. They can be cheaper but no one had came up with the cheaper ones. The microcontroller that we used to run that thing is about $2, so just this board is probably maybe $5 to produce and so it means that it should be $15-$20 to sell. Again, cost matters for the schools. If you buy one, you're going to be ok. If you buy 500, different story.

You can select the hardware that you want and you also can run it on the Raspberry Pi and you can build the controller and connect it to a TV and this is pretty cool, again, for a classroom for a demo.

We can download this one and it's the same process as before. The device shows as a USB drive and you drag the file and it just runs it. What I actually wanted to show you is that you can even go here and look at the generated assembly code if you really wanted to. This is how long we let you go. The game library here is actually quite a bit more complicated than the micro:bit library. You can see that there is like a bunch of classes, so these are different pixels that fly on the screen. There are different classes that we actually use quite a bit more of the language here than we did in the micro:bit.

Micro:bit has a very simple library and most of the programs are simple. The good thing about the games is that they let you go and come in deep in some sense, because in the micro:bit, most of the programs are five lines long and they either that simple or they're quite complicated where you do these radio protocols, mesh protocols, and whatnot and there isn't much in between. With games, you can actually go very gradually up and up with the complexity.

Takeaways

The Internet of Things is coming more and more and it will be programmed in high-level languages for the most part because that's where the programmers are. This actually has been the trend with all the programming that we did, that it went higher and higher level. This will actually happen for all the programming environments in the future, they will become more and more higher level. We have to make it easy for people to program because otherwise, there won't be enough people to program. Performance matters eventually. Static tapes are good for you, they let you compile programs for these devices, they let you build application and so forth.

Questions and Answers

Participant 1: You showed the radio with them communicating. Do they have any ID? You mentioned radio mesh, can you connect them through Java and stuff like that?

Moskal: Yes. It's a very low-level radio protocol, it's a broadcast protocol. The devices themselves have MAC address, so you can use that for an ID.

Participant 1: A follow up on that – is there a gateway or something that you could connect to a computer and then do MQTT or something to the cloud?

Moskal: Yes, it has been done.

Participant 2: Is there a standard protocol for the manufacturers to follow? These devices, do just one company make it or multiple companies?

Moskal: There are multiple companies making those things. In the past we mostly work for an existing device like the micro:bit and then we build the editor for it and so forth. With Arcade, we have a hardware specification that tells you what you're supposed to do. There are different sources of MCUs that you can use and so forth and we've actually seen all those companies, they just come to us and they tell us, "We build this device," and then we ask them to send us one or two so we can test them and then provided that they can sell them, we can put it up on the website. It's fairly generic, we don't have to add it for it to work on your device, we have a way of specifying the actual hardware configuration inside of the hardware so that we auto-detect that thing and so forth.

Participant 3: Does the IDE ever warn you about performance or warn you about RAM is about to be used up?

Moskal: I recently added memory tracing because we compile everything, so we have the full visibility over all the Garbage Collector roots, so we can actually trace all the objects that you have alive and we can show you the amount of objects. It's not really exposed, especially to kids, not yet. We are working on it. The speed of the MCU doesn't seem to be a problem so much but the memory actually is, so people often run into issues when they run programs on high level and they run out of memory. The browser has infinite memory compared to those things. We're working on it, not quite there yet.

 

See more presentations with transcripts

 

Recorded at:

Feb 27, 2020

BT