diff options
| -rw-r--r-- | keyboard/planck/Makefile | 2 | ||||
| -rw-r--r-- | keyboard/planck/config.h | 2 | ||||
| -rw-r--r-- | keyboard/planck/extended_keymap_common.h | 1 | ||||
| -rw-r--r-- | keyboard/planck/extended_keymaps/extended_keymap_default.c | 13 | ||||
| -rw-r--r-- | keyboard/planck/matrix_pcb.c | 1 | ||||
| -rw-r--r-- | protocol/lufa.mk | 7 | ||||
| -rw-r--r-- | protocol/lufa/descriptor.c | 158 | ||||
| -rw-r--r-- | protocol/lufa/descriptor.h | 23 | ||||
| -rw-r--r-- | protocol/lufa/lufa.c | 191 | ||||
| -rw-r--r-- | protocol/lufa/lufa.h | 3 | 
10 files changed, 392 insertions, 9 deletions
| diff --git a/keyboard/planck/Makefile b/keyboard/planck/Makefile index cd67c711bc..7ea71af512 100644 --- a/keyboard/planck/Makefile +++ b/keyboard/planck/Makefile @@ -75,7 +75,7 @@ SRC = extended_keymap_common.c \  	$(MATRIX) \  	led.c \  	backlight.c \ -	beeps.c  +	beeps.c  ifdef KEYMAP      SRC := extended_keymaps/extended_keymap_$(KEYMAP).c $(SRC) diff --git a/keyboard/planck/config.h b/keyboard/planck/config.h index 7e95afddea..4ac9f766e6 100644 --- a/keyboard/planck/config.h +++ b/keyboard/planck/config.h @@ -24,7 +24,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define PRODUCT_ID      0x6060  #define DEVICE_VER      0x0001  #define MANUFACTURER    Ortholinear Keyboards -#define PRODUCT         Planck +#define PRODUCT         The Planck Keyboard  #define DESCRIPTION     A compact ortholinear keyboard  /* key matrix size */ diff --git a/keyboard/planck/extended_keymap_common.h b/keyboard/planck/extended_keymap_common.h index 2dce4a2fac..e6a7dac5b5 100644 --- a/keyboard/planck/extended_keymap_common.h +++ b/keyboard/planck/extended_keymap_common.h @@ -48,6 +48,7 @@ typedef union {  keymap_config_t keymap_config;  #endif +  /* translates key to keycode */  uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key); diff --git a/keyboard/planck/extended_keymaps/extended_keymap_default.c b/keyboard/planck/extended_keymaps/extended_keymap_default.c index 1d5ac4321b..710611c3cb 100644 --- a/keyboard/planck/extended_keymaps/extended_keymap_default.c +++ b/keyboard/planck/extended_keymaps/extended_keymap_default.c @@ -1,5 +1,6 @@  #include "extended_keymap_common.h"  #include "backlight.h" +#include "lufa.h"  const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {  [0] = { /* Qwerty */ @@ -50,10 +51,18 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)        switch(id) {          case 0:             if (record->event.pressed) { -          register_code(KC_RSFT); +          if (!&midi_device) { +            register_code(KC_RSFT); +          } else { +            midi_send_noteon(&midi_device, 1, 64, 127); +          }            backlight_step();          } else { -          unregister_code(KC_RSFT); +          if (!&midi_device) { +            unregister_code(KC_RSFT); +          } else { +            midi_send_noteoff(&midi_device, 1, 64, 127); +          }          }          break;        }  diff --git a/keyboard/planck/matrix_pcb.c b/keyboard/planck/matrix_pcb.c index 6f6ccd5c1c..2a9ec8fcde 100644 --- a/keyboard/planck/matrix_pcb.c +++ b/keyboard/planck/matrix_pcb.c @@ -78,6 +78,7 @@ void matrix_init(void)      }  } +  uint8_t matrix_scan(void)  {      for (uint8_t i = 0; i < MATRIX_ROWS; i++) { diff --git a/protocol/lufa.mk b/protocol/lufa.mk index ac70ac0391..74a8bef3c6 100644 --- a/protocol/lufa.mk +++ b/protocol/lufa.mk @@ -19,7 +19,12 @@ endif  LUFA_SRC = $(LUFA_DIR)/lufa.c \  	   $(LUFA_DIR)/descriptor.c \ -	   $(LUFA_SRC_USB) +	   $(LUFA_SRC_USB) \ +	   $(LUFA_DIR)/midi/midi.c \ +	   $(LUFA_DIR)/midi/midi_device.c \ +	   $(LUFA_DIR)/midi/bytequeue/bytequeue.c \ +	   $(LUFA_DIR)/midi/bytequeue/interrupt_setting.c \ +	   $(LUFA_DIR)/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c  SRC += $(LUFA_SRC) diff --git a/protocol/lufa/descriptor.c b/protocol/lufa/descriptor.c index c13a81bda8..6eedd57000 100644 --- a/protocol/lufa/descriptor.c +++ b/protocol/lufa/descriptor.c @@ -486,6 +486,164 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =              .PollingIntervalMS      = 0x01          },  #endif + +    .Audio_ControlInterface = +        { +            .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber          = (NKRO_INTERFACE + 1), +            .AlternateSetting         = 0, + +            .TotalEndpoints           = 0, + +            .Class                    = AUDIO_CSCP_AudioClass, +            .SubClass                 = AUDIO_CSCP_ControlSubclass, +            .Protocol                 = AUDIO_CSCP_ControlProtocol, + +            .InterfaceStrIndex        = NO_DESCRIPTOR +        }, + +    .Audio_ControlInterface_SPC = +        { +            .Header                   = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_Header, + +            .ACSpecification          = VERSION_BCD(1,1,1), +            .TotalLength              = sizeof(USB_Audio_Descriptor_Interface_AC_t), + +            .InCollection             = 1, +            .InterfaceNumber          = (NKRO_INTERFACE + 2), +        }, + +    .Audio_StreamInterface = +        { +            .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + +            .InterfaceNumber          = (NKRO_INTERFACE + 2), +            .AlternateSetting         = 0, + +            .TotalEndpoints           = 2, + +            .Class                    = AUDIO_CSCP_AudioClass, +            .SubClass                 = AUDIO_CSCP_MIDIStreamingSubclass, +            .Protocol                 = AUDIO_CSCP_StreamingProtocol, + +            .InterfaceStrIndex        = NO_DESCRIPTOR +        }, + +    .Audio_StreamInterface_SPC = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_General, + +            .AudioSpecification       = VERSION_BCD(1,1,1), + +            .TotalLength              = (sizeof(USB_Descriptor_Configuration_t) - +                                         offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)) +        }, + +    .MIDI_In_Jack_Emb = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal, + +            .JackType                 = MIDI_JACKTYPE_Embedded, +            .JackID                   = 0x01, + +            .JackStrIndex             = NO_DESCRIPTOR +        }, + +    .MIDI_In_Jack_Ext = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal, + +            .JackType                 = MIDI_JACKTYPE_External, +            .JackID                   = 0x02, + +            .JackStrIndex             = NO_DESCRIPTOR +        }, + +    .MIDI_Out_Jack_Emb = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, + +            .JackType                 = MIDI_JACKTYPE_Embedded, +            .JackID                   = 0x03, + +            .NumberOfPins             = 1, +            .SourceJackID             = {0x02}, +            .SourcePinID              = {0x01}, + +            .JackStrIndex             = NO_DESCRIPTOR +        }, + +    .MIDI_Out_Jack_Ext = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface}, +            .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, + +            .JackType                 = MIDI_JACKTYPE_External, +            .JackID                   = 0x04, + +            .NumberOfPins             = 1, +            .SourceJackID             = {0x01}, +            .SourcePinID              = {0x01}, + +            .JackStrIndex             = NO_DESCRIPTOR +        }, + +    .MIDI_In_Jack_Endpoint = +        { +            .Endpoint = +                { +                    .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, + +                    .EndpointAddress     = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM), +                    .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +                    .EndpointSize        = MIDI_STREAM_EPSIZE, +                    .PollingIntervalMS   = 0x01 +                }, + +            .Refresh                  = 0, +            .SyncEndpointNumber       = 0 +        }, + +    .MIDI_In_Jack_Endpoint_SPC = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint}, +            .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General, + +            .TotalEmbeddedJacks       = 0x01, +            .AssociatedJackID         = {0x01} +        }, + +    .MIDI_Out_Jack_Endpoint = +        { +            .Endpoint = +                { +                    .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, + +                    .EndpointAddress     = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM), +                    .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), +                    .EndpointSize        = MIDI_STREAM_EPSIZE, +                    .PollingIntervalMS   = 0x01 +                }, + +            .Refresh                  = 0, +            .SyncEndpointNumber       = 0 +        }, + +    .MIDI_Out_Jack_Endpoint_SPC = +        { +            .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint}, +            .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General, + +            .TotalEmbeddedJacks       = 0x01, +            .AssociatedJackID         = {0x03} +        } +  }; diff --git a/protocol/lufa/descriptor.h b/protocol/lufa/descriptor.h index 42af07917c..58a7df4407 100644 --- a/protocol/lufa/descriptor.h +++ b/protocol/lufa/descriptor.h @@ -85,6 +85,23 @@ typedef struct      USB_HID_Descriptor_HID_t              NKRO_HID;      USB_Descriptor_Endpoint_t             NKRO_INEndpoint;  #endif + +      // MIDI Audio Control Interface +      USB_Descriptor_Interface_t                Audio_ControlInterface; +      USB_Audio_Descriptor_Interface_AC_t       Audio_ControlInterface_SPC; + +      // MIDI Audio Streaming Interface +      USB_Descriptor_Interface_t                Audio_StreamInterface; +      USB_MIDI_Descriptor_AudioInterface_AS_t   Audio_StreamInterface_SPC; +      USB_MIDI_Descriptor_InputJack_t           MIDI_In_Jack_Emb; +      USB_MIDI_Descriptor_InputJack_t           MIDI_In_Jack_Ext; +      USB_MIDI_Descriptor_OutputJack_t          MIDI_Out_Jack_Emb; +      USB_MIDI_Descriptor_OutputJack_t          MIDI_Out_Jack_Ext; +      USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_In_Jack_Endpoint; +      USB_MIDI_Descriptor_Jack_Endpoint_t       MIDI_In_Jack_Endpoint_SPC; +      USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_Out_Jack_Endpoint; +      USB_MIDI_Descriptor_Jack_Endpoint_t       MIDI_Out_Jack_Endpoint_SPC; +  } USB_Descriptor_Configuration_t; @@ -117,7 +134,7 @@ typedef struct  /* nubmer of interfaces */ -#define TOTAL_INTERFACES            (NKRO_INTERFACE + 1) +#define TOTAL_INTERFACES            (NKRO_INTERFACE + 3)  // Endopoint number and size @@ -150,12 +167,16 @@ typedef struct  #   endif  #endif +#define MIDI_STREAM_IN_EPNUM        (NKRO_IN_EPNUM + 1) +#define MIDI_STREAM_OUT_EPNUM        (NKRO_IN_EPNUM + 1) +  #define KEYBOARD_EPSIZE             8  #define MOUSE_EPSIZE                8  #define EXTRAKEY_EPSIZE             8  #define CONSOLE_EPSIZE              32  #define NKRO_EPSIZE                 16 +#define MIDI_STREAM_EPSIZE          64  uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index cdfc7bc6ad..d4c8eb1692 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -52,6 +52,7 @@  #include "descriptor.h"  #include "lufa.h" +  uint8_t keyboard_idle = 0;  uint8_t keyboard_protocol = 1;  static uint8_t keyboard_led_stats = 0; @@ -65,14 +66,51 @@ static void send_keyboard(report_keyboard_t *report);  static void send_mouse(report_mouse_t *report);  static void send_system(uint16_t data);  static void send_consumer(uint16_t data); +void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); +void usb_get_midi(MidiDevice * device); +void midi_usb_init(MidiDevice * device);  host_driver_t lufa_driver = {      keyboard_leds,      send_keyboard,      send_mouse,      send_system, -    send_consumer +    send_consumer, +    usb_send_func, +    usb_get_midi, +    midi_usb_init +}; + +void SetupHardware(void); + +USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = +{ +  .Config = +  { +    .StreamingInterfaceNumber = 1, +    .DataINEndpoint           = +    { +      .Address          = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM), +      .Size             = MIDI_STREAM_EPSIZE, +      .Banks            = 1, +    }, +    .DataOUTEndpoint          = +    { +      .Address          = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM), +      .Size             = MIDI_STREAM_EPSIZE, +      .Banks            = 1, +    }, +  },  }; +#define SYSEX_START_OR_CONT 0x40 +#define SYSEX_ENDS_IN_1 0x50 +#define SYSEX_ENDS_IN_2 0x60 +#define SYSEX_ENDS_IN_3 0x70 + +#define SYS_COMMON_1 0x50 +#define SYS_COMMON_2 0x20 +#define SYS_COMMON_3 0x30 +  /*******************************************************************************   * Console @@ -240,8 +278,13 @@ void EVENT_USB_Device_ConfigurationChanged(void)      ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,                                       NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);  #endif + + +    ConfigSuccess &= MIDI_Device_ConfigureEndpoints(&USB_MIDI_Interface);  } + +  /*  Appendix G: HID Request Support Requirements @@ -263,6 +306,8 @@ void EVENT_USB_Device_ControlRequest(void)      uint8_t* ReportData = NULL;      uint8_t  ReportSize = 0; +    MIDI_Device_ProcessControlRequest(&USB_MIDI_Interface); +      /* Handle HID Class specific requests */      switch (USB_ControlRequest.bRequest)      { @@ -541,10 +586,109 @@ int8_t sendchar(uint8_t c)  #endif + + + +void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) { +  MIDI_EventPacket_t event; +  event.Data1 = byte0; +  event.Data2 = byte1; +  event.Data3 = byte2; + +  //if the length is undefined we assume it is a SYSEX message +  if (midi_packet_length(byte0) == UNDEFINED) { +    switch(cnt) { +      case 3: +        if (byte2 == SYSEX_END) +          event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_3); +        else +          event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); +        break; +      case 2: +        if (byte1 == SYSEX_END) +          event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_2); +        else +          event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); +        break; +      case 1: +        if (byte0 == SYSEX_END) +          event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_1); +        else +          event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); +        break; +      default: +        return; //invalid cnt +    } +  } else { +    //deal with 'system common' messages +    //TODO are there any more? +    switch(byte0 & 0xF0){ +      case MIDI_SONGPOSITION: +        event.Event = MIDI_EVENT(0, SYS_COMMON_3); +        break; +      case MIDI_SONGSELECT: +      case MIDI_TC_QUARTERFRAME: +        event.Event = MIDI_EVENT(0, SYS_COMMON_2); +        break; +      default: +        event.Event = MIDI_EVENT(0, byte0); +        break; +    } +  } + +  MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event); +  MIDI_Device_Flush(&USB_MIDI_Interface); +  MIDI_Device_USBTask(&USB_MIDI_Interface); +  USB_USBTask(); +} + +void usb_get_midi(MidiDevice * device) { +  MIDI_EventPacket_t event; +  while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) { + +    midi_packet_length_t length = midi_packet_length(event.Data1); +    uint8_t input[3]; +    input[0] = event.Data1; +    input[1] = event.Data2; +    input[2] = event.Data3; +    if (length == UNDEFINED) { +      //sysex +      if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) { +        length = 3; +      } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) { +        length = 2; +      } else if(event.Event ==  MIDI_EVENT(0, SYSEX_ENDS_IN_1)) { +        length = 1; +      } else { +        //XXX what to do? +      } +    } + +    //pass the data to the device input function +    if (length != UNDEFINED) +      midi_device_input(device, length, input); +  } +  MIDI_Device_USBTask(&USB_MIDI_Interface); +  USB_USBTask(); +} + +void midi_usb_init(MidiDevice * device){ +  midi_device_init(device); +  midi_device_set_send_func(device, usb_send_func); +  midi_device_set_pre_input_process_func(device, usb_get_midi); + +  SetupHardware(); +  sei(); +} + + + + +  /*******************************************************************************   * main   ******************************************************************************/ -static void SetupHardware(void) +void SetupHardware(void)  {      /* Disable watchdog if enabled by bootloader/fuses */      MCUSR &= ~(1 << WDRF); @@ -563,12 +707,34 @@ static void SetupHardware(void)      print_set_sendchar(sendchar);  } +void fallthrough_callback(MidiDevice * device, +    uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); +void cc_callback(MidiDevice * device, +    uint8_t chan, uint8_t num, uint8_t val); +void sysex_callback(MidiDevice * device, +    uint16_t start, uint8_t length, uint8_t * data); +  int main(void)  __attribute__ ((weak));  int main(void)  { +    //setup the device + +    midi_device_init(&midi_device); +    midi_device_set_send_func(&midi_device, usb_send_func); +    midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); +      SetupHardware();      sei(); +    midi_register_fallthrough_callback(&midi_device, fallthrough_callback); +    midi_register_cc_callback(&midi_device, cc_callback); +    midi_register_sysex_callback(&midi_device, sysex_callback); + +    midi_send_cc(&midi_device, 0, 1, 2); +    midi_send_cc(&midi_device, 15, 1, 0); +    midi_send_noteon(&midi_device, 0, 64, 127); +    midi_send_noteoff(&midi_device, 0, 64, 127); +      /* wait for USB startup & debug output */      while (USB_DeviceState != DEVICE_STATE_Configured) {  #if defined(INTERRUPT_CONTROL_ENDPOINT) @@ -598,8 +764,29 @@ int main(void)          keyboard_task(); +        midi_device_process(&midi_device); +  #if !defined(INTERRUPT_CONTROL_ENDPOINT)          USB_USBTask();  #endif      }  } + +//echo data back +void fallthrough_callback(MidiDevice * device, +    uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){ +  //pass the data back to the device, using the general purpose send data +  //function, any bytes after cnt are ignored +} + +void cc_callback(MidiDevice * device, +    uint8_t chan, uint8_t num, uint8_t val) { +  //sending it back on the next channel +  midi_send_cc(device, (chan + 1) % 16, num, val); +} + +void sysex_callback(MidiDevice * device, +    uint16_t start, uint8_t length, uint8_t * data) { +  for (int i = 0; i < length; i++) +    midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i)); +} diff --git a/protocol/lufa/lufa.h b/protocol/lufa/lufa.h index 195123c0f9..505cb3279e 100644 --- a/protocol/lufa/lufa.h +++ b/protocol/lufa/lufa.h @@ -48,7 +48,7 @@  #include <LUFA/Version.h>  #include <LUFA/Drivers/USB/USB.h>  #include "host.h" - +#include "midi/midi.h"  #ifdef __cplusplus  extern "C" { @@ -66,6 +66,7 @@ typedef struct {      uint16_t usage;  } __attribute__ ((packed)) report_extra_t; +MidiDevice midi_device;  #if LUFA_VERSION_INTEGER < 0x120730      /* old API 120219 */ | 
