{"id":18824621,"url":"https://github.com/ematech/tc2290","last_synced_at":"2025-10-20T07:54:46.228Z","repository":{"id":148465384,"uuid":"570523313","full_name":"EMATech/tc2290","owner":"EMATech","description":"tc-electronic TC 2290 hardware controller protocol","archived":false,"fork":false,"pushed_at":"2023-08-17T08:07:50.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-30T04:28:26.274Z","etag":null,"topics":["hid","hidapi","python3","tc2290-dt","tc8210-dt","usb","usb-hid"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EMATech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-25T11:51:14.000Z","updated_at":"2022-11-27T00:33:25.000Z","dependencies_parsed_at":"2024-12-30T04:36:00.718Z","dependency_job_id":null,"html_url":"https://github.com/EMATech/tc2290","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EMATech%2Ftc2290","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EMATech%2Ftc2290/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EMATech%2Ftc2290/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EMATech%2Ftc2290/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EMATech","download_url":"https://codeload.github.com/EMATech/tc2290/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239763564,"owners_count":19692793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hid","hidapi","python3","tc2290-dt","tc8210-dt","usb","usb-hid"],"created_at":"2024-11-08T00:56:57.793Z","updated_at":"2025-10-20T07:54:41.197Z","avatar_url":"https://github.com/EMATech.png","language":"Python","readme":"TC2290-DT\n=========\n\nReverse Engineering\n-------------------\n\n# 2022-11-19\n\n## External features\n\nCasing:\n- Plastic (Main body)\n- Aluminium (Front panel)\n- Steel (Stand/weight)\n\nElectronics:\n- Micro USB Type B socket\n- 3× 2 digits red 7-segment displays\n- 1× 4 digits red 7-segment displays\n- 71 LEDs of various colors\n    - 2 × 11 × 2 Metering\n    - 15 + 12 status\n- 35 very small tactile buttons\n\n## Disassembly\n\nDone.\nNothing fascinating.\nCasing is mostly plastic in which self-tapping screws are used:\n- 4 hex size 2 on the front panel\n- 3 philips 0 securing the main board\n- Didn't bother removing the Philips screw on the back that retain the USB connector and associated shielding and the\nsteel baseplate\n- The back also features 2 threaded inserts (Size?) for mounting into the TC ICON Dock is suppose.\n\nTODO: add photos\n\n## USB device\n\n- VID: `0x1220` (TC Electronic)\n- PID: `0x0071` (Unknown)\n\nTODO: add PID to USB IDs database\n\nReports:\n\n- USB 1.1\n- Self-powered\n- 100mA\n- 2 endpoints\n\n### HID compliant\n\n- VID: `4640` (TC Group)\n- PID: `113` (TC2290)\n\nPACKET SIZE: `64` bytes\n\n### Capture \u0026 analysis\n\n[USBpcap (Wireshark) Capture](capture/2022-11-19%20TC2290-DT.pcapng)\n\n- -\u003e `[0]*64` Reset ?\n- (No reply)\n- -\u003e `[0x01,0x2D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00] + 43 bytes Instance name (see below) + byte[52]=0x01`\n  Handshake?\n- \u003c- Echoes the handshake with `byte[52]=0x02 and byte[53]=0x01`\n- -\u003e `[0x01,0x2D, 0x00, 0x00, 0x02]` ?\n- \u003c- Also echoed\n- -\u003e `[0x01,0x2D, 0x00, 0x00, 0x03]`\n- \u003c- Sends previous reply (`0x02` echo)\n\n`[0x0F, 0x38, 0x00, 0x02, 0x01]` Seem to be the firmware version request\nThe reply is the version number in ASCII (`1.0.0.4-358`).\nDoesn't work on isolation though.\nMay need the handshake first.\n\nA message is emitted on button down and button release.\n\nIt generally starts with `0c 08 00 00 ff ff ff ff`\n\nByte 8 (#9) is the button ID.\n\n- 110 (0x6E): MODULATION - SPEED - UP\n- 110: MODULATION - SPEED - DOWN\n- 112: MODULATION - DEPTH - UP\n- 113: MODULATION - DEPTH - DOWN\n- 114: MODULATION - WAVE FORM\n- 115: MODULATION - SELECT\n- 116: PAN - MOD\n- 117: DYN - MOD\n- 118: PAN-DYN DIRECT\n- 119: PAN-DYN REVERSE\n- 120: DELAY - UP\n  [...]\n- 144 (0x90): KEYBOARD - ENTER\n\nFollowed by `00 00 00`.\n\n12 bytes.\n\nFollowed by 52 bytes of gibberish for now (Always changing data).\n\nNo byte seem to encode the state (Down or release) on its own.\n\nLooking at the capture, the 6 first bytes seem special in the host-\u003edevice direction and the 10 first bytes in the\ndevice-\u003ehost direction.\n43 bytes (#8 to #51) contain the first 43 characters of the instance name.\nIt is registered in the device using the \"01 2D 00 00 01 00 00 00\" command followed by the 43 bytes of instance name.\nByte 53 is 01 in the request and 02 in the reply.\n\nThere is some sort of internal buffer managing instances.\nThe plugin keeps sending update messages with the first instance name even when the second is up and also appears in\nmessages.\nThis seems to help plugin instances to know which one is active.\nThe name of the active instance displayed by the inactive instance is truncated at the same 43 character length.\nUsing Unicode characters, they are byte truncated at the same 43 boundary (Displaying only 21 characters for 2-byte\nchars.)\nI think that the device literally doesn't care and just spits out this data whenever the other instance requests it\nor is just used internally\nas a 43 bytes ID.\nWhat an odd choice of length...\n\n\n## Trainer program\n\nPython with hidapi.\n\n- Connects to the device\n- Polls data from it\n  - Spits out raw messages\n  - Interpret button presses\n\n\n# 2022-11-20\n\n012d000001000000556e6e616d65642028496e7374616e63652023312900000000000000\n\nWakes the device up\n\n1138004f0100000000000000010000003f00000066000000010000000100000001000000\n\nUpdates the Modulation display\n\n1138005d010000004f0000005b0000003f00000006000000010000000000000000000000\n\nUpdates the Delay display\n\n110c006b0100000000000000010000000100000006000000010000000000000000000000\n\nUpdates the Preset status leds\n\n\n## Display format\n\n\n### Header\n\n| 11      | 38    | 00  | 5d                     | 01        | 00  | 00  | 00  |\n|---------|-------|-----|------------------------|-----------|-----|-----|-----|\n| Command | Size? |     | Start Address (Offset) | Instance? |     |     |     |\n\n\n### Data \n\n| 4f                | 00  | 00  | 00  | 5b                | 00  | 00  | 00  | 3f                | 00  | 00  | 00  | 06                | 00  | 00  | 00  | 01        | 00  | 00  | 00  | 00      | 00  | 00  | 00  | 00       | 00  | 00  | 00  |\n|-------------------|-----|-----|-----|-------------------|-----|-----|-----|-------------------|-----|-----|-----|-------------------|-----|-----|-----|-----------|-----|-----|-----|---------|-----|-----|-----|----------|-----|-----|-----|\n| DELAY #4 segments |     |     |     | DELAY #3 segments |     |     |     | DELAY #2 segments |     |     |     | DELAY #1 segments |     |     |     | DELAY LED |     |     |     | MOD LED |     |     |     | SYNC LED |     |     |     |\n\n\n| 01                   | 00  | 00  | 00  | FF                   | 00  | 00  | 00  | 07                    | 00  | 00  | 00  | 01         | 00  | 00  | 00  | 01                  |\n|----------------------|-----|-----|-----|----------------------|-----|-----|-----|-----------------------|-----|-----|-----|------------|-----|-----|-----|---------------------|\n| FEEDBACK #1 segments |     |     |     | FEEDBACK #2 segments |     |     |     | FEEDBACK display LEDs |     |     |     | F BACK LED |     |     |     | FEEDBACK F BACK LED |\n\n### Addresses\n\nThe delimiters denote blocks that work together.\nA message not sent in sequence will reset all the elements that follow in that block. \n\n- 0x00-0x39: ???\n- ---\n- 0x40-0x49: ???\n- 0x4A: Brightness (00: Full, 0F: Dim)\n- 0x4B: INPUT L LEDs bitmap\n- 0x4C: INPUT R LEDs bitmap\n- 0x4D: OUTPUT L LEDs bitmap\n- 0x4E: OUTPUT R LEDs bitmap\n- 0x4F: MODULATION OSC / THRESHOLD LED\n- 0x50: MODULATION RED LED LEFT OF DISPLAY\n- 0x51: MODULATION 7-segment Right digit (#2)\n- 0x52: MODULATION 7-segment Left digit (#1)\n- 0x53: MODULATION RED LEDs bitmap Right of display first col\n- 0x54: MODULATION RED LEDs bitmap Right of display second col\n- 0x55: MODULATION SPEED LED\n- 0x56: MODULATION DEPTH LED\n- 0x57: PAN-DYN PAN MOD LED\n- 0x58: PAN-DYN DYN MOD LED\n- 0x59: PAN-DYN DELAY LED\n- --\n- 0x5A: PAN-DYN DIRECT LED\n- 0x5B: PAN-DYN REVERSE LED\n- 0x5C: DELAY TIME LED\n- 0x5D: DELAY 7-segment leftmost digit (#4)\n- 0x5E: DELAY 7-segment center-left digit (#3)\n- 0x5F: DELAY 7-segment center-right digit (#2)\n- 0x60: DELAY 7-segment rightmost digit (#1)\n- 0x61: DELAY DELAY LED\n- 0x62: DELAY MOD LED\n- 0x63: DELAY SYNC LED\n- 0x64: FEEDBACK 7-segment Right digit (#2)\n- 0x65: FEEDBACK 7-segment Left digit (#1)\n- 0x66: FEEDBACK RED LEDs bitmap right of display\n- 0x67: FEEDBACK F BACK LED\n- --\n- 0x68: FEEDBACK INV LED\n- 0x69: PRESET SPEC 7-segment Right digit (#2)\n- 0x6A: PRESET SPEC 7-segment Left digit (#1)\n- 0x6B: PRESET SPEC RED LEDs bitmap right of display\n- 0x6C: PRESET SPEC PRESET LED\n- 0x6D: PRESET SPEC DELAY ON LED\n- ---\n- 0x6E-0xFF: ???\n\n\n### Data\n\n32 bits \n\nSent in 4 bytes little-endian (LSB first)\n\n# 2022-11-24\n\nThe reset per block was because I always used the maximum size for the message.\nWhen sized appropriately we can update a single element without disrupting the rest.\n\n# 2022-11-25\n\n- USB VID: `0x0073` = TC 8210\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fematech%2Ftc2290","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fematech%2Ftc2290","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fematech%2Ftc2290/lists"}