The Sigfox radio protocol

Sigfox phase decoding

Sigfox is a LPWAn communication technology and network dedicated to IoT. The specificity of this solution is related to the LPWAn caracteristics : communicating Low Power (25mW) and Wide Area (60km).

This is possible thanks to particular radio characteristics and modulation. This post will describes how it works at radio level and protocol level.

Bit encoding (Updated)

From the RSA Tools I’ve seen the encoding as a BPSK is Binary Phase Shift-Keying. It’s not still clear why the tool report phase change with this encoding and I hope I’ll soon clarify this point with Sigfox. By-the-way understanding BPSK helps to understand the next part. It means the signal phase is determining the Bit value (0 or 1)

BPSK bit radio encoding

The receiver job is to determine a reference for the phase and identify the phase change to identify the bit switching. There is no way when listening to identify what is a 0 and what is a 1 at this point.

According to different documentation the Sigfox modulation is DBPSK for Differential Binary Phase Shift-Keying. In this modulation we also use the phase to encode 0 and 1 but instead of using the phase for this we use the phase change. That way we do not need a reference of phase to identify a 1 vs a 0.

DBPSK 0 / 1 encoding

In the above example the 1 is identify by no change in the signal phase when the 0 is identify by a phase change during the transmission. This is the way Sigfox is encoding the information on the radio medium. That said there is a big difference between Sigfox encoding and this animation : In the animation is encoding 1 different bit per signal period. At 868MHz it means 868Mb / s … As you may know Sigfox is far away from this bitrate and basically a such encoding would have been really difficult to decode even in a short range.

The Sigfox DBPSK encoding is based on a suite of signal period : when all have the same phase the bit value is a 1, if the phase change in the middle of the time slot the bit value is a 0. That way the receiver is less impacted by local phase variation.

DBPSK 0 / 1 encoding

In the Sigfox case the bitrate is 100 bit / second and the radio signal is 868.1MHz. It means that each transmitted bit will correspond to 8 681 000 consecutive cycles. The receiver will use this large number of phase to statistically find the phase shift for the corresponding bit.

Sigfox DBPSK communication

The above animation shows a 1 encoded with 8.68M periods encoded the same phase and a 4.34 + 4.34 periods encoded with a phase shift in the middle, representing a 0.

In this above example the phase shift is executed with a full signal amplitude (and power) this would impact the spectral occupation the wrong way. To avoid it the Sigfox signal is modulating the amplitude during the phase change like in the following animation.

Sigfox amplitude modulation at phase change

Frame encoding

The Sigfox Frame format is the following (according to my reverse engineering and some other Internet post)

Each of the Cells represent a Quartet (4 bits)

F.SYNC

The F.SYNC part is the Frame Synchronization part. This is the beginning of the communication. The transmission is a suite of 0 and 1 (encoded “A” – 1010 for each quartet). This is allowing the receiver to synchronize it’s clock to correctly find the beginning of each of the bits. We have at least 6 phase alternation to make this synchronization.

The End of the synchronization is made when the pattern change from 01 to 00 or 11 depending of the type of frame. This end of synchronization depends on the F.TYPE.

F.TYPE

The F.TYPE part is the Frame Type part. It depends on two things : the size of the Payload and the repetition (each of the frame is repeated 3 times on Sigfox network).

As I only did reverse engineering it is possible that my description is not exact. Basically I was expecting bit fields for repeat and another for Frame Size but I did not. So I found constants:

Message Size F.TYPE Repeat1 F.TYPE Repeat2 F.TYPE Repeat3
12 Bytes 0x94C 0x971 0x997
08 Bytes 0x611 0x6BF 0x72C
04 Bytes 0x35F 0x598 0x5A3
01 Byte 0x08D 0x0D2 0x302
1 bit 0x06B 0x6E0 0x034
RX OOB 0xF67

F.FLAGS

The F.FLAGS contains different zone :

  • The two first bits (BB) indicates the number of Bytes added into the frame to complete the message up-to the frame size. As an example, if you send a 6 byte message, it will be sent in a  8 bytes message frame. Your 6 bytes will be completed by 2 extra Bytes. The BB field will contains the value 2 (10) to indicate this.
  • The third bit (D) is indicating if a downlink is requested as a response to this frame. When the bit is set to 1 the network will eventually respond with a downlink.
  • The last bit seems to always be 0.

SEQ.ID

The SEQuence ID field contains the 12bits (3 quartet) frame counter. Also named Sequence Number in the Sigfox API and callback. This number is incremented after each frame transmission. This way you can’t emit a previously recorded message without a detection by the Sigfox backend.  (I mean until the next 4096 messages)

