SX1231 Calculator

I was doing some testing with a Semtech SX1231 (also known as RFM69*) to
replace the Silicon Labs Si443x receiver I am currently using to receive my 433
MHz sensor nodes. The SX1231 seems to have much better reception and less
craziness in the FIFO control.

While configuring the module I found that some configuration options have
constrains on them that are a bit hidden away in the datasheet text. This is
especially annoying if you want to change some setting after a while and don’t
want to reread the whole datasheet.

So I decided to write a little configuration calculator for the chip. The
calculator converts human readable values to the register values and verifies
that they meet the constraints. It also automatically updates register values
of options that depend on a specific setting(eg. Crystal frequency or Carrier

It also allows importing register dumps so you can easily see what
configuration you are using. And it tries to visualize some of the parameters,
like packet structure and RF spectrum.

The calculator is build as a single page web application. Which means you can
use it in any modern browser. Because it is fully written in client side
javascript you don’t even need an internet connection/or need to thrust a
remote server to use it.

Writing the code was, as usual, much more work than I anticipated for. It
involved a lot of bit fiddling and copy and paste, which is rather error prone.
So be warned to verify the results, before usage.

Well enough talking, I suggestion you just try it out! The online version is available here:

SX1231 Calculator

If you want to use it offline, then you can just download the page from the online version.

The sources is of course available at GitHub


IC’s used on HopeRF modules

HopeRF makes some nice modules. But I’m always struggling to find which actual chip is used by the HopeRF radio modules. So I made a little list of HopeRF modules and the name of the IC used.

Module IC
RFM12 Silicon Labs Si4420
RFM12b Silicon Labs Si4421
RFM22b Silicon Labs Si4432
RFM23b Silicon Labs Si4431
RFM24w Silicon Labs Si446x(?)
RFM26w Silicon Labs Si446x(?)
RFM31b Silicon Labs Si4330
RFM42b Silicon Labs Si4032
RFM43b Silicon Labs Si4031
RFM50 Silicon Labs Si1000(?)
RFM60 Silicon Labs Si4010
RFM63W Semtech SX1211
RFM64W Semtech SX1212
RFM65W Semtech SX1239
RFM66W Semtech SX1232
RFM67W Semtech SX1230
RFM68W Semtech SX1243
RFM69W Semtech SX1231

This information is based on:

  • The title of the earlier Hope RF data sheets often contains the Silicon labs chip name
  • Comparing data sheets

Of course I give no guarantees about the correctness of this information. If you find something to be incorrect, please leave a comment.

SI4010 + FT232R: A 433 MHz USB Radio Transmitter

Some new updates on the SI4010 front. First of all SI4010Prog now support a FTDI FT232R chip as C2 Bus master. Second I’ve wrote a firmware that allows controlling the SI4010 transmitter through a serial line.

SI4010Prog + FT232R

SI4010prog can now use a FT232R as C2 bus interface. Major advantage of this is that you can first load a firmware into the SI4010. And than use the FT232R as USB to serial adapter to communicate with the firmware as a normal serial device.

To implement the C2 bus master I use the special FTDI ‘SYNCBB’ bit bang mode on the DTR and CTS lines of the chip. This mode guarantees that the timing of the read and write actions is accurate, and the read and write actions are synchronized.

A downside of this interface is that it is relative slow. This is caused by the fact that multiple USB control transfers have to be done for writing one byte to the SI4010’s memory.

Other FTDI chips than the FT232R that support SYNCBB mode bit banging might also be supported. But I only tested it with a FT232R(rev. C).

The updated SI4010Prog is available it the Si4010Prog repository.


To be able to play with the SI4010’s radio features without constantly having to modify and upload a new firmware to the SI4010 MCU, I wrote the SER4010 firmware. SER4010 is a firmware that allows control over the SI4010 RF functions from outside the device through a serial connection.

The firmware basically allows the following three things:

  • Configure RF parameters like: frequency, modulation type, bit rate, output power
  • Load a data frames
  • Send the loaded frame

A frame in this case is just a bit string where the bit’s encode the output level, eg. ‘1’ or ‘0’, to send. The duration of 1 bit is determined by the bit rate. This gives full flexibility for the data encoding, while having guaranteed timing of the symbols. The only limiting factor currently is that the byte string can not be longer then ~250 bytes.

To compile the firmware you need the Keil 8051 compiler toolchain and the SiLabs IDE + SI4010 common header files. But precompiled firmware file are available under releases in the Git Hub project.

The SER4010 firmware and C interface library source can be found in the SER4010 Git Hub project.

All Combined: A tunable 433 MHz USB radio transmitter

If we combine a FT232R + SI4010 with the SER4010 we end up with a USB OOK/FSK Radio transmitter for the 433 MHz ISM-band! I call this combination the SER4010-USB module. Adding a casing and a SMA antenna connector to it and it almost look like a professional device:).

