 Otherwise, Rick is going to talk to you about how with very limited means, some of you may know Shenzhen I.O., that's where this comes from, an assembly variant that he built in hardware, using very little money to create a very cool thing that children and young people can use to learn assembler language. It's supposed to be a lot of fun. I don't remember being assembler being so much fun, but anyhow, here we go. Rick, your state. Hi, this is my talk, Shenzhen I.O. in real life, where I would like to introduce my product, the MC5000 DevKit, that is an electronic puzzle game consisting of a application and a circuit board. And the task is to solve simple language, a simple task using an assembler language. About me, I've been tinkering for about 15 years in make spaces and outside of them on various projects. These are some of the things I built in the last few years. Now, regarding the current project, I came to the idea of playing the game Shenzhen I.O. from 2016. And in this game, you are an electronic engineer that newly arrived in Shenzhen in China and works on hardware. And you receive tasks by email, built a use of a security camera with two blinking LEDs. And in the game, you have a CAT CAD program, which you use to design a microcontroller and other components or put them onto the working workspace. You connect them to lines and use a pseudo assembler language to write a microcontroller to solve those tasks. And you then have a simulator that you run. And you can check whether you've actually fulfilled the requirements and then you've passed your task. And you pass on the whole documentation is completely put down in data sheets, as you find them with electronic components. And the further levels have data sheets that are in Chinese sometimes, for some components, so that you have to find out by yourself what they actually do or how you use them. There are two types of microcontrollers in the game. There is the MC 4000 and the MC 6000. They differ in the number of lines of code. The 4000 takes nine lines. And the 6000 takes 14 lines, five more. And it also has a one register more and two pins more. There are two types of pins that the controllers have. There are simple IO pins and X bus pins. Simple IO are analog ports or like analog ports. You have a value from zero to 100, as you can set there. And that corresponds to the signal level that you generate or receive or generate and send out. You can set these and query these at any time. Let's find out what's happening at the pin at the time. Then the X bus pins are more like a serial bus. You can set values from minus 999 to plus 999 there. But on the other side, a device has to be present that will take the data you send. If there isn't one such device, there are the code blocks at the point where you want to set the value until the value has been accepted on the other side. The assembler language is fairly simple. There are 15 instructions only. And I can run simple mathematical calculations with the accumulator. And simple queries is A larger than B or something like that are possible tests. So in hardware, I rebuilt this by taking a USB serial interface or creating one for programming. I built a firmware, a very cheap Chinese controller, the Padoc PFS 173. And I have two of those here. These are my so-called MC5000 controllers, which I can program through the serial interface and have a few input and output peripherals there on the circuit board. These are connected through CPUs through simple jumper wires. So that gives you the connections that GenGen.io has in its program. The objective here is to build the circuit board as cheaply as possible. It can be bought readily equipped at a Chinese maker. If you order 50 pieces, it's 650 euros, 6.5 euros per piece, including shipping. The app is written in QT5, cross-compiled for Windows, Mac OS and Linux. It doesn't have to be installed and is pre-packed for every platform. So you can just download and run it. And I'll now show you how the whole thing works. This is the DevKit circuit board. Here are the two microcontrollers, the MC1 and MC2, both type MC5000, and they both have four IO pins to signal IO, P0 and P1, and X plus X1 and X1, X0 and X1. And then you have the output peripherals, the display is the three-digit seven-segment LED display. That's an X bus peripheral. The buzzer that can play sounds again X bus. Then you have three simple IO outputs, the red and green and yellow LED. And as inputs, I have two buttons, one temperature sensor and a light sensor. Now this is the desktop application. I have two editors here, two Windows, in which I can write the code for the two microcontrollers. I can use these buttons to save the code in a file or open it from a file. There is a link here to the manual on GitHub, and the upload button saves the code on the microcontrollers. Down here you have a display for the registers. They are always initialized with zero at the start of the program, and when a program is running, these are updated four times a second, and the red area here shows you that there is no program on the microcontrollers at this time. If there is a program uploaded, then this turns to green. Now I can enter assembly instructions here, such as the move instruction. So let's say move 42 to the dot register. I'll upload that. The square turns green, and you have the value 42 here. And in the same way, I can write something into the ACC register, and you see that the 23 has arrived. The whole thing, of course, the same thing, of course, works on the other microcontroller. So that has been seated with values now again. And if I delete these and press upload, then the programs are erased and the values go back to zero. Now I'll connect a button with P0 of the first microcontroller and I'll write the value that is P0 into the ACC register. I'll press upload. The program has run. ACC shows zero. If I press the button now, ACC turns and goes up to 100. So the program runs in a loop and always queries P0, always writes it to the register, and the buttons, therefore, work simply by setting the output to five volts. And in the hardware version, the value between zero and 100 simply is is between zero and five volts in steps of 100s. Now I'll connect P1 with the red LED. And now I'll write the ACC register to P1. I'll upload that. And if I now press the button, the red LED turns on because the ACC register is set to 100. And this is then written to P1 and P1 lights the LED. That's perhaps a bit too complicated. I can do the same thing directly. I'll press the button. The same thing happens. Only the register doesn't change. That is simple IO. XBus works in much the same way. I can read the P0 value that my button is connected to and write it to X0. And I'll connect X, X0 with the display. The display simply shows what is sent through the XBus connection. And if I upload that and press the button, then the display will, as you can probably not see too well on the screen, in reality, it is much brighter, but you see the value changing to 100. So that's the XBus. The XBus I can also use to communicate between the two microcontrollers. I'll connect X1 on MC1 with X0 on MC2. And I'll write P0 to X1 now. And on the second microcontroller, I will connect it to X0 on the second microcontroller. So I'll take X0 and save it in the DAT register. Upload the whole thing. And when I press the button now, you see how the data register is set to 100 because the value from the first microcontroller was communicated to the second one. If I release the button, then it turns, goes back to zero. And one difference to change in IO is that change in IO forces you to run a sleep, include a sleep command, which is simply putting the microcontroller on hold for a while. And for me, one time unit is 100 microseconds, milliseconds. So if I put in the number 10, that is 10 times 100 milliseconds, one second waiting time. So that gives you a slight delay when I press the button, a one second delay. You probably see it better if I'll make, turn this into five seconds. I'll press the button. It takes a while. And now data is set to 100. Exactly. So this loop has now stopped for five seconds. Then it reads the value again, writes it again and again. And that is the time when the DAT register on MC2 is finally reset. And in the same way, I can send something to the buzzer. The buzzer works by taking values between one and 75. And these are increasing pitches, frequencies. So you can, we can use a mathematical feature now, such as add, add one means take the ACC register and add one to it. Because it's initialized with zero by uploading it, I see that it's immediately set to 999. The reason for that is that the code runs quite quickly. If I don't put a sleep in there, if I add a sleep for 100 milliseconds, you see how the value is slowly increasing. I increase that to five even. So the value is increased. And this value, I will now, I can now transmit to X0. And you see how things happen on the display now, how it, how the count increases. And if I now connect this to the buzzer instead, you can hear. So you can actually play melodies that way. Now, on to tests, conditionals, comparisons. You see now the ACC value has, is always increased. And I now could do something such as if, well, first I'll sleep again to prevent it from running too fast. Teq tests for equality, test equal. And I will now look into ACC and test it for 50. And after such a test, I can add further lines with a plus in front, which means that they are only executed if the test evaluates to true. So if ACC equals 50, exactly. And lines that I prefix with a minus are executed if the test is yields false. And if the value is 50, of course, I have my X1 still connected with X0 on the other controller. So I'll simply move the value 23 to X1. And the second controller still is running the code that it simply moves X0 to that. So I'll upload this. We see ACC increasing. And as soon as it reaches 50, this line will be executed. And the value 23 will be sent. And the data, there you go, it shows 23. So in this way, you can implement quite a lot of functionality. And the purpose of the game is to solve tasks such as this. So this is about getting a traffic light to work. The light is red. A pedestrian is pushing a button. And the light should switch to yellow to green. The pedestrian should have time to cross the road. And also there should be a countdown from 10 to 0. So to solve this problem, I'm adding a couple of connections. So use the yellow LED, the green one with P0. Because both controllers only have two simple IO pins. And I can only use simple IO with simple IO pins. So I'm using the second controller as kind of a port expander. So the remaining connections can stay as they are. I already wrote that program. This is slightly more complex. And we're also using labels. This time, I haven't shown that so far. Anywhere in the code, you can add a label. And you can use the jump command to jump to that particular label. So I'm uploading this now. And when I push the button, I can see the timer counting down to 0. The traffic light is turning green. The light is switching back to red. And we can do it again. The timer counts to 0. The traffic light turns green. And then it turns back to red. So I solved that problem. And on the next level, I would need to add some beeps when the light turns green. So I started with this project last year. And basically, to work on the Padauk microcontrollers, they're really cheap. But they can't do a lot. Last year, an open source tool chain became available. Previously, there was only proprietary tools from the vendor that you had to pay for. So now it is supported by the SDCC compiler. And there is an open hardware programmer. So I ordered a programmer and a bunch of the microcontrollers and played around with it a bit and looked for something to do with them. And I looked at the data sheets a lot. And I was reminded of the Shenzhen I.O. data sheets. And so the idea was born to reimplement Shenzhen I.O. in real hardware. So the processor that seemed the most fitting is this one because it has an analog digital converter. So I can use that for the simple I.O. ports. And it's also got PWM. And so there isn't a serial interface, but there's an interrupt capable pin. So that can be used for receiving on the serial port. And there's one pin that is open drain. So that can be switched only to ground. And if you set it to one, it's an open circuit. And you can use that to communicate with multiple controllers at once as kind of a bus. So otherwise if you connect multiple together, they would interfere with each other. So as long as only one of them is transmitting at any time, you can connect multiple to the same bus. So for the simple I.O. output, I connected the I added a low pass filter to use the PWM signal to convert that to an analog voltage. And I'm using that to send the signal to a simple I.O. port. On receiving, the pin is switched to an input connected to the ADC. And that works wonderfully for a simple I.O. The X-Bus is slightly more complicated. So we need a signal that the sender is ready to send and the receiver must be able to tell the sender that it's ready to receive data. So that's the way it's implemented in X-Bus. And for that, I used a feature that the PFS173 has internal pull-ups we can use. So I can switch the pin to an input. But use the pull-up nonetheless. And that pulls up the pin. And when the output is not active, it's pulled down. So the sender raises the signal, the receiver sees that, and the sender pulls it down to signal to send the data and sends 12 bits to signal value from minus 999 to plus 999. So these chips don't have very good timing on an internal RC oscillator. So an X-Bus transfer is relatively slow. It takes about 50 milliseconds. And that's mostly sufficient. And that's really sufficient for the tasks that are needed to be implemented for the game. So the firmware was quite a struggle because the microcontroller has very little RAM. So I need quite a bit of those bytes to store the program. And the remaining storage was never enough. What really helped was the compiler because it actually was optimized for this architecture. In particular, function calls were using less RAM than before. And so I learned a lot about when to inline functions so to decrease their memory use. So the SDCC compiler is not very good at figuring that out automatically. To generate the assembler code into the 65 bytes, I am doing this. I take a command like move and I'm using the upper six bits to encode that. And so since there are only 15 instructions, that's fully sufficient for the lines that have a plus or minus in front of them, depending on what the previous test command was testing. So in the same byte, I'm using the two lowmost bits to encode the plus or minus. And so that means that it won't take up any more memory in the microcontroller. The parameters are always fixed. And the first parameter can be an integer or a register. The second parameter can always only be a register. For parameters that can be registers or integers, I'm using 16 bits. For a register, I only need 8 bits. So for this line move 42 to P0, I'm using 4 bytes. And in the firmware, there's a counter that shows where we are in the program code. And for move command, that is incremented by three bytes. And that means that the 14 lines of assembler code can always be stored in the 65 bytes of RAM. Labels were a bit tricky. So I'm parsing the complete assembler code to extract the labels. There are basically strings with a colon after it. And I'm assigning a unique ID, a number between 1 and 2.5.5, encoding then by having an opcode for a label, and then the index of the label. And when a jump command occurs, then I simply scan through the entire program code to find the label, to search for the index of the label, and then I jump there. And that uses very little memory. One trick in the program code. You can add labels to lines that already have a command. I added that because that's possible in Shenzhen IO. It's not documented, but it works. So my goal definitely was that any code that works in Shenzhen IO should work on my microcontroller. If you want to try this for yourself, then you should be able to get to my GitHub page. I have added a lot of GitHub Actions. So all the binaries are built automatically for the different platforms. The CAD files, the key CAD files, are all processed. And the garbage, a bomb, and pick and place files are created automatically. And you can upload them to JLCPCB. So that includes all the order numbers from JLCPCB. And at early April, the Padauk chips are unfortunately not available right now. So it's a bit weird that they're all sold out right now. So we have to wait until they're available again, but then you can buy all the parts. I've created the layout in a way that all parts are available. JLCPCB should have all the parts available so you can have them assemble it automatically for you. And you can order pieces, five to 50 pieces, add the pick and place option, upload the bomb files, and they will populate the board for you and mail them to you. Here's a couple of links to the Git repo, to the free PDK and Shenzhen IO. And the last time I checked on Google Games, it was on special offer on Google Games for only a couple of dollars. So if you haven't played it, give it a try. It's a very nice game. Yeah. So I can't hear the Herald very well. So I think the Herald is saying that there's quite a few questions. And we can't hear the speaker. Sorry for the technical glitch. Where do you get the board from? So I can't hear the speaker and I'm guessing he's not on the stream right now. Hopefully somebody will notice that soon. So finally the director noticed that the speaker was not debatable by audio. So there were a few problems we have to start over. Okay question one, where did you get the board from? Can you hear me now? Okay. So the board comes from the Chinese manufacturer JLCPCB. And on the GitHub page, they're all production files that are needed to order a set of boards yourself. If there's a lot of interest, I could try doing a bug order at like 50 pieces as soon as the microcontrollers are available again and order a batch and send them on to people who are interested. A really cool project. So in my old age, I might be convinced to actually play around with this. So next question, is that your first cool project or is there a list? What have you done elsewhere? I have done a lot the last 10 years. I am working professionally in product development. So my hobby projects were on the back burner. So my website is Flegmatic Prototyping. And if you search for that, you should see a couple of my projects. So the next logical question is what will you be doing next? So I just heard about a project as we were talking to the operating team. Apparently, there's a game where you have to diffuse a bomb. And only one person has the instructions. I forgot the name. But it sounded like it would be very nice to build a hardware version of it. And only one person has the board and has to work on the board. And the others have to explain to them how to do that over a video conference. So clearly, the next question is by a person that is very, very experienced in the assembler. Would it be possible to use the Unicode minus character instead of the dash character? So it lines up well in the editor. So yeah, I need to check if the parser can work with that. The GUI is I haven't worked on very intensively. And since it's an open source project, if you want to improve the code editor, please go ahead, bring it on. Yeah, the question had a smiley behind it. So where is your open source project? It's on GitHub. It's released under the GPL3 license. Here we can see the link. I can't see the screen. So hopefully, it's visible in the stream. And all the source code is there as well for the board, as well as the firmware, as well as the desktop application, it's all open source. And you can all do with it, whatever you like. And I would love to see a maker space to create a couple of those and to use that as an introduction to programming. That sounds like a very nice project for a chaos, marschule chaos makes school. So another question that comes to mind. I wrote to sec. And I just copied some stuff from the documentation. And because I re-implemented all the stuff one to one, and he really likes the project and gave me permission to do all of this. Did you get that in writing? Yeah, I have that in writing. Sorry. And the question, the elephant in the room question. When is he going finally to ask it? How did you make that hat? So this this has been integrated into my video feed through snap camera tool published by snapchat. And I built that from that documentation. There's an example where you can put a crown on your head. And basically, I edited the file. And you can see that the hat is very two dimensional. I haven't rebuilt it as 2d, but I like it. All right, looks very nice. Here's another question. No, there aren't any more questions. I could ask you myself. Are you planning to like go to schools with this project? Or do you want other people to do that? But you were talking about bulk order. Yeah, I think I'll add that to the website. Just a link for people to express their interest in getting one or two boards and then collect all those people and do a bulk order and send them on. And I'll add that to the GitHub page. I'm active into maker spaces. And when we can do in person workshops again, then I would check if there's interest in that and would get a couple boards and use them in my maker space. Yeah, it sounds like a really cool project, especially in the context of Karl's Machtschule. Yeah, I noted that down and I'll stay in contact with you.