Crestron Samsung Module - Modification Help

Hi all,

I am not a SIMPL+ wiz by any means. I discovered that the Crestron module for most Samsung TVs has a bug of sorts.

The Ex-Link protocol specifies for direct channel tuning, you take the major channel number and multiply by 4 and convert to hex, and that's byte 5. Minor channel is byte 6. Byte 4 is \x80 for DTV.

The SIMPL+ processor doesn't account for channel numbers higher than 63, where channel 64 * 4 = 256 -> \x100.

The correct way to handle this is to put the "1" in byte 4 so it is \x81. The remainder is byte 5 and minor is still byte 6.

All commands need a checksum.

Below is the SIMPL+ processor. Any ideas how to modify this to handle higher channel numbers?

/*******************************************************************************************
  SIMPL+ Module Information
  (Fill in comments below)
*******************************************************************************************/
/*
Dealer Name: Crestron Electronics, Inc.
System Name:
System Number:
Programmer: LP
Comments:
*/

/*******************************************************************************************
  Compiler Directives
  (Uncomment and declare compiler directives as needed)
*******************************************************************************************/
// #ENABLE_DYNAMIC
#SYMBOL_NAME "Samsung UN55ES8000 v1.0 Processor"
// #HINT ""
// #DEFINE_CONSTANT
// #CATEGORY "" 
// #DEFAULT_VOLATILE
#PRINT_TO_TRACE
// #DIGITAL_EXPAND 
// #ANALOG_SERIAL_EXPAND 
// #OUTPUT_SHIFT 
// #HELP_PDF_FILE ""
#DEFAULT_NONVOLATILE
#ENABLE_STACK_CHECKING
#ENABLE_TRACE

#HELP_BEGIN
To be used with the Samsung UN55ES8000 v1.0.umc module only.
Not to be used as a stand-alone module.
#HELP_END


/*******************************************************************************************
  Include Libraries
  (Uncomment and include additional libraries as needed)
*******************************************************************************************/
// #CRESTRON_LIBRARY ""
// #USER_LIBRARY ""

/*******************************************************************************************
  DIGITAL, ANALOG and SERIAL INPUTS and OUTPUTS
  (Uncomment and declare inputs and outputs as needed)
*******************************************************************************************/
ANALOG_INPUT	Volume_Set_Value,	
				ThreeD_View_Point_Value,
				ThreeD_Depth_Value;
DIGITAL_INPUT 	ATV, DTV, KP[13];

STRING_INPUT String_To_Send[10];
ANALOG_INPUT Current_Channel;
ANALOG_INPUT Current_Channel_Sub;
ANALOG_INPUT Current_Volume;

// BUFFER_INPUT 
// DIGITAL_OUTPUT 
// ANALOG_OUTPUT 

STRING_OUTPUT Channel_Text, Volume_Text, To_Device; 

/*******************************************************************************************
  SOCKETS
  (Uncomment and define socket definitions as needed)
*******************************************************************************************/
// TCP_CLIENT
// TCP_SERVER
// UDP_SOCKET

/*******************************************************************************************
  Parameters
  (Uncomment and declare parameters as needed)
*******************************************************************************************/
// INTEGER_PARAMETER
// SIGNED_INTEGER_PARAMETER
// LONG_INTEGER_PARAMETER
// SIGNED_LONG_INTEGER_PARAMETER
// STRING_PARAMETER

/*******************************************************************************************
  Parameter Properties
  (Uncomment and declare parameter properties as needed)
*******************************************************************************************/
/*
#BEGIN_PARAMETER_PROPERTIES parameter_variable, parameter_variable, ...
   // propValidUnits = // unitString or unitDecimal|unitHex|unitPercent|unitCharacter|unitTime|unitTicks;
   // propDefaultUnit = // unitString, unitDecimal, unitHex, unitPercent, unitCharacter, unitTime or unitTicks;
   // propBounds = lower_bound , upper_bound;
   // propDefaultValue = ;  // or, propDefaultValue = "";
   // propList = // { "value" , "label" } , { "value" , "label" } , ... ;
   // propShortDescription = "status_bar_hint_text";
   // #BEGIN_PROP_FULL_DESCRIPTION  line_1...  line_2...  line_n  #END_PROP_FULL_DESCRIPTION
   // #BEGIN_PROP_NOTES line_1...  line_2...  line_n  #END_PROP_NOTES
#END_PARAMETER_PROPERTIES
*/

/*******************************************************************************************
  Structure Definitions
  (Uncomment and define structure definitions as needed)
  Note:  Be sure to initialize all declared STRING variables as needed
         For example, in Function Main: struct.myString = "";
*******************************************************************************************/
/*
STRUCTURE MyStruct1
{
};

MyStruct1 struct;
*/

/*******************************************************************************************
  Global Variables
  (Uncomment and declare global variables as needed)
  Note:  Be sure to initialize all declared STRING variables as needed
         For example, in Function Main: myString = "";
*******************************************************************************************/
INTEGER iSemaphore, a, iCS, iEnableChange, iLoc;
INTEGER iMainChannel, iSubChannel;
// LONG_INTEGER
// SIGNED_INTEGER
// SIGNED_LONG_INTEGER
STRING sTemp[10], sVolumeTemp[50], sThreeDViewPointTemp[50], sThreeDDepthTemp[50], sChannelTemp[50];
STRING sNumber[11], sChannelCommand[13];

