Better Coding Through Sketching

Back in the late 1970s and early 1980s, engineering students would take a few semesters of drafting and there would usually be a week or two of “computer-aided drafting.” In those days, that meant punching cards that said RECTANGLE 20,30 or something like that and getting the results on a plotter. Then we moved on to graphical  CAD packages, but lately, some have gone back to describing rather than drawing complex designs. Cornell University researchers are trying to provide the same options for coding. They’ve built a Juypter notebook extension called Notate that allows you to sketch and handwrite parts of programs that interact with traditional computer code. You can see a video about the work below.

The example shows quantum computing, but the idea could be applied to anything. The example has sketches that generate quantum circuits. Naturally, there is machine learning involved.

Continue reading “Better Coding Through Sketching”

Using I²C Sensors With Any Linux Via USB And IIO

Hooking up I2C sensors is something which is generally associated with microcontrollers and SBCs, yet it’s very easy to use such I2C sensors from basically any system that runs Linux. After all, I2C (that is, SMBus) is one of the interfaces that is highly likely to be used on your PC’s mainboard as well as peripherals. This means that running our own devices like the well-known BME280 temperature, pressure and humidity sensor, or Si1145 light sensor should be a piece of cake.

In a blog post from a few years ago, [Peter Molnar] explains in detail how to wire up a physical adapter to add a USB-connected I2C interface to a system. At its core is the ATtiny85 AVR-based MCU, which provides a built-in USB interface, running the I2C-Tiny-USB firmware.

The essential part here is that the MCU shows up to the Linux kernel as an i2c device, requiring the i2c-dev driver to be loaded. After this the I2C device that is connected to the adapter MCU’s I2C bus can be used via the Linux module’s API calls, either directly or via existing drivers. [Peter] found that the BMP280 driver came with Debian Sid, for example.

Building Your Own Consensus

With billions of computers talking to each other daily, how do they decide anything? Even in a database or server deployment, how do the different computers that make up the database decide what values have been committed? How do they agree on what time it is? How do they come to a consensus?

But first, what is the concept of consensus in the context of computers? Boiled down, it is for all involved agents to agree on a single value. However, allowances for dissenting, incorrect, or faulting agents are designed into the protocol. Every correct agent must answer, and all proper agents must have the same answer. This is particularly important for data centers or mesh networks. What happens if the network becomes partitioned, some nodes go offline, or the software crashes weirdly, sending strange garbled data? One of the most common consensus algorithms is Raft. Continue reading “Building Your Own Consensus”

Prototyping The Prototype

For basic prototyping, the go-to tool to piece together a functioning circuit is the breadboard. It’s a great way to prove a concept works before spending money and time on a PCB. For more complex tasks we can make use of simulation software such as SPICE. But there hasn’t really been a tool to blend these two concepts together. That’s what CRUMB is hoping to solve as a tool that allows simulating breadboard circuits.

Currently, most basic circuit functions are working for version 1.0. This includes passive components like resistors, capacitors, switches, some LEDs, and potentiometers, as well as some active components like transistors and diodes. There are some logic chips available such as 74XX series chips and 555 timers, which opens up a vast array of circuit building. There’s even an oscilloscope feature, plus audio output to incorporate buzzers into the circuit simulation. Currently in development is an LCD display module and improvements to the oscilloscope.

Besides prototyping, this could be useful for anyone, students included, who is learning about circuits without the need to purchase any hardware. The major downside to this project is that it there doesn’t seem to have a free or trial version, the source is not available, and it’s only for sale on Steam, Apple Store, and Google Play. That being said, there is a forum available for users to discuss problems and needs for future versions, so it’s possible that a community could build up around it. We’ve seen previously non-free versions of circuit simulation software become more open after some time, so it’s not out of the realm of possibility.

Thanks to [Thomas] for the tip!

Create A Compiler Step-By-Step

While JavaScript might not be the ideal language to write a production compiler, you might enjoy the “Create Your Own Compiler” tutorial that does an annotated walkthrough of “The Super Tiny Compiler” and teaches you the basics of writing a compiler from scratch.

The super tiny compiler itself is about 200 lines of code. The source code is well, over 1,000 but that’s because of the literate programming comments. The fancy title comments are about half as large as the actual compiler.

