~ruther/qmk_firmware

e528087ee539fda2f13795d4a6c03403faef44d5 — Jack Humbert 10 years ago 2d76b5c
midi
M keyboard/planck/Makefile => keyboard/planck/Makefile +1 -1
@@ 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)

M keyboard/planck/config.h => keyboard/planck/config.h +1 -1
@@ 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 */

M keyboard/planck/extended_keymap_common.h => keyboard/planck/extended_keymap_common.h +1 -0
@@ 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);


M keyboard/planck/extended_keymaps/extended_keymap_default.c => keyboard/planck/extended_keymaps/extended_keymap_default.c +11 -2
@@ 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;
      } 

M keyboard/planck/matrix_pcb.c => keyboard/planck/matrix_pcb.c +1 -0
@@ 78,6 78,7 @@ void matrix_init(void)
    }
}


uint8_t matrix_scan(void)
{
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {

M protocol/lufa.mk => protocol/lufa.mk +6 -1
@@ 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)


M protocol/lufa/descriptor.c => protocol/lufa/descriptor.c +158 -0
@@ 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}
        }

};



M protocol/lufa/descriptor.h => protocol/lufa/descriptor.h +22 -1
@@ 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,

M protocol/lufa/lufa.c => protocol/lufa/lufa.c +189 -2
@@ 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));
}

M protocol/lufa/lufa.h => protocol/lufa/lufa.h +2 -1
@@ 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 */