/* * Decodes the following encoding scheme: * 10 = 0 * 1100 = 1 */ unsigned ge_decode(r_device *decoder, bitbuffer_t *inbuf, unsigned row, unsigned start, bitbuffer_t *outbuf) { uint8_t *bits = inbuf->bb[row]; unsigned int len = inbuf->bits_per_row[row]; unsigned int ipos = start; while (ipos < len) { uint8_t bit1, bit2; bit1 = bit(bits, ipos++); bit2 = bit(bits, ipos++); if (bit1 == 1 && bit2 == 0) { bitbuffer_add_bit(outbuf, 0); } else if (bit1 == 1 && bit2 == 1) { // Get two more bits bit1 = bit(bits, ipos++); bit2 = bit(bits, ipos++); if (bit1 == 0 && bit2 == 0) { bitbuffer_add_bit(outbuf, 1); } else { break; } } else { break; } } return ipos; }
int main(int argc, char **argv) { fprintf(stderr, "bitbuffer:: test\n"); bitbuffer_t bits = {0}; fprintf(stderr, "TEST: bitbuffer:: The empty buffer\n"); bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Add 1 bit\n"); bitbuffer_add_bit(&bits, 1); bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Add 1 new row\n"); bitbuffer_add_row(&bits); bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Fill row\n"); for (int i=0; i < BITBUF_COLS*8; ++i) { bitbuffer_add_bit(&bits, i%2); } bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Add row and fill 1 column too many\n"); bitbuffer_add_row(&bits); for (int i=0; i <= BITBUF_COLS*8; ++i) { bitbuffer_add_bit(&bits, i%2); } bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Clear\n"); bitbuffer_clear(&bits); bitbuffer_print(&bits); fprintf(stderr, "TEST: bitbuffer:: Add 1 row too many\n"); for (int i=0; i <= BITBUF_ROWS; ++i) { bitbuffer_add_row(&bits); } bitbuffer_add_bit(&bits, 1); bitbuffer_print(&bits); return 0; }
static int lightwave_rf_callback(bitbuffer_t *bitbuffer) { bitrow_t *bb = bitbuffer->bb; // Validate package // Transmitted pulses are always 72 // Pulse 72 (delimiting "1" is not demodulated, as gap becomes End-Of-Message - thus expected length is 71 if ((bitbuffer->bits_per_row[0] == 71) && (bitbuffer->num_rows == 1)) // There should be only one message (and we use the rest...) { // Polarity is inverted bitbuffer_invert(bitbuffer); // Expand all "0" to "10" (bit stuffing) // row_in = 0, row_out = 1 bitbuffer_add_row(bitbuffer); for (unsigned n=0; n < bitbuffer->bits_per_row[0]; ++n) { if (bitrow_get_bit(bb[0], n)) { bitbuffer_add_bit(bitbuffer, 1); } else { bitbuffer_add_bit(bitbuffer, 1); bitbuffer_add_bit(bitbuffer, 0); } } // Check length is correct // Due to encoding there will be two "0"s per byte, thus message grows to 91 bits if (bitbuffer->bits_per_row[1] != 91) return 0; // Check initial delimiter bit is "1" unsigned bit_idx = 0; uint8_t delimiter_bit = bitrow_get_bit(bb[1], bit_idx++); if (delimiter_bit == 0) return 0; // Decode error // Strip delimiter bits // row_in = 1, row_out = 2 bitbuffer_add_row(bitbuffer); for(unsigned n=0; n<10; ++n) { // We have 10 bytes delimiter_bit = bitrow_get_bit(bb[1], bit_idx++); if (delimiter_bit == 0) return 0; // Decode error for(unsigned m=0; m<8; ++m) { bitbuffer_add_bit(bitbuffer, bitrow_get_bit(bb[1], bit_idx++)); } } // Final delimiter bit will be missing - so do not check... // Decode bytes to nibbles // row_in = 2, row_out = 3 bitbuffer_add_row(bitbuffer); for(unsigned n=0; n<10; ++n) { // We have 10 bytes/nibbles int nibble = lightwave_rf_nibble_from_byte(bb[2][n]); if (nibble < 0) { if (debug_output) { fprintf(stderr, "LightwaveRF. Nibble decode error %X, idx: %u\n", bb[2][n], n); bitbuffer_print(bitbuffer); } return 0; // Decode error } for (unsigned m=0; m<4; ++m) { // Add nibble one bit at a time... bitbuffer_add_bit(bitbuffer, (nibble & (8 >> m)) >> (3-m)); } } // Print out generic decode // Decoded nibbles are in row 3 fprintf(stdout, "LightwaveRF:\n"); fprintf(stdout, "ID = 0x%X%X%X\n", bb[3][2], bb[3][3], bb[3][4]); fprintf(stdout, "Subunit = %u\n", (bb[3][1] & 0xF0) >> 4); fprintf(stdout, "Command = %u\n", bb[3][1] & 0x0F); fprintf(stdout, "Parameter = %u\n", bb[3][0]); if (debug_output) { bitbuffer_print(bitbuffer); fprintf(stderr, " Row 0 = Input, Row 1 = Zero bit stuffing, Row 2 = Stripped delimiters, Row 3 = Decoded nibbles\n"); } return 1; }
static void classify_signal() { unsigned int i, k, max = 0, min = 1000000, t; unsigned int delta, count_min, count_max, min_new, max_new, p_limit; unsigned int a[3], b[2], a_cnt[3], a_new[3], b_new[2]; unsigned int signal_distance_data[4000] = {0}; struct protocol_state p = {0}; unsigned int signal_type; if (!signal_pulse_data[0][0]) return; for (i = 0; i < 1000; i++) { if (signal_pulse_data[i][0] > 0) { //fprintf(stderr, "[%03d] s: %d\t e:\t %d\t l:%d\n", //i, signal_pulse_data[i][0], signal_pulse_data[i][1], //signal_pulse_data[i][2]); if (signal_pulse_data[i][2] > max) max = signal_pulse_data[i][2]; if (signal_pulse_data[i][2] <= min) min = signal_pulse_data[i][2]; } } t = (max + min) / 2; //fprintf(stderr, "\n\nMax: %d, Min: %d t:%d\n", max, min, t); delta = (max - min)*(max - min); //TODO use Lloyd-Max quantizer instead k = 1; while ((k < 10) && (delta > 0)) { min_new = 0; count_min = 0; max_new = 0; count_max = 0; for (i = 0; i < 1000; i++) { if (signal_pulse_data[i][0] > 0) { if (signal_pulse_data[i][2] < t) { min_new = min_new + signal_pulse_data[i][2]; count_min++; } else { max_new = max_new + signal_pulse_data[i][2]; count_max++; } } } if (count_min != 0 && count_max != 0) { min_new = min_new / count_min; max_new = max_new / count_max; } delta = (min - min_new)*(min - min_new) + (max - max_new)*(max - max_new); min = min_new; max = max_new; t = (min + max) / 2; fprintf(stderr, "Iteration %d. t: %d min: %d (%d) max: %d (%d) delta %d\n", k, t, min, count_min, max, count_max, delta); k++; } for (i = 0; i < 1000; i++) { if (signal_pulse_data[i][0] > 0) { //fprintf(stderr, "%d\n", signal_pulse_data[i][1]); } } /* 50% decision limit */ if (min != 0 && max / min > 1) { fprintf(stderr, "Pulse coding: Short pulse length %d - Long pulse length %d\n", min, max); signal_type = 2; } else { fprintf(stderr, "Distance coding: Pulse length %d\n", (min + max) / 2); signal_type = 1; } p_limit = (max + min) / 2; /* Initial guesses */ a[0] = 1000000; a[2] = 0; for (i = 1; i < 1000; i++) { if (signal_pulse_data[i][0] > 0) { // fprintf(stderr, "[%03d] s: %d\t e:\t %d\t l:%d\t d:%d\n", // i, signal_pulse_data[i][0], signal_pulse_data[i][1], // signal_pulse_data[i][2], signal_pulse_data[i][0]-signal_pulse_data[i-1][1]); signal_distance_data[i - 1] = signal_pulse_data[i][0] - signal_pulse_data[i - 1][1]; if (signal_distance_data[i - 1] > a[2]) a[2] = signal_distance_data[i - 1]; if (signal_distance_data[i - 1] <= a[0]) a[0] = signal_distance_data[i - 1]; } } min = a[0]; max = a[2]; a[1] = (a[0] + a[2]) / 2; // for (i=0 ; i<1 ; i++) { // b[i] = (a[i]+a[i+1])/2; // } b[0] = (a[0] + a[1]) / 2; b[1] = (a[1] + a[2]) / 2; // fprintf(stderr, "a[0]: %d\t a[1]: %d\t a[2]: %d\t\n",a[0],a[1],a[2]); // fprintf(stderr, "b[0]: %d\t b[1]: %d\n",b[0],b[1]); k = 1; delta = 10000000; while ((k < 10) && (delta > 0)) { for (i = 0; i < 3; i++) { a_new[i] = 0; a_cnt[i] = 0; } for (i = 0; i < 1000; i++) { if (signal_distance_data[i] > 0) { if (signal_distance_data[i] < b[0]) { a_new[0] += signal_distance_data[i]; a_cnt[0]++; } else if (signal_distance_data[i] < b[1] && signal_distance_data[i] >= b[0]) { a_new[1] += signal_distance_data[i]; a_cnt[1]++; } else if (signal_distance_data[i] >= b[1]) { a_new[2] += signal_distance_data[i]; a_cnt[2]++; } } } // fprintf(stderr, "Iteration %d.", k); delta = 0; for (i = 0; i < 3; i++) { if (a_cnt[i]) a_new[i] /= a_cnt[i]; delta += (a[i] - a_new[i])*(a[i] - a_new[i]); // fprintf(stderr, "\ta[%d]: %d (%d)", i, a_new[i], a[i]); a[i] = a_new[i]; } // fprintf(stderr, " delta %d\n", delta); if (a[0] < min) { a[0] = min; // fprintf(stderr, "Fixing a[0] = %d\n", min); } if (a[2] > max) { a[0] = max; // fprintf(stderr, "Fixing a[2] = %d\n", max); } // if (a[1] == 0) { // a[1] = (a[2]+a[0])/2; // fprintf(stderr, "Fixing a[1] = %d\n", a[1]); // } // fprintf(stderr, "Iteration %d.", k); for (i = 0; i < 2; i++) { // fprintf(stderr, "\tb[%d]: (%d) ", i, b[i]); b[i] = (a[i] + a[i + 1]) / 2; // fprintf(stderr, "%d ", b[i]); } // fprintf(stderr, "\n"); k++; } if (override_short) { p_limit = override_short; a[0] = override_short; } if (override_long) { a[1] = override_long; } fprintf(stderr, "\nShort distance: %d, long distance: %d, packet distance: %d\n", a[0], a[1], a[2]); fprintf(stderr, "\np_limit: %d\n", p_limit); bitbuffer_clear(&p.bits); if (signal_type == 1) { for (i = 0; i < 1000; i++) { if (signal_distance_data[i] > 0) { if (signal_distance_data[i] < (a[0] + a[1]) / 2) { // fprintf(stderr, "0 [%d] %d < %d\n",i, signal_distance_data[i], (a[0]+a[1])/2); bitbuffer_add_bit(&p.bits, 0); } else if ((signal_distance_data[i] > (a[0] + a[1]) / 2) && (signal_distance_data[i] < (a[1] + a[2]) / 2)) { // fprintf(stderr, "0 [%d] %d > %d\n",i, signal_distance_data[i], (a[0]+a[1])/2); bitbuffer_add_bit(&p.bits, 1); } else if (signal_distance_data[i] > (a[1] + a[2]) / 2) { // fprintf(stderr, "0 [%d] %d > %d\n",i, signal_distance_data[i], (a[1]+a[2])/2); bitbuffer_add_row(&p.bits); } } } bitbuffer_print(&p.bits); } if (signal_type == 2) { for (i = 0; i < 1000; i++) { if (signal_pulse_data[i][2] > 0) { if (signal_pulse_data[i][2] < p_limit) { // fprintf(stderr, "0 [%d] %d < %d\n",i, signal_pulse_data[i][2], p_limit); bitbuffer_add_bit(&p.bits, 0); } else { // fprintf(stderr, "1 [%d] %d > %d\n",i, signal_pulse_data[i][2], p_limit); bitbuffer_add_bit(&p.bits, 1); } if ((signal_distance_data[i] >= (a[1] + a[2]) / 2)) { // fprintf(stderr, "\\n [%d] %d > %d\n",i, signal_distance_data[i], (a[1]+a[2])/2); bitbuffer_add_row(&p.bits); } } } bitbuffer_print(&p.bits); } for (i = 0; i < 1000; i++) { signal_pulse_data[i][0] = 0; signal_pulse_data[i][1] = 0; signal_pulse_data[i][2] = 0; signal_distance_data[i] = 0; } };