/** * Entry function which will process the assembled code and perform the required actions */ void processAssembledCode(char * assembled, unsigned int length, unsigned short numberSymbols, int coreId, int numberActiveCores, int baseHostPid) { stopInterpreter=0; currentSymbolEntries=0; localCoreId=coreId; numActiveCores=numberActiveCores; symbolTable=initialiseSymbolTable(numberSymbols); hostCoresBasePid=baseHostPid; unsigned int i; for (i=0;i<length;) { unsigned short command=getUShort(&assembled[i]); i+=sizeof(unsigned short); if (command == LET_TOKEN) i=handleLet(assembled, i); if (command == ARRAYSET_TOKEN) i=handleArraySet(assembled, i); if (command == DIMARRAY_TOKEN) i=handleDimArray(assembled, i, 0); if (command == DIMSHAREDARRAY_TOKEN) i=handleDimArray(assembled, i, 1); if (command == PRINT_TOKEN) i=handlePrint(assembled, i); if (command == STOP_TOKEN) return; if (command == SYNC_TOKEN) i=handleSync(assembled, i); if (command == IF_TOKEN) i=handleIf(assembled, i); if (command == IFELSE_TOKEN) i=handleIf(assembled, i); if (command == FOR_TOKEN) i=handleFor(assembled, i); if (command == GOTO_TOKEN) i=handleGoto(assembled, i); if (command == INPUT_TOKEN) i=handleInput(assembled, i); if (command == INPUT_STRING_TOKEN) i=handleInputWithString(assembled, i); if (command == SEND_TOKEN) i=handleSend(assembled, i); if (command == RECV_TOKEN) i=handleRecv(assembled, i); if (command == RECVTOARRAY_TOKEN) i=handleRecvToArray(assembled, i); if (command == SENDRECV_TOKEN) i=handleSendRecv(assembled, i); if (command == SENDRECVARRAY_TOKEN) i=handleSendRecvArray(assembled, i); if (command == BCAST_TOKEN) i=handleBcast(assembled, i); if (command == REDUCTION_TOKEN) i=handleReduction(assembled, i); if (stopInterpreter) return; } }
static void CUPTIAPI traceCallback(void *userdata, CUpti_CallbackDomain domain, CUpti_CallbackId cbid, const void *cbdata) { if (domain == CUPTI_CB_DOMAIN_RESOURCE) { handleResource(cbid, (CUpti_ResourceData *)cbdata); } else if (domain == CUPTI_CB_DOMAIN_SYNCHRONIZE) { handleSync(cbid, (CUpti_SynchronizeData *)cbdata); } }
// 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; }
/* check and handle received messages */ void handle(PtpClock *ptpClock) { int ret; ssize_t length; Boolean isFromSelf; Boolean isEvent; Boolean badTime = FALSE; TimeInternal time = { 0, 0 }; if(!ptpClock->message_activity) { ret = netSelect(0, ptpClock); if(ret < 0) { PERROR("failed to poll sockets"); toState(PTP_FAULTY, ptpClock); return; } else if(!ret) { DBGV("handle: nothing\n"); return; } /* else length > 0 */ } DBGV("handle: something\n"); isEvent = TRUE; length = netRecvEvent(ptpClock->msgIbuf, ptpClock->delayedTiming ? NULL : &time, ptpClock); if(length < 0) { PERROR("failed to receive on the event socket"); toState(PTP_FAULTY, ptpClock); return; } else if(!length) { isEvent = FALSE; length = netRecvGeneral(ptpClock->msgIbuf, ptpClock); if(length < 0) { PERROR("failed to receive on the general socket"); toState(PTP_FAULTY, ptpClock); return; } else if(!length) return; } ptpClock->message_activity = TRUE; if(!msgPeek(ptpClock->msgIbuf, length)) return; if(length < HEADER_LENGTH) { ERROR("message shorter than header length\n"); toState(PTP_FAULTY, ptpClock); return; } msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader); if(isEvent && ptpClock->delayedTiming) { /* query hardware for matching receive time stamp */ if(!getReceiveTime(&time, ptpClock->msgTmpHeader.sourceUuid, ptpClock->msgTmpHeader.sequenceId, ptpClock)) { /* * Incoming packets without hardware time stamp cannot be ignored outright because * a master might only be able to time stamp DelayReq packets; ignoring the Sync * packets from another, better clock would break the clock selection protocol. * Therefore set system time as fallback and decide below what to do. */ DBGV("*** message with no time stamp ***\n"); getTime(&time, ptpClock); badTime = TRUE; } } DBGV("%s Receipt of Message\n" " version %d\n" " type %d\n" " uuid %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n" " sequence %d\n" " time %us %dns\n", isEvent ? "event" : "control", ptpClock->msgTmpHeader.versionPTP, ptpClock->msgTmpHeader.control, ptpClock->msgTmpHeader.sourceUuid[0], ptpClock->msgTmpHeader.sourceUuid[1], ptpClock->msgTmpHeader.sourceUuid[2], ptpClock->msgTmpHeader.sourceUuid[3], ptpClock->msgTmpHeader.sourceUuid[4], ptpClock->msgTmpHeader.sourceUuid[5], ptpClock->msgTmpHeader.sequenceId, time.seconds, time.nanoseconds); if(ptpClock->msgTmpHeader.versionPTP != VERSION_PTP) { DBGV("ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP); return; } if( memcmp(ptpClock->msgTmpHeader.subdomain, ptpClock->subdomain_name, PTP_SUBDOMAIN_NAME_LENGTH) ) { DBGV("ignore message from subdomain %s\n", ptpClock->msgTmpHeader.subdomain); return; } isFromSelf = ptpClock->msgTmpHeader.sourceCommunicationTechnology == ptpClock->port_communication_technology && ptpClock->msgTmpHeader.sourcePortId == ptpClock->port_id_field && !memcmp(ptpClock->msgTmpHeader.sourceUuid, ptpClock->port_uuid_field, PTP_UUID_LENGTH); /* subtract the inbound latency adjustment if it is not a loop back and the time stamp seems reasonable */ if(!isFromSelf && time.seconds > 0) subTime(&time, &time, &ptpClock->runTimeOpts.inboundLatency); switch(ptpClock->msgTmpHeader.control) { case PTP_SYNC_MESSAGE: handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, badTime, isFromSelf, ptpClock); break; case PTP_FOLLOWUP_MESSAGE: handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock); break; case PTP_DELAY_REQ_MESSAGE: handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, badTime, isFromSelf, ptpClock); break; case PTP_DELAY_RESP_MESSAGE: handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock); break; case PTP_MANAGEMENT_MESSAGE: handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock); break; default: DBG("handle: unrecognized message\n"); break; } }
/* check and handle received messages */ void handle(RunTimeOpts *rtOpts, PtpClock *ptpClock) { int ret; ssize_t length; Boolean isFromSelf; TimeInternal time = { 0, 0 }; TimeInternal now = { 0, 0 }; if(!ptpClock->message_activity) { ret = netSelect(0, &ptpClock->netPath); if(ret < 0) { PERROR("failed to poll sockets"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if(!ret) { #if 0 DBGV("handle: nothing\n"); #endif return; } /* else length > 0 */ } DBGV("handle: something\n"); length = netRecvEvent(ptpClock->msgIbuf, &time, &ptpClock->netPath); getTime(&now); DBG("Time is %ds %dns\n", now.seconds, now.nanoseconds); if(length < 0) { PERROR("failed to receive on the event socket"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if(!length) { length = netRecvGeneral(ptpClock->msgIbuf, &ptpClock->netPath); if(length < 0) { PERROR("failed to receive on the general socket"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if(!length) return; } ptpClock->message_activity = TRUE; if(!msgPeek(ptpClock->msgIbuf, length)) return; if(length < HEADER_LENGTH) { ERROR("message shorter than header length\n"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader); DBG("event Receipt of Message\n type %d\n" " uuid %02x:%02x:%02x:%02x:%02x:%02x\n" " sequence %d\n time %us %dns\n", ptpClock->msgTmpHeader.control, ptpClock->msgTmpHeader.sourceUuid[0], ptpClock->msgTmpHeader.sourceUuid[1], ptpClock->msgTmpHeader.sourceUuid[2], ptpClock->msgTmpHeader.sourceUuid[3], ptpClock->msgTmpHeader.sourceUuid[4], ptpClock->msgTmpHeader.sourceUuid[5], ptpClock->msgTmpHeader.sequenceId, time.seconds, time.nanoseconds); isFromSelf = ptpClock->msgTmpHeader.sourceCommunicationTechnology == ptpClock->port_communication_technology && ptpClock->msgTmpHeader.sourcePortId == ptpClock->port_id_field && !memcmp(ptpClock->msgTmpHeader.sourceUuid, ptpClock->port_uuid_field, PTP_UUID_LENGTH); /* subtract the inbound latency adjustment if it is not a loop back and the time stamp seems reasonable */ if(!isFromSelf && time.seconds > 0) subTime(&time, &time, &rtOpts->inboundLatency); switch(ptpClock->msgTmpHeader.control) { case PTP_SYNC_MESSAGE: handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock); break; case PTP_FOLLOWUP_MESSAGE: handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case PTP_DELAY_REQ_MESSAGE: handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock); break; case PTP_DELAY_RESP_MESSAGE: handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case PTP_MANAGEMENT_MESSAGE: handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; default: DBG("handle: unrecognized message\n"); break; } }
/* check and handle received messages */ static void handle(PtpClock *ptpClock) { int ret; Boolean isFromSelf; TimeInternal time = { 0, 0 }; if (FALSE == ptpClock->messageActivity) { ret = netSelect(&ptpClock->netPath, 0); if (ret < 0) { ERROR("handle: failed to poll sockets\n"); toState(ptpClock, PTP_FAULTY); return; } else if (!ret) { DBGVV("handle: nothing\n"); return; } } DBGVV("handle: something\n"); //msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);//**********************************************/ ptpClock->msgIbufLength = netRecvEvent(&ptpClock->netPath, ptpClock->msgIbuf, &time); /* local time is not UTC, we can calculate UTC on demand, otherwise UTC time is not used */ /* time.seconds += ptpClock->timePropertiesDS.currentUtcOffset; */ if (ptpClock->msgIbufLength < 0) { ERROR("handle: failed to receive on the event socket\n"); toState(ptpClock, PTP_FAULTY); return; } else if (!ptpClock->msgIbufLength) { ptpClock->msgIbufLength = netRecvGeneral(&ptpClock->netPath, ptpClock->msgIbuf, &time); if (ptpClock->msgIbufLength < 0) { ERROR("handle: failed to receive on the general socket\n"); toState(ptpClock, PTP_FAULTY); return; } else if (!ptpClock->msgIbufLength) return; } ptpClock->messageActivity = TRUE; if (ptpClock->msgIbufLength < HEADER_LENGTH) { ERROR("handle: message shorter than header length\n"); toState(ptpClock, PTP_FAULTY); return; } msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader); if (ptpClock->msgTmpHeader.versionPTP != ptpClock->portDS.versionNumber) { DBGV("handle: ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP); return; } if (ptpClock->msgTmpHeader.domainNumber != ptpClock->defaultDS.domainNumber) { DBGV("handle: ignore message from domainNumber %d\n", ptpClock->msgTmpHeader.domainNumber); return; } /*Spec 9.5.2.2*/ isFromSelf = isSamePortIdentity( &ptpClock->portDS.portIdentity, &ptpClock->msgTmpHeader.sourcePortIdentity); /* subtract the inbound latency adjustment if it is not a loop back and the time stamp seems reasonable */ if (!isFromSelf && time.seconds > 0) subTime(&time, &time, &ptpClock->inboundLatency); switch (ptpClock->msgTmpHeader.messageType) { case ANNOUNCE: handleAnnounce(ptpClock, isFromSelf); break; case SYNC: handleSync(ptpClock, &time, isFromSelf); break; case FOLLOW_UP: handleFollowUp(ptpClock, isFromSelf); break; case DELAY_REQ: handleDelayReq(ptpClock, &time, isFromSelf); break; case PDELAY_REQ: handlePDelayReq(ptpClock, &time, isFromSelf); break; case DELAY_RESP: handleDelayResp(ptpClock, isFromSelf); break; case PDELAY_RESP: handlePDelayResp(ptpClock, &time, isFromSelf); break; case PDELAY_RESP_FOLLOW_UP: handlePDelayRespFollowUp(ptpClock, isFromSelf); break; case MANAGEMENT: handleManagement(ptpClock, isFromSelf); break; case SIGNALING: handleSignaling(ptpClock, isFromSelf); break; default: DBG("handle: unrecognized message %d\n", ptpClock->msgTmpHeader.messageType); break; } }
/* check and handle received messages */ void handle(RunTimeOpts *rtOpts, PtpClock *ptpClock) { int ret; ssize_t length; Boolean isFromSelf; TimeInternal time = { 0, 0 }; if (!ptpClock->message_activity) { ret = netSelect(0, &ptpClock->netPath); if (ret < 0) { PERROR("failed to poll sockets"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if (!ret) { /* DBGV("handle: nothing\n"); */ return; } /* else length > 0 */ } DBGV("handle: something\n"); /* TODO: this should be based on the select actual FDs (if(FD_ISSET(...)) */ length = netRecvEvent(ptpClock->msgIbuf, &time, &ptpClock->netPath); if (length < 0) { PERROR("failed to receive on the event socket"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if (!length) { length = netRecvGeneral(ptpClock->msgIbuf, &time, &ptpClock->netPath); if (length < 0) { PERROR("failed to receive on the general socket"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } else if (!length) return; } /* * make sure we use the TAI to UTC offset specified, if the master is sending the UTC_VALID bit * * * On the slave, all timestamps that we handle here have been collected by our local clock (loopback+kernel-level timestamp) * This includes delayReq just send, and delayResp, when it arrives. * * these are then adjusted to the same timebase of the Master (+34 leap seconds, as of 2011) * */ DBGV("__UTC_offset: %d %d \n", ptpClock->currentUtcOffsetValid, ptpClock->currentUtcOffset); if (ptpClock->currentUtcOffsetValid) { time.seconds += ptpClock->currentUtcOffset; } ptpClock->message_activity = TRUE; if (length < HEADER_LENGTH) { ERROR("message shorter than header length\n"); toState(PTP_FAULTY, rtOpts, ptpClock); return; } msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader); if (ptpClock->msgTmpHeader.versionPTP != ptpClock->versionNumber) { DBG2("ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP); return; } if(ptpClock->msgTmpHeader.domainNumber != ptpClock->domainNumber) { DBG2("ignore message from domainNumber %d\n", ptpClock->msgTmpHeader.domainNumber); return; } /*Spec 9.5.2.2*/ isFromSelf = (ptpClock->portIdentity.portNumber == ptpClock->msgTmpHeader.sourcePortIdentity.portNumber && !memcmp(ptpClock->msgTmpHeader.sourcePortIdentity.clockIdentity, ptpClock->portIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH)); /* * subtract the inbound latency adjustment if it is not a loop * back and the time stamp seems reasonable */ if (!isFromSelf && time.seconds > 0) subTime(&time, &time, &rtOpts->inboundLatency); #ifdef PTPD_DBG /* easy display of received messages */ char *st; switch(ptpClock->msgTmpHeader.messageType) { case ANNOUNCE: st = "Announce"; break; case SYNC: st = "Sync"; break; case FOLLOW_UP: st = "FollowUp"; break; case DELAY_REQ: st = "DelayReq"; break; case DELAY_RESP: st = "DelayResp"; break; default: st = "Unk"; break; } DBG(" ==> %s received\n", st); #endif /* * on the table below, note that only the event messsages are passed the local time, * (collected by us by loopback+kernel TS, and adjusted with UTC seconds * * (SYNC / DELAY_REQ / PDELAY_REQ / PDELAY_RESP) */ switch (ptpClock->msgTmpHeader.messageType) { case ANNOUNCE: handleAnnounce(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case SYNC: handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock); break; case FOLLOW_UP: handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case DELAY_REQ: handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock); break; case PDELAY_REQ: handlePDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock); break; case DELAY_RESP: handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case PDELAY_RESP: handlePDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, &time, length, isFromSelf, rtOpts, ptpClock); break; case PDELAY_RESP_FOLLOW_UP: handlePDelayRespFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case MANAGEMENT: handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; case SIGNALING: handleSignaling(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock); break; default: DBG("handle: unrecognized message\n"); break; } if (rtOpts->displayPackets) msgDump(ptpClock); }
// 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; } }