SER4010-USB device RF transmitter

SER4010-USB device RF transmitter

You might wonder why I call it ‘433 MHz tunable’. This is caused by the antenna matching network. Although the SI4010 is tunable in the 27–960 MHz range, the external circuitry to match the 50 Ohm antenna to the output impedance of the chip is designed specifically for 433 MHz. So it is only effectively tunable within the band for which the SI4010 module was designed.

I did some range testing with a cheap omni directional 433 MHz antenna. With direct line-of-sight I was able to control Somfy RTS blinds from ~300 meters away. The range might even be further, but at 300 meters I lost my line-of-sight, and thus my ability to verify that the receiver received the signal. But I was already very satisfied with the 300 meters;).

More information on the SER4010-USB module and information about building one you self see the SER4010-USB page.

SI4010 Microcontroller

When browsing eBay for new ISM-band transceivers to play with, I stumbled upon the Silicon Laboratories SI4010 micro controller. The SI4010 is a 8051 with a build in tunable RF transmitter for OOK and ASK and on top of that it has a build in AES engine. That seemed perfect for my secure domestic sensor network!

The Hardware

The module I bought on eBay is a PCB that contains a SI4010 and a 50 Ohm unbalanced antenna matching network. All pins are connected to pads on the border of the PCB. The PCB also has pads for a crystal resonator, but no crystal is present. It seems this module is possibly the same as the HopeRF RFM60.

SI4010 module front & back

SI4010 module front & back

The heart of the SI4010 is a 8051 compatible micro controller that runs at 24 MHz with 1 instruction per clock cycle. It has a build in oscillator, although there is a possibility to add an external crystal.

On the memory department it is a bit limited. Apart from the 256 Byte 8051 IRAM, it has 4 kByte of shared XRAM/CODE memory. When using the free Keil compiler, the CODE memory is even more limited to the upper 2 KByte only. Luckily there is also a 12 kByte ROM with precompiled code that offers an API for using most of the build in peripherals. By using this you can reduce the amount user code required.

For persistent storage there is only a 16 Byte EEPROM, 8 Byte of low leak RAM and 8 kByte of OTP NVRAM. The NVRAM is one time programmable, and can only be written through the in-system debug interface. Because the NVRAM is twice the CODE memory, this might allow for patching the NVRAM code by using a boot loader that can load patches from the NVRAM. I haven’t looked into this to see if it is really possible. For development it doesn’t matter that the NVRAM is one time programmable, because you can load code directly into the XRAM/CODE memory using the debug interface.

As mentioned before the chip has an in-system debug interface. It uses the Silicon Laboratories proprietary C2 protocol and uses two shared function GPIO pins. This interface is very powerful because it allows reading and writing all memory. It also offers the ability to set 8 breakpoints.

On the I/O department it has 9 GPIO pins. One pin can also function as LED driver and the pins offer some functionality to function as 18 button push button matrix. The optional external crystal and the C2 debug interface also share there functionality with GPIO pins. The SI4010 does not have a UART, I2C or SPI interface. But because of the relative high clock rate I was able to implement a 9600 Baud UART and a I2C master in software.

The cool thing about this micro controller is the build in RF-module. It supports FSK and OOK modulation in a tunable frequency range of 27 to 960 MHz. The maximum symbol rate is specified at 100 kbps, although I haven’t tested this yet. The cool thing is that it has a Output Data Serializer. The ODS takes a bit string as input and uses this to drive the radio. This allows complete freedom in the preamble, postamble and symbol encoding to use for the data. The module also has automatic antenna tuning, making the antenna choice less critical.

There is also a build in AES unit. Although I haven’t tested how fast it is.

