Sanyo data projector buffers
santi
Posts: 2
Hi,
It seems that a well known fact is that the data buffer sent from the Sanyo data projectors have to be really managed to obtain the correct meaning e.g. lamp hours, projector status etc... So I crafted this code:
//DEFINE DEVICE
PROJ = 5001:1:0 // SANYO WTC500L
//DEFINE VARIABLE
INTEGER nLampHourCounter //accumulates lamp hours
CHAR cProjectorStringBuffer[50] //input datastream from data projector
CHAR cProjectorLampTimeBuffer[5] //store lamp time
//DEFINE START
//Create the data projector input stream / buffer
CREATE_BUFFER PROJ, cProjectorLampTimeBuffer
CREATE_BUFFER PROJ, cProjectorStringBuffer
//Read Projector Status CR0
DATA_EVENT[PROJ]
{
ONLINE:
{
//clear buffer
CLEAR_BUFFER cProjectorStringBuffer
SEND_STRING PROJ, "'CR0',$0D"
//Perform active action depending on projector status
SELECT
{
//Projector is in STANDBY
ACTIVE(FIND_STRING(cProjectorStringBuffer,'80',1)):
{}
//Power ON
ACTIVE(FIND_STRING(cProjectorStringBuffer,'00',1)):
{
//Query for lamp time
SEND_STRING PROJ, "'CR3',$0D"
//Get the lamp time
nLampHourCounter = ATOI(GET_BUFFER_STRING(cProjectorLampTimeBuffer,5))
//notify RMS server
RMSSETLAMPHOURS(PROJ,nLampHourCounter)
}
//Countdown in process i.e. WARMING
ACTIVE(FIND_STRING(cProjectorStringBuffer,'40',1)):
{
//Query for lamp time
SEND_STRING PROJ, "'CR3',$0D"
//Get the lamp time
nLampHourCounter = ATOI(GET_BUFFER_STRING(cProjectorLampTimeBuffer,5))
//notify RMS server
RMSSETLAMPHOURS(PROJ,nLampHourCounter)
}
//Countdown in process i.e. COOLING
ACTIVE(FIND_STRING(cProjectorStringBuffer,'20',1)):
{}
//Power FAILURE
ACTIVE(FIND_STRING(cProjectorStringBuffer,'10',1)):
{}
//Cooling Down in process due to Abnormal Temperature
ACTIVE(FIND_STRING(cProjectorStringBuffer,'28',1)):
{}
//Standby after Cooling Down due to Abnormal Temperature
ACTIVE(FIND_STRING(cProjectorStringBuffer,'88',1)):
{}
//Power-Save Cooling Down in process
ACTIVE(FIND_STRING(cProjectorStringBuffer,'24',1)):
{}
//Cooling Down in process after OFF due to Lamp Failure
ACTIVE(FIND_STRING(cProjectorStringBuffer,'21',1)):
{}
//Standby after Cooling Down due to Lamp Failure
ACTIVE(FIND_STRING(cProjectorStringBuffer,'81',1)):
{}
//Cooling Down in process after Power Off due to Shutter management
ACTIVE(FIND_STRING(cProjectorStringBuffer,'2C',1)):
{}
//Standby after Cooling Down due to Shutter management
ACTIVE(FIND_STRING(cProjectorStringBuffer,'8C',1)):
{}
}
}
}
QUESTION: what wrong with this code? Any pointers will be really appreciated.
It seems that a well known fact is that the data buffer sent from the Sanyo data projectors have to be really managed to obtain the correct meaning e.g. lamp hours, projector status etc... So I crafted this code:
//DEFINE DEVICE
PROJ = 5001:1:0 // SANYO WTC500L
//DEFINE VARIABLE
INTEGER nLampHourCounter //accumulates lamp hours
CHAR cProjectorStringBuffer[50] //input datastream from data projector
CHAR cProjectorLampTimeBuffer[5] //store lamp time
//DEFINE START
//Create the data projector input stream / buffer
CREATE_BUFFER PROJ, cProjectorLampTimeBuffer
CREATE_BUFFER PROJ, cProjectorStringBuffer
//Read Projector Status CR0
DATA_EVENT[PROJ]
{
ONLINE:
{
//clear buffer
CLEAR_BUFFER cProjectorStringBuffer
SEND_STRING PROJ, "'CR0',$0D"
//Perform active action depending on projector status
SELECT
{
//Projector is in STANDBY
ACTIVE(FIND_STRING(cProjectorStringBuffer,'80',1)):
{}
//Power ON
ACTIVE(FIND_STRING(cProjectorStringBuffer,'00',1)):
{
//Query for lamp time
SEND_STRING PROJ, "'CR3',$0D"
//Get the lamp time
nLampHourCounter = ATOI(GET_BUFFER_STRING(cProjectorLampTimeBuffer,5))
//notify RMS server
RMSSETLAMPHOURS(PROJ,nLampHourCounter)
}
//Countdown in process i.e. WARMING
ACTIVE(FIND_STRING(cProjectorStringBuffer,'40',1)):
{
//Query for lamp time
SEND_STRING PROJ, "'CR3',$0D"
//Get the lamp time
nLampHourCounter = ATOI(GET_BUFFER_STRING(cProjectorLampTimeBuffer,5))
//notify RMS server
RMSSETLAMPHOURS(PROJ,nLampHourCounter)
}
//Countdown in process i.e. COOLING
ACTIVE(FIND_STRING(cProjectorStringBuffer,'20',1)):
{}
//Power FAILURE
ACTIVE(FIND_STRING(cProjectorStringBuffer,'10',1)):
{}
//Cooling Down in process due to Abnormal Temperature
ACTIVE(FIND_STRING(cProjectorStringBuffer,'28',1)):
{}
//Standby after Cooling Down due to Abnormal Temperature
ACTIVE(FIND_STRING(cProjectorStringBuffer,'88',1)):
{}
//Power-Save Cooling Down in process
ACTIVE(FIND_STRING(cProjectorStringBuffer,'24',1)):
{}
//Cooling Down in process after OFF due to Lamp Failure
ACTIVE(FIND_STRING(cProjectorStringBuffer,'21',1)):
{}
//Standby after Cooling Down due to Lamp Failure
ACTIVE(FIND_STRING(cProjectorStringBuffer,'81',1)):
{}
//Cooling Down in process after Power Off due to Shutter management
ACTIVE(FIND_STRING(cProjectorStringBuffer,'2C',1)):
{}
//Standby after Cooling Down due to Shutter management
ACTIVE(FIND_STRING(cProjectorStringBuffer,'8C',1)):
{}
}
}
}
QUESTION: what wrong with this code? Any pointers will be really appreciated.
0
Comments
Next i would find out if the devices sends a delimiter so you know when you've received a full command, then grab that string and process it. You also have to empty your buffer upon every complete string.
Personally i wouldn't use a created buffer but a local var appened to itself fed from data.text. I'd post an example but i'm on an iPad.
The biggest issue with the Sanyo (Eiki, Christie, whoever else OEM's from Sanyo) is that the projector doesn't reply with anything that says to which command it is replying. Whenever I work with these projectors, I just keep track of the last command I sent and parse the response from there. For instance, I recently programmed a Christie DHD800, which is OEM'd from Sanyo and uses this same protocol. When you send the CR3 command (query for lamp hours), it sends back something similar to 00034 00034 [CR]. This says that the projector has 2 lamps, and both lamps have been on for 34 hours. I then parsed the response based on what the last command sent to the projector was. See the example below for more details.
I know I'm not following good procedure by doing the variable that concatenates from data.text, but this works with the projector I'm using. Hope that helps.
Does this actually work? Does WAIT_UNTIL work differently to WAIT with regards to referring to variables that may have expired (cCMD in this case) ?
Yes, it works.
As I understand WAIT - the processor will create another thread somewhere else in the ether which is why it loses all access to local variables. I thought WAIT_UNTIL was the same? Am I wrong?
Or can WAIT also still maintain access to passed parameter variables after the function has exited?
There are no additional threads. When the code comes across a wait the wait is put into a queue structure that holds the wait id or name, the time and a pointer to the code segment to execute, either 1 line or brace to brace immediately following the wait pointer. The wait queue is regularly checked and their times decremented and when their time is reached they execute the code refenced by the pointer. Since stacks don't hold their value or even exist after after the code that created them completes they can't be referenced later when the wait executes a sub section of that code. Not a problem with locals or globals though. Of course those values may not be what you expected by the time the wait executes.
As long as it's declared global or local from the calling section of code then it's all good.
I forgot parameters are passed by reference instead of value (that is right isn't it? lol).