QuickAudine

USB interface for the Audine CCD camera
Update: 26/01/2003


Sélectionnez la langue


QuickAudine comes in the form of a small casing and is used to connect the Audine camera to a computer fitted with a USB interface (Universal Serial Bus). It is NOT necessary to modify the camera. Even for non-experts, the installation is very easy due to the Plug&Play characteristic of the USB interface.

Compared to the initial parallel interface of the Audine, QuickAudine has the following advantages:


The QuickAudine interface in action. It is placed in a little casing that you see here connected to the camera by a short parallel cable. The initial parallel cable of the Audine camera can be used for that purpose. On the other side of the casing, the USB cable goes to the computer.

QuickAudine is available in two ways:

QuickAudine was designed by Thierry Maciaszek, with the collaboration of the members of the group Pixels & Cassoulet.

Short Description

The heart of the interface is an FT245 circuit (FTDI Chip). A 16F876 PIC microcontroller at 20 MHz supplements the system. This microcontroller emulates the operation of the printer port and implements the reading code of the Audine camera. The code of the 16F876 is written in FlashBasic.

Programming examples of the FT245 chip can be found on the FTDI site. One of the main interests of these chips is that its manufacturer puts their drivers at your disposal free and free of rights. The reliability of this code seems excellent.

A simple communication protocol between QuickAudine and the PC was written. Once these parameters are loaded in the memory of the PIC controller (image format , binning, etc), the command is returned to the PC to count the integration time. It is then the PIC code which takes over to read the CCD, pixel after pixel, and to transmit digital information towards the PC. The interface is compatible not only with the Audine series, but also with its many clones and in particular the Genesis camera produced in the USA.

You will find at the end of this page a programming example of the interface board through a specially written DLL (this DLL is used for example by the Pisco program to manage Audine).

The printed circuit board is carrying the FT245 chip (small square at the top) and the 16F876 controller mounted on a socket. Two LEDs make it possible to check the operation of the system.

Installating QuickAudine

When first connecting the interface to the computer, the operating system immediately detects a new peripheral equipment. At this stage, you must provide the driver of the interface. It can be freely downloaded from the FTDI site . You can also get a version by clicking here (unzip the ZIP file "DRIVERS.ZIP" of 50K and copy the files extracted to a diskette or a CDROM for example).

When first connecting QuickAudine, this is the dialog box you will see on screen (Windows XP system):

Choose the option "Install from a specified location" and click on the "Next" button. A new dialog box appears:

Click on "Next". After a while, you will be asked for the location of the interface driver:

Give the path of the floppy, the CDROM, or the folder where you copied the driver installation files.

A warning message is displayed on the screen. Dont panic (!) and click on "Continue".

After a few seconds, Windows tells you that the installation is completed. The green indicator of the interface is lit. You can now use QuickAudine! You see, this is fairly easy.

Using Pisco with the QuickAudine interface

You must have Pisco version 2.0.

To download Pisco V2.0, click here. Before installing version 2.0, it is recommended to uninstall any previous version.

Run Pisco V2.0 and to go to the "Settings" tab , then click on the "Advanced Settings" button . The following dialog box appears:

Choose the "USB Interface" option. Also choose to switch off the amplifier during the exposure, which is always recommended.

Click on "OK".

In the "Settings" tab, if your Audine camera is fitted with an shutter, you may want to define the time given to the shutter to close before the image is read. You can use a delay of up to 2.4 seconds with QuickAudine.

You can now acquire your first image.

When the image is read after the exposure time, the red indicator of the interface comes on deemly. If your computer is slow, or if the USB is busy, the transfer from the camera to the computer might be altered. If so, the red LED becomes intermittlently brighter. This results in deem horizontal lines in the image as shown below:

This image comes from an Audine KAF-1600 and is acquired in binning 2x2. The exposure time is 5 seconds without cooling, which explains the many hot points in the image. Several defective pixels also disturb the reading of the columns (vertical lines). Horinzontal lines are caused by the problem of temporary slowdown in image reading. During this reading, the PC was connected to the network via a DSL moden connected on the USB port, which is not recommended at all for a clean reading of the image! Of course you can remove this USB load but this problem can be easily removed by cooling the camera, as shown in the following image:

 

Programming example with QUICKA.DLL

