Why?
In 2006 I decided to learn how to make my own LED hardware. My first project that involved RGB LEDs used a PIC10F202 and three transistors to pulse-width modulate each color. While the design of this project was really simple, I had to learn schematic/capture, layout, manufacturing and how to write PIC assembly. (Unfortunately, the Arduino was not widely known when I embarked on my adventure so if you wanted your LEDs to go bleep-bloop you needed your own hardware platform or a big, bulky devkit.)
I knew exactly what I wanted each LED node to do: cycle the R, G and B diodes through an ascending/descending sequence of brightness values. The theory being that as each color diode was manipulated independently the LED would slowly work through each possible color combination. When I sat down to write the initial test code using assembly I found the language to be quite tedious. After writing enough code to verify that the circuit worked I decided to make my life easier by writing a higher-level assembly syntax using Ruby.
Though the final high-level assembly I wrote -- which I had taken to calling RSM -- was not insanely maintainable, I still find it easier to understand than plain assembly. And the resulting LED behavior was pretty neat:
What?
I have cleaned up the code and packaged it into a Ruby gem,
rbpic
, suitable for use (provided you happen to have a PIC10
project in your wheelhouse.) The gem comes with an executable,
rbpic-compile
, that translates .rsm
code into .asm
.
Example
Below is a simple program that does nothing to give you a taste of the syntax:
loop(:main) { }
and here is the generated PIC assembly:
#include "p10f202.inc"
__config _WDT_OFF & _CP_OFF & _MCLRE_OFF
org 0x00
goto $+2
Four_microsecond_delay
retlw 0x0
Main
goto Main
end
Here is a more serious example:
constants do
foo
bar
end
init_clock
set :foo, 2
set :bar, 1
loop(:main) do
copy :bar, :foo
end
And the resulting assembly:
#include "p10f202.inc"
__config _WDT_OFF & _CP_OFF & _MCLRE_OFF
org 0x00
goto $+2
Four_microsecond_delay
retlw 0x0
cblock 0x08
foo
bar
endc
movwf OSCCAL
movlw b'10011000'
option
movlw 0x2
movwf foo
movlw 0x1
movwf bar
Main
movf bar, w
movwf foo
goto Main
end
You can read all about the syntax here.
Musings
The code has some warts and annoying, to me, inconsistencies, but I still think it is a good example of what is possible without having to write a full-blown parser/compiler/etc. (There are C and Basic compilers that target PIC processors and they mostly work well provided you can stay within the limits of the free license.)
I also have a new project in mind that will require a PIC18 and I
want to update rbpic
to support the more complex architecture of
that processor. Join me on github if
you want to help.