Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2117 DMR simplex transmissions now frame correctly and added additio… #2118

Merged
merged 1 commit into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ private void dispatchBufferA()
mBufferATimeslot = cach.getTimeslot();
mBufferBTimeslot = (mBufferATimeslot == 1 ? 2 : 1);
}
else if(mBufferAPattern.isMobileStationSyncPattern())
{
mBufferATimeslot = 1;
mBufferBTimeslot = 2;
if(mBufferBPattern == DMRSyncPattern.UNKNOWN)
{
mBufferBPattern = DMRSyncPattern.DIRECT_EMPTY_TIMESLOT;
}
}

dispatch(DMRMessageFactory.create(mBufferAPattern, message, cach, getTimestamp(), mBufferATimeslot));

Expand All @@ -156,8 +165,8 @@ private void dispatchBufferA()
mBufferAPattern = DMRSyncPattern.getNextVoice(mBufferAPattern);
}

//Automatically trigger buffer B burst collection if it is collecting a voice super frame.
if(mBufferBPattern.isVoicePattern())
//Automatically trigger buffer B burst collection if it is collecting a voice super frame or mobile direct.
if(mBufferBPattern.isVoicePattern() || mBufferBPattern == DMRSyncPattern.DIRECT_EMPTY_TIMESLOT)
{
mAssemblingBurst = true;
mBufferAActive = false;
Expand Down Expand Up @@ -205,6 +214,16 @@ private void dispatchBufferB()
mBufferBTimeslot = cach.getTimeslot();
mBufferATimeslot = (mBufferBTimeslot == 1 ? 2 : 1);
}
else if(mBufferBPattern.isMobileStationSyncPattern())
{
mBufferBTimeslot = 1;
mBufferATimeslot = 2;

if(mBufferAPattern == DMRSyncPattern.UNKNOWN)
{
mBufferAPattern = DMRSyncPattern.DIRECT_EMPTY_TIMESLOT;
}
}

dispatch(DMRMessageFactory.create(mBufferBPattern, burst, cach, getTimestamp(), mBufferBTimeslot));

Expand All @@ -215,8 +234,8 @@ private void dispatchBufferB()
mBufferBPattern = DMRSyncPattern.getNextVoice(mBufferBPattern);
}

//Automatically trigger buffer A burst collection if it is collecting a voice super frame.
if(mBufferAPattern.isVoicePattern())
//Automatically trigger buffer A burst collection if it is collecting a voice super frame or mobile direct.
if(mBufferAPattern.isVoicePattern() || mBufferAPattern == DMRSyncPattern.DIRECT_EMPTY_TIMESLOT)
{
mAssemblingBurst = true;
mBufferAActive = true;
Expand Down
131 changes: 130 additions & 1 deletion src/main/java/io/github/dsheirer/module/decode/dmr/bptc/BPTCBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ public BPTCBase(IHamming hamming, int columnCount, int rowCount)
mRowCount = rowCount;
}

/**
* Used by the correct() method to employ an optional attempt to correct multiple row, two-bit errors where each
* set of row errors don't shadow each other based on a test where the column cardinality is twice the row
* cardinality. This is probably not mathematically correct and should only be enabled when the decoded message
* payload has a good CRC check after the extraction (ie. only use for FLC).
* @return true if enabled, false (default) otherwise
*/
protected boolean canCorrectMultiRow2BitErrors()
{
return false;
}

/**
* Performs error detection and correction.
* @param message to correct
Expand Down Expand Up @@ -100,6 +112,28 @@ public boolean correct(CorrectedBinaryMessage message)
}
}

//3: fix single row, multi-column errors
if(rows.cardinality() == 1 && !columns.isEmpty())
{
List<Integer> solution = correctMultiBitErrors(rows.nextSetBit(0), message, columns, rows);

if(!solution.isEmpty())
{
correctedIndexes.addAll(solution);
}
}

//4: fix one or more rows that each have 2 bit errors, not shadowing each other.
if(canCorrectMultiRow2BitErrors() && rows.cardinality() > 0 && columns.cardinality() / rows.cardinality() == 2)
{
List<Integer> solution = correctMultipleRowTwoBitErrorsNotShadowing(columns, rows, message);

if(!solution.isEmpty())
{
correctedIndexes.addAll(solution);
}
}

if(columns.isEmpty() && rows.isEmpty())
{
message.incrementCorrectedBitCount(correctedIndexes.size());
Expand Down Expand Up @@ -204,6 +238,90 @@ public BinaryMessage getColumnErrors(CorrectedBinaryMessage message)
return columns;
}

/**
* Calculates the indices that make up the intersections of the row and column errors.
* @param rows bitmap indicating rows with errors
* @param columns bitmap indicating columns with errors
* @return set of intersection indices.
*/
public List<Integer> getIntersectionIndices(BinaryMessage columns, BinaryMessage rows)
{
List<Integer> intersections = new ArrayList<>();

for(int row = rows.nextSetBit(0); row >= 0 && row < mRowCount; row = rows.nextSetBit(row + 1))
{
for(int column = columns.nextSetBit(0); column >= 0 && column < mColumnCount; column = columns.nextSetBit(column + 1))
{
intersections.add(getIndex(column, row));
}
}

return intersections;
}

