We have a pool at home, and for many years, we had two switches in parallel to turn the pump on and off. One was located outside, near the pump, and another one was inside the house, so we didn't have to go outside at night or under heavy rain to turn it off. But after redecorating that specific room, there was no longer place for the internal switch.
Thinking on reducing the wire mess, I decided going wireless on that case. As a regular internet user, I was aware of readily available cheap chinese RF appliance controllers like this, but I wanted more functionality, like having a physical switch to control the pump and being able to associate more than one remote to the board. Also, the fact that I already had some microcontrollers, a RF receiver and a SSR lying in my drawer woke up my hacker spirit once again.
Once i've decided to do this myself, I connected the the RF receiver to my sound card and recorded a sample with audacity and started to figure it out. By the way, I noticed that there are many different RF transmitters around. In this case, I am using a remote with a SilvanChip SC2262 inside. It claims to be compatible with PT2262 from Princeton. The datasheet is a little bit wague, so I ignored it and simply tried to read the sequence as PWM encoded bits. I assumed that there where 24 bits of data encoded in 2ms periods and duty cycles of 25 /75% and discarded the last one (it never changed in my observations).
I already had some attiny13's that I had bought and never used. I knew that they were ICSP compatible, but had no idea if it was even possible to write them with the Arduino IDE. Thankfully, I found an excellent tutorial by Tekstop that explained the tweaks to make attiny13 work on Arduino (only Arduino 1.0 - newer version didn't work).
As you may have guessed by now, I'm not an experienced hardware programmer and although knowing something about the inner workings of processors, I always get lost when it comes to configuration registers with cryptic names like GIMSK, TCCR0B and whatsoever. So I searched until I found some ready bits of code to set up the interrupts on the attiny13 and started to work. I can't thank the author because I lost the link, but it must have been some thread on AVRFreaks.
Timer and prescaler were set to increase TCNT0 every 107 microseconds running at 9.6MHz. The rise and fall of the RF receiver signal trigger an ISR that contains the pulse length analysis. With the use of some math, I translated the signal times to timer increments, added some error margin and came up with the following table:
Within the ISR, the timer values of the current pulse are stored and tested as pairs (time_low and time_high) against these values (values adopted in the final version differ from the table) to determine wich pattern they match.
I'm proud of the way I made it, because it looks much better and mostly because it fits into the 1K flash, wich wouldn't happen if I chose the obvious nested if-then-else alternative.
I will not try to explain it in detail, because I may be reinventing some old technique, but if I had to name it, I would say it's "lossless downsampling" - wich is like if you would measure things with a customized ruler (role of the array named time_stones), spaced unevenly on purpose. I preffer you try to understand it reading the source.
By the way, I've heard of some people who decoded RF by detecting the first pulse and then sampling each pulse just once at half-period. That sounds very unstable. I hope it isn't common.
The prototype works as expected and I'm just waiting for my neighbor to finish the PCB so I can solder and install it properly. Maybe I'll post some pictures of the finished board after that.
I'm very happy to have achieved decoding RF, accepting button input, controlling an output, managing EEPROM and driving a buzzer with only 860bytes of flash. It really amazed me!
Source-code and schematics (eagle) are attached below. If you find any bugs or have any questions, feel free to ask.
If you wish to download the files below, click on the down-arrow icon. The link with version number does not work.