/* -*- c++ -*- */ /* * Copyright 2023 jmfriedt. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "m17_decoder_impl.h" #include #include #include #include #include #include "../M17_Implementations/SP5WWP/inc/m17.h" #include "../M17_Implementations/SP5WWP/m17-decoder/golay.h" #include "../M17_Implementations/SP5WWP/m17-decoder/viterbi.h" #include "../M17_Implementations/SP5WWP/m17-decoder/crc.h" #define DECODE_CALLSIGNS //#define SHOW_VITERBI_ERRS // #define CODE_MEAN -0.75 // mean(str_sync) #define CODE_STD 8.21583836f //std(str_sync)*sqrt(length(str_sync)-1) // see ../M17_Implementations/SP5WWP/inc/m17.h for const int8_t str_sync[8]={-3, -3, -3, -3, +3, +3, -3, +3}; namespace gr { namespace m17 { //soft decodes LICH into a 6-byte array //input - soft bits //output - an array of packed bits void decode_LICH(uint8_t* outp, const uint16_t* inp) { uint16_t tmp; memset(outp, 0, 5); tmp=golay24_sdecode(&inp[0]); outp[0]=(tmp>>4)&0xFF; outp[1]|=(tmp&0xF)<<4; tmp=golay24_sdecode(&inp[1*24]); outp[1]|=(tmp>>8)&0xF; outp[2]=tmp&0xFF; tmp=golay24_sdecode(&inp[2*24]); outp[3]=(tmp>>4)&0xFF; outp[4]|=(tmp&0xF)<<4; tmp=golay24_sdecode(&inp[3*24]); outp[4]|=(tmp>>8)&0xF; outp[5]=tmp&0xFF; } //decodes a 6-byte long array to a callsign void decode_callsign(uint8_t *outp, const uint8_t *inp) { uint64_t encoded=0; //repack the data to a uint64_t for(uint8_t i=0; i<6; i++) encoded|=(uint64_t)inp[5-i]<<(8*i); //check if the value is reserved (not a callsign) if(encoded>=262144000000000ULL) { if(encoded==0xFFFFFFFFFFFF) //broadcast { sprintf((char*)outp, "#BCAST"); } else { outp[0]=0; } return; } //decode the callsign uint8_t i=0; while(encoded>0) { outp[i]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded%40]; encoded/=40; i++; } outp[i] = 0; } m17_decoder::sptr m17_decoder::make(bool debug_data,bool debug_ctrl,float threshold) { return gnuradio::get_initial_sptr (new m17_decoder_impl(debug_data,debug_ctrl,threshold)); } /* * The private constructor */ m17_decoder_impl::m17_decoder_impl(bool debug_data,bool debug_ctrl,float threshold) : gr::block("m17_decoder", gr::io_signature::make(1, 1, sizeof(float)), gr::io_signature::make(1, 1, sizeof(char))), _debug_data(debug_data), _debug_ctrl(debug_ctrl), _threshold(threshold) {set_debug_data(debug_data); set_debug_ctrl(debug_ctrl); set_threshold(threshold); } /* * Our virtual destructor. */ m17_decoder_impl::~m17_decoder_impl() { } void m17_decoder_impl::set_threshold(float threshold) {_threshold=threshold; printf("Threshold: %f\n",_threshold); } void m17_decoder_impl::set_debug_data(bool debug) {_debug_data=debug; if (_debug_data==true) printf("Data debug: true\n"); else printf("Data debug: false\n"); } void m17_decoder_impl::set_debug_ctrl(bool debug) {_debug_ctrl=debug; if (_debug_ctrl==true) printf("Debug control: true\n"); else printf("Debug control: false\n"); } void m17_decoder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = 0; // noutput_items; } float eucl_norm(const float* in1, const int8_t* in2, uint8_t len) { float tmp = 0.0f; for(uint8_t i=0; i=symbs[3]) { soft_bit[i*2+1]=0xFFFF; } else if(pld[i]>=symbs[2]) { soft_bit[i*2+1]=-(float)0xFFFF/(symbs[3]-symbs[2])*symbs[2]+pld[i]*(float)0xFFFF/(symbs[3]-symbs[2]); } else if(pld[i]>=symbs[1]) { soft_bit[i*2+1]=0x0000; } else if(pld[i]>=symbs[0]) { soft_bit[i*2+1]=(float)0xFFFF/(symbs[1]-symbs[0])*symbs[1]-pld[i]*(float)0xFFFF/(symbs[1]-symbs[0]); } else { soft_bit[i*2+1]=0xFFFF; } //bit 1 if(pld[i]>=symbs[2]) { soft_bit[i*2]=0x0000; } else if(pld[i]>=symbs[1]) { soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbs[2]-symbs[1]); } else { soft_bit[i*2]=0xFFFF; } } //derandomize for(uint16_t i=0; i>(7-(i%8)))&1) //soft XOR. flip soft bit if "1" soft_bit[i]=0xFFFF-soft_bit[i]; } //deinterleave for(uint16_t i=0; i>5; lich_chunks_rcvd|=(1<