Helper functions for bit parsing

92 views
Skip to first unread message

md

unread,
Jun 10, 2024, 4:49:10 PMJun 10
to rtl_433
In my previous question https://groups.google.com/g/rtl_433/c/vouhWWwj-kE I asked about specifics for a flex
 decoder. However the same day I sat down and wrote a "proper" decoder/device for rtl_433 in C and put it under src/devices.

I used one of the existing files and adapted it to my needs and it works very well.

Some things though were not clear to me:

a) As discussed in the above thread: How can I put multiple messages into one decoding? I understand a bitbuffer_t consists of multiple rows. I presume that's exactly what I want: I then want to check if the same message is at least present in e.g. 3 of the rows.
I think the proper functions for this is "bitbuffer_find_repeated_row()" - but how do I get multiple rows into bitbuffer_t in the first step?

b) The individual symbols in my message consist of 6 bit pairs not 8 bit. However all the helper functions only seem to output hex strings of the bitbuffer which are of course based on 8 bit values. (e.g. bitbuffer_print())

What I did was to turn all the 8 byte values into 1 bitstream via some calculations:

for (int rownum=0; rownum<bitbuffer->num_rows; rownum++) {
int row_len = bitbuffer->bits_per_row[rownum];
 
if (row_len != row_length_expected)
return DECODE_ABORT_LENGTH;
        b = bitbuffer->bb[rownum];

// Create a bit stream representation
uint8_t bits[row_length_expected];
uint8_t bitpos = 0;

        for (bitpos = 0; bitpos < row_len; ++bitpos) {
            if (b[bitpos / 8] & (0x80 >> (bitpos % 8))) {
                bits[bitpos] = 1;
            }
            else {
                bits[bitpos] = 0;
    }
        }
...
and then I parse 6 bits at a time from this "bits" array:

// Dissect 10 x 6 bits from bit stream
for (int pos=0; pos<60; pos+=6)
{
int dip = 0;
dip = dip + bits[pos]*(1<<5) + bits[pos+1]*(1<<4) + bits[pos+2]*(1<<3) + bits[pos+3]*(1<<2) + bits[pos+4]*(1<<1) + bits[pos+5]*(1<<0);
dips[pos/6] = ((enum SwitchPos) dip) == PLUS ? '+' : ((enum SwitchPos) dip) == ZERO ? '0' : '-';
// printf("Dippos %d: %s, ", dippos++, ((enum SwitchPos) dip) == PLUS ? "+" : ((enum SwitchPos) dip) == ZERO ? "0" : "-");
}

Am I missing something? Is there a simpler way to do this?



Christian Z.

unread,
Jun 10, 2024, 5:01:22 PMJun 10
to rtl_433
Exceeding the "gap_limit" will break into a new row, exceeding the "reset_limit" will end the slicing and pass the bitbuffer to the decoder.
The limits can be too long, the slicer will abort on too much of a gap anyway.

md

unread,
Jun 10, 2024, 5:11:33 PMJun 10
to rtl_433
Could you have a look a the uploaded signal from the post references in my first message here? Would a spacing between the 2 repetitions of 10000 be too much of a gap? 

If my messages are separated by a 10000 gap and otherwise there are no "gaps" (MESSAGEA<gap of 10000>MESSAGEB), would specifying a gap of e.g. 5000 then do what i want or would the 2nd row start with a 5000 gap again? 

Christian Z.

unread,
Jun 11, 2024, 4:29:42 AMJun 11
to rtl_433
Your longest expected gap is ~880 µs. Set gap_limit to 1000. Try reset_limit 11000, but 10+ ms is quiet a long time to capture with rows.

Christian Z.

unread,
Jun 11, 2024, 4:39:37 AMJun 11
to rtl_433
Re decoding:
Looking at your basic PCM 360 µs symbols you have:

100 100 [+]
101 100 [0]
101 101 [-]

There are provision for a flex decoder to match complex symbols, i.e. use

symbol_one={3}4,
symbol_zero={3}5,

to decode the 3-bit pattern above.

But that looks odd for a protocol. Actually you don't have raw PCM bits in fixed time slices, you have binary PWM -- you only care if a pulse is short or long, the gaps don't encode data. I.e.

m=OOK_PWM,
s=360,
long=770,

Now you already get decoded 2 bit per DIP switch.
Further encoding could be ternary (0 /1 /Z /X) but that's not clear and not really needed to read data.

md

unread,
Jun 11, 2024, 4:35:44 PMJun 11
to rtl_433
Using your suggested values now indeed gives 2 rows, but the second row just consists of 0/nothing for every key press seen

src/rtl_433 -r ~/g011_433.92M_1000k.cu8 -X "n=dick,m=OOK_PCM,s=365,long=365,g=1000,reset=11000"
rtl_433 version 23.11-130-gf23b80f7 branch master at 202406081256 inputs file rtl_tcp RTL-SDR with TLS
Reading conf from "/home/daubsi/.config/rtl_433/rtl_433.conf".
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : 2024-06-11 22:29:29.259878
model     : dick         count     : 2             num_rows  : 2             rows      :
len       : 111          data      : 924b2d924b6db24b2cb2cb6cb2c8,
len       : 0            data      :
codes     : {111}924b2d924b6db24b2cb2cb6cb2c8, {0}0
Modulation: ASK          Freq      : 433.9 MHz
RSSI      : -0.4 dB      SNR       : 40.2 dB       Noise     : -40.6 dB
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : 2024-06-11 22:29:29.349766
model     : dick         count     : 2             num_rows  : 2             rows      :
len       : 111          data      : 924b2d924b6db24b2cb2cb6cb2c8,
len       : 0            data      :
codes     : {111}924b2d924b6db24b2cb2cb6cb2c8, {0}0
Modulation: ASK          Freq      : 433.9 MHz
RSSI      : -0.4 dB      SNR       : 40.9 dB       Noise     : -41.2 dB


Could you please elaborate how you got to gap=1000? The "reset" I can understand: Between subsequent messages there is a strict spacing of 10000, so my setting reset to 11000 the decoder won´t abort prematurely. OK.
But where "is" the 900 gap? Is this the zero signal/zero amplitude when 0 subsequent 0 are sent? So more like 2x365 actually?

Christian Z.

unread,
Jun 11, 2024, 4:44:53 PMJun 11
to rtl_433
In PWM you have data bits with gaps of either ~360 or ~770 µs, that way 1000 is a sane limit on where no proper data bit is.

md

unread,
Jun 11, 2024, 4:48:18 PMJun 11
to rtl_433
I am not sure I got your point I'm afraid :-/

What is this supposed to mean?
symbol_one={3}4,
symbol_zero={3}5,

3 bit long, value 4 == symbol_one, 3 bit long, value 5 == symbol_zero?
But... How come you define this as symbol_one/zero?  -> What's the next step then?

"Now you already get decoded 2 bit per DIP switch"
Yes, but  all the tests I did so far match precise my naive approach? Can it be wrong then?

Using you suggestion:
src/rtl_433 -r ~/g011_433.92M_1000k.cu8 -X "n=dick,m=OOK_PWM,s=360,long=770,g=1000,reset=11000"

Gives me:

time      : 2024-06-11 22:42:38.322242
model     : dick         count     : 1             num_rows  : 1             rows      :
len       : 37           data      : fa783aa8a8
codes     : {37}fa783aa8a8

Modulation: ASK          Freq      : 433.9 MHz
RSSI      : -0.4 dB      SNR       : 40.4 dB       Noise     : -40.8 dB

And 0xfa783aa8a8 = 0b1111101001111000001110101010100010101000
If I try to divide this into 10 DIP switches I get
1111 1010 0111 1000 0011 1010 1010 1000 1010 1000
which a) is more than 3 variations (and I have only +,0,- for each position)
and b) the first two representations (1111, 1010) are different but I know that the pattern is ++0-++--0+
so every representation of + should be the same...no?

