Merge pull request #138 from ortylp/Brennstuhl_RCS_2044
support Brennstuhl RCS 2044 remote control
This commit is contained in:
commit
9f5c6a86ce
5 changed files with 210 additions and 7 deletions
|
@ -73,6 +73,7 @@ Running:
|
|||
[21] Calibeur RF-104 Sensor
|
||||
[22] X10 RF
|
||||
[23] DSC (Digital Security Controls)
|
||||
[24] Brennstuhl RCS 2044
|
||||
|
||||
|
||||
Examples:
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
DECL(ambient_weather) \
|
||||
DECL(calibeur_RF104) \
|
||||
DECL(X10_RF) \
|
||||
DECL(DSC)
|
||||
DECL(DSC) \
|
||||
DECL(brennstuhl_rcs_2044)
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -42,6 +42,7 @@ add_executable(rtl_433
|
|||
devices/calibeur.c
|
||||
devices/x10_rf.c
|
||||
devices/dsc.c
|
||||
devices/brennstuhl_rcs_2044.c
|
||||
)
|
||||
|
||||
target_link_libraries(rtl_433
|
||||
|
|
186
src/devices/brennstuhl_rcs_2044.c
Normal file
186
src/devices/brennstuhl_rcs_2044.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include "rtl_433.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Brennstuhl RCS 2044 remote control on 433.92MHz
|
||||
*
|
||||
* Copyright (C) 2015 Paul Ortyl
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Receiver for the "RCS 2044 N Comfort Wireless Controller Set" sold under
|
||||
* the "Brennstuhl" brand.
|
||||
*
|
||||
* The protocol is also implemented for raspi controlled transmitter on 433.92 MHz:
|
||||
* https://github.com/xkonni/raspberry-remote
|
||||
*/
|
||||
|
||||
static int brennstuhl_rcs_2044_process_row(int row, const bitbuffer_t *bitbuffer);
|
||||
static int brennstuhl_rcs_2044_callback(bitbuffer_t *bitbuffer)
|
||||
{
|
||||
int counter = 0;
|
||||
for(int row=0; row<bitbuffer->num_rows; row++)
|
||||
counter += brennstuhl_rcs_2044_process_row(row, bitbuffer);
|
||||
return counter;
|
||||
}
|
||||
|
||||
static int brennstuhl_rcs_2044_process_row(int row, const bitbuffer_t *bitbuffer)
|
||||
{
|
||||
const uint8_t *b = bitbuffer->bb[row];
|
||||
const int length = bitbuffer->bits_per_row[row];
|
||||
/* Two bits map to 2 states, 0 1 -> 0 and 1 1 -> 1 */
|
||||
int i;
|
||||
uint8_t nb[3] = {0};
|
||||
|
||||
#if 0
|
||||
{
|
||||
// print raw bit squence for debug purposes (before exclusion of invalid sequenced is executed)
|
||||
time_t time_now;
|
||||
char time_str[LOCAL_TIME_BUFLEN];
|
||||
time(&time_now);
|
||||
local_time_str(time_now, time_str);
|
||||
fprintf(stdout, "%s Brennstuhl RCS 2044: received RAW bit sequence (%d bits): ", time_str, length);
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
for(int p=7; p>=0; p--)
|
||||
fprintf(stdout, "%d", (b[i]>>p ) & 0x1);
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
fprintf(stdout, "%s Brennstuhl RCS 2044: received RAW bit sequence (%d bits): ", time_str, length);
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
for(int p=7; p>=0; p--)
|
||||
if (p%2)
|
||||
fprintf(stdout, ".");
|
||||
else
|
||||
fprintf(stdout, "%d", (b[i]>>p ) & 0x1);
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Test bit pattern for every second bit being 1 */
|
||||
if ( 25 != length
|
||||
|| (b[0]&0xaa) != 0xaa
|
||||
|| (b[1]&0xaa) != 0xaa
|
||||
|| (b[2]&0xaa) != 0xaa
|
||||
|| (b[3] != 0x80) )
|
||||
return 0; /* something is wrong, exit now */
|
||||
|
||||
#if 0 && !defined(NDEBUG)
|
||||
{
|
||||
// print raw bit squence for debug purposes (before exclusion of invalid sequenced is executed)
|
||||
time_t time_now;
|
||||
char time_str[LOCAL_TIME_BUFLEN];
|
||||
time(&time_now);
|
||||
local_time_str(time_now, time_str);
|
||||
fprintf(stdout, "%s Brennstuhl RCS 2044: received bit sequence: ", time_str);
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
for(int p=6; p>=0; p-=2)
|
||||
fprintf(stdout, "%d", (b[i]>>p ) & 0x1);
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Only odd bits contain information, even bits are set to 1
|
||||
* First 5 odd bits contain system code (the dip switch on the remote),
|
||||
* following 5 odd bits code button row pressed on the remote,
|
||||
* following 2 odd bits code button column pressed on the remote.
|
||||
*
|
||||
* One can press many buttons at a time and the corresponding code will be sent.
|
||||
* In the code below only use of a single button at a time is reported,
|
||||
* all other messages are discarded as invalid.
|
||||
*/
|
||||
|
||||
/* extract bits for system code */
|
||||
int system_code[] =
|
||||
{
|
||||
b[0]>>6 & 1,
|
||||
b[0]>>4 & 1,
|
||||
b[0]>>2 & 1,
|
||||
b[0] & 1,
|
||||
b[1]>>6 & 1
|
||||
};
|
||||
|
||||
/* extract bits for pressed key row */
|
||||
int control_key[] =
|
||||
{
|
||||
b[1]>>4 & 1, /* Control Key A */
|
||||
b[1]>>2 & 1, /* Control Key B */
|
||||
b[1] & 1, /* Control Key C */
|
||||
b[2]>>6 & 1, /* Control Key D */
|
||||
b[2]>>4 & 1, /* Control Key E (does not exists on the remote, but can
|
||||
be set and is accepted by receiver) */
|
||||
};
|
||||
|
||||
/* extrat on/off bits (first or second key column on the remote */
|
||||
int on = b[2]>>2 & 1;
|
||||
int off = b[2] & 1;
|
||||
|
||||
{
|
||||
/* Test if the message is valid. It is possible to press multiple keys on the
|
||||
* remote at the same time. As all keys are transmitted orthogonally, this
|
||||
* information can be transmitted. This use case is not the usual use case
|
||||
* so we can use it for validation of the message:
|
||||
* ONLY ONE KEY AT A TIME IS ACCEPTED.
|
||||
*/
|
||||
int found=0;
|
||||
for( size_t i=0; i<sizeof(control_key)/sizeof(*control_key); i++)
|
||||
{
|
||||
if (control_key[i]) {
|
||||
if (found)
|
||||
return 0; /* at least two buttons have been pressed, reject the message */
|
||||
else
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (! (on ^ off ) )
|
||||
return 0; /* Pressing simultaneously ON and OFF key is not usefull either */
|
||||
}
|
||||
|
||||
char key = 0;
|
||||
if (control_key[0]) key = 'A';
|
||||
else if (control_key[1]) key = 'B';
|
||||
else if (control_key[2]) key = 'C';
|
||||
else if (control_key[3]) key = 'D';
|
||||
else if (control_key[4]) key = 'E';
|
||||
else return 0; /* None of the keys has been pressed and we still received a message.
|
||||
Skip it. It happens sometimes as the last code repetition */
|
||||
|
||||
{
|
||||
time_t time_now;
|
||||
char time_str[LOCAL_TIME_BUFLEN];
|
||||
time(&time_now);
|
||||
local_time_str(time_now, time_str);
|
||||
fprintf(stdout, "%s Brennstuhl RCS 2044: system code: %d%d%d%d%d. key: %c, state: %s\n",
|
||||
time_str,
|
||||
system_code[0], system_code[1], system_code[2], system_code[3], system_code[4],
|
||||
key,
|
||||
on ? "ON" : ( off ? "OFF" : "BOTH" ) /* "BOTH" is excluded above, but leave it here for debug purposes */
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
r_device brennstuhl_rcs_2044 = {
|
||||
.name = "Brennstuhl RCS 2044",
|
||||
.modulation = OOK_PULSE_PWM_RAW,
|
||||
.short_limit = 150,
|
||||
.long_limit = 1000,
|
||||
.reset_limit = 1000,
|
||||
.json_callback = &brennstuhl_rcs_2044_callback,
|
||||
.disabled = 0,
|
||||
.demod_arg = 0,
|
||||
};
|
|
@ -1,17 +1,31 @@
|
|||
#include "rtl_433.h"
|
||||
|
||||
static int waveman_callback(bitbuffer_t *bitbuffer) {
|
||||
bitrow_t *bb = bitbuffer->bb;
|
||||
uint8_t *b = bitbuffer->bb[0];
|
||||
/* Two bits map to 2 states, 0 1 -> 0 and 1 1 -> 1 */
|
||||
int i;
|
||||
uint8_t nb[3] = {0};
|
||||
|
||||
if (((bb[0][0]&0x55)==0x55) && ((bb[0][1]&0x55)==0x55) && ((bb[0][2]&0x55)==0x55) && ((bb[0][3]&0x55)==0x00)) {
|
||||
/*
|
||||
* Catch the case triggering false positive for other transmitters.
|
||||
* example: Brennstuhl RCS 2044SN
|
||||
* @todo is this message valid at all??? if not then put more validation below
|
||||
* instead of this special case
|
||||
*/
|
||||
if ( 24 == bitbuffer->bits_per_row[0] &&
|
||||
0xFF == b[0] &&
|
||||
0xFF == b[1] &&
|
||||
0xFF == b[2] )
|
||||
return 0;
|
||||
|
||||
/* Test if the bit stream conforms to the rule of every odd bit being set to one */
|
||||
if (((b[0]&0x55)==0x55) && ((b[1]&0x55)==0x55) && ((b[2]&0x55)==0x55) && ((b[3]&0x55)==0x00)) {
|
||||
/* Extract data from the bit stream */
|
||||
for (i=0 ; i<3 ; i++) {
|
||||
nb[i] |= ((bb[0][i]&0xC0)==0xC0) ? 0x00 : 0x01;
|
||||
nb[i] |= ((bb[0][i]&0x30)==0x30) ? 0x00 : 0x02;
|
||||
nb[i] |= ((bb[0][i]&0x0C)==0x0C) ? 0x00 : 0x04;
|
||||
nb[i] |= ((bb[0][i]&0x03)==0x03) ? 0x00 : 0x08;
|
||||
nb[i] |= ((b[i]&0xC0)==0xC0) ? 0x00 : 0x01;
|
||||
nb[i] |= ((b[i]&0x30)==0x30) ? 0x00 : 0x02;
|
||||
nb[i] |= ((b[i]&0x0C)==0x0C) ? 0x00 : 0x04;
|
||||
nb[i] |= ((b[i]&0x03)==0x03) ? 0x00 : 0x08;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Remote button event:\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue