QHY163 Low Level (1) USB Protocol


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #15 on: March 11, 2017, 11:16:21 PM »
Qiu Hongyun


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #16 on: March 11, 2017, 11:16:34 PM »
Qiu Hongyun


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #17 on: March 11, 2017, 11:28:36 PM »

Temperature Control

CCP1:     Control Mode  1=Auto temperature regular loop  0=manual set the PWM (0-255) range
CCP2:     Target PWM value This value will be active when set control mode to manual control
CCP3:     Temperature unit select  0=degree  1=ADU unit  (QHY163 use the degree)
CCP4..5: Target temperature (0.1 degree unit)    This value will be active when set to CCP3=0, degree unit
CCP6..7: Target temperature (ADU unit)        This value will be active when set to CCP3=1, adu unit

*1. The temperature unit is 0.1C  for example:

set temp to +10C

CCP1     = 1
CCP3     = 0
CCP4..5 = 100

set temp to -10C

CCP1     = 1
CCP3     = 0
CCP4..5 = 65436   (65436 is -100 for signed integer)

use manual mode , set PWM = 12
CCP1     = 0
CCP2     = 12
« Last Edit: March 11, 2017, 11:30:43 PM by QiuHY »
Qiu Hongyun


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #18 on: March 13, 2017, 10:36:50 AM »

Qiu Hongyun


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #19 on: March 13, 2017, 10:37:44 AM »
VendRequest 0XD2

Vendrequest 0XD2 direction is IN. The host will get 64byte Camera Status Information(CSI) data from camera.

The data structure is :

CSI0      current sensor readout speed. For cmos camra the unit is MHz. for CCD camera it is not an accurate data. Normally the lowest speed is 0, normal speed is 1, high speed is 2
CSI1..4  the time left to exposure end, unit is microsec. ) CSI1=MSB  CSI4=LSB  QHY163 does not support this function
CSI5..8  the exposure time which had been set

CSI9   firmware version year
CSI10 firmware version month
CSI11 frimware version day

CS12 temperature readout unit. 0=support degree output   1=support ADU unit output  2=support both output

CSI13..14 current temperature, unit is 0.1 degree. signed short number
CSI15..16 target temperature,unit is 0.1 degree. signed short number
CSI17       current PWM value (0-255)
CSI18       current temperature controller working mode    1=automatic   0=manual set the pwm

CSI19..21  current DDR data value    CSI19=MSB CSI21=LSB 

CSI22..23  current temperature (ADU unit)
CSI24..25  target temperature (ADU unit)

CSI28..29 Image Size X
CSI30..31 Image Size Y

CSI32   Image bit depth.       0=8bit   1=16bit
CSI33   Current USB Speed.  1=usb1.1  2=usb2.0  3=usb3.0

CSI46 camera model index.    no used in QHY163
CSI47 sensor type  (monochrom, bayer RGB, wRGB etc)     0:mono    1: RGB   

CSI48...63 camera series number (16byte)

Reference code to readout the information with 0XD2 command
Code: [Select]
unsigned char c_firmware_year;
unsigned char c_firmware_month;
unsigned char c_firmware_day;

int c_data_in_ddr;
unsigned int c_expTime;
unsigned int c_expTime_toend;

unsigned char c_seriesNumber[16];
unsigned char c_cmosfreq;

unsigned char c_temp_unit;

    short c_current_temp_degree;
short c_target_temp_degree;
unsigned short c_current_temp_adu;
unsigned short c_target_temp_adu;

unsigned char c_pwm;
unsigned char c_isAuto;

unsigned char c_camera_submodel;
unsigned char c_sensor_type;

unsigned short c_imageX;
unsigned short c_imageY;

unsigned char c_is16bit;
unsigned char c_usbspeed;

unsigned int c_actual_expTime;

unsigned short index, value;
unsigned char data[64];

unsigned int length = 64;
index = 0;

QHYCCDVendRequestRead(g_hCam, 0xd2, 0, index, length, data);


c_cmosfreq         =data[0];
c_expTime_toend=    data[1]*256*256*256+data[2]*256*256+data[3]*256+data[4];
c_expTime        =  data[5]*256*256*256+data[6]*256*256+data[7]*256+data[8];

c_firmware_year  =data[9];
c_firmware_month =data[10];
c_firmware_day   =data[11];

c_target_temp_degree =data[15]*256+data[16];


c_data_in_ddr=    data[19]*256*256+data[20]*256+data[21];

c_target_temp_adu =data[24]*256+data[25];




