Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

USBProtocol.h

Committer:
mjr
Date:
2015-12-19
Revision:
35:e959ffba78fd
Child:
38:091e511ce8a0

File content as of revision 35:e959ffba78fd:

// USB Message Protocol
//
// This file is purely for documentation, to describe our USB protocol.
// We use the standard HID setup with one endpoint in each direction.
// See USBJoystick.cpp/.h for our USB descriptor arrangement.
//

// ------ OUTGOING MESSAGES (DEVICE TO HOST) ------
//
// In most cases, our outgoing messages are HID joystick reports, using the
// format defined in USBJoystick.cpp.  This allows us to be installed on
// Windows as a standard USB joystick, which all versions of Windows support
// using in-the-box drivers.  This allows a completely transparent, driverless,
// plug-and-play installation experience on Windows.
//
// We subvert the joystick report format in certain cases to report other 
// types of information, when specifically requested by the host.  This allows
// our custom configuration UI on the Windows side to query additional 
// information that we don't normally send via the joystick reports.  We
// define a custom vendor-specific "status" field in the reports that we
// use to identify these special reports, as described below.
//
// Normal joystick reports always have 0 in the high bit of the first byte
// of the report.  Special non-joystick reports always have 1 in the high bit 
// of the first byte.  (This byte is defined in the HID Report Descriptor
// as an opaque vendor-defined value, so the joystick interface on the
// Windows side simply ignores it.)
//
// Pixel dumps:  requested by custom protocol message 65 3 (see below).  
// This sends a series of reports to the host in the following format, for 
// as many messages as are neessary to report all pixels:
//
//    bytes 0:1 = 11-bit index, with high 5 bits set to 10000.  For 
//                example, 0x04 0x80 indicates index 4.  This is the 
//                starting pixel number in the report.  The first report 
//                will be 0x00 0x80 to indicate pixel #0.  
//    bytes 2:3 = 16-bit unsigned int brightness level of pixel at index
//    bytes 4:5 = brightness of pixel at index+1
//    etc for the rest of the packet
//
// Configuration query:  requested by custom protocol message 65 4 (see 
// below).  This sends one report to the host using this format:
//
//    bytes 0:1 = 0x8800.  This has the bit pattern 10001 in the high
//                5 bits, which distinguishes it from regular joystick
//                reports and from exposure status reports.
//    bytes 2:3 = total number of outputs, little endian
//    bytes 4:5 = plunger calibration zero point, little endian
//    bytes 6:7 = plunger calibration maximum point, little endian
//    remaining bytes = reserved for future use; set to 0 in current version
//
//
// WHY WE USE THIS HACKY APPROACH TO DIFFERENT REPORT TYPES
//
// The HID report system was specifically designed to provide a clean,
// structured way for devices to describe the data they send to the host.
// Our approach isn't clean or structured; it ignores the promises we
// make about the contents of our report via the HID Report Descriptor
// and stuffs our own different data format into the same structure.
//
// We use this hacky approach only because we can't use the official 
// mechanism, due to the constraint that we want to emulate the LedWiz.
// The right way to send different report types is to declare different
// report types via extra HID Report Descriptors, then send each report
// using one of the types we declared.  If it weren't for the LedWiz
// constraint, we'd simply define the pixel dump and config query reports
// as their own separate HID Report types, each consisting of opaque
// blocks of bytes.  But we can't do this.  The snag is that some versions
// of the LedWiz Windows host software parse the USB HID descriptors as part
// of identifying a device as a valid LedWiz unit, and will only recognize
// the device if it matches certain particulars about the descriptor
// structure of a real LedWiz.  One of the features that's important to
// some versions of the software is the descriptor link structure, which
// is affected by the layout of HID Report Descriptor entries.  In order
// to match the expected layout, we can only define a single kind of output
// report.  Since we have to use Joystick reports for the sake of VP and
// other pinball software, and we're only allowed the one report type, we
// have to make that one report type the Joystick type.  That's why we
// overload the joystick reports with other meanings.  It's a hack, but
// at least it's a fairly reliable and isolated hack, iun that our special 
// reports are only generated when clients specifically ask for them.
// Plus, even if a client who doesn't ask for a special report somehow 
// gets one, the worst that happens is that they get a momentary spurious
// reading from the accelerometer and plunger.