By installing Pisco, a DLL with the name QUICKA.DLL is automatically copied in the folder windows/system (under Windows 98) or the folder windows/system32 (under Windows 2000, XP).

You can download this DLL independently of Pisco and use it for your own applications.

Click here to download QUICKA.DLL (file of 30 KB - V1.1).

The C sources of QUICKA.DLL can be downloaded by clicking here (sources.zip file of 15 KB). You will find all you need to carry out a compilation under Visual C++ 6.0. These sources are free of rights and can be freely modified. However, we ask you to share your tips and tricks with the community of Audine and derived camera users through publications (Web sites, articles or others).

Here a source code sample in VisualBasic 6.0 :

    ------------------------
(1) Declare QUICKA functions
    ------------------------

Public Declare Function usb_loadlib Lib "QUICKA.DLL" () As Integer
Public Declare Function usb_closelib Lib "QUICKA.DLL" () As Integer
Public Declare Function usb_init Lib "QUICKA.DLL" () As Integer
Public Declare Function usb_end Lib "QUICKA.DLL" () As Integer
Public Declare Function usb_write Lib "QUICKA.DLL" (ByVal v As Integer) As Integer
Public Declare Function usb_start Lib "QUICKA.DLL" (ByVal KAF As Integer, _
ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer, _
ByVal bin_x As Integer, ByVal bin_y As Integer, ByVal shutter As Integer, _
ByVal shutter_mode As Integer, ByVal ampli_mode As Integer, ByVal acq_mode As Integer, _
ByVal d1 As Integer, ByVal d2 As Integer, ByRef imax As Integer, _
ByRef jmax As Integer) As Integer
Public Declare Function usb_readaudine Lib "QUICKA.DLL" (ByVal imax As Integer, _
ByVal jmax As Integer, ByRef buf As Integer) As Integer

    -----------------------------
(2) Some variable declarations...
    -----------------------------

Dim shutter As Integer, shutter_mode As Integer
Dim ampli_mode As Integer, d1 As Integer, d2 As Integer
Dim x1 As Integer, x2 As Integer, y1 As Integer, y2 As Integer
Dim bin_x As Integer, bin_y As Integer
Dim KAF As Integer, program as Integer, r As Integer
Dim speed As Integer
Dim imax As Integer, jmax As Integer
Dim delay As Double 

    ------------------------------
(3) Load the USB library functions
    ------------------------------

r = usb_loadlib() ' Register the FTDI USB functions
If r <> 0 Then
   MsgBox ("ERROR: QuickAudine USB interface driver not found")
   Exit Sub
End If

r = usb_init() ' Check physical presence of QuickAudine interface
If r <> 0 Then
   MsgBox ("ERROR: QuickAudine USB interface not connected")
   Exit Sub
End If

r = usb_end() ' End of the check

    ------------------------------------------------------------------
(4) Configuration of the acquisition, clear the CCD and start exposure
    ------------------------------------------------------------------

shutter = 1 ' Synchro shutter (0 value = close shutter)
shutter_mode = 0 ' Inversion of the shutter command (1 value = inverted mode)
ampli_mode = 1 ' shutdown the CCD amplifier during exposure (0 value = always on)
delay = 1.2 ' delay in seconds between shutter close and effective reading of the images
If delay > 2.4 Then  ' 2.4 seconds is the max. value
   d1 = 0
   d2 = 15
Else
   d1 = 0
   d2 = CInt(6.25 * delay)
End If
x1 = 1 : y1 = 1 : x2 = 768 : y2 = 512 ' digitized image zone (KAF-0400 full frame example)
bin_x = 1 : bin_y = 1 ' binning factor (valid value: 1, 2, 3 and 4)
KAF = 1 ' CCD model (1 = KAF0400 , 2 = KAF1600)
program = 1 ' version of the QuickA internal program version
speed = 6 ' speed of the interface (valid value: 1...15 - standard value=6)

' Setup of the acquisition
' Note: the usb_start function return the effective size of the image (imax, jmax)
r = usb_start(KAF, x1, y1, x2, y2, bin_x, bin_y, shutter, shutter_mode, _
              ampli_mode, program, d1, d2, speed, imax, jmax)
If r = 12 Then
   MsgBox ("Error: QuickAudine USB interface USB not ready")
   Exit Sub
