Electronics, coding and hacking. And ADD.

3D printer


A few weeks ago I bought a second-hand 3D printer, namely Kossel 800 delta printer. It lacked the stepper motors, pulleys and a general clean-up of the wires. After a week of trying to figure out how this works, I had my first successful print last night.

Unfortunately I did not take pictures during the build, so you'll just have to take my word for it. We'll skip straight to the end result.

This is the latest print, the letter J. I'm quite pleased with the result so far, there are a few calibrations I need to do still, but all in all I'm very excited. Time to order a few kilogtrams of filament.

Oh, and if you're wondering why my latest posts have been from the kitchen table, it's because I'm building a new hobby room, so my daughter can have her own room in the house. The new hobby room is a converted outdoor shed; smaller and colder than ever before. Can't wait to move in.

WiFi-enabled RC car


My son owns an RC car that lacks the remote control. It's a cheap car, but still, instead of throwing it away I decided to rescue it somehow. I guess I could find a cheap replacement controller... but why not go all the way and hook it up to my WiFi network?

Good looking car does not know what's about to happen

I decided to use a WeMos D1 board that I had spare, which is an Arduino form factor ESP8266 based board. The ESP8266 specs are amazing, I encourage you to look into this if you need to WiFi-ify something (did I just invent a new word?)

WeMos D1 ESP8266 WiFi board

Not many surprises awaits when you have a transparent chassis. Either way, here's the case that holds the current motherboard. Two more screws and we're in.

Bottom's up! The bottom side appears crowded, but is actually quite nicely laid out. The easiest way to figure out what went where, is to follow the traces backwards - i.e. from the motors to the main IC.

The top side of the board reveals the main IC, which is a PT8A978BPE. It appears to be a common controller for low and mid range remote controllers. I had already figured out the pinouts for forward, reverse, left and right earlier.


Here are the pins labelled 1, 2, 3 and 4 clockwise by yours truly. I applied 3V3 directly to the pins and the wheels started spinning. This is the operating voltage of both the WeMos D1 and the PT8A978BPE, so I figured it's OK.

Wires were soldered to the pins, going directly to the WeMos board since the original motherboard provides the pull-down resistors required. The brown wire in the bottom left corner is to connect the ground planes.

All wired up!

The original battery case had room for six 1.5V AA batteries. Unfortunately I didn't have enough AAs, so I improvised with one 9V battery. However, on the bench I used a traditional power supply.

My heavy-duty power supply

The WeMos D1 found its new home, and I started writing the server software. At first I thought it would be fancy to use a web interface, and improvised a web server on it. Turns out that web calls isn't the best candidate for quick response applications, so I rewrote it down to a simple TCP client. I can even telnet to it and drive it from the command line.

The protocol is dead simple: there are four directions the car can go: forwards, backwards, left and right. The initial letter dictates the direction (F, B, L, R). Uppercase means on, lowercase means off. A sequence of commands to the car may look like this: FRfrBLbFl, and they are parsed on the fly.

The D1 found its new home

Now we're getting somewhere. All parts are wedged into place, and we are ready to start focusing on the client side of the software.

Professionally secured with electrical tape

Here it is on the test bench, a.k.a. an IKEA lamp. No wires attached, running 100% from battery power, controlled via WiFi.

Looking pretty sweet. The car looks a lot better without the original, limp antenna. And it probably does wonders for the aerodynamics as well, don't you think?

All mounted and ready to race.

It's hard to tell from the outside what's going on, but once you take a closer look you can see some of the modifications.

The client software was written in C++/Qt and works perfectly. You can click the buttons or use the keyboard, which is a bit more intuitive. The response time is around ~150-200ms, which is good enough for someone with my driving skills. Meaning I crash a lot anyway.

C++/Qt client

Here's a quick video of the thing in action. Turns out it's hard to drive around when you can't see a thing... Adding a camera to the equation is tempting...

The above video could be much cooler if I were a better driver.

Ripping graphics


There's an old strip poker game for the Amiga called Hollywood Poker Pro. The game had an introduction screen featuring the silhouette of a woman dancing to a catchy 80's tune. I wanted to rip that animation, and thought it could be an interesting read to see how it was done.

Just to get an idea of what I'm against, I loaded the game into WinUAE and took a full memory snapshot. Unfortunately, all I could find was the current frame, so it was obvious that the image was rendered in real-time somehow.

I then decided to take a closer look at the game files. Since the diskette image was NDOS (i.e. not directly readable from by AmigaDOS) I had to lift out the files somehow. I saved some time as I found the WHDLoad image of the game, with all files in a readable directory. One file in particular caught my interest, namely dance.dat.

