Created
July 2, 2026 07:57
-
-
Save moyashipan/0e9c004d3167f9983e63f0e3a4c103c8 to your computer and use it in GitHub Desktop.
M5Stack_ChainDualKey_Muter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <M5Unified.h> | |
| #include <Adafruit_NeoPixel.h> | |
| #include "USB.h" | |
| #include "USBHID.h" | |
| #define LED_PWR_PIN 40 // LED用電源ピン | |
| #define LED_SIG_PIN 21 // LED信号用ピン | |
| #define NUM_LEDS 2 // 搭載されているLEDの数 | |
| #define BUTTON_LEFT_PIN 17 // 左ボタンのピン (Mute ON用) | |
| #define BUTTON_RIGHT_PIN 0 // 右ボタンのピン (Mute OFF用) | |
| // HIDレポートの設定 | |
| constexpr uint8_t REPORT_ID = 5; | |
| Adafruit_NeoPixel strip(NUM_LEDS, LED_SIG_PIN, NEO_GRB + NEO_KHZ800); | |
| m5::Button_Class ButtonLeft; | |
| m5::Button_Class ButtonRight; | |
| USBHID HID; | |
| const uint8_t report_descriptor[] = { | |
| 0x05, 0x0B, // Usage Page (Telephony Device) | |
| 0x09, 0x01, // Usage (Phone) | |
| 0xA1, 0x01, // Collection (Application) | |
| 0x85, REPORT_ID, // Report ID | |
| 0x05, 0x0B, // Usage Page (Telephony Device) | |
| 0x09, 0x2F, // Usage (Phone Mute) | |
| 0x09, 0x20, // Usage (Hook Switch) | |
| 0x15, 0x00, // Logical Minimum (0) | |
| 0x25, 0x01, // Logical Maximum (1) | |
| 0x75, 0x01, // Report Size (1) | |
| 0x95, 0x02, // Report Count (2) | |
| 0x81, 0x02, // Input (Data, Variable, Absolute) | |
| 0x75, 0x06, // Padding (6bit) | |
| 0x95, 0x01, // Report Count (1) | |
| 0x81, 0x03, // Input (Constant, Variable, Absolute) | |
| 0x05, 0x08, // Usage Page (LEDs) | |
| 0x09, 0x09, // Usage (Mute) | |
| 0x09, 0x17, // Usage (Off-Hook) | |
| 0x15, 0x00, // Logical Minimum (0) | |
| 0x25, 0x01, // Logical Maximum (1) | |
| 0x75, 0x01, // Report Size (1) | |
| 0x95, 0x02, // Report Count (2) | |
| 0x91, 0x02, // Output (Data, Variable, Absolute) | |
| 0x75, 0x06, // Padding (6bit) | |
| 0x95, 0x01, // Report Count (1) | |
| 0x91, 0x03, // Output (Constant, Variable, Absolute) | |
| 0xC0 // End Collection | |
| }; | |
| class CustomTelephonyDevice : public USBHIDDevice { | |
| public: | |
| CustomTelephonyDevice() { | |
| HID.addDevice(this, sizeof(report_descriptor)); | |
| } | |
| uint16_t _onGetDescriptor(uint8_t* buffer) override { | |
| memcpy(buffer, report_descriptor, sizeof(report_descriptor)); | |
| return sizeof(report_descriptor); | |
| } | |
| void _onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t len) override { | |
| if (report_id == REPORT_ID && len > 0) { | |
| const bool pcIsMuted = (buffer[0] & 0x01) != 0; | |
| const bool pcIsOffHook = (buffer[0] & 0x02) != 0; | |
| if (!pcIsOffHook) { | |
| // 通話終了時: 両方のLEDを消灯 | |
| strip.setPixelColor(0, strip.Color(0, 0, 0)); | |
| strip.setPixelColor(1, strip.Color(0, 0, 0)); | |
| } else if (pcIsMuted) { | |
| // 通話中かつミュートON時: 左側のLEDを赤で点灯 | |
| strip.setPixelColor(0, strip.Color(255, 0, 0)); | |
| strip.setPixelColor(1, strip.Color(0, 0, 0)); | |
| } else { | |
| // 通話中かつミュートOFF時: 右側のLEDを緑で点灯 | |
| strip.setPixelColor(0, strip.Color(0, 0, 0)); | |
| strip.setPixelColor(1, strip.Color(0, 255, 0)); | |
| } | |
| strip.show(); | |
| } | |
| } | |
| void sendMuteOn() { | |
| uint8_t p[1] = { 0x03 }; // 11: 通話中, ミュートON | |
| HID.SendReport(REPORT_ID, p, 1); | |
| } | |
| void sendMuteOff() { | |
| uint8_t p[1] = { 0x02 }; // 10: 通話中, ミュートOFF | |
| HID.SendReport(REPORT_ID, p, 1); | |
| } | |
| void sendCallEnd() { | |
| uint8_t p[1] = { 0x01 }; // 01: 通話終了, ミュートON | |
| HID.SendReport(REPORT_ID, p, 1); | |
| } | |
| }; | |
| CustomTelephonyDevice TelephonyDevice; | |
| void setup() { | |
| pinMode(LED_PWR_PIN, OUTPUT); | |
| digitalWrite(LED_PWR_PIN, HIGH); | |
| USB.VID(0x1209); | |
| USB.PID(0x0040); | |
| USB.manufacturerName("Moyashipan"); | |
| USB.productName("M5Chain DualKey Muter"); | |
| auto cfg = M5.config(); | |
| M5.begin(cfg); | |
| ButtonLeft.setHoldThresh(1000); // 長押し判定時間 | |
| pinMode(BUTTON_LEFT_PIN, INPUT); | |
| pinMode(BUTTON_RIGHT_PIN, INPUT); | |
| strip.begin(); | |
| strip.show(); | |
| HID.begin(); | |
| USB.begin(); | |
| } | |
| void loop() { | |
| const uint32_t ms = millis(); | |
| ButtonLeft.setRawState(ms, !digitalRead(BUTTON_LEFT_PIN)); | |
| ButtonRight.setRawState(ms, !digitalRead(BUTTON_RIGHT_PIN)); | |
| if (ButtonLeft.wasHold()) { | |
| TelephonyDevice.sendCallEnd(); | |
| } else if (ButtonLeft.wasPressed()) { | |
| TelephonyDevice.sendMuteOn(); | |
| } | |
| if (ButtonRight.wasPressed()) { | |
| TelephonyDevice.sendMuteOff(); | |
| } | |
| delay(10); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment