int main(void) { SetupHardware(); // LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable(); // uint8_t BUT_current = PIND & (1 << PD1);; // текущее значение кнопки // uint8_t BUT_previous = BUT_current; // предыдущее значение кнопки //uint8_t BUT_message=0; // 0 - ничего не отправлять, 1 - отправить vel 0, 2 - отправить vel 127 //uint8_t LED_current = 0; // текущее значение светодиода int ADC_current[16]; // текущие значения АЦП int ADC_previous[16]; // предыдущие значения АЦП uint8_t ADC_deviation = 20; // порог фиксации изменения АЦП, давить шум for (uint8_t i=0; i<16; i++) { ADC_current[i] = raw_ADC(); ADC_previous[i] = ADC_current[i];} // инициализация for (;;) { // дроп входящих MIDI_EventPacket_t ReceivedMIDIEvent; while (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &ReceivedMIDIEvent)); // опрос 16 входов мультиплексора for (int MUX_pos = 0; MUX_pos < 3; MUX_pos++ ){ MUX_address(MUX_pos); // установить адрес // _delay_ms(1); // MUX_enable(); // _delay_ms(1); ADC_current[MUX_pos] = raw_ADC(); // АЦП // MUX_disable(); if ( abs(ADC_current[MUX_pos] - ADC_previous[MUX_pos]) >= ADC_deviation ) // если изменения больше порога, отправить сообщение CC { cc_send(MUX_pos, ADC_current[MUX_pos] / 8); ADC_previous[MUX_pos] = ADC_current[MUX_pos]; } _delay_ms(10); MIDI_Device_USBTask(&Keyboard_MIDI_Interface); USB_USBTask(); } // MIDI_Device_USBTask(&Keyboard_MIDI_Interface); // USB_USBTask(); } }
void MIDI_IN(void) { MIDI_EventPacket_t ReceivedMIDIEvent; if (MIDI_Device_ReceiveEventPacket(&MIDI_Interface, &ReceivedMIDIEvent)) { LEDs_TurnOnLEDs(LEDMASK_RX); Serial_TxByte(ReceivedMIDIEvent.Data1); Serial_TxByte(ReceivedMIDIEvent.Data2); Serial_TxByte(ReceivedMIDIEvent.Data3); } else { LEDs_TurnOffLEDs(LEDMASK_RX); } }
void usb_get_midi(MidiDevice * device) { /* Select the MIDI OUT stream */ Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPNUM); MIDI_EventPacket_t event; while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) { midi_packet_length_t length = midi_packet_length(event.Data1); //pass the data to the device input function //not dealing with sysex yet if (length != UNDEFINED) midi_device_input(device, length, event.Data1, event.Data2, event.Data3); } MIDI_Device_USBTask(&USB_MIDI_Interface); USB_USBTask(); }
/** Main program entry point. This routine contains the overall program flow, including initial * setup of all components and the main program loop. */ int main(void) { SetupHardware(); sei(); unsigned char c = 0; for (;;) { //Check if we've received any MIDI messages from the USB line if (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &MIDIpacket_out)) { handle_MIDI_out(); } if (Serial_getChar(&c)) { handle_MIDI_in(c); } MIDI_Device_USBTask(&Keyboard_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); //pass the data to the device input function //not dealing with sysex yet if (length != UNDEFINED) { uint8_t input[3]; input[0] = event.Data1; input[1] = event.Data2; input[2] = event.Data3; midi_device_input(device, length, input); } } MIDI_Device_USBTask(&USB_MIDI_Interface); USB_USBTask(); }
/** Main program entry point. This routine contains the overall program flow, including initial * setup of all components and the main program loop. */ int main(void) { SetupHardware(); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable(); for (;;) { CheckJoystickMovement(); MIDI_EventPacket_t ReceivedMIDIEvent; while (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &ReceivedMIDIEvent)) { if ((ReceivedMIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_ON)) && (ReceivedMIDIEvent.Data3 > 0)) LEDs_SetAllLEDs(ReceivedMIDIEvent.Data2 > 64 ? LEDS_LED1 : LEDS_LED2); else LEDs_SetAllLEDs(LEDS_NO_LEDS); } MIDI_Device_USBTask(&Keyboard_MIDI_Interface); USB_USBTask(); } }
/** Main program entry point. This routine contains the overall program flow, including initial * setup of all components and the main program loop. */ int main(void) { SetupHardware(); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable(); for (;;) { MIDI_EventPacket_t ReceivedMIDIEvent; if (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &ReceivedMIDIEvent)) { if ((ReceivedMIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_ON)) && ((ReceivedMIDIEvent.Data1 & 0x0F) == 0)) { DDSNoteData* LRUNoteStruct = &NoteData[0]; /* Find a free entry in the note table to use for the note being turned on */ for (uint8_t i = 0; i < MAX_SIMULTANEOUS_NOTES; i++) { /* Check if the note is unused */ if (!(NoteData[i].Pitch)) { /* If a note is unused, it's age is essentially infinite - always prefer unused not entries */ LRUNoteStruct = &NoteData[i]; break; } else if (NoteData[i].LRUAge >= LRUNoteStruct->LRUAge) { /* If an older entry that the current entry has been found, prefer overwriting that one */ LRUNoteStruct = &NoteData[i]; } NoteData[i].LRUAge++; } /* Update the oldest note entry with the new note data and reset its age */ LRUNoteStruct->Pitch = ReceivedMIDIEvent.Data2; LRUNoteStruct->TableIncrement = (uint32_t)(BASE_INCREMENT * SCALE_FACTOR) + ((uint32_t)(BASE_INCREMENT * NOTE_OCTIVE_RATIO * SCALE_FACTOR) * (ReceivedMIDIEvent.Data2 - BASE_PITCH_INDEX)); LRUNoteStruct->TablePosition = 0; LRUNoteStruct->LRUAge = 0; /* Turn on indicator LED to indicate note generation activity */ LEDs_SetAllLEDs(LEDS_LED1); } else if ((ReceivedMIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_OFF)) && ((ReceivedMIDIEvent.Data1 & 0x0F) == 0)) { bool FoundActiveNote = false; /* Find the note in the note table to turn off */ for (uint8_t i = 0; i < MAX_SIMULTANEOUS_NOTES; i++) { if (NoteData[i].Pitch == ReceivedMIDIEvent.Data2) NoteData[i].Pitch = 0; else if (NoteData[i].Pitch) FoundActiveNote = true; } /* If all notes off, turn off the indicator LED */ if (!(FoundActiveNote)) LEDs_SetAllLEDs(LEDS_NO_LEDS); } } MIDI_Device_USBTask(&Keyboard_MIDI_Interface); USB_USBTask(); } }
// The MIDI processing task. // // Read the buttons and expansion ports to generate MIDI notes. This routine // is the heart of the MidiFighter. // void Midifighter_Task(void) { // If the Midifighter is not completely enumerated by the USB Host, // don't go any further - no updating of LEDs, no reading from // endpoints, we wait for the USB to connect. if (USB_DeviceState != DEVICE_STATE_Configured) { main_watchdog_flag = true; return; } // Overview // -------- // The state of all the active notes is kept in an array of bytes // recording the most recent velocity of the note. A nonzero velocity is // a NoteOn and a zero velocity is a NoteOff. We update the keystate // from the outside world first, from the keyboard second, from the // expansion port third and generate LEDs from the resulting table at // the end. // // Midi Map // -------- // In normal mode only 16 notes are being tracked, as well as the // digital expansion ports, plus two notes for each analog port for the // smart filters: // // 2 2 3 3 <- analog 2,3 = 104 .. 107 // 0 0 1 1 <- analog 0,1 = 100 .. 103 // // . . . . <- bank 0 = 48 .. 52 // . . . . <- bank 0 = 44 .. 47 // . . . . <- bank 0 = 40 .. 43 // . . . . <- bank 0 = 36 .. 39 // // D D D D <- digital = 4 .. 7 // // // In 4banks Internal mode, the top 4 buttons are used as bank // selection keys so we are tracking four banks of 12 notes plus the // digital and analog notes. // // . . . . <- 124 .. 127 // . . . . <- 120 .. 123 // . . . . <- 116 .. 119 // . . . . <- 108 .. 115 // 2 2 3 3 <- analog 2,3 = 104 .. 107 // 0 0 1 1 <- analog 0,1 = 100 .. 103 // . . . . <- bank 3 = 96 .. 99 // . . . . <- bank 3 = 92 .. 95 // . . . . <- bank 3 = 88 .. 91 // . . . . <- bank 3 = 84 .. 87 // @ @ @ @ <- bank 3 = 80 .. 83 // @ @ @ @ <- bank 3 = 76 .. 79 // @ @ @ @ <- bank 3 = 72 .. 75 // # # # # <- bank 2 = 68 .. 71 // # # # # <- bank 2 = 64 .. 67 // # # # # <- bank 2 = 60 .. 63 // @ @ @ @ <- bank 1 = 56 .. 59 // @ @ @ @ <- bank 1 = 52 .. 55 // @ @ @ @ <- bank 1 = 48 .. 51 // # # # # <- bank 0 = 44 .. 47 // # # # # <- bank 0 = 40 .. 43 // # # # # <- bank 0 = 36 .. 39 // . . . . <- 32 .. 35 // . . . . <- 28 .. 31 // . . . . <- 24 .. 27 // . . . . <- 20 .. 23 // . . . . <- 16 .. 19 // . . . . <- 12 .. 15 // . . . . <- 08 .. 11 // D D D D <- digital = 4 .. 7 // B B B B <- bank select keys 0..3 // // // In 4banks External mode, the four digital pins are used as bank // select keys giving us four banks of 16 keys: // // . . . . <- 124 .. 127 // . . . . <- 120 .. 123 // . . . . <- 116 .. 119 // . . . . <- 108 .. 115 // 2 2 3 3 <- analog 2,3 = 104 .. 107 // 0 0 1 1 <- analog 0,1 = 100 .. 103 // @ @ @ @ <- bank 3 = 96 .. 99 // @ @ @ @ <- bank 3 = 92 .. 95 // @ @ @ @ <- bank 3 = 88 .. 91 // @ @ @ @ <- bank 3 = 84 .. 87 // # # # # <- bank 2 = 80 .. 83 // # # # # <- bank 2 = 76 .. 79 // # # # # <- bank 2 = 72 .. 75 // # # # # <- bank 2 = 68 .. 71 // @ @ @ @ <- bank 1 = 64 .. 67 // @ @ @ @ <- bank 1 = 60 .. 63 // @ @ @ @ <- bank 1 = 56 .. 59 // @ @ @ @ <- bank 1 = 52 .. 55 // # # # # <- bank 0 = 48 .. 51 // # # # # <- bank 0 = 44 .. 47 // # # # # <- bank 0 = 40 .. 43 // # # # # <- bank 0 = 36 .. 39 // . . . . <- 32 .. 35 // . . . . <- 28 .. 31 // . . . . <- 24 .. 27 // . . . . <- 20 .. 23 // . . . . <- 16 .. 19 // . . . . <- 12 .. 15 // . . . . <- 08 .. 11 // D D D D <- digital = 04 .. 07 // B B B B <- bank select keys 00 .. 03 // // // The Bank Select key events are sent whenever a bank select key is // pressed, regardless whether the key is on the digital port or on the // keypad. SysEx_t sysEx; uint8_t index = 0; // INPUT MIDI from USB ----------------------------------------------------- // If there is data in the Endpoint for us to read, get a USB-MIDI // packet to process. Endpoint_IsReadWriteAllowed() returns true if // there is data remaining inside an OUT endpoint or if an IN endpoint // has space left to fill. The same function doing two jobs, confusing // but there you are. MIDI_EventPacket_t input_event; while (MIDI_Device_ReceiveEventPacket(g_midi_interface_info, &input_event)) { // Assuming all virtual MIDI cables are intended for us, ensure that // this event is being sent on our current MIDI channel. // // The lower 4-bits (".Command") of the USB_MIDI event packet tells // us what kind of data it contains, and whether to expect more data // in the same message. Commands are: // 0x0 = Reserved for Misc // 0x1 = Reserved for Cable events // 0x2 = 2-byte System Common // 0x3 = 3-byte System Common // 0x4 = 3-byte Sysex starts or continues // 0x5 = 1-byte System Common or Sysex ends // 0x6 = 2-byte Sysex ends // 0x7 = 3-byte Sysex ends // 0x8 = Note On // 0x9 = Note Off // 0xA = Poly KeyPress // 0xB = Control Change (CC) // 0xC = Program Change // 0xD = Channel Pressure // 0xE = PitchBend Change // 0xF = 1-byte message // System Real Time events don't have a channel, so we check for // them first. if (input_event.Command == 0xF) { if (input_event.Data1 == 0xF8) { // Clock event, increment the counter. g_led_groundfx_counter++; } else if (input_event.Data1 == 0xFA) { // Song Start, reset the counter. g_led_groundfx_counter = 0; } else if (input_event.Data1 == 0xFC) { // Song Stop event, reset the counter. g_led_groundfx_counter = 0; } } else if (input_event.Command == 0x4) { // Start or continue 3 bytes SYSEX_READ(1); SYSEX_READ(2); SYSEX_READ(3); } else if (input_event.Command == 0x5) { // End 1 byte SYSEX_READ(1); SYSEX_END(); } else if (input_event.Command == 0x6) { // End 2 bytes SYSEX_READ(1); SYSEX_READ(2); SYSEX_END(); } else if (input_event.Command == 0x7) { // End 3 bytes SYSEX_READ(1); SYSEX_READ(2); SYSEX_READ(3); SYSEX_END(); } else { // Now we can check that the MIDI channel is the one we're payin // attention to before parsing the event. uint8_t channel = input_event.Data1 & 0x0f; if (channel == g_midi_channel) { // Work out the valid range of MIDI notes we will accept. uint8_t highest_note = MIDI_BASE_NOTE + 16; if (g_key_fourbanks_mode == FOURBANKS_INTERNAL) { highest_note = MIDI_BASE_NOTE + 48; } else if (g_key_fourbanks_mode == FOURBANKS_EXTERNAL) { highest_note = MIDI_BASE_NOTE + 64; } // Check to see if we have a NoteOn or NoteOff event. switch (input_event.Command) { case 0x9 : { // A NoteOn event was found, so update the MIDI // keystate with the note velocity (which may be // zero). uint8_t note = input_event.Data2; uint8_t velocity = input_event.Data3; // Check to see if this note is one we need to care // about. if (note >= MIDI_BASE_NOTE && note < MIDI_BASE_NOTE + highest_note) { // record the note velocity in the MIDI note state g_midi_note_state[note] = velocity; } } break; case 0x8 : { // A NoteOff event, so record a zero in the MIDI // keystate. Yes, a noteoff can have a "velocity", // but we're relying on the keystate to be zero when // we have a noteoff, otherwise the LEDs won't match // the state when we come to calculate them. uint8_t note = input_event.Data2; // Check to see if the note is one we need to care // about. if (note >= MIDI_BASE_NOTE && note < MIDI_BASE_NOTE + highest_note) { // record a zero note velocity in the MIDI note state g_midi_note_state[note] = 0; } } break; } // end switch on command } // end channel test } // end command test } // end while // OUTPUT events from the EXPANSION ports ---------------------------------- // Generate MIDI events for key changes on the digital input ports that // are currently activated (with the lower four bits of // g_exp_digital_read being the mask). // // NOTE(rgreen): Because Fourbanks External mode may be enabled, do the // external key scan once and for all right here. No need to hide it // behind g_exp_digital_read any more. exp_key_read(); // scan the debounce buffer. exp_key_calc(); // update the keyup/keydown variables. // Expansion port pins generate the MIDI notes 4 to 7. const uint8_t MIDI_DIGITAL_NOTE = 4; // lowest digital note. // NOTE: enabling fourbanks external mode turns off digital note generation. if (g_key_fourbanks_mode != FOURBANKS_EXTERNAL && g_exp_digital_read != 0) { uint8_t allow_read = g_exp_digital_read; uint8_t keydown = g_exp_key_down; uint8_t keyup = g_exp_key_up; for(uint8_t i=0; i<4; ++i) { if(allow_read & 1) { if (keydown & 1) { // There's a key down, generate a NoteOn midi_stream_note(MIDI_DIGITAL_NOTE + i, true); // Record the note in the MIDI state so we can generate LEDs // from it later. g_midi_note_state[MIDI_DIGITAL_NOTE + i] = g_midi_velocity; } if (keyup & 1) { // There's a key up, insert a NoteOff midi_stream_note(MIDI_DIGITAL_NOTE + i, false); // Record the note in the MIDI state. g_midi_note_state[MIDI_DIGITAL_NOTE + i] = 0; } } allow_read >>= 1; keydown >>= 1; keyup >>= 1; } }
/** Main program entry point. This routine contains the overall program flow, including initial * setup of all components and the main program loop. */ int main(void) { MIDI_EventPacket_t midiEvent; struct { uint8_t command; uint8_t channel; uint8_t data2; uint8_t data3; } midiMsg; int ind; int led1_ticks = 0; int led2_ticks = 0; SetupHardware(); RingBuffer_InitBuffer(&USBtoUSART_Buffer); RingBuffer_InitBuffer(&USARTtoUSB_Buffer); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); for (;;) { RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer); /* See if we have a message yet */ if (BufferCount >= 4) { /* Read in the message from the serial buffer */ for (ind=0; ind<4; ind++) { ((uint8_t *)&midiMsg)[ind] = RingBuffer_Remove(&USARTtoUSB_Buffer); } /* Build a midi event to send via USB */ midiEvent.CableNumber = 0; midiEvent.Command = midiMsg.command >> 4; midiEvent.Data1 = (midiMsg.command & 0xF0) | ((midiMsg.channel-1) & 0x0F); midiEvent.Data2 = midiMsg.data2; midiEvent.Data3 = midiMsg.data3; MIDI_Device_SendEventPacket(&Keyboard_MIDI_Interface, &midiEvent); MIDI_Device_Flush(&Keyboard_MIDI_Interface); /* Turn on the TX led and starts its timer */ LEDs_TurnOnLEDs(LEDS_LED1); led1_ticks = LED_ON_TICKS; } /* Turn off the Tx LED when the tick count reaches zero */ if (led1_ticks) { led1_ticks--; if (led1_ticks == 0) { LEDs_TurnOffLEDs(LEDS_LED1); } } if (MIDI_Device_ReceiveEventPacket(&Keyboard_MIDI_Interface, &midiEvent)) { RingBuff_Count_t count = RingBuffer_GetCount(&USBtoUSART_Buffer); /* Room to send a message? */ if ((BUFFER_SIZE - count) >= sizeof(midiMsg)) { midiMsg.command = midiEvent.Command << 4; midiMsg.channel = (midiEvent.Data1 & 0x0F) + 1; midiMsg.data2 = midiEvent.Data2; midiMsg.data3 = midiEvent.Data3; for (ind=0; ind<sizeof(midiMsg); ind++) { RingBuffer_Insert(&USBtoUSART_Buffer, ((uint8_t *)&midiMsg)[ind]); } /* Turn on the RX led and start its timer */ LEDs_TurnOnLEDs(LEDS_LED2); led2_ticks = LED_ON_TICKS; } else { /* Turn on the RX led and leave it on to indicate the * buffer is full and the sketch is not reading it * fast enough. */ LEDs_TurnOnLEDs(LEDS_LED2); } /* if there's no room in the serial buffer the message gets dropped */ } /* Turn off the RX LED when the tick count reaches zero */ if (led2_ticks) { led2_ticks--; if (led2_ticks == 0) { LEDs_TurnOffLEDs(LEDS_LED2); } } /* any data to send to main processor? */ if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) { Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer)); } MIDI_Device_USBTask(&Keyboard_MIDI_Interface); USB_USBTask(); } }