Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
HTC Vive Watchman Hacking Codes!
So, the way this goes is I post my AVR code, then I post what the HTC Vive does.
The output is: POST 0: (# of bytes) (IMU Timecode MSBs) (All raw light data)
(All raw light data ends with [3 bytes, LSB timecode] [OTA CRC (probably ignore)])
Events (TIME): (LED CODE 1)/(TIME CODE 1/TIMECODE 2)/(LED CODE 2)/(TIME CODE 3/TIMECODE 4)...
//NOTICE: The funky encoding of the numbers, and the fact that paramters are read from the end of the data going forward.
//We know we're done when the # of parameters read is (# of bytes left*2)-1
tikingfritsthecat suggests reading: https://en.wikipedia.org/wiki/Variable-length_quantity
For all of the following we will use _delay_ms(10) between messages.
PARAMETER FIELDS are encoded, read from end going forward. If MSB is 1 (i.e. 0x80) it is done! If not, then need to read next byte.
// First look at 0x04. There will be another byte because it is less than
// 128!
// 0x04<<7 = 0x200
// Because 0x81 is >= 128, it's a terminator.
// 0x200 | 0x81 = 0x281 << The actual value
//
marker = 40;
do{ PORTB = LED48;
marker--; PORTB = 0; } while( marker );
_delay_us(10);
marker = 40;
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
_delay_us(10);
marker = 40;
do{ PORTB = LED40;
marker--; PORTB = 0; } while( marker );
Produces:
POST 0: 16 (f62d) - 40 50 48 b0 05 a2 02 c1 05 c7 03 f1 03 65 9b 2f 80 03 2b 58
Events (-164652187): 48/( 688/ 290)50/( 705/ 455)40/( 497/ -1)
POST 0: 16 (f633) - 40 50 48 b0 05 a2 02 c2 05 cb 03 ec 03 63 f4 33 28 40 ed c5
Events (-164367261): 48/( 688/ 290)50/( 706/ 459)40/( 492/ -1)
POST 0: 16 (f636) - 40 50 48 b2 05 a3 02 c3 05 c5 03 f5 03 57 4e 38 d2 2e c9 30
Events (-164082089): 48/( 690/ 291)50/( 707/ 453)40/( 501/ -1)
POST 0: 16 (f63b) - 40 50 48 b2 05 a3 02 c4 05 c6 03 f4 03 c6 a8 3c fe bd ca c1
Events (-163796794): 48/( 690/ 291)50/( 708/ 454)40/( 500/ -1)
POST 0: 16 (f63e) - 40 50 48 b1 05 a3 02 c3 05 c1 03 f8 03 40 02 41 fd 6d e0 08
Events (-163511744): 48/( 689/ 291)50/( 707/ 449)40/( 504/ -1)
marker = 40; //Length of time for following
do{ PORTB = LED48;
marker--; PORTB = 0; } while( marker );
vvvvvvvv
Events (-890299908): 48/( 683/ -1)
POST 0: 6 (caf1) - 48 ac 05 bd 6b f3 9e 3b ab c6
Events (-890016835): 48/( 684/ -1)
POST 0: 6 (caf6) - 48 ac 05 f2 bd f7 dc 46 0e 7f
Events (-889733646): 48/( 684/ -1)
POST 0: 6 (caf9) - 48 ac 05 73 10 fc 7a 78 6d 93
Events (-889450381): 48/( 684/ -1)
marker = 40; //Length of time for following
do{ PORTB = LED48;
marker--; PORTB = 0; } while( marker );
marker = 40; //Length of time for following
do{ PORTB = LED50 | LED48;
marker--; PORTB = 0; } while( marker );
marker = 40; //Length of time for following
do{ PORTB = LED48;
marker--; PORTB = 0; } while( marker );
PRODUCES:::::
POST 0: 11 (b03d) - 4a 50 b8 05 c1 05 b4 05 b6 b1 3d e8 dc 86 2e
Events (-1338134090): 50/( 696/ 705)4a/( 692/ -1)
POST 0: 11 (b040) - 4a 50 b6 05 c0 05 b2 05 bf 09 42 5f 9b a8 e3
Events (-1337849409): 50/( 694/ 704)4a/( 690/ -1)
POST 0: 11 (b046) - 4a 50 b7 05 c0 05 b1 05 1d 61 46 9e d5 b2 5b
Events (-1337564899): 50/( 695/ 704)4a/( 689/ -1)
marker = 40; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
marker = 40; //Length of time for following
do{ PORTB = LED50 | LED48;
marker--; PORTB = 0; } while( marker );
marker = 40; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
PRODUCES:
POST 0: 11 (f21f) - 52 48 cb 05 ac 05 c1 05 21 5b 20 fe 55 89 00
Events (-232760543): 48/( 715/ 684)52/( 705/ -1)
POST 0: 11 (f222) - 52 48 cb 05 ac 05 c0 05 13 b2 24 2b 65 ee 99
Events (-232476141): 48/( 715/ 684)52/( 704/ -1)
POST 0: 11 (f228) - 52 48 cb 05 ab 05 c1 05 ee 08 29 56 7b 9e 70
Events (-232191762): 48/( 715/ 683)52/( 705/ -1)
POST 0: 11 (f22b) - 52 48 ca 05 ab 05 c0 05 97 5f 2d c4 01 c6 5c
Events (-231907433): 48/( 714/ 683)52/( 704/ -1)
marker = 255; //Length of time for following
for( k = 0; k < 12; k++ )
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
POST 0: 7 (6ea8) - 50 c5 7b 03 f7 a7 a0 f1 12 65 81
Events (1856022519): 50/(64965/ -1)
POST 0: 7 (6eae) - 50 c5 7b 03 81 f3 a5 37 cd 97 f1
Events (1856369537): 50/(64965/ -1)
BUT
marker = 255; //Length of time for following
for( k = 0; k < 13; k++ )
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
PRODUCES NOTHING AT ALL!!!!
Looks like maximum for timing is 65536.
marker = 80; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
marker = 90; //Length of time for following
do{ PORTB = LED50 | LED48;
marker--; PORTB = 0; } while( marker );
marker = 100; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
produces;
POST 0: 12 (e16d) - 48 50 fe 24 cd 25 11 91 0c 6a 24 6f b8 5a fd 69
Events (-512809878): 50/( 4734/283341)48/( 1553/ -1)
POST 0: 12 (e172) - 48 50 f7 24 b2 26 11 93 0c 88 84 73 8c ac ad 52
Events (-512523128): 50/( 4727/283442)48/( 1555/ -1)
POST 0: 12 (e175) - 48 50 ff 24 b3 26 11 8f 0c a6 e4 77 94 7f a1 10
Events (-512236378): 50/( 4735/283443)48/( 1551/ -1)
POST 0: 12 (e17b) - 48 50 f4 24 8c 24 11 91 0c 9a 43 7c 70 a6 51 63
Events (-511949926): 50/( 4724/283148)48/( 1553/ -1)
POST 0: 12 (e17e) - 48 50 f7 24 84 27 11 90 0c 06 a4 80 ab 7b 91 b2
Events (-511663098): 50/( 4727/283524)48/( 1552/ -1)
NOTE PARAMETER 2 IS NOT BETWEEN 0 and 65535 (it's value (above 65536) is 4.)
marker = 30; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
marker = 20; //Length of time for following
do{ PORTB = LED50 | LED48;
marker--; PORTB = 0; } while( marker );
marker = 10; //Length of time for following
do{ PORTB = LED50;
marker--; PORTB = 0; } while( marker );
Produces:
POST 0: 11 (632a) - 52 48 9f 04 c3 02 ba 01 58 40 2d 7a 4a 80 67
Events (1663909976): 48/( 543/ 323)52/( 186/ -1)
POST 0: 11 (6330) - 52 48 9f 04 c5 02 ba 01 16 92 31 ef 8e 7b 75
Events (1664193046): 48/( 543/ 325)52/( 186/ -1)
POST 0: 11 (6333) - 52 48 9f 04 c4 02 b9 01 87 e4 35 b1 e2 cf 45
Events (1664476295): 48/( 543/ 324)52/( 185/ -1)
...wat??
marker = 30; //Length of time for following
do{ PORTB = LED40;
marker--; PORTB = 0; } while( marker );
marker = 20; //Length of time for following
do{ PORTB = LED40 | LED48;
marker--; PORTB = 0; } while( marker );
marker = 10; //Length of time for following
do{ PORTB = LED40;
marker--; PORTB = 0; } while( marker );
Events (2081688601): 48/( 330/ 323)42/( 153/ -1)
POST 0: 11 (7c17) - 42 48 c8 02 c5 02 98 01 a0 5f 18 b4 65 3a 41
Events (2081972128): 48/( 328/ 325)42/( 152/ -1)
POST 0: 11 (7c1a) - 42 48 cb 02 c3 02 99 01 05 b3 1c 0b 5a 16 37
Events (2082255621): 48/( 331/ 323)42/( 153/ -1)
#define DO_MARKER( time, LEDS ) \
marker = time; do { PORTB = LEDs; marker--; PORTB = 0; } while( marker );
DO_MARKER( 30, LED48 );
DO_MARKER( 20, LED48|LED40 );
DO_MARKER( 10, LED48 );
POST 0: 11 (7bb4) - 4a 40 bb 04 9a 02 bc 01 cf 0c b6 56 5c 4d 87
Events (2075528399): 40/( 571/ 282)4a/( 188/ -1)
DO_MARKER( 30, LED48 );
DO_MARKER( 20, LED40|LED48 );
DO_MARKER( 10, LED40 );
Events ( 615414066): 49/( 676/ 188)41/( 158/ -1)
DO_MARKER( 30, LED48 );
_delay_us(50);
DO_MARKER( 70, LED40 );
Events (-1151761741): 48/( 512/ 1510)40/( 1115/ -1)
DO_MARKER( 30, LED48 );
DO_MARKER( 20, LED50|LED48 );
DO_MARKER( 10, LED50 );
Events (1259200831): 49/( 522/ 343)51/( 181/ -1)
DO_MARKER( 30, LED40 );
DO_MARKER( 20, LED50|LED40 );
DO_MARKER( 10, LED50 );
POST 0: 11 (a3b6) - 51 41 b5 03 c5 02 c9 01 8e 3f b8 86 85 bb b7
Events (-1548206194): 41/( 437/ 325)51/( 201/ -1)
DO_MARKER( 20, LED40 );
DO_MARKER( 20, LED50|LED40 );
DO_MARKER( 20, LED50 );
POST 0: 11 (dce8) - 51 41 86 02 c4 02 f8 02 90 94 eb b9 24 5b 63
Events (-588540784): 41/( 262/ 324)51/( 376/ -1)
DO_MARKER( 21, LED40 );
DO_MARKER( 21, LED50|LED40 );
DO_MARKER( 21, LED50 );
POST 0: 11 (61e6) - 51 41 93 02 d4 02 89 03 8d da e6 b2 12 4b 0e
Events (1642519181): 41/( 275/ 340)51/( 393/ -1)
DO_MARKER( 22, LED40 );
DO_MARKER( 22, LED50|LED40 );
DO_MARKER( 22, LED50 );
POST 0: 11 (a35b) - 51 41 9f 02 e7 02 99 03 2c f0 5d 5d f4 45 0d
Events (-1554124756): 41/( 287/ 359)51/( 409/ -1)
DO_MARKER( 8, LED40 );
DO_MARKER( 8, LED50|LED40 );
DO_MARKER( 8, LED50 );
Events (-220957990): 41/( 45/ 111)51/( 171/ -1)
DO_MARKER( 9, LED40 );
DO_MARKER( 9, LED50|LED40 );
DO_MARKER( 9, LED50 );
POST 0: 10 (3343) - 51 41 bf 81 01 bb 01 65 62 43 b6 8c d0 8e
Events ( 860054117): 41/( 63/ 129)51/( 187/ -1)
DO_MARKER( 9, LED50 );
DO_MARKER( 9, LED50|LED40 );
DO_MARKER( 9, LED40 );
POST 0: 11 (6cec) - 41 51 a8 01 9a 01 92 01 71 a6 ec 5f 50 40 67
Events (1827448433): 51/( 168/ 154)41/( 146/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 20, LED48|LED40 );
DO_MARKER( 30, LED40 );
POST 0: 11 (0508) - 42 48 b2 01 c4 02 93 04 24 39 09 5a e4 5e af
Events ( 84490532): 48/( 178/ 324)42/( 531/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 20, LED48|LED40 );
DO_MARKER( 10, LED40 );
POST 0: 11 (65ab) - 42 48 b1 01 c6 02 b3 01 f0 68 ae 3a 89 73 1e
Events (1705928944): 48/( 177/ 326)42/( 179/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 40, LED48|LED40 );
DO_MARKER( 80, LED40 );
POST 0: 11 (afe8) - 42 48 af 01 90 05 85 0b 65 cc e7 3b c6 92 4f
Events (-1343763355): 48/( 175/ 656)42/( 1413/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 80, LED50 );
POST 0: 11 (257b) - 51 41 94 01 ad 05 8d 0b 48 43 7e 47 ae ab e6
Events ( 629031752): 41/( 148/ 685)51/( 1421/ -1)
POST 0: 11 (2581) - 51 41 95 01 ad 05 8e 0b 1b 9b 82 d6 9e 4c b5
Events ( 629316379): 41/( 149/ 685)51/( 1422/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 80, LED40 );
POST 0: 11 (963b) - 42 50 95 01 c2 05 ef 0a 1b 1f 3b cc 8e 19 e9
Events (-1774510309): 50/( 149/ 706)42/( 1391/ -1)
POST 0: 11 (963e) - 42 50 95 01 c1 05 ee 0a 8c 76 3f 32 fe 46 87
Events (-1774225780): 50/( 149/ 705)42/( 1390/ -1)
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 40, LED40 );
Events (-415661420): 40/( 4885/282886)50/( 705/ 700)50/( 705/ 706)50/( 700/ -1)
POST 0: 22 (e73d) - 50 50 50 40 94 26 b0 23 11 c2 05 bd 05 c1 05 c4 05 bd 05 b8 e4 3d 20 92 0c ca
Events (-415374152): 40/( 4884/283056)50/( 706/ 701)50/( 705/ 708)50/( 701/ -1)
POST 0: 22 (e740) - 50 50 50 40 9c 26 a6 23 11 c1 05 be 05 c1 05 c4 05 bc 05 d3 46 42 1b 23 6d ec
Events (-415086893): 40/( 4892/283046)50/( 705/ 702)50/( 705/ 708)50/( 700/ -1)
POST 0: 22 (e746) - 50 50 50 40 9c 26 db 21 11 c2 05 bc 05 c1 05 c1 05 bb 05 1e a8 46 88 30 f0 fc
Events (-414799842): 40/( 4892/282843)50/( 706/ 700)50/( 705/ 705)50/( 699/ -1)
WWOOHHH LOOK AT THE BIG NUBMERR ^^^^^
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED50|LED40 );
DO_MARKER( 40, LED40 );
POST 0: 17 (35a1) - 50 50 40 93 1b ab 23 11 c1 05 bd 05 c1 05 70 9d a2 67 b3 6a ce
Events ( 899849584): 40/( 3475/283051)50/( 705/ 701)50/( 705/ -1)
^^^ Big numberrrrr
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED50 );
POST 0: 11 (3ee8) - 51 49 a6 05 ac 05 d1 05 6f 51 ea 6d 4c 11 df
Events (1055543663): 49/( 678/ 684)51/( 721/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
POST 0: 22 (d156) - 50 50 50 48 8b 26 bb 22 11 be 05 bc 05 bf 05 c2 05 bb 05 04 29 57 89 58 68 fe
Events (-782817020): 48/( 4875/282939)50/( 702/ 700)50/( 703/ 706)50/( 699/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
POST 0: 22 (97f3) - 40 40 40 48 a1 26 fe 21 11 bb 05 be 05 be 05 c2 05 bb 05 35 5f f5 0a fe 8c 23
Events (-1745526987): 48/( 4897/282878)40/( 699/ 702)40/( 702/ 706)40/( 699/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
Events (-573114289): 48/( 4898/282829)40/( 699/ 707)50/( 697/ 715)40/( 694/ -1)
POST 0: 22 (ddd9) - 40 50 40 48 a2 26 82 21 11 bb 05 c1 05 b9 05 ca 05 b6 05 37 59 db 02 ba 5b c3
Events (-572827337): 48/( 4898/282754)40/( 699/ 705)50/( 697/ 714)40/( 694/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
POST 0: 17 (3927) - 50 40 48 a1 1b a4 1f 11 bb 05 c1 05 ba 05 7a 99 27 2b f0 8a d0
Events ( 958896506): 48/( 3489/282532)40/( 699/ 705)50/( 698/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
_delay_us(10);
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED50|LED48 );
DO_MARKER( 40, LED48 );
Events (1353710091): 40/( 695/ 699)4a/( 689/ 275)50/( 727/ 697)4a/( 690/ -1)
POST 0: 21 (50b2) - 4a 50 4a 40 b8 05 bc 05 b0 05 94 02 d7 05 ba 05 b2 05 14 59 b4 75 86 56 a5
Events (1353996564): 40/( 696/ 700)4a/( 688/ 276)50/( 727/ 698)4a/( 690/ -1)
POST 0: 21 (50b8) - 4a 50 4a 40 b8 05 bb 05 b2 05 93 02 d7 05 ba 05 b2 05 05 b9 b8 1b ea 08 c6
Events (1354283269): 40/( 696/ 699)4a/( 690/ 275)50/( 727/ 698)4a/( 690/ -1)
DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
POST 0: 17 (499b) - 42 50 48 9f 1b bd 1f 11 bf 05 bd 05 b9 05 e7 cd 9c 01 37 d9 f8
Events (1235013095): 48/( 3487/282557)50/( 703/ 701)42/( 697/ -1)
POST 0: 17 (499e) - 42 50 48 9f 1b 87 1f 11 c0 05 be 05 ba 05 5a 28 a1 60 5f db 06
Events (1235298394): 48/( 3487/282503)50/( 704/ 702)42/( 698/ -1)
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40 );
POST 0: 17 (eccf) - 4a 50 40 b2 1b c8 20 11 af 05 bd 05 ad 05 9a c7 d1 1a 2b 09 9b
Events (-321796198): 40/( 3506/282696)50/( 687/ 701)4a/( 685/ -1)
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40 );
POST 0: 22 (91ed) - 50 50 42 48 cf 05 92 1b c4 05 bb 22 11 bd 05 b7 05 be 05 b4 6e ed 89 d4 56 85
Events (-1846710604): 48/( 719/ 3474)42/( 708/282939)50/( 701/ 695)50/( 702/ -1)
POST 0: 22 (91f0) - 50 50 42 48 ce 05 8d 1b c2 05 d3 21 11 be 05 b8 05 be 05 2b cd f1 66 d1 06 5b
Events (-1846424277): 48/( 718/ 3469)42/( 706/282835)50/( 702/ 696)50/( 702/ -1)
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40 );
POST 0: 22 (1ed9) - 50 50 42 48 cf 05 92 26 c2 05 bf 25 11 bf 05 ba 05 c0 05 80 85 da 46 01 54 29
Events ( 517637504): 48/( 719/ 4882)42/( 706/283327)50/( 703/ 698)50/( 704/ -1)
POST 2: 6 (1edc) - 50 ba 05 fa 8a da e6 b3 9b 6c
Events ( 517638906): 50/( 698/ -1)
DO_MARKER( 40, LED40 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED40|LED48|LED50 );
DO_MARKER( 40, LED40|LED50 ); <<<< Check this out!
DO_MARKER( 40, LED40 );
Events (-938793947): 40/( 4907/282843)50/( 688/ 703)4b/( 699/ 691)51/( 712/ -1)
POST 1: 22 (c80e) - 51 4b 50 40 b1 26 d8 21 11 b1 05 bf 05 ba 05 b3 05 c8 05 5d 85 0f 08 79 be 17
Events (-938506915): 40/( 4913/282840)50/( 689/ 703)4b/( 698/ 691)51/( 712/ -1)
POST 0: 22 (c811) - 51 4b 50 40 ad 26 b8 20 11 af 05 be 05 b9 05 b2 05 c6 05 ec e5 13 52 fa ff e6
Events (-938220052): 40/( 4909/282680)50/( 687/ 702)4b/( 697/ 690)51/( 710/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED48 );
DO_MARKER( 10, LED40|LED48|LED50 );
DO_MARKER( 10, LED40|LED48 );
DO_MARKER( 10, LED40|LED48|LED50 );
DO_MARKER( 10, LED40|LED50 );
DO_MARKER( 10, LED40 ); *** Maybe something is not being seen?
POST 0: 20 (b544) - 46 51 4b 50 bf 01 a0 01 b5 01 fb d2 01 bf 01 ac 01 f8 37 46 8c 97 9c 84
Events (-1253689352): 50/( 191/ 160)4b/( 181/ 123)51/( 210/ 191)46/( 172/ -1)
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED48 );
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED50 );
DO_MARKER( 10, LED40 );
POST 0: 16 (b35c) - 44 50 48 ab 01 b7 01 ab 01 b2 01 a9 01 38 c4 5c 86 12 bb 91
Events (-1285766088): 48/( 171/ 183)50/( 171/ 178)44/( 169/ -1)
It can totally move onto additional packets;
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED48 );
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED50 );
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED48 );
DO_MARKER( 10, LED40 );
DO_MARKER( 10, LED40|LED50 );
DO_MARKER( 10, LED40 );
POST 0: 21 (632c) - 50 48 50 48 b7 01 ab 01 b2 01 9f 01 c1 01 a0 01 bd 01 44 8a 2c f8 37 e7 3c
Events (1663863364): 48/( 183/ 171)50/( 178/ 159)48/( 193/ 160)50/( 189/ -1)
POST 2: 6 (632f) - 40 a4 0c ed 8a 2c 6b bc ea 55
Events (1663863533): 40/( 1572/ -1)
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED48 );
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED50 );
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED48 );
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED50 );
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED48 );
DO_MARKER( 14, LED40 );
POST 0: 6 (d7ce) - 40 8a 15 1a 0f ce 00 25 9a 03
Events (-674361574): 40/( 2698/ -1)
POST 0: 26 (d7d1) - 48 50 48 50 48 fc 01 f2 01 f8 01 ee 01 80 02 ef 01 f9 01 f3 01 fd 01 19 66 d2 d7 07 c8 40
Events (-674077159): 48/( 252/ 242)50/( 248/ 238)48/( 256/ 239)50/( 249/ 243)48/( 253/ -1)
POST 2: 6 (d7d4) - 40 89 15 04 67 d2 b3 ad 71 4e
Events (-674076924): 40/( 2697/ -1)
NOTICE: The second timecode is actually less than the first, and so we know the time code in the packet
corresponds to the start edge of the event, not the tailing edge of the event... I hope?
DO_MARKER( 14, LED40 );
DO_MARKER( 14, LED40|LED48 );
DO_MARKER( 14, LED40|LED48|LED50 );
DO_MARKER( 14, LED40|LED50 );
DO_MARKER( 14, LED40 );
POST 0: 16 (55b3) - 44 51 49 f1 01 f8 01 f9 01 f1 01 f2 01 fb 99 b5 96 78 95 4c
Events (1437964795): 49/( 241/ 248)51/( 249/ 241)44/( 242/ -1)
DO_MARKER( 14, LED40 );
DO_MARKER( 28, LED40|LED48 );
DO_MARKER( 14, LED40|LED48|LED50 );
DO_MARKER( 14, LED40|LED50 );
DO_MARKER( 14, LED40 );
POST 0: 16 (d8f1) - 44 51 49 f1 01 ef 03 f7 01 f4 01 f1 01 19 de f2 20 ee f9 82
Events (-655172071): 49/( 241/ 495)51/( 247/ 244)44/( 241/ -1)
POST 0: 16 (d8f7) - 44 51 49 f1 01 ee 03 f7 01 f5 01 f1 01 a3 32 f7 bd 50 64 dc
Events (-654888285): 49/( 241/ 494)51/( 247/ 245)44/( 241/ -1)
DO_MARKER( 14, LED40 );
DO_MARKER( 28, LED40|LED48 );
DO_MARKER( 14, LED40|LED48|LED50 );
DO_MARKER( 14, LED40|LED50 );
DO_MARKER( 14, LED40|LED48|LED50 );
DO_MARKER( 14, LED40 );
POST 0: 20 (48e6) - 46 49 52 49 f2 01 ec 03 f7 01 d1 01 97 02 82 ef 01 cf 77 e6 36 51 12 5b
Events (1223063503): 49/( 242/ 492)52/( 247/ 209)49/( 279/ 2)46/( 239/ -1)
DO_MARKER( 14, LED50 );
DO_MARKER( 28, LED50|LED48 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50|LED40 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50 );
POST 0: 20 (fab4) - 56 49 42 49 f4 01 f2 03 f4 01 d1 01 96 02 84 e9 01 f1 07 b5 62 27 b9 26
Events ( -88799247): 49/( 244/ 498)42/( 244/ 209)49/( 278/ 4)56/( 233/ -1)
Changing second to last LED
DO_MARKER( 14, LED50 );
DO_MARKER( 28, LED50|LED48 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50|LED40 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50|LED40 );
DO_MARKER( 14, LED50 );
POST 0: 21 (665d) - 56 43 48 49 f6 01 fb 03 e4 01 d6 01 95 02 ec 01 f2 01 67 ad 5f 24 9c 44 80
Events (1717546343): 49/( 246/ 507)48/( 228/ 214)43/( 277/ 236)56/( 242/ -1)
DO_MARKER( 14, LED50 );
DO_MARKER( 28, LED50|LED48 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50|LED40 );
DO_MARKER( 14, LED50|LED48|LED40 );
DO_MARKER( 14, LED50|LED48 );
DO_MARKER( 14, LED50 );
POST 0: 21 (af86) - 56 49 42 49 f7 01 fb 03 e5 01 d6 01 8b 02 81 02 e8 01 05 0c 86 92 22 2e fd
Events (-1350169595): 49/( 247/ 507)42/( 229/ 214)49/( 267/ 257)56/( 232/ -1)
^^ Look, this changed.
DO_MARKER( 90, LED48 );
DO_MARKER( 14, LED48|LED40 );
DO_MARKER( 28, LED40 );
DO_MARKER( 56, LED48|LED40 );
DO_MARKER( 10, LED48 );
POST 0: 16 (ce15) - 49 42 49 bf 0c de 01 ec 03 d6 07 b2 01 35 f7 15 51 a0 c8 09
Events (-837421259): 49/( 1599/ 222)42/( 492/ 982)49/( 178/ -1)
POST 0: 16 (ce1b) - 49 42 49 bd 0c df 01 ed 03 d6 07 b2 01 ed 53 1a 99 a3 8c 0e
Events (-837135379): 49/( 1597/ 223)42/( 493/ 982)49/( 178/ -1)
DO_MARKER(40, LED40);
_delay_us(5);
DO_MARKER(80, LED50);
POST 0: 11 (6255) - 50 40 a4 05 9b 01 f4 0a d3 c9 56 82 f0 85 a3
Events (1649854931): 40/( 676/ 155)50/( 1396/ -1)
DO_MARKER(40, LED40);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED40);
POST 0: 12 (409a) - 48 40 e0 15 fb 22 11 f6 0a 47 9a 9a 0a 5e e3 4d
Events (1083873863): 40/( 2784/283003)48/( 1398/ -1)
DO_MARKER(40, LED40);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED40);
_delay_us(10);
DO_MARKER(40, LED40);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED40);
POST 0: 22 (f2cb) - 48 42 48 40 fe 15 f9 1b 11 b4 05 f6 0a b6 05 f2 07 ee 0a 01 8c ca 77 f1 74 e4
Events (-221606911): 40/( 2814/282105)48/( 692/ 1398)42/( 694/ 1010)48/( 1390/ -1)
2's bit mayhem:
DO_MARKER(40, LED40);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED40);
Events ( 669590803): 40/( 2785/283104)48/( 1400/ -1)
DO_MARKER(40, LED48);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED48);
Events (-2138863588): 48/( 2803/282920)40/( 1380/ -1)
DO_MARKER(40, LED48);
DO_MARKER(80, LED48|LED40);
DO_MARKER(40, LED40);
POST 0: 11 (cf74) - 41 49 ce 05 e8 0a bb 05 4c 95 76 1e 8d 62 68
Events (-814312116): 49/( 718/ 1384)41/( 699/ -1)
Continuing...
//WHY IS THE ORDER REVERSED?!?!??!??
DO_MARKER(10, LED48);
_delay_us(500);
DO_MARKER(250, LED40);
Events (-2113688082): 40/( 4359/282445)48/( 165/ -1)
DO_MARKER(10, LED40|LED50);
POST 0: 9 (9af3) - 52 40 98 85 01 94 a0 66 f4 16 8a e6 2a
Events (-1695258976): 40/( 24/ 133)52/( 20/ -1)
DO_MARKER(20, LED40);
_delay_us(10);
DO_MARKER(30, LED50);
_delay_us(10);
DO_MARKER(40, LED48);
_delay_us(10);
DO_MARKER(50, LED40);
POST 0: 21 (fc73) - 40 48 50 40 b5 02 ad 02 8d 04 a2 02 b3 05 bb 02 c5 06 56 85 74 22 a2 36 96
Events ( -59472554): 40/( 309/ 301)50/( 525/ 290)48/( 691/ 315)40/( 837/ -1)
DO_MARKER(20, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(20, LED50);
DO_MARKER(20, LED50|LED48);
DO_MARKER(20, LED50);
POST 0: 16 (b269) - 53 48 41 c8 02 cd 02 f7 02 d6 02 d6 02 77 a8 6a d8 2d 7c 19
Events (-1301632905): 41/( 328/ 333)48/( 375/ 342)53/( 342/ -1)
DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(30, LED50);
DO_MARKER(40, LED50|LED48);
DO_MARKER(50, LED50);
Events ( -3705027): 41/( 151/ 334)48/( 552/ 695)53/( 867/ -1)
**********CHANGED OSCILLATOR SPEED SO NUMBERS ARE ABOUT 1/10TH OF CLKs.
The following is in reference to Alan Yates' picture on twitter.
https://twitter.com/vk2zay/status/805989864311132160
DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(30, LED50);
DO_MARKER(40, LED50|LED48);
DO_MARKER(50, LED50);
POST 0: 15 (7d39) - 53 48 41 f8 a8 02 f9 03 ef 04 98 06 8b 68 3a 45 8b d9 26
Events (2100979851): 41/( 120/ 296)48/( 505/ 623)53/( 792/ -1)
DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(50, LED50);
DO_MARKER(80, LED50|LED48);
DO_MARKER(110, LED50);
Events (-1091897926): 50/( 4118/254995)40/( 417/ 823)48/( 1258/ -1)
DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(30, LED50);
DO_MARKER(50, LED50|LED48);
DO_MARKER(70, LED50);
POST 0: 15 (77b3) - 53 48 41 fa a8 02 fa 03 8f 06 d4 08 0f 74 b4 c9 fd d7 29
Events (2008314895): 41/( 122/ 296)48/( 506/ 783)53/( 1108/ -1)
DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(30, LED50);
DO_MARKER(50, LED50|LED48);
DO_MARKER(80, LED50);
POST 0: 17 (d2d8) - 48 40 50 / a7 16 / f4 / 49 0f / a2 03 / fa 03 / 90 06 / 58 a6 d9 / bf 3f bf d8
Events (-757488040): 50/( 2855/255220)40/( 418/ 506)48/( 784/ -1) << Yeah, I'm decoding the 255220 right, I think?
FOUND SOMETHING NEW!!!: 255220−(262144) = −6924 !!! << Ok, nevermind.
They say not to look here, but, I don't get it. Otherwise, it's a mess of 1's and zeros.
"Ben Jackson you're sending a sequence ab ab ab ab and seeing "b a" b a" "b a" come out "
"Ben Jackson it's not a bug"
"Albert Fletcher Edwin called it"
When switching the _delay_ms(...) to 11 from 10...
POST 0: 17 (b3ac) - 48 40 50 ab 16 8e 14 11 a1 03 fb 03 8f 06 b5 2b ad 0b be 45 82
Events (-1280496715): 50/( 2859/281102)40/( 417/ 507)48/( 783/ -1)
that big number is different now.
...then with... _delay_ms(32);
Events (-992766494): 50/( 2849/816305)40/( 420/ 505)48/( 782/ -1)
Ben Jackson well now your debug data is so different from real data that you're seeing strangeness
Ben Jackson but the thing you're decoding is still accurate
vk2zay the delta decoding around line 357 isn't correct
Ben Jackson oh, not all his coding
Ben Jackson but my coding is accurately representing reality
Ben Jackson @cai it wouldn't, but in a real system there's a lot more data flying around
Cai Biesinger Ah, OK. That makes sense. What's the maximum time a controller would theoretically hold data?
Ben Jackson @cai not sure
switching to: _delay_ms(32);
Now, flirting with limit.
DO_MARKER(20, LED40);
DO_MARKER(35, LED50|LED40);
DO_MARKER(25, LED50);
DO_MARKER(45, LED50|LED48);
DO_MARKER(65, LED50);
Events (1574058667): 41/( 283/ 536)48/( 427/ 704)53/( 1031/ -1)
POST 0: 16 (5ddc) - 53 48 41 9b 02 99 04 ab 03 bf 05 88 08 98 c2 de 86 68 4c ac
Events (1574879896): 41/( 283/ 537)48/( 427/ 703)53/( 1032/ -1)
POST 0: 11 (5deb) - 48 40 b3 06 ac 03 c0 05 cc 45 eb eb 91 c5 bd
Events (1575699916): 40/( 819/ 428)48/( 704/ -1)
POST 0: 22 (5df6) - 53 48 41 50 8d 15 9e 77 31 9b 02 98 04 ab 03 bf 05 88 08 17 d1 f7 99 e3 75 80
Events (1576522007): 50/( 2701/818078)41/( 283/ 536)48/( 427/ 703)53/( 1032/ -1)
POST 0: 16 (5e02) - 53 48 41 99 02 98 04 ab 03 bf 05 86 08 f6 55 04 df 6e 8b 3e
Events (1577342454): 41/( 281/ 536)48/( 427/ 703)53/( 1030/ -1)
POST 0: 16 (5e0e) - 53 48 41 9b 02 98 04 ac 03 bf 05 88 08 ae dc 10 1e 35 03 35
Now this is flirting with the limit and wrapping around.
TODO TODO TODO : Look at these values and try to figure out what's wrong with the deltaA / deltaB code in survive_data.c
COMMIT. Libsurvive hash 09efa97
APPENDIX: Before I started doing inline "ben"ments I kept a log here is that log:
Ben Jackson says: not sure what's going wrong with haptics. I think there's only one command, and it's pulse duration in microseconds, and shouldn't exceed about 3500
Ben Jackson the 3 byte direct time is the first edge of the first hit
Ben Jackson
Ben Jackson there are only 2n-1 deltas
Ben Jackson: it's "first one to end first"
Ben Jackson when a pulse goes high, you don't know when it will end
Ben Jackson
Ben Jackson you can't report it until it ends
Ben Jackson
Ben Jackson so they come out in the order they end
Ben Jackson no, I can't explain the LSBs in terms of his current code
Daniel Wee that explains why the higher bits didn't show up until we had more LEDs in play
Ben Jackson he's got to fix his time decode first
Ben Jackson the starts and ends are all mixed. they have to be, with all positive deltas, right?
Ben Jackson it's literally start,d0,d1,d2,d3 making times start+d0, start+d0+d1, start+d0+d1+d2, ...
Ben Jackson those are all edges
Ben Jackson then you need the LSBs to figure out which edges go where
Ben Jackson consider nested pulses that look like rise rise fall fall, vs sequential rise fall rise fall
Ben Jackson then the decoded times go with different things
vk2zay what is 2^18
Ben Jackson Stupid question or Socratic method?
Ben Jackson I think this might be a more productive stream if it tried to *compress* the data
Ben Jackson in the process you'd probably come to a bunch of the same conclusions I did
Ben Jackson vee kay two zay is what I'm calling him from now on
The whole thing about 2^18, and it mapping into the 2's bit of the timecode + 65536, instead of
the 2's bit of the LED code.
vk2zay getting there
Daniel Wee your sequence of numbers only applies to the first few bytes - but the assignment to the timestamps may be wrong
Ben Jackson vk2zay explaining in pictures while I snag leftover Indian food
(Picture from Twitter)
Ben Jackson oh, are you in SEA Luke?
Ben Jackson I guess Phil did say something like that
training
Ben Jackson MAKING ALL YOUR TIMINGS IDENTICAL IS MAKING YOUR LIFE SO MUCH HARDER
Ben Jackson too bad all caps doesn't actually yell
Ben Jackson we need to be able to pay $1 to have a bad speech synthesizer repeat on stream
Ben Jackson vk2zay about to discover I got the last samosa
Ben Jackson @scanlime with the classic "all example numbers should be prime so no one can mistake them for anything"
Ben Jackson there is nothing of interest in the nRF24
Ben Jackson that's your whole problem, really
Ben Jackson I didn't decode it in the nRF24
Charles: "Can I record this and put it in the gist?: Ben Jackson sure, I wouldn't say anything in chat without expecting it to be public
Is it encoded in the FPGA? Ben Jackson @Na it's encoded in the controller side in an nRF51
Ben Jackson no, @scanlime guessed it was done in the FPGA
Ben Jackson the fpga outputs yet another different format over SPI
Ben Jackson but I bet you could reverse engineer that in 10 minutes
Ben Jackson well, we're not going to try to lock you out
Ben Jackson but we're going to add features someday that break this without caring that it will break you
vk2zay we would only change the protocol to add features
Ben Jackson I think eventually we'll let you do your own wireless protocol
Ben Jackson but it's not a huge priority and there's only so much time
On the gist, when I realize the big number is about - 6k.
Ben Jackson how big is your delay between batches?
Ben Jackson it's not negative
Ben Jackson whatever it is
Ben Jackson noooo
vk2zay it is not a -ve number
Ben Jackson need that chat vocoder
When I started switching the time coding...
Ben Jackson you're just wrapping around and seeing two of your events in one packet
Ben Jackson also your delay probably isn't 11ms. it's probably 280000/48e6 seconds
Ben Jackson it's not "freaking out", it's just combining them
vk2zay well I got it
APPENDIX B: Nairol from lighthouse-redux chimes in on Reddit in: https://www.reddit.com/r/Vive/comments/5gmk7l/i_live_streamed_hacking_the_vive_got_a_vive/
>>> Thanks for the kind words about Lighthouse Redox. (I did most of the initial reverse-engineering work by disassembling the base station firmware) It was meant as a resource for people interested in Lighthouse to build their own hard- and software and share their findings about the system before the eventual official documentation release by Valve (which never happened publically). I'm happy that finally people actually use it. It has been up since a few days before the release of the Vive. :)
>>> I know the repo is in a pretty bad state and lots of pieces are still missing. It hasn't been updated in months... This is partially because of laziness, partially because of my job but for the most part because I lost almost all my data (not just the Lighthouse-related stuff) to a HDD defect. The data recovery lab told me it has a misaligned read/write head with some impact damage to the disk surface. I might get most of the data back but it takes months. Of course I didn't have a backup.
>>> The wireless receiver data really is a mess. I remember sitting in front of a scrolling console window and trying to figure out WTF was going on. Until I accidentally covered the photodiodes and the data started to make sense. :)
>>> I have only watched the first 30 minutes of the screencast so I don't know how much you already know out about the protocol. I've given up on trying to reconstruct how the light pulse data is multiplexed into the data stream just by looking at the USB data. It seems to be encoded into the time stamp and an additional byte but it just doesn't make sense to me. Also there seems to be some kind of checksum (CRC32?) but I couldn't figure out what byte range it coveres...
>>> I wanted to have a look at the firmware for the controller and the wireless receiver to finally solve this riddle but haven't found the time or motivation yet. Disassembling the firmware is fast but finding the stuff you're interested in takes hours and hours of scrolling through walls of mostly boring assembly code.
>>> If you have questions I might be able to help out a bit. But don't count on it since I haven't been following the VR subreddits and haven't done any work on the Vive internals for quite some time.
>>> edit:
>>> @0:43:15
>>> I don't know who told you 2MHz was the correct modulation frequency but it should be 1.843200 MHz. (Link Ctrl+F "carrier.frequency") But 2MHz is good enough.
>>> @0:48:12
>>> I reverse-engineered the stuff on the USB protocol page the same way as you did. So that shouldn't be a problem. Most of the other documentation comes from the base station firmware but I didn't include any code from there so your version can be considered "clean room implementation" AFAIK. I've also told Alan Yates from Valve that I was disassembling his firmware and he didn't seem to have a problem with that.
>>> @x:xx:xx
>>> Afaik all microcontrollers in the system are ARM Cortex M0+ architecture with the Thumb2 instruction set. Haven't seen any 8051 code in the firmware files.
@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