The compiler’s goal is to take Lisp-style functions and convert them to equivalent C-style function calls. For example: (add 5 (subtract 3 1) would become add(5,subtract(3,1)).

Of course, there are several shortcut methods you could use to do this pretty easily, but the compiler uses a structure like most full-blown modern compilers. There is a parser, an abstract representation phase, and code generation.

Continue reading “Create A Compiler Step-By-Step”

Reinterpreting The Lua Interpreter

The idea behind Lua is a beautiful one. A simple and concise syntax offers almost all of the niceties of a first-class language. Moreover, a naive implementation of an interpreter with a giant switch case can be implemented in an afternoon. But assembly is your go-to to get decent performance in a JIT-style interpreter. So [Haoran Xu] started to ask himself if he could achieve better performance without hand-rolled assembly, and after a few months of work, he published a work-in-progress called LuaJIT Remake (LJR).

Currently, it supports Lua 5.1, and on a smattering of 34 benchmarks, LJR beats the leading fastest Lua, LuaJIT, by around 28% and the official Lua engine by 3x. [Haoran] offers a great explanation of interpreters that provides excellent background and context for the problem.

But the long and short of it is that switch cases are expensive and hard to optimize for compilers, so using tail calling is a reasonable solution that comes with some significant drawbacks. With tail calls, each case statement becomes a “function” that is jumped to and then jumped out of without mucking with the stack or the registers too much.

However, the calling convention requires any callee-saved registers to be preserved, which means you lose some registers as there is no way to tell the compiler that this function is allowed to break the calling convention. Clang is currently the only compiler that offers a guaranteed tail-call annotation ([[clang::musttail]]). There are other limitations too, for instance requiring the caller and callee to have identical function prototypes to prevent unbounded stack growth.

So [Haoran] went back to the drawing board and wrote two new tools: C++ bytecode semantical description and a special compiler called Deegen. The C++ bytecode looks like this:

void Add(TValue lhs, TValue rhs) {
  if (!lhs.Is<tDouble>() || !rhs.Is<tDouble>()) {
    ThrowError("Can't add!");
  } else {
    double res = lhs.As<tDouble>() + rhs.As<tDouble>();
    Return(TValue::Create<tDouble>(res));
  }
}
DEEGEN_DEFINE_BYTECODE(Add) {
  Operands(
    BytecodeSlotOrConstant("lhs"),
    BytecodeSlotOrConstant("rhs")
  );
  Result(BytecodeValue);
  Implementation(Add);
  Variant(
    Op("lhs").IsBytecodeSlot(),
    Op("rhs").IsBytecodeSlot()
  );
  Variant(
    Op("lhs").IsConstant(),
    Op("rhs").IsBytecodeSlot()
  );
  Variant(
    Op("lhs").IsBytecodeSlot(),
    Op("rhs").IsConstant()
  );
}

Note that this is not the C keyword return. Instead, there is a definition of the bytecode and then an implementation. This bytecode is converted into LLVM IR and then fed into Deegen, which can transform the functions to do tail calls correctly, use the GHC calling conventions, and a few other optimizations like inline caching through a clever C++ lambda mechanism. The blog post is exceptionally well-written and offers a fantastic glimpse into the wild world of interpreters.

The code is on Github. But if you’re interested in a more whimsical interpreter, here’s a Brainf**k interpreter written in Befunge.

Making SVD Files Searchable With Svd2db

Everyone who writes bare-metal code for microcontrollers probably know the joys of looking up the details of specific registers in the reference manual, including their absolute address. Although the search function of the PDF viewer can be helpful, it’d be rather nice if there was a way to search only the registers, and have the offset calculations performed automatically. This is basically what [Terry Porter]’s Svd2db tool enables. As the name suggests, this tool turns the SVD hardware description files that come with ARM-based MCUs into a database file.

This database file is an SQLite database, which allows it to be searched using the provided readdb tool, or any other SQLite tool. This would make the utility useful not just for quick look-ups during development, but presumably also for automated testing scenarios where having an easily searchable database of registers is of use. At this point Svd2db is guaranteed to work with STM32 SVDs, but may work with SVDs for other ARM-based SVD files as well.