You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					178 lines
				
				4.6 KiB
			
		
		
			
		
	
	
					178 lines
				
				4.6 KiB
			|   
											16 years ago
										 | import javax.sound.midi.*; | ||
|  | import javax.sound.midi.MidiMessage.*; | ||
|  | import java.io.RandomAccessFile; | ||
|  | 
 | ||
|  | class BIN2BOOT | ||
|  | { | ||
|  | 	private static final int MIDI_CONTROL_CHANNEL          = 9; | ||
|  | 	private static final int MIDI_DATA_CHANNEL             = 0; | ||
|  | 
 | ||
|  | 	private static final int CONTROL_DEVICE_READY          = 0xD1; | ||
|  | 	private static final int CONTROL_ENTER_PROG_MODE       = 0xDC; | ||
|  | 	private static final int CONTROL_LEAVE_PROG_MODE       = 0xDF; | ||
|  | 	private static final int CONTROL_GET_PAGE_SIZE         = 0x01; | ||
|  | 
 | ||
|  | 	public static void main(String[] args) | ||
|  | 	{ | ||
|  | 		if (args.length != 1) | ||
|  | 		{ | ||
|  | 			System.out.println("BIN2BOOT - USB-MIDI bootloader"); | ||
|  | 			System.out.println("  Usage: java BIN2BOOT {input}.bin"); | ||
|  | 		}	 | ||
|  | 	 | ||
|  | 		RandomAccessFile inFile = null; | ||
|  | 		 | ||
|  | 		try | ||
|  | 		{ | ||
|  | 			inFile = new RandomAccessFile(args[0], "r"); | ||
|  | 		} | ||
|  | 		catch (Exception e) | ||
|  | 		{ | ||
|  | 			System.out.println("Could not open input file!"); | ||
|  | 			return; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		MidiDevice  currDevice = null; | ||
|  | 		Receiver    midiOut    = null; | ||
|  | 		Transmitter midiIn     = null; | ||
|  | 		MIDIMessageReceiver midiInMessages = new MIDIMessageReceiver(); | ||
|  | 		 | ||
|  | 		try | ||
|  | 		{ | ||
|  | 			MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); | ||
|  | 			 | ||
|  | 			for (MidiDevice.Info info : infos) | ||
|  | 			{ | ||
|  | 				currDevice = MidiSystem.getMidiDevice(info); | ||
|  | 			 | ||
|  | 				if (!(currDevice instanceof Sequencer) && !(currDevice instanceof Synthesizer)) | ||
|  | 				{ | ||
|  | 					if (info.getName().indexOf("LUFA") == -1) | ||
|  | 					  continue; | ||
|  | 					   | ||
|  | 					System.out.println(" MIDI Device: " + info.getName()); | ||
|  | 				 | ||
|  | 					currDevice.open(); | ||
|  | 				 | ||
|  | 					if (currDevice.getMaxReceivers() != 0) | ||
|  | 					{ | ||
|  | 						midiOut = currDevice.getReceiver(); | ||
|  | 						break; | ||
|  | 					} | ||
|  | 
 | ||
|  | 					if (currDevice.getMaxTransmitters() != 0) | ||
|  | 					{ | ||
|  | 						midiIn  = currDevice.getTransmitter(); | ||
|  | 						midiIn.setReceiver(midiInMessages); | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 			 | ||
|  | 			if ((midiOut == null) || (midiIn == null)) | ||
|  | 			{ | ||
|  | 				System.out.println("Could not find suitable MIDI device!"); | ||
|  | 				return; | ||
|  | 			}			 | ||
|  | 		} | ||
|  | 		catch (Exception e) | ||
|  | 		{ | ||
|  | 			System.out.println("Could not enumerate MIDI devices!"); | ||
|  | 			return; | ||
|  | 		} | ||
|  | 		 | ||
|  | 		System.out.println("PROGRAMMING FILE..."); | ||
|  | 
 | ||
|  | 		ProgramFirmware(inFile, midiOut, midiInMessages); | ||
|  | 
 | ||
|  | 		System.out.println("DONE."); | ||
|  | 
 | ||
|  | 		try | ||
|  | 		{ | ||
|  | 			midiOut.close(); | ||
|  | 			midiIn.close(); | ||
|  | 			currDevice.close(); | ||
|  | 			inFile.close(); | ||
|  | 		} | ||
|  | 		catch (Exception e) | ||
|  | 		{ | ||
|  | 			System.out.println("ERROR: Could not close open resources.");		 | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	private static void ProgramFirmware(RandomAccessFile inFile, Receiver midiOut, MIDIMessageReceiver midiInMessages) | ||
|  | 	{ | ||
|  | 		try | ||
|  | 		{ | ||
|  | 			System.out.println("Entering Programming Mode..."); | ||
|  | 			sendByteViaMIDI(midiOut, MIDI_CONTROL_CHANNEL, CONTROL_ENTER_PROG_MODE); | ||
|  | 			 | ||
|  | 			int[] messageData; | ||
|  | 			do | ||
|  | 			{ | ||
|  | 				messageData = receiveByteViaMIDI(midiInMessages); | ||
|  | 			} | ||
|  | 			while ((messageData[0] != MIDI_CONTROL_CHANNEL) && (messageData[1] != CONTROL_DEVICE_READY)); | ||
|  | 			 | ||
|  | 			System.out.println("Getting Page Size..."); | ||
|  | 			sendByteViaMIDI(midiOut, MIDI_CONTROL_CHANNEL, CONTROL_GET_PAGE_SIZE); | ||
|  | 
 | ||
|  | 			int nextByte = inFile.read(); | ||
|  | 			while (nextByte != -1) | ||
|  | 			{ | ||
|  | 				sendByteViaMIDI(midiOut, 9, nextByte); | ||
|  | 
 | ||
|  | 				if ((inFile.getFilePointer() % (inFile.length() / 100)) == 0) | ||
|  | 					System.out.println("  LOADING: " + (int)(inFile.getFilePointer() / (inFile.length() / 100.0)) + "%..."); | ||
|  | 
 | ||
|  | 				nextByte = inFile.read(); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			sendByteViaMIDI(midiOut, MIDI_CONTROL_CHANNEL, CONTROL_LEAVE_PROG_MODE); | ||
|  | 		} | ||
|  | 		catch (Exception e) | ||
|  | 		{ | ||
|  | 			System.out.println("ERROR: Could not send data to device.");		 | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	private static void sendByteViaMIDI(Receiver midiOut, int channel, int data) | ||
|  | 	{ | ||
|  | 		ShortMessage sendMessage = new ShortMessage(); | ||
|  | 		 | ||
|  | 		try | ||
|  | 		{ | ||
|  | 			sendMessage.setMessage(ShortMessage.NOTE_ON, channel, (data & 0x7F), (((data & 0x80) == 0x80) ? 64 : 32)); | ||
|  | 			midiOut.send(sendMessage, -1); | ||
|  | 
 | ||
|  | //			try {Thread.sleep(1);} catch (Exception e) {}
 | ||
|  | 
 | ||
|  | 			sendMessage.setMessage(ShortMessage.NOTE_OFF, channel, (data & 0x7F), (((data & 0x80) == 0x80) ? 64 : 32)); | ||
|  | 			midiOut.send(sendMessage, -1); | ||
|  | 		} | ||
|  | 		catch (Exception e) | ||
|  | 		{ | ||
|  | 			System.out.println("ERROR: Could not send MIDI note press."); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	private static int[] receiveByteViaMIDI(MIDIMessageReceiver midiInReceiver) | ||
|  | 	{ | ||
|  | 		byte[] messageData; | ||
|  | 		 | ||
|  | 		do | ||
|  | 		{ | ||
|  | 			while (!(midiInReceiver.hasReceived())); | ||
|  | 			messageData = midiInReceiver.receive().getMessage(); | ||
|  | 		} | ||
|  | 		while ((messageData[0] & 0xF0) != ShortMessage.NOTE_ON); | ||
|  | 	 | ||
|  | 		int channel = (messageData[0] & 0x0F); | ||
|  | 		int data    = (messageData[1] | ((messageData[2] == 64) ? 0x80 : 0x00)); | ||
|  | 		 | ||
|  | 		int[] formattedMessageData = new int[2]; | ||
|  | 		formattedMessageData[0] = channel; | ||
|  | 		formattedMessageData[1] = data; | ||
|  | 	 | ||
|  | 		return formattedMessageData; | ||
|  | 	} | ||
|  | } |