ElseIf r = 16 Then
   MsgBox ("Error: Dialog problem with the QuickAudine USB interface")
   Exit Sub
ElseIf r = 17 Then
   MsgBox ("Error: USB data transmission error")
   Exit Sub
End If

    -------------------------------
(5) Gestion of the integration time
    -------------------------------

...
... Your code
...

    -------------------
(6) End of the exposure
    -------------------

r = usb_write(255) ' CCD amplifier on
Sleep (100) ' small delay
r = usb_write(255) ' Close the shutter

    --------------
(7) Read the image
    --------------

' allocate memory (note: option base 0 for the arrays)
ReDim buffer(imax - 1,jmax - 1) As Integer

r = usb_readaudine(imax, jmax, buffer(0, 0))

' Note: The reading start after the delay (d1, d2) relative to the shutter shutdown

    -------------------------------------------
(8) Erase USB FTDI library functions (optional)
    -------------------------------------------

r = usb_closelib()

' The image is now in the 768x512 - 16-bits array BUFFER(i,j)

' It's all !

 

Direct call of the FTDI functions

Visual C++ program sample for read the Audine camera (direct use of FTDI routines).

//////////// C DRIVER ROUTINES FOR QuickAudine USB interface ////////////
//

// Some declaration in the header of your program
typedef DWORD FT_HANDLE;
typedef DWORD FT_STATUS;
EXTERN FT_HANDLE UsbHandle;
EXTERN HMODULE g_usb_module;

typedef FT_STATUS (WINAPI *PtrToOpen)(PVOID, FT_HANDLE *);
EXTERN PtrToOpen g_usb_Open;
EXTERN int UsbOpen(PVOID);
typedef FT_STATUS (WINAPI *PtrToClose)(FT_HANDLE);
EXTERN PtrToClose g_usb_Close;
EXTERN int UsbClose();
typedef FT_STATUS (WINAPI *PtrToRead)(FT_HANDLE, LPVOID, DWORD, LPDWORD);
EXTERN PtrToRead g_usb_Read;
EXTERN int UsbRead(LPVOID, DWORD, LPDWORD);
typedef FT_STATUS (WINAPI *PtrToWrite)(FT_HANDLE, LPVOID, DWORD, LPDWORD);
EXTERN PtrToWrite g_usb_Write;
EXTERN int UsbWrite(LPVOID, DWORD, LPDWORD);
typedef FT_STATUS (WINAPI *PtrToResetDevice)(FT_HANDLE);
EXTERN PtrToResetDevice g_usb_ResetDevice;
EXTERN int UsbResetDevice();
typedef FT_STATUS (WINAPI *PtrToGetQueueStatus)(FT_HANDLE, LPDWORD);
EXTERN PtrToGetQueueStatus g_usb_GetQueueStatus;
EXTERN int UsbGetQueueStatus(LPDWORD);

///////////////////////////////////////////////////////
// First, load FTDI library at the start of the program
///////////////////////////////////////////////////////
open_ftdi();

// At the end of the program call to the routine close_libftdi()

/////////////////////////////////
// Main routine for read an image
/////////////////////////////////
unsigned long longueur_buffer=1024;  
char ReadBuffer[1024];
DWORD Nb_RxOctets;
unsigned long int i,j,k;
unsigned char tx[2], rx[2];
double integration;
int flag_ampli;  
int ampli;
int obturateur;
int inv_obturateur;
int nb_fastvidage;
int kaf,i_prog,speed;
int x1,y1,x2,y2,bin_x,bin_y;
int imax,jmax;

///////////////////////////
//// Acquisition parameters
///////////////////////////
i_prog = 1;  // prog. version
kaf=1; // 1 = KAF-0400 - 2 = KAF-1600  
x1=1; y1=1; x2=kaf*768; y2=kaf*512;
bin_x=1;  // valuable value : 1, 2, 3, 4
bin_y=1;
obturateur=1; // 1 = synchro - 0 = closed 
inv_obturateur=0; // 0 : no inverted - 1 : inverted
nb_fastvidage=2;  // number of fast clear of the CCD - max. 15
ampli=1;  // 1=shutdown during integration time
speed=6:  // speed of the interface (value between 1...15 - standard value=6)