Finally the micro controller accept a supply voltage in the range 1.8 to 3.6 Volt. This allows powering the chip directly from batteries. In standby the micro controller should use less then 10 nA. I wasn’t able to achieve this with the module I bought on eBay. When shut down it still uses 1 mA. This might be caused by the extra antenna circuit that the my module has. But I still have to investigate this.

Using the SI4010

When I received my SI4010 module I directly discovered a mayor problem. I had no way to actually load code into the micro controller. Silicon Laboratories offers a free for download proprietary IDE for this that only works on Windows and uses the  Keil compiler and their proprietary programmer device. But I want to use Linux and SDCC!

Luckily I was not the first to run into this and I found this programmer for the C8051F320 that also uses the Silicon Laboratories C2 protocol. After some tinkering I managed to modify the code to work with the SI4010. The original code uses a LPT port to interface with the C2 bus. But since my laptop lacks a LPT port I used a Cypress EZ-USB FX2 micro controller to perform this job.

All this tinkering finally resulted in a new program called si4010prog that can be used to load and debug a SI4010 micro controller. The source is available on github.

SDCC vs. Keil

Currently I am able to load program’s compiled with SDCC into the micro controller and run them. However I’m not yet able to utilize the build in ROM API of the SI4010. The API is specifically designed for the Keil compiler, and thus uses the Keil calling convention. As I understood this differs from the SDCC calling convention. To be able to use it in SDCC some sort of wrapper has to be build around the API functions. This is not ideal since it will require extra CODE memory when using SDCC.

So for now I’m still stuck with the Keil toolchain.

To Summarize

The SI4010 is definitely a interesting  platform for simple applications where a RF transmitter is needed.

To summarize the pro’s:

  • 8051 compatible but at 24 MHz 1 instruction per clock
  • Build in tunable RF module without restrictions on the data encoding
  • Build in AES module
  • Can be powered directly from batteries
  • In-system debugger


  • Limited amount of memory, and NVRAM only one time programmable
  • (Still) Requires Keil toolchain
  • No receiver, Can only transmit

Controlling the Wattcher Display

To measure the power consumption of my house I’m using a Wattcher. The Wattcher consists of two parts: A sender module and a Display. The communication between the two modules is wireless.

Currently I only use the sender, which I hooked up to a Raspberry Pi to get a much more accurate measurement and a historic log. So to keep in line with the whole sustainability concept of the Wattcher, I went looking for a way to reuse the display unit for a different purpose.

The Hardware

The main part of the Wattcher display is a 7-Segment display array that can display numbers between 0 and 10000. It also has a button to configure it and to request some calculated values.

Of course I wanted to know what was inside of the device so I tried opening it. This is rather hard because the two half’s are connected by pins that are glued. So my casing didn’t survive completely undamaged.

Wattcher Display PCB - front  Wattcher Display PCB - back

Inside there is a PIC microcontroller with a nRF905 RF module connected to it. The programming pin’s of the PIC are actually connected to some pad on which a connector can be soldered. Connecting my programmer showed that the chip is read protected.

The Communication

The easiest way to change the behaviour of the display would be to just reprogram the PIC microcontroller. But because the device is protected against reading the code memory, this would mean I will never be able to use the module in its original function again. So I looked for a less destructive approach.

The way the display is normally controlled is through RF, using the nRF905 chip. There are good data sheets available for the nRF905, and modules containing this chip can be bought very cheap on Ebay. So I decided to ordered some to play with.

The nRF905

After receiving the modules I hooked one up to my Raspberry PI and quickly found out that they where no good in controlling the Wattcher display. The Wattchers documentation states a carrier frequency of 868.4 MHz is used. However the modules I bought on Ebay have an antenna matching network that is specific to the 433 Mhz band. Luckily they weren’t completely useless. Because by having full control over one of these chips allowed me to write a frame receiver and decoder using software defined radio.

According to the Datasheet GFSK modulation with a +/- 50 kHz deviation. The bit rate is 100 Kbit/s. Using these parameters I made very simple GnuRadio project with just a GFSK demodulator in it that writes to file/FIFO. I thought this would be a bit to simplistic, but the output file actually showed signs of a manchester encoded signal.

nRF905 Demodulation GnuRadio

Next I converted the output bit stream to a VCD file for analyse in GTKWave. The bit stream outputted by GnuRadio has only one bit per byte, while my VCD file generator expects 8-bit per byte. For this I wrote a extra tool to pack the input stream. A voila, through the magic of shell pipes, I had a VCD file.

