mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
#2226 DMR Decoder adds an equalizer to adjust symbol constellation balance/skew and gain to optimize symbol quadrant alignment/mapping. Reduces sync detectors from 3 to 2 and sets minimum objective channel sample rate to 19.2 kHz. (#2245)
Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -42,6 +42,7 @@ public class DecimationFilterFactory
|
||||
switch(decimationRate)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
return new RealDecimateX0Filter();
|
||||
case 2:
|
||||
return new RealDecimateX2Filter();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -20,13 +20,10 @@
|
||||
package io.github.dsheirer.dsp.filter.interpolator;
|
||||
|
||||
/**
|
||||
* Linear interpolator for values in the range: -PI > 0 > PI with awareness of phase wrapping across the
|
||||
* (+/-) PI boundary.
|
||||
* Linear interpolator.
|
||||
*/
|
||||
public class PhaseAwareLinearInterpolator
|
||||
public class LinearInterpolator
|
||||
{
|
||||
public static final float TWO_PI = (float)(Math.PI * 2.0);
|
||||
|
||||
/**
|
||||
* Calculates an interpolated value between x1 and x2 at a linear position mu between 0.0 and 1.0
|
||||
* @param x1 first value
|
||||
@@ -36,39 +33,16 @@ public class PhaseAwareLinearInterpolator
|
||||
*/
|
||||
public static float calculate(float x1, float x2, float mu)
|
||||
{
|
||||
//Detect phase wrap at the +PI/-PI boundary ... ignore opposite side of the unit circle at 0 axis
|
||||
if(x1 * x2 < -Math.PI)
|
||||
if(mu < 0 || mu > 1)
|
||||
{
|
||||
if(x1 > 0)
|
||||
{
|
||||
float value = x1 + ((TWO_PI + x2 - x1) * mu);
|
||||
|
||||
if(value > Math.PI)
|
||||
{
|
||||
return -TWO_PI + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float value = x1 + ((-TWO_PI + x2 - x1) * mu);
|
||||
|
||||
if(value < -Math.PI)
|
||||
{
|
||||
return TWO_PI + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return x1 + ((x2 - x1) * mu);
|
||||
throw new IllegalArgumentException("mu [" + mu + "] must be between 0 and 1");
|
||||
}
|
||||
|
||||
return x1 + ((x2 - x1) * mu);
|
||||
}
|
||||
|
||||
public static float calculate(float x1, float x2, double mu)
|
||||
{
|
||||
return calculate(x1, x2, (float)mu);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,16 +17,16 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.interpolator.Interpolator;
|
||||
import io.github.dsheirer.dsp.filter.interpolator.InterpolatorFactory;
|
||||
import io.github.dsheirer.dsp.fm.IDemodulator;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator base class
|
||||
* Differential demodulator base class
|
||||
*/
|
||||
public abstract class DQPSKDemodulator implements IDemodulator
|
||||
public abstract class DifferentialDemodulator implements IDemodulator
|
||||
{
|
||||
private int mSymbolRate;
|
||||
private float mSampleRate;
|
||||
@@ -43,7 +43,7 @@ public abstract class DQPSKDemodulator implements IDemodulator
|
||||
* @param sampleRate in Hertz
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulator(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulator(double sampleRate, int symbolRate)
|
||||
{
|
||||
mSampleRate = (float) sampleRate;
|
||||
mSymbolRate = symbolRate;
|
||||
@@ -51,6 +51,12 @@ public abstract class DQPSKDemodulator implements IDemodulator
|
||||
mMu = mSamplesPerSymbol % 1; //Fractional part of the samples per symbol rate
|
||||
mInterpolationOffset = (int) Math.floor(mSamplesPerSymbol) - 4; //Interpolate at the middle of 8x samples
|
||||
mBufferOverlap = (int) Math.floor(mSamplesPerSymbol) + 4;
|
||||
|
||||
while(mInterpolationOffset < 0)
|
||||
{
|
||||
mInterpolationOffset++;
|
||||
mBufferOverlap++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationManager;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationType;
|
||||
@@ -26,11 +26,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Factory for creating DQPSK demodulators
|
||||
* Factory for creating PSK differential demodulators
|
||||
*/
|
||||
public class DQPSKDemodulatorFactory
|
||||
public class DifferentialDemodulatorFactory
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(DQPSKDemodulatorFactory.class);
|
||||
private static final Logger mLog = LoggerFactory.getLogger(DifferentialDemodulatorFactory.class);
|
||||
|
||||
/**
|
||||
* Creates the optimal demodulator using calibration data to select the optimal implementation from scalar and
|
||||
@@ -39,17 +39,17 @@ public class DQPSKDemodulatorFactory
|
||||
* @param symbolRate in Hertz
|
||||
* @return demodulator instance
|
||||
*/
|
||||
public static DQPSKDemodulator getDemodulator(double sampleRate, int symbolRate)
|
||||
public static DifferentialDemodulator getDemodulator(double sampleRate, int symbolRate)
|
||||
{
|
||||
Implementation implementation = CalibrationManager.getInstance().getImplementation(CalibrationType.DQPSK_DEMODULATOR);
|
||||
Implementation implementation = CalibrationManager.getInstance().getImplementation(CalibrationType.DIFFERENTIAL_DEMODULATOR);
|
||||
|
||||
return switch(implementation)
|
||||
{
|
||||
case VECTOR_SIMD_64 -> new DQPSKDemodulatorVector64(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_128 -> new DQPSKDemodulatorVector128(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_256 -> new DQPSKDemodulatorVector256(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_512 -> new DQPSKDemodulatorVector512(sampleRate, symbolRate);
|
||||
default -> new DQPSKDemodulatorScalar(sampleRate, symbolRate); //Includes SCALAR case
|
||||
case VECTOR_SIMD_64 -> new DifferentialDemodulatorVector64(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_128 -> new DifferentialDemodulatorVector128(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_256 -> new DifferentialDemodulatorVector256(sampleRate, symbolRate);
|
||||
case VECTOR_SIMD_512 -> new DifferentialDemodulatorVector512(sampleRate, symbolRate);
|
||||
default -> new DifferentialDemodulatorScalar(sampleRate, symbolRate); //Includes SCALAR case
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,25 +17,25 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator that uses scalar calculations for demodulating the sample stream.
|
||||
* Differential demodulator that uses scalar calculations for demodulating the sample stream.
|
||||
*/
|
||||
public class DQPSKDemodulatorScalar extends DQPSKDemodulator
|
||||
public class DifferentialDemodulatorScalar extends DifferentialDemodulator
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DQPSKDemodulatorScalar.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorScalar.class);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulatorScalar(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulatorScalar(double sampleRate, int symbolRate)
|
||||
{
|
||||
super(sampleRate, symbolRate);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
@@ -27,11 +27,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator that uses Vector SIMD 128 calculations for demodulating the sample stream.
|
||||
* Differential demodulator that uses Vector SIMD 128 calculations for demodulating the sample stream.
|
||||
*/
|
||||
public class DQPSKDemodulatorVector128 extends DQPSKDemodulator
|
||||
public class DifferentialDemodulatorVector128 extends DifferentialDemodulator
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DQPSKDemodulatorVector128.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector128.class);
|
||||
private static final VectorSpecies<Float> VECTOR_SPECIES = FloatVector.SPECIES_128;
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,7 @@ public class DQPSKDemodulatorVector128 extends DQPSKDemodulator
|
||||
* @param sampleRate in Hertz
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulatorVector128(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulatorVector128(double sampleRate, int symbolRate)
|
||||
{
|
||||
super(sampleRate, symbolRate);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
@@ -25,9 +25,9 @@ import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator that uses Vector SIMD calculations for demodulating the sample stream.
|
||||
* Differential demodulator that uses Vector SIMD calculations for demodulating the sample stream.
|
||||
*/
|
||||
public class DQPSKDemodulatorVector256 extends DQPSKDemodulator
|
||||
public class DifferentialDemodulatorVector256 extends DifferentialDemodulator
|
||||
{
|
||||
private static final VectorSpecies<Float> VECTOR_SPECIES = FloatVector.SPECIES_256;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class DQPSKDemodulatorVector256 extends DQPSKDemodulator
|
||||
* @param sampleRate in Hertz
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulatorVector256(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulatorVector256(double sampleRate, int symbolRate)
|
||||
{
|
||||
super(sampleRate, symbolRate);
|
||||
}
|
||||
@@ -68,7 +68,6 @@ public class DQPSKDemodulatorVector256 extends DQPSKDemodulator
|
||||
//Append new samples to the residual samples from the previous buffer.
|
||||
System.arraycopy(i, 0, mIBuffer, bufferOverlap, sampleLength);
|
||||
System.arraycopy(q, 0, mQBuffer, bufferOverlap, sampleLength);
|
||||
//mIDecoded, mQDecoded and mPhase will be filled below during the decoding process.
|
||||
|
||||
float[] interpolatedI = new float[VECTOR_SPECIES.length()];
|
||||
float[] interpolatedQ = new float[VECTOR_SPECIES.length()];
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
@@ -27,11 +27,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator that uses Vector SIMD 512 calculations for demodulating the sample stream.
|
||||
* Differential demodulator that uses Vector SIMD 512 calculations for demodulating the sample stream.
|
||||
*/
|
||||
public class DQPSKDemodulatorVector512 extends DQPSKDemodulator
|
||||
public class DifferentialDemodulatorVector512 extends DifferentialDemodulator
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DQPSKDemodulatorVector512.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector512.class);
|
||||
private static final VectorSpecies<Float> VECTOR_SPECIES = FloatVector.SPECIES_512;
|
||||
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ public class DQPSKDemodulatorVector512 extends DQPSKDemodulator
|
||||
*
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulatorVector512(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulatorVector512(double sampleRate, int symbolRate)
|
||||
{
|
||||
super(sampleRate, symbolRate);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.dsp.psk.dqpsk;
|
||||
package io.github.dsheirer.dsp.psk.demod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
@@ -27,11 +27,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* DQPSK demodulator that uses Vector SIMD 64 calculations for demodulating the sample stream.
|
||||
* Differential demodulator that uses Vector SIMD 64 calculations for demodulating the sample stream.
|
||||
*/
|
||||
public class DQPSKDemodulatorVector64 extends DQPSKDemodulator
|
||||
public class DifferentialDemodulatorVector64 extends DifferentialDemodulator
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DQPSKDemodulatorVector64.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector64.class);
|
||||
private static final VectorSpecies<Float> VECTOR_SPECIES = FloatVector.SPECIES_64;
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,7 @@ public class DQPSKDemodulatorVector64 extends DQPSKDemodulator
|
||||
* @param sampleRate in Hertz
|
||||
* @param symbolRate symbols per second
|
||||
*/
|
||||
public DQPSKDemodulatorVector64(double sampleRate, int symbolRate)
|
||||
public DifferentialDemodulatorVector64(double sampleRate, int symbolRate)
|
||||
{
|
||||
super(sampleRate, symbolRate);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 Dennis Sheirer
|
||||
*
|
||||
* 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
|
||||
@@ -21,10 +21,10 @@ package io.github.dsheirer.dsp.symbol;
|
||||
|
||||
public enum Dibit
|
||||
{
|
||||
D01_PLUS_3(false, true, 1, 4, 1, (float)(Math.PI / 4 * 3), (float)-Math.sin(Math.toRadians(45)), (float)Math.sin(Math.toRadians(45))),
|
||||
D00_PLUS_1(false, false, 0, 0, 0, (float)(Math.PI / 4.0), (float)Math.sin(Math.toRadians(45)), (float)Math.sin(Math.toRadians(45))),
|
||||
D10_MINUS_1(true, false, 2, 8, 2, (float)(Math.PI / -4.0), (float)Math.sin(Math.toRadians(45)), (float)-Math.sin(Math.toRadians(45))),
|
||||
D11_MINUS_3(true, true, 3, 12, 3, (float)(Math.PI / 4 * -3), (float)-Math.sin(Math.toRadians(45)), (float)-Math.sin(Math.toRadians(45)));
|
||||
D01_PLUS_3(false, true, 1, 4, 1, (float)((Math.PI / 4) * 3)),
|
||||
D00_PLUS_1(false, false, 0, 0, 0, (float)(Math.PI / 4)),
|
||||
D10_MINUS_1(true, false, 2, 8, 2, (float)(Math.PI / -4)),
|
||||
D11_MINUS_3(true, true, 3, 12, 3, (float)((Math.PI / 4) * -3));
|
||||
|
||||
private boolean mBit1;
|
||||
private boolean mBit2;
|
||||
@@ -32,8 +32,6 @@ public enum Dibit
|
||||
private int mHighValue;
|
||||
private int mValue;
|
||||
private float mPhase;
|
||||
private float mIdealI;
|
||||
private float mIdealQ;
|
||||
|
||||
/**
|
||||
* Dibit constructor.
|
||||
@@ -43,10 +41,8 @@ public enum Dibit
|
||||
* @param highValue integer value of the high order bit
|
||||
* @param value integer value combined of both bits.
|
||||
* @param phase optimal phase value for this symbol when transmitted.
|
||||
* @param idealI ideal inphase value for this symbol when transmitted.
|
||||
* @param idealQ ideal quadrature value for this symbol when transmitted.
|
||||
*/
|
||||
Dibit(boolean bit1, boolean bit2, int lowValue, int highValue, int value, float phase, float idealI, float idealQ)
|
||||
Dibit(boolean bit1, boolean bit2, int lowValue, int highValue, int value, float phase)
|
||||
{
|
||||
mBit1 = bit1;
|
||||
mBit2 = bit2;
|
||||
@@ -54,8 +50,6 @@ public enum Dibit
|
||||
mHighValue = highValue;
|
||||
mValue = value;
|
||||
mPhase = phase;
|
||||
mIdealI = idealI;
|
||||
mIdealQ = idealQ;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,24 +69,6 @@ public enum Dibit
|
||||
return mPhase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideal inphase value when this symbol is transmitted.
|
||||
* @return ideal I
|
||||
*/
|
||||
public float getIdealI()
|
||||
{
|
||||
return mIdealI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideal quadrature value when this symbol is transmitted.
|
||||
* @return ideal Q
|
||||
*/
|
||||
public float getIdealQ()
|
||||
{
|
||||
return mIdealQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowable transition state 1 for trellis coded modulation. Indicates
|
||||
* the dibit that differs from this dibit in the LSB bit position.
|
||||
|
||||
Reference in New Issue
Block a user