I examined the dance.dat file in a hex editor, but it left me clueless. I rolled up my sleeves and prepared for some debugging to figure this out. I loaded the game loaded in WinUAE with just 512kB RAM, 68000 CPU, OCS/ECS compatibility.

You see, in the good old days almost every program was run from a run loop. This is a loop that calls several subroutines to get things going.To identify this loop, I fired up the WinUAE debugger by hitting SHIFT+F12 several times.

After a few iterations, I started to notice a pattern in the breakpoints. It landed in the $66Exx address space every time. Dissassembling this memory neighbourhood revealed that the run loop started at $66E1C. Here is the run loop, and those of you who know Amiga assembly will recognize the classical btst #6,$bfe001 (test for left mouse button) at the end:

As you can see there are three JSRs from here, to $66B0C, $67152 and $66EAC. Interestingly, each of these subroutines begin with the instruction NOP ("no operation", opcode $4E71), so by replacing this with RTS ("return to subroutine", opcode $4E75) the function could easily be skipped without too much hassle. Using this technique, I quickly noticed that $66EAC was responsible of the upscroller, $67152 drawing the animation and $66B0C did the frame selection.

Time to debug $67152. You may scroll past this section, I'll try my best to explain it further down.

Okay, let's examine the code and try to figure out what's happening here. The first few lines are simple, the A0, A3 and A4 address registeres are loaded with three different memory addresses. By examining the addresses, I realized that A0 was the destination screen, and A3 and A4 were two lookup tables which I will cover further down.

In the next code you can see that we are loading the next byte from A1, and post-incrementing the address pointer. But what's in A1? As you may remember from the run loop above, A1 was set just before calling thus subroutine. After further inspection, it turned out that A1 is indeed pointing to the datas from dance.dat, although slightly offset.

The byte from A1 was loaded in to D7, and the code now attempts to clear the contents of (A0) "D7 times", and then one more time without incrementing the address pointer. This is probably an attempt to clear the previous image before applying the next.

The next byte from (A1) is loaded into D0. If it's zero, we'll jump ahead to $6720A, meaning we want to advance to the next scanline. If it's $ff (255) the code will jump to $67216, which is just an RTS - meaning the frame is finished.

This is where it gets interesting - and slightly confusing. First, D0 is copied to D1, and D1 is ANDed by $1F and shifted left by 2. In C, this would be D1=(D1&0x1f)*4;. D1 will later be used as an offset to look up in the table stored in A3, and this bit manipulation was to make sure the value is between 0..31 and multiplied by 4 to make sure it evens out with the 32-bit values in the table.

D0 is shifted left by 3 and then ANDed by $FC, which in C would be D0=(D0*8)&0xfc;. It's shifted left by 3 to multiply by 8, and ANDed by $FC to make sure it's not hitting an odd address - the 68000 doesn't like writing 16- and 32-bit values to odd addresses.

Now it's time to check if D2 is equal to D0. If it is, it means we're ready to draw the 32-bit value from the A4 table to the screen right now. If the carry is clear, we'll jump to $671F6. If neither of these kicked in, we'll draw a full 32-bit value of pixels before looping again.

This is the last part of the code, and it draws graphics from the A4 table.

The tables included in A3 and A4 are actually quite clever:

    dc.l %11111111111111111111111111111111
    dc.l %01111111111111111111111111111111
    dc.l %00111111111111111111111111111111
    dc.l %00011111111111111111111111111111
    ; etc...

In other words, the above table is used for looking up when to switch on a pixel. The l_605a2 table was done in similar fashion:

    dc.l %00000000000000000000000000000000
    dc.l %10000000000000000000000000000000
    dc.l %11000000000000000000000000000000
    dc.l %11100000000000000000000000000000
    ; etc...

Using this technique, one can "compress" a single line of (simple) graphics down to just two bytes - a start byte and a stop byte.

So it all makes sense. I entered the code on my A600 and included the dance.dat file to my project. After correcting a few typos and inserting a few skipped lines, stuff started happening on my screen! We have a rendered frame. The next part was looking through the $66B0C subroutine to find the offset table, which was located at $3a000 if you ever need to find it. Turns out there are a total of 106 available frames in the animation - not half bad!

The original code is very slow, and leaves very little wiggle room for other routines. It spends anywhere between 60-100% CPU each frame rendering the graphics. I did some optimizations, such as using a few faster instructions, and double-buffering where the blitter clears one frame while the CPU renders in the next. I was able to get it down to 40-70% CPU which is good enough. I have plans to use this animation in an Amiga demo I will release later. I will also rip the music, but I'll save that for later...

If you made it this far and understood all my ramblings, my hat's off to you.

