1 /** @file
2     Example of a generic remote using PT2260/PT2262 SC2260/SC2262 EV1527 protocol.
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9 */
10 
11 /**
12 Example of a generic remote using PT2260/PT2262 SC2260/SC2262 EV1527 protocol.
13 
14 fixed bit width of 1445 us
15 short pulse is 357 us (1/4th)
16 long pulse is 1064 (3/4th)
17 a packet is 15 pulses, the last pulse (short) is sync pulse
18 packet gap is 11.5 ms
19 
20 note that this decoder uses:
21 short-short (1 1 by the demod) as 0 (per protocol),
22 short-long (1 0 by the demod) as 1 (F per protocol),
23 long-long (0 0 by the demod) not used (1 per protocol).
24 */
25 
26 #include "decoder.h"
27 
waveman_callback(r_device * decoder,bitbuffer_t * bitbuffer)28 static int waveman_callback(r_device *decoder, bitbuffer_t *bitbuffer)
29 {
30     data_t *data;
31     uint8_t *b = bitbuffer->bb[0];
32     uint8_t nb[3] = {0}; // maps a pair of bits to two states, 1 0 -> 1 and 1 1 -> 0
33     char id_str[2];
34     int i;
35 
36     /* TODO: iterate through all rows */
37 
38     /* Reject codes of wrong length */
39     if (25 != bitbuffer->bits_per_row[0])
40       return DECODE_ABORT_LENGTH;
41 
42     /*
43      * Catch the case triggering false positive for other transmitters.
44      * example: Brennstuhl RCS 2044SN
45      * TODO: is this message valid at all??? if not then put more validation below
46      *       instead of this special case
47      */
48     if (0xFF == b[0] &&
49             0xFF == b[1] &&
50             0xFF == b[2])
51         return DECODE_ABORT_EARLY;
52 
53     /* Test if the bit stream has every even bit set to one */
54     if (((b[0] & 0xaa) != 0xaa) || ((b[1] & 0xaa) != 0xaa) || ((b[2] & 0xaa) != 0xaa))
55         return DECODE_FAIL_SANITY;
56 
57     /* Extract data from the bit stream */
58     for (i = 0; i < 3; ++i) {
59         nb[i] = ((b[i] & 0x40) ? 0x00 : 0x01)
60                 | ((b[i] & 0x10) ? 0x00 : 0x02)
61                 | ((b[i] & 0x04) ? 0x00 : 0x04)
62                 | ((b[i] & 0x01) ? 0x00 : 0x08);
63     }
64 
65     id_str[0] = 'A' + nb[0];
66     id_str[1] = '\0';
67 
68     /* clang-format off */
69     data = data_make(
70             "model",    "",     DATA_STRING,    "Waveman-Switch",
71             "id",       "",     DATA_STRING,    id_str,
72             "channel",  "",     DATA_INT,       (nb[1] >> 2) + 1,
73             "button",   "",     DATA_INT,       (nb[1] & 3) + 1,
74             "state",    "",     DATA_STRING,    (nb[2] == 0xe) ? "on" : "off",
75             NULL);
76     /* clang-format on */
77     decoder_output_data(decoder, data);
78 
79     return 1;
80 }
81 
82 static char *output_fields[] = {
83     "model",
84     "id",
85     "channel",
86     "button",
87     "state",
88     NULL
89 };
90 
91 r_device waveman = {
92     .name           = "Waveman Switch Transmitter",
93     .modulation     = OOK_PULSE_PWM,
94     .short_width    = 357,
95     .long_width     = 1064,
96     .gap_limit      = 1400,
97     .reset_limit    = 12000,
98     .sync_width     = 0,    // No sync bit used
99     .tolerance      = 200,  // us
100     .decode_fn      = &waveman_callback,
101     .disabled       = 0,
102     .fields         = output_fields
103 };
104