MCU: add iCON V1-M support

This commit is contained in:
Franke Burgarino 2025-10-02 17:10:07 -05:00
parent 6d9df568fe
commit 833d4142b1
7 changed files with 111 additions and 12 deletions

View file

@ -61,6 +61,7 @@ DeviceInfo::DeviceInfo()
, _uses_ipmidi (false) , _uses_ipmidi (false)
, _no_handshake (false) , _no_handshake (false)
, _is_qcon(false) , _is_qcon(false)
, _is_v1m(false)
, _is_platformMp(false) , _is_platformMp(false)
, _is_proG2(false) , _is_proG2(false)
, _is_xtouch(false) , _is_xtouch(false)
@ -347,6 +348,12 @@ DeviceInfo::set_state (const XMLNode& node, int /* version */)
_is_qcon = false; _is_qcon = false;
} }
if ((child = node.child ("IsV1M")) != 0) {
child->get_property ("value", _is_v1m);
} else {
_is_v1m = false;
}
if ((child = node.child ("IsXTouch")) != 0) { if ((child = node.child ("IsXTouch")) != 0) {
child->get_property ("value", _is_xtouch); child->get_property ("value", _is_xtouch);
} else { } else {
@ -525,6 +532,12 @@ DeviceInfo::is_qcon () const
return _is_qcon; return _is_qcon;
} }
bool
DeviceInfo::is_v1m () const
{
return _is_v1m;
}
bool DeviceInfo::is_platformMp () const bool DeviceInfo::is_platformMp () const
{ {
return _is_platformMp; return _is_platformMp;

View file

@ -80,6 +80,7 @@ class DeviceInfo
bool uses_ipmidi() const; bool uses_ipmidi() const;
bool no_handshake() const; bool no_handshake() const;
bool is_qcon() const; bool is_qcon() const;
bool is_v1m() const;
bool is_platformMp() const; bool is_platformMp() const;
bool is_proG2() const; bool is_proG2() const;
bool is_xtouch() const; bool is_xtouch() const;
@ -116,6 +117,7 @@ class DeviceInfo
bool _uses_ipmidi; bool _uses_ipmidi;
bool _no_handshake; bool _no_handshake;
bool _is_qcon; bool _is_qcon;
bool _is_v1m;
bool _is_platformMp; bool _is_platformMp;
bool _is_proG2; bool _is_proG2;
bool _is_xtouch; bool _is_xtouch;

View file

@ -108,7 +108,7 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<MACKIE_N
, _controls_locked (false) , _controls_locked (false)
, _transport_is_rolling (false) , _transport_is_rolling (false)
, _metering_active (true) , _metering_active (true)
, _lcd2_available (true) , _lcd2_available (false)
, _lcd2_label_pitch (7) , _lcd2_label_pitch (7)
, _block_screen_redisplay_until (0) , _block_screen_redisplay_until (0)
, return_to_vpot_mode_display_at (UINT64_MAX) , return_to_vpot_mode_display_at (UINT64_MAX)
@ -128,9 +128,9 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<MACKIE_N
if (s.mcp().device_info().has_qcon_second_lcd()) { if (s.mcp().device_info().has_qcon_second_lcd()) {
_lcd2_available = true; _lcd2_available = true;
// The main unit has 9 faders under the second display. // The Qcon Pro X has 9 faders under the second display.
// Extenders have 8 faders. // Extenders have 8 faders.
if (s.number() == s.mcp().device_info().master_position()) { if (s.mcp().device_info().is_qcon() && s.number() == s.mcp().device_info().master_position()) {
_lcd2_label_pitch = 6; _lcd2_label_pitch = 6;
} }
} }
@ -947,31 +947,44 @@ Strip::redisplay (PBD::microseconds_t now, bool force)
_block_screen_redisplay_until = 0; _block_screen_redisplay_until = 0;
} }
bool changed = false;
if (force || (current_display[0] != pending_display[0])) { if (force || (current_display[0] != pending_display[0])) {
_surface->write (display (0, 0, pending_display[0])); _surface->write (display (0, 0, pending_display[0]));
current_display[0] = pending_display[0]; current_display[0] = pending_display[0];
changed = true;
} }
if (return_to_vpot_mode_display_at <= now) { if (return_to_vpot_mode_display_at <= now) {
return_to_vpot_mode_display_at = UINT64_MAX; return_to_vpot_mode_display_at = UINT64_MAX;
return_to_vpot_mode_display (); return_to_vpot_mode_display ();
changed = true;
} }
if (force || (current_display[1] != pending_display[1])) { if (force || (current_display[1] != pending_display[1])) {
_surface->write (display (0, 1, pending_display[1])); _surface->write (display (0, 1, pending_display[1]));
current_display[1] = pending_display[1]; current_display[1] = pending_display[1];
changed = true;
} }
if (_lcd2_available) { if (_lcd2_available) {
if (force || (lcd2_current_display[0] != lcd2_pending_display[0])) { if (force || (lcd2_current_display[0] != lcd2_pending_display[0])) {
_surface->write (display (1, 0, lcd2_pending_display[0])); _surface->write (display (1, 0, lcd2_pending_display[0]));
lcd2_current_display[0] = lcd2_pending_display[0]; lcd2_current_display[0] = lcd2_pending_display[0];
changed = true;
} }
if (force || (lcd2_current_display[1] != lcd2_pending_display[1])) { if (force || (lcd2_current_display[1] != lcd2_pending_display[1])) {
_surface->write (display (1, 1, lcd2_pending_display[1])); _surface->write (display (1, 1, lcd2_pending_display[1]));
lcd2_current_display[1] = lcd2_pending_display[1]; lcd2_current_display[1] = lcd2_pending_display[1];
changed = true;
} }
} }
/* The iCON V1-M cannot handle many messages in quick succession.
*
* A small delay is necessary to ensure none are skipped.
*/
if (_surface->mcp().device_info().is_v1m() && changed) { g_usleep(2500); }
} }
void void
@ -1045,6 +1058,12 @@ Strip::zero ()
lcd2_current_display[1] = string(); lcd2_current_display[1] = string();
} }
/* The iCON V1-M cannot handle many messages in quick succession.
*
* A small delay is necessary to ensure none are skipped.
*/
if (_surface->mcp().device_info().is_v1m()) { g_usleep(5000); }
} }
MidiByteArray MidiByteArray
@ -1093,18 +1112,23 @@ Strip::display (uint32_t lcd_number, uint32_t line_number, const std::string& li
// code for display // code for display
retval << 0x13; retval << 0x13;
if (lcd_label_pitch == 6) { if (_index == 0 && lcd_label_pitch == 6) {
if (_index == 0) { add_left_pad_char = true;
add_left_pad_char = true; } else if (_index != 0) {
} left_pad_offset = 1;
else {
left_pad_offset = 1;
}
} }
} }
// offset (0 to 0x37 first line, 0x38 to 0x6f for second line) // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
retval << (_index * lcd_label_pitch + (line_number * 0x38) + left_pad_offset); if (_surface->mcp().device_info().is_v1m() && lcd_number == 1) {
if (line_number == 0) {
retval << (_index * (lcd_label_pitch - 1) + (line_number * 0x38) + left_pad_offset);
} else {
retval << (_index * lcd_label_pitch + (line_number * 0x38));
}
} else {
retval << (_index * lcd_label_pitch + (line_number * 0x38) + left_pad_offset);
}
if (add_left_pad_char) { if (add_left_pad_char) {
retval << ' '; // add the left pad space retval << ' '; // add the left pad space

View file

@ -139,8 +139,8 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
if ( is_qcon ) { if ( is_qcon ) {
_has_master_display = (mcp.device_info().has_master_fader() && mcp.device_info().has_qcon_second_lcd()); _has_master_display = (mcp.device_info().has_master_fader() && mcp.device_info().has_qcon_second_lcd());
_has_master_meter = mcp.device_info().has_qcon_master_meters();
} }
_has_master_meter = mcp.device_info().has_qcon_master_meters();
if (_mcp.device_info().has_global_controls()) { if (_mcp.device_info().has_global_controls()) {
init_controls (); init_controls ();

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<MackieProtocolDevice>
<Name value="iCON V1-M + V1-X on right"/>
<Strips value="8"/>
<Extenders value="1"/>
<MasterPosition value="1"/>
<MasterFader value="yes"/>
<TimecodeDisplay value="yes"/>
<TwoCharacterDisplay value="no"/>
<HasSeparateMeters value="yes"/>
<GlobalControls value="yes"/>
<JogWheel value="yes"/>
<TouchSenseFaders value="yes"/>
<LogicControlButtons value="yes"/>
<usesIPMIDI value="no"/>
<NoHandShake value="yes"/>
<IsV1M value="yes"/>
<HasQConSecondLCD value="yes"/>
<HasQConMasterMeters value="yes"/>
</MackieProtocolDevice>

20
share/mcp/v1-m.device Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<MackieProtocolDevice>
<Name value="iCON V1-M"/>
<Strips value="8"/>
<Extenders value="0"/>
<MasterPosition value="0"/>
<MasterFader value="yes"/>
<TimecodeDisplay value="yes"/>
<TwoCharacterDisplay value="no"/>
<HasSeparateMeters value="yes"/>
<GlobalControls value="yes"/>
<JogWheel value="yes"/>
<TouchSenseFaders value="yes"/>
<LogicControlButtons value="yes"/>
<usesIPMIDI value="no"/>
<NoHandShake value="yes"/>
<IsV1M value="yes"/>
<HasQConSecondLCD value="yes"/>
<HasQConMasterMeters value="yes"/>
</MackieProtocolDevice>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<MackieProtocolDevice>
<Name value="iCON V1-M + V1-X on left"/>
<Strips value="8"/>
<Extenders value="1"/>
<MasterPosition value="2"/>
<MasterFader value="yes"/>
<TimecodeDisplay value="yes"/>
<TwoCharacterDisplay value="no"/>
<HasSeparateMeters value="yes"/>
<GlobalControls value="yes"/>
<JogWheel value="yes"/>
<TouchSenseFaders value="yes"/>
<LogicControlButtons value="yes"/>
<usesIPMIDI value="no"/>
<NoHandShake value="yes"/>
<IsV1M value="yes"/>
<HasQConSecondLCD value="yes"/>
<HasQConMasterMeters value="yes"/>
</MackieProtocolDevice>