typedef struct {
  uint8_t mask    : 3;
  uint8_t sensor  : 5;
} sensors;


int main(){
  uint8_t value = 0x4a;
  sensors * t = (sensors*)&value;

  uint8_t led = t->sensor;
  printf("sensor %.2x, mask %d \n", led << 3, t->mask); 

}

this produces 48 for the led and 2 for the mask My guess is the 2 means that there are two leds on, and the first is 48.

@CaiB

This comment has been minimized.

Copy link

commented Dec 6, 2016

Not sure how much of this you already know. Hopefully this helps a bit.

Test 1

DO_MARKER(10, LED40);       //   0 -  10
DO_MARKER(20, LED50|LED40); //  10 -  30
DO_MARKER(30, LED50);       //  30 -  60
DO_MARKER(40, LED50|LED48); //  60 - 100
DO_MARKER(50, LED50);       // 100 - 150
41/(  151/  334)48/(  552/  695)53/(  867/   -1)

If we take the time values (151, 334, 552, 695, 867) and add them onto all the previous ones, we get: (151, 485, 1037, 1732, 2599)

Math in case my words don't make sense:
0 + 151 = [151]
0 + 151 + 334 = [485]
0 + 151 + 334 + 552 = [1037]
0 + 151 + 334 + 552 + 695 = [1732]
0 + 151 + 334 + 552 + 695 + 867 = [2599]

