From 35e08aaa24bd01e6ace453f89ddb73a6bb0508b0 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 14 Feb 2017 01:00:33 -0500 Subject: Still not working, but getting closer to dynamic OOTX decoding. --- src/ootx_decoder.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/ootx_decoder.c (limited to 'src/ootx_decoder.c') diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c new file mode 100644 index 0000000..b8746bc --- /dev/null +++ b/src/ootx_decoder.c @@ -0,0 +1,163 @@ +// (C) 2016 Joshua Allen, MIT/x11 License. +// +//All MIT/x11 Licensed Code in this file may be relicensed freely under the GPL or LGPL licenses. + +/* ootx data decoder */ + +#include +#include +#include +#include +#include "ootx_decoder.h" +#include + +//char* fmt_str = "L Y HMD %d 5 1 206230 %d\n"; + + +void (*ootx_packet_clbk)(ootx_decoder_context *ctx, ootx_packet* packet) = NULL; + +void ootx_init_decoder_context(ootx_decoder_context *ctx) { + ctx->buf_offset = 0; + ctx->bits_written = 0; + + ctx->preamble = 0XFFFFFFFF; + ctx->bits_processed = 0; + ctx->found_preamble = 0; + + memset( ctx->buffer, 0, sizeof( ctx->buffer ) ); + ctx->payload_size = (uint16_t*)ctx->buffer; + *(ctx->payload_size) = 0; +} +/* +void ootx_init_buffer() { + buffer = (uint8_t*)malloc(MAX_BUFF_SIZE); + payload_size = (uint16_t*)buffer; + *payload_size = 0; +} +*/ + +/* + how to decode pulses + ticks>2000 && delta>100000== master lighthouse + ticks>2000 && delta>10000 == slave lighthouse +*/ + +int8_t ootx_decode_lighthouse_number(uint8_t last_num, uint32_t ticks, int32_t delta) { + if (ticks<2000) return -1; //sweep + if ((ticks > 2000) & (delta>100000)) return 0; //master + if ((ticks > 2000) & (delta>10000)) return last_num+1; //a slave + return -1; +} + +/* +uint8_t ootx_decode_bit(uint32_t ticks) { + ticks = ((ticks/500)*500)+500; + + ticks-=3000; + if (ticks>=2000) { ticks-=2000; } + if (ticks>=1000) { return 0xFF; } + + return 0x00; +}*/ + +uint8_t ootx_detect_preamble(ootx_decoder_context *ctx, uint8_t dbit) { + ctx->preamble <<= 1; + ctx->preamble |= (0x01 & dbit); + if ((ctx->preamble & 0x0001ffff) == 0x01) return 1; + return 0; +} + +void ootx_reset_buffer(ootx_decoder_context *ctx) { + ctx->buf_offset = 0; + ctx->buffer[ctx->buf_offset] = 0; + ctx->bits_written = 0; + *(ctx->payload_size) = 0; +} + +void ootx_inc_buffer_offset(ootx_decoder_context *ctx) { + ++(ctx->buf_offset); + +// assert(ctx->buf_offsetbuf_offset>=MAX_OOTX_BUFF_SIZE) { + ctx->buf_offset = 0; + ctx->found_preamble = 0; + } + + ctx->buffer[ctx->buf_offset] = 0; +} + +void ootx_write_to_buffer(ootx_decoder_context *ctx, uint8_t dbit) { + uint8_t *current_byte = ctx->buffer + ctx->buf_offset; +// printf("%d\n", dbit); + *current_byte >>= 1; + *current_byte |= (0x80 & dbit); + ++(ctx->bits_written); + if (ctx->bits_written>7) { + ctx->bits_written=0; +// printf("%d\n", *current_byte); + ootx_inc_buffer_offset(ctx); + } +} + +void ootx_process_bit(ootx_decoder_context *ctx, uint8_t dbit) { + //uint8_t dbit = ootx_decode_bit(length); + ++(ctx->bits_processed); + +// printf("z %d %d\n", bits_processed,dbit); +// printf("d %d\n", bits_processed,dbit); + + if ( ootx_detect_preamble(ctx, dbit) ) { + /* data stream can start over at any time so we must + always look for preamble bits */ + printf("Preamble found\n"); + ootx_reset_buffer(ctx); + ctx->bits_processed = 0; + ctx->found_preamble = 1; + } + else if(ctx->bits_processed>16) { + //every 17th bit needs to be dropped (sync bit) +// printf("drop %d\n", dbit); + if( !dbit ) + { + printf( "Sync bit missing\n" ); + ootx_reset_buffer(ctx); + } + ctx->bits_processed = 0; + } + else if (ctx->found_preamble > 0) + { + /* only write to buffer if the preamble is found. + if the buffer overflows, found_preamble will be cleared + and writing will stop. data would be corrupted, so there is no point in continuing + */ + + ootx_write_to_buffer(ctx, dbit); +printf( "%d / %d -> ", ctx->buf_offset, *ctx->payload_size ); +int k; +for( k = 0; k < 32; k++ ) +{ + printf( "%02x ", ctx->buffer[k] ); +} +printf( "\n" ); + if (ctx->buf_offset >= (*(ctx->payload_size)+6)) { + /* once we have a complete ootx packet, send it out in the callback */ + ootx_packet op; + + op.length = *(ctx->payload_size); + op.data = ctx->buffer+2; + op.crc32 = *(uint32_t*)(ctx->buffer+2+op.length); + + uint32_t crc = crc32(0xffffffff,op.data,op.length); + + if (crc != op.crc32) { + printf("CRC mismatch\n"); + } + + if ((crc == op.crc32) && ootx_packet_clbk) ootx_packet_clbk(ctx, &op); + + ootx_reset_buffer(ctx); + } + } +} -- cgit v1.2.3 From 119a205619632076c7b258eaa6c28dd7bcd2c294 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 14 Feb 2017 10:03:18 -0500 Subject: integrate josh's new work. It works! #19 is just about solved! --- src/ootx_decoder.c | 213 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 153 insertions(+), 60 deletions(-) (limited to 'src/ootx_decoder.c') diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c index b8746bc..b1815d7 100644 --- a/src/ootx_decoder.c +++ b/src/ootx_decoder.c @@ -1,4 +1,4 @@ -// (C) 2016 Joshua Allen, MIT/x11 License. +// (C) 2017 Joshua Allen, MIT/x11 License. // //All MIT/x11 Licensed Code in this file may be relicensed freely under the GPL or LGPL licenses. @@ -6,15 +6,19 @@ #include #include -#include +#include #include #include "ootx_decoder.h" -#include +//#include "crc32.h" //char* fmt_str = "L Y HMD %d 5 1 206230 %d\n"; +#define MAX_BUFF_SIZE 64 -void (*ootx_packet_clbk)(ootx_decoder_context *ctx, ootx_packet* packet) = NULL; +void (*ootx_packet_clbk)(ootx_decoder_context * ctx, ootx_packet* packet) = NULL; +void (*ootx_bad_crc_clbk)(ootx_decoder_context * ctx, ootx_packet* packet, uint32_t crc) = NULL; + +void ootx_pump_bit(ootx_decoder_context *ctx, uint8_t dbit); void ootx_init_decoder_context(ootx_decoder_context *ctx) { ctx->buf_offset = 0; @@ -24,46 +28,28 @@ void ootx_init_decoder_context(ootx_decoder_context *ctx) { ctx->bits_processed = 0; ctx->found_preamble = 0; - memset( ctx->buffer, 0, sizeof( ctx->buffer ) ); + ctx->buffer = (uint8_t*)malloc(MAX_BUFF_SIZE); ctx->payload_size = (uint16_t*)ctx->buffer; *(ctx->payload_size) = 0; } -/* -void ootx_init_buffer() { - buffer = (uint8_t*)malloc(MAX_BUFF_SIZE); - payload_size = (uint16_t*)buffer; - *payload_size = 0; -} -*/ - -/* - how to decode pulses - ticks>2000 && delta>100000== master lighthouse - ticks>2000 && delta>10000 == slave lighthouse -*/ - -int8_t ootx_decode_lighthouse_number(uint8_t last_num, uint32_t ticks, int32_t delta) { - if (ticks<2000) return -1; //sweep - if ((ticks > 2000) & (delta>100000)) return 0; //master - if ((ticks > 2000) & (delta>10000)) return last_num+1; //a slave - return -1; -} -/* -uint8_t ootx_decode_bit(uint32_t ticks) { - ticks = ((ticks/500)*500)+500; - - ticks-=3000; - if (ticks>=2000) { ticks-=2000; } - if (ticks>=1000) { return 0xFF; } +void ootx_free_decoder_context(ootx_decoder_context *ctx) { + free(ctx->buffer); + ctx->buffer = NULL; + ctx->payload_size = NULL; +} - return 0x00; -}*/ +uint8_t ootx_decode_bit(uint32_t length) { + uint8_t t = (length - 2750) / 500; //why 2750? +// return ((t & 0x02)>0)?0xFF:0x00; //easier if we need to bitshift right + return ((t & 0x02)>>1); +} uint8_t ootx_detect_preamble(ootx_decoder_context *ctx, uint8_t dbit) { ctx->preamble <<= 1; - ctx->preamble |= (0x01 & dbit); - if ((ctx->preamble & 0x0001ffff) == 0x01) return 1; +// ctx->preamble |= (0x01 & dbit); + ctx->preamble |= dbit; + if ((ctx->preamble & 0x0003ffff) == 0x00000001) return 1; return 0; } @@ -80,7 +66,7 @@ void ootx_inc_buffer_offset(ootx_decoder_context *ctx) { // assert(ctx->buf_offsetbuf_offset>=MAX_OOTX_BUFF_SIZE) { + if(ctx->buf_offset>=MAX_BUFF_SIZE) { ctx->buf_offset = 0; ctx->found_preamble = 0; } @@ -90,9 +76,11 @@ void ootx_inc_buffer_offset(ootx_decoder_context *ctx) { void ootx_write_to_buffer(ootx_decoder_context *ctx, uint8_t dbit) { uint8_t *current_byte = ctx->buffer + ctx->buf_offset; -// printf("%d\n", dbit); - *current_byte >>= 1; - *current_byte |= (0x80 & dbit); + + *current_byte <<= 1; +// *current_byte |= (0x01 & dbit); + *current_byte |= dbit; + ++(ctx->bits_written); if (ctx->bits_written>7) { ctx->bits_written=0; @@ -101,17 +89,20 @@ void ootx_write_to_buffer(ootx_decoder_context *ctx, uint8_t dbit) { } } -void ootx_process_bit(ootx_decoder_context *ctx, uint8_t dbit) { - //uint8_t dbit = ootx_decode_bit(length); - ++(ctx->bits_processed); +uint8_t ootx_process_bit(ootx_decoder_context *ctx, uint32_t length) { + uint8_t dbit = ootx_decode_bit(length); + ootx_pump_bit( ctx, dbit ); + return dbit; +} -// printf("z %d %d\n", bits_processed,dbit); -// printf("d %d\n", bits_processed,dbit); +void ootx_pump_bit(ootx_decoder_context *ctx, uint8_t dbit) { +// uint8_t dbit = ootx_decode_bit(length); + ++(ctx->bits_processed); if ( ootx_detect_preamble(ctx, dbit) ) { /* data stream can start over at any time so we must always look for preamble bits */ - printf("Preamble found\n"); + //printf("Preamble found\n"); ootx_reset_buffer(ctx); ctx->bits_processed = 0; ctx->found_preamble = 1; @@ -121,7 +112,7 @@ void ootx_process_bit(ootx_decoder_context *ctx, uint8_t dbit) { // printf("drop %d\n", dbit); if( !dbit ) { - printf( "Sync bit missing\n" ); + printf("Bad sync bit\n"); ootx_reset_buffer(ctx); } ctx->bits_processed = 0; @@ -134,30 +125,132 @@ void ootx_process_bit(ootx_decoder_context *ctx, uint8_t dbit) { */ ootx_write_to_buffer(ctx, dbit); -printf( "%d / %d -> ", ctx->buf_offset, *ctx->payload_size ); -int k; -for( k = 0; k < 32; k++ ) -{ - printf( "%02x ", ctx->buffer[k] ); -} -printf( "\n" ); - if (ctx->buf_offset >= (*(ctx->payload_size)+6)) { + + uint16_t padded_length = *(ctx->payload_size); + padded_length += (padded_length&0x01); //extra null byte if odd + +/* int k; + printf( ":" ); + for( k = 0; k < 36; k++ ) + { + printf( "%02x ", ctx->buffer[k] ); + } + printf( "\n" );*/ + + if (ctx->buf_offset >= (padded_length+6)) { /* once we have a complete ootx packet, send it out in the callback */ ootx_packet op; op.length = *(ctx->payload_size); op.data = ctx->buffer+2; - op.crc32 = *(uint32_t*)(ctx->buffer+2+op.length); + op.crc32 = *(uint32_t*)(op.data+padded_length); - uint32_t crc = crc32(0xffffffff,op.data,op.length); + uint32_t crc = crc32( 0L, Z_NULL, 0 ); + crc = crc32( crc, op.data,op.length); if (crc != op.crc32) { - printf("CRC mismatch\n"); + if (ootx_bad_crc_clbk != NULL) ootx_bad_crc_clbk(ctx, &op,crc); + } + else if (ootx_packet_clbk != NULL) { + ootx_packet_clbk(ctx,&op); } - - if ((crc == op.crc32) && ootx_packet_clbk) ootx_packet_clbk(ctx, &op); ootx_reset_buffer(ctx); } } } + +uint8_t* get_ptr(uint8_t* data, uint8_t bytes, uint16_t* idx) { + uint8_t* x = data + *idx; + *idx += bytes; + return x; +} + +float _half_to_float(uint8_t* data) { + //this will not handle infinity, NaN, or denormalized floats + + uint16_t x = *(uint16_t*)data; + float f = 0; + + uint32_t *ftmp = (uint32_t*)&f; //use the allocated floating point memory + + if ((x & 0x7FFF) == 0) return f; //zero + + //sign + *ftmp = x & 0x8000; + *ftmp <<= 16; + + *ftmp += ((((uint32_t)(x & 0x7fff)) + 0x1c000) << 13); + + return f; +} + +void init_lighthouse_info_v6(lighthouse_info_v6* lhi, uint8_t* data) { + uint16_t idx = 0; + /* + uint16_t fw_version;//Firmware version (bit 15..6), protocol version (bit 5..0) + uint32_t id; //Unique identifier of the base station + float fcal_0_phase; //"phase" for rotor 0 + float fcal_1_phase; //"phase" for rotor 1 + float fcal_0_tilt; //"tilt" for rotor 0 + float fcal_1_tilt; //"tilt" for rotor 1 + uint8_t sys_unlock_count; //Lowest 8 bits of the rotor desynchronization counter + uint8_t hw_version; //Hardware version + float fcal_0_curve; //"curve" for rotor 0 + float fcal_1_curve; //"curve" for rotor 1 + int8_t accel_dir_x; //"orientation vector" + int8_t accel_dir_y; //"orientation vector" + int8_t accel_dir_z; //"orientation vector" + float fcal_0_gibphase; //"gibbous phase" for rotor 0 (normalized angle) + float fcal_1_gibphase; //"gibbous phase" for rotor 1 (normalized angle) + float fcal_0_gibmag; //"gibbous magnitude" for rotor 0 + float fcal_1_gibmag; //"gibbous magnitude" for rotor 1 + uint8_t mode_current; //Currently selected mode (default: 0=A, 1=B, 2=C) + uint8_t sys_faults; //"fault detect flags" (should be 0) + */ + + lhi->fw_version = *(uint16_t*)get_ptr(data,sizeof(uint16_t),&idx); + lhi->id = *(uint32_t*)get_ptr(data,sizeof(uint32_t),&idx); + lhi->fcal_0_phase = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_1_phase = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_0_tilt = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_1_tilt = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->sys_unlock_count = *get_ptr(data,sizeof(uint8_t),&idx); + lhi->hw_version = *get_ptr(data,sizeof(uint8_t),&idx); + lhi->fcal_0_curve = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_1_curve = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->accel_dir_x = *(int8_t*)get_ptr(data,sizeof(uint8_t),&idx); + lhi->accel_dir_y = *(int8_t*)get_ptr(data,sizeof(uint8_t),&idx); + lhi->accel_dir_z = *(int8_t*)get_ptr(data,sizeof(uint8_t),&idx); + lhi->fcal_0_gibphase = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_1_gibphase = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_0_gibmag = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->fcal_1_gibmag = _half_to_float( get_ptr(data,sizeof(uint16_t),&idx) ); + lhi->mode_current = *get_ptr(data,sizeof(uint8_t),&idx); + lhi->sys_faults = *get_ptr(data,sizeof(uint8_t),&idx); + +} + +void print_lighthouse_info_v6(lighthouse_info_v6* lhi) { + + printf("\t%X\n\t%X\n\t%f\n\t%f\n\t%f\n\t%f\n\t%d\n\t%d\n\t%f\n\t%f\n\t%d\n\t%d\n\t%d\n\t%f\n\t%f\n\t%f\n\t%f\n\t%d\n\t%d\n", + lhi->fw_version, + lhi->id, + lhi->fcal_0_phase, + lhi->fcal_1_phase, + lhi->fcal_0_tilt, + lhi->fcal_1_tilt, + lhi->sys_unlock_count, + lhi->hw_version, + lhi->fcal_0_curve, + lhi->fcal_1_curve, + lhi->accel_dir_x, + lhi->accel_dir_y, + lhi->accel_dir_z, + lhi->fcal_0_gibphase, + lhi->fcal_1_gibphase, + lhi->fcal_0_gibmag, + lhi->fcal_1_gibmag, + lhi->mode_current, + lhi->sys_faults); +} -- cgit v1.2.3 From f736678ae0df00f7b5850043d9327da44b068c47 Mon Sep 17 00:00:00 2001 From: Josh Allen Date: Tue, 14 Feb 2017 21:26:26 -0500 Subject: use 0 and not buffer offset --- src/ootx_decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ootx_decoder.c') diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c index b1815d7..894012a 100644 --- a/src/ootx_decoder.c +++ b/src/ootx_decoder.c @@ -55,7 +55,7 @@ uint8_t ootx_detect_preamble(ootx_decoder_context *ctx, uint8_t dbit) { void ootx_reset_buffer(ootx_decoder_context *ctx) { ctx->buf_offset = 0; - ctx->buffer[ctx->buf_offset] = 0; + ctx->buffer[0] = 0; ctx->bits_written = 0; *(ctx->payload_size) = 0; } -- cgit v1.2.3 From a35428f2125279252c26a645f9ee8f0818b3204c Mon Sep 17 00:00:00 2001 From: Josh Allen Date: Tue, 14 Feb 2017 22:03:36 -0500 Subject: handle infinity and NaN, also signed zero --- src/ootx_decoder.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/ootx_decoder.c') diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c index 894012a..3823beb 100644 --- a/src/ootx_decoder.c +++ b/src/ootx_decoder.c @@ -167,20 +167,27 @@ uint8_t* get_ptr(uint8_t* data, uint8_t bytes, uint16_t* idx) { } float _half_to_float(uint8_t* data) { - //this will not handle infinity, NaN, or denormalized floats + //this will not handle denormalized floats uint16_t x = *(uint16_t*)data; float f = 0; uint32_t *ftmp = (uint32_t*)&f; //use the allocated floating point memory - if ((x & 0x7FFF) == 0) return f; //zero - //sign *ftmp = x & 0x8000; *ftmp <<= 16; - *ftmp += ((((uint32_t)(x & 0x7fff)) + 0x1c000) << 13); + if ((x & 0x7FFF) == 0) return f; //signed zero + + if((x&0x7c00) == 0x7c00) { + //for infinity, fraction is 0 (just copy in 0 bits) + //for NaN, fraction is anything non zero (copy in bits, no need to shift) + *ftmp |= 0x7f800000 | (x & 0x3ff); + return f; + } + + *ftmp += ((((uint32_t)(x & 0x7fff)) + 0x1c000u) << 13); return f; } -- cgit v1.2.3 From cbbf33778e288856e48f7bcd23b1b1a8c2707d59 Mon Sep 17 00:00:00 2001 From: Josh Allen Date: Thu, 16 Feb 2017 06:23:12 -0500 Subject: full implementation of half float to single float --- src/ootx_decoder.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'src/ootx_decoder.c') diff --git a/src/ootx_decoder.c b/src/ootx_decoder.c index 3823beb..8ec16f2 100644 --- a/src/ootx_decoder.c +++ b/src/ootx_decoder.c @@ -166,30 +166,54 @@ uint8_t* get_ptr(uint8_t* data, uint8_t bytes, uint16_t* idx) { return x; } -float _half_to_float(uint8_t* data) { - //this will not handle denormalized floats +/* simply doing: +float f = 0; +uint32_t *ftmp = (uint32_t*)&f; //use the allocated floating point memory +This can cause problem when strict aliasing (-O2) is used. +Reads and writes to f and ftmp would be considered independent and could be +be reordered by the compiler. A union solves that problem. +*/ +union iFloat { + uint32_t i; + float f; +}; +float _half_to_float(uint8_t* data) { uint16_t x = *(uint16_t*)data; - float f = 0; - - uint32_t *ftmp = (uint32_t*)&f; //use the allocated floating point memory + union iFloat fnum; + fnum.f = 0; //sign - *ftmp = x & 0x8000; - *ftmp <<= 16; - - if ((x & 0x7FFF) == 0) return f; //signed zero + fnum.i = (x & 0x8000)<<16; + + if ((x & 0x7FFF) == 0) return fnum.f; //signed zero + + if ((x & 0x7c00) == 0) { + //denormalized + x = (x&0x3ff)<<1; //only mantissa, advance intrinsic bit forward + uint8_t e = 0; + //shift until intrinsic bit of mantissa overflows into exponent + //increment exponent each time + while ((x&0x0400) == 0) { + x<<=1; + e++; + } + fnum.i |= ((uint32_t)(112-e))<<23; //bias exponent to 127, half floats are biased 15 so only need to go 112 more. + fnum.i |= ((uint32_t)(x&0x3ff))<<13; //insert mantissa + return fnum.f; + } if((x&0x7c00) == 0x7c00) { - //for infinity, fraction is 0 (just copy in 0 bits) - //for NaN, fraction is anything non zero (copy in bits, no need to shift) - *ftmp |= 0x7f800000 | (x & 0x3ff); - return f; + //for infinity, fraction is 0 + //for NaN, fraction is anything non zero + //we could just copy in bits and not shift, but the mantissa of a NaN can have meaning + fnum.i |= 0x7f800000 | ((uint32_t)(x & 0x3ff))<<13; + return fnum.f; } - *ftmp += ((((uint32_t)(x & 0x7fff)) + 0x1c000u) << 13); + fnum.i |= ((((uint32_t)(x & 0x7fff)) + 0x1c000u) << 13); - return f; + return fnum.f; } void init_lighthouse_info_v6(lighthouse_info_v6* lhi, uint8_t* data) { -- cgit v1.2.3