Home AMX User Forum NetLinx Studio

unknown 'error' message in Diagnostcs - processor taking too long to boot up!

My processor is taking a good 6-8 mins to boot up, and I believe I've narrowed the fault down to one of my modules (after commenting out each module, compiling, uploading, checking processor boot time), but can't quite work out what part of my module is causing the problem.

During boot up I telnet to the processor as early as possible and poll the processor with "show buffer".
Without my suspected faulty module, the Interpreter maxes out at about 188 and then clears back to zero once all devices are online pretty quickly.
When my module is running, the interpreter will get up to about 600 over about 6-8 minutes, before eventually clearing back to zero.

In diagnostics I also repeatedly get this message which I don't get when I run the code without my module:

"CIMessageRouter - Unknown ObjectID 30"

Does anyone know what this relates to? Knowing this could help me narrow down the fault in my code.

I've spoke to AMX tech support here in the UK, but they are not allowed access to these diagnostic messages.... apparently only guys in the AMX development team in the USA are allowed knowledge of them!

thanks

Comments

  • Is this a module you've written or are you using an AMX Duet module? Could you attach the module file in question to a message here? It would help greatly to be able to see your code that might be causing the issue.
  • it's my own module for an Arcam T32 Tuner.
    module_name='SMC_Arcam_T32_v0_9' (dev dv, dev vdvArray[], char presetXMLFile[])
    /*******************************************************************************************
     * System Type	: NetLinx
     *
     * Program By		: Mark Bertenshaw (MJB)
     *
     * Rev. History	:
     * 02/06/09: v0.7 - MJB	- Initial Build (based on SMC_Arcam_DT91 module, hence version)
     * 23/07/09: v0.8 - MJB	- Added read/write to disc of preset structure in XML format
     * 26/10/10: v0.9 - MJB	- XML file IO name now passed into module, and general code update
     *******************************************************************************************/
    
    /*******************************************************************************************
     * Device Information	:
     *
     * 		Proven for: Arcam T32 DAB/FM/AM/SIRIUS tuner, running software v1.98
     *
     *		Connector Type:			Arcam 	: D-Sub 9pin female (cross)			-	AMX			: D-Sub 9pin female
     *												pin 2		: Rx														- pin 2		: Rx
     *												pin 3		: Tx														- pin 3		: Tx
     *												pin 4		: Gnd														- pin 5		: Gnd
     *
     *		Communication Format
     * 			Baud rate:									38400bps
     *			data length:								8 bits
     *			Parity:											None
     *			Stop bit:										1 bit
     *			Flow control:								None
     *******************************************************************************************/
    
    /*******************************************************************************************
     * Sample coding required for including this module with multiple touch panels:
     *
     * define_device
     * dvArcamDT91				= 	05001:1:0
     *
     * dvTP1_ArcamT32			= 	10001:1:0
     * dvTP2_ArcamT32			= 	10002:1:0
     *
     * vdvTP1_ArcamT32		= 	33001:1:0
     * vdvTP2_ArcamT32		= 	33001:1:0
     *
     * define_variable
     * dev TP_ArcamT32Array[]		=	{	dvTP1_ArcamT32, dvTP2_ArcamT32	}
     * dev vTP_ArcamT32Array[]	=	{	vdvTP1_ArcamT32, vdvTP2_ArcamT32	}
     *
     * define_start
     * define_module 'SMC_Arcam_T32_v0_7'		m_SMC_Arcam_T32		(dvArcamT32, vTP_ArcamT32Array)
     *
     * define_program
     * // for example:
     * // 	when feedback is required for dvTP1, use command:
     * // 			combine_devices(vTP_ArcamT32Array[1],TP_ArcamT32Array[1]])
     * // 	when feedback is no longer needed, use command:
     * // 			uncombine_devices(vTP_ArcamT32Array[1])
     *******************************************************************************************/
    
    /*******************************************************************************************
     * Device Definitions
     *******************************************************************************************/
    define_device
    
    /*******************************************************************************************
     * Constant Definitions
     *******************************************************************************************/
    define_constant
    
    ver			= '0.9 26/10/10 - MJB'	  // The Version of this module
    
    // timeline IDs
    tlTx = 1													// timeline to manage command transmission
    tlCommsReady = 2									// timeline to manage commsReady flag
    tlUpdateStatus = 3								// timeline to update status after pre-defined time
    tlPowerOn = 4											// timeline to pause module whilst arcam powers on
    tlPowerOff = 4										// timeline to pause module whilst arcam powers off
    
    // other
    zone = $01
    
    /*******************************************************************************************
     * data Type Definitions
     *******************************************************************************************/
    define_type
    
    structure _arcamT32
    {
    	integer		debug										// Are debug messages required or not
    
    	char			commStack[500]
    	char			commTx[500]
    	char			commRx[500]
    	char			passThru[1000]					// String of passThru command requested
    
    	integer		commsReady							// Is device ready to receive commands
    
    	integer		tlTxActive							// is timeline running
    	integer		tlCommsReadyActive			// is timeline running
    	integer		tlUpdateStatusActive		// is timeline running
    	integer		tlPowerOnActive					// is timeline running
    	integer		tlPowerOffActive				// is timeline running
    
    	integer		Power										// Power status (0 or 1 only)
    
    	integer		stationType							// 0=FM, 1=AM, 2=DAB, 3=SIRIUS, 4=AUX
    
    	char			stationName[200]				// Current station name
    	char			stationGenre[200]				// Current station genre
    	char			stationInfo[200]				// Current station info
    
    	char			fmFreq[20]							// Tuned FM (or AM) frequency
    	integer		fmStereoMono						// FM in Stereo or Mono (0 = Stereo, 1 = Mono)
    	integer		fmRDSDisabled						// is FM RDS disabled (0 = no, 1 = yes)
    
    	integer		signalStrength					// Current station signal strength (1-16)
    	integer		dabMPEG									// Current station DAB MPEG mode (0-3)
    	integer		dabBitrate							// Current station DAB data rate (0 - 224kb/s)
    
    	integer		dabScan									// DAB scanning status (0/1/2)
    
    	integer		presetCurrent						// Currently selected Preset station
    	integer		presetType[50]					// 0=FM, 1=AM, 2=DAB, 3=SIRIUS
    	char			presetName[50][200]			// Preset Name from list
    
    	char			vRS232[2]								// The rs232 protocol version
    	char			vSoftware[2]						// The main software version
    	char			vDAB[2]									// The DAB version
    }
    
    /*******************************************************************************************
     * Variable Definitions
     *******************************************************************************************/
    define_variable
    
    non_volatile			_arcamT32 arcamT32  	// Status of Device
    
    integer						PresetStore_Called				// Tracks whether a Preset Store command has been called
    
    integer           vdvArray_Channels_Sub_101_150[] =
    {
    	001,002,003,004,005,006,007,008,009,010,011,012,013,014,015,016,017,018,019,020,021,022,023,024,025,026,027,028,029,030,
    	031,032,033,034,035,036,037,038,039,040,041,042,043,044,045,046,047,048,049,050,051,052,053,054,055,056,057,058,059,060,
    	061,062,063,064,065,066,067,068,069,070,071,072,073,074,075,076,077,078,079,080,081,082,083,084,085,086,087,088,089,090,
    	091,092,093,094,095,096,097,098,099,100,
    	151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,
    	181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
    	211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
    	241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
    }
    
    integer						vdvArray_Channels_101_150[] =
    {
    	101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,
    	121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,
    	141,142,143,144,145,146,147,148,149,150
    }
    
    // timeline timings
    long      				tlTxTime[] = {100}							// 1/10 sec timeline - looping
    long      				tlCommsReadyTime[] = {10000}		// 10 sec timeline
    long      				tlUpdateStatusTime[] = {30000}	// 30 sec timeline
    long      				tlPowerOnTime[] = {4000}				// 4 sec timeline
    long      				tlPowerOffTime[] = {4000}				// 4 sec timeline
    
    /*******************************************************************************************
     * Latching Definitions
     *******************************************************************************************/
    define_latching
    
    /*******************************************************************************************
     * Mutually Exclusive Definitions
     *******************************************************************************************/
    define_mutually_exclusive
    
    /*******************************************************************************************
     * Module and Include Definitions
     *******************************************************************************************/
    
    /*******************************************************************************************
     * Subroutines/Functions
     *******************************************************************************************/
    define_function char[17] devToString(dev dv)
    {
    	return "format('%d',dv.number),':',format('%d',dv.port),':',format('%d',dv.system)"
    }
    
    define_function virtualCommandParse (char vdvArrayCommand[500])
    {
    	local_var char Instruction[100],	Identifier[1], DataPt1[100], DataPt2[100], DataPt3[100]
    	local_var integer CmdData
    	// Seperate Rx command into component sections....
    	select
    	{
    		active(find_string(vdvArrayCommand,'?',1)):									// A data request Identifier
    		{
    			Instruction = remove_string(vdvArrayCommand,'?',1)					// Instruction is all data before Identifier
    		}
    		active(find_string(vdvArrayCommand,'=',1)):									// A data request Identifier
    		{
    			Instruction = remove_string(vdvArrayCommand,'=',1)					// Instruction is all data before Identifier
    		}
    	}
    	Identifier = right_string(Instruction,1)											// Set value of Identifier
    	Instruction = left_string(Instruction,length_string(Instruction)-1)			// Remove Identifier from Instruction
    	if(Instruction = "'passThru'")																// Do not parse rest of data if arcamT32.arcamT32.passThru command is Rx
    	{
    		arcamT32.passThru = "vdvArrayCommand"
    		do_push(vdvArray[],246)
    	}
    	else
    	{
    		if(find_string(vdvArrayCommand,':',1))												// if remaining data is split by ':'
    		{
    			DataPt1 = remove_string(vdvArrayCommand,':',1)							// DataPt1 is all data before ':'
    			DataPt1 = left_string(DataPt1,length_string(DataPt1)-1)		// Remove ':' from Instruction
    			if(find_string(vdvArrayCommand,':',1))											// if remaining data is again, split by ':'
    			{
    				DataPt2 = remove_string(vdvArrayCommand,':',1)						// DataPt2 is all data before ':'
    				DataPt2 = left_string(DataPt2,length_string(DataPt2)-1)	// Remove ':' from Instruction
    				DataPt3 = vdvArrayCommand																// Remaining data is required for Instruction
    			}
    			else
    			{
    				DataPt2 = vdvArrayCommand																// Remaining data is required for Instruction
    			}
    		}
    		else
    		{
    			DataPt1 = vdvArrayCommand																	// Remaining data is required for Instruction
    		}
    		// Process each command dependant on Instruction, then Identifier....
    		switch(Instruction)
    		{
    			case 'version':
    			{
    				send_string vdvArray,"'version=',Ver"
    			}
    			case 'debug':
    			{
    				switch(Identifier)
    				{
    					case '?':
    					{
    						send_string vdvArray,"'debug=',itoa(arcamT32.debug)"				// Send integer value
    						select																											// Send text value
    						{
    							active(arcamT32.debug = 0):	{	send_string vdvArray,"'debug=off'"	}
    							active(arcamT32.debug = 1):	{	send_string vdvArray,"'debug=on'"	}
    						}
    					}
    					case '=':
    					{
    						select
    						{
    							active((DataPt1 = '0')OR(DataPt1 = 'off')):			{	arcamT32.debug = 0	}
    							active((DataPt1 = '1')OR(DataPt1 = 'on')):			{	arcamT32.debug = 1	}
    							active((DataPt1 = '3')OR(DataPt1 = 'toggle')):	{	arcamT32.debug = !arcamT32.debug	}
    						}
    					}
    				}
    			}
    		}
    	}
    }
    
    define_function txCommand(integer comm)
    {
    	local_var char StringToSend[30]				// Local string to create, which gets transmitted to device
    	StringToSend = "''"										// Clear StringToSend initially as a precautionary measure
    
    	switch (comm)
    	{
    		case 001: { StringToSend = "$21,$01,$00" }							// Insert code for FM : Stereo
    		case 002: { StringToSend = "$21,$01,$01" }							// Insert code for FM : Mono
    
    		case 003: { StringToSend = "$20,$01,$F1" }							// Insert code for DAB : Erase current station list
    		case 004: { StringToSend = "$20,$01,$F0" }							// Insert code for DAB : Scan for new stations
    
    		case 005: { StringToSend = "$16,$01,$01" }							// Insert code for FM/AM Freq : Increase
    		case 006: { StringToSend = "$16,$01,$00" }							// Insert code for FM/AM Freq : Decrease
    
    		case 007: { StringToSend = "$22,$01,$00" }							// Insert code for FM RDS : Enable
    		case 008: { StringToSend = "$22,$01,$01" }							// Insert code for FM RDS : Disabled
    
    		case 022:																								// Insert code for Next station
    		{
    			switch(arcamT32.stationType)
    			{
    				case 01:	StringToSend = "$26,$01,$F0"							// FM/AM
    				case 03:	StringToSend = "$08,$02,$11,$50"					// DAB		(using RC5 simulate command for "right")
    			}
    		}
    		case 023:																								// Insert code for previous station
    		{
    			switch(arcamT32.stationType)
    			{
    				case 01:	StringToSend = "$26,$01,$F1"							// FM
    				case 03:	StringToSend = "$08,$02,$11,$51"					// DAB		(using RC5 simulate command for "left")
    			}
    		}
    
    		case 027: {	StringToSend = "$00,$01,$01"	}							// Insert code for Power On
    		case 028: {	StringToSend = "$00,$01,$00"	}							// Insert code for Power Off
    
    		case 031: { StringToSend = "$24,$01,$00" }							// Insert code for Source : FM
    		case 032: { StringToSend = "$24,$01,$01" }							// Insert code for Source : AM
    		case 033: { StringToSend = "$24,$01,$02" }							// Insert code for Source : DAB
    		case 034: { StringToSend = "$24,$01,$03" }							// Insert code for Source : SIRIUS
    		case 035: { StringToSend = "$24,$01,$04" }							// Insert code for Source : AUX
    
    		case 044: { StringToSend = "$08,$02,$11,$7D" }					// Insert code for system menu
    		case 045: { StringToSend = "$08,$02,$11,$56" }					// Insert code for up
    		case 046: { StringToSend = "$08,$02,$11,$55" }					// Insert code for down
    		case 047: { StringToSend = "$08,$02,$11,$51" }					// Insert code for left
    		case 048: { StringToSend = "$08,$02,$11,$50" }					// Insert code for right
    		case 049: { StringToSend = "$08,$02,$11,$57" }					// Insert code for ok
    
    		case 051:	case 052:	case 053:	case 054:	case 055:				// Insert code for Preset Data Request : 1 - 50
    		case 056:	case 057:	case 058:	case 059:	case 060:
    		case 061:	case 062:	case 063:	case 064:	case 065:
    		case 066:	case 067:	case 068:	case 069:	case 070:
    		case 071:	case 072:	case 073:	case 074:	case 075:
    		case 076:	case 077:	case 078:	case 079:	case 080:
    		case 081:	case 082:	case 083:	case 084:	case 085:
    		case 086:	case 087:	case 088:	case 089:	case 090:
    		case 091:	case 092:	case 093:	case 094:	case 095:
    		case 096:	case 097:	case 098:	case 099:
    		case 100: { StringToSend = "$1B,$01,type_cast(comm-50)" }
    
    		case 101:	case 102:	case 103:	case 104:	case 105:				// Insert code for Preset select : 1 - 50
    		case 106:	case 107:	case 108:	case 109:	case 110:
    		case 111:	case 112:	case 113:	case 114:	case 115:
    		case 116:	case 117:	case 118:	case 119:	case 120:
    		case 121:	case 122:	case 123:	case 124:	case 125:
    		case 126:	case 127:	case 128:	case 129:	case 130:
    		case 131:	case 132:	case 133:	case 134:	case 135:
    		case 136:	case 137:	case 138:	case 139:	case 140:
    		case 141:	case 142:	case 143:	case 144:	case 145:
    		case 146:	case 147:	case 148:	case 149:
    		case 150: { StringToSend = "$17,$01,type_cast(comm-100)" }
    
    		case 151:	case 152:	case 153:	case 154:	case 155:				// Insert code for Preset Store : 1 - 50
    		case 156:	case 157:	case 158:	case 159:	case 160:
    		case 161:	case 162:	case 163:	case 164:	case 165:
    		case 166:	case 167:	case 168:	case 169:	case 170:
    		case 171:	case 172:	case 173:	case 174:	case 175:
    		case 176:	case 177:	case 178:	case 179:	case 180:
    		case 181:	case 182:	case 183:	case 184:	case 185:
    		case 186:	case 187:	case 188:	case 189:	case 190:
    		case 191:	case 192:	case 193:	case 194:	case 195:
    		case 196:	case 197:	case 198:	case 199:
    		case 200: { StringToSend = "$25,$01,type_cast(comm-150)" }
    
    		// Status Request commands
    		case 210: { StringToSend = "$00,$01,$F0"	}							// Insert code for Power Request
    
    		case 211: { StringToSend = "$24,$01,$F3" }							// Insert code for Source current : request
    
    		case 212: { StringToSend = "$03,$01,$F0" }							// Insert code for FM data request : Genre
    		case 213: { StringToSend = "$02,$01,$F0" }							// Insert code for FM data request : RDS
    
    		case 214: { StringToSend = "$15,$01,$F0" }							// Insert code for current Tuner preset request
    
    		case 215: {	StringToSend = "$18,$01,$F0" }							// Insert code for Station Name Request
    
    		case 216: { StringToSend = "$16,$01,$F0" }							// Insert code for FM Freq. Request
    
    		case 217: { StringToSend = "$19,$01,$F0" }							// Insert code for Program Type Request
    
    		case 218: { StringToSend = "$1A,$01,$F0" }							// Insert code for DLS/PDT Info Request
    
    		case 219: { StringToSend = "$21,$01,$F0" }							// Insert code for FM Stereo/Mono request
    
    		case 220: { StringToSend = "$22,$01,$F0" }							// Insert code for FM RDS enabled : request
    
    		case 221: { StringToSend = "$04,$01,$F0" }							// Insert code for software version request : RS232
    		case 222: { StringToSend = "$04,$01,$F1" }							// Insert code for software version request : main
    		case 223: { StringToSend = "$04,$01,$F3" }							// Insert code for software version request : DAB
    
    		// skip channels too....
    		case 246: { StringToSend = arcamT32.passThru }					// Insert code for passThru
    	}
    
    	// Set DevicePowerTime to required value for Power on or Off
    	switch (comm)
    	{
    		case 027:	{ if(!arcamT32.tlPowerOnActive)		timeline_create(tlPowerOn, tlPowerOnTime, length_array(tlPowerOnTime), timeline_absolute, timeline_once) }
    		case 028:	{ if(!arcamT32.tlPowerOffActive)	timeline_create(tlPowerOff, tlPowerOffTime, length_array(tlPowerOffTime), timeline_absolute, timeline_once) }
    	}
    
    	// if station search/change commands are called, clear out data arrays
    	switch(comm)
    	{
    		case 003:
    		case 004:
    		case 005:
    		case 006:
    
    		case 022:
    		case 023:
    
    		case 031:
    		case 032:
    		case 033:
    		case 034:
    		case 035:
    
    		case 045:
    		case 046:
    		case 047:
    		case 048:
    		case 049:
    		{
    			arcamT32.fmFreq = "''"
    			send_command vdvArray,"'^TXT-',itoa(61),',0,',arcamT32.fmFreq"
    			arcamT32.stationName = "''"
    			send_command vdvArray,"'^TXT-',itoa(62),',0,',arcamT32.stationName"
    			arcamT32.stationGenre = "''"
    			send_command vdvArray,"'^TXT-',itoa(63),',0,',arcamT32.stationGenre"
    			arcamT32.stationInfo = "''"
    			send_command vdvArray,"'^TXT-',itoa(64),',0,',arcamT32.stationInfo"
    
    			// create timeline to request general update on status after period of time
    			if(!arcamT32.tlUpdateStatusActive)	timeline_create(tlUpdateStatus, tlUpdateStatusTime, length_array(tlUpdateStatusTime), timeline_absolute, timeline_once)
    		}
    	}
    
    	// if a command has been called, transmit
    	if(length_string(StringToSend))
    	{
    		arcamT32.commTx = "$21,zone,StringToSend,$0D"						// Modify StringToSend as required by device
    		send_string dv,arcamT32.commTx													// Send final command to device
    
    		arcamT32.commsReady = 0																		// commsReady will be set on rx of data from device
    		if(!arcamT32.tlCommsReadyActive)	timeline_create(tlCommsReady, tlCommsReadyTime, length_array(tlCommsReadyTime), timeline_absolute, timeline_once)
    	}
    }
    
    define_function rxCommand ()
    {
    	local_var integer	DataStartFound,	DataEndFound,	IntData,	DataLength, 	x
    	local_var char 		DataToProcess[500],	zoneCode[1], CommandCode[1],	AnswerCode[1],	data[500],	Data1[500],	Data2[500], Data3[500]
    	DataEndFound = find_string(arcamT32.commRx,"$0D",1)						// Each Rx data shoud always end with $0D, find first instance of it....
    	while(DataEndFound>0)
    	{
    		DataToProcess = get_buffer_string(arcamT32.commRx,DataEndFound)		// Remove first $0D and its preceeding data for processing
    		DataToProcess = get_buffer_string(DataToProcess,length_string(DataToProcess)-1)		// Remove $0D at end of DataToProcess
    		DataStartFound = find_string(DataToProcess,"$21",1)				// Each Rx data shoud always begin with $21, find first instance of it....
    		if(DataStartFound==0)																			// if no $21 is found, empty DataToProcess
    		{
    			DataToProcess = "''"
    		}
    		else
    		{
    			get_buffer_string(DataToProcess,DataStartFound)							// Remove first $21 and its preceeding data, as uneeded
    			zoneCode = get_buffer_string(DataToProcess,1)								// Zone is next byte
    			CommandCode = get_buffer_string(DataToProcess,1)						// CommandCode is next byte
    			AnswerCode = get_buffer_string(DataToProcess,1)							// AnswerCode is next byte
    			if(arcamT32.debug)
    			{
    				switch(answerCode)
    				{
    					case $00:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Status update'"
    					case $82:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Zone invalid'"
    					case $83:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Command not recognised'"
    					case $84:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Parameter not recognised'"
    					case $85:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Command invalid at this time'"
    					case $86:		send_string 0,"'Answer code from ArcamT32, (DPS ',devToString(dv),') = Invalid data length'"
    				}
    			}
    			DataLength = type_cast(get_buffer_string(DataToProcess,1))
    			data = get_buffer_string(DataToProcess,DataLength)					// data = Datalength of DataToProcess
    			if(length_string(data))																			// if there is data (in case answer code is failure)
    			{
    				switch(CommandCode)
    				{
    					case $00:		arcamT32.Power = type_cast(data)						// Power
    					case $24:		arcamT32.stationType = (type_cast(data))+1	// station Type
    
    					case $12:																								// FM RDS Info
    					{
    						arcamT32.stationInfo = data
    						send_command vdvArray,"'^TXT-',itoa(64),',0,',arcamT32.stationInfo"
    					}
    					case $22:		arcamT32.fmRDSDisabled = type_cast(data)		// is FM RDS disabled
    					case $03:																								// FM Genre
    					{
    						arcamT32.stationGenre = data
    						send_command vdvArray,"'^TXT-',itoa(63),',0,',arcamT32.stationGenre"
    					}
    					case $16:																								// current FM/AM frequency
    					{
    						Data1 = get_buffer_string(data,1)											// Data1 is 1st byte
    						Data2 = data																					// Data2 is 2nd and remaining byte
    						arcamT32.fmFreq = "itoa(type_cast(Data1)),'.',itoa(type_cast(Data2))"
    						send_command vdvArray,"'^TXT-',itoa(61),',0,',arcamT32.fmFreq"
    					}
    					case $21:		arcamT32.fmStereoMono = type_cast(data)			// FM Mono/Stereo
    					case $18:																								// Station name
    					{
    						arcamT32.stationName = data
    						send_command vdvArray,"'^TXT-',itoa(62),',0,',arcamT32.stationName"
    						// check to see if any presets match current station for feedback purposes
    						off[vdvArray,vdvArray_Channels_101_150]
    						for(x=1;x<=50;x++)
    						{
    							if((arcamT32.stationName = arcamT32.presetName[x])
    							and(arcamT32.stationType = arcamT32.presetType[x]))
    							{
    								on[vdvArray,100+x]
    							}
    						}
    					}
    					case $23:																								// Radio signal info
    					{
    						Data1 = get_buffer_string(data,1)											// Data1 is 1st byte
    						Data2 = get_buffer_string(data,1)											// Data2 is 2nd byte
    						Data3 = data																					// Data3 is remaining data
    						switch(Data1)
    						{
    							case $00:																						// fm frequency
    							{
    								arcamT32.fmFreq = "itoa(type_cast(Data2)),'.',itoa(type_cast(Data3))"
    								send_command vdvArray,"'^TXT-',itoa(61),',0,',arcamT32.fmFreq"
    							}
    							case $01:																						// signal strength
    							{
    								arcamT32.signalStrength = type_cast(Data2)
    							}
    							case $02:																						// DAB bitrate
    							{
    								arcamT32.dabBitrate = type_cast(Data2)
    							}
    							case $03:																						// DAB mpeg mode
    							{
    								arcamT32.dabMPEG = type_cast(Data2)
    							}
    						}
    					}
    
    					case $19:																								// DAB Programme genre
    					{
    						arcamT32.stationGenre = data
    						send_command vdvArray,"'^TXT-',itoa(63),',0,',arcamT32.stationGenre"
    					}
    					case $1A:																								// DLS info
    					{
    						arcamT32.stationInfo = data
    						send_command vdvArray,"'^TXT-',itoa(64),',0,',arcamT32.stationInfo"
    					}
    					case $20:			arcamT32.dabScan = type_cast(data)				// DAB scanning status
    
    					case $15:																								// current preset
    					case $17:																								// preset selected
    					{
    						arcamT32.presetCurrent = type_cast(data)
    						off[vdvArray,vdvArray_Channels_101_150]
    						on[vdvArray,100+arcamT32.presetCurrent]
    					}
    					case $1B:																								// preset details
    					{
    						Data1 = get_buffer_string(data,1)											// Data1 is 1st byte
    						Data2 = get_buffer_string(data,1)											// Data2 is 2nd byte
    						Data3 = data																					// Data3 is remaining data
    						arcamT32.presetType[type_cast(data1)] = type_cast(data2)
    						arcamT32.presetName[type_cast(data1)] = Data3
    
    						presetWriteToXMLFile()
    					}
    					case $25:																								// preset stored
    					{
    						arcamT32.presetCurrent = type_cast(data)
    						arcamT32.presetType[arcamT32.presetCurrent] = arcamT32.stationType
    						arcamT32.presetName[arcamT32.presetCurrent] = arcamT32.stationName
    						off[vdvArray,100+arcamT32.presetCurrent]
    						send_command vdvArray,"'^TXT-',itoa(100+arcamT32.presetCurrent),',0,',arcamT32.stationName"
    						wait 7		// turn preset bttn off for 7/10s to let user know preset is stored
    						{
    							off[vdvArray,vdvArray_Channels_101_150]
    							on[vdvArray,100+arcamT32.presetCurrent]
    						}
    
    						presetWriteToXMLFile()
    					}
    
    					case $04:																								// software versions of arcamT32 (various)
    					{
    						Data1 = get_buffer_string(data,1)											// Data1 is 1st byte
    						Data2 = data																					// Data2 is remaining 2 bytes
    						switch(Data1)
    						{
    							case $F0:		arcamT32.vRS232 = Data2
    							case $F1:		arcamT32.vSoftware = Data2
    							case $F3:		arcamT32.vDAB = Data2
    						}
    					}
    
    				}
    			}
    		}
    		DataEndFound = find_string(arcamT32.commRx,"$0D",1)						// Does arcamT32.commRx contain more code to parse? else terminate WHILE loop
    	}
    }
    
    define_function stackCommand (integer comm)
    {
    	local_var integer x
    
    	if(arcamT32.debug)	send_string 0:1:0,"'arcamT32 : stacking command, ',itoa(comm),' ....for device, ',devToString(dv)"
    
    	// Put at the top of the switch/case any command that requires specific coding before stacking in Queue
    	switch(comm)
      {
    		case 009:																	// power toggle
    		{
    			switch(arcamT32.power)
    			{
    				case 00:	arcamT32.commStack = "arcamT32.commStack,27"			// if currently off, send power on
    				case 01:	arcamT32.commStack = "arcamT32.commStack,28"			// if currently on, send power off
    			}
    		}
    		case 049:																	// after "enter" command (which selects a station
    		{																					// ... request details on station again!
    			arcamT32.commStack = "arcamT32.commStack,comm"
    			do_push(vdvArray[1],211)
    			do_push(vdvArray[1],212)
    			do_push(vdvArray[1],213)
    			do_push(vdvArray[1],214)
    			do_push(vdvArray[1],215)
    			do_push(vdvArray[1],216)
    			do_push(vdvArray[1],217)
    			do_push(vdvArray[1],218)
    		}
    		case 240:																	// Update all data
    		{
    			do_push(vdvArray[1],210)
    			do_push(vdvArray[1],211)
    			do_push(vdvArray[1],212)
    			do_push(vdvArray[1],213)
    			do_push(vdvArray[1],214)
    			do_push(vdvArray[1],215)
    			do_push(vdvArray[1],216)
    			do_push(vdvArray[1],217)
    			do_push(vdvArray[1],218)
    			do_push(vdvArray[1],219)
    			do_push(vdvArray[1],220)
    			do_push(vdvArray[1],221)
    			do_push(vdvArray[1],222)
    			do_push(vdvArray[1],223)
    		}
    		case 250:
    		{
    			arcamT32.debug=!arcamT32.debug					// debug (toggle)
    		}
    		case 252:																	// Update all text to vdvArray
    		{
    			send_command vdvArray,"'^TXT-',itoa(61),',0,',arcamT32.fmFreq"
    			send_command vdvArray,"'^TXT-',itoa(62),',0,',arcamT32.stationName"
    			send_command vdvArray,"'^TXT-',itoa(63),',0,',arcamT32.stationGenre"
    			send_command vdvArray,"'^TXT-',itoa(64),',0,',arcamT32.stationInfo"
    			for(x=1;x<=50;x++)
    			{
    				if(length_string(arcamT32.presetName[x]))
    				{
    					send_command vdvArray,"'^TXT-',itoa(100+x),',0,',arcamT32.presetName[x]"
    				}
    				else
    				{
    					send_command vdvArray,"'^TXT-',itoa(100+x),',0,push & hold',$0D,$0A,'to store preset'"
    				}
    			}
    		}
    		// All Commands that do not require any manipulation of the queue
    		default:
    		{
    			arcamT32.commStack = "arcamT32.commStack,comm"					// Add requested command to the end of the queue
    		}
    	}
    
    	// create timeline to tx stacked commands
    	if(!arcamT32.tlTxActive)	timeline_create(tlTx, tlTxTime, length_array(tlTxTime), timeline_absolute, timeline_repeat)
    }
    
    define_function presetWriteToXMLFile()
    {
    	stack_var slong	slResult, slFile
    	stack_var char	sXMLString[50000]
    
    	// Convert To XML
    	slResult = variable_to_xml(arcamT32.presetName, sXMLString, 1, 0)
    
    	// Save Structure To Disk – XML
    	slFile = file_open(presetXmlFile, 2)
    	slResult = file_write(slFile, sXMLString, length_string(sXMLString))
    	slResult = file_close(slFile)
    }
    
    define_function presetReadFromXMLFile()
    {
    	stack_var slong	slResult, slFile, slReturn
    	stack_var char	sXMLString[50000]
    
    	// Read XML File
    	slFile = file_open(presetXmlFile,1)
    	slResult = file_read(slFile, sXMLString, 50000)
    	slResult = file_close(slFile)
    
    	// Convert To XML, and save to preset structure
    	slReturn = xml_to_variable(arcamT32.presetName, sXMLString, 1, 0)
    }
    
    /*******************************************************************************************
     * Startup Code
     *******************************************************************************************/
    define_start
    
    create_buffer dv,arcamT32.commRx
    
    arcamT32.commsReady = 1
    
    presetReadFromXMLFile()
    
    wait 300	'Wait for processor'
    {
    	do_push(vdvArray[1],240)										// 'Update All data' command
    	do_push(vdvArray[1],252)										// update text to vdvArray device
    }
    
    /*******************************************************************************************
     * Event Handlers
     *******************************************************************************************/
    define_event
    
    // Processing for all data events on physical port
    data_event[dv]
    {
      online:
    	{
    		send_command dv,'HSOFF'
    		send_command dv,'XOFF'
    		send_command dv,'RXON'
    		send_command dv,'SET BAUD 38400,N,8,1 485 DISABLE'
    	}
    	string:
    	{
    		if(arcamT32.debug)	send_string 0:1:0,"'rx data : ',data.text,'  ....from device : ',devToString(dv)"
    
    		// We've received data from device, comms can be assumed to be ok
    		if(arcamT32.tlCommsReadyActive)	timeline_kill(tlCommsReady)
    		arcamT32.commsReady = 1
    
    		rxCommand()																		// Process incoming data from device
    	}
    }
    
    data_event[vdvArray]
    {
      command:																				// send_command Instructions into this module from Mainline
    	{
    		virtualCommandParse(data.text)
    	}
    }
    
    button_event[vdvArray,vdvArray_Channels_Sub_101_150]
    {
      push:
    	{
    		// Button channel number links directly to SNAPI defined channel number
    		stackCommand(button.input.channel)
    		if(arcamT32.debug)	send_string 0:1:0,"'arcamT32: button_push ',itoa(button.input.channel),' from device ',devToString(button.input.device)"
    	}
    	hold[2,repeat]:
    	{
    		// The following commands require PUSH_HOLD processing....
    		switch(get_last(vdvArray_Channels_Sub_101_150))
    		{
    			case 022:																	// station next
    			case 023:																	// station previous
    			case 005:																	// FM Freq increase
    			case 006:																	// FM Freq decrease
    			{
    				stackCommand(button.input.channel)
    			}
    		}
    	}
    }
    
    // Processing for button_events for preset store and select
    button_event[vdvArray,vdvArray_Channels_101_150]
    {
      push:
    	{
    		PresetStore_Called = 0
    		on[vdvArray,button.input.channel]
    	}
    	hold[30]:		// Preset Store commands after 3 seconds
    	{
    		stackCommand (button.input.channel+50)
    		PresetStore_Called = 1
    	}
    	release:		// if Preset store commands hasn't been called, then Preset select
    	{
    		if(!PresetStore_Called = 1)
    		{
    			stackCommand (button.input.channel)
    		}
    	}
    }
    
    timeline_event[tlTx]
    {	// timeline manages tx commands
    	stack_var char comm
    
    	if(length_string(arcamT32.commStack))
    	{
    		if(arcamT32.commsReady && !arcamT32.tlPowerOnActive && !arcamT32.tlPowerOffActive)
    		{
    			comm = get_buffer_char(arcamT32.commStack)
    			if(arcamT32.debug)	send_string 0:1:0,"'arcamT32 : command, ',comm,' ...retrieved from stacked commands for device, ',devToString(dv)"
    			txCommand(comm)
    		}
    	}
    	else
    	{
    		timeline_kill(tlTx)
    	}
    }
    
    timeline_event[tlCommsReady]
    {	// timeline used to force comms ready flag to ok
    	arcamT32.commsReady = 1
    	do_push(vdvArray[1],210)										// request power status
    }
    
    timeline_event[tlUpdateStatus]
    {	// timeline used to request status from arcam
    	do_push(vdvArray[1],240)
    }
    
    /*******************************************************************************************
     * Mainline code
     *******************************************************************************************/
    define_program
    
    arcamT32.tlTxActive = timeline_active(tlTx)
    arcamT32.tlCommsReadyActive = timeline_active(tlCommsReady)
    arcamT32.tlUpdateStatusActive = timeline_active(tlUpdateStatus)
    arcamT32.tlPowerOnActive = timeline_active(tlPowerOn)
    arcamT32.tlPowerOffActive = timeline_active(tlPowerOff)
    
    // Feedback to vdvArray device....
    [vdvArray,9]	= arcamT32.power								// Power status				-	toggle
    [vdvArray,27]	= arcamT32.power								//										- on
    [vdvArray,28]	= !arcamT32.power								//										- off
    [vdvArray,31]	= (arcamT32.stationType==1)			// Source							- FM
    [vdvArray,32]	= (arcamT32.stationType==2)			// 		|								- AM
    [vdvArray,33]	= (arcamT32.stationType==3)			// 		|								- DAB
    [vdvArray,34]	= (arcamT32.stationType==4)			// 		|								- SIRIUS
    [vdvArray,35]	= (arcamT32.stationType==5)			// 		`---------------- AUX
    [vdvArray,250]	= arcamT32.debug							// debug							- toggle
    [vdvArray,251]	= !arcamT32.commsReady				// Comms Connected		- on if comms is OK
    
  • DHawthorneDHawthorne Posts: 4,584
    Try commenting out those timeline functions in your DEFINE_PROGRAM section. It may be running before everything is properly initialized. If that's not it, I would bet it's something on that order. The "object" not being found is something that just hasn't been fully formed yet, but is being called on.
  • DHawthorne wrote: »
    Try commenting out those timeline functions in your DEFINE_PROGRAM section. It may be running before everything is properly initialized. If that's not it, I would bet it's something on that order. The "object" not being found is something that just hasn't been fully formed yet, but is being called on.

    Commented out all of DEFINE_PROGRAM, and no change, but I have found out why the diagnostic message, "CIMessageRouter - Unknown ObjectID 30" keeps appearing.......

    ....... it's a response to me sending the command "SHOW BUFFERS" when connected via telnet to the processor!
    just noticed it by running 2 telnet connections to the processor, one showing diagnostics (with command "SHOW MSG ALL") and the other telnet window where I could poll the command "SHOW BUFFERS".

    sorry.....

    There is still a noticabley long boot time of the processor when I include my Arcam module in code.
    I'm using 3 instances of the module, which works fine once the processor is booted, but maybe this is the cause?
  • yuriyuri Posts: 861
    you have an awfull lot of stuff in your DEFINE_PROGRAM...
    Even though AMX teaches this, you should be a little carefull with doing this, as it slows down the whole thing :s
  • Jorde_VJorde_V Posts: 393
    yuri wrote: »
    you have an awfull lot of stuff in your DEFINE_PROGRAM...
    Even though AMX teaches this, you should be a little carefull with doing this, as it slows down the whole thing :s

    These days AMX actually tells you to put as little as possible in 'define_program' and handle your feedback in your functions.

    Our local Technical Representative recommends a maximum of 10 lines in define_program if you REALLY need it.

    Snippet from the Netlinx Reference Guide:
    The event processing that previously could occur only through mainline code can now be handled through code in the DEFINE_EVENT section. This provides a more efficient mechanism for processing events; mainline does not have to be traversed to process a single I/O request.
    A handler can be defined for processing device-specific events, as well as providing feedback for the device initiating the event notification. If a handler is present, mainline will not be called to process the event; the handler is called instead. Once the handler completes its execution, the system is ready to process the next input message. When no more messages are pending, mainline runs.
    In effect, mainline in NetLinx is an idle time process. With the addition of the DEFINE_EVENT section for processing events, the role of mainline in a NetLinx
    program becomes greatly diminished if not totally eliminated.
    Programs can still be written using the traditional technique of processing events and providing feedback through mainline code. However, programs written using the event table structure, provided in the NetLinx system, will run faster and be easier to maintain.

    I've put in bold what's really important.

    I would also agree that you should not use the mainline for anything at all

    The way the NetLinx system works: (see attachment)
  • time to go through all my modules and start pulling feedback from mainlin back into event handlers....

    I've only ever put channel feedback to devices in mainline (and recently tracking the state of timelines for debug purposes), but with some of my systems using a good 20 or more modules, and often with multiples of the same modules, this overloading of mainline can't be good as you say.

    thanks for the advice guys.
Sign In or Register to comment.