VirtualComponentInterface.cpp 6.08 KB
//////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------//
//-- Copyright 2001 VAutomation Inc. Nashua NH USA. All rights reserved.//
//-- This software is provided under license and contains proprietary   //
//-- and confidential material which is the property of VAutomation Inc.//
//-- HTTP://www.vautomation.com											//
//----------------------------------------------------------------------//
//////////////////////////////////////////////////////////////////////////


// VirtualComponentInterface.cpp: implementation of the CVirtualComponentInterface class.
//
//////////////////////////////////////////////////////////////////////
#include "DeviceSpecificInclude.h"
#include "VirtualComponentInterface.h"
#include <memory.h> 
#include <string.h>
#include <stdio.h>


struct DeviceInfo
{
	char m_device_name[256];
	AddressType m_device_offset_address;
};

///////////////////////////////////////////////////////////////////////
// Example of Two address offsets with names
///////////////////////////////////////////////////////////////////////


CVirtualComponentInterface::CVirtualComponentInterface( )
{
	m_internal_info_pointer = new DeviceInfo;
}

CVirtualComponentInterface::~CVirtualComponentInterface()
{
	delete m_internal_info_pointer;
}

bool CVirtualComponentInterface::SetAttribute( char* attribute_name, char* value )
{
	return( true );
}

bool CVirtualComponentInterface::GetAttribute( char* attribute_name, char* value )
{
	return( true );
}

bool CVirtualComponentInterface::Create( char *device_name, VCDeviceType device_type  )
{

	AddressType offset = 0x0000;

	strcpy(&(((DeviceInfo*)(m_internal_info_pointer))->m_device_name[0]), device_name );

	if( strcmp(DEVICE_1_NAME, device_name) == 0 )
	{
		offset = DEVICE_1_OFFSET_ADDRESS;
	}
	else
	if( strcmp(DEVICE_2_NAME, device_name) == 0 )
	{
		offset = DEVICE_2_OFFSET_ADDRESS;
	}
	else
	{
		printf("Error: Unknown device name.\n");
		return(false);
	}

	((DeviceInfo*)(m_internal_info_pointer))->m_device_offset_address = offset;

	return(true);
}

extern void PrintStringStdioLFAll( char* print_string );


//#define ARC_TANGENT_5_AND_NEWER


#ifdef ARC_TANGENT_5_AND_NEWER //The old arc can not do a byte write with the DMP interface.

bool CVirtualComponentInterface::WriteBuffer( const AddressType& dest_address, const AddressType& src_address, const UnSignedLong& byte_count , const bool asynchronous_operation)
{
	AddressType dest_offset_address = (((DeviceInfo*)(m_internal_info_pointer))->m_device_offset_address) + dest_address;
	volatile unsigned char* src_data = (volatile unsigned char*)src_address;
	volatile unsigned char* dest_data = (volatile unsigned char*)dest_offset_address;
	
	for( UnSignedLong i=0; i<byte_count; i++ )
	{

#ifdef TURN_ON_DMP_RW_DISPLAY

		char buffer[200];
		sprintf(&(buffer[0]),"                         <DMP:WriteByte: DestAddress=%10lXh SourceDataByte=%10lXh> ", &(dest_data[i]), src_data[i] );
		PrintStringStdioLFAll( &(buffer[0]) );

#endif

		//This will create a warning to get around the dmp problems.
		dest_data[i] = src_data[i]; 
	}

	return(true);
}

#else //NOT ARC_TANGENT_5_AND_NEWER

bool CVirtualComponentInterface::WriteBuffer( const AddressType& dest_address, const AddressType& src_address, const UnSignedLong& byte_count , const bool asynchronous_operation)
{
	//Assume the writes are never larger than 32 bits.
	if( byte_count > 4 )
	{
		return( false );
	}

	//Get the addres of the bytes we want to write
	AddressType dest_offset_address = (((DeviceInfo*)(m_internal_info_pointer))->m_device_offset_address) + dest_address;

	//Get the quad aligned address of the bytes we want to write.
	volatile unsigned long *quad_data_ptr = ((volatile unsigned long*)(dest_offset_address - (dest_offset_address%4)));

	//Read the whole quad aligned word into a word
	volatile unsigned long org_quad_data = *quad_data_ptr;
	volatile unsigned long quad_data = org_quad_data;

	//Get a char pointer to the word we want to change.
	volatile unsigned char* quad_data_char_ptr = (volatile unsigned char*) (&quad_data);

	//Get a char pointer to the source, the data we want to put in the word.
	volatile unsigned char* src_data = (volatile unsigned char*)src_address;

	//Loop over the byte we want to replace.
	for( UnSignedLong i=0; i<byte_count; i++ )
	{
		quad_data_char_ptr[i + (dest_offset_address%4)] = src_data[i];
	}

	//Write the whole word back to the interface
	*quad_data_ptr = quad_data;

#ifdef TURN_ON_DMP_RW_DISPLAY

		char buffer[200];
		sprintf(&(buffer[0]),"                         <DMP:WriteByte: DestAddress=%10lXh OrgQuadData=%10lXh NewQuadData=%10lXh> ", quad_data_ptr, org_quad_data, quad_data );
		PrintStringStdioLFAll( &(buffer[0]) );

#endif

	return(true);
}

#endif //ARC_TANGENT_5_AND_NEWER


bool CVirtualComponentInterface::ReadBuffer( const AddressType& dest_address, const AddressType& src_address, const UnSignedLong& byte_count, const bool asynchronous_operation)
{

	volatile unsigned char* dest_data = (volatile unsigned char*)(dest_address);
	AddressType src_offset_address = ((((DeviceInfo*)(m_internal_info_pointer))->m_device_offset_address) + src_address) - ( src_address % 4 );
	volatile unsigned long read_data = *((volatile unsigned long*)src_offset_address); //Read the quad in 
	volatile unsigned char* aligned_read_data = (((volatile unsigned char*)(&read_data)) + ( src_address % 4 ));//Read the first byte 

	
	for( UnSignedLong i=0; i<byte_count; i++ )
	{
		dest_data[i] = aligned_read_data[i]; 

#ifdef TURN_ON_DMP_RW_DISPLAY

		char buffer[200];
		sprintf(&(buffer[0]),"                         <DMP:ReadByte: ReadDataByte=%10lXh SourceAddress=%10lXh QuadReadData=%10lXh> ", dest_data[i], src_offset_address + ( src_address % 4 ) + i, read_data);
		PrintStringStdioLFAll( &(buffer[0]) );

#endif

	}

	return(true);
}

bool CVirtualComponentInterface::SetCallbacks( ReadOperationCallbackType *read_func, WriteOperationCallbackType *write_func )
{
	//This will be device specific, or not used
	return(true);
}

const char *CVirtualComponentInterface::DeviceGetName()
{
	return( &(((DeviceInfo*)(m_internal_info_pointer))->m_device_name[0]) );
}