Having the firmware image to decompile allowed me to find the settings for the radio. How close was I?
I had guessed that they may well be using the STM SPIRIT1 library and after some looking I found that this was the case. It took a little while but eventually I found the data structures thet would let me know how the radio should be configured.
This is defined in the SPIRIT_Radio.h header for the library.
The structure is passed to the init function for the radio.
uint8_t SpiritRadioInit(SRadioInit* pxSRadioInitStruct);
Finding the function did take some looking but by working backwars from the SPI references I was able to find the functions that interacted with the Spirit radio and from there found the SpiritRadioInit function. In fact I found two of them!
It turns out there are 2 seperate sets of setup routines for the radio, each with their own init structures.
The spacer0 and spacer1 fields were needed as the alignment wasn't correct without them, so I guess the compiler has aligned things?
The frequency is 868200000 - exactly what I had settled on using. The data rate is also an exact match at 50,000.
I had the modulation as GFSK_BT1 so I was close :-)
Having found the basic radio setup, next I wanted to find the settings for the packets. I had guessed these would be Basic and so I should be looking for a PktBasicInit structure.
Again, this is used by the init function. Once I had the SPI calls it was possible to work backwards and again find the function.
void SpiritPktBasicInit(PktBasicInit* pxPktBasicInit);
This led to the discovery of 2 init structures.
Again I found that the byte alignment wasn't an exact match and the decompiled code expected the spacer bytes to be present.
Here I found there were quite a few things I had got wrong. The 3 byte CRC was a surprise and the FEC being nabled wasn't something I had considered. Also the use of an address field with 4 bytes of control data wasn't something I had correctly detected.
After making the changes to the radio and some slight updates to the module and test script, I grabbed some more packets.
All the messages are 19 bytes and all come from the same address, 0xff. The control bytes all have a very consistent pattern.
As we have 3 devices, each could relate to one and so the first number may actually be an device id? The third number appears to be a counter that wraps at 0x3F.
The 19 byte content is a little strangely sized. There is a lot of reference in the decompilation to AES like functionality, including a seeming key generation. The code appears to work on 16 byte blocks, which makes sense for AES so perhaps the CRC bytes are still attached and the messages are 16 bytes of payload plus 3 bytes of CRC?
The decompiled code is labyrinthal as it deals with button presses, LCD, networking and also tries to sleep as much as possible to preserve batteries. Some avenues of discovery work well and I have found a lot of the HAL library code which has allowed me to gain insights into what is being done, but much of the remaining code remains a list of maths operations on seemingly random addresses. It's impressive just how quickly it all starts to make sense with the appropriate structures added and referenced, but without an external reference it's a case of deductions.
I'm also conscious that my aim isn't to fully reverse engineer the firmware for the device, just try and understand the networking such that I can replicate it without the device. Sadly things appear more interwoven than I would have liked.
If anyone has suggestions for places to find help and strategies to use to speed things up then I'd love to hear from you :-)