//
//  Copyright © 2002, RESON Inc. All Rights Reserved.
//
//  No part of this file may be reproduced or transmitted in any form or by
//  any means, electronic or mechanical, including photocopy, recording, or
//  information storage or retrieval system, without permission in writing
//  from RESON Inc.
//
//  Filename:   BlueFinNetworkFrame.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#include "StdAfx.h"
#include "BlueFinNetworkFrame.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// CBlueFinNetworkFrame class implementation.

CBlueFinNetworkFrame::CBlueFinNetworkFrame( const BYTE          *pbyMessage,
                                            const unsigned long &rulBytes )

                     :m_ulHeaderSize( sizeof( tagBLUEFINNETWORKHEADER ) )
{
    m_bValid    = false;
    m_psHeader  = NULL;
    m_pbyHeader = NULL;

    ASSERT( pbyMessage != NULL );
    ASSERT( rulBytes   >  0UL );

    if ( ( pbyMessage != NULL ) && ( rulBytes >= m_ulHeaderSize ) )
    {
        m_pbyHeader = const_cast<BYTE *>( pbyMessage );
        m_psHeader  = reinterpret_cast<BLUEFINNETWORKHEADER *>( m_pbyHeader );

        const char * pcDataSection       = reinterpret_cast<const char *>( &pbyMessage[ m_ulHeaderSize ] );
        const int    iBytesInDataSection = static_cast<int>( rulBytes - m_ulHeaderSize );

        //{
        //    PTIME7K psTime = reinterpret_cast<TIME7K *>( &(m_psHeader->m_byTimeStamp[ 0 ]));
        //    TRACE( _T( "Julian day is: %u\n" ), psTime->m_unDay );
        //}

        m_bValid = ( CheckSumCRC32( pcDataSection, iBytesInDataSection ) == static_cast<int>( m_psHeader->m_ulChecksum ) );
    }

    ASSERT( m_bValid );
}

CBlueFinNetworkFrame::~CBlueFinNetworkFrame( void )
{
    m_bValid   = false;
    m_psHeader = NULL;
}

bool CBlueFinNetworkFrame::IsValid( void ) const
{
    return m_bValid;
}

CBlueFinNetworkFrame::EDATATYPE CBlueFinNetworkFrame::DataType( void ) const
{
    ASSERT( m_psHeader != NULL );

    return static_cast<EDATATYPE>( m_psHeader->m_ulDataType );
}

CBlueFinNetworkFrame::operator BLUEFINNETWORKHEADER const * ( void ) const
{
    // Pointer to network header.

    ASSERT( m_psHeader != NULL );

    return m_psHeader;
}

CBlueFinNetworkFrame::operator BYTE const * ( void ) const
{
    // Pointer to trailing data as raw byte pointer.

    ASSERT( m_psHeader != NULL );

    return  ( &(reinterpret_cast<const BYTE *>( m_psHeader ))[ m_ulHeaderSize ] );
}

CBlueFinNetworkFrame::operator TIME7K const * ( void ) const
{
    ASSERT( m_psHeader != NULL );

    return ( reinterpret_cast<const TIME7K *>( m_psHeader->m_byTimeStamp ) );
}

CBlueFinNetworkFrame::operator BLUEFINNAVIGATIONMESSAGE const * ( void ) const
{
    ASSERT( m_pbyHeader != NULL );

    return  ( reinterpret_cast<const BLUEFINNAVIGATIONMESSAGE *>( &m_pbyHeader[ m_ulHeaderSize ] ) );
}

CBlueFinNetworkFrame::operator BLUEFINENVIRONMENTMESSAGE  const * (   void )  const
{
    ASSERT( m_pbyHeader != NULL );

    return  ( reinterpret_cast<const BLUEFINENVIRONMENTMESSAGE *>( &m_pbyHeader[ m_ulHeaderSize ] ) );
}

///////////////////////////////////////////////////////////////////////////////
// Private helpers.

inline
int CBlueFinNetworkFrame::CheckSumCRC32( const char *pcBuffer, const int &riBufferLength ) const
{
    // Routine supplied by BlueFin w/ only slight modifications made.

 	const char * pcNext = pcBuffer;
 	const char * pcEnd  = pcBuffer + riBufferLength;

 	const int c1    = 52845;
 	const int c2    = 22719;
 	int r           = 55665;
 	int iChecksum   = 0;

 	for ( ; pcNext < pcEnd; ++pcNext )
 	{
 		unsigned char cipher = static_cast<unsigned char>( ( (*pcNext) ^ (r >> 8)) );
 		r = (cipher + r) * c1 + c2;
 		iChecksum += cipher;
 	}

 	return iChecksum;
}