If we graph this series, as well as the same thing from the AVR LED timings, we get this (please excuse the 5-second Excel job):
excel-cnlohr-4

Therefore, we can infer that the numbers in parentheses in your output {e.g. ( 151/ 334)} are deltas, from the first event (LED40 on), of other events (event = rise or fall). This sounds very similar to what Ben said.

Event sequence:
R = rising, F = falling

[R40][R50][F40][R48][F48][F50]
           ^         ^    ^

Ben said that pulses are not sent until they finish (fall). You'd re-write the events to be in the order that the arrows appear above.
Therefore, the events might be sent like:
[R40][F40] / [R48][F48] / [R50][F50]

The LED codes seem to be in this order, 41, 48, 53.
I'm thinking we are getting LED code + number of transitions in time it was on.

While 40 was on, 1 other event happened: R50. Therefore 40 + 1evt = 41.
While 48 was on, nothing happened. 48 + 0evt = 48
While 50 was on, 3 other events happened: F50, R48, F48. Therefore, 50 + 3evt = 53.

OK, time to confirm if this is correct.
Another dataset:

Test 2

DO_MARKER( 90, LED48 );       //   0 -  90
DO_MARKER( 14, LED48|LED40 ); //  90 - 104
DO_MARKER( 28, LED40 );       // 104 - 132
DO_MARKER( 56, LED48|LED40 ); // 132 - 188
DO_MARKER( 10, LED48 );       // 188 - 198
49/( 1599/  222)42/(  492/  982)49/(  178/   -1)

AVR Timings summed are: (0, 90, 104, 132, 188, 198)
Controller timings summed are: (0, 1599, 1821, 2313, 3295, 3473)

excel-cnlohr-6

Event sequence:

[R48][R40][F48][R48][F40][F48]
           ^         ^    ^

Reported in this order:
[R48][F48] / [R40][F40] / [R48][F48]

LED codes: 49, 42, 49.

While 48 was on, 1 other event (R40). Therefore 48 + 1evt = 49
While 40 was on, 2 other events (F48, R48). Therefore 40 + 2evt = 42
While 48 was on, 1 other event (F40). Therefore 48 + 1evt = 49

Wow, this actually looks to be working out.
But there's a problem. What if this happened:
40 turned on. 9 events happened. 40 turned off.
We would get 40 + 9evt = 49. Oh no, how is that different from 48 + 1evt?
This puts a maximum of 7 other events on my theory.

If you did what I did at this point you would think this: Hey, we have LEDs 48 and 50. Wouldn't that allow for only 1 event to be reported?!
Then you would find an example, and think Doh! this is hexadecimal.

DO_MARKER( 40, LED48 );
DO_MARKER( 40, LED40|LED48 );
DO_MARKER( 40, LED48 );
Events (1353710091): 40/(  695/  699)4a/(  689/  275)50/(  727/  697)4a/(  690/   -1)

In this case, LED 48 + 2 evt = 4A. Still good, just me doing a dumb.

OK, what happens when we exceed 7 events?

Luckily, Charles did some crazy things, so let's look at an example where there's a lot going on. (Excellent work on providing varied data, Charles!)

Test 3

DO_MARKER( 10, LED40 );       //  0 - 10
DO_MARKER( 10, LED40|LED48 ); // 10 - 20
DO_MARKER( 10, LED40 );       // 20 - 30
DO_MARKER( 10, LED40|LED50 ); // 30 - 40
DO_MARKER( 10, LED40 );       // 40 - 50
DO_MARKER( 10, LED40|LED48 ); // 50 - 60
DO_MARKER( 10, LED40 );       // 60 - 70
DO_MARKER( 10, LED40|LED50 ); // 70 - 80
DO_MARKER( 10, LED40 );       // 80 - 90
Events (1663863364): 48/(  183/  171)50/(  178/  159)48/(  193/  160)50/(  189/   -1)
Events (1663863533): 40/( 1572/   -1)

Hmm. Interesting. At first glance, it looks like events with more than 7 transitions are split out into their own packet. Let's do the full analysis.

AVR Timings are: (0, 10, 20, 30, 40, 50, 60, 70, 80, 90)
Controller Timings are: (0, 183, 354, 532, 691, 884, 1044, 1233) and then (1572)

excel-cnlohr-8

Something's wrong. In the data packets above, I cannot find where LED50 turns off the last time. This will definitely need investigation, as it needs to know this somehow...

Could it be that the data is in the packet, but Charles is ignoring it, replacing with -1 when he shouldn't?
I.e. is the last part of the first packet not "50/( 189/ -1)", but "50/( 189/ 165)"?
I don't really feel like trying to decipher his code, so he'll need to check into that.

Event sequence:

[R40] [R48] [F48] [R50] [F50] [R48] [F48] [R50] [F50] [F40]
             ^           ^           ^           ^     ^

Reported sequence:
[R48][F48] / [R50][F50] / [R48][F48] / [R50][F50] / [R40][F40]
But in between [R40] and [F40], we had 8 other events. How does this translate?

LED codes: 48, 50, 48, 50. Then 40.
Looking good so far.

While 48 was on, no other events happened. LED48 + 0evt = 48.
While 50 was on, no other events happened. LED50 + 0evt = 50.
...
While 40 was on, 8 events happened. 8 > 7, so we split this into a new packet, clearing the event count.

More special cases to clutter up your code! Yaaay!

All in all, I can't find an instance of my method not working. That said, I'm sure there's a few flaws. Please comment, and let me know of all the mistakes I made :P

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

I have layed out the data from one of the more interesting tests above.
I think this tells exctly what happened, but I still need help correlating the lsb to the precise timings.
My thought is that the LEDs are in order of when they turned off, but the LSB tells you when they turned on.

DO_MARKER( 14, LED50 );              ON50 (0)  // 50 turns on at 0
DO_MARKER( 28, LED50|LED48 );        ON48 (14) // 48 turns on 14 later
DO_MARKER( 14, LED50|LED48|LED40 );  ON40 (28) // 40 turns on 28 later
DO_MARKER( 14, LED50|LED40 );        OF48 (14) // 48 turns off 14 later
DO_MARKER( 14, LED50|LED48|LED40 );  ON48 (14) // 48 turns on 14 later
                                     OF40 (14) // 40 turns off 14 later 
                                     OF48 (0)  // 48 turns off ~0 later (could be switched with above)
