Пример #1
0
void CLogicalChannel::handle(byte status, byte *params)
{
  byte cmd = (status & 0xF0);
  switch(cmd) {    
  case 0x80:
  case 0x90:
    if(cmd == 0x80 || cmd == 0x90) {
      if(cmd == 0x80 || params[1] == 0x00) {
        handleNoteOff(params[0]);
      }
      else {
        handleNoteOn(params[0], params[1]);
      }        
    }
    break;
  case 0xB0: 
    handleCC(params[0], params[1]);
    break;
  case 0xE0: 
    handlePitchBend(params[0], params[1]);
    break;
  }    
}
Пример #2
0
// Handle decoding incoming MIDI traffic a byte at a time -- remembers
//  what it needs to from one call to the next.
//
//  This is a private function & not meant to be called from outside this class.
//  It's used whenever data is available from the serial port.
//
void Midi::recvByte(int value)
{
    int tmp;
    int channel;
    int bigval;           /*  temp 14-bit value for pitch, song pos */


    if (recvMode_ & MODE_PROPRIETARY
      && value != STATUS_END_PROPRIETARY)
    {
        /* If proprietary handling compiled in, just pass all data received
         *  after a START_PROPRIETARY event to proprietary_decode
         *  until get an END_PROPRIETARY event
         */

#ifdef CONFIG_MIDI_PROPRIETARY
        proprietaryDecode(value);
#endif

        return;
    }

    if (value & 0x80) {
    
        /* All < 0xf0 events get at least 1 arg byte so
         *  it's ok to mask off the low 4 bits to figure
         *  out how to handle the event for < 0xf0 events.
         */

        tmp = value;

        if (tmp < 0xf0)
            tmp &= 0xf0;

        switch (tmp) {
            /* These status events take 2 bytes as arguments */
            case STATUS_EVENT_NOTE_OFF:
            case STATUS_EVENT_NOTE_ON:
            case STATUS_EVENT_VELOCITY_CHANGE:
            case STATUS_EVENT_CONTROL_CHANGE:
            case STATUS_PITCH_CHANGE:
            case STATUS_SONG_POSITION:
                recvBytesNeeded_ = 2;
                recvByteCount_ = 0;
                recvEvent_ = value;
                break;

            /* 1 byte arguments */
            case STATUS_EVENT_PROGRAM_CHANGE:
            case STATUS_AFTER_TOUCH:
            case STATUS_SONG_SELECT:
                recvBytesNeeded_ = 1;
                recvByteCount_ = 0;
                recvEvent_ = value;
                return;

            /* No arguments ( > 0xf0 events) */
            case STATUS_START_PROPRIETARY:
                recvMode_ |= MODE_PROPRIETARY;

#ifdef CONFIG_MIDI_PROPRIETARY
                proprietaryDecodeStart();
#endif

                break;
            case STATUS_END_PROPRIETARY:
                recvMode_ &= ~MODE_PROPRIETARY;

#ifdef CONFIG_MIDI_PROPRIETARY
                proprietaryDecodeEnd();
#endif

                break;
            case STATUS_TUNE_REQUEST:
                handleTuneRequest();
                break;
            case STATUS_SYNC:
                handleSync();
                break;
            case STATUS_START:
                handleStart();
                break;
            case STATUS_CONTINUE:
                handleContinue();
                break;
            case STATUS_STOP:
                handleStop();
                break;
            case STATUS_ACTIVE_SENSE:
                handleActiveSense();
                break;
            case STATUS_RESET:
                handleReset();
                break;
        }

        return;
    }

    if (++recvByteCount_ == recvBytesNeeded_) {
        /* Copy out the channel (if applicable; in some cases this will be meaningless,
         *  but in those cases the value will be ignored)
         */
        channel = (recvEvent_ & 0x0f) + 1;

        tmp = recvEvent_;
        if (tmp < 0xf0) {
            tmp &= 0xf0;
        }

        /* See if this event matches our MIDI channel
         *  (or we're accepting for all channels)
         */
        if (!channelIn_
             || (channel == channelIn_)
             || (tmp >= 0xf0))
        {
            switch (tmp) {
                case STATUS_EVENT_NOTE_ON:
                    /* If velocity is 0, it's actually a note off & should fall thru
                     *  to the note off case
                     */
                    if (value) {
                        handleNoteOn(channel, recvArg0_, value);
                        break;
                    }

                case STATUS_EVENT_NOTE_OFF:
                    handleNoteOff(channel, recvArg0_, value);
                    break;
                case STATUS_EVENT_VELOCITY_CHANGE:
                    handleVelocityChange(channel, recvArg0_, value);
                    break;
                case STATUS_EVENT_CONTROL_CHANGE:
                    handleControlChange(channel, recvArg0_, value);
                    break;
                case STATUS_EVENT_PROGRAM_CHANGE:
                    handleProgramChange(channel, value);
                    break;
                case STATUS_AFTER_TOUCH:
                    handleAfterTouch(channel, value);
                    break;
                case STATUS_PITCH_CHANGE:
                    bigval = (value << 7) | recvArg0_;
                    handlePitchChange(bigval);
                    break;
                case STATUS_SONG_POSITION:
                    bigval = (value << 7) | recvArg0_;
                    handleSongPosition(bigval);
                    break;
                case STATUS_SONG_SELECT:
                    handleSongSelect(value);
                    break;
            }
        }

        /* Just reset the byte count; keep the same event -- might get more messages
            trailing from current event.
         */
        recvByteCount_ = 0;
    }
    
    recvArg0_ = value;
}
Пример #3
0
void SysexComm::handleNoteOff(MidiKeyboardState* source, int midiChannel, int midiNoteNumber) {
    handleNoteOn(source, midiChannel, midiNoteNumber, 0);
}
Пример #4
0
// Process a MIDI Note On message
void MidiSostenutoPedal::noteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
    bitSet(prePedalNotes[channel & 0xF][(note & 0x7F) / 32], (note & 0x7F) % 32); // Remember as channel pre-pedal note
    if (bitRead(pressed, channel & 0xF)) // If pedal pressed, reset channel held note
        bitClear(heldNotes[channel & 0xF][(note & 0x7F) / 32], (note & 0x7F) % 32);
    handleNoteOn(channel, note, velocity);
}
Пример #5
0
////////////////////////////////////////////////////////////
// MAIN
void main()
{ 
	int i;
	
	// osc control / 16MHz / internal
	osccon = 0b01111010;
		
	apfcon0 = APFCON0_MASK;
	
	// configure io. Initially all outputs are 
	// disabled except for the LED and all outputs
	// states are zeroed
	trisa = 0b11111111;
	trisc = 0b11111111;

	T_LED = 0;    
	ansela = 0b00000000;
	anselc = 0b00000000;
	porta =  0b00000000;
	portc =  0b00000000;

	P_WPU = 1; // weak pull up on switch input
	option_reg.7 = 0; // weak pull up enable

	// initialise MIDI comms
	init_usart();
	
	intcon.7 = 1; //GIE
	intcon.6 = 1; //PEIE
	
	// Configure timer 0 (controls systemticks)
	// 	timer 0 runs at 4MHz
	// 	prescaled 1/16 = 250kHz
	// 	rollover at 250 = 1kHz
	// 	1ms per rollover	
	option_reg.5 = 0; // timer 0 driven from instruction cycle clock
	option_reg.3 = 0; // timer 0 is prescaled
	option_reg.2 = 0; // }
	option_reg.1 = 1; // } 1/16 prescaler
	option_reg.0 = 1; // }
	intcon.5 = 1; 	  // enabled timer 0 interrrupt
	intcon.2 = 0;     // clear interrupt fired flag
	
	// enable interrupts	
	intcon.7 = 1; //GIE
	intcon.6 = 1; //PEIE

	// Initialise the table of port info pointers
	port[0] = &port0;
	port[1] = &port1;
	port[2] = &port2;
	port[3] = &port3;
	port[4] = &port4;
	port[5] = &port5;
	port[6] = &port6;
	port[7] = &port7;
	
	// allow time for input to settle then load 
	// EEPROM settings, allowing a hold of MODE
	// to restore default settings
	delay_ms(5);
	loadPortInfo((!P_MODE));		

#ifdef RELAY_SWITCHER
	// In relay switching mode set all output latches LOW
	// and set default tristate (INPUT/1 selected for OFF)
	T_OUT0 = !port0.cfg.invert;
	T_OUT1 = !port1.cfg.invert;
	T_OUT2 = !port2.cfg.invert;
	T_OUT3 = !port3.cfg.invert;
	T_OUT4 = !port4.cfg.invert;
	T_OUT5 = !port5.cfg.invert;
	T_OUT6 = !port6.cfg.invert;
	T_OUT7 = !port7.cfg.invert;
		
	P_OUT0 = 0;		P_OUT1 = 0;		P_OUT2 = 0;		P_OUT3 = 0;
	P_OUT4 = 0;		P_OUT5 = 0;		P_OUT6 = 0;		P_OUT7 = 0;
		
#else
	// In transistor switching mode set default "off"
	// states and enable digital outputs
	P_OUT0 = !!port0.cfg.invert;
	P_OUT1 = !!port1.cfg.invert;
	P_OUT2 = !!port2.cfg.invert;
	P_OUT3 = !!port3.cfg.invert;
	P_OUT4 = !!port4.cfg.invert;
	P_OUT5 = !!port5.cfg.invert;
	P_OUT6 = !!port6.cfg.invert;
	P_OUT7 = !!port7.cfg.invert;
		
	T_OUT0 = 0;		T_OUT1 = 0;		T_OUT2 = 0;		T_OUT3 = 0;
	T_OUT4 = 0;		T_OUT5 = 0;		T_OUT6 = 0;		T_OUT7 = 0;
#endif
		
	int ledCount = 0;
	int modeHeld = 0;
	byte enableNrpn = 0;
	byte nrpnLo = 0;
	byte nrpnHi = 0;
	byte pwm=0;
	int cycles = 0;
	for(;;)
	{	
		// Fetch the next MIDI message
		byte msg = receiveMessage();
		if(msg && !ledCount)
			ledCount = LEDCOUNT_BRIEF;
				
		// NOTE ON
		if(((msg & 0xf0) == 0x90) && midiParams[1])
		{
			handleNoteOn(msg&0xF, midiParams[0], midiParams[1]);
		}
		// NOTE OFF
		else if((((msg & 0xf0) == 0x80)||((msg & 0xf0) == 0x90)))
		{
			handleNoteOff(msg&0xF, midiParams[0]);
		}
		// CONTROLLER
		else if((msg & 0xf0) == 0xb0) 
		{			
			if(enableNrpn) 
			{
				switch(midiParams[0])
				{
					case MIDI_NRPN_HI: 
						nrpnHi = midiParams[1]; 
						break;
					case MIDI_NRPN_LO: 
						nrpnLo = midiParams[1]; 
						break;
					case MIDI_DATA_HI: 
					case MIDI_DATA_LO: 
						if(nrpnHi < NUM_PORTS)
							handleNrpn(port[nrpnHi], nrpnLo, midiParams[1], (midiParams[0] == MIDI_DATA_LO));
						else if(nrpnHi == NRPN_HI_EEPROM && nrpnLo == NRPN_LO_SAVE)
							savePortInfo();
					break;
					default:
						handleCC(msg&0xF, midiParams[0], midiParams[1]);
						break;
						
				}
			}
			else
			{
				handleCC(msg&0xF, midiParams[0], midiParams[1]);			
			}
		}
		// PITCH BEND
		else if((msg & 0xf0) == 0xe0) 
		{
			handlePitchBend(msg&0xF, midiParams[0]);
		}
		
		
		if(ledCount)
			P_LED = !!(--ledCount);
			
		// EVERY MS
		if(timerTicked)
		{
			timerTicked = 0;
			
			// Decrement nonzero port latch counts
			for(i=0;i<NUM_PORTS;++i)
			{				
				if(port[i]->status.count>0)
					--port[i]->status.count;
			}
				
			// If the MODE button is held for 1 second
			// this enables the receiving of config info		
			if(!enableNrpn)
			{
				if(P_MODE)//mode button released
				{
					
					modeHeld = 0;
				}
				else if(++modeHeld >= 1000)// mode button pressed for more than 1 second
				{					
					P_LED = 1; delay_s(1); P_LED = 0;
					enableNrpn = 1;
				}
			}
			else if(isDirtyConfig)//config has been updated
			{
				if(!P_MODE)//
				{
					P_LED = 1;	delay_s(1);	P_LED = 0;				
					savePortInfo();
					isDirtyConfig = 0;					
				}
				else
				{
					++cycles;
					if(!(cycles & 0x1FF) && !ledCount)
						ledCount = LEDCOUNT_MEDIUM;
				}
			}
			else
			{
				++cycles;
				if(!(cycles & 0x7FF) && !ledCount)
					ledCount = LEDCOUNT_LONG;
			}
		}

#ifdef RELAY_SWITCHER

		// Manage outputs for relay switcher. PWM is ignored and switching
		// is done on the TRIS bit. The outputs are active low for ON and 
		// floating for OFF
		#define OUT_STATE(P) !(P.status.count)
		#define OUT_STATEN(P) !!(P.status.count)
		T_OUT0 = port0.cfg.invert? OUT_STATEN(port0) : OUT_STATE(port0);
		T_OUT1 = port1.cfg.invert? OUT_STATEN(port1) : OUT_STATE(port1);
		T_OUT2 = port2.cfg.invert? OUT_STATEN(port2) : OUT_STATE(port2);
		T_OUT3 = port3.cfg.invert? OUT_STATEN(port3) : OUT_STATE(port3);
		T_OUT4 = port4.cfg.invert? OUT_STATEN(port4) : OUT_STATE(port4);		
		T_OUT5 = port5.cfg.invert? OUT_STATEN(port5) : OUT_STATE(port5);
		T_OUT6 = port6.cfg.invert? OUT_STATEN(port6) : OUT_STATE(port6);
		T_OUT7 = port7.cfg.invert? OUT_STATEN(port7) : OUT_STATE(port7);	
		P_OUT0 = 0;		
		P_OUT1 = 0;		
		P_OUT2 = 0;		
		P_OUT3 = 0;
		P_OUT4 = 0;		
		P_OUT5 = 0;		
		P_OUT6 = 0;		
		P_OUT7 = 0;		
		
#elif TRS_SWITCHER

		// Manage outputs for TRS relay switcher. PWM is ignored and switching
		// is active high
		#define OUT_STATE(P) !!(P.status.count)
		#define OUT_STATEN(P) !(P.status.count)
		P_OUT0 = port0.cfg.invert? OUT_STATEN(port0) : OUT_STATE(port0);
		P_OUT1 = port1.cfg.invert? OUT_STATEN(port1) : OUT_STATE(port1);
		P_OUT2 = port2.cfg.invert? OUT_STATEN(port2) : OUT_STATE(port2);
		P_OUT3 = port3.cfg.invert? OUT_STATEN(port3) : OUT_STATE(port3);
		P_OUT4 = port4.cfg.invert? OUT_STATEN(port4) : OUT_STATE(port4);
		P_OUT5 = port5.cfg.invert? OUT_STATEN(port5) : OUT_STATE(port5);
		P_OUT6 = port6.cfg.invert? OUT_STATEN(port6) : OUT_STATE(port6);
		P_OUT7 = port7.cfg.invert? OUT_STATEN(port7) : OUT_STATE(port7);		
#else		

		// Manage outputs for transistor switchers. PWM is used and switching
		// is active high
		#define OUT_STATE(P) (P.status.count && (pwm < P.status.duty))
		#define OUT_STATEN(P) (!P.status.count && (pwm < P.status.duty))
		P_OUT0 = port0.cfg.invert? OUT_STATEN(port0) : OUT_STATE(port0);
		P_OUT1 = port1.cfg.invert? OUT_STATEN(port1) : OUT_STATE(port1);
		P_OUT2 = port2.cfg.invert? OUT_STATEN(port2) : OUT_STATE(port2);
		P_OUT3 = port3.cfg.invert? OUT_STATEN(port3) : OUT_STATE(port3);
		P_OUT4 = port4.cfg.invert? OUT_STATEN(port4) : OUT_STATE(port4);
		P_OUT5 = port5.cfg.invert? OUT_STATEN(port5) : OUT_STATE(port5);
		P_OUT6 = port6.cfg.invert? OUT_STATEN(port6) : OUT_STATE(port6);
		P_OUT7 = port7.cfg.invert? OUT_STATEN(port7) : OUT_STATE(port7);		
		if(++pwm>100)
			pwm=0;
#endif 
			
	}
}
Пример #6
0
// Process a MIDI Note On message
void MidiDamperPedal::noteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
    if (bitRead(heldNotes[channel & 0xF][(note & 0x7F) / 32], (note & 0x7F) % 32))
        bitClear(heldNotes[channel & 0xF][(note & 0x7F) / 32], (note & 0x7F) % 32); // Reset channel held note
    handleNoteOn(channel, note, velocity);
}
Пример #7
0
// Handle decoding incoming MIDI traffic a byte at a time -- remembers
//  what it needs to from one call to the next.
//
//  This is a private function & not meant to be called from outside this class.
//  It's used whenever data is available from the serial port.
//
void USBMidi::dispatchPacket(uint32 p)
{
    union EVENT_t e;
    
    e.i=p;
    // !!!!!!!!!!!!!!!!  Add a sysex handler  FIX THIS VERY VERY SHORTLY !!!!!!!!!!!!!!
    if (recvMode_ & MODE_PROPRIETARY
        && CIN_IS_SYSEX(e.p.cin))
    {
        /* If sysex handling compiled in, just pass all data received
         * to the sysex handler
         */
        
#ifdef CONFIG_MIDI_PROPRIETARY
//        handleSysex(p);
#endif
        
        return;
    }
    
    switch (e.p.cin) {
        case CIN_3BYTE_SYS_COMMON:
            if (e.p.midi0 == MIDIv1_SONG_POSITION_PTR) {
                handleSongPosition(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
            }
            break;

        case CIN_2BYTE_SYS_COMMON:
             switch (e.p.midi0) {
                 case MIDIv1_SONG_SELECT:
                     handleSongSelect(e.p.midi1);
                     break;
                 case MIDIv1_MTC_QUARTER_FRAME:
                     // reference library doesnt handle quarter frame.
                     break;
             }
            break;
        case CIN_NOTE_OFF:
            handleNoteOff(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
            break;
        case CIN_NOTE_ON:
            handleNoteOn(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
            break;
        case CIN_AFTER_TOUCH:
            handleVelocityChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
            break;
        case CIN_CONTROL_CHANGE:
            handleControlChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
            break;
        case CIN_PROGRAM_CHANGE:
            handleProgramChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
            break;
        case CIN_CHANNEL_PRESSURE:
            handleAfterTouch(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
            break;
                     
        case CIN_PITCH_WHEEL:
            handlePitchChange(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
            break;
        case CIN_1BYTE:
            switch (e.p.midi0) {
                case MIDIv1_CLOCK:
                    handleSync();
                    break;
                case MIDIv1_TICK:
                    break;
                case MIDIv1_START:
                    handleStart();
                    break;
                case MIDIv1_CONTINUE:
                    handleContinue();
                    break;
                case MIDIv1_STOP:
                    handleStop();
                    break;
                case MIDIv1_ACTIVE_SENSE:
                    handleActiveSense();
                    break;
                case MIDIv1_RESET:
                    handleReset();
                    break;
                case MIDIv1_TUNE_REQUEST:
                    handleTuneRequest();
                    break;

                default:
                    break;
            }
            break;
    }
}