Design Docs - Sammy1Am/Moppy2 GitHub Wiki

A working draft the the design for Moppy 2.0

Overview

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.

Message Protocol

Moppy messages have a 4 byte preamble, followed by a 1+ byte message body

Bytes

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.

Commands

System commands

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

Device commands

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.
⚠️ **GitHub.com Fallback** ⚠️