diff --git a/.gitignore b/.gitignore index 6143e53..e2d80c3 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,10 @@ *.tar.gz *.rar +# Gradle Artifacts # +**/.gradle/** + # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +/Java/MoppyLib/.nb-gradle/ +/Java/MoppyLib/build/ \ No newline at end of file diff --git a/Arduino/FloppyDrives/README.md b/Arduino/FloppyDrives/README.md new file mode 100644 index 0000000..3391e61 --- /dev/null +++ b/Arduino/FloppyDrives/README.md @@ -0,0 +1,2 @@ +# MoppyLib +Library for core Moppy logic. diff --git a/Java/MoppyControlGUI/README.md b/Java/MoppyControlGUI/README.md new file mode 100644 index 0000000..2dadeb2 --- /dev/null +++ b/Java/MoppyControlGUI/README.md @@ -0,0 +1,2 @@ +# MoppyControlGUI +Java GUI for controlling a Moppy network. diff --git a/Java/MoppyDeviceGUI/README.md b/Java/MoppyDeviceGUI/README.md new file mode 100644 index 0000000..5b50b2e --- /dev/null +++ b/Java/MoppyDeviceGUI/README.md @@ -0,0 +1,2 @@ +# MoppyDeviceGUI +A simulated moppy device that can be used for testing. diff --git a/Java/MoppyLib/README.md b/Java/MoppyLib/README.md new file mode 100644 index 0000000..3ebc6ea --- /dev/null +++ b/Java/MoppyLib/README.md @@ -0,0 +1,2 @@ +# FloppyDrives.ino +Arduino sketch for controlling floppy drives using Moppy. diff --git a/Java/MoppyLib/build.gradle b/Java/MoppyLib/build.gradle new file mode 100644 index 0000000..7aa7170 --- /dev/null +++ b/Java/MoppyLib/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'java' + +sourceCompatibility = '1.8' +[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' + +// NetBeans will automatically add "run" and "debug" tasks relying on the +// "mainClass" property. You may however define the property prior executing +// tasks by passing a "-PmainClass=" argument. +// +// Note however, that you may define your own "run" and "debug" task if you +// prefer. In this case NetBeans will not add these tasks but you may rely on +// your own implementation. +if (!hasProperty('mainClass')) { + ext.mainClass = '' +} + +repositories { + mavenCentral() + // You may define additional repositories, or even remove "mavenCentral()". + // Read more about repositories here: + // http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:repositories +} + +dependencies { + // TODO: Add dependencies here ... + // You can read more about how to add dependency here: + // http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies + testCompile group: 'junit', name: 'junit', version: '4.10' +} diff --git a/Java/MoppyLib/settings.gradle b/Java/MoppyLib/settings.gradle new file mode 100644 index 0000000..2ec408a --- /dev/null +++ b/Java/MoppyLib/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'MoppyLib' diff --git a/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessage.java b/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessage.java new file mode 100644 index 0000000..00351f5 --- /dev/null +++ b/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessage.java @@ -0,0 +1,74 @@ +package com.moppy.core.comm; + +import java.util.Arrays; + +/** + * Represents a message suitable for sending to a Moppy network. + * + * NOTE: Java treats ALL bytes as signed, but we're using them unsigned. Casts / conversions will be required! + */ +public class MoppyMessage { + private final byte[] messageBytes; + + public static final byte START_BYTE = (byte)0x4d; + public static final byte SYSTEM_ADDRESS = (byte)0x00; + + public static final MoppyMessage SYS_PING = new MoppyMessage(new byte[]{ + START_BYTE, // Start byte + SYSTEM_ADDRESS, // System address + 0x01, // Message body size + CommandByte.SYS_PING}); // Ping command + public static final MoppyMessage SYS_RESET = new MoppyMessage(new byte[]{START_BYTE, SYSTEM_ADDRESS, 0x01, CommandByte.SYS_RESET}); + public static final MoppyMessage SYS_START = new MoppyMessage(new byte[]{START_BYTE, SYSTEM_ADDRESS, 0x01, CommandByte.SYS_START}); + public static final MoppyMessage SYS_STOP = new MoppyMessage(new byte[]{START_BYTE, SYSTEM_ADDRESS, 0x01, CommandByte.SYS_STOP}); + + + protected MoppyMessage(byte[] messageBytes) { + if (messageBytes.length < 4) { + throw new IllegalArgumentException("Not enough bytes for a MoppyMessage!"); + } + + this.messageBytes = messageBytes; + } + + public static class CommandByte { + public static byte SYS_PING = (byte)0x80; + public static byte SYS_PONG = (byte)0x81; + public static byte SYS_RESET = (byte)0x82; + public static byte SYS_START = (byte)0x83; + public static byte SYS_STOP = (byte)0x84; + + public static byte DEV_RESET = 0x00; + public static byte DEV_PLAYNOTE = 0x01; + public static byte DEV_STOPNOTE = 0x02; + public static byte DEV_BENDPITCH = 0x03; + } + + public byte[] getMessageBytes(){ + return messageBytes; + } + + public byte getDeviceAddress() { + return messageBytes[1]; + } + + public boolean isSystemMessage() { + return getDeviceAddress() == SYSTEM_ADDRESS; + } + + public byte getSubAddress() { + if (isSystemMessage()) { + throw new IllegalStateException("This is a system message and has no sub-address"); + } else { + return messageBytes[2]; + } + } + + public byte[] getMessageBody() { + int bodyLength = isSystemMessage() ? messageBytes[2] : messageBytes[3]; + int bodyStart = isSystemMessage() ? 3 : 4; + return Arrays.copyOfRange(messageBytes, bodyStart, bodyStart + bodyLength); + } + + +} diff --git a/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessageFactory.java b/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessageFactory.java new file mode 100644 index 0000000..9283ae9 --- /dev/null +++ b/Java/MoppyLib/src/main/java/com/moppy/core/comm/MoppyMessageFactory.java @@ -0,0 +1,34 @@ +package com.moppy.core.comm; + +import static com.moppy.core.comm.MoppyMessage.CommandByte.DEV_PLAYNOTE; +import static com.moppy.core.comm.MoppyMessage.CommandByte.DEV_RESET; +import static com.moppy.core.comm.MoppyMessage.CommandByte.DEV_STOPNOTE; +import static com.moppy.core.comm.MoppyMessage.CommandByte.SYS_PONG; +import static com.moppy.core.comm.MoppyMessage.START_BYTE; +import static com.moppy.core.comm.MoppyMessage.SYSTEM_ADDRESS; + +/** + * Class for building common MoppyMessages. + */ +public class MoppyMessageFactory { + public static MoppyMessage systemPong(byte deviceAddress, byte numberOfSubAddresses) { + return new MoppyMessage(new byte[]{START_BYTE, SYSTEM_ADDRESS, 0x03, SYS_PONG, deviceAddress, numberOfSubAddresses}); + } + + public static MoppyMessage deviceReset(byte deviceAddress) { + return new MoppyMessage(new byte[]{START_BYTE, deviceAddress, 0x00, 0x01, DEV_RESET}); + } + + public static MoppyMessage devicePlayNote(byte deviceAddress, byte subAddress, byte noteNumber) { + return new MoppyMessage(new byte[]{START_BYTE, deviceAddress, subAddress, 0x02, DEV_PLAYNOTE, noteNumber}); + } + + public static MoppyMessage deviceStopNote(byte deviceAddress, byte subAddress, byte noteNumber) { + return new MoppyMessage(new byte[]{START_BYTE, deviceAddress, subAddress, 0x02, DEV_STOPNOTE, noteNumber}); + } + + public static MoppyMessage devicePitchBend(byte deviceAddress, byte subAddress, short bendAmount) { + return new MoppyMessage(new byte[]{START_BYTE, deviceAddress, subAddress, 0x03, DEV_STOPNOTE, + (byte)((bendAmount >> 8) & 0xff), (byte)(bendAmount & 0xff)}); + } +} diff --git a/Python/delete.me b/Python/delete.me new file mode 100644 index 0000000..5897633 --- /dev/null +++ b/Python/delete.me @@ -0,0 +1 @@ +Placeholder to show where Python Moppy projects should go. Can be removed once the first project exists. \ No newline at end of file diff --git a/RaspPi/delete.me b/RaspPi/delete.me new file mode 100644 index 0000000..e2bc9a2 --- /dev/null +++ b/RaspPi/delete.me @@ -0,0 +1 @@ +Placeholder to show where Raspberry Pi Moppy projects should go. Can be removed once the first project exists. \ No newline at end of file