Skip to content

Commit 9953dc4

Browse files
authored
-esqpanel.cpp: Improved functionality, added three more views, including a working keyboard. (#14455) [CBrunschen]
The panel view is improved after re-measuring on a real keyboard. Colors have been changed a bit in order to improve contrast. Three new views have been added: 1. a Full view of the keyboard, including the controls to the left of the keyboard, specifically the Pitch-Bend and Modulation Wheels and the Patch Select buttons, as well as a representation of the floppy drive and the little "storage compartment" above it that is a bit of a characteristic shape. 2. a "Compact" view that includes all the controls and a 37-key (3-octave) keyboard that may be both legible and playable at the same time, on a reasonably-sized touch screen. 3. a "Tablet" view of the front-panel controls, with the display and buttons stacked vertically instead of stretched horizontally, as well as the "Patch Select" buttons. This view, together with a MIDI keyboard controller, this should give users a reasonably workable facsimile of the real thing: Keys, Pitch Bend and Modulation wheels on their MIDI keyboard controller; all the keyboard-specific controls and the Ensoniq-specific Patch Select buttons on the "Tablet" view. The Full and Compact views also include a keyboard: the full 61 keys and a reduced 37 keys respectively. These work, tracking pointer events, and generate not just key-down events with velocity, but also per-key "pressure" or "aftertouch". Velocity is simulated by position of the click/touch; Pressure by movement of the pointer on the key while down. Both are also animated: Velocity is shown as a colour between blue (1) and green (127), Pressure between yellow (1) and red (127).
1 parent 6fa40f8 commit 9953dc4

File tree

6 files changed

+12724
-3184
lines changed

6 files changed

+12724
-3184
lines changed

src/mame/ensoniq/esqpanel.cpp

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
#include "main.h"
1111

1212
#include "esq2by40_vfx.lh"
13-
#include "sd1.lh"
1413
#include "vfx.lh"
1514
#include "vfxsd.lh"
15+
#include "sd1.lh"
16+
#include "sd132.lh"
1617

1718
#include <algorithm>
1819

@@ -679,6 +680,32 @@ void esqpanel_device::set_button(uint8_t button, bool pressed)
679680
}
680681
}
681682

683+
void esqpanel_device::key_down(uint8_t key, uint8_t velocity)
684+
{
685+
if (velocity < 1)
686+
velocity = 1;
687+
else if (velocity > 127)
688+
velocity = 127;
689+
690+
xmit_char(0x80 | (key & 0x3f));
691+
xmit_char(velocity);
692+
}
693+
694+
void esqpanel_device::key_pressure(uint8_t key, uint8_t pressure)
695+
{
696+
if (pressure > 127)
697+
pressure = 127;
698+
699+
xmit_char(0x40 | (key & 0x3f));
700+
xmit_char(pressure);
701+
}
702+
703+
void esqpanel_device::key_up(uint8_t key)
704+
{
705+
xmit_char(key & 0x3f);
706+
xmit_char(0x40);
707+
}
708+
682709
/* panel with 1x22 VFD display used in the EPS-16 and EPS-16 Plus */
683710

684711
void esqpanel1x22_device::device_add_mconfig(machine_config &config)
@@ -719,8 +746,10 @@ void esqpanel2x40_vfx_device::device_add_mconfig(machine_config &config)
719746
config.set_default_layout(layout_vfx);
720747
else if (m_panel_type == VFX_SD)
721748
config.set_default_layout(layout_vfxsd);
722-
else if (m_panel_type == SD_1 || m_panel_type == SD_1_32)
749+
else if (m_panel_type == SD_1)
723750
config.set_default_layout(layout_sd1);
751+
else if (m_panel_type == SD_1_32)
752+
config.set_default_layout(layout_sd132);
724753
else // lowest common demonimator as the default: just the VFD.
725754
config.set_default_layout(layout_esq2by40_vfx);
726755
}
@@ -752,7 +781,7 @@ bool esqpanel2x40_vfx_device::write_contents(std::ostream &o)
752781
}
753782

754783
void esqpanel2x40_vfx_device::update_lights() {
755-
// set the lights according to their status and bllink phase.
784+
// set the lights according to their status and blink phase.
756785
int32_t lights = 0;
757786
int32_t bit = 1;
758787
for (int i = 0; i < 16; i++)
@@ -763,6 +792,9 @@ void esqpanel2x40_vfx_device::update_lights() {
763792
}
764793
bit <<= 1;
765794
}
795+
// We use the next bit, 16, for the floppy LED
796+
if (m_floppy_active)
797+
lights |= 1 << 16;
766798
m_lights = lights;
767799
}
768800

@@ -810,6 +842,22 @@ static INPUT_PORTS_START(esqpanel2x40_vfx_device)
810842
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::button_change), 32 + i)
811843
}
812844