The bits are in the frame order : highest bit comes first.

DEVICE.ID

The DEVICE ID field is the 32 bits unique Sigfox device ID. The Bytes are ordered starting by the less significant one. Each Byte is encorded highest bit comes first. As an example the device 000FAFDC will be encoded:

D C A F 0 F 0 0

PAYLOAD

The payload contains the data transmitted. There is no specific processing for the payload (for repeat 1) you can see the data in “clear text”. This not means you can understand them as, due to the small size of the frame, the information is compressed and not directly readable by a human. It means you need to know the context to be able to understand it.  This field can by 12 Bytes, 8 Bytes or 4 Bytes long. The data are in the same order used for the transmission : Byte 0 comes first. For each of the byte, highest bit comes first.

HMAC

The HMAC fields contains the HMAC signature corresponding to this frame. A HMAC is a hash computed from a private key. Each of the Sigfox devices have it’s own private and secrete key burn in the hardware. Only Sigfox know it and is able to verify the signature. A frame is valid only if the HMAC signature is valid otherwise it is rejected.

It means you can’t forge your own frame if you do not have this key. To have the key, you need to have the hardware, open it, and plug a debug equipment on it (that said, forging a frame in such conditions is just for labo demonstration, not for real attack)

The key is a 16byte key.

A public Key can be used for some of the tools provided by sigfox and certification. The public key is 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff – A sensor using a public key will be rejected by the network. This is a way during hardware test to not pollute the network.

I do not have details but I assume the signature is covering the entire frame up-to the CRC field.

CRC

The end of the frame is a 16bits CRC to validate the transmission of the whole frame.

Replicate specific encoding

During a transmission of data the frame is transmitted 3 times. The network to not transmit exactly the same information 3 times. The First Repeat (first transmission) is not encoded the bytes are directly readable.

The second repeat is encoded in a specific way, thanks to this encoding the phase switching will be totally different from the first transmission. I assume this is helping the receiver to extract the information more easily in strong noise conditions. At end of this post you will find the algorithm to be used for encode/decode the information. The function is not to apply to the whole frame but only the F.TYPE, SEQ.ID, DEVICE.ID and PAYLOAD part (at least) separately.

Basically for the second repeat, the bit value depends on the previous two bit values : when not identical the current bit is switched.

The third repeat is encoded the same way but using a different algorithm. Basically depends on the previous two bits, each of them indicates is the current bit and the next one have to be switched or not.

RX OOB Frame format

After receiving a downlink, the device is responding with an OOB Frame containing informations like Voltage, Temperature and Reception Level (Rx Rssi).

Sigfox Rx OOB frame format

The frame is a 8 byte frame with a specific F.TYPE (see above). There is no repeat for this frame (for this reason a lot of them are lost). It contains different fields in the payload:

  • Voltage in Idle : 16 bits little endian mV value – 3300 = 3.3V
  • Voltage in Transmission : 16 bits little endian mV value – 3290= 3.29V
  • Temperature : 16 bits little endian c°C value – 152 = 15.2°C
  • Delta RssI from -100dB : 8 bits value – 10 = -100 + 10 = -90dB

Annexe

Replica 2 byte encoding

Depends on previous 2 bit decide to switch or keep the current bit value. The previous 2 bits are initialized at 0 before starting to encode.

var encodeR2 = function( w, encode ) {
 var b2=0;
 var b1=0;
 for ( var j = 0 ; j < w.length ; j++ ) {
   var n=w[j];
   var v=0;
   for ( var i=0 ; i < 8 ; i++ ) {
    var b0=(n&128)>>7;
    v += ( b2 == b1 )? b0:(1-b0);
    b2 = b1;
    b1 = (encode)?b0:v&1;
    n = n << 1;
    v = v << 1;
   }
   v >>= 1;
   w[j] = v;
   console.log(w[j].toString(16));
  }
}
console.log("Encode for network");
encodeR2([0x2A, 0x65, 0x43, 0x21], true);
console.log("Decode from network");
encodeR2([0x35, 0xCE, 0xB2, 0x79],false);

Replica 3 byte encoding

Depends on previous 2 bit decide to switch or keep the current two bits value. Each of the two previous bits are deciding for each of the current 2 bits. The previous bits are initialized at 0 before starting to encode.