x1=x1/bin_x;
x2=x2/bin_x;
y1=y1/bin_y;
y2=y2/bin_y;
if (x1<=0) x1=1;
if (y1<=0) y1=1;
if (x2<=0) x2=10;
if (y2<=0) y2=10;

imax=x2-x1+1;
jmax=y2-y1+1;

if (InitUsb()==PB) exit(-1);  // check USB interface

unsigned long nb_pixel = imax*jmax; // size of the image
int X1_H_1 = x1/256;
int X1_L_2 = (x1-X1_H_1*256)/16;
int X1_L_1 = x1-X1_H_1*256 - X1_L_2*16;
int X2_H_1 = x2 / 256;
int X2_L_2 = (x2 - X2_H_1 * 256) / 16;
int X2_L_1 = x2 - X2_H_1 * 256 - X2_L_2 * 16;
int Y1_H_1 = y1/256;
int Y1_L_2 = (y1-Y1_H_1*256)/16;
int Y1_L_1 = y1-Y1_H_1*256 - Y1_L_2*16;
int Y2_H_1 = y2 / 256;
int Y2_L_2 = (y2 - Y2_H_1 * 256) / 16;
int Y2_L_1 = y2 - Y2_H_1 * 256 - Y2_L_2 * 16;

tx[0]=0;
tx[1]=i_prog * 16;
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=kaf*16;
usbWrite(tx,2,&Nb_RxOctets);
tx[1]=bin_x*16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=bin_y*16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X1_L_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X1_L_2 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X1_H_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X2_L_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X2_L_2 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=X2_H_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y1_L_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y1_L_2 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y1_H_1 * 16;      
usbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y2_L_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y2_L_2 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=Y2_H_1 * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=nb_fastvidage * 16;      
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=obturateur * 16;             
UsbWrite(tx,2,&Nb_RxOctets);
tx[1]=inv_obturateur * 16;             
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=16*0; // q1            
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=16*15; // q2    delay before shutter closing = (q1+16.q2)*10 ms        
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=ampli * 16;             
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=speed * 16;   
// speed of the interface (value between 1 and 15 - normal value = 6) 
UsbWrite(tx,2,&Nb_RxOctets);tx[0]=0;
tx[0]=0;
tx[1]=0;  
// reserved 
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=0;  
// reserved 
UsbWrite(tx,2,&Nb_RxOctets);
tx[0]=0;
tx[1]=0;  
// reserved 
UsbWrite(tx,2,&Nb_RxOctets);

////////////////
// Clear the CCD
////////////////
k=0;
UsbGetQueueStatus(&Nb_RxOctets);
while (Nb_RxOctets==0)
  {
  UsbGetQueueStatus(&Nb_RxOctets);
  sleep(100); // TimeOut
  k++;
  if (k==200)
     {
     msg("USB interface not ready");
     CloseUsb();
     exit(-1);
     }
  }

UsbRead(rx,1,&Nb_RxOctets);
if ((rx[0] & 240) / 16 != 11)
  {
  msg("Data transmission error");
  CloseUsb();
  exit(-1);
  }

///////////
// Exposure
///////////

// Your code...

//////////////////
// End of exposure
//////////////////
tx[0]=0;
tx[1]=255;             
UsbWrite(tx,2,&Nb_RxOctets);  // ampli on
sleep(100); // delay
tx[0]=0;
tx[1]=255;             
UsbWrite(tx,2,&Nb_RxOctets);  // close shutter


//////////////////////
// Image read
//////////////////////
// p is a pointer to a short type buffer of size (imax,jmax)
j=0;
k=0;
int v1,v2,v3,v4,v;
while (j<=4*nb_pixel-longueur_buffer)
  {
  UsbGetQueueStatus(&Nb_RxOctets);
  while (Nb_RxOctets<longueur_buffer) UsbGetQueueStatus(&Nb_RxOctets);
  UsbRead(ReadBuffer,longueur_buffer,&Nb_RxOctets);
  for (i=0;i<Nb_RxOctets;i+=4)
     {
     v1=(int)ReadBuffer[i] & 15;
     v2=(int)ReadBuffer[i+1] & 15;
     v3=(int)ReadBuffer[i+2] & 15;
     v4=(int)ReadBuffer[i+3] & 15;
     v=v1+16*v2+256*v3+4096*v4;
     if (v>32767)
        p[k]=32767;
     else
        p[k]=(short)v;
     k++;
     }
  j=j+longueur_buffer;
  }

