The following is from the "ServoDoc.pdf" provided by Sitech in support of their
controller, and from and correspondence wth Dan Gray.


USB to Serial
=============

The chip is an FTDI IC that makes the controller appear as a serial port on 
the host computer.  The default baud rate is 19.2kb between the controller 
and the USB-to-Serial converter.

Code snippet for motor rates
============================

internal static double DegsPerSec2MotorSpeed(double dps, double TicksPerRev)
{
    return Math.Round(TicksPerRev * dps * 0.09321272116971);
}


internal static double MotorSpeed2DegsPerSec(double Speed, double TicksPerRev)
{
    if (TicksPerRev == 0.0) TicksPerRev= 1.0;
    return Speed/TicksPerRev*10.7281494140625;
}

internal const double SiderealConstant  = 0.00038942519;
internal static double TicksPerRev2SiderealRate(double TicksPerRev)
{
    return Math.Round(TicksPerRev * SiderealConstant);
}

The serial port routine in the controller takes a "snapshot" of all 4 encoders,
at a single moment, so the information you have with the binary protocol is for
a single moment in time.  You have to do whatever you need to do to cascade the
motor location to make the scope encoder location accurate.  Look below for
information about 

XXS<cr>
XXR<cr>
YXR<cr>



Controller communication protocol
=================================

The following is the ASCII protocol documented on the Sitech website.  The
binary protocol is described at the end of this file.

List of ASCII commands (all get terminated with an <cr> ). 

Note in Sitech's document they refer to CR as <E>.  However, CR is 0dh,
decimal 13, or "\r" in a C string so take care not to be confused by
this in the following.  CR is the requisit terminator for most ASCII 
controller commands.  We use <cr> here to represent this return.

Be sure to use upper case.

For the Azimuth or Right Ascension servo, use 'Y' instead of 'X' The # symbol
means there is a number required.

The X servo is the Altitude or Declination. The Y servo is the Azimuth or Right
Ascension.

If you change the Address of the controller AD1, AD3,
or AD5, the controller will respond differently. If the address is
3, then all beginning X's should be T's, and beginning Y's should be U's.

If you've changed your address to Address 5, then use V and W for X and Y.

To change the address of a controller from the default (1) to (2), 
send the byte sequence: AD2<cr>

(Make sure any other controllers are not connected to the serial port first). If
you want to make this permanent, you will have to write to the flash ROM. This
would normally be the XW command, but since the controller address
is 2 now, you would issue the command TW.

If the controller is Address 1, and if you send an <cr> with nothing before it,
the controller responds with a lot of useful information as follows:

X# Y# XZ# YZ# XC# YC# V# T# X(A or M) Y(A or M) K#

Where:

X# is the location of the Altitude/Dec Axis in MOTOR encoder ticks

Y# is the location of the Azimuth/RA Axis in MOTOR encoder ticks

XZ# is the location of the Altitude/Dec Axis in SCOPE encoder ticks

YZ# is the location of the Azimuth/RA Axis in SCOPE encoder ticks

XC# is the Altitude/Dec motor current * 100.0

YC# is the Azimuth/RA motor current * 100.0

V# is the controller power supply voltage * 10.0

T# is the controller CPU temperature (Deg's F )

XA (or XM) is the Altitude/Dec Motor status, if XA, it's in Auto (normal) if XM,
it's in manual.

YA (or YM) is the Azimuth/RA Motor status, if YA, it's in Auto (normal) if YM,
it's in manual.

K# is the handpad Status. (Version 1.5 and later).



ASCII Commands:

SB# Set Baud Rate (1 = 9600, 2 = 19200) Changes all controllers on serial bus.
(1.5 or later)

X# Move Servo (-2147483648 to +2147483647) You can tag a speed command at the
end.

Example: X-2345S1000000<cr>

X Returns the X position of the servo

XF# Forces the X position to be equal to the number (-2147483648 to +2147483647)
(This stops the controller if moving)

XS# Velocity of X Servo (0-2147483647)

XS Returns the X velocity of the servo (what it would be if it was currently
moving at fully accelerated speed, this may not be what it acually is at the
moment).

XR# Ramping speed or Acceleration of X servo (0-3900)

XR Returns the Ramp speed.

XP# Proportional Band of X servo (0-32767)

XP Returns the Proportional band

XI# X Integral (0-32767)

XI Returns the Integral

XD# X Derivative (0-32767)

XD Returns the Integral

XE# Maximum position error limit before servo turns off (0-32767)

XEL Returns position error limit.

XE Returns the position error of the servo

XO# X Output limit (0-255)

