Beispiel #1
0
void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
{
#if 0
	if (mode != M_INTELLIGENT)
	{
		mpu401_uart_init(mpu, addr);
		return;
	}
#endif

	mpu->status = STATUS_INPUT_NOT_READY;
	mpu->irq = irq;
	mpu->queue_used = 0;
	mpu->queue_pos = 0;
	mpu->mode = M_UART;

	mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0;
	pclog("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART");

	mpu401_event_callback = 0;
	mpu401_eoi_callback = 0;
	mpu401_reset_callback = 0;

	io_sethandler(addr, 0x0002, mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
	io_sethandler(0x2A20, 0x0010, NULL, NULL, NULL, imf_write, NULL, NULL, mpu);
	timer_add(MPU401_Event, &mpu401_event_callback, &mpu401_event_callback, mpu);
	timer_add(MPU401_EOIHandler, &mpu401_eoi_callback, &mpu401_eoi_callback, mpu);
	timer_add(MPU401_ResetDone, &mpu401_reset_callback, &mpu401_reset_callback, mpu);
	
	MPU401_Reset(mpu);
}
Beispiel #2
0
/* HardMPU: Initialisation */
void MPU401_Init()
{
	/* Initalise PIC code */
	PIC_Init();

	/* Initialise MIDI handler */
        MIDI_Init(CONFIG_SYSEXDELAY,CONFIG_FAKEALLNOTESOFF);
	if (!MIDI_Available()) return;

	mpu.queue_used=0;
	mpu.queue_pos=0;
	mpu.mode=M_UART;

        mpu.intelligent=true; /* Default is on */
	if (!mpu.intelligent) return;

        /* SOFTMPU: Moved IRQ 9 handler init to asm */
	MPU401_Reset();
}
Beispiel #3
0
void MPU401_WriteCommand(Bit8u val) { /* SOFTMPU */
	Bit8u i; /* SOFTMPU */
	if (mpu.state.reset) {
		if (mpu.state.cmd_pending || (val!=0x3f && val!=0xff)) {
			mpu.state.cmd_pending=val+1;
			return;
		}
		PIC_RemoveEvents(RESET_DONE);
		mpu.state.reset=false;
	}
	if (val<=0x2f) {
		switch (val&3) { /* MIDI stop, start, continue */
			case 1: {MIDI_RawOutByte(0xfc);break;}
			case 2: {MIDI_RawOutByte(0xfa);break;}
			case 3: {MIDI_RawOutByte(0xfb);break;}
		}
		/*if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",val);*/ /* SOFTMPU */
		switch (val&0xc) {
			case  0x4:      /* Stop */
				PIC_RemoveEvents(MPU_EVENT);
				mpu.state.playing=false;
				for (i=0xb0;i<0xbf;i++) {  /* All notes off */
					MIDI_RawOutByte(i);
					MIDI_RawOutByte(0x7b);
					MIDI_RawOutByte(0);
				}
				break;
			case 0x8:       /* Play */
				/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started");*/ /* SOFTMPU */
				mpu.state.playing=true;
				PIC_RemoveEvents(MPU_EVENT);
                PIC_AddEvent(MPU_EVENT,(Bitu)MPU401_TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase));
				ClrQueue();
				break;
		}
	}
	else if (val>=0xa0 && val<=0xa7) {      /* Request play counter */
		if (mpu.state.cmask&(1<<(val&7))) QueueByte((Bit8u)mpu.playbuf[val&7].counter);
	}
	else if (val>=0xd0 && val<=0xd7) {      /* Send data */
		mpu.state.old_chan=mpu.state.channel;
		mpu.state.channel=val&7;
		mpu.state.wsd=true;
		mpu.state.wsm=false;
		mpu.state.wsd_start=true;
	}
	else
	switch (val) {
		case 0xdf:      /* Send system message */
			mpu.state.wsd=false;
			mpu.state.wsm=true;
			mpu.state.wsd_start=true;
			break;
		case 0x8e:      /* Conductor */
			mpu.state.cond_set=false;
			break;
		case 0x8f:
			mpu.state.cond_set=true;
			break;
		case 0x94: /* Clock to host */
			mpu.clock.clock_to_host=false;
			break;
		case 0x95:
			mpu.clock.clock_to_host=true;
			break;
		case 0xc2: /* Internal timebase */
                        mpu.clock.timebase=48/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc3:
                        mpu.clock.timebase=72/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc4:
                        mpu.clock.timebase=96/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc5:
                        mpu.clock.timebase=120/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc6:
                        mpu.clock.timebase=144/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc7:
                        mpu.clock.timebase=168/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc8:
                        mpu.clock.timebase=192/(RTCFREQ/1000); /* SOFTMPU */
			break;
		/* Commands with data byte */
		case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: 
		case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
			mpu.state.command_byte=val;
			break;
		/* Commands 0xa# returning data */
		case 0xab:      /* Request and clear recording counter */
			QueueByte(MSG_MPU_ACK);
			QueueByte(0);
			return;
		case 0xac:      /* Request version */
                        if (CONFIG_VERSIONFIX)
                        {
                                /* SOFTMPU: Fix missing music in Gateway by reversing version and ACK */
                                QueueByte(MPU401_VERSION);
                                QueueByte(MSG_MPU_ACK);
                        }
                        else
                        {
                                QueueByte(MSG_MPU_ACK);
                                QueueByte(MPU401_VERSION);
                        }
			return;
		case 0xad:      /* Request revision */
			QueueByte(MSG_MPU_ACK);
			QueueByte(MPU401_REVISION);
			return;
		case 0xae:		/* HardMPU: Request config */
			QueueByte(MSG_MPU_ACK);
			QueueByte(mpu.config);
			return;
		case 0xaf:      /* Request tempo */
			QueueByte(MSG_MPU_ACK);
			QueueByte(mpu.clock.tempo);
			return;
		case 0xb1:      /* Reset relative tempo */
			mpu.clock.tempo_rel=40;
			break;
		case 0xb9:      /* Clear play map */
		case 0xb8:      /* Clear play counters */
			for (i=0xb0;i<0xbf;i++) {  /* All notes off */
				MIDI_RawOutByte((Bit8u)i);
				MIDI_RawOutByte(0x7b);
				MIDI_RawOutByte(0);
			}
			for (i=0;i<8;i++) {
				mpu.playbuf[i].counter=0;
				mpu.playbuf[i].type=T_OVERFLOW;
			}
			mpu.condbuf.counter=0;
			mpu.condbuf.type=T_OVERFLOW;
			if (!(mpu.state.conductor=mpu.state.cond_set)) mpu.state.cond_req=0;
			mpu.state.amask=mpu.state.tmask;
			mpu.state.req_mask=0;
			mpu.state.irq_pending=true;
			break;
		case 0xfe:		/* HardMPU: Reset with config byte */
			mpu.state.command_byte=val;
			break;
		case 0xff:      /* Reset MPU-401 */
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",val);*/ /* SOFTMPU */
            PIC_AddEvent(RESET_DONE,MPU401_RESETBUSY);
			mpu.state.reset=true;
			MPU401_Reset();
			if (mpu.mode==M_UART) return;//do not send ack in UART mode
			break;
		case 0x3f:      /* UART mode */
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val);*/ /* SOFTMPU */
			mpu.mode=M_UART;
			break;
		default:
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val);*/
			break;
	}
	QueueByte(MSG_MPU_ACK);
}
Beispiel #4
0
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
{	
	uint8_t i;

	if (mpu->state.reset) 
	{
		mpu->state.cmd_pending=val+1;
		return;
	}
	
	if (val<=0x2f) 
	{
		switch (val&3) 
		{ /* MIDI stop, start, continue */
			case 1: {midi_write(0xfc);break;}
			case 2: {midi_write(0xfa);break;}
			case 3: {midi_write(0xfb);break;}
		}
//		if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",(int)val);
		switch (val&0xc) 
		{
			case  0x4:	/* Stop */
				mpu->state.playing=0;
				mpu401_event_callback = 0;
				for (i=0xb0;i<0xbf;i++) 
				{	/* All notes off */
					midi_write(i);
					midi_write(0x7b);
					midi_write(0);
				}
				break;
			case 0x8:	/* Play */
//				LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started");
				mpu->state.playing=1;
				mpu401_event_callback = (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000 * TIMER_USEC;
				ClrQueue(mpu);
				break;
		}
	}
	else if (val>=0xa0 && val<=0xa7) 
	{	/* Request play counter */
		if (mpu->state.cmask&(1<<(val&7))) QueueByte(mpu, mpu->playbuf[val&7].counter);
	}
	else if (val>=0xd0 && val<=0xd7) 
	{	/* Send data */
		mpu->state.old_chan=mpu->state.channel;
		mpu->state.channel=val&7;
		mpu->state.wsd=1;
		mpu->state.wsm=0;
		mpu->state.wsd_start=1;
	}
	else
	switch (val) 
	{
		case 0xdf:	/* Send system message */
			mpu->state.wsd=0;
			mpu->state.wsm=1;
			mpu->state.wsd_start=1;
			break;
		case 0x8e:	/* Conductor */
			mpu->state.cond_set=0;
			break;
		case 0x8f:
			mpu->state.cond_set=1;
			break;
		case 0x94: /* Clock to host */
			mpu->clock.clock_to_host=0;
			break;
		case 0x95:
			mpu->clock.clock_to_host=1;
			break;
		case 0xc2: /* Internal timebase */
			mpu->clock.timebase=48;
			break;
		case 0xc3:
			mpu->clock.timebase=72;
			break;
		case 0xc4:
			mpu->clock.timebase=96;
			break;
		case 0xc5:
			mpu->clock.timebase=120;
			break;
		case 0xc6:
			mpu->clock.timebase=144;
			break;
		case 0xc7:
			mpu->clock.timebase=168;
			break;
		case 0xc8:
			mpu->clock.timebase=192;
			break;
		/* Commands with data byte */
		case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: 
		case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
			mpu->state.command_byte=val;
			break;
		/* Commands 0xa# returning data */
		case 0xab:	/* Request and clear recording counter */
			QueueByte(mpu, MSG_MPU_ACK);
			QueueByte(mpu, 0);
			return;
		case 0xac:	/* Request version */
			QueueByte(mpu, MSG_MPU_ACK);
			QueueByte(mpu, MPU401_VERSION);
			return;
		case 0xad:	/* Request revision */
			QueueByte(mpu, MSG_MPU_ACK);
			QueueByte(mpu, MPU401_REVISION);
			return;
		case 0xaf:	/* Request tempo */
			QueueByte(mpu, MSG_MPU_ACK);
			QueueByte(mpu, mpu->clock.tempo);
			return;
		case 0xb1:	/* Reset relative tempo */
			mpu->clock.tempo_rel=40;
			break;
		case 0xb9:	/* Clear play map */
		case 0xb8:	/* Clear play counters */
			for (i=0xb0;i<0xbf;i++) 
			{	/* All notes off */
				midi_write(i);
				midi_write(0x7b);
				midi_write(0);
			}
			for (i=0;i<8;i++) 
			{
				mpu->playbuf[i].counter=0;
				mpu->playbuf[i].type=T_OVERFLOW;
			}
			mpu->condbuf.counter=0;
			mpu->condbuf.type=T_OVERFLOW;
			if (!(mpu->state.conductor=mpu->state.cond_set)) mpu->state.cond_req=0;
			mpu->state.amask=mpu->state.tmask;
			mpu->state.req_mask=0;
			mpu->state.irq_pending=1;
			break;
		case 0xff:	/* Reset MPU-401 */
			pclog("MPU-401:Reset %X\n",val);
			mpu401_reset_callback = MPU401_RESETBUSY * 33 * TIMER_USEC;
			mpu->state.reset=1;
			MPU401_Reset(mpu);
#if 0
			if (mpu->mode==M_UART) return;//do not send ack in UART mode
#endif
			break;
		case 0x3f:	/* UART mode */
			pclog("MPU-401:Set UART mode %X\n",val);
			mpu->mode=M_UART;
			break;
		default:;
			//LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val);
	}
	QueueByte(mpu, MSG_MPU_ACK);
}