poly-1-fw/sysex.hpp

99 lines
4.0 KiB
C++

// intellectual property is bullshit bgdc
#ifndef SYSEX_HPP
#define SYSEX_HPP
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#include "midi.hpp"
// All sysex messages start with manuf id 7D (prototyping, test, private use,
// and experimentation).
//
//
// 7D 01 - storage commands
// 7D 02 - front panel controls
// 7D 7F - status codes
//
//
// -- Storage commands --
//
// Storage commands interface with the onboard storage (SD card). Large
// arguments are generally encoded using base64, while smaller arguments are
// generally ascii hex.
//
// 7D 01 01 cksum ... - data response message, base64
// 7D 01 02 AAAAAAAA - request SD block AAA... (hex, data sent via 7D 01 01)
// 7D 01 03 AAAAAAAA - open SD block AAA... for write (hex). If a
// write is ongoing, will return STATUS_BUSY.
// 7D 01 04 cksum ... - append data to the write buffer.
// 7D 01 05 - commit the in-progress write
// 7D 01 06 - cancel the in-progress write
//
// -- Status codes --
// 7D 7F 01 - general ACK
// 7D 7F 02 - message format error
//
//
// == Writing data to storage ==
//
// To write a sector to the storage card, the sector must be opened using
// MIDI_SYSEX_STORAGE_OPENWR. The argument is a 32-bit (hex encoded) sector
// number, in 512-byte sectors. Following this, MIDI_SYSEX_STORAGE_WRDATA is
// sent repeatedly to append data to the write buffer. This data is encoded
// using base64, and up to (MIDIX_SYSEX_LEN - 8) base64 characters representing
// 42 bytes of data (assuming MIDIX_SYSEX_LEN is 64) may be sent at once. If
// more than 512 bytes are sent, the extras are dropped; if fewer than 512
// bytes are sent, the sector is padded with undefined data. Once the write
// buffer is full, commit it with MIDI_SYSEX_STORAGE_COMMIT or cancel the
// write with MIDI_SYSEX_STORAGE_CANCEL. TODO: add a command to query this
// length limit
//
// No matter how many midi ports exist on the system, there is only one storage
// buffer, so you must expect to receive MIDI_SYSEX_STATUS_BUSY in response to
// OPENWR. In this case, poll with the same message to await completion. A user-
// confirmed hard cancel may be performed by sending MIDI_SYSEX_STORAGE_CANCEL
// (this can cancel the buffer regardless of which interface holds it).
//
// == Reading data from storage ==
//
// To read a sector from the storage card, send the sector number in the same
// format as for a write, using MIDI_SYSEX_STORAGE_READ. The data will be sent
// back in a series of MIDI_SYSEX_STORAGE_RESPONSE packets, followed by a
// MIDI_SYSEX_STATUS_ACK to acknowledge completion, or a MIDI_SYSEX_STATUS_IOERR
// at any point to terminate the process and report an error.
//
// == Storage checksums ==
//
// Both MIDI_SYSEX_STORAGE_RESPONSE and MIDI_SYSEX_STORAGE_WRDATA contain a
// checksum byte. This byte is simply the bit-inverted lower 7 bits of the sum
// of all data bytes in the message, prior to encoding as base64. If you send
// data and it is received with a bad checksum, a MIDI_SYSEX_STATUS_CKSUM will
// be sent back to you; you must cancel the write operation and retry it.
// If you receive a bad checksum, your recourse is to request it again.
#define MIDI_MANUF_ID 0x7D
#define MIDI_SYSEX_STORAGE_GRP 0x01
#define MIDI_SYSEX_STORAGE_RESPONSE 0x01
#define MIDI_SYSEX_STORAGE_READ 0x02
#define MIDI_SYSEX_STORAGE_OPENWR 0x03
#define MIDI_SYSEX_STORAGE_WRDATA 0x04
#define MIDI_SYSEX_STORAGE_COMMIT 0x05
#define MIDI_SYSEX_STORAGE_CANCEL 0x06
#define MIDI_SYSEX_STATUS_GRP 0x7F
#define MIDI_SYSEX_STATUS_ACK 0x01
#define MIDI_SYSEX_STATUS_FMT_ERR 0x02
#define MIDI_SYSEX_STATUS_UNKNOWN 0x03
#define MIDI_SYSEX_STATUS_BUSY 0x04
#define MIDI_SYSEX_STATUS_IOERR 0x05
#define MIDI_SYSEX_STATUS_CKSUM 0x06
// Handle a sysex message
void sysex_handle(struct midi_message const * msg);
#endif // !defined(SYSEX_HPP)