AN27079 - Developing PC Applications for USB-I2C Bridge

Developing PC Applications for USB-I2C Bridge
AN27079
Author: Andrew Smetana
Associated Project: Yes
Associated Part Family: CY8C24894
Software Version: C#, Visual Basic, Delphi, C++
Associated Application Notes: AN2352
Application Note Abstract
This application note describes how to use a USB-I2C bridge ActiveX control (bridge driver) in software designs. It discusses
the history of ActiveX, ActiveX interface documentation, and its use in popular programming environments (languages).

Introduction
The USB-I2C bridge is popularly used in many applications.
The bridge enables debugging the hardware and software of
PSoC® applications by connecting the board to a USB port
on a PC and communicating with the application’s I2C
interface.

The USB-I2C bridge software GUI simplifies use of the
bridge. It is a powerful tool that allows you to use many of
the bridge features from an easy-to-operate form. Some of
these features are:

Interactive communication through the I2C bus using a
simple script language

Configuration of the bridge and I2C bus (such as set
power and speed settings)

Build graphs in quasi-real time mode based on the data
from the I2C device
This is great, until you need to develop your own GUI using
the bridge. Developing your own GUI requires an
understanding of bridge protocol details, USB-HID device
functionality, and Windows APIs for I/O operations. In other
words, you must develop your own bridge driver. This is a
lot of work for one application, especially if it is not the key
function of your software. It is only a low level
communication protocol.

You do not have to work with low level Windows APIs to
communicate with the bridge; everything is hidden
inside an ActiveX control. It has bridge names (not
system PnP identifiers) to address one bridge or
another.
It enables you to use bridge ActiveX control in different
programming environments. It is a cross-language,
integrating technology. You are not limited to a single
development environment. Choose the language you
like best.
The ActiveX control is a high level abstraction of the
bridge hardware, developed for programmers.
A software-hardware model of a typical developer system is
shown in Figure 1 on page 2; the placement of Bridge
ActiveX control is also shown. It shows the “long path”
between the application and target device (bridge or I2C
device). ActiveX simplifies the path from application to
device from the standpoint of the software developer. You
need not know the details of the packet travel. The dash line
is the logical connection between software and target I2C
device established by the Bridge ActiveX Control.
Each application works with its own instance of the ActiveX
control. Two or more applications cannot work at the same
time with one bridge. This is done to eliminate collisions
between applications.
The special ActiveX control makes it easier for you to use
the bridge in your software applications. The advantages of
the ActiveX bridge driver are:

It is a simple software interface to the bridge hardware.
You need to just call the required function of the
ActiveX control to communicate with the I2C bus
devices and configure the bridge. There are no complex
bridge protocols.
May 5, 2010
Document No. 001-27079 Rev. *A
-1-
[+] Feedback
AN27079
Figure 1. Software-Hardware Model of Working Environment
Application 1
Application 2
Bridge ActiveX Control
(instance 1)
Bridge ActiveX Control
(instance 2)
Win APIs
Application N
...
Hid.dll
Bridge ActiveX Control
(instance N)
SetupAPI.dll
USB Driver Stack
USB Host Controller HW
USB cable
USB-I2C Bridge 1
I2C bus
...
USB-I2C Bridge 2
I2C bus
USB-I2C Bridge N
I2C bus
Device 1
Device 1
Device 1
Device 2
Device 2
Device 2
...
...
Device X
...
Device Y
Device Z
ActiveX Control for a Programmer
Bridge ActiveX control is implemented as an external COM-server. It is external because it is executed in its own context and
implemented as a Windows executable file. It can be run only within your application. It cannot be started as an independent
Windows application.
Figure 2. Application and Bridge Control Architecture with ActiveX Technology
C
A
L
L
E
R
S
Application (Client)
Bridge Reference
A
C
T
I
O
N
S
Bridge ActiveX Control (Server)
USB-I2C interface
implementation
Local Events
OnTransferFinished
OnTransferError
Sink – Events (Outgoing)
Interface Implementation
Source - Connection Point,
referenced to Sink
Events
Windows Events
OnBridgeConnect
OnBridgeDisconnect
Figure 2 clarifies the communication interface between the
application and the Bridge ActiveX Control. ActiveX (COM)
technology defines the application as a Client, and the
ActiveX (COM) control as a Server.
To start work with the Bridge Control, run the ActiveX control
from your client application. Register the ActiveX control in
Windows (instructions to follow) before running it. After that,
your client application creates a Bridge Control instance and
then it can reference the USB-I2C interface of the server in
the Bridge Reference variable. Then different fragments of
the client code (Callers in Figure 2) can use bridge services.
These functions are discussed later. Some of them are:
May 5, 2010
Win APIs (HW)
Requests

SendIICdata(BridgeID, SlaveAddress, Data) – sends an
array of data addressed by SlaveAddress to the I2C
device connected to the bridge with BridgeID.

ReadIICdata(BridgeID, SlaveAddress, DataLen, Data) –
reads DataLen bytes from the slave device of the
BridgeID bridge.

SetPower(BridgeID, PowerValue) – supply power to the
bridge (+5V,+3.3V, External Power).
Also shown in Figure 2 is the events (outgoing) interface.
This interface can be implemented in your client application,
Document No. 001-27079 Rev. *A
-2-
[+] Feedback
AN27079
but it is optional. This interface is called Sink, and the part of
the server (Bridge Control) that generates events for the
client is Source.
In some cases, it is useful to respond to events instead of
long polling. This saves system resources and allows the
processor to do more useful work. Using events, the server
provides information necessary for non-synchronous
operation.
OnBridgeDisconnect(BridgeID) – Fires when the bridge
is disconnected from the PC.

OnTransferFinished(Data) – Fires when the server
receives the result of an asynchronous operation.

OnTransferError(ErrorCode) – Fires when an error
occurs during an asynchronous operation.
Figure 3 is a communication diagram of a typical session
with the Bridge ActiveX Control. Usually, it consists of two
stages: initialization and working process. During the
initialization process, the following actions occur:
As a rule, a client application interested in the server events
connects its event interface (Sink) to the server, immediately
after the server is created. After that, the server directs all
events to the client Sink interface. The client’s Sink receives
notifications from the server and executes corresponding
Actions. Currently, four events are available.



Only the OnBridgeConnect and OnBridgeDisconnect events
can be used in your applications. The other two,
TransferFinished and TransferError are used in
asynchronous transactions. They are called from the bridge
side as a result of asynchronous requests to the bridge
services. The current Bridge ActiveX control supports only
synchronous (blocking) transactions. These events cannot
be used at this time. They may be added in the future.


Create a new instance of ActiveX Control.
Set an event mechanism between Client and Server.
Call the InitUSB2IIC() function to start communication.
During the working process the Client application can use
any Bridge services and respond to its events. All requests
from both sides (application and ActiveX Control) are
blocking (synchronous). Therefore, you should not do a lot
of work in the event handlers.
When the application is complete or terminates the ActiveX
Control does the same. It monitors its Client to know
whether it is alive. If it is dead, the Server terminates as well.
OnBridgeConnect(BridgeID,PnPId) – Fires when a new
bridge is connected to the USB port of the PC.
Figure 3. Typical Diagram of Interaction between Application and ActiveX Control
Application
Bridge ActiveX Control
new BridgeInstance
Initialization
stage
Connect Events
InitUSB2IIC(ProcessID)
Legend
OnBridgeConnect(BridgeID,PnP)
– Time of Object living
SetPower(BridgeID,+5V)
SetSpeed(BridgeID,100K)
– Object doesn’t exist
SendIICData(BridgeID,Addr,Data)
– Object is active
ReadIICData(BridgeID..Data)
Working
Process
...
OnBridgeDisconnect(BridgeID)
ExitProcess(ExitCode)
ExitProcess(ExitCode)
May 5, 2010
Document No. 001-27079 Rev. *A
-3-
[+] Feedback
AN27079
2.
Installing and Uninstalling
The current version of ActiveX Control contains only one file,
usb2iic.exe. Before initial use of the ActiveX Control in your
application (or after you get an updated version), register the
ActiveX control in Windows:
1.
Copy the control to your hard drive, for example in
C:\BridgeActiveX folder.
2.
Run the ActiveX Control from the command line with a
/regserver parameter:
Place two buttons on the form and name the
corresponding objects buttonConnect and
buttonDisconnect. Change the captions on the buttons
to Connect and Disconnect respectively. Your form
should resemble Figure 4.
Figure 4. First Application for Quick Start
C:\BridgeActiveX\usb2iic.exe /regserver
If the control registers successfully you will not see any
messages.
If none of your applications have any use for the control it is
a good idea to unregister it. Do this with the following
command:
C:\BridgeActiveX\usb2iic.exe /unregserver
3.
Doing this unregisters the ActiveX control in Windows, but it
does not delete it from your machine. You can do this
manually if required.
Using the ActiveX Control
This section describes how to use the Bridge ActiveX
Control in programming languages such as C#, Visual
Basic, Delphi, and C++. All functions are divided into three
groups according to how they are used. All functions
mentioned here are documented. The ActiveX Control has
some functions that are not documented. They are used
internally and they should not be used in your applications
because they may be changed or eliminated in future
versions of the bridge.
4.


5.
Borland C++ Builder 6.0
As an exercise, create a frame (sample) application that can
Connect to and Disconnect from the ActiveX component.
This application is developed into a demo program later in
the application note. All bridge functions explored later are
included in this demo even if they are not used.
1.

Find and select the USB2IIC Library component.
Make sure that the Path of this component is the
same as the path you used when you registered it.

Click OK.
Add the USB2IIC namespace to the source file. Switch
into the Code View of the Form. To the end of the list of
using directives add two more:
Declare the Bridge variable. In the class Form1 add
following code:
This declares the Bridge variable of the wrapper class
of the ActiveX Control. It encapsulates all functionality
and the event sink of the Bridge.
6.
7.
Double click on the Click event handler to generate two
event handlers for the Connect and Disconnect
buttons. The two event handlers are generated in the
Form1 class:

buttonConnect_Click

buttonDisconnect_Click.
Add two private methods which are event handlers for
the Bridge Control:
private void OnBridgeConnect(string BridgeID,
string str);
Start Microsoft Visual Studio and create a new Visual
C# project of Windows Application (Forms) type. Name
it USB2IIC_CS_Example.
May 5, 2010
In the Add Reference window select the COM tab.
USB2IICcom_EXEClass Bridge;
Import and Initialize the ActiveX Control
C# Example:

The second line adds the namespace of the Type
Library and wrapper class created by Visual Studio for
the USB2IIC ActiveX Control. Now you can use all
types and definitions from ActiveX component in this
source file.
Borland Delphi 7.0
Before beginning this example, be sure to install and
register the Active X control as explained in Installing and
Uninstalling.
Select Project > Add Reference.
using USB2IIC;
Microsoft Visual Studio 2005 using C#, Visual Basic,
and C++ (MFC) examples
The demo program demonstrates the abilities of the bridge
control. It is developed in all of the programming languages
named earlier and is a good start point when learning to use
the bridge driver.