DO_MARKER( 14, LED50 );              OF50 (14) // 50 turns off 14 later


// The times below are un-reversed ie starting at the low addresses.
// I think they correlate with the events listed above cronologically.
time[0] = 000F4 (244)   
time[1] = 001F2 (498)
time[2] = 000F4 (244)
time[3] = 000D1 (209)
time[4] = 00116 (278)
time[5] = 00004 (4)
time[6] = 000E9 (233)

// The LED's are listed I think in the order they turn off (reverse order of packet)
LED[0] 48, lsb 001 (1)
LED[1] 40, lsb 010 (2)
LED[2] 48, lsb 001 (1)
LED[3] 50, lsb 110 (6)

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

In fact, i think you can correlate the LEDS this way

time[0] = 000F4 (244)  || // start of LED[0]
time[1] = 001F2 (498)  || // start of LED[2]
time[2] = 000F4 (244)  || LED[0] 48, lsb 001 (1)  // turned on 1(+1) ago ie index 0
time[3] = 000D1 (209)  || // since 48 turned on at index 43 we push LED[0] back one more
time[4] = 00116 (278)  || LED[1] 40, lsb 010 (2)  // turned on 2(+1) ago ie index 1
time[5] = 00004 (4)    || LED[2] 48, lsb 001 (1)  // turned on 1(+1) ago ie index 3
time[6] = 000E9 (233)  || LED[3] 50, lsb 110 (6)  // turned on 6(+1) ago ie index -1

starting from the last LED to turn off (which is the beginning of the packet), you associate the led to the last time code (which is the first one you read), then you use the LSB of the LED to tell you how many time codes to skip before you have the code when that LED came on.

@danweecc

This comment has been minimized.

Copy link

commented Dec 6, 2016

Looks like lots of people have been working on this as well. Okay, here are my observations:

  1. In doing these tests, once the pulse-period gets too long, weird things start to happen and breaks the easy to understand protocol so it is better to keep the pulse-periods shorter

  2. The final delta in whatever sequence seems to always be somewhat wrong (usually shorter than it should be). I am not sure if this is due to the AVR or the Watchman itself

  3. Although the DO_MARKER code ends by turning all LEDs off, when used back-to-back, the LEDs are turned back on so quickly that the short off-period is undetected or ignored by the Watchman and treated as a continuous pulse if the same LED is turned back on in the subsequent call to DO_MARKER.

  4. The packet format appears to be something like the following:-

[LL LL ...] xxxx1 xxxx2 .... [TT TT TT] [CC CC CC CC]

The LL block indicates how many LEDs are in play, with the lower 3-bits indicating the number of transitions within it's pulse-period. I'll explain this later.

xxxx1 xxxx2 ... are the periods between edge transitions after the initial rising-edge which is not counted. The exact number of transitions depends on the pulse sequence and there will be as many xxxx parameters as there are transitions, inclusive of the final falling edge.

The TT TT TT block are 3-bytes for the time-stamp of the rising edge that marks the beginning of the packet.

The final CC CC CC CC block are a 32-bit checksum but does not correspond to CRC32. It's probably some custom checksum.

Below are some examples to illustrate the above protocol description:

DO_MARKER(40, LED48);

LED48 |---|---|---|---| 40
      0   1   2   3   4

 LL  xxxx1  TT TT TT   CC CC CC CC
[48] ac 05 [73 10 fc] [7a 78 6d 93]

xxxx1 = 0x05AC = 1452
timestamp = 0xFC1073

This is the simplest case. Notice that the LL is a plain 48 because there were no other LEDs in play to cause transitions within it's own pulse-period.

Now, let us look at another case to expand on this protocol:

DO_MARKER(40, LED48);
DO_MARKER(40, LED50|LED48);
DO_MARKER(40, LED48);

            xxxx1           xxxx2           xxxx3
LED48 |---|---|---|---|---|---|---|---|---|---|---|---| 120
LED50                 |---|---|---|---| 40
      0   1   2   3   4   5   6   7   8   9   10  11  12

 vv
[4a 50] b8 05 - c1 05 - b4 05 [b6 b1 3d] [e8 dc 86 2e]
        1464    1473    1460

xxxx1 = 1464
xxxx2 = 1473
xxxx3 = 1460
timestamp = 0x3DB1B6

In this example, we observe that the longer pulse of LED48 contains the rise and fall of LED50 (2-transitions) which lead to the 0x48 being OR-ed with a value of 2 = 0x4A. LED50, however, has no transitions within it's entire period and so the LL of 0x50 is left unaltered.

To make this clearer, let us look at the reverse case:-

DO_MARKER(30, LED50);
DO_MARKER(20, LED50|LED48);
DO_MARKER(10, LED50);

          xxxx1     xxxx2 xxxx3
LED50 |---|---|---|---|---|---| 60
LED48             |---|---| 20
      0   1   2   3   4   5   6

 vv
[52 48] 9f 04 - c3 02 - ba 01 [58 40 2d] [7a 4a 80 67]
        1183    707     442

xxxx1 = 1183
xxxx2 = 707
xxxx3 = 442

Like before, this example has 3 transitions. Unlike before, LED48's pulse is completed without any transitions within it so it's LL code is left unaltered. LED50's pulse-period, however, contains the 2-transitions of LED48's rise and fall edges and so it's code is OR-ed with 2 to give 0x52.

Note that xxxx3 is longer than it should be. I am uncertain as to why this is the case but the last delta always seems to out somewhat - sometimes longer and sometimes shorter than it should be.

Let us consider a slightly different case to explore the function of the LL LSB bits:

DO_MARKER(30, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(10, LED50);

          xxxx1     xxxx2 xxxx3
LED40 |---|---|---|---|---| 50
LED50             |---|---|---| 30
      0   1   2   3   4   5   6

 vv vv
[51 41] b5 03 - c5 02 - c9 01 [8e 3f b8] [86 85 bb b7]
        949     709     457

xxxx1 = 949
xxxx2 = 709
xxxx3 = 457

In this example, both pulses contain a transition-edge of the other LED so both their LL codes are OR-ed with 1 resulting in 0x41 and 0x51.

I hope this illustrates how the LSB bits of the LL code works.

Let us talk about exception cases - when the pulse period gets too long - and see what happens that breaks the protocol:

DO_MARKER(80, LED50);
DO_MARKER(90, LED50|LED48);
DO_MARKER(100, LED50);

                   xxxx1                              xxxx2                                  xxxx3
LED50 |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| 270
LED48                                 |---|---|---|---|---|---|---|---|---| 90
      0                               8                                   17                                      27

[48 50] fe 24 - cd 25 11 - 91 0c [6a 24 6f] [b8 5a fd 69]
        9470    1123789    3217

As with previous examples, this one also contains 3-transitions (excluding the starting edge) so there are 3 parameters to be found between the LL codes and the TT timestamp. These 3-transitions would normally produce 3-words representing the duration of the periods but because the overall pulse period is so long, we get some breaking of the protocol here with the xxxx1 and xxxx2 period becoming uncharacteristically long. I have not investigated how this actually works or how to interpret the codes in this situation but the length of the packet itself should indicate a problem with such long pulses.

Other examples that might be of interest are as follows:

DO_MARKER(40, LED48);
_delay_us(10);
DO_MARKER(40, LED48);
_delay_us(10);
DO_MARKER(40, LED48);

     xxxx1      xxxx2      xxxx3     xxxx4      xxxx5
LED48                LED50                LED40
|---|---|---|---|    |---|---|---|---|    |---|---|---|---|

Total of 5-transitions

 vv vv vv
[40 50 48] b0 05 - a2 02 - c1 05 - c7 03 - f1 03 [65 9b 2f] [80 03 2b 58]
           1456    674     1473    967     1009?

Once again, xxxx5 is lower than it should be - I'm not sure why this always happens with the last delta. Since none of the pulses contain transitions of any of the other LEDs, their LL codes are left unaltered. Note also that blank periods also generate a delta entry in the packet.

And the last example:

DO_MARKER(10, LED40);
DO_MARKER(20, LED50|LED40);
DO_MARKER(30, LED50);
DO_MARKER(40, LED50|LED48);
DO_MARKER(50, LED50);

5-transitions
      xxxx1 xxxx2     xxxx3         xxxx4             xxxx5
LED40 |---|---|---| 30
LED50     |---|---|---|---|---|---|---|---|---|---|---|---|---|---| 140
LED48                         |---|---|---|---| 40

[53 48 41] f8 - a8 02 - f9 03 - ef 04 - 98 06 [8b 68 3a] [45 8b d9 26]
           ?    680     1017    1263    1688

In this example, we have 5-transitions in total (excluding the starting rising edge of LED40) so we expect to find 5-deltas in the packet. The pulse-period of LED40 contains one rising-edge transition of LED50 so the LL code is OR-ed with 1 giving us 0x41. The pulse period of LED50 contains the falling-edge of LED40 as well as the rise-and-fall-edges of LED48, a total of 3-transitionary edges. As a result, the LL code is OR-ed with 3 giving us 0x53. The pulse period for LED48 contains no edges so it is left unaltered.

As for the periods - the xxxx1 is only a single byte long - possibly because it is very short. I have not completely investigated what's happening here but I think these examples should be roughly correct in general.

It goes without saying that this method of encoding can only reliably encode for 7-transitions within any pulse-period of an LED. Once you go above this, it will probably wrap around, ie. 8-transitions = 8 & 0x07 = 0x00. I don't think the system expects these situations to occur so we might be testing exceptions which won't be terribly helpful (likewise for extremely long or complex packets).

Another situation that has not been checked for thus far is simultaneous activation of multiple LEDs at the rising-edge. Eg:-

DO_MARKER(40, LED40|LED50);

I don't think this has been tried so I don't know how this is represented in the packet. You may want to try this and see.

Hope this helps.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 6, 2016

@CaiB: Re 7 events maximum. "Could it be that the data is in the packet, but Charles is ignoring it, replacing with -1 when he shouldn't?" I am not ignoring data. At least not that I'm aware of. I thought if I was, it would display a warning. You can always look at the raw hex coming back... And in this case, it appears I am displaying the packet exactly as it came.

POST 0:   21 (632c) - 50 48 50 48 b7 01 ab 01 b2 01 9f 01 c1 01 a0 01 bd 01 44 8a 2c f8 37 e7 3c 
Events (1663863364): 48/(  183/  171)50/(  178/  159)48/(  193/  160)50/(  189/   -1)
POST 2:    6 (632f) - 40 a4 0c ed 8a 2c 6b bc ea 55 
Events (1663863533): 40/( 1572/ -1)

I will admit, I am very confused myself, as I simply cannot find where 50 ends, either.

It is conceivable I have something out of order. After all @vk2zay said "vk2zay the delta decoding around line 357 isn't correct"


@MobiusHorizons : Hmm, this is very difficult to really dig through. It makes me wonder what the timestamp is. I feel like we 'know" it's the time of the first event because of the packet that spills over to the next line.

POST 0:   22 (1ed9) - 50 50 42 48 cf 05 92 26 c2 05 bf 25 11 bf 05 ba 05 c0 05 80 85 da 46 01 54 29 
Events ( 517637504): 48/(  719/ 4882)42/(  706/283327)50/(  703/  698)50/(  704/   -1)
POST 2:    6 (1edc) - 50 ba 05 fa 8a da e6 b3 9b 6c 
Events ( 517638906): 50/(  698/   -1)

It makes me very confused that events happening at the same time would be in the reverse order of discrete events.

Discrete events like this

		_delay_us(50);
		DO_MARKER( 70, LED40 );
Events (-1151761741): 48/( 512/ 1510)40/( 1115/ -1)

or



		DO_MARKER( 10, LED40 );
		DO_MARKER( 10, LED40|LED48 );
		DO_MARKER( 10, LED40 );
		DO_MARKER( 10, LED40|LED50 );
		DO_MARKER( 10, LED40 );
POST 0:   16 (b35c) - 44 50 48 ab 01 b7 01 ab 01 b2 01 a9 01 38 c4 5c 86 12 bb 91 
Events (-1285766088): 48/(  171/  183)50/(  171/  178)44/(  169/   -1)

Verses

		DO_MARKER( 10, LED40 );
		DO_MARKER( 10, LED40|LED48 );
		DO_MARKER( 10, LED40|LED48|LED50 );
		DO_MARKER( 10, LED40|LED48 );
		DO_MARKER( 10, LED40|LED48|LED50 );
		DO_MARKER( 10, LED40|LED50 );
		DO_MARKER( 10, LED40 );  *** Maybe something is not being seen?
POST 0:   20 (b544) - 46 51 4b 50 bf 01 a0 01 b5 01 fb d2 01 bf 01 ac 01 f8 37 46 8c 97 9c 84 
Events (-1253689352): 50/(  191/  160)4b/(  181/  123)51/(  210/  191)46/(  172/   -1)

These LSBs, man.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 6, 2016

*** NOTE Above message was written before I read the post by @danweecc

@CaiB

This comment has been minimized.

Copy link

commented Dec 6, 2016

@cnlohr

Regarding your statement:

It makes me very confused that events happening at the same time would be in the reverse order of discrete events.

Keep in mind that the controller cannot report data on a pulse until that pulse ends. Therefore, if (fake scenario) LED40 turns on, 50 on, 50 off, 40 off, you'll get 50's report before 40's. I assume it keeps data on when an LED turned on in memory, then only places it into a packet when that LED turns off, which would explain the reverse order in this case. I did mention how this works in my comment, using the litte arrows underneath the events:

[R40] [R48] [F48] [R50] [F50] [R48] [F48] [R50] [F50] [F40]
             ^           ^           ^           ^     ^

In this case, even though 40 turned on first, since it was last to turn off, it was last to get sent out.
You place arrows underneath falling edges, like I have, then events are sent out by the order of arrows (i.e. 1st arrow is first LED sent out, 2nd arrow is 2nd LED sent out, etc).

Then you use the information in the LSB (# of other transitions during this LED's on time) to determine how each LED relates to another.

To me, this seems like an incredibly space-efficient way to transfer this data, but it also seems like it'll be a huge pain to decode.

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

The following code seems to parse the packet

struct watchman_event_t {
  uint8_t  LED;
  uint32_t on;
  uint32_t off;
};

int main(){
  uint8_t * readdata = p;
  uint8_t length = readdata[0];
  printf("length = %d\n", length);

  readdata++;
  uint8_t * end   = &readdata[length];

  int32_t ts =  
      end[0] << 0 |
      end[1] << 8 |
      end[2] << 16;

  printf("event time = %x (%d)\n", ts, ts);
  length -= 3;
  uint32_t values[16] = {0};
  uint8_t num_values = 0;
  uint32_t total_value = 0;

  while(length--){
    // This is my ARCANEPOP
    uint8_t temp = readdata[length];
    values[num_values] = (values[num_values] << 7) | (temp & 0x7f);
    if (temp & 0x80){
      total_value += values[num_values];
      num_values++;
      if ((num_values) > length){
        break;
      }
    }
  }

  int i;
  uint8_t on_times[16] = {0};
  struct watchman_event_t events[16] = {0};
  uint8_t num_events;


  for (i = 0; i < num_values; i++){
    if ( on_times[i] ) {
      events[on_times[i]].on = total_value;
      total_value -= values[i];
      continue;
    };

    uint8_t led = *readdata++;

    events[num_events].LED = led & 0xf8;
    int on_index = i + (led & 0x7) + 1;

    events[num_events].off = total_value;
    total_value = total_value - values[i];
    on_times[on_index] = num_events++;
  }

  for (i = num_events; i--;){
    printf("EVENT: %.2X ( %d / %d )\n", events[i].LED, events[i].on, events[i].off);
  }

}

Using the following packet:

uint8_t packet[] = { 0x14, 0x56, 0x49, 0x42, 0x49, 0xf4, 0x01, 0xf2, 0x03, 0xf4, 0x01, 0xd1, 0x01, 0x96, 0x02, 0x84, 0xe9, 0x01, 0xf1, 0x07, 0xb5, 0x62, 0x27, 0xb9, 0x26};

output:

length = 20
event time = b92762 (12134242)
EVENT: 48 ( 244 / 986 )
EVENT: 40 ( 742 / 1473 )
EVENT: 48 ( 1195 / 1477 )
EVENT: 50 ( 0 / 1710 )
@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

@cnlohr. Wow, so much activity.

@danweecc, I totally missed your post just because I forgot to refresh the page. I'm not sure I completely understand what you are saying yet, but I think we agree? I don't have time now to look, but I'll read through it this evening.

There is some really detailed analysis here.
You guys are amazing.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 6, 2016

I don't know why I'm having such a hard time wrapping my head around the deltas... They can't be the end of time, since ... OH MY GOSH ... I have been reading this example backwards the entire time!

POST 0:   26 (d7d1) - 48 50 48 50 48 fc 01 f2 01 f8 01 ee 01 80 02 ef 01 f9 01 f3 01 fd 01 19 66 d2 d7 07 c8 40 
Events (-674077159): 48/(  252/  242)50/(  248/  238)48/(  256/  239)50/(  249/  243)48/(  253/   -1)
POST 2:    6 (d7d4) - 40 89 15 04 67 d2 b3 ad 71 4e 
Events (-674076924): 40/( 2697/ -1)

-674077159 IS before -674076924 chronologically!!! I can't believe I didn't notice the - sign until now! So the event time really is the end time of the packet! Sorry I've been so dense there.

Moving on... @MobiusHorizons - if you can, also print the absolute times you think these things are happening at (or start time and pulse length). I think it will make it a lot easier for us to make sure we're all on the same page. But, if I read it right... it corresponds to:

		DO_MARKER( 14, LED50 );
		DO_MARKER( 28, LED50|LED48 );
		DO_MARKER( 14, LED50|LED48|LED40 );
		DO_MARKER( 14, LED50|LED40 );
		DO_MARKER( 14, LED50|LED48|LED40 );
		DO_MARKER( 14, LED50 );

Which totally looks right to me.

If someone wants to try to shoehorn this into libsurvive (under survive_data.c), then, fire it up with the actual system, I think it would be really cool to try to read the data and see if things still make sense. I won't be able to get to it till Thursday :(

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 6, 2016

@cnlohr, I can submit a pull request, but I won't be able to test it.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 6, 2016

@MobiusHorizons if you give it a solid go, I can try to eek out an hour tonight to test and debug what I can. I will probably have another hour tomorrow.

@danweecc

This comment has been minimized.

Copy link

commented Dec 6, 2016

I should also add that the way the LL codes (LEDs) are sequenced in the packet are according to the falling edge of the pulse. So if you start at the end of the packet, the LED with the last falling edge will be listed first. For example:

LED40 |---|---|---| <-- third last falling edge
LED50     |---|---|---|---|---|---|---|---|---|---|---|---|---|---| <-- last falling edge
LED48                         |---|---|---|---| <-- second last falling edge

[53 48 41] f8 - a8 02 - f9 03 - ef 04 - 98 06 [8b 68 3a] [45 8b d9 26]

Here we find that the last falling edge belongs to LED50, followed by LED48 and finally LED40. This then determines the order where the LL codes are listed: [53 48 41]. The lower 3-bits have already been explained in my earlier post so I won't go over that again here. Just as a reminder -things break when the pulse period gets too long so keep it short and the protocol will behave. Once it gets too long, weird things happen and the rules are no longer applicable.

To reconstruct the pulses from individual LEDs, you would do something like the following:-

  1. Start from the end of the packet
  2. First LED listed is LED50 so it goes on first
  3. LED50 has the lower bits set to 3 so there are 3-transitions within it's period arising from the other LEDs
  4. add the last delta 0x0698 to the LED50 period
  5. We now reach the first transition within the LED50 period and need to determine what is happening here. Decrement LED50's transitions
    4b. LED50 now has 2 transitions left in it's period
  6. The next last falling edge belongs to the LED listed after LED50 which is LED48 so we must have reached it's falling edge
  7. From here, going backwards, LED48 has turned on
  8. The lower bits of LED48 is 0 so there are no other transitions within it's period
  9. This means that the next transition must be LED48's rising edge
  10. add the next delta, 0x04EF, to LED50's and LED48's period
  11. We now reach the next transition. Decrement LED50's and LED48's transitions
    10b. LED50 now has 1 transition left in it's period
  12. LED48 now has -1 transitions left so this means that we found it's rising edge. This pulse is done and out of play
  13. add the next delta, 0x03F9, to LED50's period
  14. We're now at the next transition edge. Decrement LED50's transitions
    13b. LED50 now has 0 transitions left in it's period
  15. This transition must belong to the next listed LED which is LED40
  16. LED40 is listed with a 1 in the LSB bits, indicating that there is one transition from the other LEDs in it;s period
  17. LED40, traversing backwards, goes on
  18. add the next delta, 0x02A8, to LED50's and LED40's periods. LED48 is out of play
  19. We now reach the next transition edge. Decrement the transitions for LED50 and LED40
    18b. LED50 now has -1 transitions left meaning that we found it's rising edge. This pulse is done and out of play
    18c. LED40 now has 0 transitions left
  20. add the next delta, 0xF8?, to the period of LED40. LED50 and LED48 are out of play
  21. We now reach the next transition edge. Decrement the transitions for LED40
    20b. LED40 now has -1 transitions left meaning that we've found it's rising edge. This pulse is done and out of play

By now we have the cumulative periods for LED50 and LED40, and the period for LED48. We know where they start and end.

What I've not ascertained is what happens when two or more LED's have simultaneous rising and/or falling edges.

@CaiB

This comment has been minimized.

Copy link

commented Dec 6, 2016

What I've not ascertained is what happens when two or more LED's have simultaneous rising and/or falling edges.

DO_MARKER( 14, LED40 );             //  0 - 14
DO_MARKER( 28, LED40|LED48 );       // 14 - 42
DO_MARKER( 14, LED40|LED48|LED50 ); // 42 - 56
DO_MARKER( 14, LED40|LED50 );       // 56 - 70
DO_MARKER( 14, LED40|LED48|LED50 ); // 70 - 84
DO_MARKER( 14, LED40 );             // 84 - 98

Events (1223063503): 49/(  242/  492)52/(  247/  209)49/(  279/    2)46/(  239/   -1)

This is closest we have to two turning off simultaneously, but the controller just reports the two edges as 2 cycles apart. I'm assuming the AVR's output, and the imperfect positioning of the LEDs on the sensors is causing this delay. It'd be very interesting to see what is actually output if the controller sees them turning off simultaneously.
@cnlohr: Could you try a few more times to get simultaneous edges, and give us the output if you get one?

@danweecc

This comment has been minimized.

Copy link

commented Dec 7, 2016

@CaiB - Do we have the raw packet data?

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

For @CaiB:

		DO_MARKER(20, LED40);
		DO_MARKER(45, LED50|LED40);

produces:

POST 0:   10 (f83d) - 51 41 ae 02 b3 05 95 18 5a 3f 6e 75 be 18 
Events (-130065896): 41/(  302/  691)51/(   21/   -1)
POST 0:   10 (ab75) - 51 41 c2 02 b6 05 80 4e 41 77 57 32 38 74 
Events (-1418247858): 41/(  322/  694)51/(    0/   -1)

and

Events (-1423959211): 50/(  322/  693)42/(    1/   -1)
@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

@danweecc @MobiusHorizons I think we're all on the same page, it's just very difficult to speak in terms of each other. Like I think I could describe it better than I could read what someone else wrote and agree if they're thinking the same thing as me. I am taking a peek at Mobius Horizon's code.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

I have more code. Mine seems to work almost perfectly (haven't checked start times) But I found a case where it breaks.

		uint32_t imutime = (time1<<24) | (time2<<16);
		uint32_t mytime = (end[1] << 0)|(end[2] << 8)|(end[3] << 16);
		mytime |= (time1<<24);
		int32_t tdiff = mytime - imutime;
		if( tdiff > 0x7fffff )  { mytime -= 0x01000000; }
		if( tdiff < -0x7fffff ) { mytime += 0x01000000; }

		uint32_t  parameters[25];
		int parplace = 0;

		while( end != start )
		{
			uint32_t acpop = ARCANEPOP( &end, start );
			parameters[parplace++] = acpop;
			int remain = end - start + 1;
			if( (parplace+1) / 2 >= remain ) break;
		}

		uint32_t lights[10];
		int lightno = 0;

		while( end >= start )
		{
			lights[lightno++] = end[0];
			end--;
		}

		if( (parplace+1)/2 != lightno )
		{
			struct SurviveContext * ctx = w->ctx;
			SV_INFO( "Watchman code count doesn't match" );
			return;
		}
#if 1
		//This is getting very close.

		const int M_LEDS = 32;
		uint8_t onleds[M_LEDS];
		uint32_t offtimes[M_LEDS];
		memset( onleds, 0, sizeof( onleds ) );
		int k = 0;

		for( i = lightno-1; i >= 0; i-- )
		{
			int led = lights[i]>>3;
			int ledtime = lights[i]&0x07;
			int deltaA = k?parameters[k*2-1]:0;
			int deltaB = parameters[k*2+0];

			k++;

			onleds[led] = ledtime+2;
			offtimes[led] = mytime;
			printf( "%d %d %d %d\n", led, ledtime, deltaA, deltaB );

			mytime -= deltaA;

			for( j = 0; j < M_LEDS; j++ )
			{
				if( onleds[j] )
				{
					onleds[j]--;
					if( !onleds[j] )
					{
						//Got a light event.
						struct LightcapElement le;
						le.type = 0xfe;
						le.sensor_id = j;
						le.timestamp = mytime;
						le.length = offtimes[j] - mytime;
						handle_lightcap( w, &le );
						printf( "Light Event: LED %d @ %d, len %d (%d)\n", j, mytime, le.length, deltaB );
					}
				}
			}
			mytime -= deltaB;
			for( j = 0; j < M_LEDS; j++ )
			{
				if( onleds[j] )
				{
					onleds[j]--;
					if( !onleds[j] )
					{
						//Got a light event.
						struct LightcapElement le;
						le.type = 0xfe;
						le.sensor_id = j;
						le.timestamp = mytime;
						le.length = offtimes[j] - mytime;
						handle_lightcap( w, &le );
						printf( "Light Event: LED %d @ %d, len %d (%d)\n", j, mytime, le.length, deltaB );
					}
				}
			}
		}

		for( j = 0; j < M_LEDS; j++ )
		{
			if( onleds[j] )
			{
				fprintf(stderr, "ERROR: Too many LEDs found (%d = %d)\n", j, onleds[j] );
			}
		}

#endif

If I use the following AVR code:

		DO_MARKER(20, LED50);
		DO_MARKER(20, LED50|LED48);
		DO_MARKER(20, LED48);
		DO_MARKER(20, LED40|LED48);
		DO_MARKER(20, LED40);
		DO_MARKER(20, LED40|LED48);
		DO_MARKER(20, LED40);
		DO_MARKER(20, LED40|LED48);
		DO_MARKER(20, LED40);
		DO_MARKER(20, LED40|LED48);
		DO_MARKER(20, LED48);

It seems to break it.

POST 0:   25 (528a) - 45 48 48 4a 51 cb 04 b5 bd 02 99 02 95 03 e9 01 98 03 e5 01 98 05 82 80 8a 79 50 0f 73 
8 5 0 664
9 0 229 408
Light Event: LED 9 @ 1384807277, len 637 (408)
9 0 233 405
Light Event: LED 9 @ 1384806639, len 638 (405)
9 2 281 317
Light Event: LED 8 @ 1384806358, len 2220 (317)
10 1 53 587
Light Event: LED 9 @ 1384805401, len 1238 (587)
ERROR: Too many LEDs found (10 = 1)
POST 0:    6 (528a) - 48 a3 04 a7 81 8a 6f 94 08 b6 
9 0 0 547
Light Event: LED 9 @ 1384808324, len 547 (547)

Any ideas?

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

@CaiB do you have a twitter account so I can ping you?

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

@cnlohr Yeah, @TheCaiB.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

@CaiB, @danweecc @MobiusHorizons - looks like I ran into something that doesn't work. I wonder if that is a special code for "this continues onto the next line or something.

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

Does it really need a continuation flag? You might be able to infer that it will continue from the fact that an LED is reported to turn on, but it turning off is never reported in the current packet.

Like this:
If an LED turns on, creating a new packet (time=0 for turnon), and other LEDs happen, you know that some LED must've turned on at time=0. If the end is not found inside this packet, you know it must be in the next.

If the long LED pulse starts after the start of a packet, you track the amount of transitions, and if one is missing, you know that something is still on, therefore you wait until the next packet to see when it turns off.

You may also be able to use the overall time and deltas to see that a second packet continues from the first. This approach may be simpler and more reliable.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

Even with that next packet, how would you infer when it actually turned off? Even if I know it continues, I can't really tell /when/ the final transition would happen, since the next packet only contains one parameter.

@danweecc

This comment has been minimized.

Copy link

commented Dec 7, 2016

@cnlohr - I'm looking at the example you gave above but the raw packet data seems to either be corrupt or incomplete:

POST 0: 25 (528a) - 45 48 48 4a 51 cb 04 b5 bd 02 99 02 95 03 e9 01 98 03 e5 01 98 05 82 80 8a 79 50 0f 73

There seem to be three LEDs involved - LED40, LED48 and LED50 - and the header is showing:

45 48 48 4a 51

I'm actually somewhere over the East China Sea in a plane so I've not been tracking the developments but based on my understanding of how the LSB bits encode for the transitions - I don't think it is possible for it to encode so many events within a packet. Basically here's how I see the data header above: In order to encode for the particular pulse configuration that you have generated, and following on the rules for encoding derived earlier - the header should actually look like:-

49 46 48 48 4a 51

This comes from the following pulse configuration:

      0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22  23
LED50 |---+---+---+---|
LED48         |---+---+---+---+---+---|       |---+---|       |---+---|       |---+---+---+---| <-- this pulse went missing
LED40                         |---+---+---+---+---+---+---+---+---+---+---+---+---+---|
                      ^               ^               ^               ^               ^       ^
                      51              4a              48              48              46      49

Looking at the actual raw data, we seem to be missing out on the very last pulse so the "49" does not appear as the first light code. Secondly, the rising edge of that pulse was also not counted by the system such that the LED40 code which should have been 46 due to the 6-transitions within it's pulse period now contains one less transition giving us 45 as the second light code. All of this points to the entire pulse configuration being too complex (too many pulses to track) and so the system is dropping the last pulse.

It looks like there is a possible limit to how many light codes are permitted within a packet. In your example, you needed 6 light codes to properly encode the frame but maybe the system can only handle a maximum of 5 and so that's causing the last pulse to be dropped.

@danweecc

This comment has been minimized.

Copy link

commented Dec 7, 2016

More from 35000ft in the sky.

I'm not completely sure how the deltaA and deltaB are derived and how they work in your code but it looks like they represent the periods from one transition edge to another. Assuming we drop the last pulse (as explained in my previous post) and take the configuration as presented in the raw data, you will be looking at 9 edge transitions in all, excluding the final falling edge. This means we can expect 9 period parameters in the packet. Assuming that each parameter is a 2-byte word, we are expecting 18-bytes of parameters but the raw data is showing only 17-bytes.

It may be that you have already figured out how to parse the parameter string correctly but I'm still a little confused by it. From your code, it looks like you're treating deltaA separately from deltaB - I must have missed the bit where you guys worked this out. How are you handling the single-byte parameters?

[45 48 48 4a 51] cb 04 - b5 - bd 02 - 99 02 - 95 03 - e9 01 - 98 03 - e5 01 - 98 05 [82 80 8a] [79 50 0f 73] ^^

That's as much as I can figure out for now.

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

Hmm, honestly, the more I look at the case with > 7 events, the less I understand how it's supposed to be interpreted.

Which brought me to this thought: In a real-world application, I can't think of a scenario where you have one sensor excited, more than three other complete pulses, and then the first one turns off. The lighthouse sweeps, so I can't imagine a placement of the controller that would actually cause this in a real application.

Maybe the controller isn't programmed to handle this unusual circumstance, so the output is corrupted somehow? I have a hard time believing the devs at Valve would've spent extra time on a feature that should never be needed...

Thoughts?

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

Here's an idea, @cnlohr. Add a global counter to your program for the amount of times that you receive a packet that you can't interpret properly like above. Then, use the controllers with actual lighthouses (remove AVR) for a while, in a realistic way, and see what happens. If you only get a minimal amount of unreadable packets, we can probably just ignore them for now...

@danweecc

This comment has been minimized.

Copy link

commented Dec 7, 2016

@CaiB - the key to working out the pulse configuration lies in the initial lights code and the LSB bits encoded in them. In this example, a correctly encoded header should read as follows:-

49 46 48 48 4a 51

This is normally followed by the 11-deltas that reflect the 11-edges in the frame. Looking at this header, we know that the last falling-edge belongs to LED48 so we work backwards from this. I started writing out pseudo-code to explain this but it got too complicated. I suggest you work through this logically - every time you encounter a transition that isn't a falling edge of an already-on-LED, you read the next LED code and turn it on. If you keep going this way, you should be able to generate the pulse frame.

There is only one caveat - when you scan through your LED state table, you need to process the LEDs with the least remaining transitions first. After you've processed all the LEDs, you look to see if the transition is unaccounted for (ie. no edge from other LED's turning on or off). If there are unaccounted transitions, you read the next LED code.

This strategy allows you to turn on the same LED a few times. Your result must be a dynamically generated event and not a fixed state table to allow for the same LED being turned on and off a few times. In Charles' code, he did this with the "le" struct so that's good.

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

@danweecc Which comment are you replying to here?

@danweecc

This comment has been minimized.

Copy link

commented Dec 7, 2016

Hmm, honestly, the more I look at the case with > 7 events, the less I understand how it's supposed to be interpreted

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

I think we're looking at two different issues here.

If you look back at my very first comment (second comment in the whole thread), where I detailed my findings, the last test I did involved an LED turning on, then 8 other transitions (rising & falling edges) happening, then the first LED turning off. This created two packets, and a data point went missing.

In your example, you're talking about too many transitions for a single data packet to contain, but not too many transitions in the duration of a single LED's pulse.

My statement regarding > 7 events was meant as "the case with > 7 events in the course of a single LED being on". Sorry, this was vague, I should word things better.

As I found, the LED codes have the number of other transitions added on. But there's only 7 possible transitions you can add on before you increase the code so much it appear like the next LED (LED40 + 8 transitions = 48, which would be interpreted as 48 with no transitions). Or as you like to put it, the 3 LSBs of the LED code can no longer hold the number of transitions that occurred.

Therefore, I was looking at the example where the controller may try to encode LED40 + 8 events = 48. It didn't do this, instead creating a new packet for LED40, but the last event went missing somehow. This is what I was confused by, and what I was saying to Charles to see if this scenario ever happens in a real world application.

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

But, likewise with your proposed scenario, we should still get Charles to check if anything like that ever happens. Your example has 6 pulses overlapping in such a way that they can't be split well. Would this ever occur in the real world with lighthouses? If no, pursuing these scenarios seems like a waste of time to me.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

I was just thinking about it... in my code... even on the first event, when there's only one possible edge, I still -deltaA, and check for subtracting edges. That is definitely wrong. I think I said ledtime+1; to compensate for that. Which is also wrong. I'll have to poke with it later today, but I "think" the packets make sense as they are and do not violate any of the rules. I don't think there needs to be a continuation bit and I don't think anything's really... wrong.

I don't "think" I need to keep state between led batches either. I will have to test tonight.

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

OK, I think we have a good handle on the logic now, just needs code and a bit more testing. That said, I will leave the actual code implementation to you, unless you want it in C# :P

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

Got some more data... Including some general lighthouse outputs.

DO_MARKER(20, LED50|LED48);
DO_MARKER(20, LED48);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED48);

produces:

POST 0:   26 (9ee9) - 48 48 48 49 51 db 02 a0 02 e1 04 cd 02 ae 02 ce 02 ad 02 cf 02 ad 02 c3 4d e9 9b 0f 3a e8 
9 0 0 301
Light Event: LED 9 @ -1628877674, len 301
9 0 335 301
Light Event: LED 9 @ -1628878009, len 335
9 0 334 302
Light Event: LED 9 @ -1628878644, len 334
9 1 333 609
Light Event: LED 9 @ -1628879888, len 942
10 1 288 347
Light Event: LED 10 @ -1628880523, len 635
POST 0:   11 (9ee9) - 49 41 be 13 aa 02 bf 02 7b 51 e9 2d c8 8f 11 
9 1 0 319
8 1 298 2494
Light Event: LED 9 @ -1628877038, len 617
Light Event: LED 8 @ -1628879532, len 2792
POST 0:   26 (9ef5) - 48 48 48 49 51 db 02 a1 02 e2 04 cd 02 af 02 ce 02 ae 02 cf 02 ad 02 e0 d0 f5 9b 0f 3a e8 
9 0 0 301
Light Event: LED 9 @ -1628057677, len 301
9 0 335 302
Light Event: LED 9 @ -1628058012, len 335
9 0 334 303
Light Event: LED 9 @ -1628058648, len 334
9 1 333 610
Light Event: LED 9 @ -1628059894, len 943
10 1 289 347
Light Event: LED 10 @ -1628060530, len 636
POST 0:   11 (9ef5) - 49 41 c1 13 ad 02 be 02 9a d4 f5 b9 b4 98 51 
9 1 0 318
8 1 301 2497
Light Event: LED 9 @ -1628057041, len 619
Light Event: LED 8 @ -1628059538, len 2798
POST 0:   26 (9f00) - 48 48 48 49 51 db 02 a1 02 e2 04 cd 02 b0 02 cd 02 ae 02 ce 02 ae 02 2c 55 02 9b 0f 3a e8 
9 0 0 302
Light Event: LED 9 @ -1627237378, len 302
9 0 334 302
Light Event: LED 9 @ -1627237712, len 334
9 0 333 304
Light Event: LED 9 @ -1627238347, len 333
9 1 333 610
Light Event: LED 9 @ -1627239594, len 943
10 1 289 347
Light Event: LED 10 @ -1627240230, len 636
POST 2:   11 (9f03) - 49 41 c3 13 ac 02 be 02 e5 58 02 3f 9b 0f 3a 
9 1 0 318
8 1 300 2499
Light Event: LED 9 @ -1627236741, len 618
Light Event: LED 8 @ -1627239240, len 2799
DO_MARKER(20, LED50);
DO_MARKER(20, LED50|LED48);
DO_MARKER(20, LED48);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
produces:
POST 0:   22 (236f) - 48 49 51 40 ac 18 ee 66 31 da 02 a1 02 e1 04 ce 02 ae 02 6e 7c 70 24 82 a2 3a 
9 0 0 302
Light Event: LED 9 @ 594574144, len 302
9 1 334 609
Light Event: LED 9 @ 594573201, len 943
10 1 289 346
Light Event: LED 10 @ 594572566, len 635
8 0 815982 3116
OFLOW: LED 8 @ 593756584, len 815982
POST 0:   16 (236f) - 48 48 48 ad 02 cf 02 ad 02 cf 02 ad 02 e1 83 70 36 ac 89 ab 
9 0 0 301
Light Event: LED 9 @ 594576052, len 301
9 0 335 301
Light Event: LED 9 @ 594575717, len 335
9 0 335 301
Light Event: LED 9 @ 594575081, len 335
POST 0:   22 (237b) - 48 49 51 40 aa 18 c6 63 31 db 02 a1 02 e3 04 cd 02 af 02 3f fe 7c a4 a1 30 5d 
9 0 0 303
Light Event: LED 9 @ 595393808, len 303
9 1 333 611
Light Event: LED 9 @ 595392864, len 944
10 1 289 347
Light Event: LED 10 @ 595392228, len 636
8 0 815558 3114
OFLOW: LED 8 @ 594576670, len 815558
POST 2:   11 (237e) - 48 48 ad 02 cf 02 ad 02 37 03 7d 3e 22 0f 30 
9 0 0 301
Light Event: LED 9 @ 595395082, len 301
9 0 335 301
Light Event: LED 9 @ 595394747, len 335
POST 0:    6 (237e) - 48 ad 02 b4 05 7d 7c f2 48 19 
9 0 0 301
Light Event: LED 9 @ 595395719, len 301
POST 0:   22 (2389) - 48 49 51 40 ae 18 f8 60 31 da 02 a0 02 e0 04 cd 02 ad 02 bd 7e 89 d1 6c d8 04 
9 0 0 301
Light Event: LED 9 @ 596213136, len 301
9 1 333 608
Light Event: LED 9 @ 596212195, len 941
10 1 288 346
Light Event: LED 10 @ 596211561, len 634
8 0 815224 3118
OFLOW: LED 8 @ 595396337, len 815224

General lighthouse outputs:

Light Event: LED 5 @ -1471666040, len 593
POST 0:   11 (a848) - 00 10 b2 04 fc 04 ce 04 dc 31 48 8b 25 a9 ce 
Light Event: LED 0 @ -1471664242, len 590
Light Event: LED 2 @ -1471664878, len 636
POST 0:   15 (a84e) - be 2c 1a 50 cc df db ee 12 89 85 85 1a 54 4c 16 b9 bf fa 
Light Event: LED 3 @ -1471395361, len 2600
Light Event: LED 5 @ -1471395361, len 2614
Light Event: LED 10 @ -1471395361, len 95
Light Event: LED 23 @ -1471395437, len 2695
POST 0:   25 (a84e) - 59 81 60 28 60 94 17 95 7e ef 26 cb 1a 0c b1 02 86 02 8f 8c 01 bc 0c b7 4f 16 a8 15 51 
Light Event: LED 11 @ -1471171004, len 200
Light Event: LED 16 @ -1471171019, len 155
Light Event: LED 12 @ -1471171281, len 262
OFLOW: LED 5 @ -1471371597, len 200011
Light Event: LED 12 @ -1471392721, len 16149
POST 2:    6 (a851) - b0 c6 02 99 bd 4f cd eb d2 bf 
Light Event: LED 22 @ -1471169453, len 326
POST 0:   22 (a854) - 60 b0 28 b0 f0 22 86 72 e2 2a d0 3e 0a a9 02 a5 07 89 02 3b 68 55 06 86 23 f2 
Light Event: LED 12 @ -1470798030, len 265
Light Event: LED 22 @ -1470798963, len 933
OFLOW: LED 5 @ -1470971116, len 171856
Light Event: LED 22 @ -1470991188, len 14598
POST 0:   25 (a85a) - 2b 51 4a 28 60 c7 2e e6 66 84 1f fb 31 0b d9 01 da ca db 02 e4 02 f6 b4 5b 9a a8 15 51 
Light Event: LED 10 @ -1470385683, len 421
Light Event: LED 5 @ -1470385773, len 867
OFLOW: LED 5 @ -1470572609, len 186619
OFLOW: LED 9 @ -1470572609, len 186926
Light Event: LED 12 @ -1470589739, len 13158
POST 2:   11 (a85d) - 90 38 f6 05 f3 05 81 05 81 bb 5b 7e a8 15 51 
Light Event: LED 18 @ -1470383872, len 641
Light Event: LED 7 @ -1470384627, len 755
POST 0:   26 (a85d) - 10 0b 03 1b 23 30 b2 02 ba 0a c9 b2 c3 96 02 ea 02 ee d4 ff 05 b0 06 6d cc 5b a8 15 51 e8 
Light Event: LED 2 @ -1470379715, len 816
Light Event: LED 1 @ -1470381038, len 1323
Light Event: LED 0 @ -1470381383, len 817
Light Event: LED 3 @ -1470381506, len 468
Light Event: LED 6 @ -1470382844, len 1338
Light Event: LED 4 @ -1470383150, len 1767
POST 0:   22 (a860) - 20 18 28 b0 c9 2a 98 6a 96 1b fd 39 06 a7 03 b7 08 a3 02 3d 94 60 b7 58 3f 5a 
Light Event: LED 4 @ -1470065894, len 291
Light Event: LED 3 @ -1470066973, len 1079
OFLOW: LED 5 @ -1470173121, len 105725
Light Event: LED 22 @ -1470190191, len 13592
POST 2:   10 (a862) - 09 29 89 04 c9 fd 03 ca 96 60 1a b3 a8 15 
Light Event: LED 1 @ -1470065532, len 582
Light Event: LED 5 @ -1470066053, len 594
POST 0:   11 (a862) - 00 10 b3 04 fa 04 d1 04 d1 9b 60 b3 c9 f9 a3 
Light Event: LED 0 @ -1470064256, len 593
Light Event: LED 2 @ -1470064890, len 634
POST 0:   25 (a868) - 59 81 60 28 b0 ff 1e c1 76 ee 26 b6 1a 0c af 02 8a 02 86 93 01 bd f4 20 68 82 a8 15 51 
Light Event: LED 11 @ -1469571036, len 208
Light Event: LED 16 @ -1469571042, len 153
Light Event: LED 12 @ -1469571308, len 266

and

Light Event: LED 2 @ 1876791825, len 814
1 3 766 96
0 3 94 372
Light Event: LED 1 @ 1876790497, len 1328
3 3 266 80
Light Event: LED 0 @ 1876790151, len 812
4 3 26 81
Light Event: LED 3 @ 1876790044, len 453
6 0 1407 223
Light Event: LED 6 @ 1876788637, len 1407
Light Event: LED 4 @ 1876788414, len 1737
POST 0:   22 (6fe1) - 20 18 28 60 d4 2a c8 70 fb 22 89 32 06 a0 03 c3 08 90 02 20 5d e2 37 61 b9 19 
4 0 0 272
Light Event: LED 4 @ 1877105680, len 272
3 0 1091 416
Light Event: LED 3 @ 1877104589, len 1091
5 0 104713 4475
OFLOW: LED 5 @ 1876999460, len 104713
12 0 14408 5460
Light Event: LED 12 @ 1876980577, len 14408
POST 2:   10 (6fe4) - 09 29 8b 04 bf fc 03 b1 5f e2 29 a2 6f 0f 
1 1 0 508
5 1 63 523
Light Event: LED 1 @ 1877106038, len 571
Light Event: LED 5 @ 1877105515, len 586
POST 0:   11 (6fe4) - 00 10 ad 04 80 05 ca 04 ba 64 e2 d6 4a 7a ce 
0 0 0 586
Light Event: LED 0 @ 1877107312, len 586
2 0 640 557
Light Event: LED 2 @ 1877106672, len 640
POST 0:   25 (6fe7) - 59 81 60 28 60 f8 1e ac 7c d0 2e d9 0c 0c ad 02 83 02 9c 84 01 b5 c1 e6 e9 af 6f 0f cd 
11 1 0 53
16 1 132 28
Light Event: LED 11 @ 1877599752, len 185
Light Event: LED 16 @ 1877599724, len 160
12 0 259 301
Light Event: LED 12 @ 1877599465, len 259
5 0 198233 5968
OFLOW: LED 5 @ 1877400931, len 198233
12 0 15916 3960
Light Event: LED 12 @ 1877379047, len 15916
POST 2:    6 (6fea) - b0 c4 02 51 ed e9 44 76 ba 18 
22 0 0 324
Light Event: LED 22 @ 1877601293, len 324
POST 0:   22 (6fed) - 60 b0 28 60 ef 22 a2 78 d2 32 b0 30 0a a6 02 a8 07 89 02 fd 97 ef 8f e0 60 70 
12 0 0 265
Light Event: LED 12 @ 1877972724, len 265
22 0 936 294
Light Event: LED 22 @ 1877971788, len 936
5 0 170032 6482
OFLOW: LED 5 @ 1877801462, len 170032
12 0 15394 4463
Light Event: LED 12 @ 1877779586, len 15394
@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 7, 2016

(Above for @CaiB @danweecc and @MobiusHorizons -- do you guys get notifications when I @ you?

@CaiB

This comment has been minimized.

Copy link

commented Dec 7, 2016

@cnlohr: No, I don't get notifications, and I can't find a place to enable them. I'll have a look at the data later.

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 8, 2016

@danweecc, I just have to say I really love your ASCII graphs, I think they help clarify the encoding very much.

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 8, 2016

@cnlohr: about the packet with dropped events:

If there are too many events for a packet, I would expect the packet to get sent as soon as it filled up. And another packet to follow it with the later events shortly after. For this reason I don't think you would have some kind of continue packet, but rather two packets of events one after the other. However this is based on my understanding of the comments of Ben and vk2zay on chat, so I wouldn't be surprised to be wrong.

The biggest limitation on the packet seems to me to be based on the LSB's only being 3 bits. I would expect that the system can't handle more than 7 events taking place in between a sensor's rising and falling edge. I think @CaiB is probably right that this is an uncommon scenario that didn't need to be handled for normal operation of the watchman, although that is just a guess.

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 8, 2016

@cnlohr, your event parsing seems good to me, although i'll be honest and say i don't completely understand the timestamp at the end of the packet. I remember in your Saturday night -> Sunday morning stream, you (at one point) found that the IMU timestamps and the sensor timestamps were lining up. Is that still the case? I wonder because the negative numbers don't look like what I remember.

what condition causes the OFLOW in your logs above. Is that when packets don't match up number of leds, to number of transitions?

At this point it looks to me like you have gotten everything I understand. What do you need next?

@danweecc

This comment has been minimized.

Copy link

commented Dec 8, 2016

@MobiusHorizons - thanks. The visualizations help me think this through logically.

@cnlohr - no I don't get notifications either.

From your recent examples I am inclined to agree with Mobius. It looks like additional packets are handled in a subsequent packet and the encoding is done cleanly. All you really need to correlate the two, then, are the actual timestamps. Looks like this is pretty much cracked.

@Zmathue

This comment has been minimized.

Copy link

commented Dec 8, 2016

So I wrote this today after watching the latest youtube video, so far it has succeed at pretty much everything I threw at it. (the scanline packets that are very long dont look so great, but those would be filtered out anyway as that is not something we need to measure)

The only thing I cant figure out is why in the most recent data

DO_MARKER(20, LED50|LED48);
DO_MARKER(20, LED48);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED48);

LED50 does not start at the same time as LED48, it should be able to but instead of the lower bits being 000 to achieve this they are set to 001. There is also no other place in the packet for this information to be stored so I have no idea what is wrong....

cnlohr7pm
the magenta line is LED50, and cyan is LED48

and the information parsed from this:

Time:  29996
Deltas:  [347, 289, 610, 333, 304, 333, 302, 334, 302]
Times:  [26842, 27189, 27478, 28088, 28421, 28725, 29058, 29360, 29694, 29996]
LED  0x48 Flags:  000
LED  0x48 Flags:  000
LED  0x48 Flags:  000
LED  0x48 Flags:  001
LED  0x50 Flags:  001
ViveLEDNumber:  0x48    Start time:  29694    End time: 29996   transNum(should be negative!):  -9
ViveLEDNumber:  0x48    Start time:  29058    End time: 29360   transNum(should be negative!):  -7
ViveLEDNumber:  0x48    Start time:  28421    End time: 28725   transNum(should be negative!):  -5
ViveLEDNumber:  0x48    Start time:  27189    End time: 28088   transNum(should be negative!):  -2
ViveLEDNumber:  0x50    Start time:  26842    End time: 27478   transNum(should be negative!):  -1

Time:  30949
Deltas:  [2499, 300, 318]
Times:  [27832, 30331, 30631, 30949]
LED  0x48 Flags:  001
LED  0x40 Flags:  001
ViveLEDNumber:  0x48    Start time:  30331    End time: 30949   transNum(should be negative!):  -2
ViveLEDNumber:  0x40    Start time:  27832    End time: 30631   transNum(should be negative!):  -1

and the code: (i'm a C developer I swear!!, but python is so good for RE)

#!/usr/bin/env python
#Zack Kolarich 2016

import numpy as np
import matplotlib.pyplot as plt

packets = []
#GOOD
#packets.append(bytes.fromhex("  40 50 48 b0 05 a2 02 c1 05 c7 03 f1 03 65 9b 2f 80 03 2b 58  "))
#packets.append(bytes.fromhex("  40 50 48 b0 05 a2 02 c2 05 cb 03 ec 03 63 f4 33 28 40 ed c5  "))
#packets.append(bytes.fromhex("  40 50 48 b2 05 a3 02 c3 05 c5 03 f5 03 57 4e 38 d2 2e c9 30  "))
#GOOD
#packets.append(bytes.fromhex("  4a 50 b8 05 c1 05 b4 05 b6 b1 3d e8 dc 86 2e    "))
#packets.append(bytes.fromhex("  4a 50 b6 05 c0 05 b2 05 bf 09 42 5f 9b a8 e3   "))
#packets.append(bytes.fromhex("  4a 50 b6 05 c0 05 b2 05 bf 09 42 5f 9b a8 e3   "))

#91 GOOD
#packets.append(bytes.fromhex("  52 48 cb 05 ac 05 c0 05 13 b2 24 2b 65 ee 99   "))
#104 GOOD, shows a large value as it is reading the scanline as part of the frame 
#packets.append(bytes.fromhex("  50 c5 7b 03 f7 a7 a0 f1 12 65 81   "))
#204 Good
#packets.append(bytes.fromhex("   51 41 b5 03 c5 02 c9 01 8e 3f b8 86 85 bb b7    "))
#211 Good
#packets.append(bytes.fromhex("  51 41 86 02 c4 02 f8 02 90 94 eb b9 24 5b 63    "))
#276 GOOd
#packets.append(bytes.fromhex("  42 50 95 01 c2 05 ef 0a 1b 1f 3b cc 8e 19 e9    "))
#285 Odd
#packets.append(bytes.fromhex("  50 50 50 40 94 26 b0 23 11 c2 05 bd 05 c1 05 c4 05 bd 05 b8 e4 3d 20 92 0c ca    "))

#325  
#packets.append(bytes.fromhex("  50 50 50 48 8b 26 bb 22 11 be 05 bc 05 bf 05 c2 05 bb 05 04 29 57 89 58 68 fe    "))

#367 GOOD 
#packets.append(bytes.fromhex("  4a 50 4a 40 b8 05 bc 05 b0 05 94 02 d7 05 ba 05 b2 05 14 59 b4 75 86 56 a5     "))

#392 odd 
#packets.append(bytes.fromhex("  50 50 42 48 cf 05 92 1b c4 05 bb 22 11 bd 05 b7 05 be 05 b4 6e ed 89 d4 56 85     "))

#435 PERFECT!
#packets.append(bytes.fromhex("  46 51 4b 50 bf 01 a0 01 b5 01 fb d2 01 bf 01 ac 01 f8 37 46 8c 97 9c 84      "))


#471 also PERFECT! it did not split over a packet boundry, not sure if coincidence or just protocal working correctly, pretty sure if I wrote
#the protocal I dont see there being a need to split over boundry as it should work better without, especially if timing comes over internal bus
#from fpga to mcu
#packets.append(bytes.fromhex("  48 50 48 50 48 fc 01 f2 01 f8 01 ee 01 80 02 ef 01 f9 01 f3 01 fd 01 19 66 d2 d7 07 c8 40       "))
#packets.append(bytes.fromhex("  40 89 15 04 67 d2 b3 ad 71 4e    "))

#455 MULTIPACKET GOOD
#packets.append(bytes.fromhex("  50 48 50 48 b7 01 ab 01 b2 01 9f 01 c1 01 a0 01 bd 01 44 8a 2c f8 37 e7 3c       "))
#packets.append(bytes.fromhex("  40 a4 0c ed 8a 2c 6b bc ea 55       "))

#532 Good
#packets.append(bytes.fromhex("  56 43 48 49 f6 01 fb 03 e4 01 d6 01 95 02 ec 01 f2 01 67 ad 5f 24 9c 44 80       "))
#623good
#packets.append(bytes.fromhex(" 40 48 50 40 b5 02 ad 02 8d 04 a2 02 b3 05 bb 02 c5 06 56 85 74 22 a2 36 96      "))

# #test 654
# #10,20,30,40,50
# packets.append(bytes.fromhex("  53 48 41 f8 a8 02 f9 03 ef 04 98 06 8b 68 3a 45 8b d9 26   "))
# #10,20,30,50,70
# packets.append(bytes.fromhex("  53 48 41 fa a8 02 fa 03 8f 06 d4 08 0f 74 b4 c9 fd d7 29    "))

#cnlohr 10/7 ~7pm gist post GOOD, make sure you get two that the data blocks overlap otherwise it may look odd, but it is still good either way
#packets.append(bytes.fromhex("  48 48 48 49 51 db 02 a1 02 e2 04 cd 02 af 02 ce 02 ae 02 cf 02 ad 02 e0 d0 f5 9b 0f 3a e8       "))
#packets.append(bytes.fromhex("  49 41 c1 13 ad 02 be 02 9a d4 f5 b9 b4 98 51       "))
	#Identicle \/
#packets.append(bytes.fromhex("  48 48 48 49 51 db 02 a1 02 e2 04 cd 02 b0 02 cd 02 ae 02 ce 02 ae 02 2c 55 02 9b 0f 3a e8      "))
#packets.append(bytes.fromhex("  49 41 c3 13 ac 02 be 02 e5 58 02 3f 9b 0f 3a       "))

#General lighthouse outputs
#packets.append(bytes.fromhex(" 00 10 b2 04 fc 04 ce 04 dc 31 48 8b 25 a9 ce   "))
#packets.append(bytes.fromhex(" be 2c 1a 50 cc df db ee 12 89 85 85 1a 54 4c 16 b9 bf fa    "))
# packets.append(bytes.fromhex(" 59 81 60 28 60 94 17 95 7e ef 26 cb 1a 0c b1 02 86 02 8f 8c 01 bc 0c b7 4f 16 a8 15 51    "))
# packets.append(bytes.fromhex(" b0 c6 02 99 bd 4f cd eb d2 bf     "))
# packets.append(bytes.fromhex(" 60 b0 28 b0 f0 22 86 72 e2 2a d0 3e 0a a9 02 a5 07 89 02 3b 68 55 06 86 23 f2    "))
# packets.append(bytes.fromhex(" 2b 51 4a 28 60 c7 2e e6 66 84 1f fb 31 0b d9 01 da ca db 02 e4 02 f6 b4 5b 9a a8 15 51    "))

#OFLOW test
# packets.append(bytes.fromhex("  00 10 b2 04 fc 04 ce 04 dc 31 48 8b 25 a9 ce       "))
# packets.append(bytes.fromhex("  be 2c 1a 50 cc df db ee 12 89 85 85 1a 54 4c 16 b9 bf fa     "))
# packets.append(bytes.fromhex("  59 81 60 28 60 94 17 95 7e ef 26 cb 1a 0c b1 02 86 02 8f 8c 01 bc 0c b7 4f 16 a8 15 51     "))
# packets.append(bytes.fromhex("  b0 c6 02 99 bd 4f cd eb d2 bf        "))
# packets.append(bytes.fromhex("  60 b0 28 b0 f0 22 86 72 e2 2a d0 3e 0a a9 02 a5 07 89 02 3b 68 55 06 86 23 f2       "))
# packets.append(bytes.fromhex("  2b 51 4a 28 60 c7 2e e6 66 84 1f fb 31 0b d9 01 da ca db 02 e4 02 f6 b4 5b 9a a8 15 51     "))
# packets.append(bytes.fromhex("  90 38 f6 05 f3 05 81 05 81 bb 5b 7e a8 15 51    "))
# packets.append(bytes.fromhex("  10 0b 03 1b 23 30 b2 02 ba 0a c9 b2 c3 96 02 ea 02 ee d4 ff 05 b0 06 6d cc 5b a8 15 51 e8        "))
# packets.append(bytes.fromhex("  20 18 28 b0 c9 2a 98 6a 96 1b fd 39 06 a7 03 b7 08 a3 02 3d 94 60 b7 58 3f 5a     "))
# packets.append(bytes.fromhex("  09 29 89 04 c9 fd 03 ca 96 60 1a b3 a8 15     "))
# packets.append(bytes.fromhex("  00 10 b3 04 fa 04 d1 04 d1 9b 60 b3 c9 f9 a3     "))
# packets.append(bytes.fromhex("  59 81 60 28 b0 ff 1e c1 76 ee 26 b6 1a 0c af 02 8a 02 86 93 01 bd f4 20 68 82 a8 15 51      "))

#ben packet

packets.append(bytes.fromhex("  2b 51 4a 28 60 c7 2e e6 66 84 1f fb 31 0b d9 01 da ca db 02 e4 02 f6 b4 5b 9a a8 15 51       "))

#654 #3
#packets.append(bytes.fromhex("  48 40 50 a7 16 f4 49 0f a2 03 fa 03 90 06 58 a6 d9 bf 3f bf d8    "))
#this test removed because it reads the long scanline pause as being an event, this is correct functioning
#but just confuses matters for the time being
def arcaneValues(p):
	deltas = []
	leds = []
	count = 0
	i = len(p) - 4	#4bytes of mac leftover from RF encryp, ignore
	i -= 3 #move to start of timestamp
	time = (p[i+2]<<12)|(p[i+1]<<8)|(p[i]<<0)		#note this time can only be used to compare two packets near each other
														#incorperate IMU msb into this to get a more absolute time
	#deltas.append(time)
	#do{ ...}while() dont exist in python :(
	i -= 1
	while(i > (count-1)/2 ):		
		accumilate = 0
		while(True):
			accumilate <<= 7	#shift over
			accumilate |= p[i] & ~(1<<7)	#clear highest bit before accumilate
			
			if(p[i] & 1<<7):
				i-=1
				break	#terminate value when 1 in highest bit
				
			i-=1				
		#deltas.append(accumilate)	#TODO: is this the right way or backwards, should prepend to array?
										#^----- Yes this was backwards,see test line #654 of gist document
		deltas.insert(0,accumilate)
		count +=  1


	while (i >= 0):
		leds.insert(0,p[i])	#append(p[i])
		i -= 1
	return (time,leds,deltas)
		
graph=0
for p in packets:
	graph+=1
	times = [0,] 
	(abstime,leds,deltas)=arcaneValues(p)
	
	accumilate = 0
	for i in range(len(deltas)):
		accumilate += deltas[i]
		times.append(accumilate)
	
	#for multiple packets to align they must be anchored at the last value, ie, the 3 byte timestamp of the packet is the time of the last event
	for i in range(len(times)):
		times[i] += abstime - times[-1]	
	
	print("Time: ",abstime)	
	print("Deltas: ",deltas)
	print("Times: ",times)
	for led in leds: 
		print("LED ", hex(led & ~7),"Flags: ", format(led&7, '03b'))
		
	event = len(times) - 1	#holds postition of the event that is being assigned
	
	activeLeds = []
	
	#for i in range(len(leds)-1,-1,-1):	#main led loops this will loop as long as there are leds that havent been activated yet
	while(event >= 0):
		eventUsed = 0 
		for a in activeLeds:					#check all active leds to see if any have an end transtition to process
			#print("check",event,a)				
			if a["transNum"] == 0:				#this event can be shared, not that it would in practice
				eventUsed = 1
				a["startTime"] = times[event] 
			
			a["transNum"] -= 1	#if 0 -> -1, if not subtract 1 for next loop
		
		#we hit a transtition that has not been accounted for, give it to the next LED
		if(not eventUsed):
			led = leds.pop(0)	#pop the first element from leds array and put it in the active leds array 
			#print("new",event,led)
			newLed = {}
			newLed["endTime"] = times[event]
			newLed["ledNum"] = led & ~7
			newLed["transNum"] = led&7	#lowest three bits
			activeLeds.append(newLed)
		event -= 1
		
	for led in activeLeds:
		print("ViveLEDNumber: " ,led["ledNum"]>>3,"   Start time: ", led["startTime"], "   End time:", led["endTime"],"Width:", led["endTime"]-led["startTime"])#"	transNum(should be negative!): ", led["transNum"]  )
		#plt.subplot(3,1,graph)
		plt.subplot(1,1,1)
		plt.plot([led["startTime"]-1,led["startTime"],led["endTime"],led["endTime"]+1],[0,1,1,0])
		plt.ylim(0, 1.1)
		#plt.xlim(0,3000)
		
	#plt.show()
	print("")
	
plt.show()
@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

@MobiusHorizons @CaiB - I don't think the thing about multiple lights being on at the same time is an uncommon occurrance. Look at all the overlfow'd results in the actual lighthouse data, of 200,000+ ticks. They are marked as "OFLOW"

@danweecc - give me an example where things look like they are happening in a subsequent packet.

@MobiusHorizons: The negative timestamps I think are right because I found the overflow packet showed the thing forward in time, so it was clearly when the thing went dark, not when it went light. I vaguely remember Ben saying something to that effect, at least that the timing things were wrong, and based on this...

I don't know why I'm having such a hard time wrapping my head around the deltas... They can't be the end of time, since ... OH MY GOSH ... I have been reading this example backwards the entire time!

POST 0:   26 (d7d1) - 48 50 48 50 48 fc 01 f2 01 f8 01 ee 01 80 02 ef 01 f9 01 f3 01 fd 01 19 66 d2 d7 07 c8 40 
Events (-674077159): 48/(  252/  242)50/(  248/  238)48/(  256/  239)50/(  249/  243)48/(  253/   -1)
POST 2:    6 (d7d4) - 40 89 15 04 67 d2 b3 ad 71 4e 
Events (-674076924): 40/( 2697/ -1)

If events ever don't line up, it will spit out an error, not OFLOW

OFLOW is strictly caused when everything is parsed fine (all transitions line up) BUT a time comes in that exceeds 65535. There are no natural situations with the lighthouses that will cause an indicator to be on for more than a (8?) thousand ticks, so the 100,000+ ones are clearly something else.

This brings us down to: Is the really big number a code or a bug?

Everyone: We will not use Gist anymore for correspondance in future subprojects, and instead use an issue in the main project, that way all notifications will go as-is. For now, we are stuck with this. Hopefully it will be done soon. Thank you, all for checking back so frequently!

Think about the example lighthouse data with the "OFLOW" stuff. Additionally, I intend to put together a video of this soap opera. I think it'll be really cool! You all will be clearly outlined in the highlights. Can you guys just think through this some more? Any more tests I can run?

@MobiusHorizons

This comment has been minimized.

Copy link

commented Dec 8, 2016

@cnlohr, ok, makes sense. I'll be thinking about it. Let you know when/if I come up with anything.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

@Zmathue I just noticed your post. I will compare what you have to what I currently have in libsurvive.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

@Zmathue... can you run your test against some of the things I just posted (like the real-world lighthouse data) to see if they agree with the unusualalities?

@Zmathue

This comment has been minimized.

Copy link

commented Dec 8, 2016

So I did a test running 8 different packets from the lighthouse data including the OFLOW ones. It appears like those long delta times are not what I thought earlier.

Looking at the lighthouse data it appears that the long deltas always appear in between two signals. ie the long gap is the spacing not the length of a signal. I thought they might be packing older data with newer in the packet but that would lead to their being like 0.1s latency while waiting for the slow half of the packet so its definitely not that.

Time:  358459
Deltas:  [4464, 14598, 5474, 171856, 297, 933, 265]
Times:  [160572, 165036, 179634, 185108, 356964, 357261, 358194, 358459]
LED  0x60 Flags:  000
LED  0xb0 Flags:  000
LED  0x28 Flags:  000
LED  0xb0 Flags:  000
ViveLEDNumber:  0x60    Start time:  358194    End time: 358459         transNum(should be negative!):  -7
ViveLEDNumber:  0xb0    Start time:  356964    End time: 357261         transNum(should be negative!):  -5
ViveLEDNumber:  0x28    Start time:  179634    End time: 185108         transNum(should be negative!):  -3
ViveLEDNumber:  0xb0    Start time:  160572    End time: 165036         transNum(should be negative!):  -1

Note large gap for 0xb0 between the two waves 

Time:  374006
Deltas:  [5959, 13158, 3972, 186619, 217, 90, 74, 347, 356]
Times:  [163214, 169173, 182331, 186303, 372922, 373139, 373229, 373303, 373650,
 374006]
LED  0x28 Flags:  011
LED  0x50 Flags:  001
LED  0x48 Flags:  010
LED  0x28 Flags:  000
LED  0x60 Flags:  000
ViveLEDNumber:  0x28    Start time:  373139    End time: 374006         transNum(should be negative!):  -6
ViveLEDNumber:  0x50    Start time:  373229    End time: 373650         transNum(should be negative!):  -7
ViveLEDNumber:  0x48    Start time:  372922    End time: 373303         transNum(should be negative!):  -5
ViveLEDNumber:  0x28    Start time:  182331    End time: 186303         transNum(should be negative!):  -3
ViveLEDNumber:  0x60    Start time:  163214    End time: 169173         transNum(should be negative!):  -1

Large gap for 0x28 between both waves

Time:  431165
Deltas:  [5449, 13592, 3478, 105725, 423, 1079, 291]
Times:  [301128, 306577, 320169, 323647, 429372, 429795, 430874, 431165]
LED  0x20 Flags:  000
LED  0x18 Flags:  000
LED  0x28 Flags:  000
LED  0xb0 Flags:  000
ViveLEDNumber:  0x20    Start time:  430874    End time: 431165         transNum(should be negative!):  -7
ViveLEDNumber:  0x18    Start time:  429372    End time: 429795         transNum(should be negative!):  -5
ViveLEDNumber:  0x28    Start time:  320169    End time: 323647         transNum(should be negative!):  -3
ViveLEDNumber:  0xb0    Start time:  301128    End time: 306577         transNum(should be negative!):  -1

Time:  434420
Deltas:  [3967, 15169, 4974, 199990, 303, 266, 6, 147, 61]
Times:  [209537, 213504, 228673, 233647, 433637, 433940, 434206, 434212, 434359,
 434420]
LED  0x58 Flags:  001
LED  0x80 Flags:  001
LED  0x60 Flags:  000
LED  0x28 Flags:  000
LED  0xb0 Flags:  000
ViveLEDNumber:  0x58    Start time:  434212    End time: 434420         transNum(should be negative!):  -8
ViveLEDNumber:  0x80    Start time:  434206    End time: 434359         transNum(should be negative!):  -7
ViveLEDNumber:  0x60    Start time:  433637    End time: 433940         transNum(should be negative!):  -5
ViveLEDNumber:  0x28    Start time:  228673    End time: 233647         transNum(should be negative!):  -3
ViveLEDNumber:  0xb0    Start time:  209537    End time: 213504         transNum(should be negative!):  -1

Here is a graph of the lighthouse data
figure_1
both axis are linear

@danweecc

This comment has been minimized.

Copy link

commented Dec 8, 2016

@cnlohr - you posted the following output above:-

DO_MARKER(20, LED50|LED48);
DO_MARKER(20, LED48);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED40);
DO_MARKER(20, LED40|LED48);
DO_MARKER(20, LED48);

POST 0:   26 (9ee9) - 48 48 48 49 51 db 02 a0 02 e1 04 cd 02 ae 02 ce 02 ad 02 cf 02 ad 02 c3 4d e9 9b 0f 3a e8 
POST 0:   11 (9ee9) - 49 41 be 13 aa 02 bf 02 7b 51 e9 2d c8 8f 11

LED50 |---+---|
LED48 |---+---+---+---+---+---|       |---+---|       |---+---|       |---+---|       |---+---+---+---| <-- appears in next packet
LED40                 |---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---| <-- appears in next packet

If we follow the encoding rules that we have derived so far, the LED header for this pulse configuration should read:-

49 40|8 48 48 48 4a 50

Note that LED50 is encoded as 51 probably because of timing jitter. It could easily be 50 or 51 in this case. If it came in as 50, the you would have 4b preceding it due to the way the final edge overlaps.

I wrote 40|8 because there are 8-transitions within the LED40 pulse, which is more than the system can handle. Nevertheless, instead of getting this string, we have it broken up into two separate packets as you posted:-

48 48 48 49 51
49 41

What seems to be happening here is that the LED40 pulse is completely encoded in the second packet and is completely ignored in the first packet. This is the reason why you have 49 51 in the first packet instead of 4a 51 - because it does not count the LED40's rising edge.

I did not check this but I'd guess that if you looked at the actual timestamp and added the respective deltas, you'd find that the LED40 from the second packet overlaps the first packet.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

Ok... Ben just kinda gave us the ranch...

2b 51 4a 28 60 c7 2e e6 66 84 1f fb 31 0b d9 01 da ca db 02 e4 02 f6 b4 5b 9a a8 15 51 

decodes to:

id 12 start 5799310 width 5959
id 5 start 5818427 width 3972
id 9 start 6009018 width 381
id 10 start 6009325 width 421
id 5 start 6009235 width 867

according to him.

Meanwhile, I decode it as:

Light Event: LED 10 @ -1470385683, len 421  (6009325 = -1470385683)
Light Event: LED 5 @ -1470385773, len 867 (6009235 =  -1470385773)
OFLOW: LED 5 @ -1470572609, len 186619 (5822399 = -1470572609)
OFLOW: LED 9 @ -1470572609, len 186926
Light Event: LED 12 @ -1470589739, len 13158 (5805269 = -1470589739)

Any of you guys mind seeing if your stuff decodes to the same as Ben's...?

@Zmathue

This comment has been minimized.

Copy link

commented Dec 8, 2016

I got the same thing as him, the start times are offset because I didn't include the imu in the time calc but the rest is right (the start times are all offset by the same value). I updated the code in the post above to have the same IDs as bens

C:\Users\Zack\Documents\Vive>python vive.py
Time:  374006
Deltas:  [5959, 13158, 3972, 186619, 217, 90, 74, 347, 356]
Times:  [163214, 169173, 182331, 186303, 372922, 373139, 373229, 373303, 373650,
 374006]
LED  0x28 Flags:  011
LED  0x50 Flags:  001
LED  0x48 Flags:  010
LED  0x28 Flags:  000
LED  0x60 Flags:  000
ViveLEDNumber:  5    Start time:  373139    End time: 374006 Width: 867
ViveLEDNumber:  10    Start time:  373229    End time: 373650 Width: 421
ViveLEDNumber:  9    Start time:  372922    End time: 373303 Width: 381
ViveLEDNumber:  5    Start time:  182331    End time: 186303 Width: 3972
ViveLEDNumber:  12    Start time:  163214    End time: 169173 Width: 5959
@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 8, 2016

So, I lost this challenge, who would we say won first? P.S. I still need to make a good implementation. The one currently in libsurvive is kinda broken and awful.

@CaiB

This comment has been minimized.

Copy link

commented Dec 8, 2016

@cnlohr I mean, that's a really difficult thing to determine... While I was the first to determine what LED LSBs mean, and I had a most-of-the-way-there idea of how the timing worked, we wouldn't have a solution without the other awesome people here.

So I guess the answer is the general tacky one: The open source community wins :P

@Zmathue

This comment has been minimized.

Copy link

commented Dec 8, 2016

@danweecc the 0x51 is whats been confusing me it seems more like some kind of bug than intended operation as it should be able to handle that case fine. And yeah for the case of multiple packets they are aligned by assigning the last timing (the sum of all the deltas) to the absolute timing (from 3bytes timestamp)

I still am curious how it handles the edge case of having overlapping data. I imagine if it has two overlapping falling edges it will break into two separate packets, same with a rising edge and a falling. It should be able to handle two coinciding rising edges in a packet but I haven't seen that yet.

@cnlohr is there any way you can test this input for me? and yeah I understand the avr probably won't be able to turn them on a exactly the same time, but I wouldn't mind seeing how close it can get

DO_MARKER(30, LED48);
DO_MARKER(20, LED48|LED40|LED50);
DO_MARKER(20, LED48|LED40);
DO_MARKER(30, LED48);
DO_MARKER(20, LED48|LED40);
DO_MARKER(20, LED48|LED50);
DO_MARKER(30, LED48);
DO_MARKER(20, LED48|LED40);
DO_MARKER(20, LED48|LED40|LED50);
DO_MARKER(30, LED48);

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2016

Hmm, this seems very odd... This is what I get.

POST 0:   25 (0b25) - 50 40 42 50 48 c0 1d cc 68 31 81 bd 02 b8 02 d3 03 c5 02 86 bc 02 f7 79 26 c1 01 0f 00 
10 0 0 316
Light Event: LED 10 @ 187070651, len 316
8 0 6 325
Light Event: LED 8 @ 187070645, len 6
8 2 467 312
10 0 317 1
Light Event: LED 8 @ 187069224, len 1096
Light Event: LED 10 @ 187069224, len 317
9 0 816204 3776
OFLOW: LED 9 @ 186253019, len 816204
POST 2:   10 (0b28) - 51 41 bd 02 b6 02 87 4c 7e 26 70 81 01 0f 
10 1 0 7
8 1 310 317
Light Event: LED 10 @ 187071759, len 317
Light Event: LED 8 @ 187071442, len 627
POST 0:   25 (0b31) - 50 40 42 50 48 bf 1d e0 64 31 81 bd 02 ba 02 d2 03 c6 02 87 bc 02 3f f9 32 b0 01 0f 00 
10 0 0 316
Light Event: LED 10 @ 187889667, len 316
8 0 7 326
Light Event: LED 8 @ 187889660, len 7
8 2 466 314
10 0 317 1
Light Event: LED 8 @ 187888237, len 1097
Light Event: LED 10 @ 187888237, len 317
9 0 815712 3775
OFLOW: LED 9 @ 187072524, len 815712
POST 2:   10 (0b34) - 51 41 be 02 b6 02 87 95 fd 32 e2 4d 01 0f 
@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2016

Ok, this is weird, a little bit later (and updated algorithm), it gives me this:

POST 0:   10 (8b05) - 51 41 bc 02 b5 02 89 6d b6 05 65 42 73 7e 
8: 625 [373747]
10: 318 [374063]
POST 0:   25 (8b11) - 50 40 41 51 48 d3 1d e0 76 31 82 bb 02 b6 02 d9 03 c1 02 8a bc 02 6a 3a 12 53 88 0f b0 
9: 3795 [371044]
10: 317 [1192855]
8: 625 [1192857]
8: 321 [1193955]
10: 316 [1194286]
POST 0:   10 (8b11) - 51 41 bc 02 b4 02 89 c2 3e 12 54 3b 5f 45 
8: 624 [1195081]
10: 317 [1195397]
POST 0:   25 (8b1d) - 50 40 41 51 48 d1 1d ff 6e 31 81 bc 02 b6 02 d8 03 c1 02 8a bc 02 de be 1e 06 88 0f b0 
9: 3793 [1192380]
10: 317 [2013196]
8: 626 [2013197]
8: 321 [2014295]
10: 316 [2014626]
@Zmathue

This comment has been minimized.

Copy link

commented Dec 9, 2016

yeah it was very odd seeing a negative number show up as the delta is actually larger than the time stamp. The width all pulses are exactly as expected (even id:9 which is way off at an earlier time).

and its only the one (id:9) that is so far delayed. I don't know if this is because it is in queue somewhere that is just backed up or if something else is going on.

1

the ones on the left are all id:9

2
this is a closer look at the ones on the right which look very good.

@cnlohr the new algorithm looks good, exactly what I got

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2016

Ben says: "Kind of. We coalesce syncs because there are a lot of them (they hit all the sensors) so it conserves bandwidth. The syncs themselves aren't directly used to track, so we can wait for the actual hits to come to flush them out."

@Zmathue

This comment has been minimized.

Copy link

commented Dec 9, 2016

okay that makes perfect sense, that's why the large offsets are only when you leave an led on for a long time, it passes the threshold where a pulse is no longer considered a hit and is now considered part of the sync flash.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2016

That is a little annoying from my side, as I average the sync flashes among all of the hit pulses on the headset, but I guess the headset matters more than the controllers.

@danweecc

This comment has been minimized.

Copy link

commented Dec 9, 2016

@Zmathue - the 51 or 50 is really easy to understand if you think in terms of an analog system with a lot of jitter. The rising edges of LED50 and LED48 happen at virtually the same moment but they are detected with some jitter. This means that in practice, LED50 could rise just a hair faster or slower than LED48, and depending on which one - there might be an extra edge-transition in the faster LED and one less in the slower LED.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2016

I have noticed sometimes delta is actually 0. But, when it is, everything /still/ works since you still individually use the edges.

@danweecc

This comment has been minimized.

Copy link

commented Dec 10, 2016

@cnlohr - maybe the 0-delta corresponds to a simultaneous edge.

@cnlohr

This comment has been minimized.

Copy link
Owner Author

commented Dec 10, 2016

that's my feelings exactly. They happen when I purposefully make edges as simultaneous as I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.