Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: USBProtocol.h
- Revision:
- 77:0b96f6867312
- Parent:
- 75:677892300e7a
- Child:
- 78:1e00b3fa11af
--- a/USBProtocol.h Fri Feb 03 20:50:02 2017 +0000 +++ b/USBProtocol.h Fri Mar 17 22:02:08 2017 +0000 @@ -59,6 +59,8 @@ // 3 -> latch off, SET pin low, ready to check status // 4 -> TV timer countdown in progress // 5 -> TV relay is on +// 6 -> sending IR signals designated as TV ON signals +// 0x20 -> IR learning mode in progress // 00 2nd byte of status (reserved) // 00 3rd byte of status (reserved) // 00 always zero for joystick reports @@ -241,7 +243,8 @@ // In response, the device sends one report using this format: // // bytes 0:1 = 0xA000. This has bit pattern 10100 in the high 5 bits -// to distinguish it from other report types. +// (and 10100000 in the high 8 bits) to distinguish it from +// other report types. // bytes 2:5 = Build date. This is returned as a 32-bit integer, // little-endian as usual, encoding a decimal value // in the format YYYYMMDD giving the date of the build. @@ -254,8 +257,9 @@ // This is requested by sending custom protocol message 65 13 (see below). // In response, the device sends one report using this format: // -// bytes 0:1 = 0xA1. This has bit pattern 10101 in the high 5 bits -// to distinguish it from other report types. +// bytes 0:1 = 0xA1. This has bit pattern 10100 in the high 5 bits (and +// 10100001 in the high 8 bits) to distinguish it from other +// report types. // byte 2 = number of button reports // byte 3 = Physical status of buttons 1-8, 1 bit each. The low-order // bit (0x01) is button 1. Each bit is 0 if the button is off, @@ -270,8 +274,62 @@ // byte 7 = buttons 33-40 // byte 8 = buttons 41-48 // +// 2G. IR sensor data report. +// This is requested by sending custom protocol message 65 12 (see below). +// That command puts controller in IR learning mode for a short time, during +// which it monitors the IR sensor and send these special reports to relay the +// readings. The reports contain the raw data, plus the decoded command code +// and protocol information if the controller is able to recognize and decode +// the command. // -// WHY WE USE THIS HACKY APPROACH TO DIFFERENT REPORT TYPES +// bytes 0:1 = 0xA2. This has bit pattern 10100 in the high 5 bits (and +// 10100010 in the high 8 bits to distinguish it from other +// report types. +// byte 2 = number of raw reports that follow +// bytes 3:4 = first raw report, as a little-endian 16-bit int. The +// value represents the time of an IR "space" or "mark" in +// 2us units. The low bit is 0 for a space and 1 for a mark. +// To recover the time in microseconds, mask our the low bit +// and multiply the result by 2. Received codes always +// alternate between spaces and marks. A space is an interval +// where the IR is off, and a mark is an interval with IR on. +// If the value is 0xFFFE (after masking out the low bit), it +// represents a timeout, that is, a time greater than or equal +// to the maximum that can be represented in this format, +// which is 131068us. None of the IR codes we can parse have +// any internal signal component this long, so a timeout value +// is generally seen only during a gap between codes where +// nothing is being transmitted. +// bytes 4:5 = second raw report +// (etc for remaining reports) +// +// If byte 2 is 0x00, it indicates that learning mode has expired without +// a code being received, so it's the last report sent for the learning +// session. +// +// If byte 2 is 0xFF, it indicates that a code has been successfully +// learned. The rest of the report contains the learned code instead +// of the raw data: +// +// byte 3 = protocol ID, which is an integer giving an internal code +// identifying the IR protocol that was recognized for the +// received data. See IRProtocolID.h for a list of the IDs. +// byte 4 = bit flags: +// 0x02 -> the protocol uses "dittos" +// bytes 5:6:7:8:9:10:11:12 = a little-endian 64-bit int containing +// the code received. The code is essentially the data payload +// of the IR packet, after removing bits that are purely +// structural, such as toggle bits and error correction bits. +// The mapping between the IR bit stream and our 64-bit is +// essentially arbitrary and varies by protocol, but it always +// has round-trip fidelity: using the 64-bit code value + +// protocol ID + flags to send an IR command will result in +// the same IR bit sequence being sent, modulo structural bits +// that need to be updates in the reconstruction (such as toggle +// bits or sequencing codes). +// +// +// WHY WE USE A 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. @@ -279,30 +337,26 @@ // 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. +// We use this hacky approach only because we can't use the standard USB +// HID mechanism for varying report types, which is to provide multiple +// report descriptors and tag each report with a type byte that indicates +// which descriptor applies. We can't use that standard approach because +// we want to be 100% LedWiz compatible. The snag is that some Windows +// LedWiz clients parse the USB HID descriptors as part of identifying a +// USB HID device as a valid LedWiz unit, and will only recognize the device +// if certain properties of the HID descriptors match those of a real LedWiz. +// One of the features that's important to some clients 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, in 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. @@ -473,8 +527,24 @@ // 1 = turn relay on // 2 = pulse the relay as though the power-on delay timer fired // -// 12 -> Unused -// +// 12 -> Learn IR code. The device enters "IR learning mode". While in +// learning mode, the device reports the raw signals read through +// the IR sensor to the PC through the special IR learning report +// (see "2G" above). If a signal can be decoded through a known +// protocol, the device sends a final "2G" report with the decoded +// command, then terminates learning mode. If no signal can be +// decoded within a timeout period, the mode automatically ends, +// and the device sends a final IR learning report with zero raw +// signals to indicate termination. After initiating IR learning +// mode, the user should point the remote control with the key to +// be learned at the IR sensor on the KL25Z, and press and hold the +// key on the remote for a few seconds. Holding the key for a few +// moments is important because it lets the decoder sense the type +// of auto-repeat coding the remote uses. The learned code can be +// written to an IR config variable slot to program the controller +// to send the learned command on events like TV ON or a button +// press. +// // 13 -> Get button status report. The device sends one button status report // in response (see section "2F" above). // @@ -600,6 +670,8 @@ // Any bytes at the end of the message not otherwise specified are reserved // for future use and should always be set to 0 in the message data. // +// Variable IDs: +// // 0 -> QUERY ONLY: Describe the configuration variables. The device // sends a config variable query report with the following fields: // @@ -659,13 +731,18 @@ // (including virtual buttons, such as the ZB Launch Ball feature) are assigned // to generate keyboard key input. // -// 4 -> Accelerometer orientation. +// 4 -> Accelerometer settings // // byte 3 -> orientation: // 0 = ports at front (USB ports pointing towards front of cabinet) // 1 = ports at left // 2 = ports at right // 3 = ports at rear +// byte 4 -> dynamic range +// 0 = +/- 1G (2G hardware mode, but rescales joystick reports to 1G range) +// 1 = +/- 2G (2G hardware mode) +// 2 = +/- 4G (4G hardware mode) +// 3 = +/- 8G (8G hardware mode) // // 5 -> Plunger sensor type. // @@ -738,6 +815,11 @@ // Set the delay time to 0 to disable the feature. The pin assignments will // be ignored if the feature is disabled. // +// If an IR remote control transmitter is installed (see variable 17), we'll +// also transmit any IR codes designated as TV ON codes when the startup timer +// finishes. This allows TVs to be turned on via IR remotes codes rather than +// hard-wiring them through the relay. The relay can be omitted in this case. +// // 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 @@ -874,6 +956,19 @@ // // byte 3 = button number - 1..MAX_BUTTONS, or 0 for none. // +// 17 -> IR Remote Control physical device setup. We support IR remotes for +// both sending and receiving. On the receive side, we can read from a +// sensor such as a TSOP384xx. The sensor requires one GPIO pin with +// interrupt support, so any PTAxx or PTDxx pin will work. On the send +// side, we can transmit through any IR LED. This requires one PWM +// output pin. To enable send and/or receive, specify a valid pin; to +// disable, set the pin NC (not connected). Send and receive can be +// enabled and disabled independently; it's not necessary to enable +// the transmit function to use the receive function, or vice versa. +// +// byte 3 = receiver input GPIO pin ID. Must be interrupt-capable. +// byte 4 = transmitter pin. Must be PWM-capable. +// // // SPECIAL DIAGNOSTICS VARIABLES: These work like the array variables below, // the only difference being that we don't report these in the number of array @@ -924,15 +1019,75 @@ // variable with index 0, with the first (and only) byte after that indicating // the maximum array index. // +// 250 -> IR remote control commands - code part 2. This stores the high-order +// 32 bits of the remote control for each slot. These are combined with +// the low-order 32 bits from variable 251 below to form a 64-bit code. +// +// byte 3 = Command slot number (1..MAX_IR_CODES) +// byte 4 = bits 32..39 of remote control command code +// byte 5 = bits 40..47 +// byte 6 = bits 48..55 +// byte 7 = bits 56..63 +// +// 251 -> IR remote control commands - code part 1. This stores the protocol +// identifier and low-order 32 bits of the remote control code for each +// remote control command slot. The code represents a key press on a +// remote, and is usually determined by reading it from the device's +// actual remote via the IR sensor input feature. These codes combine +// with variable 250 above to form a 64-bit code for each slot. +// See IRRemote/IRProtocolID.h for the protocol ID codes. +// +// byte 3 = Command slot number (1..MAX_IR_CODES) +// byte 4 = protocol ID +// byte 5 = bits 0..7 of remote control command code +// byte 6 = bits 8..15 +// byte 7 = bits 16..23 +// byte 8 = bits 24..31 +// +// 252 -> IR remote control commands - control information. This stores +// descriptive information for each remote control command slot. +// The IR code for each slot is stored in the corresponding array +// entry in variables 251 & 250 above; the information is split over +// several variables like this because of the 8-byte command message +// size in our USB protocol (which we use for LedWiz compatibility). +// +// byte 3 = Command slot number (1..MAX_IR_CODES) +// byte 4 = bit flags: +// 0x01 -> send this code as a TV ON signal at system start +// 0x02 -> use "ditto" codes when sending the command +// byte 5 = key type; same as the key type in an input button variable +// byte 6 = key code; same as the key code in an input button variable +// +// Each IR command slot can serve three purposes: +// +// - First, it can be used as part of the TV ON sequence when the +// system powers up, to turn on cabinet TVs that don't power up by +// themselves. To use this feature, set the TV ON bit in the flags. +// +// - Second, when the IR sensor receives a command in a given slot, we +// can translate it into a keyboard key or joystick button press sent +// to the PC. This lets you use any IR remote to send commands to the +// PC, allowing access to additional control inputs without any extra +// buttons on the cabinet. To use this feature, assign the key to +// send in the key type and key code bytes. +// +// - Third, we can send a given IR command when a physical cabinet +// button is pressed. This lets you use cabinet buttons to send IR +// commands to other devices in your system. For example, you could +// assign cabinet buttons to control the volume on a cab TV. To use +// this feature, assign an IR slot as a button function in the button +// setup. +// // 253 -> Extended input button setup. This adds on to the information set by // variable 254 below, accessing additional fields. The "shifted" key // type and code fields assign a secondary meaning to the button that's // used when the local Shift button is being held down. See variable 16 // above for more details on the Shift button. // -// byte 3 = Button number 91..MAX_BUTTONS +// byte 3 = Button number (1..MAX_BUTTONS) // byte 4 = shifted key type (same codes as "key type" in var 254) -// byte 5 = shifted key code (same meaning as "key code" in var 254) +// byte 5 = shifted key code (same codes as "key code" in var 254) +// byte 6 = shifted IR command (see "IR command" in var 254) // // 254 -> Input button setup. This sets up one button; it can be repeated for each // button to be configured. There are MAX_EXT_BUTTONS button slots (see @@ -955,6 +1110,9 @@ // state. This is useful for the VPinMAME Coin Door button, // which requires the End key to be pressed each time the // door changes state. +// byte 8 = IR command to transmit when unshifted button is pressed. This +// contains an IR slot number (1..MAX_IR_CODES), or 0 if no code +// is associated with the button. // // 255 -> LedWiz output port setup. This sets up one output port; it can be repeated // for each port to be configured. There are 128 possible slots for output ports,