if (j!=4*nb_pixel)
   {
   UsbGetQueueStatus(&Nb_RxOctets);
   while (Nb_RxOctets<4*nb_pixel-j) UsbGetQueueStatus(&Nb_RxOctets);
   UsbRead(ReadBuffer,4*nb_pixel-j,&Nb_RxOctets);
   for (i=0;i<Nb_RxOctets;i+=4)
      {
      v1=(int)ReadBuffer[i] & 15;
      v2=(int)ReadBuffer[i+1] & 15;
      v3=(int)ReadBuffer[i+2] & 15;
      v4=(int)ReadBuffer[i+3] & 15;
      v=v1+16*v2+256*v3+4096*v4;
      if (v>32767)
         p[k]=32767;
      else
         p[k]=(short)v;
      k++;
      }
   }
CloseUsb();

/********* InitUsb ***********/
int InitUsb()
{
if (UsbOpen(0)!=0)
  {
  msg("USB not Ok");
  return(PB);    
  }
UsbResetDevice();
return(OK);
}

/*********** CloseUsb **********/
int CloseUsb()
{
UsbClose();
return(OK);
}

//********************************************************************
int UsbRead(LPVOID lpvBuffer, DWORD dwBuffSize, LPDWORD lpdwBytesRead)
{
return (*g_usb_Read)(UsbHandle,lpvBuffer,dwBuffSize,lpdwBytesRead);
}       

//********************************************************************
int UsbWrite(LPVOID lpvBuffer,DWORD dwBuffSize,LPDWORD lpdwBytes)
{
return (*g_usb_Write)(UsbHandle,lpvBuffer,dwBuffSize,lpdwBytes);
}       
 
//********************************************************************
int UsbOpen(PVOID pvDevice)
{
return (*g_usb_Open)(pvDevice,&UsbHandle);
}       

//********************************************************************
int UsbClose()
{       
return (*g_usb_Close)(UsbHandle);
}       

//********************************************************************
int UsbResetDevice()
{
return (*g_usb_ResetDevice)(UsbHandle);
}       

//*********************************************************************
int UsbGetQueueStatus(LPDWORD lpdwAmountInRxQueue)
{
return (*g_usb_GetQueueStatus)(UsbHandle,lpdwAmountInRxQueue);
}       

/****************** OPEN_LIBFTDI ******************/
/* Load FTDI library                              */
/**************************************************/
int open_libftdi(void)
{
g_usb_module=LoadLibrary("Ftd2xx.dll"); 
if (g_usb_module == NULL)
  {
  AfxMessageBox("Error: Can't Load ft8u245.dll");
  return 1;
  }

g_usb_Write=(PtrToWrite)GetProcAddress(g_usb_module, "FT_Write");
if (g_usb_Write == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_Write");
  return 1;
  }

g_usb_Read = (PtrToRead)GetProcAddress(g_usb_module, "FT_Read");
if (g_usb_Read == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_Read");
  return 1;
  }

g_usb_Open = (PtrToOpen)GetProcAddress(g_usb_module, "FT_Open");
if (g_usb_Open == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_Open");
  return 1;
  }

g_usb_Close = (PtrToClose)GetProcAddress(g_usb_module, "FT_Close");
if (g_usb_Close == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_Close");
  return 1;
  }

g_usb_ResetDevice = (PtrToResetDevice)GetProcAddress(g_usb_module, "FT_ResetDevice");
if (g_usb_ResetDevice == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_ResetDevice");
  return 1;
  }

g_usb_GetQueueStatus = (PtrToGetQueueStatus)GetProcAddress(g_usb_module, "FT_GetQueueStatus");
if (g_usb_GetQueueStatus == NULL)
  {
  AfxMessageBox("Error: Can't Find FT_GetQueueStatus");
  return 1;
  }
return 0;
}

/************** CLOSE_LIBFTDI *************/
/* Libère la librairie FTDI de la mémoire */
/******************************************/
int close_libftdi(void)
{
FreeLibrary(g_usb_module);
return(0);
}

Back