Hoff Solo

User Manual

Overview

  • The Hoff Solo is a programmable MIDI master clock and controller.
  • It is based on a Raspberry Pi W micro-controller, which featues two cores and two hardware UARTS for MIDI control.
  • One core is used for the user interface, whereas the other core is dedicated to controller and MIDI events.
  • The user interface features a full colour resistive touch screen, with two robust and silent switches that can be comfortably operated by foot or hand.
  • Everything is housed in a robust metal enclosure.

Connections

  • There are two DIN-5 MIDI out ports. MIDI can also be sent over USB.
  • It supports MIDI over Bluetooth LE.
  • Two 5V sync outs are available through a 1/8" (3.5mm) TRS socket.
  • Two 1/4" (6.35mm) TRS sockets allow up to four additional foot switches to be connected.
  • Power is supplied through a USB Micro B port, which is also used for firmware & SYSEX updates.

Usage

Preset screen

The preset screen consists of a title area, BPM area and switches area. Press on the screen to select a function.

  • Title area
    • Shows the title of the current preset
    • Short press on the title opens the preset menu screen
    • Long press on the title shows the current preset settings
  • BPM area
    • Shows the current BPM
    • Short press on the BPM expands/shrinks the size of the display
  • Switches area
    • Shows the label of each switch
    • Long press on a label shows the current switch settings

Menu screen

The menu screen shows the list of avalable presets. Press on the screen to select a preset.

System screen

The system screen area shows utility functions.

Programming

Preset programming is done by downloading, modifying and uploading single text file via SYSEX. This text file contains a complete set of presets, with each preset configured through a set of properties.

Each named property is identified with angle brackets <>, followed by a property value. A property value van be either a label, description or an instruction.

There is no closing tag as such - the start of a new property denotes the end of the previous property's value.


<SYSTEM>  //No value - denotes the start of the file, serves to identify the system attributes
<VERSION>DESCR  //The firmware version
<DEFAULT>LABEL  //The label of the preset that is active on startup

<PRESET>  //No value - denotes the start of a new preset
<PST_LBL>LABEL  //The label for this preset
<PST_DSC>DESCR  //The description for this preset
<PST_CLK>INSTR  //The instruction performed with each MIDI clock cycle
<PST_ENT>INSTR  //The instruction performed once when entering this preset
<PST_EXT>INSTR  //The instruction performed once when exiting this preset

<LS0_LBL>LABEL  //The label for the left main switch 0
<LS0_INF>DESCR  //The description for the left main switch 0
<LS0_PRS>INSTR  //The instruction performed when the left main switch 0 is pressed
<LS0_RLS>INSTR  //The instruction performed when the left main switch 0 is released after a short interval
<LS0_RLL>INSTR  //The instruction performed when the left main switch 0 is released after a long interval

<LS1_LBL>LABEL  //The label for the left external switch 1
<LS1_INF>DESCR  //The description for the left external switch 1
<LS1_PRS>INSTR  //The instruction performed when the left external switch 1 is pressed
<LS1_RLS>INSTR  //The instruction performed when the left external switch 1 is released after a short interval
<LS1_RLL>INSTR  //The instruction performed when the left external switch 1 is released after a long interval

<LS2_LBL>LABEL  //The label for the left external switch 2
<LS2_INF>DESCR  //The description for the left external switch 2
<LS2_PRS>INSTR  //The instruction performed when the left external switch 2 is pressed
<LS2_RLS>INSTR  //The instruction performed when the left external switch 2 is released after a short interval
<LS2_RLL>INSTR  //The instruction performed when the left external switch 2 is released after a long interval

<RS0_LBL>LABEL  //The label for the right main switch 0
<RS0_INF>DESCR  //The description for the right main switch 0
<RS0_PRS>INSTR  //The instruction performed when the right main switch 0 is pressed
<RS0_RLS>INSTR  //The instruction performed when the right main switch 0 is released after a short interval
<RS0_RLL>INSTR  //The instruction performed when the right main switch 0 is released after a long interval

<RS1_LBL>LABEL  //The label for the right external switch 1
<RS1_INF>DESCR  //The description for the right external switch 1
<RS1_PRS>INSTR  //The instruction performed when the right external switch 1 is pressed
<RS1_RLS>INSTR  //The instruction performed when the right external switch 1 is released after a short interval
<RS1_RLL>INSTR  //The instruction performed when the right external switch 1 is released after a long interval

<RS2_LBL>LABEL  //The label for the right external switch 2
<RS2_INF>DESCR  //The description for the right external switch 2
<RS2_PRS>INSTR  //The instruction performed when the right external switch 2 is pressed
<RS2_RLS>INSTR  //The instruction performed when the right external switch 2 is released after a short interval
<RS2_RLL>INSTR  //The instruction performed when the right external switch 2 is released after a long interval

The following property values are valid:

LABEL
  • All alphanumerics allowed except for Angle brackets, <> (ASCII 0x20 .. 0x7D, excluding 0x3C and 0x3E)
  • Maximum length is 8 characters
  • Example
    • TRANSPRT
DESCR
  • All alphanumerics allowed except for Angle brackets, <> (ASCII 0x20 .. 0x7D, excluding 0x3C and 0x3E)
  • Maximum length is 255 characters
  • Line breaks can be forced by using \n
  • Example
    • This preset allows the LEFT\n button to set the BPM\nand the RIGHT button to\nstart/stop the transport
INSTR
  • Contains a list of FUNCTIONs, seperated by spaces
  • Maximum length is 255 characters, or 10 FUNCTIONS
  • Example
    • [1,1]MSG_USB(0X90,1,127) [1,1]MSG_LFT(0X90,4,127) [1,1]MSG_RGT(0X90,7,127)
FUNCTION
  • A function consists of an interval and a function name with arguments
  • Maximum length is 255 characters, or 10 FUNCTIONS
  • Interval [index,total]
    • Delimited by square brackets [ ] with two integer arguments, seperated by a comma
    • The first argument is index, specifying on which interval to call the function (1-based)
    • The second argument is total, specifying the total number of intervals (1-based) before starting again at 1
  • Function ???_???(n1,n2,..)
    • The function name is a seven character string consisting of two sets of three characters, seperated by an underscore _
    • The function argument is delimited by round brackets ( ), with arguments seperated by commas
    • Each function takes specific arguments
      • MSG_BLE(n1,n2,n3)
        • Send a MIDI MESSAGE over Bluetooth LE
        • Each argument is a MIDI message byte
        • Takes up to 3 unsigned integer arguments, specified as either decimal or hex (0x00)
      • MSG_USB(n1,n2,n3)
        • Send a MIDI MESSAGE to the USB port
        • Each argument is a MIDI message byte
        • Takes up to 3 unsigned integer arguments, specified as either decimal or hex (0x00)
      • MSG_LFT(n1,n2,n3)
        • Send a MIDI MESSAGE to the left DIN-5 port
        • Each argument is a MIDI message byte
        • Takes up to 3 unsigned integer arguments, specified as either decimal or hex (0x00)
      • MSG_RGT(n1,n2,n3)
        • Send a MIDI MESSAGE to the right DIN-5 port
        • Each argument is a MIDI message byte
        • Takes up to 3 unsigned integer arguments, specified as either decimal or hex (0x00)
      • SET_BPM(n)
        • Sets the MIDI clock to a specified BPM (tempo)
        • The argument is the desired Beats Per Minute (tempo)
        • Takes 1 unsigned integer argument, specified as either decimal or hex (0x00)
      • TAP_BPM(n)
        • Sets the MIDI clock to a BPM (tempo) determined by tap intervals.
        • The argument is a BPM multiplier, multiplying the detected tap tempo by n
        • Takes 1 unsigned integer argument, specified as either decimal or hex (0x00)
      • SET_PST(????????)
        • Switches to the specified preset.
        • The argument is the label of the desired preset.
        • Takes 1 string argument
      • SET_VAR(v,n)
        • Sets a variable (v) to a specified value (n).
        • v is the index of the variable to set [0..9].
        • n is the value (unsigned int) [0..65535].
      • SET_SCx(l,t)
        • Sets a sync output (x) to a specified level value (l), for a duration (t).
        • x is the sync output to set [1..2].
        • l is the level to set: 1 = 5V, 0 = 0V [0..1].
        • t is the duration of the pulse in millisends (unsigned byte) [0..255].
  • Variables
    • There are 10 general purpose variables.
    • Variables are referenced by index no. 0..9, and prefixed with an @ to get their value.
    • You can use the @n variable reference in any function argument, even in SET_VAR if you need complex logic.
    • E.g.
      • Set variable 1 to 120, and use the variable to set the tempo: [1,1]SET_VAR(1,120) [1,1]SET_BPM(@1)
      • Set variable 1 to 5, and set the nth variable to 100: [1,1]SET_VAR(1,5) [1,1]SET_VAR(@1,100)
      • Set variable 3 to 0, and set the interval to 0 (to prevent it from executing): [1,1]SET_VAR(1,0) [@1,1]SET_BPM(100)
    • Example: Send MIDI CLOCK message to USB port, once every clock interval (which is 24x per beat) if using the PST_CLK property
      • [1,1]MSG_USB(0xF8)
    • Example: Send MIDI CLOCK message to left DIN-5 port, every third clock interval (which is 8x per beat) if using the PST_CLK property
      • [1,3]MSG_USB(0xF8)
    • Example: Set tap tempo to double to BPM, i.e. if tap tempo is detected at 100 BPM, it will set the BPM to 200 if using the PST_CLK property
      • [1,1]TAP_BPM(2)