// ------- INCOMING MESSAGES (HOST TO DEVICE) -------
//
// For LedWiz compatibility, our incoming message format conforms to the
// basic USB format used by real LedWiz units.  This is simply 8 data
// bytes, all private vendor-specific values (meaning that the Windows HID
// driver treats them as opaque and doesn't attempt to parse them).
//
// Within this basic 8-byte format, we recognize the full protocol used
// by real LedWiz units, plus an extended protocol that we define privately.
// The LedWiz protocol leaves a large part of the potential protocol space 
// undefined, so we take advantage of this undefined region for our 
// extensions.  This ensures that we can properly recognize all messages 
// intended for a real LedWiz unit, as well as messages from custom host 
// software that knows it's talking to a Pinscape unit.

// --- REAL LED WIZ MESSAGES ---
//
// The real LedWiz protocol has two message types, identified by the first
// byte of the 8-byte USB packet:
//
// 64              -> SBA (64 xx xx xx xx ss uu uu)
//                    xx = on/off bit mask for 8 outputs
//                    ss = global flash speed setting (1-7)
//                    uu = unused
//
// If the first byte has value 64 (0x40), it's an SBA message.  This type of 
// message sets all 32 outputs individually ON or OFF according to the next 
// 32 bits (4 bytes) of the message, and sets the flash speed to the value in 
// the sixth byte.  (The flash speed sets the global cycle rate for flashing
// outputs - outputs with their values set to the range 128-132 - to a   
// relative speed, scaled linearly in frequency.  1 is the slowest at about 
// 2 Hz, 7 is the fastest at about 14 Hz.)
//
// 0-49 or 128-132 -> PBA (bb bb bb bb bb bb bb bb)
//                    bb = brightness level/flash pattern for one output
//
// If the first byte is any valid brightness setting, it's a PBA message.
// Valid brightness settings are:
//
//     0-48 = fixed brightness level, linearly from 0% to 100% intensity
//     49   = fixed brightness level at 100% intensity (same as 48)
//     129  = flashing pattern, fade up / fade down (sawtooth wave)
//     130  = flashing pattern, on / off (square wave)
//     131  = flashing pattern, on for 50% duty cycle / fade down
//     132  = flashing pattern, fade up / on for 50% duty cycle
//     
// A PBA message sets 8 outputs out of 32.  Which 8 are to be set is 
// implicit in the message sequence: the first PBA sets outputs 1-8, the 
// second sets 9-16, and so on, rolling around after each fourth PBA.  
// An SBA also resets the implicit "bank" for the next PBA to outputs 1-8.
//
// Note that there's no special first byte to indicate the PBA message
// type, as there is in an SBA.  The first byte of a PBA is simply the
// first output setting.  The way the LedWiz creators conceived this, the 
// SBA distinguishable from a PBA because 64 isn't a valid output setting, 
// hence a message that starts with a byte value of 64 isn't a valid PBA 
// message.
//
// Our extended protocol uses the same principle, taking advantage of the
// other byte value ranges that are invalid in PBA messages.  To be a valid
// PBA message, the first byte must be in the range 0-49 or 129-132.  As
// already mentioned, byte value 64 indicates an SBA message.  This leaves
// these ranges available for other uses: 50-63, 65-128, and 133-255.