using System.Diagnostics;
The following IDEs were tested for this application note:

Import the USB2IIC ActiveX Control into the project.
private
BridgeID);
Document No. 001-27079 Rev. *A
void
OnBridgeDisconnect(string
-4-
[+] Feedback
AN27079
Code 1. A C# Sample Application
public partial class Form1 : Form
{
USB2IICcom_EXEClass Bridge;
public Form1()
{
InitializeComponent();
}
private void buttonConnect_Click(object sender, EventArgs e)
{
if (Bridge!=null) return; // Bridge is already connected
// Create Bridge Instance
Bridge = new USB2IICcom_EXEClass();
// Connect Events
Bridge.BridgeConnected += OnBridgeConnect;
Bridge.BridgeDisconnected += OnBridgeDisconnect;
// Start USB Communication
Bridge.InitUSB2IIC(Process.GetCurrentProcess().Id);
}
private void buttonDisconnect_Click(object sender, EventArgs e)
{
Bridge = null;
GC.GetTotalMemory(true);
}
private void OnBridgeConnect(string BridgeID, string str)
{
MessageBox.Show("Connected: " + BridgeID);
}
private void OnBridgeDisconnect(string BridgeID)
{
MessageBox.Show("Disconnected: " + BridgeID);
}
}
The most interesting parts of this code sample are the
initialization and finalization of the Bridge object. In the
buttonConnect_Click method, the code first checks to see if
the object exists. If it does then it exits. It does not make
sense for one application to have multiple Bridge controls
running. Then a new instance of the bridge wrapper class is
created. Later, events are connected and communication is
started. You can now connect the bridge to and disconnect
the bridge from the PC and watch the attendant messages.
In the buttonDisconnect_Click handler, the Bridge control is
detached from the application and frees Windows
resources.
.NET Visual Basic Example
1.
Start MS Visual Studio and create new Visual Basic
project of Windows Application (Forms) type. Name it
USB2IIC_VB_Example.
2.
Put two buttons on the form and name the
corresponding
objects
buttonConnect
and
buttonDisconnect. Change the captions on the buttons
to Connect and Disconnect respectively. Your form
should resemble Figure 4 on page 4.
3.
Import the USB2IIC ActiveX Control into the project.
Use this sample code to develop your program and use any
of the Bridge functions described later. In the demo project
is a class called BridgeFunctionsUsage that shows how to
use each of the Bridge functions in the C# environment.
4.
May 5, 2010

Select Project > Add Reference.

In the Add Reference window select the COM tab.

Find and select the USB2IIC Library component.
Make sure that the path of this component is the
same as the path you used when you registered it.

Click OK.
Add the USB2IIC namespace to the source file. Switch
into the Code View of the Form. At the end of the list of
Imports directives add two more:
Document No. 001-27079 Rev. *A
-5-
[+] Feedback
AN27079
Imports System.Diagnostics
Imports USB2IIC
each. There are two functions in the Form1 class:
buttonConnect_Click and buttonDisconnect_Click.
The second line adds the namespace of the Type
Library and wrapper class created by Visual Studio for
the USB2IIC ActiveX Control. It is now possible to use
all types and definitions from ActiveX component in this
source file.
5.
7.
Add two private methods which are event handlers of
Bridge Control:
Sub OnBridgeConnect(ByVal BridgeID As String,
ByVal
Str
As
String)
Handles
Bridge.BridgeConnected
Declare the Bridge variable. In the class Form1 and
add following code
Sub
OnBridgeDisconnect(ByVal
BridgeID
String) Handles Bridge.BridgeDisconnected
Dim WithEvents Bridge As
As
Code 2 shows an implementation of the event handlers
added.
USB2IICcom_EXE
This declares the Bridge variable of wrapper class of
ActiveX Control. It encapsulates all functionality and the
event sink of the Bridge.
6.
Generate two event handlers for Connect and
Disconnect buttons. For that make left double click on
Code 2. .NET Visual Basic Sample Application
Imports System.Diagnostics
Imports USB2IIC
Public Class Form1
Dim WithEvents Bridge As USB2IICcom_EXE
Private Sub buttonConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
buttonConnect.Click
'Is Bridge is already connected?
If Not (Bridge Is Nothing) Then Return
'Create Bridge Instance
Bridge = New USB2IICcom_EXEClass()
'Start USB Communication
Bridge.InitUSB2IIC(Process.GetCurrentProcess().Id)
End Sub
Private Sub buttonDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles buttonDisconnet.Click
Bridge = Nothing
GC.GetTotalMemory(True)
End Sub
Sub OnBridgeConnect(ByVal BridgeID As String, ByVal Str As String) Handles Bridge.BridgeConnected
MessageBox.Show("Connected: " + BridgeID)
End Sub
Sub OnBridgeDisconnect(ByVal BridgeID As String) Handles Bridge.BridgeDisconnected
MessageBox.Show("Disconnected: " + BridgeID)
End Sub
End Class
The most interesting parts of this code sample are the
initialization and finalization of the Bridge object. In the
buttonConnect_Click method, the code first checks to see if
the object exists. If it does then it exits. It does not make
sense for one application to have multiple Bridge controls
running. Then a new instance of the bridge wrapper class is
created. Later, events are connected and communication is
started. You can now connect the bridge to and disconnect
the bridge from the PC and watch the attendant messages.
In the buttonDisconnect_Click handler, the Bridge control is
detached from your application and frees Windows
resources.
May 5, 2010
Use this sample code to develop your program and use any
of the other Bridge functions described later. The demo
project contains a class called BridgeFunctionsUsage that
shows how to use each of the Bridge functions in the .Net
Visual Basic environment.
Delphi Example
1.
Start Borland Delphi and create a new Application.
2.
Create a directory with the name
USB2IIC_Delphi_Example. This is your project
directory.
3.
Select File >Save Project As.
Document No. 001-27079 Rev. *A
-6-
[+] Feedback
AN27079
4.
In the Save Unit1 As window enter the path to the
project directory (USB2IIC_Delphi_Example) and click
Save.
5.
In the Save Project As window, select the same path
as before and name the project
USB2IIC_Delphi_Example
and definitions from imported ActiveX components in
this source file.
11. Declare the Bridge variable. In the class definition
TForm1 add following code:
public
Bridge: TUSB2IICcom_EXE;
6.
Click Save.
7.
Put two buttons on the form and name the
corresponding objects buttonConnect and
buttonDisconnect.
8.
Change their captions to Connect and Disconnect. Your
form should resemble Figure 4 on page 4.
9.
Import the USB2IIC ActiveX Control into the project.

buttonConnectClick

To do this, select Project > Import Type Library.

buttonDisconnectClick

In the Import Type Library window find and select
the component USB2IIC Library.

Make sure that the path of this component is the
same as the control you registered.

In the Unit Dir Name field set the path to your
project directory (USB2IIC_Delphi_Example).

Check Generate Component Wrapper.

Click Create Unit. The USB2IIC_TLB.pas module
is added to the project.
This declares the Bridge variable of the wrapper class
of the ActiveX Control. It encapsulates all functionality
and the event sink of the Bridge.
12. Generate two event handlers for the Connect and
Disconnect buttons. Double click on each button. You
will get two functions in the TForm1 class:
13. Add two private methods which are event handlers of
Bridge Control:
procedure OnBridgeConnect
(ASender:TObject;
const BridgeID: WideString;
const DeviceID:WideString);
procedure OnBridgeDisconnect
(ASender:TObject;
10. In the file Unit1.pas add the USB2IIC_TLB module to
the uses clause of interface section:
uses Windows, ... , USB2IIC_TLB;
The definition of the ActiveX control wrapper class is
added to the Unit1 module. Now you can use all types
const BridgeID:WideString);
Code 3 shows an implementation of all event handlers
added to the Unit1.pas file.
Code 3. Borland Delphi Sample Application
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, USB2IIC_TLB;
type
TForm1 = class(TForm)
buttonConnect: TButton;
buttonDisconnect: TButton;
procedure buttonConnectClick(Sender: TObject);
procedure buttonDisconnectClick(Sender: TObject);
private
{ Private declarations }
procedure OnBridgeConnect(ASender:TObject; const BridgeID:WideString; const DeviceID:WideString);
procedure OnBridgeDisconnect(ASender:TObject; const BridgeID:WideString);
public
Bridge: TUSB2IICcom_EXE;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.buttonConnectClick(Sender: TObject);
May 5, 2010
Document No. 001-27079 Rev. *A
-7-
[+] Feedback
AN27079
begin
if (Bridge <> nil) then exit; // Bridge is already connected
// Create Bridge Instance
Bridge := TUSB2IICcom_EXE.Create(nil);
// Connect Events
Bridge.OnBridgeConnected := OnBridgeConnect;
Bridge.OnBridgeDisconnected := OnBridgeDisconnect;
// Start USB Communication
Bridge.InitUSB2IIC(GetCurrentProcessId());
end;
procedure TForm1.buttonDisconnectClick(Sender: TObject);
begin
if (Bridge=nil) then exit;
FreeAndNil(Bridge);
end;
procedure TForm1.OnBridgeConnect(ASender:TObject; const BridgeID:WideString; const
DeviceID:WideString);
begin
MessageDlg('Connected: '+BridgeID,mtInformation,[mbOk],0);
end;
procedure TForm1.OnBridgeDisconnect(ASender:TObject; const BridgeID:WideString);
begin
MessageDlg('Disconnected: '+BridgeID,mtInformation,[mbOk],0);
end;
end.
The most interesting parts of this code sample are the
initialization and finalization of the Bridge object. In the
buttonConnectClick the code first checks to see if the object
exists. If it does then it exits. It does not make sense for one
application to have multiple Bridge controls running. Then a
new instance of the bridge wrapper class is created. Later,
events are connected and communication is started. You
can now connect the bridge to and disconnect the bridge
from the PC and watch the attendant messages. In the
buttonDisconnectClick handler, the Bridge control is
detached from your application and frees Windows
resources.
Use this sample code to develop your program and use any
of the other Bridge functions described later. The demo
project contains a class called TBridgeFunctionsUsage that
shows how to use each Bridge function in the Borland
Delphi environment.
C++ Builder Example:
1.
Start Borland C++ Builder and create a new Application.
Create a directory with the name
USB2IIC_C++Builder_Example. This is your project
directory.
2.
Select File > Save Project As.
3.
In the Save Unit1 As window enter the path to the
previously created project directory
(USB2IIC_C++Builder_Example)
7.
Add two buttons to the form and name the
corresponding objects buttonConnect and
buttonDisconnect.
8.
Change the captions on the buttons to Connect and
Disconnect respectively. Your form should resemble
Figure 4 on page 4.
9.
Import the USB2IIC ActiveX Control into the project.

Select Project > Import Type Library

In the Import Type Library window find and select
the component USB2IIC Library. Make sure that
the path of the selected component matches the
path of the ActiveX control you installed.

In the Unit Dir Name field set the path to your
project directory (USB2IIC_C++Builder_Example).

Check Generate Component Wrapper.

Click Create Unit.
The project is added to the USB2IIC_TLB.cpp file. You
should also see a new file in the project directory;
USB2IIC_OCX.cpp.
This
is
the
wrapper
class
implementation. You need to add it to your project. Select
Project->Add to project and select USB2IIC_OCX.cpp
from the project directory.
10. In the file Unit1.h file add the USB2IIC_OCX.h header
file to the end of the #include list.
4.
Click Save.
#include "usb2iic_ocx.h"
5.
In the Save Project As window select the same path,
and name the project USB2IIC_CppBuilder_Example
6.
Click Save.
This adds the definition of the ActiveX control’s wrapper
class to the Unit1 module. Now you can use all types
and definitions from the imported ActiveX components
in this source file.
May 5, 2010
Document No. 001-27079 Rev. *A
-8-
[+] Feedback
AN27079
11. Declare the Bridge variable. In the class definition for
TForm1, add the following code:
void __fastcall OnBridgeConnect
(System::TObject * Sender,
public:
BSTR BridgeID, BSTR DeviceID);
TUSB2IICcom_EXE* Bridge;
This declares the Bridge variable of the wrapper class
of the ActiveX Control. It encapsulates all functionality
and the event sink of the Bridge.
12. Generate two event handlers for the Connect and
Disconnect buttons. Double click on each to add event
handlers. There are two functions in the TForm1 class:
buttonConnectClick and buttonDisconnectClick.
void __fastcall OnBridgeDisconnect
(System::TObject * Sender,
BSTR BridgeID);
Code 4 shows an implementation of all event handlers
added in the Unit1.cpp file.
13. Add two private methods to the TForm1 class that will
be event handlers of the Bridge Control:
Code 4. Borland C++ Builder Sample Application
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::buttonConnectClick(TObject *Sender)
{
if (Bridge != NULL) return; // Bridge is already connected
// Create Bridge Instance
Bridge = new TUSB2IICcom_EXE(NULL);
// Connect Events
Bridge->OnBridgeConnected = OnBridgeConnect;
Bridge->OnBridgeDisconnected = OnBridgeDisconnect;
// Start USB Communication
Bridge->InitUSB2IIC(GetCurrentProcessId());
}
//--------------------------------------------------------------------------void __fastcall TForm1::buttonDisconnectClick(TObject *Sender)
{
if (Bridge == NULL) return;
delete Bridge;
Bridge=NULL;
}
May 5, 2010
Document No. 001-27079 Rev. *A
-9-
[+] Feedback
AN27079
//--------------------------------------------------------------------------void __fastcall TForm1::OnBridgeConnect(System::TObject * Sender, BSTR BridgeID,BSTR DeviceID)
{
WideString str = L"Connected: ";
str += BridgeID;
MessageDlg(str.c_bstr(),mtInformation,TMsgDlgButtons() << mbOK,0);
}
//--------------------------------------------------------------------------void __fastcall TForm1::OnBridgeDisconnect(System::TObject * Sender, BSTR BridgeID)
{
WideString str = L"Disconnected: ";
str += BridgeID;
MessageDlg(str.c_bstr(),mtInformation,TMsgDlgButtons() << mbOK,0);
}
The most interesting parts of this code sample are the
initialization and finalization of the Bridge object. In the
buttonConnect_Click method, the code first checks to see
if the object exists. If it does then it exits. It does not make
sense for one application to have multiple Bridge controls
running. A new instance of the bridge wrapper class is
created. Later, events are connected and communication
is started. You can now connect the bridge to and
disconnect the bridge from the PC and view the attendant
messages. In the buttonDisconnect_Click handler, the
Bridge control is detached from your application and frees
Windows resources.
IDConnect and IDDisconnect. Delete the static label
in the center of the form. Arrange the form and its
buttons so it is similar to Figure 4 on page 4.
4.
Generate OnClick event handlers for buttons. To do
this, double click on each of the event handlers. Two
dummy functions, OnBnClickedConnect() and
OnBnClickedDisconnect() are created in the file
USB2IIC_C++MFC_ExampleDlg.cpp. These functions
are implemented later.
5.
Import the USB2IIC ActiveX Control into the project.
Use this sample code to develop your program and use
any of the other Bridge functions described later. The
demo
project
contains
a
class
called
TBridgeFunctionsUsage that shows how to use each of
the Bridge functions in the Borland C++ Builder
environment.
C++ MFC Example:
1.
Start MS Visual Studio and create a new C++ MFC
based application. Select File > New > Project. In the
New Project window select Other Languages\Visual
C++\MFC from the Project Types tree. In Templates
select MFC Application. Name your project
USB2IIC_C++MFC_Example. Specify the location of
this project and click OK.
2.
In the MFC Application Wizard, click on Application
Type and choose Dialog based instead of the default
Multiple documents. Click on User Interface
Features and uncheck the About box control.
Specify a title for your project, USB2IIC C++MFC
Example. Click the Finish button.
3.
Open the Resource View window by selecting View
> Other Windows > Resource View and then open
the Dialog resource. To do this, double click on the
IDD_USB2IIC_CMFC_EXAMPLE_DIALOG form
resource. By default, this form has two buttons, Ok
and Cancel. Change the text on these two buttons to
Connect and Disconnect. Change their IDs to
May 5, 2010

From the Project menu, select Add Class.

In the Add Class dialog, choose the MFC branch
in the Categories tree. In Templates select the
MFC Class From TypeLib option. Click the Add
button.

In the wizard, choose add class from Registry.

In the Available Type Libraries list find and
select USB2IIC Library <1.0>.

In the Interfaces section there are two interfaces
available from the USB2IIC control, they are:
IUSB2IICcom_Exe and IUSB2IICcomEvents.
Add only one IUSB2IICcom_Exe interface to the
Generated classes section.

Click Finish.
The wrapper class of Bridge ActiveX control is
generated and added to the project file
(CUSB2IICcom_Exe.h). Note that it only implements
access to the methods and properties of Bridge
control, the event mechanism must be added
manually.
6.
Add the event sink interface to the Bridge client.

On the Project menu item, select Add Class.

In Add Class dialog, select MFC Class.
Document No. 001-27079 Rev. *A
- 10 -
[+] Feedback
AN27079

In the wizard, on the Name page, under Base
Class, select CCmdTarget.

Select the Automation option and type the name
of the generated class, CUSB2IICevent_Sink.

Click Finish.
There are now two more files in your project:
USB2IICevent_Sink.cpp and USB2IICevent_Sink.h.
You must now implement the Sink class.
7.
Open USB2IICevent_Sink.cpp and find line which
begins as following:
static
{...};
const
IID
IID_IUSB2IICevent_Sink
=
Change the value of this constant to:
{ 0x80efe271, 0xeb62, 0x4e20, { 0x96, 0x9f,
0x23, 0x20, 0x8b, 0xe1, 0x9e, 0x10} };
This is the GUID (Globally Unique Identifier) of the
IUSB2IICcomEvents interface (declared in the type
library of the Bridge ActiveX).
8.
In the DISPATCH_MAP of the CUSB2IICevent_Sink
class, add a DISP_FUNCTION_ID macro for each of
the events defined in the source interface. In this case
only two events are used: BridgeConnected and
BridgeDisconnected. The resulting dispatch map and
corresponding event handlers appears as shown in
Code 5.
Code 5. Sink Interface Event Handlers in the C++ MFC Example
void CUSB2IICevent_Sink::OnBridgeConnect(BSTR BridgeID, BSTR str)
{
CString msg = L"Connected: ";
msg += BridgeID;
AfxMessageBox(msg, MB_ICONINFORMATION | MB_OK);
}
void CUSB2IICevent_Sink::OnBridgeDisconnect(BSTR BridgeID)
{
CString msg = L"Disconnected: ";
msg += BridgeID;
AfxMessageBox(msg, MB_ICONINFORMATION | MB_OK);
}
BEGIN_DISPATCH_MAP(CUSB2IICevent_Sink, CCmdTarget)
DISP_FUNCTION_ID(CUSB2IICevent_Sink,"BridgeConnected",1,OnBridgeConnect,VT_EMPTY,
VTS_BSTR VTS_BSTR)
DISP_FUNCTION_ID(CUSB2IICevent_Sink,"BridgeDisconnected",2,OnBridgeDisconnect,
VT_EMPTY,VTS_BSTR)
END_DISPATCH_MAP()
9.
Add two prototypes for the event handlers shown in
Code 5 to the CUSB2IICevent_Sink class definition
(in CUSB2IICevent_Sink.h):
private:
void OnBridgeConnect(BSTR BridgeID,
BSTR str);
void OnBridgeDisconnect(BSTR BridgeID);
At the end of this header file add the following
external reference:
extern const IID
IID_IUSB2IICevent_Sink;
10. To tie all of this together, open
USB2IIC_C++MFC_ExampleDlg.cpp make the
following additions to the #include section:
#include "CUSB2IICcom_Exe.h"
#include "USB2IICevent_Sink.h"
#include "afxctl.h"
In the same file, declare three global variables (or
members of CUSB2IIC_CMFC_ExampleDlg class):
CUSB2IICcom_Exe* Bridge;
CUSB2IICevent_Sink* BridgeEventSink;
DWORD dwCookie;
Now, implement the event handlers for the Connect and
Disconnect buttons.
May 5, 2010
Document No. 001-27079 Rev. *A
- 11 -
[+] Feedback
AN27079
Code 6. Connect and Disconnect Button Event Handlers Code for the C++ MFC Example
void CUSB2IIC_CMFC_ExampleDlg::OnBnClickedConnect()
{
if (Bridge!=NULL) return;
//Initialize the COM library on the current thread
CoInitialize(NULL);
//Create Bridge Instance
Bridge = new CUSB2IICcom_Exe();
BOOL r = Bridge->CreateDispatch(L"USB2IIC.USB2IICcom_EXE");
if (r == 0) {
AfxMessageBox(L"Cann't Connect to the USB2IIC Automation Object",
MB_ICONERROR | MB_OK);
delete Bridge;
Bridge = NULL;
CoUninitialize();
return;
}
//Connect Events
BridgeEventSink = new CUSB2IICevent_Sink();
LPUNKNOWN pUnkSink = BridgeEventSink->GetIDispatch(FALSE);
r = AfxConnectionAdvise(Bridge->m_lpDispatch,IID_IUSB2IICevent_Sink,
pUnkSink,FALSE,&dwCookie);
if (r==0){
AfxMessageBox(L"Cann't Connect Events");
}
// Start USB Communication with Bridge
Bridge->InitUSB2IIC(GetCurrentProcessId());
}
void CUSB2IIC_CMFC_ExampleDlg::OnBnClickedDisconnect()
{
if (Bridge == NULL) return;
// Disconnect Events
LPUNKNOWN pUnkSink = BridgeEventSink->GetIDispatch(FALSE);
BOOL r = AfxConnectionUnadvise(Bridge->m_lpDispatch,IID_IUSB2IICevent_Sink,
pUnkSink,FALSE,dwCookie);
if (r==0){
AfxMessageBox(L"Cann't Disconnect Events");
}
// Destroy Bridge Object
Bridge->m_bAutoRelease = TRUE;
delete Bridge;
delete BridgeEventSink;
Bridge = NULL;
//Closes the COM library on the current thread
CoUninitialize();
}
The most interesting parts of this code sample are the
initialization and finalization of the Bridge object. In the
buttonConnect_Click method, the code first checks to see
if the object exists. If it does, then it exits. It does not make
sense for one application to have multiple Bridge controls
running. A COM library is initialized before it calls any of
the library functions. Then a new instance of the bridge
wrapper class is created using the CreateDispatch method
of the Bridge variable. Its parameter is ProgID of the
USB2IIC Automation object (ActiveX control). It uniquely
identifies this object in the system along with its GUID.
The next step is to connect the events. First, the event
sink object is created (which implements the event sink
interface), and then the connection is established between
May 5, 2010
the Sink (BridgeEventSink object) and Source (Bridge
object) by means of an AfxConnectionAdvise() MFC
function. You can now connect the bridge to and
disconnect the bridge from the PC and view the attendant
messages. In the OnBnClickedDisconnect handler the
Bridge control is detached from your application and frees
Windows resources.
With this sample code you can develop your programs
that use any other Bridge functions, described later. The
demo project contains a class CBridgeFunctionsUsage
that shows how to use each Bridge function in the Visual
C++ environment.
Document No. 001-27079 Rev. *A
- 12 -
[+] Feedback
AN27079
Function Reference
Initialization Functions
InitUSB() – This function starts communication between the ActiveX Control and Bridge Hardware. It initiates the USB
interface; after it completes, all other ActiveX Control functions can be called.
Language
Interface and Usage Example
C#
void InitUSB();
Bridge.InitUSB();
Visual Basic
.NET
Delphi
Sub InitUSB()
Bridge.InitUSB()
procedure InitUSB;
Bridge.InitUSB;
C++ Builder
void InitUSB(void);
Bridge->InitUSB();
C++ MFC
void InitUSB();
Bridge->InitUSB();
InitUSB2IIC(ProcessID) – This function does the same as InitUSB() with one exception. It has a ProcessID parameter that is
the identifier of current (client) process in the Windows. Use this function instead of InitUSB() because it allows the ActiveX
control to unload (terminate) if the client quits abnormally. When the client quits abnormally, the Bridge Control terminates by
itself and frees resources.
Language
Interface and Usage Example
C#
void InitUSB2IIC(int ProcessID);
using System.Diagnostics;
...
Bridge.InitUSB2IIC(Process.GetCurrentProcess().Id);
Visual Basic
.NET
Sub InitUSB2IIC(ByVal ProcessID As Integer)
Imports System.Diagnostics
...
Bridge.InitUSB2IIC(Process.GetCurrentProcess().Id)
Delphi
procedure InitUSB2IIC(ProcessID: SYSINT);
uses Windows;
...
Bridge.InitUSB2IIC(GetCurrentProcessId());
C++ Builder
void InitUSB2IIC(int ProcessID);
#include <Windows.h>
...
Bridge->Init2USBIIC(GetCurrentProcessId());
C++ MFC
void InitUSB2IIC(long ProcessID);
Bridge->Init2USBIIC(GetCurrentProcessId());
UnInitUSB() – This is a satellite function to InitUSB(). Currently, it is a dummy routine, but it may be used in future versions.
There is no need to call it to finish communication.
May 5, 2010
Document No. 001-27079 Rev. *A
- 13 -
[+] Feedback
AN27079
Language
Interface and Usage Example
C#
void UnInitUSB();
Bridge.UnInitUSB();
Visual Basic
Sub UnInitUSB()
.NET
Bridge.UnInitUSB()
Delphi
procedure UnInitUSB;
Bridge.UnInitUSB;
C++ Builder
void UnInitUSB(void);
Bridge->UnInitUSB();
C++ MFC
void UnInitUSB();
Bridge->UnInitUSB();
Configuration and Status Functions
GetBridgeList() – This function returns a list (array) of bridges currently connected to the PC. A list element is a BridgeID.
This function is especially useful in the applications that do not use ActiveX events (OnBridgeConnect/OnBridgeDisconnect).
Note the first element index in the array is 1 (not 0).
Language
Interface and Usage Example
C#
object GetBridgeList();
object List = Bridge.GetBridgeList();
Array bl = List as Array;
int count = bl.GetLength(0); // Bridges count
string s="Bridges Count:"+count.ToString()+'\n';
for (int i=1; i<=count; i++)
s+=(bl.GetValue(i) as string+'\n');
MessageBox.Show(s);
Visual Basic
Function GetBridgeList() As Object
.NET
Dim List As System.Array = Bridge.GetBridgeList()
Dim count = List.GetLength(0) 'Bridges count
Dim s = "Bridges Count: " + count.ToString()+Chr(Keys.Return)
Dim i As Integer
For i = 1 To count Step 1
s += (List.GetValue(i) + Chr(Keys.Return))
Next
MessageBox.Show(s)
Delphi
Function GetBridgeList: OleVariant;
var s:string;
List:OleVariant;
highBound,lowBound,count,i:integer;
begin
List := Bridge.GetBridgeList();
highBound := VarArrayHighBound(List,1);
lowBound := VarArrayLowBound(List,1);
count:=highBound-LowBound+1;
s:='Bridges Count: '+IntToStr(count)+#13#10;
for i:=lowBound to highBound do begin
s:=s+List[i]+#13#10;
end;
MessageDlg(s,mtInformation,[mbOk],0);
end;
May 5, 2010
Document No. 001-27079 Rev. *A
- 14 -
[+] Feedback
AN27079
Language
Interface and Usage Example
C++ Builder
TVariant GetBridgeList(void);
Variant List = Bridge->GetBridgeList();
int highBound = List.ArrayHighBound(1);
int lowBound = List.ArrayLowBound(1);
int count = highBound - lowBound + 1;
WideString str = L"Bridges Count: ";
str += IntToStr(count).c_str();
str += L"\r\n";
for (int i=lowBound; i<=highBound; i++){
BSTR bridgeID = List.GetElement(i);
str += bridgeID;
str += L"\r\n";
}
MessageDlg(str->c_bstr(),mtInformation,
TMsgDlgButtons()<< mbOK, 0);
delete str;
C++ MFC
VARIANT GetBridgeList();
VARIANT data = Bridge->GetBridgeList();
SAFEARRAY FAR *List = data.parray;
long highBound, lowBound, count;
SafeArrayGetUBound(List, 1, &highBound);
SafeArrayGetLBound(List, 1, &lowBound);
count = highBound - lowBound + 1;
CString str;
str.Format (L"Bridges Count: %d%s",count,L"\r\n");
for (long i=lowBound; i<=highBound; i++){
LPCTSTR bridgeID;
SafeArrayGetElement(List,&i,&bridgeID);
str += bridgeID;
str += L"\r\n";
}
AfxMessageBox(str,MB_ICONINFORMATION | MB_OK);
GetBridgeStatus(WhatStatus) – This function returns the status of the last executed Bridge function or the function currently
being executed (depending on parameter). Possible values of the WhatStatus parameter:
0x00 – current operation status (for asynchronous operations, currently not used)
0x01 – status of last operation (last function call)
This function can be used with other functions that do not return the status of an executed operation (for example,
GetDeviceList(BridgeID)). Use this function to test whether another function completed successfully, for example to see if the
results of that function are valid before using the results.
Language
Interface and Usage Example
C#
sbyte GetBridgeStatus(sbyte WhatStatus);
int lastError = Bridge.GetBridgeStatus(1);
Visual Basic
.NET
Delphi
Function GetBridgeStatus(ByVal WhatStatus As SByte) As SByte
Dim lastError As SByte = Bridge.GetBridgeStatus(1)
Function GetBridgeStatus(WhatStatus:Shortint): Shortint;
var lastError:Shortint;
begin
lastError := Bridge.GetBridgeStatus(1);
...
end;
May 5, 2010
Document No. 001-27079 Rev. *A
- 15 -
[+] Feedback
AN27079
Language
Interface and Usage Example
C++ Builder
signed char GetBridgeStatus(signed char WhatStatus);
int lastError = Bridge->GetBridgeStatus(1);
C++ MFC
signed char GetBridgeStatus(signed char WhatStatus);
int lastError = Bridge->GetBridgeStatus(1);
GetStatusMsg(MsgCode) – This function returns a description of the status code returned by an operation. This function is
useful to know what a status code means.
Language
Interface and Usage Example
C#
string GetStatusMsg(int MsgCode);
string msg = Bridge.GetStatusMsg(34);
Visual Basic
.NET
Delphi
Function GetStatusMsg(ByVal MsgCode As Integer) As String
Dim msg As String = Bridge.GetStatusMsg(34)
Function GetStatusMsg(MsgCode:SYSINT): WideString;
var msg: string;
begin
msg := Bridge.GetStatusMsg(34);
...
end;
C++ Builder
BSTR GetStatusMsg(int MsgCode);
BSTR msg = Bridge->GetStatusMsg(34);
C++ MFC
CString GetStatusMsg(long MsgCode);
CString msg = Bridge->GetStatusMsg(34);
GetBridgeVersion(BridgeID,Version) – This function returns the version of the given bridge in the string format in the
Version parameter. The result of this function is a status code of this transaction. Analyze the status code before using the
Version parameter. In the case of a transaction failure the function returns the string “Unknown” and an error code as a result.
Language
Interface and Usage Example
C#
object GetBridgeVersion(string BridgeID, out object Version);
object str, r;
r = Bridge.GetBridgeVersion("86A4D2890E0B", out str);
if ((int)r == 34) // operation finished successfully
{
MessageBox.Show("Version = " + str.ToString());
}
Visual Basic
Function GetBridgeVersion(ByVal BridgeID As String, ByRef Version As Object)
.NET
As Object
Dim str = "", r
r = Bridge.GetBridgeVersion("86A4D2890E0B", str)
If (r = 34) Then 'operation finished successfully
MessageBox.Show("Version = " + str.ToString())
End If
Delphi
Function GetBridgeVersion(const BridgeID: WideString; out Version: OleVariant):
OleVariant;
May 5, 2010
Document No. 001-27079 Rev. *A
- 16 -
[+] Feedback
AN27079
Language
Interface and Usage Example
var r: byte;
str: OleVariant;
begin
r := Bridge.GetBridgeVersion('86A4D2890E0B', str);
if (r = 34) then // operation finished successfully
MessageDlg('Version = ' + str, mtInformation, [mbOk],0);
End;
C++ Builder
TVariant GetBridgeVersion(BSTR BridgeID, VARIANT* Version);
WideString BridgeID = L"86A4D2890E0B";
Variant version;
TVariant r = Bridge->GetBridgeVersion(BridgeID, version);
if (r == 34) // operation finished successfully
{
WideString str = "Version = " + version;
MessageDlg(str,mtInformation,TMsgDlgButtons() << mbOK,0);
}
C++ MFC
VARIANT GetBridgeVersion(LPCTSTR BridgeID, VARIANT* Version);
VARIANT version;
VariantInit(&version);
VARIANT r = Bridge->GetBridgeVersion(L"86A4D2890E0B", &version);
if (r.bVal == 34) // operation finished successfully
{
CString str = L"Version = ";
str += version.bstrVal;
AfxMessageBox(str,MB_ICONINFORMATION | MB_OK);
}
VariantClear(&version);
GetPowerSpeed(BridgeID,Power,Speed) – This function returns the Power and Speed settings of the given bridge. The
result of the function is a status code of this transaction. Possible values of the Power and Speed parameters are:
Power: 0x00 – The bridge does not supply power to the connected board. The board is self-powered.
0x01 – The bridge supplies +5V voltage to the connected board.
0x02 – The bridge supplies +3.3V voltage to the connected board.
Speed: 0x20 – The data exchange frequency on the I2C bus bridge is 100K.
0x24 – The data exchange frequency on the I2C bus bridge is 400K.
0x28 – The data exchange frequency on the I2C bus bridge is 50K.
Language
Interface and Usage Example
C#
object GetPowerSpeed(string BridgeID, out object Power, out object Speed);
object r, Power, Speed;
int iPower, iSpeed;
r=Bridge.GetPowerSpeed("86A4D2890E0B", out Power, out Speed);
if ((int)r == 34) // operation finished successfully
{
iPower = (int)Power;
iSpeed = (int)Speed;
...
}
Visual Basic
Function GetPowerSpeed(ByVal BridgeID As String, ByRef Power As Object,
.NET
ByRef Speed As Object) As Object
Dim r
Dim Power As Integer = 0, Speed As Integer = 0
r = Bridge.GetPowerSpeed("86A4D2890E0B", Power, Speed)
If (r = 34) Then 'operation finished successfully
MessageBox.Show("Power: " + Power.ToString() + _
Chr(Keys.Return) + "Speed: " + Speed.ToString())
End If
May 5, 2010
Document No. 001-27079 Rev. *A
- 17 -
[+] Feedback
AN27079
Language
Interface and Usage Example
Delphi
Function GetPowerSpeed(const BridgeID: WideString; out Power: OleVariant;
Out Speed: OleVariant): OleVariant;
var r: byte;
Power,Speed: OleVariant;
iPower,iSpeed: integer;
begin
r := Bridge.GetPowerSpeed('86A4D2890E0B', Power, Speed);
if (r = 34) then begin // operation finished successfully
iPower:=Power;
iSpeed:=Speed;
MessageDlg('Power: '+VarToStr(Power)+#13#10+
'Speed: '+VarToStr(Speed),
mtInformation,[mbOk],0);
end;
end;
C++ Builder
TVariant GetPowerSpeed(BSTR BridgeID, VARIANT* Power, VARIANT* Speed);
WideString BridgeID = L"86A4D2890E0B";
Variant Power, Speed, r;
r = Bridge->GetPowerSpeed(BridgeID, Power, Speed);
if (r == 34) // operation finished successfully
{
int iPower = Power;
int iSpeed = Speed;
//...
}
C++ MFC
VARIANT GetPowerSpeed(LPCTSTR BridgeID, VARIANT* Power, VARIANT* Speed);
VARIANT Power, Speed, r;
VariantInit(&Power);
VariantInit(&Speed);
r = Bridge->GetPowerSpeed(L"86A4D2890E0B", &Power, &Speed);
if (r.bVal == 34) // operation finished successfully
{
int iPower = Power.intVal;
int iSpeed = Speed.intVal;
//...
}
VariantClear(&Power);
VariantClear(&Speed);
SetPower(BridgeID,Power) – This function sets the power source to the target board given by Power parameter. The
possible values of Power are similar to the ones listed in the GetPowerSpeed() function. It returns a status code based on the
result of this transaction.
Language
Interface and Usage Example
C#
object SetPower(string BridgeID, int Power);
object r;
r = Bridge.SetPower("86A4D2890E0B", 0x01); //set +5V
if ((int)r != 34)
{
MessageBox.Show(Bridge.GetStatusMsg((int)r), "Error!", 0,
MessageBoxIcon.Error);
}
Visual Basic
May 5, 2010
Function SetPower(ByVal BridgeID As String, ByVal Power As Integer) As Object
Document No. 001-27079 Rev. *A
- 18 -
[+] Feedback
AN27079
Language
.NET
Delphi
Interface and Usage Example
Dim r = Bridge.SetPower("86A4D2890E0B", &H1) 'set +5V
If (r <> 34) Then
MessageBox.Show(Bridge.GetStatusMsg(r), "Error!", 0,
MessageBoxIcon.Error)
End If
Function SetPower(const BridgeID: WideString; Power: Integer): OleVariant;
var r: byte;
begin
r := Bridge.SetPower('86A4D2890E0B', $01); //set +5V
if (r <> 34) then
MessageDlg(Bridge.GetStatusMsg(r),mtError,[mbOk],0);
end;
C++ Builder
TVariant SetPower(BSTR BridgeID, long Power);
WideString BridgeID = L"86A4D2890E0B";
Variant r;
r = Bridge->SetPower(BridgeID, 0x01); //set +5V
if (r != 34)
{
MessageDlg(Bridge->GetStatusMsg(r),mtError,
TMsgDlgButtons() << mbOK,0);
}
C++ MFC
VARIANT SetPower(LPCTSTR BridgeID, long Power);
VARIANT r = Bridge->SetPower(L"86A4D2890E0B", 0x01); //set +5V
if (r.bVal != 34)
{
AfxMessageBox(Bridge->GetStatusMsg(r.bVal),MB_ICONERROR | MB_OK);
}
SetSpeed(BridgeID,Speed) – sets I2C bus speed in the given bridge. The possible values of Speed is the similar to the
corresponding parameter of GetPowerSpeed() function. It returns status code of last (this) transaction.
Language
Interface and Usage Example
C#
object SetSpeed(string BridgeID, int Speed);
object r;
r = Bridge.SetSpeed("86A4D2890E0B", 0x20); //set 100K
Visual Basic
.NET
Delphi
Function SetSpeed(ByVal BridgeID As String, ByVal Speed As Integer) As Object
Dim r = Bridge.SetSpeed("86A4D2890E0B", &H20) 'set 100K
Function SetSpeed(const BridgeID: WideString; Speed: Integer): OleVariant;
var r: byte;
begin
r := Bridge.SetSpeed('86A4D2890E0B', $20); //set 100K
end;
C++ Builder
TVariant SetSpeed(BSTR BridgeID, long Speed);
WideString BridgeID = L"86A4D2890E0B";
Variant r = Bridge->SetSpeed(BridgeID, 0x20); //set 100K
C++ MFC
VARIANT SetSpeed(LPCTSTR BridgeID, long Speed);
VARIANT r = Bridge->SetSpeed(L"86A4D2890E0B", 0x20); //set 100K
May 5, 2010
Document No. 001-27079 Rev. *A
- 19 -
[+] Feedback
AN27079
ResetBridge(BridgeID) – resets I2C bus of the given bridge. This is hardware reinitialization of I2C bus in case of bus hangup. It returns status code of last (this) transaction.
Language
Interface and Usage Example
C#
object ResetBridge(string BridgeID);
object r =Bridge.ResetBridge("86A4D2890E0B");
if ((int)r == 34)
MessageBox.Show("I2C bus Reset Successfully!");
else
MessageBox.Show(Bridge.GetStatusMsg((int)r), "Error!", 0,
MessageBoxIcon.Error);
Visual Basic
Function ResetBridge(ByVal BridgeID As String) As Object
.NET
Dim r = Bridge.ResetBridge("86A4D2890E0B")
If (r = 34) Then
MessageBox.Show("I2C bus Reset Successfully!")
Else
MessageBox.Show(Bridge.GetStatusMsg(r), "Error!", 0,
MessageBoxIcon.Error)
End If
Delphi
Function ResetBridge(const BridgeID: WideString): OleVariant;
var r: byte;
begin
r := Bridge.ResetBridge('86A4D2890E0B');
if (r = 34) then
MessageDlg('I2C bus Reset Successfully',
mtInformation,[mbOk],0)
else
MessageDlg(Bridge.GetStatusMsg(r), mtError, [mbOk],0);
end;
C++ Builder
TVariant ResetBridge(BSTR BridgeID);
WideString BridgeID = L"86A4D2890E0B";
Variant r = Bridge->ResetBridge(BridgeID);
if (r == 34)
MessageDlg("I2C bus Reset Successfully!",mtInformation,
TMsgDlgButtons() << mbOK,0);
else
MessageDlg(Bridge->GetStatusMsg(r),mtError,
TMsgDlgButtons() << mbOK,0);
C++ MFC
VARIANT ResetBridge(LPCTSTR BridgeID);
VARIANT r = Bridge->ResetBridge(L"86A4D2890E0B");
if (r.bVal == 34)
AfxMessageBox(L"I2C bus Reset Successfully!",
MB_ICONINFORMATION | MB_OK);
else
AfxMessageBox(Bridge->GetStatusMsg(r.bVal),
MB_ICONERROR | MB_OK);
May 5, 2010
Document No. 001-27079 Rev. *A
- 20 -
[+] Feedback
AN27079
IsPowerDetected(BridgeID,PowerStatus) – This function returns whether target board connected to the bridge is powered or
not in the PowerStatus parameter. It returns a status code indicating the results of the transaction. Possible values of
PowerStatus:
0x00 – The target board is not powered.
0x01 – The target board is powered.
Language
Interface and Usage Example
C#
object IsPowerDetected(string BridgeID, out byte PowerStatus);
object r;
sbyte PowerStatus;
r = Bridge.IsPowerDetected("86A4D2890E0B", out PowerStatus);
if ((int)r == 34)
{
if (PowerStatus == 0) MessageBox.Show("No Power Detected");
else MessageBox.Show("POWERED");
}
Visual Basic
Function IsPowerDetected(ByVal BridgeID As String, ByRef PowerStatus As SByte)
.NET
As Object
Dim r
Dim PowerStatus As Byte
r = Bridge.IsPowerDetected("86A4D2890E0B", PowerStatus)
If (r = 34) Then
If (PowerStatus = 0) Then
MessageBox.Show("No Power Detected")
Else
MessageBox.Show("POWERED")
End If
End If
Delphi
Function IsPowerDetected(const BridgeID: WideString; out PowerStatus: ShortInt):
OleVariant;
var r: byte;
PowerStatus: Shortint;
begin
r := Bridge.IsPowerDetected('86A4D2890E0B', PowerStatus);
if (r = 34) then begin
if (PowerStatus = 0) then
MessageDlg('No Power Detected',mtInformation,[mbOk],0)
else
MessageDlg('POWERED',mtInformation,[mbOk],0);
end;
end;
C++ Builder
TVariant IsPowerDetected(BSTR BridgeID, signed char* PowerStatus);
WideString BridgeID = L"86A4D2890E0B";
signed char PowerStatus;
Variant r = Bridge->IsPowerDetected(BridgeID, &PowerStatus);
if (r == 34)
{
if (PowerStatus == 0)
MessageDlg("No Power Detected",mtInformation,
TMsgDlgButtons() << mbOK,0);
else
MessageDlg("POWERED",mtInformation,
TMsgDlgButtons() << mbOK,0);
}
C++ MFC
May 5, 2010
VARIANT IsPowerDetected(LPCTSTR BridgeID, signed char* PowerStatus);
Document No. 001-27079 Rev. *A
- 21 -
[+] Feedback
AN27079
Language
Interface and Usage Example
signed char PowerStatus;
VARIANT r = Bridge->IsPowerDetected(L"86A4D2890E0B", &PowerStatus);
if (r.bVal == 34)
{
if (PowerStatus == 0)
AfxMessageBox(L"No Power Detected",MB_ICONINFORMATION | MB_OK);
else
AfxMessageBox(L"POWERED",MB_ICONINFORMATION | MB_OK);
}
SetTimeoutPeriod(Timeout) – This function sets the timeout for the USB transactions. This timeout is the software timeout in
the ActiveX control. It triggers if no reply was received during the last transaction (the Bridge failed to answer a PC software
request). This timeout is measured in the milliseconds and by default it is 1000 ms.
Language
Interface and Usage Example
C#
object SetTimeoutPeriod(int Timeout);
Bridge.SetTimeoutPeriod(2000);
Visual Basic
.NET
Delphi
Sub SetTimeoutPeriod(ByVal timeout As Integer)
Bridge.SetTimeoutPeriod(2000)
Procedure SetTimeoutPeriod(timeout: Integer);
Bridge.SetTimeoutPeriod(2000);
C++ Builder
void SetTimeoutPeriod(long timeout);
Bridge->SetTimeoutPeriod(2000);
C++ MFC
void SetTimeoutPeriod(long timeout);
Bridge->SetTimeoutPeriod(2000);
I2C Functions
GetDeviceList(BridgeID) – This function scans the I2C bus of the given bridge and returns an array of I2C devices that
respond. The element zero of the array is number (N) of devices present, and the elements one to N contain the addresses of
those devices. Note that the function does not return a status code. Call the GetBridgeStatus() function to determine if it
completed successfully.
Language
Interface and Usage Example
C#
object GetDeviceList(string BridgeID);
object List = Bridge.GetDeviceList("86A4D2890E0B");
byte[] bl = List as byte[];
int lastError = Bridge.GetBridgeStatus(1);
if (lastError != 34) // failure of bus scanning
MessageBox.Show(Bridge.GetStatusMsg((int)lastError),
"Error!", 0, MessageBoxIcon.Error);
else // bus scanned successfully
{
int count = bl.GetLength(0);
string s = "Devices Count: " + bl.GetValue(0) + '\n';
for (int i = 1; i < count; i++)
s += ("0x"+bl[i].ToString("X2") + '\n');
MessageBox.Show(s);
}
Visual Basic
May 5, 2010
Function GetDeviceList(ByVal BridgeID As String) As Object
Document No. 001-27079 Rev. *A
- 22 -
[+] Feedback
AN27079
Language
.NET
Delphi
Interface and Usage Example
Dim List = Bridge.GetDeviceList("86A4D2890E0B")
Dim lastError = Bridge.GetBridgeStatus(1)
If (lastError <> 34) Then 'failure of bus scanning
MessageBox.Show(Bridge.GetStatusMsg(lastError), "Error!",
0, MessageBoxIcon.Error)
Else 'bus scanned successfully
Dim i As Integer
Dim count = List.GetLength(0)
Dim s = "Devices Count: " + List(0).ToString() + _
Chr(Keys.Return)
For i = 1 To count - 1 Step 1
Dim Device As Byte = List(i)
s += ("0x" + Device.ToString("X2") + Chr(Keys.Return))
Next
MessageBox.Show(s)
End If
Function GetDeviceList(const BridgeID: WideString): OleVariant;
var List: OleVariant;
lastError: Shortint;
highBound,lowBound,count,i: byte;
s:string;
begin
List := Bridge.GetDeviceList('86A4D2890E0B');
lastError := Bridge.GetBridgeStatus(1);
if (lastError <> 34) then // failure of bus scanning
MessageDlg(Bridge.GetStatusMsg(lastError),mtError,[mbOk],0)
else begin // bus scanned successfully
highBound := VarArrayHighBound(List,1);
lowBound := VarArrayLowBound(List,1);
count := highBound - lowBound + 1;
s := 'Devices Count: ' + IntToStr(List[0]) + #13#10;
for i:=1 to count-1 do
s := s+ '0x'+IntToHex(List[i],2) + #13#10;
MessageDlg(s,mtInformation,[mbOk],0);
end;
end;
C++ Builder
TVariant GetDeviceList(BSTR BridgeID);
WideString BridgeID = L"86A4D2890E0B";
Variant List = Bridge->GetDeviceList(BridgeID);
int lastError = Bridge->GetBridgeStatus(1);
if (lastError != 34) // failure of bus scanning
MessageDlg(Bridge->GetStatusMsg(lastError),mtError,
TMsgDlgButtons() << mbOK,0);
else // bus scanned successfully
{
int highBound = List.ArrayHighBound(1);
int lowBound = List.ArrayLowBound(1);
int count = highBound - lowBound + 1;
WideString s = "Devices Count: "+IntToStr(count-1)+"\n";
for (int i = 1; i < count; i++){
int device = List.GetElement(i);
s += ("0x"+IntToHex(device,2)+"\n");
}
MessageDlg(s,mtInformation,TMsgDlgButtons() << mbOK,0);
}
C++ MFC
May 5, 2010
VARIANT GetDeviceList(LPCTSTR BridgeID);
Document No. 001-27079 Rev. *A
- 23 -
[+] Feedback
AN27079
Language
Interface and Usage Example
VARIANT data = Bridge->GetDeviceList(L"86A4D2890E0B");
int lastError = Bridge->GetBridgeStatus(1);
if (lastError != 34) // failure of bus scanning
AfxMessageBox(Bridge->GetStatusMsg(lastError),
MB_ICONERROR | MB_OK);
else // bus scanned successfully
{
SAFEARRAY FAR *List = data.parray;
long highBound, lowBound, count;
SafeArrayGetUBound(List, 1, &highBound);
SafeArrayGetLBound(List, 1, &lowBound);
count = highBound - lowBound + 1;
BYTE HUGEP *pDevice;
CString s,strDevice;
s.Format(L"Devices Count: %d\n\r",count-1);
SafeArrayAccessData(List, (void HUGEP* FAR*)&pDevice);
for(int i = 1; i < count; i++){
int device = pDevice[i];
strDevice.Format(L"0x%02X\r\n",device);
s += strDevice;
}
SafeArrayUnaccessData(List);
AfxMessageBox(s,MB_ICONINFORMATION | MB_OK);
}
SendIICdata(BridgeID,DeviceAddress,Data) – This function sends an array of byte Data to the I2C device addressed by
DeviceAddress connected to the bridge given by BridgeID. It returns a status code indicating the result of the transaction. It
generates Start and Stop signals on I2C bus for each transaction.
Language
Interface and Usage Example
C#
object SendIICdata(string BridgeID, int DeviceAddress, object Data);
object r;
byte[] data = new byte[5];
for (byte i=0; i<5; i++) data[i]=i;
r = Bridge.SendIICdata("86A4D2890E0B", 0x00, data);
if ((int)r != 34) // Error occurred
{
MessageBox.Show(Bridge.GetStatusMsg((int)r));
}
else // data sent successfully
{ ... }
Visual Basic
Function SendIICdata(ByVal BridgeID As String, ByVal DeviceAddress As Integer,
.NET
ByVal Data As Object) As Object
Dim data() = {0, 1, 2, 3, 4, 5, 6, 7} 'data to send
Dim r = Bridge.SendIICdata("86A4D2890E0B", &H0, data)
If (r <> 34) Then 'Error occurred
MessageBox.Show(Bridge.GetStatusMsg(r))
Else
'data sent successfully
...
End If
Delphi
Function SendIICdata(const BridgeID: WideString; DeviceAddress: Integer;
Data:OleVariant): OleVariant;
var r,i: byte;
data: OleVariant;
begin
data := VarArrayCreate([0,7],varByte);
for i:=0 to 7 do data[i]:=i;
r := Bridge.SendIICdata('86A4D2890E0B', $00, data);
if (r <> 34) then // Error occurred
MessageDlg(Bridge.GetStatusMsg(r),mtError,[mbOk],0)
else begin // data sent successfully
...
end;
end;
May 5, 2010
Document No. 001-27079 Rev. *A
- 24 -
[+] Feedback
AN27079
Language
Interface and Usage Example
C++ Builder
TVariant SendIICdata(BSTR BridgeID, long DeviceAddress; VARIANT Data);
WideString BridgeID = L"86A4D2890E0B";
Variant data;
int Bounds[2] = {0,7};
data = VarArrayCreate(Bounds,1,varByte);
for (int i=0; i<=7; i++) data.PutElement(2*i,i);
Variant r = Bridge->SendIICdata(BridgeID, 0x00, data);
if (r != 34) // Error occurred
{
MessageDlg(Bridge->GetStatusMsg(r),mtError,
TMsgDlgButtons() << mbOK,0);
}
else // data sent successfully
{ ... }
C++ MFC
VARIANT SendIICdata(LPCTSTR BridgeID, long DeviceAddress, VARIANT& Data);
VARIANT FAR data;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
// low bound is 0
rgsabound[0].cElements = 8; // number of elements is 8
data.vt = VT_ARRAY | VT_UI1; // array of bytes
data.parray = SafeArrayCreate(VT_UI1,1,rgsabound);
for (long i=0; i<8; i++) {
BYTE byte = (BYTE)i;
SafeArrayPutElement(data.parray, &i, &byte);
}
VARIANT r = Bridge->SendIICdata(L"86A4D2890E0B", 0x00, data);
if (r.bVal != 34) // Error occurred
{
AfxMessageBox(Bridge->GetStatusMsg(r.bVal),
MB_ICONERROR | MB_OK);
}
else // data sent successfully
{ ... }
SafeArrayDestroy(data.parray);
ReadIICdata(BridgeID,DeviceAddress,DataLen,DataIn) – This function reads DataLen bytes in the array DataIn from the
I2C device addressed by DeviceAddress connected to the bridge given by BridgeID. It returns a status code indicating the
result of the transaction. It generates Start and Stop signals on I2C bus for each transaction.
Language
Interface and Usage Example
C#
int ReadIICdata(string BridgeID, int DeviceAddress, int DataLen, out object DataIn);
int r;
object dataIn;
r = Bridge.ReadIICdata("86A4D2890E0B", 0x00, 5, out dataIn);
byte[] data = dataIn as byte[];
if (r == 34) // data read successfully
{
string s = "";
for (byte i = 0; i < 5; i++) s = s + data[i] + " ";
MessageBox.Show("Read 5 bytes from Device 0x00: " + s);
}
Visual Basic
.NET
May 5, 2010
Function ReadIICdata(ByVal BridgeID As String, ByVal DeviceAddress As Integer,
ByVal DataLen As Integer, ByRef DataIn As Object) As Integer
Document No. 001-27079 Rev. *A
- 25 -
[+] Feedback
AN27079
Language
Interface and Usage Example
Dim dataIn = Nothing
Dim r = Bridge.ReadIICdata("86A4D2890E0B", &H0, 5, dataIn)
If (r = 34) Then 'data read successfully
Dim s = ""
Dim i As Integer
For i = 0 To 4 Step 1
Dim ReadByte As Byte = dataIn(i)
s = s + ReadByte.ToString("X2") + " "
Next
MessageBox.Show("Read 5 bytes from Device 0x00: " + s)
End If
Delphi
Function ReadIICdata(const BridgeID: WideString; DeviceAddress: Integer;
DataLen: Integer; out DataIn: OleVariant): Integer;
var r,i:byte;
dataIn: OleVariant;
s:string;
begin
r := Bridge.ReadIICdata('86A4D2890E0B', $00, 5, dataIn);
if (r = 34) then begin // data read successfully
s:='';
for i:=0 to 4 do s := s + IntToHex(dataIn[i],2) + ' ';
MessageDlg('Read 5 bytes from Device 0x00: ' + s,
mtInformation,[mbOk],0);
end;
end;
C++ Builder
long ReadIICdata(BSTR BridgeID, long DeviceAddress; long DataLen, VARIANT* DataIn);
WideString BridgeID = L"86A4D2890E0B";
Variant dataIn;
Variant r = Bridge->ReadIICdata(BridgeID, 0x00, 5, dataIn);
if (r == 34) // data read successfully
{
AnsiString s = "Read 5 bytes from Device 0x00: ";
for (int i = 0; i < 5; i++) {
unsigned char ReadByte = dataIn.GetElement(i);
s += (IntToHex(ReadByte,2) + " ");
}
MessageDlg(s,mtInformation,TMsgDlgButtons() << mbOK,0);
}
C++ MFC
long ReadIICdata(LPCTSTR BridgeID, long DeviceAddress, long DataLen,
VARIANT* DataIn);
VARIANT dataIn;
VariantInit(&dataIn);
long r = Bridge->ReadIICdata(L"86A4D2890E0B", 0x00, 5, &dataIn);
if (r == 34) // data read successfully
{
CString s = L"Read 5 bytes from Device 0x00: ";
CString strByte;
for (long i = 0; i < 5; i++) {
BYTE ReadByte;
SafeArrayGetElement(dataIn.parray, &i, &ReadByte);
strByte.Format(L"%02X ",ReadByte);
s += strByte;
}
AfxMessageBox(s,MB_ICONINFORMATION | MB_OK);
}
VariantClear(&dataIn);
May 5, 2010
Document No. 001-27079 Rev. *A
- 26 -
[+] Feedback
AN27079
ReadIICdataReg(BridgeID,DeviceAddress,ReadAddress,DataLen,DataIn) – This function reads DataLen bytes in the array
DataIn from the register (memory address, offset) specified by ReadAddress of the I2C device addressed by DeviceAddress
connected to the bridge given by BridgeID. This function is implemented to support the Cypress I2C Port Expander with
EEPROM. It can also be used with I2C devices that have similar transaction sequences on the I2C bus during read-register
operation. It assumes that the I2C device has an addressable memory organization. To learn more about this device refer to
the CY8C95xx data sheet and AN2304. Note that the ReadAddress parameter is an array of bytes because the address can
be 1 or 2 bytes wide. It returns a status code indicating the result of the transaction.
This transaction consists of two steps:
1.
Generate start condition, send “DeviceAddress” and then write “ReadAdress”, but do not generate Stop at the end of this
sub-transaction.
2.
Generate Restart condition, send “DeviceAddress” and then read “DataLen” bytes from Device. Put Stop at the end of this
sub-transaction.
Two other APIs, SendIICData() and ReadIICdata(), always generate Start and Stop for their transactions.
Language
Interface and Usage Example
C#
int ReadIICdataReg(string BridgeID, int DeviceAddress, object ReadAddress,
int DataLen, out object DataIn);
int r;
object dataIn;
byte[] ReadAddress = new byte[2] { 0x01, 0x00 }; // 0x0100 EEPROM address
r = Bridge.ReadIICdataReg("86A4D2890E0B", 0x5B, ReadAddress, 3,
out dataIn);
byte[] data = dataIn as byte[];
if (r == 34) // data read successfully
{
string s = "";
for (byte i = 0; i < 3; i++)
s = s + data[i].ToString("X2") + " ";
MessageBox.Show("Read data from addr 0x0100 of EEPROM Device
0x5B: " + s);
}
Visual Basic
.NET
Function ReadIICdataReg(ByVal BridgeID As String, ByVal DeviceAddress As Integer,
ByVal ReadAddr As Object, ByVal DataLen As Integer,
ByRef DataIn As Object) As Integer
Dim dataIn = Nothing
Dim ReadAddress() = {&H1, &H0} ' 0x0100 EEPROM's address
Dim r = Bridge.ReadIICdataReg("86A4D2890E0B", &H5B, ReadAddress,
3, dataIn)
If (r = 34) Then 'data read successfully
Dim s = ""
Dim i As Byte
For i = 0 To 2 Step 1
Dim ReadByte As Byte = dataIn(i)
s = s + ReadByte.ToString("X2") + " "
Next
MessageBox.Show("Read data from addr 0x0100 of EEPROM Device
0x5B: " + s)
End If
Delphi
Function ReadIICdataReg(const BridgeID: WideString; DeviceAddress: Integer;
ReadAddr: OleVariant; DataLen: Integer;
out DataIn: OleVariant): Integer;
May 5, 2010
Document No. 001-27079 Rev. *A
- 27 -
[+] Feedback
AN27079
Language
Interface and Usage Example
var r,i:byte;
dataIn,ReadAddress: OleVariant;
s:string;
begin
ReadAddress := VarArrayCreate([0,1],varByte);
ReadAddress[0]:=$01; ReadAddress[1]:=$00; // 0x0100 address
r := Bridge.ReadIICdataReg('86A4D2890E0B', $5B,
ReadAddress, 3, dataIn);
if (r = 34) then begin // data read successfully
s:='';
for i:=0 to 2 do s := s + IntToHex(dataIn[i],2) + ' ';
MessageDlg('Read data from addr 0x0100 of EEPROM Device
0x5B:'+ s, mtInformation,[mbOk],0);
end;
end;
C++ Builder
long ReadIICdataReg(BSTR BridgeID, long DeviceAddress; VARIANT ReadAddr,
long DataLen, VARIANT* DataIn);
WideString BridgeID = L"86A4D2890E0B";
Variant ReadAddress;
int Bounds[2] = {0,1};
ReadAddress = VarArrayCreate(Bounds,1,varByte);
ReadAddress.PutElement(0x01,0); // High of 0x0100 EEPROM address
ReadAddress.PutElement(0x00,1); // Low of 0x0100 EEPROM address
Variant dataIn;
Variant r = Bridge->ReadIICdataReg(BridgeID, 0x5B, ReadAddress,
3, dataIn);
if (r == 34) // data read successfully
{
AnsiString s = "Read data from addr 0x0100 of EEPROM Device 0x5B: ";
for (int i = 0; i < 3; i++) {
unsigned char ReadByte = dataIn.GetElement(i);
s += (IntToHex(ReadByte,2) + " ");
}
MessageDlg(s,mtInformation,TMsgDlgButtons() << mbOK,0);
}
C++ MFC
long ReadIICdata(LPCTSTR BridgeID, long DeviceAddress, VARIANT& ReadAddr,
long DataLen, VARIANT* DataIn);
CByteArray baAddr;
baAddr.SetSize (2);
// 2 byte Address of EEPROM storage cell
baAddr.SetAt(0,0x01); // High of 0x0100 EEPROM address
baAddr.SetAt(1,0x00); // Low of 0x0100 EEPROM address
COleVariant ReadAddress(baAddr); // Create ReadAddress argument
VARIANT dataIn;
VariantInit(&dataIn);
long r = Bridge->ReadIICdataReg(L"86A4D2890E0B", 0x5B, ReadAddress,
3, &dataIn);
if (r == 34) // data read successfully
{
CString s = L"Read data from addr 0x0100 of EEPROM Device 0x5B: ";
CString strByte;
for (long i = 0; i < 3; i++) {
BYTE ReadByte;
SafeArrayGetElement(dataIn.parray, &i, &ReadByte);
strByte.Format(L"%02X ",ReadByte);
s += strByte;
}
AfxMessageBox(s,MB_ICONINFORMATION | MB_OK);
}
VariantClear(&dataIn);
May 5, 2010
Document No. 001-27079 Rev. *A
- 28 -
[+] Feedback
AN27079
AbortTransfer() – This function aborts transactions with a bridge during asynchronous operation. It reinitializes software
transfer protocol and breaks all active transactions. It closes the active bridge handle. Call this function if your software needs
to free the Windows file handle of the active bridge connection to enable other applications to communicate with it. The bridge
becomes active (its file handle is opened and used by this application), when you communicate with it using its BridgeID in the
any of previously described functions.
Language
Interface and Usage Example
C#
void AbortTransfer();
Bridge.AbortTransfer();
Visual Basic
.NET
Delphi
Sub AbortTransfer()
Bridge.AbortTransfer()
Procedure AbortTransfer;
Bridge.AbortTransfer()
C++ Builder
void AbortTransfer(void);
Bridge->AbortTransfer();
C++ MFC
void AbortTransfer();
Bridge->AbortTransfer();
Demonstration Software
As part of the quick start guide, a special demo program is
developed, which demonstrates the features of the
ActiveX control in one application. They are the most
commonly used functions of the bridge driver. This
application is developed in multiple programming
languages to help different users to start coding with the
ActiveX control quickly. Figure 5 shows the interface of the
C# application.
Figure 5. Demo Application of Bridge ActiveX Control
In the figure, the I2C communication section sends data to
or reads data from the I2C device selected in the Devices
Connected to Bridge box. Data is represented in HEX
format.
To start this demo:
1.
Run the application.
2.
Click Connect. Select the Bridge from the
Connected USB <-> I2C Bridges list (or connect a
Bridge to USB port and then select it).
3.
Set the required Bridge Power and IIC Bus Speed.
4.
Click the Device List button.
5.
Select the I2C device from the list.
You can then use the I2C communication section.
May 5, 2010
Document No. 001-27079 Rev. *A
- 29 -
[+] Feedback
AN27079
Example of a Real Application

This section is useful for engineers who are not experts in
Windows programming, but need to develop some GUI
software to visualize data from their I2C devices. If you are
comfortable with Windows application development, skip
this section. It covers general questions and
recommendations
about
different
methods
of
communication implementation in the C# language. C#
was selected due to its popularity. If you prefer another
language, this section is still useful to help you understand
the basic principles and procedures used by IDEs to
organize communication processes with the bridge.
Each of these ways has its advantages and drawbacks.
The following discussion contains some recommendations
about where each of them is preferred.
Many PC applications that communicate with external
devices require frequent or continuous data exchange with
the real world (through sensors). The applications may
monitor the actual sensor’s state, build signal graphs in
quasi-real time mode, and provide feedback correlation.
The application described here requires continuous sensor
polling; at the same time it controls the state of the LEDs.
This makes it a good example of a typical application with
bidirectional communication.
Task Definition
The application uses the I2C slave demo board from I2CUSB bridge kit (CY3240). It has two LEDs, temperature
and illumination sensors onboard. At the core of this board
is a CY8C21123 PSoC device, which provides an I2C
interface with the host. This example develops a C#
application that continuously reads the latest state of both
sensors, and allows you to manipulate the state of the two
LEDs. For this example, the bridge is connected to the PC
2
and has an I C slave address of zero.
Solution
This example demonstrates how to implement a
communication process with an I2C device. It explains how
to do it in three different ways:


Using the Application.DoEvents() method
Create a WinForm application that demonstrates the use
of each of these methods. The form is shown in Figure 6.
Figure 6. Real Application View
In the Method group, select the I2C communication
algorithm. The I2C device group manipulates the LEDs of
the target device and shows the latest measured
temperature and illumination of the device’s sensors. The
active Bridge and actual Polling Rate (speed) calculated
during communication are shown in the status bar. The
Result indicates the result of the last I2C transaction. Only
successfully finished transactions are taken into account
to calculate the polling rate.
Select any method and click the Start button, then test the
I2C device section. It takes several seconds for the polling
rate to be measured. Changing the state of the LEDs
during this time leads to inaccuracy. It is alright, even if
you do not have an I2C device available for this test. It is
more important to understand the source of these
methods. Click Stop to terminate communication.
Comparative Analysis of the Methods
Table 1 lists the basic characteristics of the methods.
Using a threading approach
Using a Timer resource
Table 1. Communication Methods Summary
Method
Execution
Context
Transaction
Initiator
Working Function
Speed Range
Measured Speed
Threading
Polling Thread
Application
Thread Function
[Low ... Fast]
195 pkts/sec
Timer
Main Thread
System Timer of
Windows
Timer Event
Handler
[Low ... Average]
65 pkts/sec
Application.DoEvents()
Main Thread
Application
User Function
[Fast ... Fastest]
250 pkts/sec
Select the method that best fits your application
requirements. Note that values in the Measured Speed
column are not absolute. They can vary depending on
factors such as PC performance and load, packet length,
and bus speed. Consider them as a quality estimation of
the speed rather than quantity. The values in that column
are close to the maximum speed that can be reached
using the corresponding method.
May 5, 2010
The derivation of the results in the Measured Speed
column is described in the following section.
Document No. 001-27079 Rev. *A
- 30 -
[+] Feedback
AN27079
Threading
The example has a main thread and a second thread
intended for communication. All actions related to I2C bus
data exchange are executed in the communication
thread’s function (method):
public void RunProc()
{
while (true)
{
OneCommIteration();
Thread.Sleep(0);
}
}
Timer is a convenient function to use in low speed
applications. The main advantage of this method is its
simplicity because there are no synchronization problems
and it uses a standard control.
Application.DoEvents()
Application is a class that encapsulates Windows Forms
support necessary for each application.
This procedure is run in parallel to the main thread, so
time resources of the process are divided between them.
For this reason, it cannot reach the high speed of the
Application.DoEvents method.
The transaction initiator according to the table is the
application. It is the OneCommIteration() function, which is
called continuously in the infinite loop. It implements all
communication details, measures speed, and displays
received data on the form. Using the Sleep(x) method
between transactions regulates the polling speed.
Therefore, the Speed Range characteristic of this method
is very wide. This universal communication method can be
used in a wide range of applications. The main advantage
of threading is that I2C transactions are executed in
background mode while the main thread carries out its
direct functions (processing events). Multithreading helps
to divide the load among a pool of threads. This method
can cause problems related to access of common
resources from different threads. To avoid this, some
synchronization is necessary.
Timer
In this example, a standard Windows Forms’ Timer control
is used. It polls the I2C device regularly. The timing
intervals cannot be small enough to get as high a speed
as the other methods. In this example, the timer interval
property is set to 5 ms. Theoretically, the polling speed
should be 1000/5 = 200 pkts/sec. But the speed here is 65
pkts/sec. Why the difference?
The timer is a Windows system resource and sends
events to application WM_TIMER at regular intervals.
After WM_TIMER processes this message, it calls the
timer event handler. In the example it is:
private void timer_Tick(object sender, EventArgs
e)
{
OneCommIteration();
}
If you run the timer with a very short period, the system
can get paralyzed, doing nothing but timer event handling.
To avoid this, Windows admits only one WM_TIMER
event placed in the message queue of every application at
any moment of time. Also, the WM_TIMER event is
generated by the system only if there are no unhandled
messages in the queue (excepting WM_PAINT). Thus, all
other messages have a higher priority than timer does.
May 5, 2010
The applications waits until Windows allows it to call the
OneCommIteration() function. The application does not
influence the traffic directly.
DoEvents() is a static method of the Application class,
which provides the ability to process messages from a
queue during execution of long operations.
This is a tricky method and should be use with care. The
communication procedure is as follows:
private void AppCommunicate()
{
if (fIsStarted) return;
fIsStarted = true;
while (fIsStarted)
{
OneCommIteration();
Application.DoEvents();
}
}
This code is initiated when you click the Start button. It is
executed in the main thread until you click the Stop button
(sets the fIsStarted variable to false).
How does it work? Using the Application.DoEvents()
method between transactions enables the application to
respond to user activity. This allows the Stop button to
terminate communication. If you comment out the
Application.DoEvents() call in the code, the application
hangs (you get only infinite bridge polling, without updating
the information on the form).
Why is this method the fastest? Because, it works in the
context of the main thread and initiates all transactions.
Note that this method does not allow you to manipulate
the communication speed as easily as the other two
methods. It is intended for high speed applications only.
This section should help you develop your own
applications that require full-functional I2C communication.
Summary
The USB2IIC ActiveX component helps you write software
to easily interface with the USB-I2C bridge. Use parts of
this application in your designs to save time in total
product development.
This is not the final release of the bridge software
documentation. The bridge is an evolving project. This
document will be update if the hardware, firmware, or the
corresponding software is modified.
Document No. 001-27079 Rev. *A
- 31 -
[+] Feedback
AN27079
About the Author
Name:
Andrew Smetana
Title:
Senior Software Engineer
Background:
Andrew Smetana received a Master of Science degree in 2004 from
National University “Lvivska Polytechnika” (Ukraine). He has 7 years
experience in software development and embedded designs. His
interests involve different aspects of software development: SW
architecture, Windows OS, computer graphics, math, investigating and
developing algorithms, conundrums, and low level system
programming. He also focuses on designs from embedded world and
communication protocols.
Contact:
[email protected]
Document History
Document Title: Developing PC Applications for USB-I2C Bridge
Document Number: 001-27079
Revision
ECN
Orig. of
Change
Submission
Date
Description of Change
**
1506205
Andrew
Smetana
09/24/07
New Application Note
*A
2918410
Andrew
Smetana
05/05/10
Updated content to describe how the following APIs generate Start/Stop/Restart
signals on the I2C-bus: 1. ReadIICdata(); 2. ReadIICdataReg(); 3. SendIICdata()
PSoC is a registered trademark of Cypress Semiconductor Corp. "Programmable System-on-Chip" is a trademark of Cypress Semiconductor
Corp. All other trademarks or registered trademarks referenced herein are the property of their respective owners.
Cypress Semiconductor
198 Champion Court
San Jose, CA 95134-1709
Phone: 408-943-2600
Fax: 408-943-4730
http://www.cypress.com/
© Cypress Semiconductor Corporation, 2007-2010. The information contained herein is subject to change without notice. Cypress Semiconductor
Corporation assumes no responsibility for the use of any circuitry other than circuitry embodied in a Cypress product. Nor does it convey or imply any
license under patent or other rights. Cypress products are not warranted nor intended to be used for medical, life support, life saving, critical control or
safety applications, unless pursuant to an express written agreement with Cypress. Furthermore, Cypress does not authorize its products for use as
critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The
inclusion of Cypress products in life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies
Cypress against all charges.
This Source Code (software and/or firmware) is owned by Cypress Semiconductor Corporation (Cypress) and is protected by and subject to worldwide
patent protection (United States and foreign), United States copyright laws and international treaty provisions. Cypress hereby grants to licensee a
personal, non-exclusive, non-transferable license to copy, use, modify, create derivative works of, and compile the Cypress Source Code and derivative
works for the sole purpose of creating custom software and or firmware in support of licensee product to be used only in conjunction with a Cypress
integrated circuit as specified in the applicable agreement. Any reproduction, modification, translation, compilation, or representation of this Source
Code except as specified above is prohibited without the express written permission of Cypress.
Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the
right to make changes without further notice to the materials described herein. Cypress does not assume any liability arising out of the application or
use of any product or circuit described herein. Cypress does not authorize its products for use as critical components in life-support systems where a
malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress’ product in a life-support systems
application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
Use may be limited by and subject to the applicable Cypress software license agreement.
May 5, 2010
Document No. 001-27079 Rev. *A
- 32 -
[+] Feedback