Fsbus DLL Manual
Fsbus DLL Manual
FSBUS DLL
Programmers
Manual
2008
Version 1.0
Dirk Anderseck
FSBUS DLL
History
08/2008 Change in CheckIn procedure; fsobjects.cpp with all fsuipc
variables added
This SDK is posted with the intention that flightsim enthusiasts around the world will
be able to build their own cockpit that are both inexpensive and highly functional.
While the instructions may be printed and followed at no charge, they are not
intended to be used as instructions for starting your own business.
Terms of use
The software and documentation included in the FSBUS DLL is copyrighted by Dirk
Anderseck (dirk@anderseck-net).
Permission is granted to anyone to use this software for any purpose, FSBUS DLL is
free software for non-commercial purpose.
All rights in the Software (including any images or text incorporated into the
Software) are owned by the author of this software, except otherwise stated.
The author of this software does not guarantee that this software is free from bugs
or free from viruses.
The author may, from time to time, revise or update the Software. In so doing, the
author incurs no obligation to furnish such revision or updates to you.
The software is provided “as is” and the author disclaims all other warrenties and
conditions, fitness for a particular purpose, conformance with description, title and
non-infringement of third party rights.
Introduction
The FSBUS DLL is a powerfull tool for your home-cockpit. It integrates the flightsim
interface, the FSBUS hardware, the DirectX Sound Mixer, timers and more into an
easy programming API.
You need to define your FSBUS hardware objects and modify the list of the fsuipc
variables, which are predefined for your convinience.
I have designed the interface as easy as possible. That’s the reason why the syntax
is classic C-style for console applications.
I have developed the DLL with Microsoft Visual C++ 2008 Express, which is free
available in the internet. The tests were made with Windows Vista and FSX SP2. It
may also work with Windows XP and FS2004.
The FSBUS DLL makes use of fsuipc. According to the license policy of the fsuipc
interface, your selfmade application may require a personal license, which you can
refer over the Internet. It’s up to you to fullfill these license terms.
The FSBUS DLL itself is free for personal usage. If you like it, a small donation is
welcome (please refer to www.fsbus.de ).
Thank you!
Files
There is also a “Zero Cockpit” zip file which contains a small cockpit solution ready to
run with Microsoft Visual C++ 2008 tools. This could be a base for any of your
cockpits. You can extract the file into a directory of your choice, start Visual C++ and
open the cockpit.vcproj file.
fsbus.dll The DLL which is loaded, when your exe program starts.
fsbus.lib This file is the interface to the DLL. You will have to add
this file as a resource into your project.
laser.wav This is a demo sound for the intro1 sample. FSBUS DLL
makes use of Direct Sound.
Requirements
• Windows XP, Windows Vista
• Microsoft Flightsimulator 2004, FSX
• fsuipc DLL in Modules folder of Flight Simulator
• Microsoft Visual C++ 2008 Express Edition
• Microsoft Windows SDK
int _tmain(int argc, _TCHAR* argv[]) The main function is the start of a C-program.
{
void EventCallback(int oid,int val,double dval) This function is called from the DLL at any event.
{
DWORD dw;
The timer T_HEY is fired one time after 1s. The
switch (oid)
{ action to this event is playing the laser sound
case T_HEY: followed by a direct read of the fsuipc version
Play(M_MYSOUND); number.
FsReadDirect(0x3306, 2, &dw);
With these predefined objects you have access to any of the thousands of
parameters inside Flightsim. To access an object, you pass the object ID (oid) to
one the FSBUS DLL functions.
There are two strategies to read a value from flightsim, POLLING and DIRECTREAD.
All frequently used values should be polled automatically by the internal FSBUS DLL
functions.
Anyway you can obtain a value from flightsim by calling FsReadDirect(). This should
be used for parameters read once or very few times. Another good choice of
FsReadDirect is, if you read variables with special length or format.
Each change of the value is sent as an event to your event callback function. There
are 3 parameters in the callback, the first identifies the source, the second one
contains a converted integer value and the third is the floating point value, which is
valid for fsuipc parameters in 8 byte floating point format.
// file fsobjects.cpp:
MakeFsObject(FS_PAUSEINDICATOR, 0x0264, 2,TP_UI16, FS_NORMAL);
Example: read the objects read buffer, instead of using the converted int “val”.
switch (oid)
{
case FS_PAUSEINDICATOR:
FsGetCompareBuffers (oid, &newvar, &lastvar);
if (newvar->urd.i16 == 0)
printf (“continue flying\r\n”);
else
printf (“time for coffee \r\n”);
break;
}
}
This is very usefull for values with a high resolution as the altitude value which
changes very frequently, because the resolution is in some millimeters.
It makes no sense to perform actions on a millimeter base. It only costs cpu time.
With FsGetCompareBuffers() you now have a chance to make your own compare and
probably return without action.
Example:
short zoom;
FsReadDirect (0x02b2, 2, &zoom);
The arguments for this function are the fsuipc based offset, the length information
and an address of a variable, where to put the read value.
oid The id of this object (1-3999). You may choose your own numbering
scheme.
c Controller ID
flg Flags
FLG_DISABLED
FLG_ONESHOT
Example:
Each hardware event (button, switch, rotary, pot) is sent as an event to your event
callback function. There is one parameter in the callback, that contains the converted
integer value.
BOOL FsbusWrite(unsigned char* buf, int You can build your own buffer
according to the fsbus
count) software documentation and
send this raw buffer.
BOOL FsbusWriteFmt2(int cid, int rid, int val) FSBUS software format has 3
different length of command
blocks.
You can send a 2 byte long
format with this function.
BOOL FsbusWriteFmt3(int cid, int rid, int val) FSBUS software format has 3
different length of command
blocks.
You can send a 3 byte long
format with this function.
BOOL FsbusWriteFmtVar(int cid, int rid, int val) FSBUS software format has 3
different length of command
blocks.
You can send a variable length
format with this function.
FSBUS DLL
The FSBUS DLL contains functions and variables. The names and structures are
declared in fsbus.h.
DLL functions
GetFsbusDLLVersion
Syntax int GetFsbusDLLVersion ()
CheckIn
Syntax BOOL CheckIn (void (*cbEvent)(DObject* po, int v, double d))
This initializes the DLL functions and objects. cbEvent Is a pointer to
a function which receives any event of flightsim, fsbus hardware and
timers.
Return This function will return, if it was success full. If an error occurs
the error function is executed.
Unless you change the default error mode, the application will show a
message and stop execution.
CheckOut
Syntax BOOL CheckOut ();
FsbusMux
Syntax BOOL FsbusMux (int maxtime);
Return
This is the single multiplexer function, which handles all your defined
objects. Usually you call this function in a permanent loop. In order
to get you a chance to add own code, you define a time in milliseconds.
The function will return after that period.
In the example below, the kbhit function checks for a keyboard action
after the 500ms FSBUS actions are done.
Don’t worry about 500ms actions with full cpu load, the strategy is to
sleep most time. It’s your responsibility to keep your event code as
efficient as possible.
while (!kbhit())
FsbusMux(500);
MakeFsObject
Syntax BOOL MakeFsObject (int id, DWORD offset,int datasz, UTYPE datatp,
FSINTERVAL intvl, int flags);
Datatp: the type of the data. It is used for a default conversion into
an int32 datatype. Valid types are:
TP_I8, TP_UI8, // signed, unsigned 8Bit vars
TP_I16, TP_UI16, // signed, unsigned 16Bit vars
TP_I32, TP_UI32, // signed, unsigned 32Bit vars
TP_I64, // signed 64Bit vars
TP_DBL // 8Byte floating point vars
The only flag for FS objects is the FLG_DISABLED flag, which turns the
object off until you reenable it.
Example
#define F_BUSVOLT 1002
MakeFsObject (F_BUSVOLT, 0x2384,8, TP_DBL, FS_LAZY, 0);
MkFsbusObject
Syntax BOOL MkFsbusObject (FSBUSTYPE ftp, int id, int c, int r, int flg=0);
MkFsbusObject
MkFsbusObject (BTP_D_IN, C_GEARUP, 2, 33, FLG_DISABLED);
Enable(C_GEARUP
C_GEARUP);
C_GEARUP
MkTimer
Syntax BOOL MkTimer (int id, DWORD tm, int flg);
Return
Example
MkSound
Syntax BOOL MkSound (int id, char* soundfile);
The FSBUS DLL supports the DirectX polyphonic mixer capabilities. A
sound object is created with MkSound.
Return
Example
BCD2Int
Syntax int BCD2Int (unsigned short bcd);
This helper function converts the bcd based dataformat of some fsuipc
varaibles mainly in the navigation area.
Example
Keyboard
Syntax void Keyboard (const char* simple);
The FSBUS simple keyformat can generate keycodes for the following keys:
Numeric 0-9
Lowercase alpha a-z
Upercase alpha A-Z
German Umlauts äöüß
Special characters #,.-´<+
Return
Example Keyboard(“A”);
ExtKeyboard
Syntax void ExtKeyboard (const char* complex);
If you need to generate other keys, modifier keys, mouse events or other controls, you’ll
have to use the complex format.
Return
FsConnect
Syntax BOOL FsConnect ();
Connects the object to fsuipc. Flightsim must be started before executing FsConnect.
Return
Example
FsDisconnect
Syntax BOOL FsDisconnect ();
Disconnects the object from fsuipc.
Return
Example
FsReadDirect
Syntax BOOL FsReadDirect (int offset, int sz, void* dest)
You can read any offset in fsuipc without declaring an object with the FsReadDirect function.
Return
FsWriteDirect
Syntax BOOL FsWriteDirect (int offset, int sz, void* dest)
Return
FsWrite
Syntax BOOL FsWrite (int oid, int )
BOOL FsWrite (int oid, double)
BOOL FsWrite (int oid, __int64)
BOOL FsWrite (int oid, UVAR )
Return
Example
FsSetPollTiming
Syntax BOOL FsSetPollTiming (int quick, int normal, int lazy)
Any created DFsObject is assigned a poll class . The class determines the pollfrequency.
There are 4 classes defined:
None (no polling)
Lazy (3s)
Normal (300ms)
Fast (100ms)
FsbusOpen
Syntax BOOL FsbusOpen (LPSTR dev);
Open the serial interface. Dev is one of the predefined device names
like “COM1” “COM2” a.s.o.
Example try
{
CheckIn(EventCallback, EventCompare);
FsbusOpen("COM1");
}
catch (LPSTR text)
{
cout << text << endl;
}
FsbusClose
Syntax BOOL FsbusClose();
Close the serial interface.
Example FsbusClose();
FsbusWrite
Syntax BOOL FsbusWrite (int oid, int val);
FsbusWrite
Syntax BOOL FsbusWrite(unsigned char* buf, int count);
Usually, you send a command to one of your cockpit controls by
FsbusWrite(int oid, int val).
FsbusWrite is a generic function to build and send a command buffer by
yourself. Please refer to the software interface description at the end
of this book.
FsbusWriteFmt2
Syntax BOOL FsbusWriteFmt2(int cid, int rid, int val);
This is another way to send a command to an fsbus controller. All 2
byte long commands can be sent with this function.
FsbusWriteFmt3
Syntax BOOL FsbusWriteFmt3(int cid, int rid, int val);
This is another way to send a command to an fsbus controller. All 3
byte long commands can be sent with this function.
Example Send the voltage information (80%) to all controllers with command 131.
FsWriteFmt3 (0, 131, 80);
FsbusWriteFmtVar
Syntax BOOL FsbusWriteFmtVar(int cid, int rid, int val);
This Write function sends a variable length data format to controllers
which require longer data formats like stepper controller.
Example
DisplayOptions
Syntax BOOL DisplayOptions (int oid, int SegCount, int SegOffs, bool
LeadZero, int DecPoint);
Display Options sets some paramters to a 7 segment display controller.
The number of segment can vary between 3 and 6, the offset parameter is
a shift of the display start. If you want leading zeros, set LeadZero
to TRUE, The DecPoint controls the position of decimal point, where the
value zero means no decimal point.
Example
Error Handling
There are 3 different modes to deal with errors. The error mode is defined by the
internal variable “ErrorMode” which is of type ERRORMODE. It is declared in fsbus.h.
The default (EM_STOPEXECUTION) will show an error message on the console and
after a keypress, the application exits. This suites the needs of most applications.
If you like to handle all errors by yourself, you can set ErrorMode =
EM_RESUMERETURN. In this case, the error text is not shown on console, but copied
into the variable ErrorText. The function which caused the failure will return with
FALSE (if it is one of the BOOL ... functions) and you can code your own error
handling.
Own error handling may be usefull, if you want to control the initialization phase.
One example might be waiting for the flightsim until it has started.
Example code:
ErrorMode = EM_RESUMERETURN;
int retry;
if (retry >= 5)
{
printf (“cannot open flightsim\r\n”);
exit (1);
}
ErrorMode = EM_STOPEXECUTION; // continue with default error mode
People writing C++ application frequently use a throw/catch mode to handle errors.
If you want the DLL to throw an exception, set ErrorMode = EM_THROWEXCEPTION.
On error it will throw an exception with one argument of type LPSTR.
This project still contains some code for real cockpit implementations. Just look at
gauges.cpp, gauges.h and get an idea how you can extend that. It is also a
recommendation how to deal with more than one sourcecode file.
Now i will describe the steps to make a new throttle group by copying the gauges
example files.
Edit the throttle.h file and modify it. It should look loke this:
#ifndef __THROTTLE_H
#define __THROTTLE_H
void BuildThrottleObjects();
void cbThrottle (int oid, int val, double dval);
#endif
The important things are the new unique group id 5 and the associated name
OID_THROTTTLE_GROUP. There is one object to control the flightsim and an analogue
input (potentiometer) to receive the input. And as usual the definition of the
functions in throttle.cpp.
#include "stdafx.h"
void BuildThrottleObjects ()
{
MakeFsObject(FS_ENGINE1_THROTTLE_CONTROL, 0x089A, 2,TP_I16,
FS_NONE);
MkFsbusObject (BTP_A_IN, C_THROTTLE_LEVER_LEFT, 2, 70);
Dirk Anderseck, Erkrath dirk@anderseck.net 22 von 33
FSBUS DLL
}
We see the code to create both objects and the function which receives the throttle
movement events. Of coarse you have to modify the CID and RID to your cockpit
hardware address. The cbThrottle callback function will receive a value from 0 to
255 depending on the lever position. Each new value is sent immediatly to flightsim
by FsWrite. Since the fsuipc expects a value from 0 to 16384, we have to multiply val
by 64.
The first line includes the stdafx.h file. It contains the include statements of all our
selfmade groups. We have to manually add the last lines.
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include "fsbus.h"
#include "gauges.h"
#include "planectrl.h"
#include "llswitchboard.h"
#include "throttle.h"
Last not least, the main callback function in cockpit.cpp is modified. It now contains
code to dispatch all events of the throttle group to our cbThrottle function:
#include "stdafx.h"
BuildGaugesObjects();
BuildPlaneControlObjects();
BuildLLSwitchboardObjects ();
BuildThrottleObjects ();
FsConnect();
while (!_kbhit())
FsbusMux(500);
}
Once you are familiar with this scheme, you can adopt these procedures for any
group of your cockpit.
I made a design decision and reduced the number of objects, fsbus objects +
flightsim objects, to a maximum amout of 4096. This is due to performance issues.
Each object is accessed by an object id (OID). Accessing the objects is very
frequently done during runtime and a table in memory with 4096 slots is by far the
most quickest way to get a pointer to the objects.
The names for each object are C-macro names. All names and id’s are defined in .h
files.
If we are dealing with 10 or 100 objects, it’s easy to put all into a single file, but i
think our cockpit solutions are somewhat larger than 100.
I recommend grouping the objects into functional units and giving each unit or group
it’s own unique id. Please compare this to the ip addresses, where the network part
and computer part of the address are also mixed into a 4 byte ip address.
11 10 9 8 7 6 5 4 3 2 1 0
With 12 bit we can address 4096 different objects. Bits 0-4 allows us to define 32
objects per group.
Bits 5-11 allows to build 128 groups.
Guidelines
• Make individual files (.cpp sourcefile and .h include file) per group
Application Notes
Nearly every component of a real cockpit is driven by electric power. During flight the
power is supplied by one or more generators and a small battery is used to start the
engines and provide basic power during startup phase.
The FSBUS controllers have a builtin feature to emulate power up and down. It is
sent with a RID of 131.
The example below reads the battery value from flightsim via offset 0x2834. This
value ranges from 0 to 24 and is read from fsuipc as a double value. FSBUS supports
a percentage value, which is calculated by multiplying 100 and dividing 24. The
system route is used to send this value to any attached controller.
FSBUS dataformat
This chapter describes the dataformat for FSBUS hardware controllers. The hardware
parameters for serial communication is 19200bps, 8bit, no parity, 2 stop bit. Usually
you haven’t to deal with this format, because the Fsbus Object in the DLL does the
conversion.
The normal way of sending data to a piece of hardware is:
FsWrite (C_NAVDISPLAY, 11375);
If you like to do something special, like sending data as a broadcast to all controllers,
the following dataformat description and a couple of function will help you doing so.
A value may have different length and format. A general format is shown in the table
below. Value bits (V) are marked grey.
Byte 7 6 5 4 3 2 1 0
1 1 C4 C3 C2 C1 C0 R7 V0
2 0 R6 R5 R4 R3 R2 R1 R0
3 0 V7 V6 V5 V4 V3 V2 V1
4 0 V14 V13 V12 V11 V10 V9 V8
5 0 V21 V20 V19 V18 V17 V16 V15
6 0 V28 V27 V26 V25 V24 V23 V22
Byte 7 6 5 4 3 2 1 0
1 1 C4 C3 C2 C1 C0 R7 V0
2 0 R6 R5 R4 R3 R2 R1 R0
3 0 V7 V6 V5 V4 V3 V2 V1
Common R-Commands
all commonly used R-commands are numbered between 128 and 255.
R Name L
128 Reset 2 0: Reset controller without
displaying the CID
1: Reset controller and display
the CID after reboot
Except the display format, any IO controller uses this multi purpose data format.
R Name L to fsbus router to controller
0-7 Key R0 3 Keyvalue setup keytype
bit 0-7
8-15 Key R1 3 Keyvalue setup keytype
Display Controller
the display controllers display values are in a special format. It is detected by a 0 in
bit 1 of byte 0.
Each segment value is transmitted as a 4bit nibble. The dataformat has variable
length. The final byte is detected by a 1 in bit 6 of the last byte.
Byte 7 6 5 4 3 2 1 0
0 1 C4 C3 C2 C1 C0 0 x
1 0 0 A3 A2 B3 B2 B1 B0
2 0 0 A1 A0 C3 C2 C1 C0
3 0 0 D3 D2 E3 E2 E1 E0
4 0 1 D1 D0 F3 F2 F1 F0
C0-4 Controller ID
A,B,C,D,E,F nibbles for max. 6 segments
The decimal point is defined by a R-Command 132. The value defines the position of
decimal point:
F E D C B A
6 5 4 3 2 1
Byte 7 6 5 4 3 2 1 0
1 1 1 1 1 1 1 R7 V0
2 0 C6 C5 C4 C3 C2 C1 C0
3 0 R6 R5 R4 R3 R2 R1 R0
4 0 V7 V6 V5 V4 V3 V2 V1
5 0 V14 V13 V12 V11 V10 V9 V8
6 0 V21 V20 V19 V18 V17 V16 V15
7 0 V28 V27 V26 V25 V24 V23 V22
This format is now able to support 30 + 128 CID’s. There must be an updated
firmware for the controllers.