/*******************************************************************************************
  Functions
  (Add any additional functions here)
  Note:  Functions must be physically placed before the location in
         the code that calls them.
*******************************************************************************************/

String_Function SendString(STRING StringSend)
{
	INTEGER a, iCS;
	STRING sStringFinal[50];
	iCS = 0;
	for(a = 1 to len(StringSend))
	{
		iCS = iCS + byte(StringSend, a);
	}
	iCS = (0x0100 - iCS);
	sStringFinal = StringSend + chr(iCS);
	Return (sStringFinal);
}

/*******************************************************************************************
  Event Handlers
  (Uncomment and declare additional event handlers as needed)
*******************************************************************************************/

CHANGE String_To_Send
{
	iCS = 0;
	if(iSemaphore = 0)
	{
		iSemaphore = 1;
		sTemp = String_To_Send;
		To_Device = SendString(sTemp);
		iSemaphore = 0;
	}
}
CHANGE Volume_Set_Value
{
	if(iEnableChange = 1)
	{
		makestring(sVolumeTemp, "\x08\x22\x01\x00\x00%s", chr(Volume_Set_Value));
		To_Device = SendString(sVolumeTemp);
		makestring(Volume_Text, "%s", itoa(Volume_Set_Value));
	}
}

CHANGE ThreeD_View_Point_Value
{
	if(iEnableChange = 1)
	{
		makestring(sThreeDViewPointTemp, "\x08\x22\x0B\x0C\x02%s", chr(ThreeD_View_Point_Value));
		To_Device = SendString(sThreeDViewPointTemp);
	}
}

CHANGE ThreeD_Depth_Value
{
	if(iEnableChange = 1)
	{
		makestring(sThreeDDepthTemp, "\x08\x22\x0B\x0C\x03%s", chr(ThreeD_Depth_Value));
		To_Device = SendString(sThreeDDepthTemp);
	}
}

PUSH KP		// used to send channel number command
{
	switch(getlastmodifiedarrayindex())
	{
		case(1):
			makestring(sNumber, "%s0", sNumber);
		case(2):
			makestring(sNumber, "%s1", sNumber);
		case(3):
			makestring(sNumber, "%s2", sNumber);
		case(4):
			makestring(sNumber, "%s3", sNumber);
		case(5):
			makestring(sNumber, "%s4", sNumber);
		case(6):
			makestring(sNumber, "%s5", sNumber);
		case(7):
			makestring(sNumber, "%s6", sNumber);
		case(8):
			makestring(sNumber, "%s7", sNumber);
		case(9):
			makestring(sNumber, "%s8", sNumber);
		case(10):
			makestring(sNumber, "%s9", sNumber);
		case(11):								// dash
		{
			iLoc = find("-", sNumber);
			if(iLoc = 0 && len(sNumber) > 0)	// if a dash doesn't already exist and the number field has at least one number in it
			{
				makestring(sNumber, "%s-", sNumber);	// append dash
			}
		}
		case(12):		// clear
		{
			clearbuffer(sNumber);
		}
		case(13):		//
		{
			if(len(sNumber) > 0)		// if number string exists
        	{
				if(find("-", sNumber))
				{
					iMainChannel = atoi(left(sNumber, find("-", sNumber) - 1));
					iSubChannel = atoi(right(sNumber, len(sNumber) - find("-", sNumber)));
					if(ATV)
						makestring(sChannelCommand, "\x08\x22\x04\x00\x00%s", chr(iMainChannel));
					if(DTV)
						makestring(sChannelCommand, "\x08\x22\x04\x80%s%s", chr(iMainChannel * 4), chr(iSubChannel));
				}
				else
				{
					iMainChannel = atoi(sNumber);

					if(ATV)
						makestring(sChannelCommand, "\x08\x22\x04\x00\x00%s", chr(iMainChannel));
					if(DTV)
						makestring(sChannelCommand, "\x08\x22\x04\x80%s\x00", chr(iMainChannel * 4));
				}
				To_Device = SendString(sChannelCommand);
				clearbuffer(sNumber);
			}
		}
	}
	if(len(sNumber) > 0)		// if number string exists
		makestring(Channel_Text, "%s", sNumber);		// send to text field 
	else						// if not
		makestring(Channel_Text, "\x20");		// clear text field
}		

CHANGE Current_Channel
{
	if(Current_Channel_Sub = 0)
		makestring(Channel_Text, "%d", Current_Channel);
	else
		makestring(Channel_Text, "%d-%d", Current_Channel, Current_Channel_Sub);
}

CHANGE Current_Channel_Sub
{
	if(Current_Channel_Sub = 0)
		makestring(Channel_Text, "%d", Current_Channel);
	else
		makestring(Channel_Text, "%d-%d", Current_Channel, Current_Channel_Sub);
}

CHANGE Current_Volume
{
	makestring(Volume_Text, "%d", Current_Volume);
}

/******************************************************************************************
  Main()
  Uncomment and place one-time startup code here
  (This code will get called when the system starts up)
*******************************************************************************************/

Function Main()
{
	iEnableChange = 0;
	iSemaphore = 0;
	wait(100)
	{
		iEnableChange = 1;
	}
	
}


Posted Mar 12, 2018, 9:15 PM UTC · edited

21
Loading comments…