XO Returns the PWM output of the servo (0-255)

XC# X Current Limit (0-240 = 0-2.40 amps)

XC Returns the X motor current * 100 (240 MAX)

XM# X to manual mode, the number is the PWM value, -255 to +255

XA X to Auto mode

XN X Normal Stop (ramps down, then stops. Automatically clears when new position
is given)

XNT Just like XN, except when it slows down enough, it starts tracking in the
DragNTrack or SlewNTrack mode

XG X Emergency stop (stops immediately)

XL# Set Integral Limit (0-24000)

XL Returns Integral Limit

XB# Number sets the servo bits like direction, etc. (0-255)

XB Returns current X Bits Value

XZ# Forces the scope encoder position to be equal to the number (-2147483648 to
+2147483647)

XZ Returns the scope encoder position


The following commands don't have a 'Y' command, only X. 
They affect both servos

XK Returns the handpad info in Decimal

XH Returns the temperature of the CPU chip (in deg's F)

XV Returns the firmware version * 10

XJ Returns the motor power supply voltage * 10 (please divide returned number by 10)

XQ Resets the servo system (both)

XU Programs factory defaults into the flash ROM

XW Writes the configuration of both the x and y parameters from working RAM to
the flash ROM

XT Reads the configuration from the Flash Rom into the working RAM

FC Flash Configure, Send 128 more bytes, then 2 bytes of checksum (Simple
Addition of all data bytes sent), and it will write the new data to
configuration. It also reads the new data into the working RAM

SC Send Configuration, The controller Sends 128 bytes, followed by two bytes of
checksum. This data is what is in the flash, not necessarily what is in the
working RAM.

All of the following XX extended commands have a corresponding read command
as an example, if you type "XXL<cr>" it responds with the latitude.

XXL# Store the latitude to the controller (4500 = 45 deg's north, -4500 = 45
deg's south)

XXZ# Store the azimuth encoder ticks per full circle

XXT# Store the altitude encoder ticks per full circle

XXU# Store the number of encoder ticks for the Altitude Motor Encoder to the
controller

XXV# Store the number of encoder ticks for the Azimuth Motor Encoder to the
controller

XXA# Stores the Altitude Slew Rate to the controller

XXB# Stores the Azimuth Slew Rate to the controller

XXC# Stores the Altitude Pan Rate to the controller

XXD# Stores the Azimuth Pan Rate to the controller

XXE# Stores the Platform tracking rate to the controller

XXF# Stores the Platform up/down adjuster to the controller

XXG# Stores the Platform Goal to the controller

XXH# Stores the Altitude Guide Rate to the controller

XXI# Stores the Azimuth Guide Rate to the controller

XXJ# Stores the PicServo Timeout Value to the controller (Seconds).

XXQ# Turns off or on the digital outputs of the Radio Handpad Reciever

XXN# A zero turns off the Argo Navis\u2122 mode. A one turns it on.

When the controller receives a 'Q' as the first character in a line, it responds
emulating the Tangent Q protocol. The encoder resolution is always 18000 (the
controller uses the configured values for encoder ticks per revolution for the
Scope Encoders, and converts it to 18000). If you are using servo firmware
version 1.6 or later, the following commands have been added:

XXK# Local Search Radius in arc Minutes

XXM# Local Search Speed in arc seconds per second.

XXO# Altitude Backlash

XXP# Azimuth Backlash

New commands in version 1.7:

XXW# Backlash Motor Speed (Speed while in the backlash area) 
Should be 200,000 to 500,000.

XXX# Altitude in deg's times 100. The altitude should be sent to the controller
by the host computer (ScopeII, the Ascom driver, etc) after initialization. Then
the Local searches will be round, and the Pan and Guide speeds will be linear in
relation to the sky (version 1.7 or later).

XXY# Sets the Azimuth/RA in the controller. Not useful until version 1.8.

0AAh Puts the servo into the PicServo Emulation mode (no CR required). See
http://www.jrkerr.com/psdata.pdf for a description. There are some items
different, all motion control is the same. The differences are descibed below.


The following two ASCII commands with Binary data are for reading and
controlling the servo controller in a very efficient manner. They have been
added at version 1.5 of the controller firmware.  (See below for more
information about the binary commands in the A200HR mount controller.)

XXS<cr>

The controller responds with four long ints of position, 
then other bytes for keypad status, X and Y Bits, and other bits as follows:

Byte 0-3 Current Altitude/Dec Motor Position (most to least significant)

Byte 4-7 Current Azimuth/RA Motor Position.

Byte 8-11 Current Altitude/Dec Scope Encoder Position

Byte 12-15 Current Azimuth/RA Scope Encoder Position.

Byte 16 is Keypad Status (see the top of this section for a description of bits)

Byte 17 is XBits

Byte 18 is YBits

Byte 19 is Extra bits

Bit 0 - Set if Altitude/Dec motor is stopped

Bit 1 - Set if Altitude/Dec motor is in manual

Bit 2 - future

Bit 3 - future

Bit 4 - Set if Azimuth/RA motor is stopped

Bit 5 - Set if Azimuth/RA motor is in manual

Bit 6 - future

Bit 7 - future

Byte 20 is a 1 byte checksum of the previous 19 bytes (simple addition).

XXR<cr>

The controller now waits for an additional 20 bytes from a host as follows:

Byte 0-3 New Altitude/Dec Motor Position Goal (least significant byte first)

Byte 4-7 New Azimuth/RA Motor Position Goal.

Byte 8-11 New Altitude/Dec Motor Speed

Byte 12-15 New Azimuth/RA Motor Speed

Byte 16 Various bits

Bit 0 
If '0', the following new XBit and YBit values are ignored. 
If '1', the new XBit and YBit values are used.

Bit 1 -7 future

Byte 17 New XBits value (must have previous bit 0 set)

Byte 18 New YBits value (must have previous bit 0 set)

Byte 19 Checksum of all above data bits (simple 8 bit addition)


If you use the above binary command to control the servo controller, be sure to
have a restart communication if the command gets out of sync by a communication
fault. If you receive a bad checksum, you should resync communication by sending
a few of XXS commands.

The flash RAM values are loaded from the flash ROM to RAM on reset.

Both the X and Y parameters are stored to the flash ROM.

Use X and Y for module address 1.

If the module address is 3, use 'T' and 'U', for address 5, it's 'V' and 'W'.

Description of the bits for the XBits and YBits:

0 if 1, the motor encoder is incremented the other direction

1 if 1, the motor polarity is reversed

2 if 1, the azimuth (or altitude) encoder is reversed

3 if 1, (x only) we're in the computerless drag and track mode

3 if 1, (y only) we're in the computerless slew and track mode 
(no clutches, must use handpad to slew)
(must be in drag and track too)

4 if 1, (x only) we're in the tracking platform mode

5 if 1, (x only) we enable the hand paddle

6 if 1, (x only) hand paddle is compatible with New Hand Paddle (allows slewing
in two directions, and guiding)

7 if 1, (x only) we're in the guide mode. The pan rate is added or subtracted
from the current tracking rate.

Note about the Guide Mode: If PC software puts the controller in the guide mode,
and you are controlling an Equatorial mount, you must give the declination motor
a destination, even if you want it to be stopped. If you want the declination
axis to be normally stopped, give the declination a far far away goal, and set
the speed to zero. This is because the controller adds or subtracts from the
current speed and direction, and the controller gets confused if the axis is at
its destination. This is changed inf servo version 1.6, and this is
automatically done for you in the controller. The Y_Bits bits 4-7 are the
digital input status for the 4 digital inputs from the radio handpad reciever.
This is only available if you're using servo version 1.6 and also if you have a
handpad reciever connected.

PicServo Mode Differences:

If you intend to write a telescope driver for the SiTech controller, we
recommend you use the new binary protocol mentioned above, as it is simpler and
faster. If you have exsisting software for the PicServo chips, you can use the
PicServo protocol, but there are a few differences as described here:

The controller address must be set beforehand, and saved to flash ROM. The
PicServo address commands are ignored with the SiTech controller. When the
controller is set for address 1, the altitude motor will be addressed with
address 1, and the azimuth with address 2. You can set address using the ASCII
command AD1, AD3, or AD5. You then save the address to flash ROM using the
following ASCII commands. \u201cXW\u201d for address 1, \u201cTW\u201d for
address2, and \u201cVW\u201d for address 3. This must be done with only 1
controller connected at a time. You can also set the address of the controller
using the ServoConfig software.

When the Define Status specifies the Home position for return, the
\u201cHOME\u201d position returnes the location of the telescope encoder
location, instead of the HOME position.

When the Define Status specifies the A/D to be returned, it returns the motor
current times 10 instead. Bit 6 of the Define Status must be clear.

When you set bit 6 of the Define Status, the motor voltage will be returned in
the A/D location if it is an odd address for the controller.

When you set bit 6 of the Define Status, the CPU temperature will be returned in
the A/D location if it is an even address for the controller.

The ReadVersion bit of the Define Status returns the handpad status instead of
the version. The handpad bits are as follows:

The handpad number is an 8 bit number where each bit represents a push button.

Bit 0 Left

Bit 1 Right

Bit 2 Up

Bit 3 Down

Bit 4 Speed (this is a toggle, a 1 is Pan mode and a 0 is slew mode).

Bit 5 Top Right key

Bit 6 Top Left key

Bit 7 Changed key.

The Changed key (bit 7) is used to tell if someone has pressed a keypad button
since the last speed command is received. This feature is useful so a new
tracking coordinate can be obtained, and the new tracking setpoint will track
from the new position. This bit is automatically cleared if a new speed command
is received.

Several more functions have been added to the PicServo protocol. They are
accessed using the PicServo NOP function with various lengths specified.

Length of 0 (send a 0Eh. This is the same as the PicServo NOP function)

Length of 1 (send a 1Eh for the PicServo function, then another control byte).

If Control byte = 4, the controller reads the configuration from flash ROM

If Control byte = 8, the controller writes the current configuration to flash
ROM

If Control byte = 16 the controller writes the factory defaults to the flash ROM

If Control byte = 32 the controller reverts to the ASCII mode.

Length of 2 (send a 2Eh for the PicServo function, the control byte, then
another data byte.

If Control byte = 2 the controller will update the Xbits (or Ybits if even
address) with the data byte.

Length of 5 (send a 5Eh for the PicServo function, a control byte, then four
data bytes.

If Control byte = 1 the controller will update the Altitude (Azimuth if even
address) location with the next 4 bytes.

If Control byte = 64 the controller will update the Altitude (Azimuth if even
address) guide rate with the next 4 bytes.

Length of 9 (send a 9Eh for the PicServo function, a control byte, then eight
data bytes.

If Control byte = 32 the controller will load the next two long ints (8 data
bytes) into the Slew rate and the Pan rate. For odd address it is the altitude,
for even addresses it is the azimuth.

If the controller hasn't received a PicServo command for more than the PicServo
timeout period, the controller will stop any motion, and revert to the ASCII
mode. The PicServo timout is set with the XXJ command, and the units are
Seconds. Set to zero to disable PicServo timout.


*****************************************************************************
*****************************************************************************
*****************************************************************************

New ASCII checksum commands
===========================


About the new ASCII CS (ACS) Mode:

The SiTech ASCII command set has a lot of commands that can be typed in from a
terminal program.  But this was problematic when communications were not very
good (noisy RS232 lines, etc).  Sometimes when SiTechExe sent a binary command,
the controller did not receive it as a binary command.  Then, by chance, some of
the binary data would equal an ASCII command, such as "Reset Controller", or
other commands, and the controller would do unpredictable things.

To solve this, I devised an ASCII Checksum Mode (ACS).  If in the ACS mode,
after the <cr> in the command is sent, you send another byte, which is the 8 bit
sum of all the bytes, inverted.

Entering and Leaving the ACS mode:

YXY0<cr> + 184   We go out of the ASCII Checksum mode

YXY1<cr>   We go into the ASCII Checksum mode

YXY<cr> + 232    Returns "Y0<cr><lf>" if not in ASCII Checksum mode, 
and "Y1<cr><lf>" if in ASCII cs mode.

If controller is in the ASCII CS mode, and it is receiving characters, if the
character stream stops for more than 50 mSecs, the controller resets the serial
stream, and the next character will be placed at the beginning of the receive
buffer.

If the controller is not in the ASCII CS mode, you can send characters with any
time spacing, and it will always respond.

Example of a "YXS" command, in ACS mode:

59 58 53 D EE

One more oddity.... If controller is in the ACS mode, and you want to "talk" to
the focuser/rotator, then you replace the first 'X' with 'T', and the first 'Y'
with 'U' (same as previously), but you calculate the checksum based on if it had
been the 'X' or 'Y'.

*****************************************************************************

There are two ASCII commands that require binary data to follow.  These are:

XXR<cr> and YXR<cr>

Obviously, if in the ACS mode, there would be a checksum following the <cr>

The checksums in the following commands do not include the ASCII portion, or the
ASCII checksum (if in ACS mode)

Following the ASCII portion of the XXR command, is the 21 binary data as
follows:

4 bytes Alt/Dec destination

4 bytes Alt/Dec Speed

4 bytes Az/RA destination

4 bytes Az/RA Speed

1 byte.   bit 0 means use following xbits and ybits value, if zero, ignore.

1 byte xbits

1 byte ybits

1 byte checksum (low byte)

1 byte checksum (high byte) (inverted)


Following the ASCII portion of the YXR command, is the 34 binary data as
follows:

4 bytes Alt/Dec destination

4 bytes Alt/Dec Speed (base rate)

4 bytes Az/RA destination

4 bytes Az/RA Speed (base rate)

4 bytes Alt/Dec Rate Adder

4 bytes Az/RA Rate Adder

4 bytes Alt/Dec Rate Adder Time (in Servo Loops (1953 would be 1 second) )

4 bytes Az/RA Rate Adder Time (in Servo Loops (1953 would be 1 second) )

1 byte checksum (low byte)

1 byte checksum (high byte) (inverted)

The Rate Adder is added to the base rate for the number of servo loops
specified.  For instance if the base rate is 2000 and the rate adder is -2100,
then the rate will be -100 for 66 servo loops.  This in effect will change the
direction of the motor for 66 servo loops.  In SiTechExe, I truncate the rate
adder so in never actually changes motor directions, because, if the controller
has backlash enabled, it will toggle back and forth.

Here's an example of what SiTechExe sends the controller for the YXR command
while in the ACS mode:

59 58 52 D EF F7 25 CF FF D0 7 0 0 B CF BA 58 EB 
15 0 0 0 0 0 0 16 EA FF FF 42 0 0 0 42 0 0 0 2F F5

Here's the interpretation thereof:

YXR/n,ASCIICS:239,AlDst:-3201545,AlSpd:2000,
AzDst:1488637707,AzSpd:5611,AlRateAdd:0,AzRateAdd:-5610,
AlRateTime:66,AzRateTime:66

*****************************************************************************
*****************************************************************************

Here is the Binary Response, returned from the controller, Version 3.6C:

This response is returned from all of these commands:

XXS<cr>

XXR<cr>

YXR<cr>

All Multi-bytes (Ints and Longs) are lsb first.

1 byte  0xA8 + controller address (1, 3 or 5)

4 bytes of Alt motor position

4 bytes of AZ motor position

4 bytes of Alt scope encoder position

4 bytes of Az scope encoder position

1 byte of keyboard status

1 byte for Xbits

1 byte for YBits

1 byte for various bits.

       //0 = X stopped    (altitude)

       //1 = X Manual     (Altitide)

       //2 = DigIn0 (v2.0 and later)

       //3 = DigIn1 (v2.0 and later)

       //4 = YStopped     (Azimuth)

       //5 = Y Manual     (Azimuth)

       //6 = Y PEC Recording

       //7 = Y PEC Playing

2 bytes Analog Input 1

2 bytes Analog Input 2

4 bytes millisecond clock

1 byte, temperature Deg's F  
(This will be changed to Alt/Dec Worm Phase eventually)

1 byte Az/RA Worm Phase

4 bytes.  Alt/Dec motor location at last Alt/Dec Scope Encoder location change

4 bytes.  Az/RA motor location at last Az/RA Scope Encoder location change

2 bytes for checksum

The checksum is the 16 bit sum of all bytes, starting with the A8 + controller
address (byte 1)

The high byte of the cs is inverted.

Here's a typical binary response (in hex):

A9 1D 5C 0 0 5E 67 4 0 0 0 0 0 1D 19 0 0 0 60 0 
80 0 0 0 0 5E 96 E 0 50 99 0 0 0 0 2D 67 4 0 84 FA


Here's the same response broken down:

A9 = 0xA8 + controller address

Alt/Dec Motor Position

1D 5C 0 0

23581

Az/Ra Motor Position

5E 67 4 0

288606

Alt/Dec Scope Encoder Location

0 0 0 0

0

Az/RA Scope Encoder Location

1D 19 0 0

6429

Keypad Status:

0

0

XBits (XBits and YBits functions are the same as listed in ServoDoc.pdf

60 (hex)

96 (dec)

YBits

0 (hex)

0 (bin)

0 (dec)

0 (oct)

Various Bits (it looks like the YPEC is playing)

80 (hex)

128 (dec)

Analog Input 1

0

0

Analog Input 2

0

0

Millisecond Clock

5E 96 E 0

955998

Temperature (Deg's F) (will be changed to Alt/Dec Worm Phase eventually)

50 (hex)

80 (dec)

Az/RA Worm Phase (0-255)

99

153

(59.7 percent)

Alt/Dec Motor Location at last Alt/Dec Scope Encoder Location Position Change

0 0 0 0


Az/RA Motor Location at last Az/Ra Scope Encoder Location Position Change

2D 67 4 0

288557

Checksum

84 FA

*****************************************************************************
*****************************************************************************
*****************************************************************************