import java.awt.Color; import java.awt.Dimension; import java.awt.Image; final public class MultipathPPM extends MultiPathConvolution{ public MultipathPPM (Dimension dim, Image img, String problemName){ super(dim,img,problemName); } //========================================== // Parameter initializations //------------------------------------------ protected void initPreconstructor_Variables(){ initPreconstructorInMPLevel(); L=2; Amax=1; subModel=2; tapsSimulationLimit=10000; flgDrawNumbers=-1; modelDescription[0]="Program2. Model: PPM with ISI, Noise, and Ambient Light. Graph: BER(SNR)."; modelDescription[2]=" "; modelDescription[3]=" "+"Horizontal axis stands for SNR, db. "+ "Vertical axis stands for log(BER)/log(10)."; functionCOUNT=4; functionTitle[0]="BER. SNR=2. Rb=100 MHz"; functionTitle[1]="BER,db. Rb=0.05 Mhz"; functionTitle[2]="BER,db. Rb=10 Mhz"; functionTitle[3]="BER,db. Rb=100 Mhz"; dmnRangeF=20.0; dmnRangeFDown=19.0; dmnRangeX=10.0; grPoints=20; drawGrid=true; drawLengenOnCurve=false; gridStepY=1.0; grStartF=120; functionColor=new Color[]{ new Color(150,0,0), new Color(0,40,0), new Color(150,0,150), new Color(0,0,255), new Color(255,0,0), new Color(0,0,255) }; } //----------------------------------------------- // User Input Prompts //- - - - - - - - - - - - - - - - - - - - - - - - protected int setParsToStrings(){ int i=0; String decription=""; for(int j=0; j<subModelTitle.length; j++){ decription += ", "+j+" - " + subModelTitle[j]; } strParsCrr[i][0]=String.valueOf(subModel); strParsCrr[i][1]="Sub Model: "+decription; strParsCrr[i++][2]="int"; strParsCrr[i][0]=String.valueOf(shotNoisePresented); strParsCrr[i][1]="shotNoisePresented, 0 or 1"; strParsCrr[i++][2]="int"; //strParsCrr[i][0]=String.valueOf(SNR); strParsCrr[i][1]="SNR, dB"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(amSAR); strParsCrr[i][1]="SAR, Signal to Ambient Light Ratio"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(amInterferencePeriodTi); strParsCrr[i][1]="Ti, Ambient Light Interference Period, sec"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(amInteferenceSummationPoints); strParsCrr[i][1]="NTi, Ambient Light Interf. Sum. Points Numb., 1 for no Interference."; strParsCrr[i++][2]="int"; strParsCrr[i][0]=String.valueOf(dmnRangeX); strParsCrr[i][1]="Argument Range"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(dmnRangeF); strParsCrr[i][1]="Function Range"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(dmnStartF); strParsCrr[i][1]="Function Start"; strParsCrr[i++][2]="double"; //strParsCrr[i][0]=String.valueOf(Rb); strParsCrr[i][1]="Bit Rate, Rb"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(ceilingHeight); strParsCrr[i][1]="Room Height, meters"; strParsCrr[i++][2]="double"; strParsCrr[i][0]=String.valueOf(L); strParsCrr[i][1]="Maximum symbol length, L"; strParsCrr[i++][2]="int"; strParsCrr[i][0]=String.valueOf(Amax); strParsCrr[i][1]="Non-zero levels in chip amplitude, A"; strParsCrr[i++][2]="int"; return i; } public String setParsFromStrings(){ int i=0; try{ subModel =Integer.parseInt(strParsCrr[i][0]); i++; shotNoisePresented =Integer.parseInt(strParsCrr[i][0]); i++; //SNR =Double.parseDouble(strParsCrr[i][0]); i++; amSAR =Double.parseDouble(strParsCrr[i][0]); i++; amInterferencePeriodTi = Double.parseDouble(strParsCrr[i][0]); i++; amInteferenceSummationPoints = Integer.parseInt(strParsCrr[i][0]); i++; dmnRangeX =Double.parseDouble(strParsCrr[i][0]); i++; dmnRangeF =Double.parseDouble(strParsCrr[i][0]); i++; dmnStartF =Double.parseDouble(strParsCrr[i][0]); i++; //Rb =Double.parseDouble(strParsCrr[i][0]); i++; ceilingHeight =Double.parseDouble(strParsCrr[i][0]); i++; L =Integer.parseInt(strParsCrr[i][0]); i++; Amax =Integer.parseInt(strParsCrr[i][0]); i++; }catch(Exception e){ return "Exception when (re)setting parameters.\n" + e; } return ""; } //- - - - - - - - - - - - - - - - - - - - - - - - // User Input Prompts //================================================================ protected void spawnParametersAfterUserApplied(){ tapsSimulationLimit=10000; simulationBlocked=false; userImputCheckOrCorrectionBeforeBasic(); if(!simulationBlocked)spanParsInMPLevel(); if(!simulationBlocked)userImputCheckOrCorrectionAfterBasic(); if(!simulationBlocked)displySpawnedPars(); simulateThresholding(); if(simulationBlocked){ for(int i=20; i<modelDescription.length; i++){ modelDescription[i]=null; } //Set B to 1.0 to attract attention: BAmb=1.0; con("Simulation blocked."); } } private void userImputCheckOrCorrectionBeforeBasic(){ for(int i=4; i<modelDescription.length; i++){ modelDescription[i]=null; } if(L<2){ modelDescription[10]="L must be > 1"; //Set B to 1.0 to attract attention: simulationBlocked=true; } } private void userImputCheckOrCorrectionAfterBasic(){ for(int i=20; i<modelDescription.length; i++){ modelDescription[i]=null; } if(tapsSimulationLimit<=tapsNumber){ modelDescription[20]="BER for sub Model " + subModelTitle[subModel]+". Taps Number exceeded limit."; //Set B to 1.0 to attract attention: simulationBlocked=true; } if(2!=subModel){ modelDescription[20]="Sub model " + subModelTitle[subModel]+ " requested, but only " + subModelTitle[subModel]+ " is implemented in this window."; //Set B to 1.0 to attract attention: simulationBlocked=true; } } //--------------------------------------------------------- //To display this strings in graph background: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - private void displySpawnedPars(){ //con("subModelTile[0]="+subModelTitle[0]+" " + subModel); modelDescription[1]="Sub Model = "+subModelTitle[subModel]; modelDescription[4]="A="+Amax; modelDescription[5]="L="+L; //modelDescription[6]="SNR="+SNR+",db SNR="+SN; modelDescription[7]="Symbols in Alphabet="+aphabetCount; modelDescription[8]="M="+M; //modelDescription[9]="BitRate, Rb="+Rb+", bits/second."; modelDescription[10]="Average Length="+avLength; modelDescription[11]="Bits per chip="+bitsPerChip; //modelDescription[12]="Chip Length="+T+", seconds."; modelDescription[13]="Room Height="+ceilingHeight+", meters."; modelDescription[14]="Dispersion Length Scale, a="+a+", seconds."; modelDescription[15]="Lambda="+lambda; modelDescription[16]="Recent tapsNumber="+tapsNumber; } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - // To display this strings in graph background: //------------------------------------------ // Parameter initializations //========================================== //========================================== // Simulation //------------------------------------------ final protected void simulateThresholding(){ if(simulationBlocked)return; //First, find out number of slots of symbols which //precede primary symbol and can interfere with primary symbol: int sslots=0; while(sslots*L<tapsNumber)sslots=sslots+1; //Recalculated taps number which fits preceding symbols: int pastTaps=sslots*L; modelDescription[17]="RecentConvolving symbol slots number="+sslots; //Recalculate tapsNumber including primary symbol: int symTapsNumber=pastTaps+L; modelDescription[18]="Recent preceding taps + L ="+symTapsNumber; b=new int[symTapsNumber]; result=new double[symTapsNumber]; //Convolved primary symbol's ambient contribution for each chip: double[] V=new double[L]; int symbol_events=1; for(int i=0; i<sslots; i++){ symbol_events=symbol_events*L; } //Now, symbol_events=L^sslots int PPMSymbolSimulationLimit=1000000; //Protect against long calculations: if(PPMSymbolSimulationLimit<=symbol_events){ modelDescription[20]="BER for sub Model " + subModelTitle[subModel]+ ". Symbol Slots Limit exceeded."; simulationBlocked=true; return; } modelDescription[19]="Recent symbol events="+symbol_events; //We are about ready to summarize ... //Variance of J is squrt(2) times more than variance of N: //UFun.setHMode(SN/Math.sqrt(2.0), 0==shotNoisePresented); double SNR_PPM=SN/Math.sqrt(2.0); boolean HeavisideMode=0==shotNoisePresented; //Shortcuts: double amK=1.0/amSAR; //Parameter K-declared in [7, Wong, ...] double weight_ISI_NOISE=1.0/symbol_events/L/(L-1)/M; BAmb=0.0; //Full BER double amInterferenceStep=amInterferencePeriodTi/amInteferenceSummationPoints; for(int iXAm=0; iXAm<amInteferenceSummationPoints; iXAm++){ double tt=amInterferenceStep*iXAm; double BB=0.0; //BER under integration by time. //Prepare ambient contributions to current symbol: for(int i=0; i<L; i++){ V[i]=amK*am_vi(tt+T*i, T); } for(int e=0; e<symbol_events; e++){ //------------------------------------ //Generate symbols and chip sequences. //- - - - - - - - - - - - - - - - - - - int mask=symbol_events; for(int slot=0; slot<sslots; slot++){ int sym=mask%L; mask=(mask-sym)/L; for(int i=0; i<L; i++){ b[slot*L+i]=0; if(sym==i)b[slot*L+i]=Amax; } } //- - - - - - - - - - - - - - - - - - - //Generate symbols and chip sequences. //------------------------------------ //Cycle through primary chips: for(int i=0; i<L; i++){ //Fill primary symbol's chips with zeros: for(int k=0; k<L; k++)b[sslots*L+k]=0; //Fill one primary chip "with" non-zero amplitude: b[sslots*L+i]=Amax; //Calculate convolved chips from the top-1 to //top-L-1 chip which are chips of current symbol: convolve(pastTaps,b,result,false); //con("e="+e); //String debS=""; //for(int iii=0; iii<result.length; iii++){ // debS+=""+result[iii]; //} //con("bh="+debS); double Zi=lambda*result[pastTaps+i]; //con("Zi="+Zi); if(amInteferenceSummationPoints>1)Zi=Zi+V[i]; //Cycle through competing chips: for(int j=0; j<L; j++){ if(i==j)continue; double Zj=lambda*result[pastTaps+j]; //con("Zj="+Zj); if(amInteferenceSummationPoints>1)Zj=Zj+V[j]; double G=Zi-Zj; //BB=BB+UFun.erfh(G); BB=BB+UFun.erfh(G*SNR_PPM,HeavisideMode); //con("Binstant="+BB+" G="+G); } } //con("e="+e+" BB="+BB); } //for(e BAmb=BAmb+weight_ISI_NOISE*BB; //con("iXAm="+iXAm+" BB="+BB+" BAmb="+BAmb); } //for(int iXAm=0; BAmb=BAmb/amInteferenceSummationPoints; //do1 Wrong way. These values printed before calculations: modelDescription[20]="Recent BER "+BAmb; con("Recent BER "+BAmb); } //------------------------------------------ // Simulation //========================================== //Accuracy is restricted by 1e-16. private double LogBERonSNR(double SNR, double Rb){ this.SNR=SNR; this.Rb=Rb; spawnParametersAfterUserApplied(); //simulateThresholding(); if(1.0e-16>BAmb)return -16.0; //Blind return. Assumed accuracy limit in Java. return Math.log(BAmb)/Math.log(10); } //Accuracy is restricted by 1e-16. private double BERonSNR(double SNR, double Rb){ this.SNR=SNR; this.Rb=Rb; spawnParametersAfterUserApplied(); //simulateThresholding(); if(1.0e-16>BAmb)return 1.0e-16; //Blind return. Assumed accuracy limit in Java. return BAmb; } //UCFun ftest=new UCFun(); protected double functionSwitchX(int fIx, double t) {return 0;} protected double functionSwitch(int fIx, double x){ switch(fIx){ case 1: return LogBERonSNR(x, 0.05E6); case 2: return LogBERonSNR(x, 50.0E6); case 3: return LogBERonSNR(x, 100.0E6); case 0: return BERonSNR(2.0, 100.0E6); } return 0; } } Copyright (C) 2009 Konstantin Kirillov