/* -*- 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_coder_impl.h" #include #include #include #include #include "m17.h" namespace gr { namespace m17 { struct LSF lsf; m17_coder::sptr m17_coder::make(std::string src_id,std::string dst_id,int mode,int data,int encr_type,int encr_subtype,int can,std::string meta, bool debug) { return gnuradio::get_initial_sptr (new m17_coder_impl(src_id,dst_id,mode,data,encr_type,encr_subtype,can,meta,debug)); } /* * The private constructor */ m17_coder_impl::m17_coder_impl(std::string src_id,std::string dst_id,int mode,int data,int encr_type,int encr_subtype,int can,std::string meta, bool debug) : gr::block("m17_coder", gr::io_signature::make(1, 1, sizeof(char)), gr::io_signature::make(1, 1, sizeof(float))) , _mode(mode),_data(data),_encr_type(encr_type),_encr_subtype(encr_subtype), _can(can),_meta(meta), _debug(debug) { set_type(mode, data, encr_type, encr_subtype, can); set_meta(meta); // depends on ^^^ encr_subtype set_src_id(src_id); set_dst_id(dst_id); set_debug(debug); set_output_multiple(192); uint16_t ccrc=LSF_CRC(&lsf); lsf.crc[0]=ccrc>>8; lsf.crc[1]=ccrc&0xFF; _got_lsf=0; //have we filled the LSF struct yet? _fn=0; //16-bit Frame Number (for the stream mode) } void m17_coder_impl::set_debug(bool debug) {_debug=debug; if (_debug==true) printf("Debug true\n"); else printf("Debug false\n"); } void m17_coder_impl::set_src_id(std::string src_id) {int length; for (int i=0;i<10;i++) {_src_id[i]=0;} if (src_id.length()>9) length=9; else length=src_id.length(); for (int i=0;i>8; lsf.crc[1]=ccrc&0xFF; } void m17_coder_impl::set_dst_id(std::string dst_id) {int length; for (int i=0;i<10;i++) {_dst_id[i]=0;} if (dst_id.length()>9) length=9; else length=dst_id.length(); for (int i=0;i>8; lsf.crc[1]=ccrc&0xFF; } void m17_coder_impl::set_meta(std::string meta) // either an ASCII string if encr_subtype==0 or *UTF-8* encoded byte array {int length; printf("new meta: "); if (_encr_subtype==0) // meta is \0-terminated string {if (meta.length()<14) length=meta.length(); else {length=14;meta[length]=0;} printf("%s\n",meta.c_str()); for (int i=0;i ",length); int i=0,j=0; do {if ((unsigned int)meta.data()[i]<0xc2) // https://www.utf8-chartable.de/ {lsf.meta[j]=meta.data()[i];i++;j++;} else {lsf.meta[j]=(meta.data()[i]-0xc2)*0x40+meta.data()[i+1];i+=2;j++;} } while ((j<=14) && (i<=length)); length=j; printf("%d bytes: ",length); for (i=0;i>8; lsf.crc[1]=ccrc&0xFF; } void m17_coder_impl::set_mode(int mode) {_mode=mode; printf("new mode: %x -> ",_mode); set_type(_mode,_data,_encr_type,_encr_subtype,_can); } void m17_coder_impl::set_data(int data) {_data=data; printf("new data type: %x -> ",_data); set_type(_mode,_data,_encr_type,_encr_subtype,_can); } void m17_coder_impl::set_encr_type(int encr_type) {_encr_type=encr_type; printf("new encr type: %x -> ",_encr_type); set_type(_mode,_data,_encr_type,_encr_subtype,_can); } void m17_coder_impl::set_encr_subtype(int encr_subtype) {_encr_subtype=encr_subtype; printf("new encr subtype: %x -> ",_encr_subtype); set_type(_mode,_data,_encr_type,_encr_subtype,_can); } void m17_coder_impl::set_can(int can) {_can=can; printf("new CAN: %x -> ",_can); set_type(_mode,_data,_encr_type,_encr_subtype,_can); } void m17_coder_impl::set_type(int mode,int data,int encr_type,int encr_subtype,int can) {short tmptype; tmptype = mode | (data<<1) | (encr_type<<3) | (encr_subtype<<5) | (can<<7); lsf.type[0]=tmptype>>8; // MSB lsf.type[1]=tmptype&0xff; // LSB uint16_t ccrc=LSF_CRC(&lsf); lsf.crc[0]=ccrc>>8; lsf.crc[1]=ccrc&0xFF; printf("type: %hhX%hhX\n",lsf.type[0],lsf.type[1]);fflush(stdout); } /* * Our virtual destructor. */ m17_coder_impl::~m17_coder_impl() { } void m17_coder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items/12; // 16 inputs -> 192 outputs } int m17_coder_impl::general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { const char *in = (const char *) input_items[0]; float *out = (float *) output_items[0]; int countin=0; uint32_t countout=0; uint8_t enc_bits[SYM_PER_PLD*2]; //type-2 bits, unpacked uint8_t rf_bits[SYM_PER_PLD*2]; //type-4 bits, unpacked uint8_t lich[6]; //48 bits packed raw, unencoded LICH uint8_t lich_encoded[12]; //96 bits packed, encoded LICH uint8_t data[16]; //raw payload, packed bits uint8_t lich_cnt=0; //0..5 LICH counter, derived from the Frame Number while (countout<(uint32_t)noutput_items) { if (countin+16<=noutput_items) {for (int i=0;i<16;i++) {data[i]=in[countin];countin++;} if(_got_lsf) //stream frames { //send stream frame syncword send_syncword(out,&countout,SYNC_STR); //extract LICH from the whole LSF extract_LICH(lich, lich_cnt, &lsf); //encode the LICH encode_LICH(lich_encoded, lich); //unpack LICH (12 bytes) unpack_LICH(enc_bits, lich_encoded); //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) // conv_encode_stream_frame(&enc_bits[96], data, finished ? (_fn | 0x8000) : _fn); JMF review conv_encode_stream_frame(&enc_bits[96], data, _fn); //reorder bits reorder_bits(rf_bits, enc_bits); //randomize randomize_bits(rf_bits); //send dummy symbols (debug) /*float s=0.0; for(uint8_t i=0; i