Using GTKWave and the documentation, I was able to determine the frame structure that the nRF905 module uses. The frames have the following structure:

| Preamble |   Address  |   Payload   |    CRC     |
| (10-bit) | (1-4 Byte) | (1-32 byte) | (0-2 byte) |


  • Preamble: The Preamble consist of a 10-bit value of 0x3f5. The preamble is also manchester encoded
  • Address: The address of the target node(s). Depending on the configuration can be 1, 2, 3 or 4 bytes
  • Payload: the payload data. Length depends on the configuration of the chip
  • CRC: The CRC calculated over the Address and Payload fields. This can be 16-bit, 8-bit or absent depending on the configuration. The 16-bit CRC is a CRC16-CCITT with start value of 0xffff. The 8-bit CRC I haven’t analysed.

All bits, including the preamble, are Manchester encoded. There is no inter-frame gap. So if the auto-retransmit function is used you’ll end up with one long bit stream. Interesting thing is that there seams to be no bit stuffing used. So if there is a value of 0x3f5 somewhere in the address, payload or CRC fields, there is noway to distinguish this from the preamble.

With this information I wrote a little tool to decode the nRF905 frames from the output of the GFSK demodulator. The decoder automatically tries to detect the frame length and CRC settings in use. The source can be found here.

As it normally goes, only after having figured this all out, I found out that there was already someone who did the same. See

Wattcher protocol

Using the nRF905 frame capturing I was able to analyse the protocol used by the Wattcher.

The Wattcher display and sender communicate in a Master-Slave fashion, where the display only sends a frame after receiving one from the sender. This is probably done because the sender is battery powered. Because the sender now only has to keep it’s receiver enabled for a very short time after having send a frame. The rest of the time it can completely power down the RF unit.

The Wattcher’s use the following nRF905 configuration:

Address Length 4
Payload length 16
CRC 16-bit
Address 0xaa61cc16
Sync/Pairing Address 0xc12cc21c

Normal mode

The payload of a packet send by the Wattcher sender contains the following information:

| 40 10 20 4a | aa 00 | ab | 00 | 00 75 96 | 00 0a | 00 00 00 |
|  Wattcher   |       |Vbat|    |  19-bit  | Disp. |          | 
| Virt. Addr. |       |    |    |  Counter | Value |          |

The nRF905 payload starts with a 32-bit ‘virtual’ address that couples a Sender module to a Display module. Then there are two fixed bytes. The 7th byte is a battery indicator, changing this causes a replace battery message to be displayed on the Wattcher display. Then there is a 19-bit counter which increases about 1’s per millisecond. It starts at 0 after sending a frame and is stopped when the sender receives a reply from the display unit. After this there is the value that will be displayed on the display.

When the display receives a frame from the sender it replies with the following message:

| 40 10 20 4a | a6 | 02 58 | 00 00 00 00 00 00 00 00 00 |
|  Wattcher   |    | Cval  |                            |
| Virt. Addr. |    |       |                            |

Again this starts with the Wattcher couple’s unique address. Apart from that the only useful information is the ‘C’ value as configured on the Display unit. The Sender uses this value to calculate the value to display from the amount of impulses registered by it’s sensor.

Sync mode

A Wattcher Display and a Sender are paired together by the 32-bit virtual address at the start of each frame. The Wattcher allows creating a new pairing by long pressing the red button on the Display and the Sender. When this is done the units will enter a sync mode.

In sync mode another nRF905 address, 0xc12cc21c, is used to distinguish the traffic from the normal traffic. Other than that nothing is changed to the nRF905 settings.

The sender will determine a new random virtual address for the pair. This is send in a frame with the following structure:

| c1 3a 11 4a | 1c | 00 00 00 00 00 00 00 00 00 00 00 |
|New Wattcher |    |                                  |
| Virt. Addr. |    |                                  |

The Display with answer with the following frame:

| c1 3a 11 4a | 2c | 00 00 00 00 00 00 00 00 00 00 00 |
|New Wattcher |    |                                  |
| Virt. Addr. |    |                                  |

Taking Over Control!

So now I can receive the traffic, but I wanted to control the Display unit!