var encodeR3 = function( w, encode ) {
 var b2=0;
 var b1=0;
 for ( var j = 0 ; j < w.length ; j++ ) { 
   var n=w[j];
   var v=0;
   for ( var i=0 ; i < 8 ; i+=2 ) {
     var b00=(n&128)>>7;
     var b01=(n&64)>>6; 
     v += (b2==0)?b00:(1-b00);
     v = v << 1;
     v += (b1==0)?b01:(1-b01);
     b2 = (encode)?b00:(v&2)>>1;
     b1 = (encode)?b01:(v&1);
     v = v << 1;
     n = n << 2;
   }
   v >>= 1;
   w[j] = v;
   console.log(w[j].toString(16));
  }
}

console.log("Encode R3");
encodeR3([0x2A, 0x65, 0x43, 0x21], true);
console.log("Decode R3");
encodeR3([0x20, 0xFC, 0x13, 0xE9],false);

18 thoughts on “The Sigfox radio protocol

  1. WOW, highly detailed information. Some aditions to the post:
    * The modulation is DBPSK, Diferential Binary Phase Shift-Keying. Binary because there are only two symbols, 0º and 180º and Differential because there is not a direct relation between bits and symbols, but a relation between bits and symbol change (0: change phase, 1: keep phase).
    * Apart from phase modulation, there is a “amplitude modulation” as well. Whenever there is a phase change, there is an amplitude ramp-down and ramp-up to reduce the spectral occupation.
    * There are extra symbols at the begining and the end of the frame.
    * As I understood, the Sigfox header was 14bytes long, your example is 13bytes long.
    * The payload field is a container of 0, 4, 8 or 12bytes length, if you you want to transmit a 10byte frame, the 12byte container will be used and two bytes will be wasted.
    * There is not a Frame Size field, so I asume the F.TYPE table is more extensive, covering all possible Frame Size values (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).
    * The shortest Sigfox frame is a single data bit. In this case a 0byte container is used and I asume the bit value is located in F.FLAGS

    More resources here:
    https://storage.sbg1.cloud.ovh.net/v1/AUTH_669d7dfced0b44518cb186841d7cbd75/staging_docs/att14425021-PRS_UNB_MODEM_RC1_UDL_ENC.pdf
    At the end of the document there are examples of how to achieve DBPSK modulation for unsupported transceivers using Continuous Wave or 4GFSK Modulation.

    • Thank you Nestor for these precision. I’ll investigate and complete my post according to your new informations.
      About the DBPSK it is also what I was expecting, but when I did the decoding manually from the RSA tool I’ve a BPSK encoding and not a DBPSK encoding. As the information on this topic are changing from a source to another I kept what I’ve seen. The document you are sharing looks more official than most of my source so I thing we can trust you 😉
      Now my question is Why the RSA tool does not provide the same elements ?

      Regarding the synchronization header, it seems to vary depending on the frame type as the bit > 12 vary, in some case they still 10101 in some other not (this is a strange part making the mystery more and more interesting to investigate) 😉

  2. Dear Paul ;
    could you please explain more about the algorithm of third repetition? I could understand how it is encoding the bits.
    regards

    • I’m sorry for this but as you have the algo and you can reproduce you may be able to get the information. I’ve already done my best to find the algo you need to do the rest.

  3. hello paul
    do you have more information about HMAC? do you have its hash function? how can we get more information about it?
    regards

    • HMAC and CRC are standard things. I did not inestigate more on it as you can find a lot of documentation asking Google

  4. Dear Paul ;
    thanks for all of your great information about sigfox protocol. do you have any information about downlink frame format? and how we can get it by using the sigfox network emulator or sigfox analyzer?

  5. Hi Paul,

    https://assets.tue.nl/fileadmin/content/faculteiten/ee/Onderzoek/Technologische_centra/Centre_for_Wireless_Technology/CWTe_2016_RR_SIGFOX-Mallart-IoTSolutions.pdf

    In this presentation, page 22, you can see the frame structure, the frame overhead is 14 bytes.
    We can see what fields are used for CRC and HMAC calculation respectively.
    And as you discovered, the payload length is a function of LG and FS fields.
    I don’t know why the HMAC field has variable length 16 to 40 bits.

      • i checked the CRC part. it is from the begining of the frame. i am confused now why in this codument mentioned it is from the LG part!!!!

  6. Hi, this a lot of very useful information. Tank you!
    Can I have a question? How are you demodulating the signal? I mean are you using SDR? What software are you using to read the actual bits from the signal? I’m trying to to receive Sigfox messages on my computer using RTL-SDR and GNU Radio but so far without luck Maybe seeing how you do it could help me. Let me know please 🙂

  7. Pingback: How to transfer pictures over Sigfox network ? - disk91.com - technology blogdisk91.com – technology blog

  8. Pingback: LIbrenard is out - Open Source Sigfox stack implementation - disk91.com - technology blogdisk91.com – technology blog

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.