public String[] decode(DMRDecode TtheApp, byte[] dibit_buf) { String cline; theApp = TtheApp; DecodeCACH cachdecode = new DecodeCACH(); // CACH decode cline = cachdecode.decode(theApp, dibit_buf); resCACH = cachdecode.isPassErrorCheck(); if (resCACH == true) { line[1] = cline; fonts[1] = theApp.italicFont; colours[1] = Color.BLACK; resEMB = EMBdecode(dibit_buf); // If short LC data is available then display it if (cachdecode.getShortLC() == true) { line[7] = cachdecode.getShortLCline(); fonts[7] = theApp.boldFont; if (cachdecode.getshortLCError() == true) { colours[7] = Color.RED; if (theApp.isDisplayOnlyGoodFrames() == true) line[7] = null; } else colours[7] = Color.BLACK; cachdecode.clearShortLC(); } } if ((resCACH == false) && (resEMB == false)) theApp.embeddedFrameCount = 8; theApp.frameCount++; return line; }
// Error check and decode the EMB private boolean EMBdecode(byte[] dibit_buf) { int a, r, cc, lcss; boolean pi; boolean EMDdata[] = new boolean[16]; // Convert from dibits into boolean // The EMB is broken into 2 parts either side of the embedded // these need reuniting into a single 20 bit boolean array r = 0; for (a = 66; a < 70; a++) { if (dibit_buf[a] == 0) { EMDdata[r] = false; EMDdata[r + 1] = false; } else if (dibit_buf[a] == 1) { EMDdata[r] = false; EMDdata[r + 1] = true; } else if (dibit_buf[a] == 2) { EMDdata[r] = true; EMDdata[r + 1] = false; } else if (dibit_buf[a] == 3) { EMDdata[r] = true; EMDdata[r + 1] = true; } r = r + 2; } for (a = 86; a < 90; a++) { if (dibit_buf[a] == 0) { EMDdata[r] = false; EMDdata[r + 1] = false; } else if (dibit_buf[a] == 1) { EMDdata[r] = false; EMDdata[r + 1] = true; } else if (dibit_buf[a] == 2) { EMDdata[r] = true; EMDdata[r + 1] = false; } else if (dibit_buf[a] == 3) { EMDdata[r] = true; EMDdata[r + 1] = true; } r = r + 2; } // Error check the EMB // If it passes this is a Voice Burst with Embedded Signalling if (QuadResidue1676(EMDdata) == true) { StringBuilder sb = new StringBuilder(250); line[0] = theApp.getTimeStamp() + " DMR Voice Frame with Embedded Signalling"; colours[0] = Color.BLACK; fonts[0] = theApp.boldFont; // Colour code if (EMDdata[0] == true) cc = 8; else cc = 0; if (EMDdata[1] == true) cc = cc + 4; if (EMDdata[2] == true) cc = cc + 2; if (EMDdata[3] == true) cc = cc + 1; // Update the colour code display if (theApp != null) theApp.setColourCode(cc); // PI pi = EMDdata[4]; // LCSS if (EMDdata[5] == true) lcss = 2; else lcss = 0; if (EMDdata[6] == true) lcss++; // Display the colour code sb.append("EMB : Colour Code " + Integer.toString(cc)); // PI if (pi == true) sb.append(" : PI=1"); // LCSS if (lcss == 0) sb.append(" : Single fragment LC "); else if (lcss == 1) sb.append(" : First fragment of LC "); else if (lcss == 2) sb.append(" : Last fragment of LC"); else if (lcss == 3) sb.append(" : Continuation fragment of LC"); line[2] = sb.toString(); // Add this to the embedded data class theApp.embedded_lc.addData(dibit_buf, lcss); // Is embedded data ready if (theApp.embedded_lc.getDataReady() == true) { String elines[] = theApp.embedded_lc.getLines(); // Display the embedded LC along with a timestamp line[3] = theApp.getTimeStamp() + " " + elines[0]; } // Pass on voice data VoiceData voicedata = new VoiceData(); voicedata.handleVoice(theApp, dibit_buf); // If the user doesn't want to see voice frames set shouldDisplay to false if (theApp.isDisplayVoiceFrames() == false) shouldDisplay = false; // Return all done return true; } else { // Is this a Data Frame with Embedded signalling // See if its has a slot type field that passes its error check SlotType slottype = new SlotType(); boolean SLOT_TYPEres, BPTCres = false; line[0] = theApp.getTimeStamp() + " DMR Data Frame with Embedded Signalling"; colours[0] = Color.BLACK; fonts[0] = theApp.boldFont; line[2] = slottype.decode(theApp, dibit_buf); SLOT_TYPEres = slottype.isPassErrorCheck(); // If the slot type is OK try to decode the rest if (SLOT_TYPEres == true) { int dataType = slottype.returnDataType(); // PI Header if (dataType == 0) { BPTC19696 bptc19696 = new BPTC19696(); if (bptc19696.decode(dibit_buf) == true) { BPTCres = true; boolean bits[] = bptc19696.dataOut(); // Display the PI header bits as raw binary StringBuilder sb = new StringBuilder(); int ai; for (ai = 0; ai < bits.length; ai++) { if (bits[ai] == true) sb.append("1"); else sb.append("0"); } line[3] = sb.toString(); fonts[3] = theApp.boldFont; colours[3] = Color.BLACK; } } // Voice LC Header if (dataType == 1) { BPTC19696 bptc19696 = new BPTC19696(); if (bptc19696.decode(dibit_buf) == true) { BPTCres = true; boolean bits[] = bptc19696.dataOut(); // TODO : Ensure the Voice LC Headers in Embedded Data Frames pass the Reed Solomon // (12,9) error check FullLinkControl flc = new FullLinkControl(); String clines[] = new String[3]; clines = flc.decode(theApp, bits); line[3] = clines[0]; line[4] = clines[1]; line[5] = clines[2]; fonts[3] = theApp.boldFont; colours[3] = Color.BLACK; fonts[4] = theApp.boldFont; colours[4] = Color.BLACK; fonts[5] = theApp.boldFont; colours[5] = Color.BLACK; } } // Terminator with LC if (dataType == 2) { BPTC19696 bptc19696 = new BPTC19696(); if (bptc19696.decode(dibit_buf) == true) { BPTCres = true; boolean bits[] = bptc19696.dataOut(); // TODO : Ensure the Terminator LCs in Embedded Data Frames pass the Reed Solomon (12,9) // error check FullLinkControl flc = new FullLinkControl(); String clines[] = new String[3]; clines = flc.decode(theApp, bits); line[3] = clines[0]; line[4] = clines[1]; line[5] = clines[2]; fonts[3] = theApp.boldFont; colours[3] = Color.BLACK; fonts[4] = theApp.boldFont; colours[4] = Color.BLACK; fonts[5] = theApp.boldFont; colours[5] = Color.BLACK; } } // CSBK if (dataType == 3) { BPTC19696 bptc19696 = new BPTC19696(); if (bptc19696.decode(dibit_buf) == true) { crc tCRC = new crc(); boolean bits[] = bptc19696.dataOut(); // Does the CSBK pass its CRC test ? if (tCRC.crcCSBK(bits) == true) { CSBK csbk = new CSBK(); String clines[] = new String[3]; BPTCres = true; clines = csbk.decode(theApp, bits); line[3] = clines[0]; line[4] = clines[1]; line[5] = clines[2]; fonts[3] = theApp.boldFont; colours[3] = Color.BLACK; fonts[4] = theApp.boldFont; colours[4] = Color.BLACK; fonts[5] = theApp.boldFont; colours[5] = Color.BLACK; } } } // Data Header if (dataType == 6) { BPTC19696 bptc19696 = new BPTC19696(); if (bptc19696.decode(dibit_buf) == true) { crc tCRC = new crc(); boolean bits[] = bptc19696.dataOut(); // Does the Data Header pass its CRC test ? if (tCRC.crcDataHeader(bits) == true) { String clines[] = new String[3]; BPTCres = true; DMRData data = new DMRData(theApp); clines = data.decodeHeader(bits); line[3] = clines[0]; line[4] = clines[1]; line[5] = clines[2]; fonts[3] = theApp.boldFont; colours[3] = Color.BLACK; fonts[4] = theApp.boldFont; colours[4] = Color.BLACK; fonts[5] = theApp.boldFont; colours[5] = Color.BLACK; } } } // Rate ½ Data Continuation if (dataType == 7) BPTCres = true; // Rate ¾ Data Continuation if (dataType == 8) BPTCres = true; // Idle // Error check this to detect problems with the data stream if (dataType == 9) { BPTC19696 bptc19696 = new BPTC19696(); BPTCres = bptc19696.decode(dibit_buf); // If we don't want to display these then clear the lines if (theApp.isDisplayIdlePDU() == false) shouldDisplay = false; } } if ((SLOT_TYPEres == true) && (BPTCres == true)) return true; else return false; } }