mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
ant to gradle. Removes linux and windows application launch scripts and produces an executable jar with all resources included.
186 lines
4.4 KiB
Java
186 lines
4.4 KiB
Java
/*******************************************************************************
|
|
* SDR Trunk
|
|
* Copyright (C) 2014 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
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
******************************************************************************/
|
|
package io.github.dsheirer.edac;
|
|
|
|
import io.github.dsheirer.message.MessageDirection;
|
|
|
|
import java.util.BitSet;
|
|
|
|
/**
|
|
* LTR CRC checksum utility
|
|
*
|
|
* LTR message blocks are 41 bits in length as follows:
|
|
* 0 - 9: Sync
|
|
* 10 - 34: message bits
|
|
* 35 - 41: CRC-7 check bits
|
|
*
|
|
* LTR uses a CRC-7 (0xFD) with an initial fill of 0x00.
|
|
*
|
|
* CRC-7 Generating Polynomial: x7 + x6 + x5 + x4 + x3 + x2 + 1 (0xFD)
|
|
*/
|
|
public class CRCLTR
|
|
{
|
|
private static byte[] sCHECKSUMS = new byte[]
|
|
{
|
|
0x38, //Area
|
|
0x1C, //Channel 4
|
|
0x0E, //Channel 3
|
|
0x46, //Channel 2
|
|
0x23, //Channel 1
|
|
0x51, //Channel 0
|
|
0x68, //Home 4
|
|
0x75, //Home 3
|
|
0x7A, //Home 2
|
|
0x3D, //Home 1
|
|
0x1F, //Home 0
|
|
0x4F, //Group 7
|
|
0x26, //Group 6
|
|
0x52, //Group 5
|
|
0x29, //Group 4
|
|
0x15, //Group 3
|
|
0x0B, //Group 2
|
|
0x45, //Group 1
|
|
0x62, //Group 0
|
|
0x31, //Free 4
|
|
0x19, //Free 3
|
|
0x0D, //Free 2
|
|
0x07, //Free 1
|
|
0x43 //Free 0
|
|
};
|
|
|
|
/**
|
|
* Determines if message bits 10 - 34 pass the LTR CRC checksum
|
|
* contained in bits 35 - 41, using a lookup table of CRC checksum values
|
|
* derived from the CRC-7 value.
|
|
*/
|
|
public static CRC check( BitSet msg, MessageDirection direction )
|
|
{
|
|
CRC crc = CRC.UNKNOWN;
|
|
|
|
int calculated = getCalculatedChecksum( msg );
|
|
int transmitted = getTransmittedChecksum( msg );
|
|
|
|
/* Normal CRC only for Outbound Status Word */
|
|
if( direction == MessageDirection.OSW )
|
|
{
|
|
if( calculated == transmitted )
|
|
{
|
|
return CRC.PASSED;
|
|
}
|
|
}
|
|
/* Normal or Inverted CRC for Inbound Status Word */
|
|
else
|
|
{
|
|
if( ( calculated ^ 127 ) == transmitted )
|
|
{
|
|
return CRC.PASSED_INV;
|
|
}
|
|
else if( calculated == transmitted )
|
|
{
|
|
return CRC.PASSED;
|
|
}
|
|
}
|
|
|
|
return CRC.FAILED_CRC;
|
|
}
|
|
|
|
public static byte[] getChecks()
|
|
{
|
|
return sCHECKSUMS;
|
|
}
|
|
|
|
public static int getCalculatedChecksum( BitSet msg )
|
|
{
|
|
int calculated = 0;
|
|
|
|
//Iterate bits that are set and XOR running checksum with lookup value
|
|
for (int i = msg.nextSetBit( 9 ); i >= 9 && i < 33; i = msg.nextSetBit( i+1 ) )
|
|
{
|
|
calculated ^= sCHECKSUMS[ i - 9 ];
|
|
}
|
|
|
|
return calculated;
|
|
}
|
|
|
|
/**
|
|
* Returns the integer value of the 7 bit crc checksum
|
|
*/
|
|
public static int getTransmittedChecksum( BitSet msg )
|
|
{
|
|
int retVal = 0;
|
|
|
|
for( int x = 0; x < 7; x++ )
|
|
{
|
|
if( msg.get( x + 33 ) )
|
|
{
|
|
retVal += 1<<( 6 - x );
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* Determines the errant bit positions and returns them in an array of
|
|
* integer bit positions.
|
|
*
|
|
* Note: currently only detects single-bit errors
|
|
*
|
|
* @param msg to be checked for errors
|
|
* @return - array of integer positions of bits that need flipped
|
|
*/
|
|
public static int[] findBitErrors( BitSet msg )
|
|
{
|
|
int[] retVal = null;
|
|
|
|
int checksum = getTransmittedChecksum( msg );
|
|
|
|
//Remove the initial fill value (1)
|
|
checksum ^= 1;
|
|
|
|
//Iterate set message bits, removing their respective checksum value
|
|
//from the transmitted checksum, to arrive at the remainder
|
|
for (int i = msg.nextSetBit( 0 ); i >= 0 && i < 47; i = msg.nextSetBit( i+1 ) )
|
|
{
|
|
checksum ^= sCHECKSUMS[ i ];
|
|
}
|
|
|
|
//If at this point the checksum is 0, then the errant bit is the parity
|
|
//bit
|
|
if( checksum == 0 )
|
|
{
|
|
msg.flip( 62 );
|
|
}
|
|
//Otherwise, try to lookup the syndrome for a single bit error
|
|
else
|
|
{
|
|
for( int x = 0; x < 47; x++ )
|
|
{
|
|
if( checksum == sCHECKSUMS[ x ] )
|
|
{
|
|
//return this bit position
|
|
retVal = new int[ 1 ];
|
|
retVal[ 0 ] = x;
|
|
}
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
}
|