As I mentioned above the nRF905 module I got from eBay was no good, because it’s matching network seemed to kill the RF signals in the 868 MHz band. I came to this conclusion because the Nordic nAN900-04 application note for the nRF905 describes a different matching network for the 868 MHz band then for the 433 MHz band.

A closer look at my module and the circuit diagrams of the application note showed that the matching network for the different bands only really differ in the values of the components. So I got the idea to just replace the components.

Although this does sound simple, it proved to be rather challenging. Mainly because: A) The components are rather small SMD component. and B) The values of the components are of such a small order that any parasitic capacitance introduced by bad soldering will have a relative large effect.

First attempt proved to be a failure. After sending one frame the sender would continue to oscillate until the module was completely powered down. Yeah, I’ve got a jamming device;).

The second attempt proved more successful. I’m now able to send working frames when using the module is ‘auto-retransmit’ mode for 10 Millisecond. That’s good enough for my purpose.

But even though I was able to send frames and receive them with my SDR setup. I wasn’t able to control the Wattcher display. This was caused by the nRF905 module being tuned at a offset of about 100 kHz of the requested frequency. When I started looking into replacing the crystal for a better one, I found that the Cl value of 12 pF specified in the reference design was actually very hard to get. I assumed that the makers of this cheap module would also have run into this problem and just used some common crystal. While using a crystal with another Cl, they apparently didn’t update the values of the C1 and C2 capacitors. This would explain the fixed tuning offset.

Guessing the Cl was actually the much more common value of 16 pF. I calculated, using the formula in the datasheet, that the capacitors should be 33 pF. And so I finally took over:

Leet Wattcher

Doing Something Useful

Ok, now I can display a number… but what shall I do with this tremendous power. As it happens I was already playing around with a DHT22 Temperature/Humidity sensor. So I wrote some code to combine all of this on a Raspberry Pi. And now I have an exclusive, designer, temperature display!

Raspberry Pi + nRF905

The picture above shows my setup. Note the crappy soldered SMD components between the antenna and the nRF905, which is the replaced matching network

The source code of all tools I used is available on github: nrf905_stuff and generic radio stuff

Somfy + RTL SDR

I’ve finally managed to capture some Somfy RTS frames using a RTL2838 based DVB-T dongle. By demodulating the signal using rtl_fm in AM mode and feeding the output through a simple threshold detector, the binary data can be obtained.

rtl_fm -M am -f 433.42M -s 270K | ./am_to_ook -d 10 -t 2000 -  | ./decode_somfy

During testing at first I only managed to receive one of my remotes. Taking a look with GQRX quickly showed the problem. Seems like the crystal in the other remote isn’t very accurate causing it to send on a slightly higher frequency of about 433.5 MHz. Given the low sample rate of 27 KHz I was using, the signal fell outside the tuned range. Increasing the sample rate fixed this.

All tools are now available from github.

Waterfall Plot showing button presses of three different remotes

Waterfall Plot showing button presses of three different remotes

Reversing Somfy RTS

somfy smoove origin RTS

Some time ago we got new motorized blinds at my office which are controlled by a small wireless remote control. This made me curious how these remotes actually work, and if I would be able to control the blinds from a PC.

In this post I’ll explain the process of reverse engineering the protocol. For a detailed explanation of the protocol it self see here.

Capturing the communication

The remotes are of the type Somfy Smoove Origin RTS. Some searching revealed that RTS stands for “Radio Technology Somfy” and is a proprietary system. It uses an OOK(/ASK) modulated signal on 433.42 Mhz.

This was very convenient since I already had a microcontroller with an Aurel RX-4M50RR30SF 433.92 Mhz OOK receiver attached laying around from an other project. Although the frequency’s don’t exactly match, the receiver is able to pick up the signal if the remote is within ~10 meters. The microcontroller, a Cypress EZ-USB FX2, was running a very simple program that samples the data output from the RF receiver every 35 us and forward it to my PC through USB.

With this setup I created traces of different button presses; 4 times ‘up’, 4 times ‘down’ and so on.

Analysing traces

The trace files are just a big bunch of 1’s and 0’s, not very readable. So I searched for a way to plot the traces.

I started of using GnuPlot. Although very cumbersome and time consuming, I was able to get some useful images out of it. Later I converted my trace files to VCD files and used GTKWave. GTKWave isn’t very user friendly either, but it works a lot better then GnuPlot, especially with longer traces.