A little VICtory


I wrote a little emulator for the Historic computer, and I'm currently using that as a toolbox for importing other systems into the firmware. It took a day of tweaking to get this thing running, but now I'm proud to show the fourth system this computer is capable of running. Here's the Commodore VIC-20 kernel running as if there's no tomorrow.

Now, I have to be fair, this just works. Lots of I/O's for the VIC-20 is located in the memory area where the 32K ROM currently sits, so it can't update those locations. However, the video image is as real as it gets: a big chunk of data being transferred between the RAM and the ATmega16 each frame to present the output.

As you may remember, this computer is already running a homebrew ROM, as well as unmodified ORIC-1 ROM, Apple ][ ROM and now the VIC-20's ROM kernal.

Any ideas for 6502 based arcade systems I should try?

Microscope, tags and a trip down memory lane


I recently bought a 500x USB microscope off ebay. Let's use that as an excuse to have a look at two arch rivals from the late 2000's: Q-Free and Fenrits electronic toll tags.

Here's the microscope. It's actually just a very near-sighted webcam with a mount, but it does the job. The quality is so-so. Up close it's not very good, but if you zoom out a little it's acceptable. I guess there's something about the saying "you get what you pay for." With a little extra lighting and some patience on the zoom wheel it's OK.

The one we'll have a look at first is the Q-Free tag that was recently removed from my car. I was told the battery is dead, and the tag should be disposed of. Heh, no. I was very interested in what's inside this one.

Now, the first thing I noticed is the tamper pin. When you remove the tag from its mounting bracket, this spring-like pin will drop to a contact surface and pull a pin on the DSRC controller up. A "tamper bit" is set and the toll road officials will be notified the next time you pass. If it's an automated booth, like we have here in Norway, your photo will be taken for further inspection. This is to prevent from tags from being moved between cars.

It's also interesting to see that the PCB is directly exposed at this point. This must mean that the mounting bracket forms a pretty good seal, condering the amount of moisture that accumulates on the inside of a windshield.

On the front side of the housing there are 9 drilled holes that also caught my attention.

These are guides to a set of test pins on the PCB, probably used to personalize the tag so it identifies your vehicle.

Here is the bottom side of the PCB exposed. The silver housing is a grounded RF noise shield for the PCB antenna located on the other side. Interestingly, there's also an additional reflector inside the case as well. The battery is labelled "Size 1/2 AA" and is a 3.6V Tadiran Lithium SL850/P.

This is the front side of the PCB. There's a handwritten number on top, B331. I don't know what this means, or why it's written there. Maybe it's a batch number. Anyway, let's inspect the three IC's, starting to the left going clockwise. The first IC is a 7404 NAND gate, so there's really nothing surprising going on there. However the next IC on is the DSRC controller 27PA5885N-2C. I couldn't find any datasheets for this IC, which leads me to think it may be a proprietary ASIC. It even has a dedicated 12MHz crystal.

Here's a close-up of the IC. The second line says "DSRC EFC CTRL", which probably stands for "Dedicated Short Range Communications Electronic Fee Collection Controller." This little guy deals with the communication, 3DES encryption and the local storage.

The next IC is AT25160 a serial EPROM (pdf). This chip can also be programmed via the test pins I mentioned earlier, and this is probably where all the personalized data is stored, as well as a short transaction log. I suspect that this is also the place the DES keys are stored. I will try to dump the contents of this one later on, but I doubt I will find anything useful.

I used to work for a Q-Free competetor called Fenrits. We did some low volume production for Norway, and attempted to take some international market. Unfortunately the competition was too hard, and eventually the production was halted rendering employees reduntant. I kept a tag as a souvenir, and let's have a look at it and compare it to the one from Q-Free.

This tag has the optional buzzer mounted, as well as a debug port (bottom pins). Other than that, the tag is pretty much standard. You'll notice that it does not have an on-board battery, but a connector on the side for replaceable batteries. This was a major selling point back then. There's also completely different design on the PCB antenna, as opposed to the square one on the Q-Free tag.

This is the Fenrits FZB240i, which is a proprietary RF ASIC manufactured by Fenrits. When it detects activity in the 5.8GHz range, it wakes up the FZP460i and feeds it the demodulated bit stream. It also generates the clock for the mcu, if I remember correctly.

This is the main FZP460i MCU that maintains all the 3DES, communication, storage, keys and transaction logs. It's capable of implementing a variety of protocols with minimal effort.

All tag personalization was done via the radio link. We also experimented with patching and upgrading the firmware via the same RF link, which would have simplified and extended the life span of the tags dramatically. Unfortunately, the shop was closed before we got a chance to break the news.

Add to Google