// --- PRIVATE EXTENDED MESSAGES ---
//
// All of our extended protocol messages are identified by the first byte:
//
// 65  -> Miscellaneous control message.  The second byte specifies the specific
//        operation:
//
//        1 -> Set device unit number and plunger status, and save the changes immediately
//             to flash.  The device will automatically reboot after the changes are saved.
//             The additional bytes of the message give the parameters:
//
//               third byte = new unit number (0-15, corresponding to nominal unit numbers 1-16)
//               fourth byte = plunger on/off (0=disabled, 1=enabled)
//
//        2 -> Begin plunger calibration mode.  The device stays in this mode for about
//             15 seconds, and sets the zero point and maximum retraction points to the
//             observed endpoints of sensor readings while the mode is running.  After
//             the time limit elapses, the device automatically stores the results in
//             non-volatile flash memory and exits the mode.
//
//        3 -> Send pixel dump.  The plunger sensor object sends a series of the special 
//             pixel dump reports, defined in USBJoystick.cpp; the device automatically
//             resumes normal joystick messages after sending all pixels.  If the 
//             plunger sensor isn't an image sensor type, no pixel messages are sent.
//
//        4 -> Query configuration.  The device sends a special configuration report,
//             defined in USBJoystick.cpp, then resumes sending normal joystick reports.
//
//        5 -> Turn all outputs off and restore LedWiz defaults.  Sets output ports
//             1-32 to OFF and LedWiz brightness/mode setting 48, sets outputs 33 and
//             higher to brightness level 0, and sets the LedWiz global flash speed to 2.
//
//        6 -> Save configuration to flash.  This saves all variable updates sent via
//             type 66 messages since the last reboot, then automatically reboots the
//             device to put the changes into effect.
//
// 66  -> Set configuration variable.  The second byte of the message is the config
//        variable number, and the remaining bytes give the new value for the variable.
//        The value format is specific to each variable; see the list below for details.
//        This message only sets the value in RAM - it doesn't write the value to flash
//        and doesn't put the change into effect immediately.  To put updates into effect,
//        the host must send a type 65 subtype 6 message (see above), which saves updates
//        to flash and reboots the device.
//
// 200-228 -> Set extended output brightness.  This sets outputs N to N+6 to the
//        respective brightness values in the 2nd through 8th bytes of the message
//        (output N is set to the 2nd byte value, N+1 is set to the 3rd byte value, 
//        etc).  Each brightness level is a linear brightness level from 0-255,
//        where 0 is 0% brightness and 255 is 100% brightness.  N is calculated as
//        (first byte - 200)*7 + 1:
//
//               200 = outputs 1-7
//               201 = outputs 8-14
//               202 = outputs 15-21
//               ...
//               228 = outputs 197-203
//
//        This message is the only way to address ports 33 and higher, since standard
//        LedWiz messages are inherently limited to ports 1-32.
//
//        Note that these extended output messages differ from regular LedWiz settings
//        in two ways.  First, the brightness is the ONLY attribute when an output is
//        set using this mode - there's no separate ON/OFF setting per output as there 
//        is with the SBA/PBA messages.  To turn an output OFF with this message, set
//        the intensity to 0.  Setting a non-zero intensity turns it on immediately
//        without regard to the SBA status for the port.  Second, the brightness is
//        on a full 8-bit scale (0-255) rather than the LedWiz's approximately 5-bit
//        scale, because there are no parts of the range reserved for flashing modes.
//
//        Outputs 1-32 can be controlled by EITHER the regular LedWiz SBA/PBA messages
//        or by the extended messages.  The latest setting for a given port takes
//        precedence.  If an SBA/PBA message was the last thing sent to a port, the
//        normal LedWiz combination of ON/OFF and brightness/flash mode status is used
//        to determine the port's physical output setting.  If an extended brightness
//        message was the last thing sent to a port, the LedWiz ON/OFF status and
//        flash modes are ignored, and the fixed brightness is set.  Outputs 33 and
//        higher inherently can't be addressed or affected by SBA/PBA messages.


