// Copyright 2012 (C) Matthew Brejza // // This program 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 of the License, or // (at your option) any later version. // // This program 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. package rtty; //import java.awt.Color; public class fsk_demodulator { //MUST give sample rate of 8000 //private static final boolean DEBUG = false; //int _data_bits=7; double _f1; //low LO double _f2; //high LO private double _LO2_phase; //high LO private double _LO1_phase; //low LO private double _lastMaxPower = -1; private double _lastAveragePower_tot = -1; private int _lastBitCount = -1; private double sync_con = 2; //demod int resample_counter = 0; //sync private int _sync_pos = 0; //counter in the sync, for position in the bit (0->6) private double _sync_error = 0; //stores the error (currently an integrator) private double _sync_late = 0; //late gate value private moving_average _sync_thres;//value over which the sync should add/skip a cycle private double _last_bit = 0; //last bit value the sync encountered //sync2 private int _sync2_pos = 0; //counter in the sync, for position in the bit (0->6) private double _sync2_error = 0; //stores the error private double _sync2_error_int = 0; //stores the integrated error private double _sync2_late = 0; //late gate value private double _sync2_early = 0; //late gate value private double _sync2_vco = 0; private double _sync2_alpha = 0.5; private double _sync2_beta = 0.06; private fir_filter fir_res1_300; private fir_filter fir_res2_300; private fir_filter fir_res3_300; private fir_filter fir_res4_300; private fir_filter fir_res1_50; private fir_filter fir_res2_50; private fir_filter fir_res3_50; private fir_filter fir_res4_50; private fir_filter fir_res1_150; private fir_filter fir_res2_150; private fir_filter fir_res3_150; private fir_filter fir_res4_150; private fir_filter fir_res1_100; private fir_filter fir_res2_100; private fir_filter fir_res3_100; private fir_filter fir_res4_100; private fir_filter fir_outi1; private fir_filter fir_outq1; private fir_filter fir_outi2; private fir_filter fir_outq2; //previous window for debug //private double[] prev_win = new double[200]; // private graph_baseband gbb; public fsk_demodulator(double f1, double f2) { //if (DEBUG) // gbb = new graph_baseband(); _f1 = f1 /8000; _f2 = f2 /8000; fir_res1_300 = new fir_filter(new double[] {0.000786526835886959, 0.000599114690717327, 0.000400204797590807, -0.000307882669456068, -0.00166263695026489, -0.00366837630292647, -0.00612518190577769, -0.00858589989940669, -0.0103628564209468, -0.0105943725464158, -0.00837134797365531, -0.00290532178931729, 0.00628520202560880, 0.0192179861031230, 0.0353433796420604, 0.0535430726303462, 0.0722257626486942, 0.0895215970746844, 0.103547570655055, 0.112691192664381, 0.115866753291496, 0.112691192664381, 0.103547570655055, 0.0895215970746844, 0.0722257626486942, 0.0535430726303462, 0.0353433796420604, 0.0192179861031230, 0.00628520202560880, -0.00290532178931729, -0.00837134797365531, -0.0105943725464158, -0.0103628564209468, -0.00858589989940669, -0.00612518190577769, -0.00366837630292647, -0.00166263695026489, -0.000307882669456068, 0.000400204797590807, 0.000599114690717327, 0.000786526835886959}); fir_res2_300 = new fir_filter(new double[] {0.000786526835886959, 0.000599114690717327, 0.000400204797590807, -0.000307882669456068, -0.00166263695026489, -0.00366837630292647, -0.00612518190577769, -0.00858589989940669, -0.0103628564209468, -0.0105943725464158, -0.00837134797365531, -0.00290532178931729, 0.00628520202560880, 0.0192179861031230, 0.0353433796420604, 0.0535430726303462, 0.0722257626486942, 0.0895215970746844, 0.103547570655055, 0.112691192664381, 0.115866753291496, 0.112691192664381, 0.103547570655055, 0.0895215970746844, 0.0722257626486942, 0.0535430726303462, 0.0353433796420604, 0.0192179861031230, 0.00628520202560880, -0.00290532178931729, -0.00837134797365531, -0.0105943725464158, -0.0103628564209468, -0.00858589989940669, -0.00612518190577769, -0.00366837630292647, -0.00166263695026489, -0.000307882669456068, 0.000400204797590807, 0.000599114690717327, 0.000786526835886959}); fir_res3_300 = new fir_filter(new double[] {0.000786526835886959, 0.000599114690717327, 0.000400204797590807, -0.000307882669456068, -0.00166263695026489, -0.00366837630292647, -0.00612518190577769, -0.00858589989940669, -0.0103628564209468, -0.0105943725464158, -0.00837134797365531, -0.00290532178931729, 0.00628520202560880, 0.0192179861031230, 0.0353433796420604, 0.0535430726303462, 0.0722257626486942, 0.0895215970746844, 0.103547570655055, 0.112691192664381, 0.115866753291496, 0.112691192664381, 0.103547570655055, 0.0895215970746844, 0.0722257626486942, 0.0535430726303462, 0.0353433796420604, 0.0192179861031230, 0.00628520202560880, -0.00290532178931729, -0.00837134797365531, -0.0105943725464158, -0.0103628564209468, -0.00858589989940669, -0.00612518190577769, -0.00366837630292647, -0.00166263695026489, -0.000307882669456068, 0.000400204797590807, 0.000599114690717327, 0.000786526835886959}); fir_res4_300 = new fir_filter(new double[] {0.000786526835886959, 0.000599114690717327, 0.000400204797590807, -0.000307882669456068, -0.00166263695026489, -0.00366837630292647, -0.00612518190577769, -0.00858589989940669, -0.0103628564209468, -0.0105943725464158, -0.00837134797365531, -0.00290532178931729, 0.00628520202560880, 0.0192179861031230, 0.0353433796420604, 0.0535430726303462, 0.0722257626486942, 0.0895215970746844, 0.103547570655055, 0.112691192664381, 0.115866753291496, 0.112691192664381, 0.103547570655055, 0.0895215970746844, 0.0722257626486942, 0.0535430726303462, 0.0353433796420604, 0.0192179861031230, 0.00628520202560880, -0.00290532178931729, -0.00837134797365531, -0.0105943725464158, -0.0103628564209468, -0.00858589989940669, -0.00612518190577769, -0.00366837630292647, -0.00166263695026489, -0.000307882669456068, 0.000400204797590807, 0.000599114690717327, 0.000786526835886959}); //FIR least squares, Fs=8000, Fpass = 150, Fstop = 400, Wp/s = 1, order = 60 fir_res1_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res2_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res3_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res4_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); //Fpass = 250, Fstop = 500 fir_res1_150 = new fir_filter(new double[] { 0.000341988756080458, -0.000975573743855966, -0.00272598601203830, -0.00481359856713222, -0.00706845646761779, -0.00925042592744038, -0.0110621626092471, -0.0121705223903709, -0.0122349858974459, -0.0109407235793830, -0.00803318760089823, -0.00335068142996516, 0.00314870261149203, 0.0113690448867442, 0.0210699981543467, 0.0318731154024040, 0.0432813297940419, 0.0547104613511678, 0.0655303399204986, 0.0751120580472253, 0.0828771256545980, 0.0883439809981085, 0.0911674632422062, 0.0911674632422062, 0.0883439809981085, 0.0828771256545980, 0.0751120580472253, 0.0655303399204986, 0.0547104613511678, 0.0432813297940419, 0.0318731154024040, 0.0210699981543467, 0.0113690448867442, 0.00314870261149203, -0.00335068142996516, -0.00803318760089823, -0.0109407235793830, -0.0122349858974459, -0.0121705223903709, -0.0110621626092471, -0.00925042592744038, -0.00706845646761779, -0.00481359856713222, -0.00272598601203830, -0.000975573743855966, 0.000341988756080458 }); fir_res2_150 = new fir_filter(new double[] { 0.000341988756080458, -0.000975573743855966, -0.00272598601203830, -0.00481359856713222, -0.00706845646761779, -0.00925042592744038, -0.0110621626092471, -0.0121705223903709, -0.0122349858974459, -0.0109407235793830, -0.00803318760089823, -0.00335068142996516, 0.00314870261149203, 0.0113690448867442, 0.0210699981543467, 0.0318731154024040, 0.0432813297940419, 0.0547104613511678, 0.0655303399204986, 0.0751120580472253, 0.0828771256545980, 0.0883439809981085, 0.0911674632422062, 0.0911674632422062, 0.0883439809981085, 0.0828771256545980, 0.0751120580472253, 0.0655303399204986, 0.0547104613511678, 0.0432813297940419, 0.0318731154024040, 0.0210699981543467, 0.0113690448867442, 0.00314870261149203, -0.00335068142996516, -0.00803318760089823, -0.0109407235793830, -0.0122349858974459, -0.0121705223903709, -0.0110621626092471, -0.00925042592744038, -0.00706845646761779, -0.00481359856713222, -0.00272598601203830, -0.000975573743855966, 0.000341988756080458 }); fir_res3_150 = new fir_filter(new double[] { 0.000341988756080458, -0.000975573743855966, -0.00272598601203830, -0.00481359856713222, -0.00706845646761779, -0.00925042592744038, -0.0110621626092471, -0.0121705223903709, -0.0122349858974459, -0.0109407235793830, -0.00803318760089823, -0.00335068142996516, 0.00314870261149203, 0.0113690448867442, 0.0210699981543467, 0.0318731154024040, 0.0432813297940419, 0.0547104613511678, 0.0655303399204986, 0.0751120580472253, 0.0828771256545980, 0.0883439809981085, 0.0911674632422062, 0.0911674632422062, 0.0883439809981085, 0.0828771256545980, 0.0751120580472253, 0.0655303399204986, 0.0547104613511678, 0.0432813297940419, 0.0318731154024040, 0.0210699981543467, 0.0113690448867442, 0.00314870261149203, -0.00335068142996516, -0.00803318760089823, -0.0109407235793830, -0.0122349858974459, -0.0121705223903709, -0.0110621626092471, -0.00925042592744038, -0.00706845646761779, -0.00481359856713222, -0.00272598601203830, -0.000975573743855966, 0.000341988756080458 }); fir_res4_150 = new fir_filter(new double[] { 0.000341988756080458, -0.000975573743855966, -0.00272598601203830, -0.00481359856713222, -0.00706845646761779, -0.00925042592744038, -0.0110621626092471, -0.0121705223903709, -0.0122349858974459, -0.0109407235793830, -0.00803318760089823, -0.00335068142996516, 0.00314870261149203, 0.0113690448867442, 0.0210699981543467, 0.0318731154024040, 0.0432813297940419, 0.0547104613511678, 0.0655303399204986, 0.0751120580472253, 0.0828771256545980, 0.0883439809981085, 0.0911674632422062, 0.0911674632422062, 0.0883439809981085, 0.0828771256545980, 0.0751120580472253, 0.0655303399204986, 0.0547104613511678, 0.0432813297940419, 0.0318731154024040, 0.0210699981543467, 0.0113690448867442, 0.00314870261149203, -0.00335068142996516, -0.00803318760089823, -0.0109407235793830, -0.0122349858974459, -0.0121705223903709, -0.0110621626092471, -0.00925042592744038, -0.00706845646761779, -0.00481359856713222, -0.00272598601203830, -0.000975573743855966, 0.000341988756080458 }); //Fpass = 200, Fstop = 450 fir_res1_100 = new fir_filter(new double[] { -0.000785322968770648, -0.00183034176097845, -0.00310789924606038, -0.00455305320714628, -0.00606508050183854, -0.00750958288459318, -0.00872398673704316, -0.00952633536812975, -0.00972695695504517, -0.00914229004306465, -0.00760989157149020, -0.00500346676215420, -0.00124666757380930, 0.00367557933655379, 0.00970932870707903, 0.0167283395241270, 0.0245358271355535, 0.0328714225223429, 0.0414230994386041, 0.0498434162302048, 0.0577690452041549, 0.0648422624993631, 0.0707328737026778, 0.0751589745612591, 0.0779050010932041, 0.0788357066572436, 0.0779050010932041, 0.0751589745612591, 0.0707328737026778, 0.0648422624993631, 0.0577690452041549, 0.0498434162302048, 0.0414230994386041, 0.0328714225223429, 0.0245358271355535, 0.0167283395241270, 0.00970932870707903, 0.00367557933655379, -0.00124666757380930, -0.00500346676215420, -0.00760989157149020, -0.00914229004306465, -0.00972695695504517, -0.00952633536812975, -0.00872398673704316, -0.00750958288459318, -0.00606508050183854, -0.00455305320714628, -0.00310789924606038, -0.00183034176097845, -0.000785322968770648 }); fir_res2_100 = new fir_filter(new double[] { -0.000785322968770648, -0.00183034176097845, -0.00310789924606038, -0.00455305320714628, -0.00606508050183854, -0.00750958288459318, -0.00872398673704316, -0.00952633536812975, -0.00972695695504517, -0.00914229004306465, -0.00760989157149020, -0.00500346676215420, -0.00124666757380930, 0.00367557933655379, 0.00970932870707903, 0.0167283395241270, 0.0245358271355535, 0.0328714225223429, 0.0414230994386041, 0.0498434162302048, 0.0577690452041549, 0.0648422624993631, 0.0707328737026778, 0.0751589745612591, 0.0779050010932041, 0.0788357066572436, 0.0779050010932041, 0.0751589745612591, 0.0707328737026778, 0.0648422624993631, 0.0577690452041549, 0.0498434162302048, 0.0414230994386041, 0.0328714225223429, 0.0245358271355535, 0.0167283395241270, 0.00970932870707903, 0.00367557933655379, -0.00124666757380930, -0.00500346676215420, -0.00760989157149020, -0.00914229004306465, -0.00972695695504517, -0.00952633536812975, -0.00872398673704316, -0.00750958288459318, -0.00606508050183854, -0.00455305320714628, -0.00310789924606038, -0.00183034176097845, -0.000785322968770648 }); fir_res3_100 = new fir_filter(new double[] { -0.000785322968770648, -0.00183034176097845, -0.00310789924606038, -0.00455305320714628, -0.00606508050183854, -0.00750958288459318, -0.00872398673704316, -0.00952633536812975, -0.00972695695504517, -0.00914229004306465, -0.00760989157149020, -0.00500346676215420, -0.00124666757380930, 0.00367557933655379, 0.00970932870707903, 0.0167283395241270, 0.0245358271355535, 0.0328714225223429, 0.0414230994386041, 0.0498434162302048, 0.0577690452041549, 0.0648422624993631, 0.0707328737026778, 0.0751589745612591, 0.0779050010932041, 0.0788357066572436, 0.0779050010932041, 0.0751589745612591, 0.0707328737026778, 0.0648422624993631, 0.0577690452041549, 0.0498434162302048, 0.0414230994386041, 0.0328714225223429, 0.0245358271355535, 0.0167283395241270, 0.00970932870707903, 0.00367557933655379, -0.00124666757380930, -0.00500346676215420, -0.00760989157149020, -0.00914229004306465, -0.00972695695504517, -0.00952633536812975, -0.00872398673704316, -0.00750958288459318, -0.00606508050183854, -0.00455305320714628, -0.00310789924606038, -0.00183034176097845, -0.000785322968770648 }); fir_res4_100 = new fir_filter(new double[] { -0.000785322968770648, -0.00183034176097845, -0.00310789924606038, -0.00455305320714628, -0.00606508050183854, -0.00750958288459318, -0.00872398673704316, -0.00952633536812975, -0.00972695695504517, -0.00914229004306465, -0.00760989157149020, -0.00500346676215420, -0.00124666757380930, 0.00367557933655379, 0.00970932870707903, 0.0167283395241270, 0.0245358271355535, 0.0328714225223429, 0.0414230994386041, 0.0498434162302048, 0.0577690452041549, 0.0648422624993631, 0.0707328737026778, 0.0751589745612591, 0.0779050010932041, 0.0788357066572436, 0.0779050010932041, 0.0751589745612591, 0.0707328737026778, 0.0648422624993631, 0.0577690452041549, 0.0498434162302048, 0.0414230994386041, 0.0328714225223429, 0.0245358271355535, 0.0167283395241270, 0.00970932870707903, 0.00367557933655379, -0.00124666757380930, -0.00500346676215420, -0.00760989157149020, -0.00914229004306465, -0.00972695695504517, -0.00952633536812975, -0.00872398673704316, -0.00750958288459318, -0.00606508050183854, -0.00455305320714628, -0.00310789924606038, -0.00183034176097845, -0.000785322968770648 }); fir_res1_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res2_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res3_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_res4_50 = new fir_filter(new double[] {-0.000470150951958517, -0.000998444628627754, -0.00166659230451889, -0.00246057404752554, -0.00335187222880445, -0.00429665490816831, -0.00523593893273512, -0.00609683876406133, -0.00679493819123118, -0.00723774490572776, -0.00732910763626992, -0.00697439793371205, -0.00608618964206127, -0.00459011414921971, -0.00243053347211709, 0.000424340274996863, 0.00397823930812195, 0.00820387248501318, 0.0130414594402352, 0.0183989498042643, 0.0241540141790163, 0.0301577870656315, 0.0362402324935664, 0.0422168980203310, 0.0478967292940066, 0.0530905421049322, 0.0576196972923792, 0.0613244999799519, 0.0640718505133941, 0.0657617102714020, 0.0663320092670076, 0.0657617102714020, 0.0640718505133941, 0.0613244999799519, 0.0576196972923792, 0.0530905421049322, 0.0478967292940066, 0.0422168980203310, 0.0362402324935664, 0.0301577870656315, 0.0241540141790163, 0.0183989498042643, 0.0130414594402352, 0.00820387248501318, 0.00397823930812195, 0.000424340274996863, -0.00243053347211709, -0.00459011414921971, -0.00608618964206127, -0.00697439793371205, -0.00732910763626992, -0.00723774490572776, -0.00679493819123118, -0.00609683876406133, -0.00523593893273512, -0.00429665490816831, -0.00335187222880445, -0.00246057404752554, -0.00166659230451889, -0.000998444628627754, -0.000470150951958517}); fir_outi1 = new fir_filter(new double[] {7.66162137128810e-20, 3.43550906278866e-05, -8.83345603792872e-20, -0.000122408611849792, -0.000346506388319725, -0.000677302805286787, -0.00110849468468061, -0.00162028620808185, -0.00217798010455547, -0.00273157043974124, -0.00321650959397525, -0.00355574358872080, -0.00366301597355252, -0.00344733783933627, -0.00281841824515606, -0.00169275411240634, 1.24442056906536e-18, 0.00231081620366610, 0.00526568968969643, 0.00886109513374814, 0.0130609054973305, 0.0177950964431462, 0.0229604512616186, 0.0284233508924476, 0.0340245905577380, 0.0395860193321182, 0.0449186628386524, 0.0498318729891462, 0.0541429618220168, 0.0576867264750822, 0.0603242638564779, 0.0619505081454146, 0.0625000000000000, 0.0619505081454146, 0.0603242638564779, 0.0576867264750822, 0.0541429618220168, 0.0498318729891462, 0.0449186628386524, 0.0395860193321182, 0.0340245905577380, 0.0284233508924476, 0.0229604512616186, 0.0177950964431462, 0.0130609054973305, 0.00886109513374814, 0.00526568968969643, 0.00231081620366610, 1.24442056906536e-18, -0.00169275411240634, -0.00281841824515606, -0.00344733783933627, -0.00366301597355252, -0.00355574358872080, -0.00321650959397525, -0.00273157043974124, -0.00217798010455547, -0.00162028620808185, -0.00110849468468061, -0.000677302805286787, -0.000346506388319725, -0.000122408611849792, -8.83345603792872e-20, 3.43550906278866e-05, 7.66162137128810e-20}); fir_outq2 = new fir_filter(new double[] {7.66162137128810e-20, 3.43550906278866e-05, -8.83345603792872e-20, -0.000122408611849792, -0.000346506388319725, -0.000677302805286787, -0.00110849468468061, -0.00162028620808185, -0.00217798010455547, -0.00273157043974124, -0.00321650959397525, -0.00355574358872080, -0.00366301597355252, -0.00344733783933627, -0.00281841824515606, -0.00169275411240634, 1.24442056906536e-18, 0.00231081620366610, 0.00526568968969643, 0.00886109513374814, 0.0130609054973305, 0.0177950964431462, 0.0229604512616186, 0.0284233508924476, 0.0340245905577380, 0.0395860193321182, 0.0449186628386524, 0.0498318729891462, 0.0541429618220168, 0.0576867264750822, 0.0603242638564779, 0.0619505081454146, 0.0625000000000000, 0.0619505081454146, 0.0603242638564779, 0.0576867264750822, 0.0541429618220168, 0.0498318729891462, 0.0449186628386524, 0.0395860193321182, 0.0340245905577380, 0.0284233508924476, 0.0229604512616186, 0.0177950964431462, 0.0130609054973305, 0.00886109513374814, 0.00526568968969643, 0.00231081620366610, 1.24442056906536e-18, -0.00169275411240634, -0.00281841824515606, -0.00344733783933627, -0.00366301597355252, -0.00355574358872080, -0.00321650959397525, -0.00273157043974124, -0.00217798010455547, -0.00162028620808185, -0.00110849468468061, -0.000677302805286787, -0.000346506388319725, -0.000122408611849792, -8.83345603792872e-20, 3.43550906278866e-05, 7.66162137128810e-20}); fir_outi2 = new fir_filter(new double[] {7.66162137128810e-20, 3.43550906278866e-05, -8.83345603792872e-20, -0.000122408611849792, -0.000346506388319725, -0.000677302805286787, -0.00110849468468061, -0.00162028620808185, -0.00217798010455547, -0.00273157043974124, -0.00321650959397525, -0.00355574358872080, -0.00366301597355252, -0.00344733783933627, -0.00281841824515606, -0.00169275411240634, 1.24442056906536e-18, 0.00231081620366610, 0.00526568968969643, 0.00886109513374814, 0.0130609054973305, 0.0177950964431462, 0.0229604512616186, 0.0284233508924476, 0.0340245905577380, 0.0395860193321182, 0.0449186628386524, 0.0498318729891462, 0.0541429618220168, 0.0576867264750822, 0.0603242638564779, 0.0619505081454146, 0.0625000000000000, 0.0619505081454146, 0.0603242638564779, 0.0576867264750822, 0.0541429618220168, 0.0498318729891462, 0.0449186628386524, 0.0395860193321182, 0.0340245905577380, 0.0284233508924476, 0.0229604512616186, 0.0177950964431462, 0.0130609054973305, 0.00886109513374814, 0.00526568968969643, 0.00231081620366610, 1.24442056906536e-18, -0.00169275411240634, -0.00281841824515606, -0.00344733783933627, -0.00366301597355252, -0.00355574358872080, -0.00321650959397525, -0.00273157043974124, -0.00217798010455547, -0.00162028620808185, -0.00110849468468061, -0.000677302805286787, -0.000346506388319725, -0.000122408611849792, -8.83345603792872e-20, 3.43550906278866e-05, 7.66162137128810e-20}); fir_outq1 = new fir_filter(new double[] {7.66162137128810e-20, 3.43550906278866e-05, -8.83345603792872e-20, -0.000122408611849792, -0.000346506388319725, -0.000677302805286787, -0.00110849468468061, -0.00162028620808185, -0.00217798010455547, -0.00273157043974124, -0.00321650959397525, -0.00355574358872080, -0.00366301597355252, -0.00344733783933627, -0.00281841824515606, -0.00169275411240634, 1.24442056906536e-18, 0.00231081620366610, 0.00526568968969643, 0.00886109513374814, 0.0130609054973305, 0.0177950964431462, 0.0229604512616186, 0.0284233508924476, 0.0340245905577380, 0.0395860193321182, 0.0449186628386524, 0.0498318729891462, 0.0541429618220168, 0.0576867264750822, 0.0603242638564779, 0.0619505081454146, 0.0625000000000000, 0.0619505081454146, 0.0603242638564779, 0.0576867264750822, 0.0541429618220168, 0.0498318729891462, 0.0449186628386524, 0.0395860193321182, 0.0340245905577380, 0.0284233508924476, 0.0229604512616186, 0.0177950964431462, 0.0130609054973305, 0.00886109513374814, 0.00526568968969643, 0.00231081620366610, 1.24442056906536e-18, -0.00169275411240634, -0.00281841824515606, -0.00344733783933627, -0.00366301597355252, -0.00355574358872080, -0.00321650959397525, -0.00273157043974124, -0.00217798010455547, -0.00162028620808185, -0.00110849468468061, -0.000677302805286787, -0.000346506388319725, -0.000122408611849792, -8.83345603792872e-20, 3.43550906278866e-05, 7.66162137128810e-20}); _sync_thres = new moving_average(16); } //this returns the raw bitstream for purposes of working out 7n1/8n1 etc public boolean[] processBlock_2bits (double[] samples, int baud) { double[] llrs = (sync(demod_samples(samples,baud))); boolean[] out = new boolean[llrs.length]; for (int i = 0; i < llrs.length; i++) { if (llrs[i]<0) out[i] = true; else out[i] = false; } return out; } //this returns the raw bitstream for purposes of working out 7n1/8n1 etc public double[] processBlock_2bits_llr (double[] samples, int baud) { return (sync(demod_samples(samples, baud))); } private double[] demod_samples (double[] samples, int baud) { int upsample_ratio = 1; int downsample_ratio = 1; if (baud == 300) { upsample_ratio = 3; downsample_ratio = 5; } else if (baud == 150) { upsample_ratio = 3; downsample_ratio = 10; } else if (baud == 100) { downsample_ratio = 5; } else //if (baud == 50) { downsample_ratio = 10; } double[] bb_h_s = new double[samples.length*upsample_ratio]; double[] bb_h_c = new double[samples.length*upsample_ratio]; double[] bb_l_s = new double[samples.length*upsample_ratio]; double[] bb_l_c = new double[samples.length*upsample_ratio]; //perform multiplication for each tone with sin and cos for (int i = 0; i < samples.length; i++) { bb_h_s[i*upsample_ratio] = samples[i] * Math.sin(2 * Math.PI *_LO2_phase); bb_h_c[i*upsample_ratio] = samples[i] * Math.cos(2 * Math.PI *_LO2_phase); bb_l_s[i*upsample_ratio] = samples[i] * Math.sin(2 * Math.PI *_LO1_phase); bb_l_c[i*upsample_ratio] = samples[i] * Math.cos(2 * Math.PI *_LO1_phase); //increment phases _LO1_phase = _LO1_phase + _f1; _LO2_phase = _LO2_phase + _f2; } _LO1_phase = _LO1_phase % 1; _LO2_phase = _LO2_phase % 1; //filter so that the sample rate can be reduced if (baud == 300) { for (int i =0; i<samples.length*upsample_ratio; i++) { bb_h_s[i] = fir_res1_300.step(bb_h_s[i]); bb_h_c[i] = fir_res2_300.step(bb_h_c[i]); bb_l_s[i] = fir_res3_300.step(bb_l_s[i]); bb_l_c[i] = fir_res4_300.step(bb_l_c[i]); } } else if (baud == 150) { for (int i =0; i<samples.length*upsample_ratio; i++) { bb_h_s[i] = fir_res1_150.step(bb_h_s[i]); bb_h_c[i] = fir_res2_150.step(bb_h_c[i]); bb_l_s[i] = fir_res3_150.step(bb_l_s[i]); bb_l_c[i] = fir_res4_150.step(bb_l_c[i]); } } else if (baud == 100) { for (int i =0; i<samples.length*upsample_ratio; i++) { bb_h_s[i] = fir_res1_100.step(bb_h_s[i]); bb_h_c[i] = fir_res2_100.step(bb_h_c[i]); bb_l_s[i] = fir_res3_100.step(bb_l_s[i]); bb_l_c[i] = fir_res4_100.step(bb_l_c[i]); } } else //else 50 { for (int i =0; i<samples.length*upsample_ratio; i++) { bb_h_s[i] = fir_res1_50.step(bb_h_s[i]); bb_h_c[i] = fir_res2_50.step(bb_h_c[i]); bb_l_s[i] = fir_res3_50.step(bb_l_s[i]); bb_l_c[i] = fir_res4_50.step(bb_l_c[i]); } } //consider only every 5th sample (300 baud) or every 10th sample (50 baud) int R = downsample_ratio; if (R-resample_counter < 0) resample_counter = 0; int len = (int) Math.ceil(((double)((double)(samples.length*upsample_ratio)-(R-resample_counter)%R))/R); if (len > 0) { double[] out = new double[len]; //sample, square and add int j = 0; for (int i = (R-resample_counter) % R; i < samples.length*upsample_ratio; i=i+R) { //output filter bb_l_s[i] = fir_outi1.step(bb_l_s[i]); bb_l_c[i] = fir_outq1.step(bb_l_c[i]); bb_h_s[i] = fir_outi2.step(bb_h_s[i]); bb_h_c[i] = fir_outq2.step(bb_h_c[i]); //if (j < len){ out[j] = (Math.pow(bb_l_s[i],2) + Math.pow(bb_l_c[i],2)) - (Math.pow(bb_h_s[i],2) + Math.pow(bb_h_c[i],2)); //} j++; } //TODO FILTER THEN SQUARE!!! NEEDS CHANGING (done) //TODO for science compare performance of each arrangement resample_counter = ((resample_counter + (samples.length*upsample_ratio)) % R) % R; return out; } else { resample_counter = ((resample_counter + (samples.length*upsample_ratio)) % R) % R; return null; } } private double[] sync(double[] input) { if (true) return sync2(input); // TODO increment values more than just 1/-1; // TODO remember that data is already squared coming into this block //debug int le = Math.min(400, input.length); double[] gin = new double[le]; System.arraycopy(input,0,gin,0,le); //System.arraycopy(prev_win,0,gin,0,200); //if (DEBUG) //{ // gbb.drawsingle(gin); // gbb.clearMarkers(); //} //System.arraycopy(input,input.length-200,prev_win,0,200); // _lastBitCount = 0; _lastMaxPower = 0; _lastAveragePower_tot = 0; double[] out = new double[input.length/10]; int out_count = 0; for (int i = 0; i < input.length; i++) { switch (_sync_pos) { case 3: //early gate if (Math.signum(input[i]) != Math.signum(_last_bit)) { _sync_error = _sync_error + Math.pow(input[i],2) - _sync_late; } //if (i < 400) // if (DEBUG) {gbb.addMarkers(i, Color.RED); } //break; case 6: //skip or add a cycle if (_sync_error > sync_con * _sync_thres.getMA()) //skip { _sync_pos = _sync_pos + 1; _sync_error = _sync_error - sync_con * _sync_thres.getMA(); } else if (_sync_error > sync_con * _sync_thres.getMA()) //add { _sync_pos = _sync_pos - 1; _sync_error = _sync_error + sync_con * _sync_thres.getMA(); } break; case 8: //sample gate out[out_count] = input[i]; out_count++; _last_bit = input[i]; _sync_thres.update(Math.pow(input[i],2)); _lastMaxPower = Math.max(_lastMaxPower, Math.abs(input[i])); _lastAveragePower_tot += Math.abs(input[i]); _lastBitCount ++; //if (i < 400) // if (DEBUG) { gbb.addMarkers(i, Color.BLUE); } break; case 12: //late gate _sync_late = Math.pow(input[i],2); //if (i < 400) // if (DEBUG) { gbb.addMarkers(i, Color.GREEN); } break; } _sync_pos = (_sync_pos+1) % 16; } //resize output length if (out_count == 0) { return null; } else { double[] fo = new double[out_count]; System.arraycopy(out, 0, fo, 0, out_count); return fo; } } private double[] sync2(double[] input) { // TODO increment values more than just 1/-1; // TODO remember that data is already squared coming into this block //debug int le = Math.min(400, input.length); double[] gin = new double[le]; System.arraycopy(input,0,gin,0,le); //System.arraycopy(prev_win,0,gin,0,200); //if (DEBUG) //{ // gbb.drawsingle(gin); // gbb.clearMarkers(); //} //System.arraycopy(input,input.length-200,prev_win,0,200); // _lastBitCount = 0; _lastMaxPower = 0; _lastAveragePower_tot = 0; double[] out = new double[input.length/10]; int out_count = 0; double error; for (int i = 0; i < input.length; i++) { switch (_sync2_pos) { case 0: _sync2_late = Math.signum(input[i]); break; case 1: case 2: case 3: case 4: case 5: _sync2_late = _sync2_late + Math.signum(input[i]); break; case 6: _sync2_late = _sync2_late + Math.signum(input[i]); _sync2_error = (+Math.abs(_sync2_late)-Math.abs(_sync2_early)); _sync2_error_int = _sync2_error_int + _sync2_error; _sync2_error_int = Math.min(_sync2_error_int, 2 * _sync2_beta); _sync2_error_int = Math.max(_sync2_error_int, -2 * _sync2_beta); break; case 7: //skip or add a cycle if (_sync2_vco < 6.4) { _sync2_pos = 6; break; } else if (_sync2_vco > 7.6) { if (_sync2_vco > 8.6) _sync2_pos = 8; else _sync2_pos = 9; } else break; case 8: //sample gate out[out_count] = input[i]; out_count++; _last_bit = input[i]; //_sync_thres.update(Math.pow(input[i],2)); _lastMaxPower = Math.max(_lastMaxPower, Math.abs(input[i])); _lastAveragePower_tot += Math.abs(input[i]); _lastBitCount ++; //if (i < 400) // if (DEBUG) { gbb.addMarkers(i, Color.BLUE); } if (_sync2_pos == 8) break; case 9: _sync2_early = Math.signum(input[i]); break; case 10: case 11: case 12: case 13: case 14: case 15: _sync2_early = _sync2_early + Math.signum(input[i]); break; } error = (_sync2_alpha * _sync2_error + _sync2_beta * _sync2_error_int)/16; _sync2_pos = (_sync2_pos+1) % 16; _sync2_vco = (_sync2_vco + error + 1) % 16; } //resize output length if (out_count == 0) { return null; } else { double[] fo = new double[out_count]; System.arraycopy(out, 0, fo, 0, out_count); return fo; } } public void setFreq(double f1, double f2) { _f1 = f1/8000; _f2 = f2/8000; } public double getLastMaxPower(){ return _lastMaxPower; } public double getLastAveragePower(){ if (_lastBitCount > 0) return _lastAveragePower_tot/(double)_lastBitCount; else return -1; } }