Now we have a working serial_line_decoder_f_u8.
This commit is contained in:
parent
380bfded2c
commit
d79807a67c
3 changed files with 51 additions and 63 deletions
15
csdr.c
15
csdr.c
|
@ -1921,7 +1921,6 @@ int main(int argc, char *argv[])
|
||||||
sscanf(argv[2],"%f",&serial.samples_per_bits);
|
sscanf(argv[2],"%f",&serial.samples_per_bits);
|
||||||
if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1.");
|
if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1.");
|
||||||
if(serial.samples_per_bits<5) fprintf(stderr, "serial_line_decoder_sy_u8: warning: this algorithm does not work well if samples_per_bits is too low. It should be at least 5.\n");
|
if(serial.samples_per_bits<5) fprintf(stderr, "serial_line_decoder_sy_u8: warning: this algorithm does not work well if samples_per_bits is too low. It should be at least 5.\n");
|
||||||
serial.actual_samples_per_bits = serial.samples_per_bits;
|
|
||||||
|
|
||||||
serial.databits=8;
|
serial.databits=8;
|
||||||
if(argc>3) sscanf(argv[3],"%d",&serial.databits);
|
if(argc>3) sscanf(argv[3],"%d",&serial.databits);
|
||||||
|
@ -1931,8 +1930,7 @@ int main(int argc, char *argv[])
|
||||||
if(argc>4) sscanf(argv[4],"%f",&serial.stopbits);
|
if(argc>4) sscanf(argv[4],"%f",&serial.stopbits);
|
||||||
if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1.");
|
if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1.");
|
||||||
|
|
||||||
serial.samples_per_bits_max_deviation_rate=0.001;
|
serial.bit_sampling_width_ratio = 0.4;
|
||||||
serial.samples_per_bits_loop_gain=0.05;
|
|
||||||
serial.input_used=0;
|
serial.input_used=0;
|
||||||
|
|
||||||
if(!sendbufsize(initialize_buffers())) return -2;
|
if(!sendbufsize(initialize_buffers())) return -2;
|
||||||
|
@ -1942,13 +1940,16 @@ int main(int argc, char *argv[])
|
||||||
FEOF_CHECK;
|
FEOF_CHECK;
|
||||||
if(serial.input_used)
|
if(serial.input_used)
|
||||||
{
|
{
|
||||||
memmove(input_buffer, input_buffer+serial.input_used, the_bufsize-serial.input_used);
|
memmove(input_buffer, input_buffer+serial.input_used, sizeof(float)*(the_bufsize-serial.input_used));
|
||||||
fread(input_buffer+(the_bufsize-serial.input_used), sizeof(unsigned char), serial.input_used, stdin);
|
fread(input_buffer+(the_bufsize-serial.input_used), sizeof(float), serial.input_used, stdin);
|
||||||
}
|
}
|
||||||
else fread(input_buffer, sizeof(unsigned char), the_bufsize, stdin); //should happen only on the first run
|
else fread(input_buffer, sizeof(float), the_bufsize, stdin); //should happen only on the first run
|
||||||
serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize);
|
serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize);
|
||||||
if(serial.input_used==0) { fprintf(stderr, "serial_line_decoder_sy_u8: error: serial_line_decoder() stuck.\n"); return -3; }
|
//printf("now in | ");
|
||||||
|
if(serial.input_used==0) { fprintf(stderr, "serial_line_decoder_sy_u8: error: serial_line_decoder_f_u8() got stuck.\n"); return -3; }
|
||||||
|
//printf("now out %d | ", serial.output_size);
|
||||||
fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout);
|
fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout);
|
||||||
|
fflush(stdout);
|
||||||
TRY_YIELD;
|
TRY_YIELD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
95
libcsdr.c
95
libcsdr.c
|
@ -1256,11 +1256,19 @@ char rtty_baudot_decoder_push(rtty_baudot_decoder_t* s, unsigned char symbol)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEBUG_SERIAL_LINE_DECODER 0
|
||||||
|
|
||||||
|
//What has not been checked:
|
||||||
|
// behaviour on 1.5 stop bits
|
||||||
|
// check all exit conditions
|
||||||
|
|
||||||
void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* output, int input_size)
|
void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* output, int input_size)
|
||||||
{
|
{
|
||||||
|
static int abs_samples_helper = 0;
|
||||||
|
abs_samples_helper += s->input_used;
|
||||||
|
int iabs_samples_helper = abs_samples_helper;
|
||||||
s->output_size = 0;
|
s->output_size = 0;
|
||||||
s->input_used = 0;
|
s->input_used = 0;
|
||||||
int oi=0;
|
|
||||||
short* output_s = (short*)output;
|
short* output_s = (short*)output;
|
||||||
unsigned* output_u = (unsigned*)output;
|
unsigned* output_u = (unsigned*)output;
|
||||||
for(;;)
|
for(;;)
|
||||||
|
@ -1270,76 +1278,57 @@ void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* out
|
||||||
int i;
|
int i;
|
||||||
for(i=1;i<input_size;i++) if(input[i] < 0 && input[i-1] > 0) { startbit_start=i; break; }
|
for(i=1;i<input_size;i++) if(input[i] < 0 && input[i-1] > 0) { startbit_start=i; break; }
|
||||||
|
|
||||||
if(startbit_start == -1) { s->input_used += i; fprintf(stderr,"sld:nstartbit\n"); return; }
|
if(startbit_start == -1) { s->input_used += i; DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_not_found (+%d)\n", s->input_used); return; }
|
||||||
fprintf(stderr,"sld:startbit_found at %d\n", startbit_start);
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:startbit_found at %d (%d)\n", startbit_start, iabs_samples_helper + startbit_start);
|
||||||
//We estimate where the stop bit edge can be, and search for it.
|
|
||||||
int stopbit_end = -1;
|
|
||||||
float all_bits = 1 + s->databits + s->stopbits;
|
|
||||||
float stopbit_end_estimate = startbit_start + s->samples_per_bits * all_bits;
|
|
||||||
float stopbit_end_search_start = stopbit_end_estimate - s->actual_samples_per_bits * 0.4;
|
|
||||||
float stopbit_end_search_end = stopbit_end_estimate + s->actual_samples_per_bits * 0.4;
|
|
||||||
if(stopbit_end_search_end>=input_size) return;
|
|
||||||
fprintf(stderr,"sld:all_bits = %f\n", all_bits);
|
|
||||||
fprintf(stderr,"sld:actual_samples_per_bits = %f\n", s->actual_samples_per_bits);
|
|
||||||
fprintf(stderr,"sld:stopbit_end_search_start = %f\n", stopbit_end_search_start);
|
|
||||||
fprintf(stderr,"sld:stopbit_end_search_end = %f\n", stopbit_end_search_end);
|
|
||||||
|
|
||||||
//If it is too far and we reached the end of the buffer, then we return failed.
|
//If the stop bit would be too far so that we reached the end of the buffer, then we return failed.
|
||||||
//The caller can rearrange the buffer so that the whole character fits into it.
|
//The caller can rearrange the buffer so that the whole character fits into it.
|
||||||
if(stopbit_end_search_end>=input_size)
|
float all_bits = 1 + s->databits + s->stopbits;
|
||||||
for(i=stopbit_end_search_start+1;i<stopbit_end_search_end;i++) if(input[i-1] < 0 && input[i] > 0) { stopbit_end=i; break; }
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:all_bits = %f\n", all_bits);
|
||||||
if(stopbit_end == -1)
|
if(startbit_start + s->samples_per_bits * all_bits >= input_size) { s->input_used += MAX_M(0,startbit_start-2); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_too_far (+%d)\n", s->input_used); return; }
|
||||||
{
|
|
||||||
s->input_used += i+1;
|
|
||||||
if(s->input_used >= input_size)
|
|
||||||
{
|
|
||||||
s->input_used = input_size;
|
|
||||||
fprintf(stderr,"sld:nstopbit input_used out %d\n", s->input_used);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
input += s->input_used;
|
|
||||||
input_size -= s->input_used;
|
|
||||||
fprintf(stderr,"sld:nstopbit remain = %d\n", input_size); continue;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"sld:stopbit_end = %d\n", stopbit_end);
|
|
||||||
|
|
||||||
//If we have the position of the stop bit, we calculate the actual_samples_per_bits:
|
//We do the actual sampling.
|
||||||
float calculated_samples_per_bits = (stopbit_end - startbit_start) / all_bits;
|
|
||||||
float error_samples_per_bits = s->actual_samples_per_bits - calculated_samples_per_bits;
|
|
||||||
s->actual_samples_per_bits = s->actual_samples_per_bits - s->samples_per_bits_loop_gain * error_samples_per_bits;
|
|
||||||
s->actual_samples_per_bits = MIN_M(s->actual_samples_per_bits, (1+s->samples_per_bits_max_deviation_rate) * s->samples_per_bits);
|
|
||||||
s->actual_samples_per_bits = MAX_M(s->actual_samples_per_bits, (1-s->samples_per_bits_max_deviation_rate) * s->samples_per_bits);
|
|
||||||
fprintf(stderr,"sld:calculated_samples_per_bits = %f\n", calculated_samples_per_bits);
|
|
||||||
fprintf(stderr,"sld:error_samples_per_bits = %f\n", error_samples_per_bits);
|
|
||||||
|
|
||||||
fprintf(stderr, "actual_samples_per_bits = %f\n", s->actual_samples_per_bits);
|
|
||||||
|
|
||||||
//Now we have an actual_samples_per_bits, we do the actual sampling
|
|
||||||
int di; //databit counter
|
int di; //databit counter
|
||||||
unsigned shr = 0;
|
unsigned shr = 0;
|
||||||
for(di=0; di < s->databits; di++)
|
for(di=0; di < s->databits; di++)
|
||||||
{
|
{
|
||||||
int databit_start = startbit_start + di * s->actual_samples_per_bits;
|
int databit_start = startbit_start + (1+di+(0.5*(1-s->bit_sampling_width_ratio))) * s->samples_per_bits;
|
||||||
int databit_end = startbit_start + (di+1) * s->actual_samples_per_bits;
|
int databit_end = startbit_start + (1+di+(0.5*(1+s->bit_sampling_width_ratio))) * s->samples_per_bits;
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_start = %d (%d)\n", databit_start, iabs_samples_helper+databit_start);
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_end = %d (%d)\n", databit_end, iabs_samples_helper+databit_end);
|
||||||
float databit_acc = 0;
|
float databit_acc = 0;
|
||||||
for(i=databit_start;i<databit_end;i++) databit_acc += input[i];
|
for(i=databit_start;i<databit_end;i++) { databit_acc += input[i]; /*DEBUG_SERIAL_LINE_DECODER && fprintf(stderr, "%f (%f) ", input[i], databit_acc);*/ }
|
||||||
|
//DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"\n");
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:databit_decision = %d\n", !!(databit_acc>0));
|
||||||
shr=(shr<<1)|!!(databit_acc>0);
|
shr=(shr<<1)|!!(databit_acc>0);
|
||||||
}
|
}
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:shr = 0x%x, %d\n", shr, shr);
|
||||||
|
|
||||||
//optionally we could check if the stopbit is correct
|
//We check if the stopbit is correct.
|
||||||
|
int stopbit_start = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1-s->bit_sampling_width_ratio)) * s->samples_per_bits;
|
||||||
|
int stopbit_end = startbit_start + (1+s->databits) * s->samples_per_bits + (s->stopbits * 0.5 * (1+s->bit_sampling_width_ratio)) * s->samples_per_bits;
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_start = %d (%d)\n", stopbit_start, iabs_samples_helper+stopbit_start);
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_end = %d (%d)\n", stopbit_end, iabs_samples_helper+stopbit_end);
|
||||||
|
float stopbit_acc = 0;
|
||||||
|
for(i=stopbit_start;i<stopbit_end;i++) { stopbit_acc += input[i]; DEBUG_SERIAL_LINE_DECODER && fprintf(stderr, "%f (%f) ", input[i], stopbit_acc); }
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"\n");
|
||||||
|
if(stopbit_acc<0) { s->input_used += MIN_M(startbit_start + 1, input_size); DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_stopbit_faulty (+%d)\n", s->input_used); return; }
|
||||||
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:stopbit_found\n");
|
||||||
|
|
||||||
//we write the output sample
|
//we write the output sample
|
||||||
if(s->databits <= 8) output[oi++] = shr;
|
if(s->databits <= 8) output[s->output_size] = shr;
|
||||||
else if(s->databits <= 16) output_s[oi] = shr;
|
else if(s->databits <= 16) output_s[s->output_size] = shr;
|
||||||
else output_u[oi++] = shr;
|
else output_u[s->output_size] = shr;
|
||||||
|
s->output_size++;
|
||||||
|
|
||||||
int samples_used_up_now = MIN_M(stopbit_end + s->actual_samples_per_bits, input_size);
|
int samples_used_up_now = MIN_M(startbit_start + all_bits * s->samples_per_bits, input_size);
|
||||||
s->input_used += samples_used_up_now;
|
s->input_used += samples_used_up_now;
|
||||||
input += samples_used_up_now;
|
input += samples_used_up_now;
|
||||||
input_size -= samples_used_up_now;
|
input_size -= samples_used_up_now;
|
||||||
|
iabs_samples_helper += samples_used_up_now;
|
||||||
|
if(!input_size) { DEBUG_SERIAL_LINE_DECODER && fprintf(stderr,"sld:return_no_more_input (+%d)\n", s->input_used); return; }
|
||||||
}
|
}
|
||||||
s->output_size = oi;
|
DEBUG_SERIAL_LINE_DECODER && fprintf(stderr, "sld: >> output_size = %d (+%d)\n", s->output_size, s->input_used);
|
||||||
fprintf(stderr, "so: %d\n", s->output_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void binary_slicer_f_u8(float* input, unsigned char* output, int input_size)
|
void binary_slicer_f_u8(float* input, unsigned char* output, int input_size)
|
||||||
|
|
|
@ -227,13 +227,11 @@ char psk31_varicode_decoder_push(unsigned long long* status_shr, unsigned char s
|
||||||
typedef struct serial_line_s
|
typedef struct serial_line_s
|
||||||
{
|
{
|
||||||
float samples_per_bits;
|
float samples_per_bits;
|
||||||
float actual_samples_per_bits;
|
|
||||||
int databits; //including parity
|
int databits; //including parity
|
||||||
float stopbits;
|
float stopbits;
|
||||||
int output_size;
|
int output_size;
|
||||||
int input_used;
|
int input_used;
|
||||||
float samples_per_bits_max_deviation_rate;
|
float bit_sampling_width_ratio;
|
||||||
float samples_per_bits_loop_gain;
|
|
||||||
} serial_line_t;
|
} serial_line_t;
|
||||||
|
|
||||||
void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* output, int input_size);
|
void serial_line_decoder_f_u8(serial_line_t* s, float* input, unsigned char* output, int input_size);
|
||||||
|
|
Loading…
Reference in a new issue