/*******************************************************************************
* 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 module.decode.mdc1200;
import message.Message;
import sample.Broadcaster;
import sample.Listener;
import alias.AliasList;
import bits.BinaryMessage;
public class MDCMessageProcessor implements Listener<BinaryMessage>
{
private static int sMESSAGE_LENGTH = 112;
private Broadcaster<Message> mBroadcaster = new Broadcaster<Message>();
private AliasList mAliasList;
public MDCMessageProcessor( AliasList aliasList )
{
mAliasList = aliasList;
}
public void dispose()
{
mBroadcaster.dispose();
}
@Override
public void receive( BinaryMessage buffer )
{
/**
* De-interleave the 112 bits of message one, starting after the sync
* pattern
*/
deinterleave( buffer, 40 );
/**
* For simplicity, we also deinterleave message 2, which may or may not
* be there, starting after the initial sync ( 0 - 39 ) and the initial
* message ( 40 - 151 ) and the second sync ( 152 - 191 ).
*/
deinterleave( buffer, 192 );
/**
* Wrap the buffer in a message along with the designated alias list
* and send it on its merry way
*/
MDCMessage message = new MDCMessage( buffer, mAliasList );
mBroadcaster.receive( message );
}
public void addMessageListener( Listener<Message> listener )
{
mBroadcaster.addListener( listener );
}
public void removeMessageListener( Listener<Message> listener )
{
mBroadcaster.removeListener( listener );
}
/**
* Removes NRZ-I encoding from the entire buffer. Assumes that the initial
* bit will be a 0 after decode, despite what is currently in the buffer,
* in order to maintain correct polarity of the decoded message.
*/
private void removeNRZIEncoding( BinaryMessage buffer )
{
/**
* Clear bit position 0, the first bit of the sync pattern, to start
* the decode with the correct polarity
*/
buffer.clear( 0 );
/**
* Set each bit according to the state of the previous bit using XOR
* as follows:
*
* 0 = same as previous state
* 1 = inverse of previous state
*/
for( int x = 1; x < buffer.size(); x++ )
{
if( buffer.get( x - 1 ) ^ buffer.get( x ) )
{
buffer.set( x );
}
else
{
buffer.clear( x );
}
}
}
/**
* Deinterleaves a 112-bit packet, starting at the offset into the buffer
*/
private void deinterleave( BinaryMessage buffer, int offset )
{
if( buffer.size() < sMESSAGE_LENGTH + offset )
{
throw new IllegalArgumentException( "MDCMessageProcessor - "
+ "cannot deinterleave message - message buffer too short" );
}
BinaryMessage deinterleaved = new BinaryMessage( 112 );
int deinterleavedPointer = 0;
for( int column = 0; column < 16; column++ )
{
for( int row = 0; row < 7; row++ )
{
if( buffer.get( ( row * 16 ) + column + offset ) )
{
deinterleaved.set( deinterleavedPointer );
}
deinterleavedPointer++;
}
}
//Overlay the deinterleaved bits back onto the source message and
//return it
buffer.clear( offset, offset + sMESSAGE_LENGTH );
for( int x = 0; x < sMESSAGE_LENGTH; x++ )
{
if( deinterleaved.get( x ) )
{
buffer.set( x + offset );
}
else
{
buffer.clear( x + offset );
}
}
}
}