Skip to content
Benjamin Klum edited this page Mar 12, 2025 · 4 revisions
Support

Unofficial

Programming the display

There’s no built-in support for programming the display of the EC4. But you can add support for it manually by using ReaLearn’s MIDI script source.

If you are in a hurry and want something printed onto the display right away, just copy below Quick start - Main compartment preset code to the clipboard and import it into ReaLearn via Import from clipboard. Don’t forget to choose the Faderfox EC4 as output device! You should see "Hello world!" written on the display. Then edit the mapping and enter arbitrary text in the Glue section. If you want the text to be dynamic, read more about Text feedback, which is a general device-agnostic concept in ReaLearn (programming which text to display is not specific to the EC4 …​ it works the same no matter which device you use).

Quick start - Main compartment preset code
{
    kind = "MainCompartment",
    version = "2.18.0-pre.2",
    value = {
        mappings = {
            {
                id = "nZYdVlNrZU9k-o6kaP-2M",
                name = "Set first line of total display",
                source = {
                    kind = "MidiScript",
                    script_kind = "Lua",
                    script = [[
local ec4 = require("compartment").ec4
return {
	address = 0,
	messages = {
        ec4.write_total_display(ec4.default_device_id, 0, 20, y),
        ec4.show_total_display(ec4.default_device_id, true),
    }
}

]],
                },
                glue = {
                    feedback = {
                        kind = "Text",
                        text_expression = "Hello World!",
                    },
                },
                target = {
                    kind = "Dummy",
                },
            },
        },
        common_lua = [[
local module = {}

module.ec4 = {}

local function append_list(t1, t2)
	local n1 = #t1
	for i = 1, #t2 do
		t1[n1 + i] = t2[i]
	end
end

local function encode_as_two_bytes(byte: number)
	local nibble_hi = bit32.rshift(byte, 4)
	local nibble_lo = bit32.band(byte, 0x0F)
	return { 0x20 + nibble_hi, 0x10 + nibble_lo }
end

local function to_text_data(text: string, num_chars: number)
	local bytes = {}
	if text ~= nil then
		for i = 1, num_chars do
			local c = string.byte(text, i)
			-- For now, only accept the following input: SPACE (0x20) to "Z" (0x5A) and "a" (0x61) to "z" (0x7A)
			local is_valid = c ~= nil and ((c >= 0x20 and c <= 0x5A) or (c >= 0x61 and c < 0x7A))
			if not is_valid then
				-- Use space as fallback character
				c = 0x20
			end
            table.insert(bytes, 0x4D)
			append_list(bytes, encode_as_two_bytes(c))
		end
	end
	return bytes
end

local prefix = { 0xF0, 0x00, 0x00, 0x00, 0x4E, 0x2C }
local suffix = { 0xF7 }

--- Writes text to single displays.
function module.ec4.write_ctrl_display(device_id: number, pos: number, len: number, text: string)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, 0x10, 0x4A })
    append_list(msg, encode_as_two_bytes(pos))
	append_list(msg, to_text_data(text, len))
	append_list(msg, suffix)
	return msg
end

--- Writes text to the total display.
function module.ec4.write_total_display(device_id: number, pos: number, len: number, text: string)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, 0x13, 0x4A })
    append_list(msg, encode_as_two_bytes(pos))
	append_list(msg, to_text_data(text, len))
	append_list(msg, suffix)
	return msg
end

--- Shows or hides the total display.
function module.ec4.show_total_display(device_id: number, show: boolean)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, if show then 0x14 else 0x15 })
	append_list(msg, suffix)
	return msg
end

module.ec4.default_device_id = 0x0B

return module
]],
    },
}

Read further if you want to know how to set this up manually, step by step.

Warning
This is advanced territory!

1. Add reusable EC4 display functions

At first, we are going to add some reusable Lua functions to the current compartment by leveraging the compartment-wide Lua code feature.

Choose Menu  Edit compartment-wide Lua code and enter the following code:

See compartment-wide Lua code
local module = {}

module.ec4 = {}

local function append_list(t1, t2)
	local n1 = #t1
	for i = 1, #t2 do
		t1[n1 + i] = t2[i]
	end
end

local function encode_as_two_bytes(byte: number)
	local nibble_hi = bit32.rshift(byte, 4)
	local nibble_lo = bit32.band(byte, 0x0F)
	return { 0x20 + nibble_hi, 0x10 + nibble_lo }
end

local function to_text_data(text: string, num_chars: number)
	local bytes = {}
	if text ~= nil then
		for i = 1, num_chars do
			local c = string.byte(text, i)
			-- For now, only accept the following input: SPACE (0x20) to "Z" (0x5A) and "a" (0x61) to "z" (0x7A)
			local is_valid = c ~= nil and ((c >= 0x20 and c <= 0x5A) or (c >= 0x61 and c < 0x7A))
			if not is_valid then
				-- Use space as fallback character
				c = 0x20
			end
            table.insert(bytes, 0x4D)
			append_list(bytes, encode_as_two_bytes(c))
		end
	end
	return bytes
end

local prefix = { 0xF0, 0x00, 0x00, 0x00, 0x4E, 0x2C }
local suffix = { 0xF7 }

--- Writes text to single displays.
function module.ec4.write_ctrl_display(device_id: number, pos: number, len: number, text: string)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, 0x10, 0x4A })
    append_list(msg, encode_as_two_bytes(pos))
	append_list(msg, to_text_data(text, len))
	append_list(msg, suffix)
	return msg
end

--- Writes text to the total display.
function module.ec4.write_total_display(device_id: number, pos: number, len: number, text: string)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, 0x13, 0x4A })
    append_list(msg, encode_as_two_bytes(pos))
	append_list(msg, to_text_data(text, len))
	append_list(msg, suffix)
	return msg
end

--- Shows or hides the total display.
function module.ec4.show_total_display(device_id: number, show: boolean)
	local msg = {}
	append_list(msg, prefix)
	append_list(msg, { 0x10 + device_id, 0x4E, 0x22, if show then 0x14 else 0x15 })
	append_list(msg, suffix)
	return msg
end

module.ec4.default_device_id = 0x0B

return module

2. Use the functions in your mappings

Below is a single example mapping which leverages the functions that we added in the previous step. You can import this mapping by copying the code below, adding a mapping row in ReaLearn, right-clicking the mapping row and choosing Advanced  Paste from Lua (replace).

See example mapping code
{
    kind = "Mapping",
    version = "2.18.0-pre.2",
    value = {
        name = "Set first line of total display",
        source = {
            kind = "MidiScript",
            script_kind = "Lua",
            script = [[
local ec4 = require("compartment").ec4
return {
	address = 0,
	messages = {
        ec4.write_total_display(ec4.default_device_id, 0, 20, y),
        ec4.show_total_display(ec4.default_device_id, true),
    }
}

]],
        },
        glue = {
            feedback = {
                kind = "Text",
                text_expression = "Hello World!",
            },
        },
        target = {
            kind = "Dummy",
        },
    },
}

Have a look into the MIDI source script of that mapping! The code there uses the functions write_total_display and show_total_display (passing true) to print the text "Hello World!" to the first line of the display. You can also use write_ctrl_display and show_total_display (passing false) to target displays of single controls. Both functions write_total_display and write_ctrl_display expect 4 parameters:

  1. device_id: The device ID

  2. pos: Start position in characters (from the upper-left)

  3. len: Length of the text that you want to write, in characters

  4. text: The actual text. You probably want to pass y here, which makes the text dynamic.

Clone this wiki locally