for(int i=0;i<16;i++){

debug_print "cmos freq:     " + AnsiString(c_cmosfreq);
debug_print "exptime to end:" + AnsiString(c_expTime_toend);
debug_print "target exptime:" + AnsiString(c_expTime);
debug_print "firmware year: " + AnsiString(c_firmware_year);
debug_print "firmware month:" + AnsiString(c_firmware_month);
debug_print "firmware day:  " + AnsiString(c_firmware_day);
debug_print "data in ddr 2kb" +    AnsiString(c_data_in_ddr);
debug_print "temp unit:"      +    AnsiString(c_temp_unit);
debug_print "current temp degree"+ AnsiString((double)c_current_temp_degree/10);
debug_print "target temp degree" + AnsiString((double)c_target_temp_degree/10);
debug_print "current temp adu"+ AnsiString(c_current_temp_adu);
debug_print "target temp adu" + AnsiString(c_target_temp_adu);

debug_print "c_pwm:         " + AnsiString(c_pwm);
debug_print "c_isAuto:      " + AnsiString(c_isAuto);
debug_print "c_camera_submodel"+AnsiString(c_camera_submodel);
debug_print "c_sensor_type    "+AnsiString(c_sensor_type);

debug_print "imageX:        " + AnsiString(c_imageX);
debug_print "imageY:        " + AnsiString(c_imageY);
debug_print "is16BIT        " + AnsiString(c_is16bit);
debug_print "usb speed      " + AnsiString(c_usbspeed);

for(int i=0;i<16;i++){
  debug_print "GUID"+AnsiString(i)+":"+c_seriesNumber[i];
« Last Edit: March 13, 2017, 10:50:59 AM by QiuHY »
Qiu Hongyun


  • *****
  • 5000
    • View Profile
    • Email
Re: QHY163 Low Level (1) USB Protocol
« Reply #20 on: March 13, 2017, 11:09:20 AM »
Image Readout of QHY163

QHY163 has two endpoint. One is the control end point which is used for vend request. Another is the bulk(in) endpoint for data transfer. 

This bulk in endpoint address is 0x81

In both Single frame capture and video streaming mode. The QHY163 use four byte as image head identity

0XEE  0X11 0XDD 0x22

The image head will comes with a PKEND signal. Since PKEND will cause one USB read return immediately. So the four number should always appear in the end of one USB read.

Normally there is two conditions to show it is a frame beginning. You can use this to trig a frame start.

1. readout a 4 byte package and it is just 0xEE,0X11,0XDD,0X22.
2. readout a package above 4 byte and the last 4 byte is 0xEE,0X11,0XDD,0X22

Video Streaming Mode

Please refer the white paper of QHYCCD low level(1) usb protocol

Single Frame Mode

Currently the QHY163 single frame data readout includes two frame. The first frame is a frame with no use. The second frame is a frame that we need.

The readout progress is like this:

1.Set CCC=0xA0 to start single frame initialize   (the camera will be set to 4720*3534 16bit mode, default exposure is 20ms,default USB bandwdith control is 0)
2.Set ROI if necesseary
3.Set exposure time
4.Set Analog Gain and digital gain (for DSO capture it is no necessary to use any digital gain. so Digital gain should be set to 64 for digital gain x1)
5.Set Offset
6.Set CCC=0XA6 to start a single capture
7.read vendrequest 0xd2 to get to know how many data is transferred into DDR.Please note the unit is 2KB. For example, if the number is 32000, it means the data in DDR is 32000*2KB=64MB.
8.You will find the first frame will transfered into DDR immdiately after starting single frame. And after exposure finished, the second frame will be transfered into DDR.
9.Wait till there is no more data come into the DDR (*1)
10.Readout the data with asyn or sync bulk read. It is best to remain a little data inside the DDR to avoid some problem happen (For example,  remain 20-40KB)  (*2)

*1 How to know the all image data were transferred into the DDR. This is some magic to play with. Since QHY163 has two frame. The first frame will start transfer immdiately , then wait the exposure then the secondary image will transfer. So it can not simply to use the method that check if there is no more data comes or not.  The best way is to use a threshold . First wait the data reach the threshold. (the threshold should exceed one frame length). then check if the data is changed . if the data is not change in two check. it shows the image transfer is finished.

Code: [Select]

Application->ProcessMessages() ;

debug_print "DDR memory is zero";


 while(dataInDDR<=threshold ){
         Application->ProcessMessages() ;


pre_dataInDDR = dataInDDR;      debug_print "the ddr data in last time:"+AnsiString(pre_dataInDDR);
dataInDDR=getUsedDDR();      debug_print "the ddr data in current time:"+AnsiString(dataInDDR);

Application->ProcessMessages() ;



*2 When readout each usb transfer. You can check the last four byte of the data to see if it is a head. If it is a head you can record the head position. Then you can find the secondary image head position and copy the data after this position to image buffer.

Code: [Select]
unsigned char ImgData[imgX * imgY * 4];

void __fastcall TForm1::Button43Click(TObject *Sender)

unsigned int l;

unsigned char data[4096];

unsigned long k=0;

unsigned long start_position=0;


for (int i=0; i < data_recevied_ddr/2-10; i++) {
  l = QHYCCDReadUSB_SYNC(g_hCam,0x81,4096,data,1500);

  if (l==0) {debug_print "one time out appear"; return;}

  else if (l==4) {
           debug_print "find a 4byte packet:"+AnsiString(i)+"packet";

  else if (l<4 && l>0) debug_print "find the size of"+AnsiString(l)+" packet";
  else if (l<4096 && l>4)debug_print "find the size of"+AnsiString(l)+" packet";


if (data[l-4]== 238 && data[l-3]==17 && data[l-2]==221 && data[l-1]==34){
start_position=k+l-1;debug_print "image head detected, position is :"+AnsiString(i);




   //the image MSB and LSB is different with the opencv's define. So swift them

   IplImage *img = cvCreateImageHeader(cvSize(imgX,imgY),16,1);
   img->imageData = (char *)ImgData+start_position+4096;

debug_print "finished transfer" ;

« Last Edit: April 29, 2017, 11:53:10 AM by QiuHY »
Qiu Hongyun