Design Docs - Sammy1Am/Moppy2 GitHub Wiki
A working draft the the design for Moppy 2.0
The general goals of Moppy 2.0 are:
- To modularize the code a bit (i.e. breaking core functionality into a separate library)
- Improve user experience (i.e. better GUI, easier setup)
- Support more musical devices (e.g. stepper motors, relays, HDDs) on more platforms (e.g. Raspberry Pi, Python)
To that end, the plan is to create slightly more robust message protocol that offloads a tiny bit more logic onto the device-side of things, to free up the controller library to be a little more generic. The GUI will be rewritten separate from the core logic code, and also allow remote configuration of the receiving devices. And generally the project is going to be restructured a little to allow contributions for other platforms and instruments.
Moppy messages have a 4 byte preamble, followed by a 1+ byte message body
Byte | Required? | Example | Contents |
---|---|---|---|
Start of Message | Yes | 01001101 |
Always contains 01001101 and marks the start of a Moppy message |
Device Address | Yes |
00000001 (Device id 1) 00000000 (System message) |
First half of device address. 00000000 indicates a system-wide message. |
Sub-address | Yes |
00000011 (Sub-address 3) |
Second half of device address. Ignored if the previous byte is 00000000 indicating a system message. By convention, the first sub-address should be 00000001 , and 00000000 should be reserved for device-wide commands. |
Length | Yes |
00000010 (Two byte body) |
Indicates the number of bytes following this byte that make up the message body. For example, a command with two payload bytes would have a length of 3. |
Command | Yes | 00001010 |
The command for this message (see table below) |
Payload | No | 01101011 00100010 ... |
Zero or more bytes containing relevant payload information for the given command. |
These commands should be addressed to 00000000
(the sub-address should be ignored). Where possible commands are maped from relatively-equivalent MIDI commands (e.g. Start and Stop sequence) to ease conversion.
Command | Command Byte | Payload Bytes | Description |
---|---|---|---|
Ping | 0x80 |
None | Requests a pong message from any Moppy devices on the network |
Pong | 0x81 |
[DeviceAddress] [MinSubAddress] [MaxSubAddress]
|
A pong message returned by devices when requested by the controller. The first payload byte indicates the device address, the second indicates the minimum subAddress (not including 0x00, which is a special case), and the third the max subAddress. Note: It is allowed for multiple devices to have the same address, possibly with a different range of sub-addresses |
Reset | 0xff |
None | Instructs all devices to halt, and return to start / ready state |
Sequence Start | 0xfa |
None | Informs all devices that a sequence has started (should precede note messages) |
Sequence Stop | 0xfc |
None | Informs all devices that the sequence has stopped. Devices should halt, but not necessarily reset to their start / ready state |
These commands should be addressed to both a device-address and a sub-address. A sub-address of 0x00
indicates that the command is meant as a device-level command (e.g. The reset command should probably reset the whole device instead of just one sub-address), but actual implementation may vary. Where applicable, commands are mapped from the first four bits of the equivalent MIDI command (e.g. MIDI's 1001nnnn
Note On is mapped to 0x09
, Play Note)
Command | Command Byte | Payload Bytes | Description |
---|---|---|---|
Reset | 0x00 |
None | Instructs device to halt and reset itself to a start / ready state |
Stop Note | 0x08 |
[Note Number] |
Stops playing the indicated note |
Play Note | 0x09 |
[Note Number] [Velocity]
|
Plays note indicated by number (which aligns to the MIDI note numbering standard). MIDI supports only notes 0-127, so any numbers above 128 are probably undefined (but could be used?). Velocity is likewise from 1-127 (0 velocity is remapped as a Stop Note event) |
Bend Pitch | 0x0e |
[MSB][LSB] |
Bends the pitch of note on this device interpreting the two payload bytes as a signed 16-bit integer. The actual bending procedure is a bit funky and left up to the implementer. |