// ------- CONFIGURATION VARIABLES -------
//
// Message type 66 (see above) sets one configuration variable.  The second byte
// of the message is the variable ID, and the rest of the bytes give the new
// value, in a variable-specific format.  16-bit values are little endian.
//
// 1  -> USB device ID.  Bytes 3-4 give the 16-bit USB Vendor ID; bytes
//       5-6 give the 16-bit USB Product ID.  For LedWiz emulation, use
//       vendor 0xFAFA and product 0x00EF + unit# (where unit# is the
//       nominal LedWiz unit number, from 1 to 16).  If LedWiz emulation
//       isn't desired or causes host conflicts, you can use our private
//       ID assigned by http://pid.codes (a registry for open-source USB
//       devices) of vendor 0x1209 and product 0xEAEA.  (You can also use
//       any other values that don't cause a conflict on your PC, but we
//       recommend using one of these pre-assigned values if possible.)
//
// 2  -> Pinscape Controller unit number for DOF.  Byte 3 is the new
//       unit number, from 1 to 16.
//
// 3  -> Enable/disable joystick reports.  Byte 2 is 1 to enable, 0 to
//       disable.  When disabled, the device registers as a generic HID 
/        device, and only sends the private report types used by the
//       Windows config tool.
//
// 4  -> Accelerometer orientation.  Byte 3 is the new setting:
//        
//        0 = ports at front (USB ports pointing towards front of cabinet)
//        1 = ports at left
//        2 = ports at right
//        3 = ports at rear
//
// 5  -> Plunger sensor type.  Byte 3 is the type ID:
//
//         0 = none (disabled)
//         1 = TSL1410R linear image sensor, 1280x1 pixels, serial mode
//         2 = TSL1410R, parallel mode
//         3 = TSL1412R linear image sensor, 1536x1 pixels, serial mode
//         4 = TSL1412R, parallel mode
//         5 = Potentiometer with linear taper, or any other device that
//             represents the position reading with a single analog voltage
//         6 = AEDR8300 optical quadrature sensor, 75lpi
//         7 = AS5304 magnetic quadrature sensor, 160 steps per 2mm
//
// 6  -> Plunger pin assignments.  Bytes 3-6 give the pin assignments for
//       pins 1, 2, 3, and 4.  These use the Pin Number Mappings listed
//       below.  The meaning of each pin depends on the plunger type:
//
//         TSL1410R/1412R, serial:    SI (DigitalOut), CLK (DigitalOut), AO (AnalogIn),  NC
//         TSL1410R/1412R, parallel:  SI (DigitalOut), CLK (DigitalOut), AO1 (AnalogIn), AO2 (AnalogIn)
//         Potentiometer:             AO (AnalogIn),   NC,               NC,             NC
//         AEDR8300:                  A (InterruptIn), B (InterruptIn),  NC,             NC
//         AS5304:                    A (InterruptIn), B (InterruptIn),  NC,             NC
//
// 7  -> Plunger calibration button pin assignments.  Byte 3 is the DigitalIn
//       pin for the button switch; byte 4 is the DigitalOut pin for the indicator
//       lamp.  Either can be set to NC to disable the function.  (Use the Pin
//       Number Mappins listed below for both bytes.)
//
// 8  -> ZB Launch Ball setup.  This configures the ZB Launch Ball feature.  Byte
//       3 is the LedWiz port number (1-255) mapped to the "ZB Launch Ball" output
//       in DOF.  Set the port to 0 to disable the feature.  Byte 4 is the button
//       number (1-32) that we'll "press" when the feature is activated.  Bytes 5-6
//       give the "push distance" for activating the button by pushing forward on
//       the plunger knob, in .001 inch increments (e.g., 80 represents 0.08", which
//       is the recommended setting).
//
// 9  -> TV ON relay setup.  This requires external circuitry implemented on the
//       Expansion Board (or an equivalent circuit as described in the Build Guide).
//       Byte 3 is the GPIO DigitalIn pin for the "power status" input, using the 
//       Pin Number Mappings below.  Byte 4 is the DigitalOut pin for the "latch"
//       output.  Byte 5 is the DigitalOut pin for the relay trigger.  Bytes 6-7
//       give the delay time in 10ms increments as an unsigned 16-bit value (e.g.,
//       550 represents 5.5 seconds).  
//
// 10 -> TLC5940NT setup.  This chip is an external PWM controller, with 32 outputs
//       per chip and a serial data interface that allows the chips to be daisy-
//       chained.  We can use these chips to add an arbitrary number of PWM output 
//       ports for the LedWiz emulation.  Set the number of chips to 0 to disable
//       the feature.  The bytes of the message are:
//          byte 3 = number of chips attached (connected in daisy chain)
//          byte 4 = SIN pin - Serial data (must connect to SPIO MOSI -> PTC6 or PTD2)
//          byte 5 = SCLK pin - Serial clock (must connect to SPIO SCLK -> PTC5 or PTD1)
//          byte 6 = XLAT pin - XLAT (latch) signal (any GPIO pin)
//          byte 7 = BLANK pin - BLANK signal (any GPIO pin)
//          byte 8 = GSCLK pin - Grayscale clock signal (must be a PWM-out capable pin)
//
// 11 -> 74HC595 setup.  This chip is an external shift register, with 8 outputs per
//       chip and a serial data interface that allows daisy-chaining.  We use this
//       chips to add extra digital outputs for the LedWiz emulation.  In particular,
//       the Chime Board (part of the Expansion Board suite) uses these to add timer-
//       protected outputs for coil devices (knockers, chimes, bells, etc).  Set the
//       number of chips to 0 to disable the feature.  The message bytes are:
//          byte 3 = number of chips attached (connected in daisy chain)
//          byte 4 = SIN pin - Serial data (any GPIO pin)
//          byte 5 = SCLK pin - Serial clock (any GPIO pin)
//          byte 6 = LATCH pin - LATCH signal (any GPIO pin)
//          byte 7 = ENA pin - ENABLE signal (any GPIO pin)
//
// 12 -> Input button setup.  This sets up one button; it can be repeated for each
//       button to be configured.  There are 32 button slots, numbered 1-32.  Each
//       key can be configured as a joystick button, a regular keyboard key, a
//       keyboard modifier key (such as Shift, Ctrl, or Alt), or a media control
//       key (such as volume up/down).
//
//       The bytes of the message are:
//          byte 3 = Button number (1-32)
//          byte 4 = GPIO pin to read for button input
//          byte 5 = key type reported to PC when button is pushed:
//                    1 = joystick button -> byte 6 is the button number, 1-32
//                    2 = regular keyboard key -> byte 6 is the USB key code (see below)
//                    3 = keyboard modifier key -> byte 6 is the USB modifier code (see below)
//                    4 = media control key -> byte 6 is the USB key code (see below)
//          byte 6 = key code, which depends on the key type in byte 5
//          
// 13 -> LedWiz output port setup.  This sets up one output port; it can be repeated
//       for each port to be configured.  There are 203 possible slots for output ports, 
//       numbered 1 to 203.  The number of ports visible to the host is determined by
//       the first DISABLED port (type 0).  For example, if ports 1-32 are set as GPIO
//       outputs and port 33 is disabled, the host will see 32 ports, regardless of
//       the settings for post 34 and higher.
//
//       The bytes of the message are:
//         byte 3 = LedWiz port number (1 to maximum number or ports)
//         byte 4 = physical output type:
//                   0 = Disabled.  This output isn't used, and isn't visible to the
//                       LedWiz/DOF software on the host.  The FIRST disabled port
//                       determines the number of ports visible to the host - ALL ports
//                       after the first disabled port are also implicitly disabled.
//                   1 = GPIO PWM output: connected to GPIO pin specified in byte 5,
//                       operating in PWM mode.  Note that only a subset of KL25Z GPIO
//                       ports are PWM-capable.
//                   2 = GPIO Digital output: connected to GPIO pin specified in byte 5,
//                       operating in digital mode.  Digital ports can only be set ON
//                       or OFF, with no brightness/intensity control.  All pins can be
//                       used in this mode.
//                   3 = TLC5940 port: connected to TLC5940 output port number specified 
//                       in byte 5.  Ports are numbered sequentially starting from port 0
//                       for the first output (OUT0) on the first chip in the daisy chain.
//                   4 = 74HC595 port: connected to 74HC595 output port specified in byte 5.
//                       As with the TLC5940 outputs, ports are numbered sequentially from 0
//                       for the first output on the first chip in the daisy chain.
//                   5 = Virtual output: this output port exists for the purposes of the
//                       LedWiz/DOF software on the host, but isn't physically connected
//                       to any output device.  This can be used to create a virtual output
//                       for the DOF ZB Launch Ball signal, for example, or simply as a
//                       placeholder in the LedWiz port numbering.  The physical output ID 
//                       (byte 5) is ignored for this port type.
//         byte 5 = physical output ID, interpreted according to the value in byte 4
//         byte 6 = flags: a combination of these bit values:
//                   1 = active-high output (0V on output turns attached device ON)