845+
PORT_START("patch_select")
846+
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD);
847+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::patch_select_change), 1)
848+
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD);
849+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::patch_select_change), 1)
850+
851+
PORT_START("analog_pitch_bend")
852+
PORT_BIT(0x3ff, 0x200, IPT_PADDLE) PORT_NAME("Pitch Bend") PORT_MINMAX(0, 0x3ff) PORT_SENSITIVITY(30) PORT_KEYDELTA(15) PORT_CENTERDELTA(128)
853+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::analog_value_change), 0)
854+
855+
PORT_START("analog_mod_wheel")
856+
// An adjuster, but with range 0 .. 1023, to match the 10 bit resolution of the OTIS ADC
857+
configurer.field_alloc(IPT_ADJUSTER, 0x3ff, 0x3ff, "Modulation");
858+
configurer.field_set_min_max(0, 0x3ff);
859+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::analog_value_change), 2)
860+
813861
PORT_START("analog_data_entry")
814862
// An adjuster, but with range 0 .. 1023, to match the 10 bit resolution of the OTIS ADC
815863
configurer.field_alloc(IPT_ADJUSTER, 0x200, 0x3ff, "Data Entry");
@@ -822,6 +870,19 @@ static INPUT_PORTS_START(esqpanel2x40_vfx_device)
822870
configurer.field_set_min_max(0, 0x3ff);
823871
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::analog_value_change), 5)
824872

873+
for (int i = 0; i < 61; i++) {
874+
std::string port_name = util::string_format("key_%d", i);
875+
PORT_START(port_name.c_str());
876+
PORT_BIT(0x3fff, 0x0, IPT_PADDLE)
877+
PORT_GM_NOTE(36 + i)
878+
879+
// the following must be set ot MAME complains, but we don't use them:
880+
// we always pass the values through explicitly, overriding anything else.
881+
PORT_SENSITIVITY(1) PORT_KEYDELTA(1) PORT_CENTERDELTA(1)
882+
883+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::key_change), i)
884+
}
885+
825886
INPUT_PORTS_END
826887

827888
ioport_constructor esqpanel2x40_vfx_device::device_input_ports() const
@@ -836,13 +897,61 @@ INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::button_change)
836897
esqpanel_device::set_button(param, newval != 0);
837898
}
838899

900+
// A Patch Select button is pressed on the internal panel
901+
INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::patch_select_change)
902+
{
903+
// Update the internal state from the full value of the port: presented as an analog value!
904+
int value = (field.port().read() & 0x03) * 250;
905+
set_analog_value(1, value << 6);
906+
}
907+
839908
// An anlog value was changed on the internal panel
840909
INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::analog_value_change)
841910
{
842911
int channel = param;
843912
int clamped = std::clamp((int)newval, 0, 1023);
844913
int value = clamped << 6;
845-
esqpanel_device::set_analog_value(channel, value);
914+
set_analog_value(channel, value);
915+
}
916+
917+
// An key changed on the internal panel
918+
INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::key_change)
919+
{
920+
uint8_t key = param & 0x3f;
921+
uint8_t velocity = newval & 0x7f;
922+
923+
if (velocity == 0)
924+
{
925+
uint8_t old_pressure = (oldval >> 7) & 0x7f;
926+
if (old_pressure != 0)
927+
{
928+
// there was pressure before; reset the pressure to zero before the key-up event.
929+
key_pressure(key, 0);
930+
}
931+
key_up(key);
932+
}
933+
else
934+
{
935+
uint8_t old_velocity = oldval & 0x7f;
936+
uint8_t pressure = (newval >> 7) & 0x7f;
937+
938+
if (old_velocity == 0)
939+
{
940+
// this is a key down event. Might also include an ensuing pressure event.
941+
key_down(key, velocity);
942+
}
943+
944+
if (pressure != 0)
945+
{
946+
// if we have pressure, then it is (also) a pressure event.
947+
key_pressure(key, pressure);
948+
}
949+
}
950+
}
951+
952+
void esqpanel2x40_vfx_device::set_floppy_active(bool floppy_active) {
953+
m_floppy_active = floppy_active;
954+
update_lights();
846955
}
847956

848957
ioport_value esqpanel2x40_vfx_device::get_adjuster_value(required_ioport &ioport)

src/mame/ensoniq/esqpanel.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ class esqpanel_device : public device_t, public device_serial_interface
3434
void xmit_char(uint8_t data);
3535
virtual void set_analog_value(offs_t offset, uint16_t value);
3636
virtual void set_button(uint8_t button, bool pressed);
37+
virtual void key_down(uint8_t key, uint8_t velocity);
38+
virtual void key_pressure(uint8_t key, uint8_t pressure);
39+
virtual void key_up(uint8_t key);
40+
virtual void set_floppy_active(bool floppy_active) { }
3741

3842
protected:
3943
// construction/destruction
@@ -108,7 +112,10 @@ class esqpanel2x40_vfx_device : public esqpanel_device {
108112
esqpanel2x40_vfx_device(const machine_config &mconfig, const char *tag, device_t *owner, int panel_type = UNKNOWN, uint32_t clock = 0);
109113

110114
DECLARE_INPUT_CHANGED_MEMBER(button_change);
115+
DECLARE_INPUT_CHANGED_MEMBER(patch_select_change);
111116
DECLARE_INPUT_CHANGED_MEMBER(analog_value_change);
117+
DECLARE_INPUT_CHANGED_MEMBER(key_change);
118+
void set_floppy_active(bool floppy_active) override;
112119

113120
void set_family_member(int family_member);
114121

@@ -150,6 +157,8 @@ class esqpanel2x40_vfx_device : public esqpanel_device {
150157
required_ioport m_analog_data_entry;
151158
required_ioport m_analog_volume;
152159

160+
bool m_floppy_active = false;
161+
153162
TIMER_CALLBACK_MEMBER(update_blink);
154163
void update_lights();
155164

0 commit comments

Comments
 (0)