mirror of
https://github.com/merbanan/rtl_433.git
synced 2026-04-23 19:17:03 -04:00
Merge pull request #333 from ygator/master
Oregon Scientific V1 Decoding
This commit is contained in:
@@ -115,6 +115,10 @@ Supported devices:
|
||||
[43] CurrentCost Current Sensor
|
||||
[44] OpenEnergyMonitor emonTx v3
|
||||
[45] HT680 Remote control
|
||||
[46] S3318P Temperature & Humidity Sensor
|
||||
[47] Akhan 100F14 remote keyless entry
|
||||
[48] Quhwa
|
||||
[49] Oregon Scientific v1 Temperature Sensor
|
||||
```
|
||||
|
||||
|
||||
|
||||
3
include/pulse_demod.h
Normal file → Executable file
3
include/pulse_demod.h
Normal file → Executable file
@@ -135,4 +135,7 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, struct protocol_s
|
||||
/// @return number of events processed
|
||||
int pulse_demod_clock_bits(const pulse_data_t *pulses, struct protocol_state *device);
|
||||
|
||||
|
||||
int pulse_demod_osv1(const pulse_data_t *pulses, struct protocol_state *device);
|
||||
|
||||
#endif /* INCLUDE_PULSE_DEMOD_H_ */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define DEFAULT_LEVEL_LIMIT 8000 // Theoretical high level at I/Q saturation is 128x128 = 16384 (above is ripple)
|
||||
#define MINIMAL_BUF_LENGTH 512
|
||||
#define MAXIMAL_BUF_LENGTH (256 * 16384)
|
||||
#define MAX_PROTOCOLS 48
|
||||
#define MAX_PROTOCOLS 49
|
||||
#define SIGNAL_GRABBER_BUFFER (12 * DEFAULT_BUF_LENGTH)
|
||||
|
||||
/* Supported modulation types */
|
||||
@@ -45,7 +45,8 @@
|
||||
#define OOK_PULSE_PWM_PRECISE 6 // Pulse Width Modulation with precise timing parameters
|
||||
#define OOK_PULSE_PWM_RAW 7 // Pulse Width Modulation. Short pulses = 1, Long = 0
|
||||
#define OOK_PULSE_PWM_TERNARY 8 // Pulse Width Modulation with three widths: Sync, 0, 1. Sync determined by argument
|
||||
#define OOK_PULSE_CLOCK_BITS 9 // Level shift within the clock cycle.
|
||||
#define OOK_PULSE_CLOCK_BITS 9 // Level shift within the clock cycle.
|
||||
#define OOK_PULSE_PWM_OSV1 10 // Pulse Width Modulation. Oregon Scientific v1
|
||||
|
||||
#define FSK_DEMOD_MIN_VAL 16 // Dummy. FSK demodulation must start at this value
|
||||
#define FSK_PULSE_PCM 16 // FSK, Pulse Code Modulation
|
||||
|
||||
@@ -49,9 +49,10 @@
|
||||
DECL(current_cost) \
|
||||
DECL(emontx) \
|
||||
DECL(ht680) \
|
||||
DECL(s3318p) \
|
||||
DECL(s3318p) \
|
||||
DECL(akhan_100F14) \
|
||||
DECL(quhwa)
|
||||
DECL(quhwa) \
|
||||
DECL(oregon_scientific_v1)
|
||||
|
||||
typedef struct {
|
||||
char name[256];
|
||||
|
||||
@@ -55,6 +55,7 @@ add_executable(rtl_433
|
||||
devices/nexus.c
|
||||
devices/oil_watchman.c
|
||||
devices/oregon_scientific.c
|
||||
devices/oregon_scientific_v1.c
|
||||
devices/prologue.c
|
||||
devices/rubicson.c
|
||||
devices/silvercrest.c
|
||||
|
||||
@@ -41,6 +41,7 @@ rtl_433_SOURCES = baseband.c \
|
||||
devices/nexus.c \
|
||||
devices/oil_watchman.c \
|
||||
devices/oregon_scientific.c \
|
||||
devices/oregon_scientific_v1.c \
|
||||
devices/prologue.c \
|
||||
devices/quhwa.c \
|
||||
devices/rubicson.c \
|
||||
|
||||
92
src/devices/oregon_scientific_v1.c
Executable file
92
src/devices/oregon_scientific_v1.c
Executable file
@@ -0,0 +1,92 @@
|
||||
#include "rtl_433.h"
|
||||
#include "data.h"
|
||||
#include "util.h"
|
||||
|
||||
#define OSV1_BITS 32
|
||||
|
||||
static int rev_nibble(int nib)
|
||||
{
|
||||
int revnib = 0;
|
||||
|
||||
revnib += (nib >> 3) & 0x1;
|
||||
revnib += (nib >> 1) & 0x2;
|
||||
revnib += (nib << 1) & 0x4;
|
||||
revnib += (nib << 3) & 0x8;
|
||||
|
||||
return(revnib);
|
||||
}
|
||||
|
||||
static int oregon_scientific_callback_v1(bitbuffer_t *bitbuffer) {
|
||||
int ret = 0;
|
||||
char time_str[LOCAL_TIME_BUFLEN];
|
||||
int row;
|
||||
int cs;
|
||||
int i;
|
||||
int nibble[OSV1_BITS/4];
|
||||
int sid, channel, uk1;
|
||||
float tempC;
|
||||
int battery, uk2, sign, uk3, checksum;
|
||||
data_t *data;
|
||||
|
||||
local_time_str(0, time_str);
|
||||
|
||||
for(row = 0; row < bitbuffer->num_rows; row++) {
|
||||
if(bitbuffer->bits_per_row[row] == OSV1_BITS) {
|
||||
cs = 0;
|
||||
for(i = 0; i < OSV1_BITS / 8; i++) {
|
||||
nibble[i * 2 ] = rev_nibble((bitbuffer->bb[row][i] >> 4));
|
||||
nibble[i * 2 + 1] = rev_nibble((bitbuffer->bb[row][i] & 0x0f));
|
||||
if(i < ((OSV1_BITS / 8) - 1))
|
||||
cs += nibble[i * 2] + 16 * nibble[i * 2 + 1];
|
||||
}
|
||||
cs = (cs & 0xFF) + (cs >> 8);
|
||||
checksum = nibble[6] + (nibble[7] << 4);
|
||||
if(checksum == cs) {
|
||||
sid = nibble[0];
|
||||
channel = ((nibble[1] >> 2) & 0x03) + 1;
|
||||
uk1 = (nibble[1] >> 0) & 0x03; /* unknown. Seen change every 60 minutes */
|
||||
tempC = nibble[2] / 10. + nibble[3] + nibble[4] * 10.;
|
||||
battery = (nibble[5] >> 3) & 0x01;
|
||||
uk2 = (nibble[5] >> 2) & 0x01; /* unknown. Always zero? */
|
||||
sign = (nibble[5] >> 1) & 0x01;
|
||||
uk3 = (nibble[5] >> 0) & 0x01; /* unknown. Always zero? */
|
||||
|
||||
if(sign) tempC = -tempC;
|
||||
|
||||
data = data_make(
|
||||
"time", "", DATA_STRING, time_str,
|
||||
"model", "", DATA_STRING, "OSv1 Temperature Sensor",
|
||||
"sid", "SID", DATA_INT, sid,
|
||||
"channel", "Channel", DATA_INT, channel,
|
||||
"battery", "Battery", DATA_STRING, battery ? "LOW" : "OK",
|
||||
"temperature_C","Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, tempC,
|
||||
NULL);
|
||||
data_acquired_handler(data);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *output_fields[] = {
|
||||
"time",
|
||||
"model",
|
||||
"id",
|
||||
"channel",
|
||||
"battery",
|
||||
"temperature_C",
|
||||
NULL
|
||||
};
|
||||
|
||||
r_device oregon_scientific_v1 = {
|
||||
.name = "OSv1 Temperature Sensor",
|
||||
.modulation = OOK_PULSE_PWM_OSV1,
|
||||
.short_limit = 300,
|
||||
.long_limit = 430,
|
||||
.reset_limit = 14000,
|
||||
.json_callback = &oregon_scientific_callback_v1,
|
||||
.disabled = 0,
|
||||
.demod_arg = 0,
|
||||
.fields = output_fields
|
||||
};
|
||||
72
src/pulse_demod.c
Normal file → Executable file
72
src/pulse_demod.c
Normal file → Executable file
@@ -319,3 +319,75 @@ int pulse_demod_clock_bits(const pulse_data_t *pulses, struct protocol_state *de
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
/*
|
||||
* Oregon Scientific V1 Protocol
|
||||
* Starts with a clean preamble of 12 pulses with
|
||||
* consistent timing followed by an out of time Sync pulse.
|
||||
* Data then follows with manchester encoding, but
|
||||
* care must be taken with the gap after the sync pulse since it
|
||||
* is outside of the normal clocking. Because of this a data stream
|
||||
* beginning with a 0 will have data in this gap.
|
||||
* This code looks at pulse and gap width and clocks bits
|
||||
* in from this. Since this is manchester encoded every other
|
||||
* bit is discarded.
|
||||
*/
|
||||
|
||||
int pulse_demod_osv1(const pulse_data_t *pulses, struct protocol_state *device) {
|
||||
unsigned int n;
|
||||
int preamble = 0;
|
||||
int events = 0;
|
||||
int manbit = 0;
|
||||
bitbuffer_t bits = {0};
|
||||
|
||||
/* preamble */
|
||||
for(n = 0; n < pulses->num_pulses; ++n) {
|
||||
if(pulses->pulse[n] >= 350 && pulses->gap[n] >= 200) {
|
||||
preamble++;
|
||||
if(pulses->gap[n] >= 400)
|
||||
break;
|
||||
} else
|
||||
return(events);
|
||||
}
|
||||
if(preamble != 12) {
|
||||
printf("preamble %d %d %d\n", preamble, pulses->pulse[0], pulses->gap[0]);
|
||||
return(events);
|
||||
}
|
||||
|
||||
/* sync */
|
||||
++n;
|
||||
if(pulses->pulse[n] < 1000 || pulses->gap[n] < 1000) {
|
||||
return(events);
|
||||
}
|
||||
|
||||
/* data bits - manchester encoding */
|
||||
|
||||
/* sync gap could be part of data when the first bit is 0 */
|
||||
if(pulses->gap[n] > pulses->pulse[n]) {
|
||||
manbit ^= 1;
|
||||
if(manbit) bitbuffer_add_bit(&bits, 0);
|
||||
}
|
||||
|
||||
/* remaining data bits */
|
||||
for(n++; n < pulses->num_pulses; ++n) {
|
||||
manbit ^= 1;
|
||||
if(manbit) bitbuffer_add_bit(&bits, 1);
|
||||
if(pulses->pulse[n] > 615) {
|
||||
manbit ^= 1;
|
||||
if(manbit) bitbuffer_add_bit(&bits, 1);
|
||||
}
|
||||
if (n == pulses->num_pulses - 1 || pulses->gap[n] > device->reset_limit) {
|
||||
if((bits.bits_per_row[bits.num_rows-1] == 32) && device->callback) {
|
||||
events += device->callback(&bits);
|
||||
}
|
||||
return(events);
|
||||
}
|
||||
manbit ^= 1;
|
||||
if(manbit) bitbuffer_add_bit(&bits, 0);
|
||||
if(pulses->gap[n] > 450) {
|
||||
manbit ^= 1;
|
||||
if(manbit) bitbuffer_add_bit(&bits, 0);
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -647,6 +647,9 @@ static void rtlsdr_callback(unsigned char *iq_buf, uint32_t len, void *ctx) {
|
||||
case OOK_PULSE_CLOCK_BITS:
|
||||
pulse_demod_clock_bits(&demod->pulse_data, demod->r_devs[i]);
|
||||
break;
|
||||
case OOK_PULSE_PWM_OSV1:
|
||||
pulse_demod_osv1(&demod->pulse_data, demod->r_devs[i]);
|
||||
break;
|
||||
// FSK decoders
|
||||
case FSK_PULSE_PCM:
|
||||
case FSK_PULSE_PWM_RAW:
|
||||
@@ -669,6 +672,7 @@ static void rtlsdr_callback(unsigned char *iq_buf, uint32_t len, void *ctx) {
|
||||
case OOK_PULSE_PWM_TERNARY:
|
||||
case OOK_PULSE_MANCHESTER_ZEROBIT:
|
||||
case OOK_PULSE_CLOCK_BITS:
|
||||
case OOK_PULSE_PWM_OSV1:
|
||||
break;
|
||||
case FSK_PULSE_PCM:
|
||||
pulse_demod_pcm(&demod->fsk_pulse_data, demod->r_devs[i]);
|
||||
|
||||
Reference in New Issue
Block a user