The image below shows 4 traces of pressing the same button. The frames are clearly visible and it is pretty obvious that there is a preamble at the start of the frame.

GTKWave showing 4 traces of Somfy RTS frames

GTKWave showing 4 traces of Somfy RTS frames

The next image is a close up of the data. One thing I noticed when looking at the differences between traces is that there is always one point where all traces change state, followed by a point where only some or none of the traces changes state. I highlighted this in the image below, red always changes, blue sometimes. This suggests that the actual data bits are encoded in the edge at the point where the signal always changes state. One obvious encoding that springs to mind when seeing this is Manchester encoding.

Somfy RTS traces close up - annotated

Close up of Somfy RTS data. On the red markers the signal level always changes, on the blue only sometimes

Payload Data

Now I knew how the data was modulated, framed and encoded I could actually analyse the frame payload data. As always when reverse engineering I started by making a list of data fields I would expect to be in the protocol and then started comparing the frames from the different traces.

This directly showed that pressing the same button multiple times resulted in different data. Suggesting that the protocol is not static, but uses some kind of rolling code/sequence number. Comparing the traces of two different buttons shows that the upper nibble of the second byte is probably the button code.

Looking at the bytes that change with every button press I noticed that some actually behave as counters that constantly increase by 1, but with some bits flipped. So I assumed that there was some sort of XOR based obfuscation going on. Using these counters I started XOR’ing nibbles together, till the counters increased as expected. This finally brought me at a point where I was able to predict the data multiple frames ahead of the current frame. But it wasn’t perfect.


With all the information gathered so far I went back to Google and stumbled upon US Patent 8,189,620 B 2. Skimming through it I found an image of the frame structure I already determined. Hmmm… interesting! Reading further I found that this patent almost completely describes the RTS protocol. With this new information I was able to determine the obfuscation algorithm used.

An other interesting patent I found was US 7860481 B2. But that one doesn’t describe the payload data.

Taking over control!

Now I could decode the protocol I went on to write a program to actually send out my own frames. Given a captured address, rolling code and ‘encryption key’ I was indeed able to control the blinds. Victory!

To transmit I use a Aurel TX-SAW-MID 5v transmitter hand soldered on an experiment board. The antenna attached is a home-brew 1/4 lambda antenna with 4 radials. I was told this antenna design should sort of match the output impedance of the transmitter, although I’ve got no tools to test this.

With this setup I was able to control the blinds at about 5 meter distance, with a wall/coated window in between. This isn’t very impressive, although expectable given that I’m transmitting at 0.5 MHz above the centre frequency of the receiver. And all soldering and wiring is suboptimal. The actual range also depends on the blinds. One of them I wasn’t able to control at all, even when standing next to it.

One problem was that if I controlled the blinds with my program, the rolling code would advance. This caused the original remote to become out of sync. Luckily the blinds allow multiple remotes to be bound to it. This way I could create a virtual remote with my program with its own rolling code.


When I started of I didn’t expect this to be secure in any way. The requirements on security probably aren’t very high for these systems, since some attacker controlling my blinds would just be very annoying. But it is actually better then I anticipated(as in just replaying a frame doesn’t work).

Obviously the ‘encryption’ doesn’t offer any protection. Even if the algorithm would have been strong, only 4 bits of the 8-bit ‘key’ actually change(in a predictable manner…). And the ‘key’ is send with the frame in the clear.

So what about the rolling code? Well it is 16-bit, so there is a chance of 1 out of 65535 that you guess the next value of the code. But if the receiver only accepted the next value of the rolling code as valid and the remote is out of range, one button press would mean that receiver and remote will be out of sync. To prevent this the receiver uses a window in which the rolling code must fall. This size of this window is somewhere in the order of ~100. So this would give a chance of 1 in 655 to guess a working rolling code, or not? Somfy actually did something clever here, because the receiver seems to shrink the window every time it receives an incorrect rolling code! So in worst case you still have to try 65535 codes.

An important thing to note is that the rolling code is sequential and starts at 0. So especially for new systems it is relatively easy to predict/calculate an approximation of the rolling code using the usage frequency + age of the system. Also the address isn’t a random number, but seems to be assigned sequentially. So given the age of the system, or the address of an other remote in the system you might be able to greatly reduce the address space to search.