I am working on the VISCA protocol recently. I write here for my record. Visca is a protocol developed by SONY to control the camera, which usually communicates via RS232 (read some data, rs485 is also useful).
1. Command format
The basic unit of command communication is called a Packet. A package is 3 to 16 bytes in length and consists of a header, a message body, and an terminator. The first byte of a command package is called a Header. The high half byte is composed of 1 (the highest bit, fixed as 1) and the address of the sender (controller) (the address is generally 0), and the low half byte is composed of 0 and the address of the device (camera) (or “number”). From the composition format, a maximum of 7 external cameras can be connected. If a command is sent to camera 1, the command header is 0x81. The last byte of the command package is the terminal symbol, which is fixed at 0xff. The middle byte is called the message body. In the protocol description, the command header is written as 8x, where x indicates the camera address.
There are two types of commands: Command and Inquiry. The former sends commands directly to the camera, while the latter gets data from the camera.
The command package format is as follows:
8 x QQ RR... FFCopy the code
QQ is a command category, 01 is a common command, and 09 is a query command. RR indicates a Category code. X is the camera address. Range of 1 ~ 7.
Second, the response
Each command has a response packet in the following format:
X0... ... FFCopy the code
The X range is 9 F, and the value is the camera number +8. End with FF. When a normal command is sent, the camera returns an ACK response, but a query command does not. ACK response packet format: X0 41 FF Common command response packet format: X0 51 FF Query command response packet format: X0 51… FF Where, X is in the range of 9, F is the camera address value +8. The response packet of the query command contains data. Each data is different. You can query the protocol document.
The format of the error information is as follows: Syntax error: X0 61 02 FF command cancelled: X0 61 04 FF No socket: X0 61 05 FF command not executed: X0 61 41 FF The X value is the same as the preceding one. The scope of “socket” is not yet known. These values are what the code uses to make its judgment.
Iii. Remarks of the Protocol Document
For the description of QPRS in the protocol document, directly put it into the 16-bit hexadecimal data (hexadecimal format is 0xAAAA). For example, if the response packet format of a command is y0 50 0p 0Q 0r 0s FF, the actual data obtained is 0xpqrs. For example, 01, 02, 03, 04, the corresponding data is 0x1234. And vice versa. In the code to use the shift to achieve. Let’s look at some classic command formats.
1. A command with no parameters
Power on the camera CAM_Power Command format: 8x 01 04 00 02 FF X in 8X indicates the camera number. Such commands can be directly assembled by command fields.
2. Commands with parameters
The format of the CAM_Zoom command is 8x 01 04 47 0p 0Q 0R 0S FF. The PQRS in “0P 0Q 0R 0s” constitutes the Focus Position parameter. When the command is assembled, this parameter is shifted to the corresponding field in turn. If the parameter value is 0x1234, the corresponding field is 01 02 03 04. Using the CAM_AFMode command, you can set the values of Active and Interval Time in the following format: 8x 01 04 27 0p 0q 0r 0s FF “0p 0q” corresponds to movement time, “0r 0s” corresponds to Interval, when assembling command, should be assembled separately. See above for details.
3. Query command without parameters
Like the CAM_PowerInq query command, send 8x 09 04 00 FF and directly return y0 50 02 FF or Y0 50 03 FF where “y0 50 02 FF” is the returned data and the y value is the camera number +8. For such a command, the corresponding state can be obtained by reading the third byte directly.
4. Query commands with parameters
For example, the CAM_ZoomPosInq command sends 8x 09 04 47 FF and returns y0 50 0p 0q 0r 0s FF. In the query command, most commands have variable data. “0p 0q 0r 0s” in “y0 50 0p 0q 0r 0s FF” needs to be shifted to know the exact value, and the corresponding value is 0xpqrs.
Four, implementation,
Fortunately, there is already a libvisca open source project for Visca (see Resources). Here’s a look at the project, make some minor changes, and write the key implementation code. I will not say more about the opening, reading, and closing of serial ports. Here’s how to encapsulate a command:
void _visca_append_byte(VISCAPacket_t *packet, unsigned char byte)
{
packet->bytes[packet->length]=byte;
(packet->length)++;
}
void _visca_init_packet(VISCAPacket_t *packet)
{
// set it to null
memset(packet->bytes, '\0', sizeof(packet->bytes));
// we start writing at byte 1, the first byte will be filled by the
// packet sending function(_visca_send_packet). This function will also append a terminator.
packet->length=1;
}
Copy the code
These two functions are command padding, one character per call to _visca_append_byte, and before that, _visca_init_packet is called to initialize the length of the packet. Of course, the implementation can also directly send each command in an array form together. The _visca_send_packet is populated with header and tail data without the caller having to worry about the actual command data. This is also a benefit of using VISCAInterface_t (as you’ll see when you write pelco’s implementation later).
int32_t _visca_send_packet(VISCAInterface_t *iface, VISCACamera_t *camera, VISCAPacket_t *packet)
{
// check data:
if ((iface->address>7)||(camera->address>7)||(iface->broadcast>1))
{
com_print("(%s): Invalid header parameters\n",__FILE__);
com_print("addr: %d %d broadcast: %d(0x%x)\n",iface->address,camera->address,
iface->broadcast,iface->broadcast);
return VISCA_FAILURE;
}
// build header:
packet->bytes[0]=0x80;
packet->bytes[0]|=(iface->address << 4);
if (iface->broadcast>0)
{
packet->bytes[0]|=(iface->broadcast << 3);
packet->bytes[0]&=0xF8;
}
else
{
packet->bytes[0]|=camera->address;
}
// append footer(0xff)
_visca_append_byte(packet,VISCA_TERMINATOR);
return _visca_write_packet_data(iface,packet);
}
Copy the code
The command response package functions are as follows:
int32_t _visca_get_reply(VISCAInterface_t *iface, VISCACamera_t *camera) { // first message: ------------------- if (_visca_get_packet(iface)! = VISCA_SUCCESS) return VISCA_FAILURE; iface->type=iface->ibuf[1]&0xF0; // skip ack messages while (iface->type==VISCA_RESPONSE_ACK) { if (_visca_get_packet(iface)! =VISCA_SUCCESS) return VISCA_FAILURE; iface->type=iface->ibuf[1]&0xF0; } switch (iface->type) { case VISCA_RESPONSE_CLEAR: return VISCA_SUCCESS; break; case VISCA_RESPONSE_ADDRESS: return VISCA_SUCCESS; break; case VISCA_RESPONSE_COMPLETED: return VISCA_SUCCESS; break; case VISCA_RESPONSE_ERROR: return VISCA_CMDERROR; break; } return VISCA_FAILURE; }Copy the code
Some macros are defined as follows:
/* response types */
#define VISCA_RESPONSE_CLEAR 0x40
#define VISCA_RESPONSE_ADDRESS 0x30
#define VISCA_RESPONSE_ACK 0x40
#define VISCA_RESPONSE_COMPLETED 0x50
#define VISCA_RESPONSE_ERROR 0x60
Copy the code
In fact, the judgment is very simple, according to the error code given by the protocol to judge one by one. Other code, refer directly to libvisca, not listed here.
Resources: 1, the visca protocol library: open source libvisca: damien.douxchamps.net/libvisca/ 2, visca protocol wiki is introduced: en.wikipedia.org/wiki/VISCA_…
Postscript: at the time of writing, I have no hardware resources at hand. This article is written according to the description in the libvisca and visca protocol documents, which should not be of practical value.