// --- PIN NUMBER MAPPINGS ---
//
// In USB messages that specify GPIO pin assignments, pins are identified with
// our own private numbering scheme.  Our numbering scheme only includes the 
// ports connected to external header pins on the KL25Z board, so this is only
// a sparse subset of the full GPIO port set.  These are numbered in order of
// pin name.  The special value 0 = NC = Not Connected can be used where
// appropriate to indicate a disabled or unused pin.
//
//     0 = NC (not connected)
//     1 = PTA1
//     2 = PTA2
//     3 = PTA4
//     4 = PTA5
//     5 = PTA12
//     6 = PTA13
//     7 = PTA16
//     8 = PTA17
//     9 = PTB0
//    10 = PTB1
//    11 = PTB2
//    12 = PTB3
//    13 = PTB8
//    14 = PTB9
//    15 = PTB10
//    16 = PTB11
//    17 = PTC0
//    18 = PTC1
//    19 = PTC2
//    20 = PTC3
//    21 = PTC4
//    22 = PTC5
//    23 = PTC6
//    24 = PTC7
//    25 = PTC8
//    26 = PTC9
//    27 = PTC10
//    28 = PTC11
//    29 = PTC12
//    30 = PTC13
//    31 = PTC16
//    32 = PTC17
//    33 = PTD0
//    34 = PTD1
//    35 = PTD2
//    36 = PTD3
//    37 = PTD4
//    38 = PTD5
//    39 = PTD6
//    40 = PTD7
//    41 = PTE0
//    42 = PTE1
//    43 = PTE2
//    44 = PTE3
//    45 = PTE4
//    46 = PTE5
//    47 = PTE20
//    48 = PTE21
//    49 = PTE22
//    50 = PTE23
//    51 = PTE29
//    52 = PTE30
//    53 = PTE31


