Saturday, June 28, 2014

Hacking microcontroller assembler macros to provide C like conditional blocks

I started off with microcontrollers about 10 years ago using Microchip PICs. While they haven't kept pace with some of the other stuff out there and the limited development tools has relegated them to obscurity compared to the Atmel powered Arduino, I still have a place in my heart for these old favorites.

PICs are dirt cheap, and have very good internal oscillators, which means a lot less fussing around to get something working. You can get away with just the chip and a capacitor, and you can pick up chips for under a buck. They also have oodles of variations and a wide selection of peripherals that compensate for the less powerful core.

The new MPLAB X and free-tier XC8 compiler provides a usable but suboptimal development environment. The free tier compiler includes anti-optimizations that needlessly bloat your code. Some times you need to really eek out a high performance loop or control the timing of something very precisely, and the inline assembly options here just suck. For example, consider this limitation as seen in the XC8 Compiler User Guide:
The #asm and #endasm directives are used to start and end a block of assembly instructions which are to be embedded into the assembly output of the code generator. The #asm block is not syntactically part of the C program, and thus it does not obey normal C flow-of-control rules. This means that you should not use this form of in-line assembly inside or near C constructs like if(), while() , and for() statements. 

Prior to MPLAB X, I used SourceBoost, which was a very basic IDE with limited features glued on to an amazing compiler. Unfortunately active development on this seems to have stopped, and only works on Windows.

SourceBoost supported C++ style templates for their C compiler, another feature I found missing when I switched to XC8. It was slightly better than the MPLAB assembler macros as it would create a reusable function tailored depending on the template args vs assembler macros that just insert the generated code inline, saving flash. In addition, it was possible to insert some assembly mostly pain-free if you needed to.

Prior to SourceBoost, I coded in assembly in the old MPLAB IDE. I had quite a bit of fun eeking out every byte of ram and flash on a PIC12F629. To make thinks easier, I took good advantage of the call stack to create functions, and the assembler macro capability to create inline functions. The dynamic code generating capabilities of the macro language they provide is more elegant and powerful than a mess of #IF directives in C.

My latest project finds me back to where I started - pure assembly. 90% of my project involves hand stitched code that is doing 4 things at once, while doing a very timing specific bit-banging with precision +- 150ns at a ~1.25us interval. At 12 million instructions per second giving 83.33ns between instructions, that doesn't really leave a lot of wiggle room, nothing close to what would be needed to implement this using a timer and interrupt service routine. With all of the headaches of gluing assembly into C code, it made sense to keep the whole thing in assembly.

The one thing I notice coding in assembly more than anything else is the lack of if-else style blocks. I don't mind adding a label, increment/decrement, and test/goto for a loop, but creating dozens of silly labels for conditionals somehow short circuits the part of my brain responsible for variable naming.

Taking an idea from Karl Lunt's PIC macro library, which implemented a for-next, repeat-until, and switch-case, I created a set of nestable if-else-endif macros. Combined with the fact that the assembler is indentation agnostic after the first column (labels), this makes it really pretty easy to create a regular C like conditional block.

This allows you to take a goto-poorly-named-label style of coding like this:

  btfss flags, hasData ;bit test, skip next if set
  goto noData
  call readFromBuffer
  movfw tmp
  call putch
  goto endDataCheck
noData:
  ;all done!
  blink LED1, 1, 1000
endDataCheck:

Into this:
  ifbtf flags, hasData ;if bit test
     call readFromBuffer
     movfw tmp
     call putch
  ifelse
     ;all done!
     blink LED1, 1, 1000
  ifend

You can download my library here: bensmacros.asm.

Sunday, June 22, 2014

Bad Ideas: Street Speeders

Street Speeders

So I live next to a fairly busy street. Often people will be hitting full throttle right as they pass, as there is a light just a block up, the street is fairly wide, and market 30 MPH which means closer to 45.

It's kind of annoying, just enough to remind me a few times a day as someone tears ass through my neighborhood. Double pane windows helped a lot, but doesn't counteract the 80 cubic inches of displacement in the Harley-Davidson as it accelerates 300lbs of grisly biker dude, leather, and metal studs.

For a while I've been pondering different possibilities to combat this. It had to be legal and safe, after all this is where I live. This simple set of criteria has filtered out most of my ideas.

Bad Idea #3: "Big Brother is watching"

Down the street a bit is one of those radar displays that tells you how fast you are going, and blinks if it thinks you are going too fast. These appear to be fairly ineffective - everyone knows these don't issue tickets.

What about a large screen shaming the drivers as they go past? Surely having a photo of you speed by talking/texting on a cell phone combined information from public records displayed on a billboard would get your attention.

Maybe too much attention. The last thing my neighborhood needs is a more distracted driver, or a riot of privacy advocates.

Bad Idea #2: "You are driving in a residential area"

Taking the helpful signs to the next level.

If a helpful reminder that they are driving through a residential area is a good thing, then how bad could it be to remind drivers that at any moment a cat, dog, or kid could dart into the road? What better reminder than a simulated reproduction of the experience? Imagine a stuffed animal racing toward the street to intersect with speeders, stopping safely just past curbside parking.

I can only imagine how many collisions this would cause as speeders swerve and overcorrect to avoid the faux-inevitable collision.

Bad Idea #1: "Welcome to the car wash"

Even if it would be really cool to have a speed activated sprinkler that would give speeders a wake up call, I can't imaging this working out well in the long term. 

Firstly, it's not really safe. A splash of water is probably a little too startling, and could temporarily impair visibility.

Second, I have to consider that it might also hit the grisly biker dude.