kopia lustrzana https://github.com/xaelsouth/rtl-wmbus
C1 mode improvements; S1 mode implemented
rodzic
cec199312e
commit
a517da71d1
|
@ -0,0 +1,29 @@
|
|||
clear all;
|
||||
|
||||
samplerate = 800e3;
|
||||
nyqistrate = samplerate/2;
|
||||
|
||||
Ws1 = 22e3/nyqistrate;
|
||||
Wp1 = 30e3/nyqistrate;
|
||||
Wp2 = 34e3/nyqistrate;
|
||||
Ws2 = 42e3/nyqistrate;
|
||||
Rp = 1;
|
||||
Rs = 40;
|
||||
|
||||
% seems to be the best
|
||||
[n, Wc] = cheb1ord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs);
|
||||
[b, a] = cheby1(n, Rp, Wc);
|
||||
|
||||
% does not work at all
|
||||
%[n, Wc] = cheb2ord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs);
|
||||
%[b, a] = cheby2(n, Rp, Wc);
|
||||
|
||||
% performs badly
|
||||
%[n, Wc] = ellipord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs);
|
||||
%[b, a] = ellip(n, Rp, Rs, Wc);
|
||||
|
||||
% big filter order - unpracticable
|
||||
%[n, Wc] = buttord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs);
|
||||
%[b, a] = butter(n, Wc);
|
||||
|
||||
print_iir_filter_coef(b ,a);
|
|
@ -0,0 +1,15 @@
|
|||
clear all;
|
||||
|
||||
samplerate = 800e3;
|
||||
nyqistrate = samplerate/2;
|
||||
|
||||
Wp1 = 100e3/nyqistrate;
|
||||
Ws1 = 160e3/nyqistrate;
|
||||
Rp = 1;
|
||||
Rs = 40;
|
||||
|
||||
[n, Wc] = buttord(Wp1, Ws1, Rp, Rs);
|
||||
[b] = fir1(n, Wc);
|
||||
|
||||
print_fir_filter_coef(b);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
clear all;
|
||||
|
||||
samplerate = 800e3;
|
||||
nyqistrate = samplerate/2;
|
||||
|
||||
Wp1 = 32e3/nyqistrate;
|
||||
Ws1 = 36e3/nyqistrate;
|
||||
Rp = 1;
|
||||
Rs = 40;
|
||||
|
||||
[n, Wc] = buttord(Wp1, Ws1, Rp, Rs);
|
||||
[b] = fir1(n, Wc);
|
||||
|
||||
print_fir_filter_coef(b);
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
#ifndef S1_PACKET_DECODER_H
|
||||
#define S1_PACKET_DECODER_H
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2021 <xael.south@yandex.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
static const uint8_t MANCHESTER_IEEE_802_3[4] = {
|
||||
0xFF, 0x01, 0x00, 0xFF // According to wireless MBus spec.: "01b” representing a “one”; "10b" representing a "zero".
|
||||
};
|
||||
|
||||
struct s1_packet_decoder_work;
|
||||
typedef void (*s1_packet_decoder_state)(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
|
||||
static void s1_idle(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_done(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_rx_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_rx_bit2(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
|
||||
static void s1_rx_first_mode_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_rx_last_mode_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
|
||||
static void s1_rx_first_lfield_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_rx_last_lfield_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
|
||||
static void s1_rx_first_data_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
static void s1_rx_last_data_bit(unsigned bit, struct s1_packet_decoder_work *decoder);
|
||||
|
||||
|
||||
static const s1_packet_decoder_state s1_decoder_states[] =
|
||||
{
|
||||
s1_idle, // 0
|
||||
|
||||
s1_rx_first_lfield_bit, // 1
|
||||
s1_rx_bit2, // 2
|
||||
s1_rx_bit, // 3
|
||||
s1_rx_bit2, // 4
|
||||
s1_rx_bit, // 5
|
||||
s1_rx_bit2, // 6
|
||||
s1_rx_bit, // 7
|
||||
s1_rx_bit2, // 8
|
||||
s1_rx_bit, // 9
|
||||
s1_rx_bit2, // 10
|
||||
s1_rx_bit, // 11
|
||||
s1_rx_bit2, // 12
|
||||
s1_rx_bit, // 13
|
||||
s1_rx_bit2, // 14
|
||||
s1_rx_bit, // 15
|
||||
s1_rx_last_lfield_bit, // 16
|
||||
|
||||
s1_rx_first_data_bit, // 17
|
||||
s1_rx_bit2, // 18
|
||||
s1_rx_bit, // 19
|
||||
s1_rx_bit2, // 20
|
||||
s1_rx_bit, // 21
|
||||
s1_rx_bit2, // 22
|
||||
s1_rx_bit, // 23
|
||||
s1_rx_bit2, // 24
|
||||
s1_rx_bit, // 25
|
||||
s1_rx_bit2, // 26
|
||||
s1_rx_bit, // 27
|
||||
s1_rx_bit2, // 28
|
||||
s1_rx_bit, // 29
|
||||
s1_rx_bit2, // 30
|
||||
s1_rx_bit, // 31
|
||||
s1_rx_last_data_bit, // 32
|
||||
|
||||
s1_done, // 33
|
||||
};
|
||||
|
||||
|
||||
struct s1_packet_decoder_work
|
||||
{
|
||||
const s1_packet_decoder_state *state;
|
||||
unsigned current_rssi;
|
||||
unsigned packet_rssi;
|
||||
union
|
||||
{
|
||||
unsigned flags;
|
||||
struct
|
||||
{
|
||||
unsigned unused: 1;
|
||||
unsigned crc_ok: 1;
|
||||
};
|
||||
};
|
||||
unsigned l;
|
||||
unsigned L;
|
||||
unsigned mode;
|
||||
unsigned byte;
|
||||
__attribute__((__aligned__(16))) uint8_t packet[290]; // max. packet length with L- and all CRC-Fields
|
||||
char timestamp[64];
|
||||
};
|
||||
|
||||
static int in_rx_s1_packet_decoder(struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
return (decoder->state == &s1_decoder_states[0]) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void reset_s1_packet_decoder(struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
memset(decoder, 0, sizeof(*decoder));
|
||||
decoder->state = &s1_decoder_states[0];
|
||||
}
|
||||
|
||||
static void s1_idle(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
if (!(bit & PACKET_PREAMBLE_DETECTED_MASK))
|
||||
{
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
static void s1_done(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
(void)bit;
|
||||
(void)decoder;
|
||||
}
|
||||
|
||||
static void s1_rx_bit(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= (bit & PACKET_DATABIT_MASK);
|
||||
}
|
||||
|
||||
static void s1_rx_bit2(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= (bit & PACKET_DATABIT_MASK);
|
||||
|
||||
const unsigned b = MANCHESTER_IEEE_802_3[decoder->byte & 0b11];
|
||||
|
||||
if (b == 0xFFu)
|
||||
{
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoder->byte >>= 2;
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= b;
|
||||
}
|
||||
}
|
||||
|
||||
static void s1_rx_first_lfield_bit(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte = (bit & PACKET_DATABIT_MASK);
|
||||
}
|
||||
|
||||
static void s1_rx_last_lfield_bit(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= (bit & PACKET_DATABIT_MASK);
|
||||
|
||||
const unsigned b = MANCHESTER_IEEE_802_3[decoder->byte & 0b11];
|
||||
|
||||
if (b == 0xFFu)
|
||||
{
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoder->byte >>= 2;
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= b;
|
||||
}
|
||||
|
||||
decoder->L = decoder->byte;
|
||||
decoder->l = 0;
|
||||
decoder->packet[decoder->l++] = decoder->L;
|
||||
decoder->L = FULL_TLG_LENGTH_FROM_L_FIELD[decoder->L];
|
||||
}
|
||||
|
||||
static void s1_rx_first_data_bit(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte = (bit & PACKET_DATABIT_MASK);
|
||||
}
|
||||
|
||||
static void s1_rx_last_data_bit(unsigned bit, struct s1_packet_decoder_work *decoder)
|
||||
{
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= (bit & PACKET_DATABIT_MASK);
|
||||
|
||||
const unsigned b = MANCHESTER_IEEE_802_3[decoder->byte & 0b11];
|
||||
|
||||
if (b == 0xFFu)
|
||||
{
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoder->byte >>= 2;
|
||||
decoder->byte <<= 1;
|
||||
decoder->byte |= b;
|
||||
}
|
||||
|
||||
decoder->packet[decoder->l++] = decoder->byte;
|
||||
|
||||
if (decoder->l < decoder->L)
|
||||
{
|
||||
decoder->state = &s1_decoder_states[17]; // s1_rx_first_data_bit
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
struct tm *timeinfo = gmtime(&now);
|
||||
strftime(decoder->timestamp, sizeof(decoder->timestamp), "%Y-%m-%d %H:%M:%S.000", timeinfo);
|
||||
}
|
||||
}
|
||||
|
||||
static void s1_packet_decoder(unsigned bit, unsigned rssi, struct s1_packet_decoder_work *decoder, const char *algorithm)
|
||||
{
|
||||
decoder->current_rssi = rssi;
|
||||
|
||||
(*decoder->state++)(bit, decoder);
|
||||
|
||||
if (*decoder->state == s1_idle)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
else if (*decoder->state == s1_done)
|
||||
{
|
||||
decoder->crc_ok = check_calc_crc_wmbus(decoder->packet, decoder->L) ? 1 : 0;
|
||||
|
||||
if (!opts_show_used_algorithm) algorithm = "";
|
||||
fprintf(stdout, "%s%s;%u;%u;%s;%u;%u;%08X;", algorithm, "S1",
|
||||
decoder->crc_ok,
|
||||
1,
|
||||
decoder->timestamp,
|
||||
decoder->packet_rssi,
|
||||
rssi,
|
||||
get_serial(decoder->packet));
|
||||
|
||||
#if 0
|
||||
fprintf(stdout, "0x");
|
||||
for (size_t l = 0; l < decoder->L; l++) fprintf(stdout, "%02x", decoder->packet[l]);
|
||||
fprintf(stdout, ";");
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
decoder->L = cook_pkt(decoder->packet, decoder->L);
|
||||
fprintf(stdout, "0x");
|
||||
for (size_t l = 0; l < decoder->L; l++) fprintf(stdout, "%02x", decoder->packet[l]);
|
||||
#endif
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fflush(stdout);
|
||||
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stop receiving packet if current rssi below threshold.
|
||||
// The current packet seems to be collided with an another one.
|
||||
if (rssi < PACKET_CAPTURE_THRESHOLD)
|
||||
{
|
||||
reset_s1_packet_decoder(decoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* S1_PACKET_DECODER_H */
|
||||
|
Ładowanie…
Reference in New Issue