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