/**
* Calculates the indices that make up the intersections of the row and column errors.
* @param rows bitmap indicating rows with errors
* @param columns bitmap indicating columns with errors
* @return set of intersection indices.
*/
public List<Integer> getIntersectionIndices(BinaryMessage columns, int row)
{
List<Integer> intersections = new ArrayList<>();

for(int column = columns.nextSetBit(0); column >= 0 && column < mColumnCount; column = columns.nextSetBit(column + 1))
{
intersections.add(getIndex(column, row));
}

return intersections;
}

/**
* Correct multiple rows with two-bit errors each where the error columns are not shadowing each other.
* @param columns error map
* @param rows error map
* @param message to correct
* @return corrected indices
*/
public List<Integer> correctMultipleRowTwoBitErrorsNotShadowing(BinaryMessage columns, BinaryMessage rows,
CorrectedBinaryMessage message)
{
List<Integer> solution = new ArrayList<>();

for(int row = rows.nextSetBit(0); row >= 0 && row < mRowCount; row = rows.nextSetBit(row + 1))
{
for(int column1 = columns.nextSetBit(0); column1 >= 0; column1 = columns.nextSetBit(column1 + 1))
{
for(int column2 = columns.nextSetBit(column1 + 1); column2 >= 0; column2 = columns.nextSetBit(column2 + 1))
{
int index1 = getIndex(column1, row);
int index2 = getIndex(column2, row);
message.flip(index1);
message.flip(index2);

if(isRowCorrect(row, message))
{
solution.add(index1);
solution.add(index2);
columns.clear(column1);
columns.clear(column2);
rows.clear(row);
column1 = mColumnCount;
column2 = mColumnCount;
}
else
{
message.flip(index1);
message.flip(index2);
}
}
}
}

return solution;
}

/**
* Corrects single bit errors in each row using only the Hamming error index.
* @param row to correct
Expand Down Expand Up @@ -313,7 +431,18 @@ public void logErrorMap(CorrectedBinaryMessage message)
int offset = row * mColumnCount;
sb.append("Row ").append(row).append(": ");
sb.append(message.getSubMessage(offset, offset + mColumnCount));
sb.append(" ").append(offset).append(":").append(offset + mColumnCount).append("\n");
sb.append(" (").append(offset).append(":").append(offset + mColumnCount).append(")");

for(int error = offset; error < offset + mColumnCount; error++)
{
if(message.get(error))
{
sb.append(" ").append(error);
}
}

sb.append("\n");

}

System.out.println(sb);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ public BPTC_128_77()
super(new Hamming16(), 16, 8);
}

/**
* Allow the base class to attempt to correct multiple rows of 2-bit errors each
*/
@Override
protected boolean canCorrectMultiRow2BitErrors()
{
return true;
}

/**
* Performs error detection and correction and extracts the payload from the BPTC encoded message.
* @param message with BPTC encoding.
Expand Down Expand Up @@ -93,15 +102,15 @@ public CorrectedBinaryMessage deinterleave(BinaryMessage interleaved)
public static void main(String[] args)
{
BPTC_128_77 bptc = new BPTC_128_77();
String deinterleavedRaw = "00000000000000000000000000000000001000000010010101011001001000010000000000000000000000000110101000010110111100010000111110011111";
String deinterleavedRaw = "00000100000101010000001000111000100000000001001101000010001001000000000010101000111100000000001000011000100010110010100100100000";
CorrectedBinaryMessage deinterleaved = new CorrectedBinaryMessage(BinaryMessage.load(deinterleavedRaw));

String deinterleavedReference = "00000000000000000000000000000000000000000010011100011001001000110000000000000000000000000110101000010110111100010000111110011111"; //No errors
String deinterleavedReference = "00000100000101010000011000111001100000000001001101000010001101100000000110101000111100000000101000011000100010110010100100100000"; //No errors
CorrectedBinaryMessage deinterleavedReferenceMessage = new CorrectedBinaryMessage(BinaryMessage.load(deinterleavedReference));

String interleaved = "00000000000000000000000000010010000100010000001000000010000100010000001100000110001101100000001100000101001000010010010100110011"; //Under test
CorrectedBinaryMessage interleavedMessage = new CorrectedBinaryMessage(BinaryMessage.load(interleaved));
// String interleaved = "00000000000000000000000000010010000100010000001000000010000100010000001100000110001101100000001100000101001000010010010100110011"; //Under test
// CorrectedBinaryMessage interleavedMessage = new CorrectedBinaryMessage(BinaryMessage.load(interleaved));
// CorrectedBinaryMessage deinterleaved = deinterleave(interleavedMessage);
CorrectedBinaryMessage deinterleaved = new CorrectedBinaryMessage(BinaryMessage.load(deinterleavedRaw));


String deinterleavedUncorrected = deinterleaved.toString();
Expand All @@ -120,6 +129,7 @@ public static void main(String[] args)
System.out.println("--------------------------------");
System.out.println("Residual Error Map:");
bptc.logErrorMap(deinterleaved);
System.out.println("Columns:" + bptc.getColumnErrors(deinterleaved) + " Rows:" + bptc.getRowErrors(deinterleaved));
System.out.println("--------------------------------");
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,12 @@ private FullLCMessage decode2(BinaryMessage message, long timestamp, int timeslo
{
CorrectedBinaryMessage extractedMessage = mBPTC.extract(message);
FullLCMessage flco = LCMessageFactory.createFull(extractedMessage, timestamp, timeslot, false);
flco.setValid(extractedMessage.getCorrectedBitCount() >= 0);

if(extractedMessage.getCorrectedBitCount() < 0)
{
flco.setValid(false);
}

return flco;
}

Expand Down
Loading