I probably misunderstood your point. Could you kindly give a complete exampl? 

Christian Z.

unread,
Jun 11, 2024, 5:16:25 PMJun 11
to rtl_433
Don't worry too much about the symbol_x decoding. You got the option right, it matches 100 and 101, the assignment to 0/1 then is arbitrary.
But those are not the fundamental symbols. In PCM the symbols would be 100 and 110, a short pulse followed by a long gap or a long pulse followed by a short gap.

If you shift your PWM data by one bit you'll get only the patterns 11, 00, and 01. See https://triq.net/bitbench#c=%7B37%7Dfa783aa8a8&f=2b.&z=1&s=-1&cw=4
One switch would be only 2 bits. There might also be a preamble and sync at the start.

Drop your recording on https://triq.org/pdv/ and select PWM 360 / 770 to visualize the raw bits. Take the resulting code to BitBench to pick it apart.

md

unread,
Jun 14, 2024, 2:26:31 AMJun 14
to rtl_433
For PWM, isn't it the case, that each "interval" should have the same duration/length and the length within between high/low varies?
If I load my file into triq and highlight identical patterns I get the following picture. 
The first 4 are pretty identical: short high of 370mu and long low of 880mu.
But already the purple one doesn't fit anymore, not to talk about the green one? 
I had expected to have a green like 768 high and 300-something low, but instead the low is even longer than the high?