// --- USB KEYBOARD SCAN CODES ---
//
// Use the standard USB HID keyboard codes for regular keys.  See the
// HID Usage Tables in the official USB specifications for a full list.
// Here are the most common codes for quick references:
//
//    A-Z              -> 4-29
//    top row numbers  -> 30-39
//    Return           -> 40
//    Escape           -> 41
//    Backspace        -> 42
//    Tab              -> 43
//    Spacebar         -> 44
//    -_               -> 45
//    =+               -> 46
//    [{               -> 47
//    ]}               -> 48
//    \|               -> 49
//    ;:               -> 51
//    '"               -> 52
//    `~               -> 53
//    ,<               -> 54
//    .>               -> 55
//    /?               -> 56
//    Caps Lock        -> 57
//    F1-F12           -> 58-69
//    F13-F24          -> 104-115
//    Print Screen     -> 70
//    Scroll Lock      -> 71
//    Pause            -> 72
//    Insert           -> 73
//    Home             -> 74
//    Page Up          -> 75
//    Del              -> 76
//    End              -> 77
//    Page Down        -> 78
//    Right Arrow      -> 79
//    Left Arrow       -> 80
//    Down Arrow       -> 81
//    Up Arrow         -> 82
//    Num Lock/Clear   -> 83
//    Keypad / * - +   -> 84 85 86 87
//    Keypad Enter     -> 88
//    Keypad 1-9       -> 89-97
//    Keypad 0         -> 98
//    Keypad .         -> 99
//  


// --- USB KEYBOARD MODIFIER KEY CODES ---
//
// Use these codes for modifier keys in the button mappings
//
//    0x01 = Left Control
//    0x02 = Left Shift
//    0x04 = Left Alt
//    0x08 = Left GUI ("Windows" key)
//    0x10 = Right Control
//    0x20 = Right Shift
//    0x40 = Right Alt
//    0x80 = Right GUI ("Windows" key)


// --- USB KEYBOARD MEDIA KEY CODES ---
//
// Use these for media control keys in the button mappings
//
//    0x01 = Volume Up
//    0x02 = Volume Down
//    0x04 = Mute on/off