In the last part, we looked at sniffing the SPI traffic between the Elan microprocessor and CC1150 RF chip in a door contact from a Friedland Response alarm system. We worked out which pin was which, and interpreted some of the SPI traffic to check our assumptions were correct.
Part of my general philosophy when reverse engineering products is to just get a good idea of what is going on, rather than rigorously explore each and every avenue. Generally this will give you an overall picture of the system far quicker, and allow you to identify weak points to look at in more detail. So, on the whole, I never have a 100% confidence level in my assumptions.
Let’s look at some other aspects of the sniffed traffic.
First, let’s look right at the beginning of the signals immediately after the sensor is triggered.
We have worked out what channel 0, 3, 4 and 5 do. So what is going on with channel 1? It has an approximate 135kHz clock signal for a short period. Why is this?
Let’s go and look at the datasheet once again. Page 37 – we can see that general purpose I/O pin GDO0 defaults to output a 125-146kHz clock output – the main oscillator frequency over 192. We have a 26MHz crystal, giving us 135.4kHz – exactly as observed.
Why then does it stop suddenly. Maybe one of the registers we set just prior to it turning off – 0x01 or 0x02 – control this pin?
IOCFG0, 0x02, controls GDO0. The lowest 6 bits select what GDO0 should output. What does 0x0C correspond to? Page 38, table 24, shows 0x0C as “Reserved – defined on the transceiver version” – what’s going on here then? Is it a mistake? We’ll come back to this later.
Again, this is something that is really key in reverse engineering – read the datasheets, and read the manuals. They are full of useful information.
Moving further through the SPI packets sent, we get to the end:
Time [s] | Packet ID | MOSI | MISO |
0.0041055 | 28 | 0x2D | 0x0F |
0.00417875 | 28 | 0x35 | 0x0F |
0.00424825 | 29 | 0x2E | 0x0F |
0.0043215 | 29 | 0x09 | 0x0F |
0.00438775 | 30 | 0x7E | 0x0F |
0.004463 | 30 | 0x00 | 0x0F |
0.00451425 | 30 | 0x0B | 0x0F |
0.00456675 | 30 | 0x25 | 0x0F |
0.0046195 | 30 | 0x68 | 0x0F |
0.00467225 | 30 | 0x60 | 0x0F |
0.004725 | 30 | 0x86 | 0x0F |
0.0047775 | 30 | 0xCC | 0x0F |
0.00483075 | 30 | 0xC3 | 0x0F |
0.0049125 | 31 | 0x35 | 0x0F |
0.01802275 | 32 | 0x36 | 0x2F |
Why is packet 30 so long? 9 bytes instead of 1 or 2 as per the previous strobe commands and register writes.
Address 0x7E doesn’t seem to come up directly in the datasheet. If we refer to Table 28 though, we see that if we want to write to 0x3E in burst mode, we need to add 0x40 onto the address. Burst mode allows us to write multiple values in one go without incrementing the address. 0x3E is the PATABLE or power table, allowing the power of the radio signal to be modulated.
Let’s zoom right back out on the logic trace:
The small white blocks are bursts of SPI traffic as we have looked at already. What about the huge white blocks – let’s zoom in to take a look at them.
That looks like synchronous serial data to me with a clock on channel 3 and data on channel 1. Let’s scroll backwards to examine the SPI transfer immediately prior to this to see how the CC1150 is being configured.
We’ll start from the beginning and manually interpret the commands (I might skip or gloss a few of the really unimportant ones)
- Strobe command SRES – reset the chip
- IOCFG1 – GDO1 output pin configuration – set to 0x0B – Set GDO1 to “Serial Clock. Synchronous to the data in synchronous serial mode.“
- IOCFG0 – GDO0 output pin configuration – set to 0x0C – Reserved in the datasheet as it is for the transceiver, CC1101, only. If we look there it means “Serial Synchronous Data Output. Used for synchronous serial mode” So far it looks like these are being setup for some kind of synchronous serial data transfer.
- SYNC1, SYNC0 – sync word – set to 0xD391. The sync word is a bit pattern that receivers can look out for, in a way people listen out for their name. Oddly, 0xD391 is the default used in the TI software (SmartRF Studio) and code examples. Keeping it as default would likely cause problems in a busy environment (these chips are becoming very common), so this might indicate they are not using the packet control built into the chip.
- PKTLEN – packet length – set to 0xFF. This is the maximum – 255 packets. It can mean one of three things – fixed packets 255 long, variable length packets up to 255 long, or don’t use the packet control at all. Another sign they might not be using packet control!
- PKTCTRL0 – Packet automation control – set to 0x12. this is made up of a number of smaller settings:
- WHITE_DATA – data whitening – set to off.
- PKT_FORMAT – set to 0b01 – “Serial Synchronous mode, data in on GDO0“.
- CRC_EN – enable CRC – set to off.
- LENGTH_CONFIG – set to 0b10 – “Infinite packet length packets” – again, bypassing the built in packet control
- ADDR – address – set to 0x00. This can be used to filter packets down.
- CHANNR – channel number – set to 0x00. A neat feature of the CC11xx chips is being able to use a number of channels – offsets from the frequency. This can be used for frequency hopping spread spectrum. Not used here though.
- FREQ2, FREQ1, FREQ0 – frequency control – set to 0x21656a. This equates to 868,299,865kHz. As the channel is set to 0x00, this will be the frequency used.
- MDMCFG4, MDMCFG3 – modulator configuration, data rate – set to 0x87, 0xF8. This is calculated in a similar way to the frequency using an exponent and mantissa, and gives us 6.24847kBaud. If we look up to MISO/GDO1 in the screenshot above – the clock is showing as 6.25kHz. It’s all starting to come together.
- MDMCFG2, MDMCFG1, MDMCFG0 – modulator configuration, various. We can see:
- MOD_FORMAT – modulation – set to 0b000 – 2-FSK.
- SYNC_MODE – synchronisation mode – set to 0b000 – “No preamble/sync word”. This means that the system is not using any of the inbuilt packet control. The microprocessor must deal with pre-amble, sync word and so on.
- NUM_PREAMBLE – number of preamble bytes sent. This is set to 4, but because the SYNC_MODE is set to use no preamble, it is ignored.
- CHANSPC – channel spacing. If the system was using multiple channels, this decides how far apart they are. This system isn’t so we’ll ignore this.
- MCSM1, MCSM0 – main radio control state machine config. I’m not going to look in here as it’s unlikely to change how the data is handled.
- FREND0 – front end TX config. Going to skip this for now.
- FSCAL4, FSCAL3, FSCAL2, FSCAL1, FSCAL0 – again, RF related and we can skip.
- FSTEST, PTEST, TEST2, TEST1, TEST0 – various test settings. These are usually defaulted, not explained or shouldn’t be set. Let’s keep it that way.
Immediately after this, the STX strobe command is issued, along with setting IOCFG1 and IOCFG0 again. The SPI stops, GDO0 becomes a clock at 6.5kBaud, and MOSI starts showing data. I don’t know which direction this data and clock are going in, but we can have a good guess.
It looks like the CC1150 is in a mode where it will accept synchronous serial data, generating a clock for the microprocessor to use. Pre-amble, sync, packet length and other features are implemented in the microprocessor. This is an interesting revelation – a huge advantage of the CC11xx chips is the automated packet control, and it has been thrown aside.
Why would this be done? We can only speculate. Asynchronous serial mode is often used by devices when the CC1150 is interfaced to legacy microprocessors – you can just send it raw data and it only does the RF side of things. Ancient 434MHz systems using AM OOK modulation can be changed into narrowband 868MHz products using 2-FSK easily.
Synchronous serial is a bit different – the microprocessor needs to listen to a clock and clock data out. Whilst this is trivial to implement afresh, it doesn’t really fit in with the idea of supporting a legacy application. Maybe Friedland used to use another module that used a similar data exchange.
Decoding an RF packet in a microprocessor isn’t hugely challenging (VirtualWire on the Arduino is a nice example, well implemented), but I have seen numerous systems with quirks and bugs in the packet handling. It’s sometimes even possible to crash receivers using malformed packets.
Now we know how the CC1150 is accepting data – so now we need to try and interpret that data. Next time!