Is my assumption wrong, that the duration of the "low" is also relevant? 
Could I also encode 1 as "500 high, 10 low" and 0 as "1000 high, 10 low" as well? I always thought it's about the amount of high within a fixed width...?

If I just take the high duration in consideration I have of course only values around 360-ish and 770-ish and those seem to directly decode to 1 and 0 which, in the end make up the binary sequence you also showed here:
2024-06-14_08-17-47.png

md

unread,
Jun 14, 2024, 2:53:05 AMJun 14
to rtl_433
Looking at: https://triq.org/rtl_433/PULSE_FORMATS.html#structure-of-fsk-and-ook-transmissions, I am not sure to which kind of encoding it actually should match to?
It's neither a fixed-bit PWM (which would be what I assumed a PWM always is: pulse+gap==fixed period) nor is it fixed-gap-width PWM? 
The best guess would actually be the "fixed bit-width pwm with leading gaps", cause if I shift my boxes in the screenshot one step to the right so the gap is touching the left frame, the perios is always 1250mus on average.
This would also explain why rtl_433 by default assumes it to be a manchester encoding without futher hints ("In some few protocols, as a special case, the gaps matching the pulses will preceed the pulses: (this can easily be mistaken as gaps carrying data, e.g. Manchester coding)"

So is it this than? Is there a flex decoder preset which can be used for that? OOK_PPM/OOK_PWM is then not the right one?

md

unread,
Jun 14, 2024, 3:49:01 AMJun 14
to rtl_433
Can I do the "shift -1" / preamble = 1 (https://triq.net/bitbench#c=%7B37%7DFA%2078%203A%20A8%20A8&c=%7B37%7D%20FA%2078%203A%20A8%20A8%20%2F&f=bb%20&z=1&a=Preamble&m=0y1&cw=4) in the flex decoder specification on the cmdline as well?

Using this it cuts the decoded signal from 37 bits to 31 and returns a wrong decoding?

Also I am still not sure what the "rows" actually shall mean? If it's not for example, 2 times a given message right after each other with a short gap (e.g. due to a longer button press), what then? What's the meaning of "rows"?

rtl_433 -r ~/two_messages_1M.cu8 -s1M -X "n=dickert2,m=OOK_PWM,s=362,l=770,gap=1064,reset=12000,bits=37,preamble={1}0x1"
rtl_433 version 22.11 (2022-11-19) inputs file rtl_tcp RTL-SDR SoapySDR
Use -h for usage help and see https://triq.org/ for documentation.
Trying conf file at "rtl_433.conf"...
Trying conf file at "/home/daubsi/.config/rtl_433/rtl_433.conf"...

Reading conf from "/home/daubsi/.config/rtl_433/rtl_433.conf".
Registered 192 out of 223 device decoding protocols [ 1-4 8 11-12 15-17 19-23 25-26 29-36 38-60 63 67-71 73-100 102-105 108-116 119 121 124-128 130-149 151-161 163-168 170-175 177-197 199 201-215 217-223 ]
Test mode active. Reading samples from file: /home/daubsi/two_messages_1M.cu8
baseband_demod_FM: low pass filter for 1000000 Hz at cutoff 100000 Hz, 10.0 us

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : 2024-06-14 09:46:06.402979
model     : dickert2     count     : 1             num_rows  : 1             rows      :
len       : 31           data      : 9e0eaa2a
codes     : {31}9e0eaa2a
Modulation: ASK          Freq      : 1.0 MHz
RSSI      : -1.4 dB      SNR       : 39.3 dB       Noise     : -40.7 dB

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : 2024-06-14 09:46:06.439292
model     : dickert2     count     : 1             num_rows  : 1             rows      :
len       : 31           data      : 9e0eaa2a
codes     : {31}9e0eaa2a
Modulation: ASK          Freq      : 1.0 MHz
RSSI      : -1.2 dB      SNR       : 40.7 dB       Noise     : -41.9 dB
Estimated noise level is -23.8 dB, adjusting minimum detection level to -20.8 dB


Christian Z.

unread,
Jun 14, 2024, 4:06:40 AMJun 14
to rtl_433
Yes, fixed bit-width PWM with leading gaps seems correct. The OOK_PWM slicer can deal with that (by simply discarding any gaps).

Rows would be successive packets in the same transmisson (repeats usually).

You don't need the shift and the preamble of {1}1 aligns at the first 0-bit, you might have wanted {1}8 -- the nibble always aligns to the left/front.

To get the bits/switches look at example  getters in rtl_433's conf folder.

md

unread,
Jun 14, 2024, 6:07:23 AMJun 14
to rtl_433
Fixed-width PWM with leading gaps: Jay!! I understood something :-D
So I don't need to tell it anything special then? My current flex decoder is -X "n=Dickert_Flex,m=OOK_PWM,s=362,l=770,gap=1064,reset=12000,bits=37,preamble={1}8"
Thanks for the hint of the preamble, misunderstood it's working. Makes sense now

Rows: Ok but that's the point why I am asking: If I keep the button pressed: Using your wording: Is this then the same transmission or a sequence of transmissions?
....
I think I get what the term "row" is alluring to: So it is a repetition of parts of the message by design within a single transmission (which is the minimal "thing" that's put on the ether once the user presses a button (the {37}FA 78 3A A8 A8))?
So in that case we don't HAVE a repetition of (parts of ) the actual payload. The "repetition" I am talking about is actually another "transmission" 10000mu later?

Hm, but why would I want to repeat myself in the same transmission anyway? For data quality reasons? I usually have CRCs or something so when the first transmission fails, it would be discarded anyways, no?
Or are repetitions simply a way of a "poor man's CRC"?

Christian Z.

unread,
Jun 14, 2024, 6:47:34 AMJun 14
to rtl_433
Re rows:
Some rare protocols send each byte with it's own header and checksum (IIRC we have two decoders like that)

Most protocols just want to ensure the message is heard. We usually require a minimum amount of repeats in lieu of checksums -- but I doubt hardware receivers do this. We sometimes also use a quorum where the majority of a bit state across rows is used -- special cases only though.

And then some protocols have a counter in their repeats, so every row would be different.

If packets are too far apart rtl_433 won't associate them and you get mulitple events with one row instead of one event with multiple rows.
10 ms is right on the edge. 5 ms should always work, 20 ms likely won't. 10 ms can't say, depends on the overall speed (the regular gaps) of the protocol.

md

unread,
Jun 16, 2024, 4:51:56 PMJun 16
to rtl_433
I think I now got the mechanics so far. I rewrote the decoder using the "new" approach and it again works very well!
Now I want to implement my sender (the hw key fob I have) with a CC1101 and Arduino. Basically what I need to do is to send the 5 raw bytes 0xfa, 0x78, 0x3a, 0xa8, 0xa8 in the proper speed so the decoder picks it up due to matching pulse/gap width, right?

Using https://github.com/LSatan/SmartRC-CC1101-Driver-Lib I can set the Data rate in kBaud between 0.02 and 1621.83, default is 99.97 kBaud. 

Looking at our already familar sample from the sender with short=360, long=770 the total length of our 5 bytes 0xfa783aa8a8 is 55ms, so we have 5 bytes in 55ms, so thats 90,90 bytes/s * 8 = 727 baud = 0.727 kBaud.

Is this correct?

Karl Lohner

unread,
Jun 16, 2024, 8:41:27 PMJun 16
to md, rtl_433
Here's what I came up with if looking at this as PCM, based on the .cu8 file provided a few days ago.

I measure symbols to be 414 µs in length; message is 109 symbols; preamble is perhaps just the initial 1 symbol pulse.

Then a logical "0" bit is symbols "011" and a logical "1" bit is symbols "001".   This looks like an inverted PWM?

The gap between (15?) message repetitions is about 108 symbols long (about 44722 µs) which seems to be too long for rtl_433 to organize these repetitions as data rows.

Here are decoders I got working:

# {109}924b2d924b6db24b2cb2cb6cb2c8
decoder {
    name        = Dickert_PCM_raw,
    modulation  = OOK_PCM,
    short       = 414,
    long        = 414,
    reset       = 1242,
    bits       >= 109,
    bits       <= 116,
}

Decoded, I get a logical message of {36}f4f075515.

If we can assume the initial logical "f" nibble is part of the preamble (making a 13 symbol preamble), it may allow for a more discriminating decoder and result in a tidy 4 byte logical message (of {32}4f075515 in this example).

decoder {
    name        = Dickert_PCM_logical,
    modulation  = OOK_PCM,
    short       = 414,
    long        = 414,
    reset       = 1242,
    preamble    = {13}9248,
    bits       >= 109,
    bits       <= 116,
    symbol_zero = {3}6,
    symbol_one  = {3}2,
}

md

unread,
Jun 17, 2024, 3:23:15 AMJun 17
to rtl_433
Hi Karl, thanks for that alternative approach using PCM instead of PWM. I can confirm it arrives at the same result as what we discussed in this thread so far with PWM. I think I now also understood what symbol_zero/one are actually meant for :-)

md

unread,
Jun 17, 2024, 3:30:58 AMJun 17
to rtl_433
Tried to mimic the signal generation using a CC1101 with Arduino by just sending "0xfa, 0x78, 0x3a, 0xa8, 0xa8" at the appropriate speed. Recording the signal using URH works and gets decoded properly but rtl_433 can't pick it up. Probably due to my non-exact timing. 
Looking at the demodulated signal in URH however shows that the actual demodulated bits are "shown" completely different (long runs of high etc.), which is explainable because the library https://github.com/LSatan/SmartRC-CC1101-Driver-Lib does not seem to support PWM by itself. So I am scratching my head if I now have to do an PWM encoding myself? On the other hand if it can be decoded as PCM as well I could as well basically send the original "924b2d924b6db24b2cb2cb6cb2c8" sequence and it should be PWM decodable as well? Or am I thinking in the wrong direction here? 

md

unread,
Jun 17, 2024, 3:46:24 AMJun 17
to rtl_433
My current attempt at coding the PWM variant for rtl_433:

static int dickert_mahs_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    uint8_t b[40];
    data_t *data;
    char dips[20] = {0};
    char dips_s[20] = {0};

    const int MSG_LEN = 37;

    enum SwitchPos {
 PLUS  = 3, // 0b11
 ZERO  = 1, // 0b01
 MINUS = 0, // 0x00
    };

    enum SwitchPos dip;

    // We only expect one row per transmission
    if (bitbuffer->num_rows != 1) {
    return DECODE_ABORT_EARLY;
    }

    if (bitbuffer->bits_per_row[0] != MSG_LEN) {
return DECODE_ABORT_LENGTH;
    }

    // Remove the first bit and store in b
    bitbuffer_extract_bytes(bitbuffer, 0, 1, b, MSG_LEN);

    // Get dip switches
    for (int idx=0; idx<5; idx++) {
        uint8_t byte = b[idx];

for (int nib=3; nib>=0; nib--) {
                dip = (enum SwitchPos) ((byte >> (2*nib)) & 3);
dips[idx * 4 + (3-nib)] = dip == PLUS ? '+' : dip == ZERO ? '0' : dip == MINUS ? '-' : '?';
}
    }

    // Extract the 10 first switch positions
    // We intentionally disable the stringop-truncation warning as we're sure dips_s will be \0-terminated as it's initialized
    // with 0 and > 10 chars

    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wstringop-truncation"
    strncat(dips_s, dips, 10);
    #pragma GCC diagnostic pop

    /* clang-format off */
    data = data_make(
            "model",        "",      DATA_STRING, "Dickert MAHS433-01 remote control",
            "dipswitches",  "DIP switches configuration", DATA_STRING, dips_s,
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}

Is this a sensible way of stripping the leading pulse (preamble)?

// Remove the first bit and store in b
    bitbuffer_extract_bytes(bitbuffer, 0, 1, b, MSG_LEN);

Christian Z.

unread,
Jun 17, 2024, 5:22:13 AMJun 17
to rtl_433
does not seem to support PWM by itself. So I am scratching my head if I now have to do an PWM encoding myself?

Yes, like Karl suggested, you need to encode the bits to symbols of 011 and 001. And ensure that you send "raw", without preamble, sync-word, CRC, and of course without Manchester coding.
 

Karl Lohner

unread,
Jun 17, 2024, 10:48:31 AMJun 17
to rtl_433
does not seem to support PWM by itself. So I am scratching my head if I now have to do an PWM encoding myself?

Yes, like Karl suggested, you need to encode the bits to symbols of 011 and 001. And ensure that you send "raw", without preamble, sync-word, CRC, and of course without Manchester coding.

And, at 414 µs per symbol, I think you're looking at a data rate of around 2415 bps.

md, perhaps it makes sense to open an issue at https://github.com/merbanan/rtl_433/issues to further discuss this decoder?

md

unread,
Jun 17, 2024, 3:10:38 PMJun 17
to rtl_433
I got it working! I can now send the signal with an Arduino/CC1101 module and the SmartRF library. It needed patching the library sources as shown here: https://github.com/LSatan/SmartRC-CC1101-Driver-Lib/issues/135 as it always wants to send the size as the first byte of the payload. 

I used the long representation of our message without on-the-fly encoding:
byte pwm_sequence[15]={0x92,0x4b,0x2d,0x92,0x4b,0x6d,0xb2,0x4b,0x2c,0xb2,0xcb,0x6c,0xb2,0xc8,0x00};

This is the full sketch I used to send it:

//New transmission method.
//In addition, the gdo0 and gdo2 pin are not required.
//https://github.com/LSatan/SmartRC-CC1101-Driver-Lib
//by Little_S@tan
#include <ELECHOUSE_CC1101_SRC_DRV.h>

byte pwm_sequence[15]={0x92,0x4b,0x2d,0x92,0x4b,0x6d,0xb2,0x4b,0x2c,0xb2,0xcb,0x6c,0xb2,0xc8,0x00};

void setup() {

    Serial.begin(9600);

    if (ELECHOUSE_cc1101.getCC1101()){      // Check the CC1101 Spi connection.
    Serial.println("Connection OK");
    }else{
    Serial.println("Connection Error");
    }
 
    ELECHOUSE_cc1101.Init();                // must be set to initialize the cc1101!
    ELECHOUSE_cc1101.setCCMode(1);          // set config for internal transmission mode.
    ELECHOUSE_cc1101.setModulation(2);      // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK.
    ELECHOUSE_cc1101.setMHZ(433.92);        // Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet.
    //ELECHOUSE_cc1101.setDeviation(47.6);   // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz.
    ELECHOUSE_cc1101.setDeviation(15);
    ELECHOUSE_cc1101.setChannel(0);         // Set the Channelnumber from 0 to 255. Default is cahnnel 0.
    ELECHOUSE_cc1101.setChsp(199.95);       // The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz.
    ELECHOUSE_cc1101.setRxBW(812.50);       // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz.
    //ELECHOUSE_cc1101.setDRate(99.97);       // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud!
    ELECHOUSE_cc1101.setDRate(2.415);
    ELECHOUSE_cc1101.setPA(10);             // Set TxPower. The following settings are possible depending on the frequency band.  (-30  -20  -15  -10  -6    0    5    7    10   11   12) Default is max!
    ELECHOUSE_cc1101.setSyncMode(4);        // Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold.
    ELECHOUSE_cc1101.setSyncWord(211, 145); // Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low)
    ELECHOUSE_cc1101.setAdrChk(0);          // Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast.
    ELECHOUSE_cc1101.setAddr(0);            // Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF).
    ELECHOUSE_cc1101.setWhiteData(0);       // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on.
    ELECHOUSE_cc1101.setPktFormat(0);       // Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. 3 = Asynchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins.
    ELECHOUSE_cc1101.setLengthConfig(1);    // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved
    ELECHOUSE_cc1101.setPacketLength(0);    // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed.
    ELECHOUSE_cc1101.setCrc(0);             // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX.
    ELECHOUSE_cc1101.setCRC_AF(0);          // Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size.
    ELECHOUSE_cc1101.setDcFilterOff(0);     // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity).
    ELECHOUSE_cc1101.setManchester(0);      // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable.
    ELECHOUSE_cc1101.setFEC(0);             // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable.
    ELECHOUSE_cc1101.setPRE(0);             // Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24
    ELECHOUSE_cc1101.setPQT(0);             // Preamble quality estimator threshold. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted.
    ELECHOUSE_cc1101.setAppendStatus(0);    // When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK.

    Serial.println("Tx Mode");
}

void loop() {

//3 different methods to send data without gdo
//When sending, we give a little time to completely transmit the message (time in millis).
//You can shorten the time. It depends on the data rate and the packet length. Just try it out for fine tuning.

//Transmitt "Hello World" from byte format.
Serial.println("Sending");
ELECHOUSE_cc1101.SendData(pwm_sequence, 15, 2000);
delay(2000);
}

I had to add a 0x00 at the end of the send buffer, because otherwise URH would improperly decode it.
I had to use the Baudrate of 2415 baud as Karl said. 
Karl, how did you end up at 414ms? I think we were talking about 360 all the time because that's what rtl_433 printed?

The strange thing is it only now works with my first implementation using this r_device definition:
r_device const dickert = {
        .name        = "Dickert MAHS433-01 garage door remote control",
        .modulation  = OOK_PULSE_PCM,
        .short_width = 365,
        .long_width  = 365,
        .gap_limit   = 900,
        .reset_limit = 10000,
.disabled    = 1,
        .decode_fn   = &dickert_decode,
        .fields      = output_fields,
};

The second iteration using OOK_PULSE_PWM did not pick up the decoding... 
Not even after adapting the pulse durations:

r_device const dickert_mahs = {
        .name        = "Dickert MAHS433-01 garage door remote control",
        .modulation  = OOK_PULSE_PWM,
        .short_width = 413,//362,
        .long_width  = 827,//770,
        .gap_limit   = 1064,
        .reset_limit = 12000,
.disabled    = 1,
        .decode_fn   = &dickert_mahs_decode,
        .fields      = output_fields,
};

I will now try to adapt the sending to actually encode the symbols with 011 and 001.

I am happy to continue with a github issue, but honestly I thought this would be a better place to discuss as the initial idea was just to ask some questions about how to approach the task, but Christian was patient enough to answer all my questions.

md

unread,
Jun 17, 2024, 3:32:30 PMJun 17
to rtl_433
PWM Version: My bad, it worked. The device had a different ID and I activated the wrong one with "-R <id>" 

Christian Z.

unread,
Jun 17, 2024, 3:39:41 PMJun 17
to rtl_433
Great to hear! Someone should turn this into a Howto, maybe as wiki page at https://github.com/merbanan/rtl_433/wiki/ :)

md

unread,
Jun 17, 2024, 4:06:42 PMJun 17
to rtl_433
Hello, I am "someone" ;-)
Happy to do so once everything is cleaned up properly.

md

unread,
Jun 18, 2024, 4:03:48 AMJun 18
to rtl_433
How would you like to get this "howto" done? Should I just create this on my own github and you pull it over if it is of satisfying quality or what's your idea for that? 

Christian Z.

unread,
Jun 18, 2024, 4:33:30 AMJun 18
to rtl_433
You can write it directly on the wiki, access should work.
If you are unsure about things or have question then just leave notes in the text and I'll gladly review all.

Thanks!
Reply all
Reply to author
Forward
0 new messages