Skip to content

Commit efc67b4

Browse files
committed
Add layouts for the vfx family of keypoards, panel-only for now, nbut reproducing the panels quite closely.
UI elements are kept in sync between the internal, layout-based panel, and any external panel.
1 parent 8f54eb7 commit efc67b4

File tree

7 files changed

+3577
-131
lines changed

7 files changed

+3577
-131
lines changed

src/mame/ensoniq/esqpanel.cpp

Lines changed: 185 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
Ensoniq panel/display device
55
*/
66
#include "emu.h"
7+
#include "ioport.h"
78
#include "esqpanel.h"
89
#include "extpanel.h"
910

11+
#include "vfx.lh"
12+
#include "vfxsd.lh"
13+
#include "sd1.lh"
14+
1015
#include "main.h"
1116

1217
//**************************************************************************
@@ -45,12 +50,13 @@ esqpanel_device::esqpanel_device(const machine_config &mconfig, device_type type
4550
device_t(mconfig, type, tag, owner, clock),
4651
device_serial_interface(mconfig, *this),
4752
m_external_panel(*this, "esq_external_panel"),
48-
m_light_states(0x3f), // maximum number of lights
53+
m_light_states(),
4954
m_write_tx(*this),
5055
m_write_analog(*this),
5156
m_read_analog(*this, 0)
5257
{
5358
std::fill(std::begin(m_xmitring), std::end(m_xmitring), 0);
59+
m_light_states.reserve(0x80);
5460
}
5561

5662

@@ -247,9 +253,16 @@ uint16_t esqpanel_device::get_analog_value(offs_t offset)
247253
return m_read_analog(offset, 0);
248254
}
249255

250-
251256
void esqpanel_device::set_button(uint8_t button, bool pressed)
252257
{
258+
printf("esqpanel.set_button(%d, %d)\r\n", button, pressed);
259+
bool current = m_pressed_buttons.find(button) != m_pressed_buttons.end();
260+
if (pressed == current)
261+
{
262+
printf("- button %d already %d, skipping\r\n", button, pressed);
263+
return;
264+
}
265+
253266
uint8_t sendme = (pressed ? 0x80 : 0) | (button & 0xff);
254267
// printf("button %d %s : sending char to mainboard: %02x\n", button, down ? "down" : "up", sendme);
255268
xmit_char(sendme);
@@ -270,6 +283,7 @@ TIMER_CALLBACK_MEMBER(esqpanel_device::check_external_panel_server) {
270283
{
271284
switch (c.kind) {
272285
case esq_external_panel_device::Command::ButtonKind:
286+
printf("Panel Handling button event from external panel\r\n");
273287
set_button(c.button, c.pressed);
274288
break;
275289

@@ -318,17 +332,31 @@ esqpanel2x40_device::esqpanel2x40_device(const machine_config &mconfig, const ch
318332

319333
/* panel with 2x40 VFD display used in the VFX, VFX-SD, SD-1 series */
320334

335+
esqpanel2x40_vfx_device::esqpanel2x40_vfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
336+
esqpanel_device(mconfig, ESQPANEL2X40_VFX, tag, owner, clock),
337+
m_vfd(*this, "vfd"),
338+
m_lights(*this, "lights"),
339+
m_variant(*this, "variant"), // an output on the panel
340+
m_buttons_0(*this, "buttons_0"),
341+
m_buttons_32(*this, "buttons_32"),
342+
m_analog_data_entry(*this, "analog_data_entry"),
343+
m_analog_volume(*this, "analog_volume")
344+
{
345+
m_eps_mode = false;
346+
}
347+
321348
void esqpanel2x40_vfx_device::device_add_mconfig(machine_config &config)
322349
{
323350
ESQ2X40_VFX(config, m_vfd, 60);
324351
ESQ_EXTERNAL_PANEL(config, m_external_panel, 0);
325-
}
326352

327-
esqpanel2x40_vfx_device::esqpanel2x40_vfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
328-
esqpanel_device(mconfig, ESQPANEL2X40_VFX, tag, owner, clock),
329-
m_vfd(*this, "vfd")
330-
{
331-
m_eps_mode = false;
353+
const std::string &name = owner()->shortname();
354+
if (name == "vfx")
355+
config.set_default_layout(layout_vfx);
356+
else if (name == "vfxsd")
357+
config.set_default_layout(layout_vfxsd);
358+
else // "sd1" or "sd132"
359+
config.set_default_layout(layout_sd1);
332360
}
333361

334362
void esqpanel2x40_vfx_device::rcv_complete() // Rx completed receiving byte
@@ -376,7 +404,12 @@ void esqpanel2x40_vfx_device::rcv_complete() // Rx completed receiving byte
376404
// 3 = Blinking
377405
auto light_state = (data & 0xc0) >> 6;
378406
m_light_states[light_number] = light_state;
407+
408+
// update the internal panel
409+
update_lights();
410+
// and any external panel
379411
m_external_panel->set_light(light_number, light_state);
412+
380413
m_expect_light_second_byte = false;
381414
}
382415
else if (data == 0xfb) // request calibration
@@ -463,18 +496,34 @@ void esqpanel2x40_vfx_device::rcv_complete() // Rx completed receiving byte
463496
}
464497
}
465498

499+
void esqpanel2x40_vfx_device::update_lights() {
500+
// set the lights according to their status and bllink phase.
501+
int32_t lights = 0;
502+
int32_t bit = 1;
503+
for (int i = 0; i < 16; i++)
504+
{
505+
if (m_light_states[i] == 2 || (m_light_states[i] == 3 && ((m_blink_phase & 1) == 0)))
506+
{
507+
lights |= bit;
508+
}
509+
bit <<= 1;
510+
}
511+
m_lights = lights;
512+
}
513+
466514
TIMER_CALLBACK_MEMBER(esqpanel2x40_vfx_device::update_blink) {
467515
m_blink_phase = (m_blink_phase + 1) & 3;
468516
m_vfd->set_blink_on(m_blink_phase & 2);
469517
m_external_panel->set_blink_phase(m_blink_phase);
518+
update_lights();
470519
}
471520

472521
void esqpanel2x40_vfx_device::device_start()
473522
{
474523
esqpanel_device::device_start();
475524

476-
m_external_panel->set_keyboard(owner()->shortname());
477-
m_external_panel->set_version("1");
525+
m_variant.resolve();
526+
m_lights.resolve();
478527

479528
m_blink_timer = timer_alloc(FUNC(esqpanel2x40_vfx_device::update_blink), this);
480529
m_blink_timer->enable(false);
@@ -484,13 +533,32 @@ void esqpanel2x40_vfx_device::device_reset()
484533
{
485534
esqpanel_device::device_reset();
486535

536+
const std::string &shortname = owner()->shortname();
537+
bool has_seq = shortname.find("sd") != std::string::npos;
538+
bool has_bank_set = shortname.find("1") != std::string::npos;
539+
bool has_32_voices = shortname.find("32") != std::string::npos;
540+
541+
u32 bit_seq = 1 << 0;
542+
u32 bit_bank_set = 1 << 1;
543+
u32 bit_32_voices = 1 << 2;
544+
545+
m_variant =
546+
(has_seq ? bit_seq : 0)
547+
| (has_bank_set ? bit_bank_set : 0)
548+
| (has_32_voices ? bit_32_voices : 0);
549+
550+
m_external_panel->set_keyboard(shortname);
551+
m_external_panel->set_version("1");
552+
487553
if (m_blink_timer) {
488554
attotime sample_time(0, 250 * ATTOSECONDS_PER_MILLISECOND);
489555
attotime initial_delay(0, 250 * ATTOSECONDS_PER_MILLISECOND);
490556

491557
m_blink_timer->adjust(initial_delay, 0, sample_time);
492558
m_blink_timer->enable(true);
493559
}
560+
561+
494562
}
495563

496564
void esqpanel2x40_vfx_device::device_reset_after_children()
@@ -545,6 +613,113 @@ void esqpanel2x40_vfx_device::send_light_states()
545613
m_external_panel->set_light_states(light_states);
546614
}
547615

616+
static INPUT_PORTS_START(esqpanel2x40_vfx_device)
617+
PORT_START("buttons_0")
618+
for (int i = 0; i < 32; i++)
619+
{
620+
PORT_BIT((1 << i), IP_ACTIVE_HIGH, IPT_KEYBOARD);
621+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::button_change), i)
622+
}
623+
624+
PORT_START("buttons_32")
625+
for (int i = 0; i < 32; i++)
626+
{
627+
PORT_BIT((1 << i), IP_ACTIVE_HIGH, IPT_KEYBOARD);
628+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::button_change), 32 + i)
629+
}
630+
631+
PORT_START("analog_data_entry")
632+
PORT_ADJUSTER(255, "Data Entry")
633+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::analog_value_change), 3)
634+
635+
PORT_START("analog_volume")
636+
PORT_ADJUSTER(255, "Volume")
637+
PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esqpanel2x40_vfx_device::analog_value_change), 5)
638+
639+
INPUT_PORTS_END
640+
641+
ioport_constructor esqpanel2x40_vfx_device::device_input_ports() const
642+
{
643+
return INPUT_PORTS_NAME(esqpanel2x40_vfx_device);
644+
}
645+
646+
// A button is pressed on the internal panel
647+
INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::button_change)
648+
{
649+
// Update the internal state
650+
esqpanel_device::set_button(param, newval != 0);
651+
652+
// Synchronize the change to the external panel
653+
m_external_panel->set_button(param, newval != 0);
654+
}
655+
656+
// A button is pressed on the external panel
657+
void esqpanel2x40_vfx_device::set_button(uint8_t button, bool pressed)
658+
{
659+
// Update the internal state
660+
esqpanel_device::set_button(button, pressed);
661+
662+
// Synchronize the change to the internal panel
663+
auto &port = button < 32 ? m_buttons_0 : m_buttons_32;
664+
auto bit = 1 << (button % 32);
665+
port->field(bit)->set_value(pressed);
666+
}
667+
668+
// An anlog value was changed on the internal panel
669+
INPUT_CHANGED_MEMBER(esqpanel2x40_vfx_device::analog_value_change)
670+
{
671+
if (oldval == 255)
672+
{
673+
// This is the initial write from the layout. Skip this.
674+
printf("skipping initial write from internal panel to channnel %d\r\n", param);
675+
return;
676+
}
677+
678+
int channel = param;
679+
int clamped = std::max(0, std::min(100, (int)newval));
680+
int value = (1023 << 6) * clamped / 100;
681+
esqpanel_device::set_analog_value(channel, value);
682+
printf("sending analog channel %d value %d to external panel\r\n", channel, value);
683+
m_external_panel->set_analog_value(channel, value);
684+
}
685+
686+
// An anlog value was changed on the external panel
687+
void esqpanel2x40_vfx_device::set_analog_value(offs_t offset, uint16_t value)
688+
{
689+
// Update the internal state
690+
esqpanel_device::set_analog_value(offset, value);
691+
692+
int intvalue = 100 * ((int)value) / (1023 << 6);
693+
694+
// Synchronize the change to the internal panel by writing it to the corresponding io port
695+
if (offset == 3)
696+
{
697+
set_adjuster_value(m_analog_data_entry, intvalue);
698+
printf("Setting data entry io port to %d\r\n", intvalue);
699+
}
700+
else if (offset == 5)
701+
{
702+
set_adjuster_value(m_analog_volume, intvalue);
703+
printf("Setting volume io port to %d\r\n", intvalue);
704+
}
705+
}
706+
707+
ioport_value esqpanel2x40_vfx_device::get_adjuster_value(required_ioport &ioport)
708+
{
709+
auto field = ioport->fields().first();
710+
ioport_field::user_settings user_settings;
711+
field->get_user_settings(user_settings);
712+
return user_settings.value;
713+
}
714+
715+
void esqpanel2x40_vfx_device::set_adjuster_value(required_ioport &ioport, const ioport_value & value)
716+
{
717+
auto field = ioport->fields().first();
718+
ioport_field::user_settings user_settings;
719+
field->get_user_settings(user_settings);
720+
user_settings.value = value;
721+
field->set_user_settings(user_settings);
722+
}
548723

549724
// --- SQ1 - Parduz --------------------------------------------------------------------------------------------------------------------------
550725
void esqpanel2x16_sq1_device::device_add_mconfig(machine_config &config)

src/mame/ensoniq/esqpanel.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ class esqpanel_device : public device_t, public device_serial_interface
3131
void xmit_char(uint8_t data);
3232

3333
void set_char(int row, int column, uint8_t c, uint8_t attr);
34-
void set_analog_value(offs_t offset, uint16_t value);
34+
virtual void set_analog_value(offs_t offset, uint16_t value);
3535
uint16_t get_analog_value(offs_t offset);
36-
void set_button(uint8_t button, bool pressed);
36+
virtual void set_button(uint8_t button, bool pressed);
3737

3838
protected:
3939
// construction/destruction
@@ -109,11 +109,15 @@ class esqpanel2x40_vfx_device : public esqpanel_device {
109109
public:
110110
esqpanel2x40_vfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
111111

112+
DECLARE_INPUT_CHANGED_MEMBER(button_change);
113+
DECLARE_INPUT_CHANGED_MEMBER(analog_value_change);
114+
112115
protected:
113116
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
114117
virtual void device_start() override ATTR_COLD;
115118
virtual void device_reset() override ATTR_COLD;
116119
virtual void device_reset_after_children() override ATTR_COLD;
120+
virtual ioport_constructor device_input_ports() const override;
117121

118122
virtual void send_to_display(uint8_t data) override { }
119123
virtual void rcv_complete() override; // Rx completed receiving byte
@@ -123,6 +127,9 @@ class esqpanel2x40_vfx_device : public esqpanel_device {
123127
virtual void send_button_states() override;
124128
virtual void send_light_states() override;
125129

130+
virtual void set_button(uint8_t button, bool pressed) override;
131+
virtual void set_analog_value(offs_t offset, uint16_t value) override;
132+
126133
required_device<esq2x40_vfx_device> m_vfd;
127134

128135
static constexpr uint8_t AT_NORMAL = 0x00;
@@ -131,13 +138,27 @@ class esqpanel2x40_vfx_device : public esqpanel_device {
131138

132139
TIMER_CALLBACK_MEMBER(update_blink);
133140

141+
ioport_value get_adjuster_value(required_ioport &ioport);
142+
void set_adjuster_value(required_ioport &ioport, const ioport_value & value);
143+
134144
private:
135145
int m_cursx = 0, m_cursy = 0;
136146
int m_savedx = 0, m_savedy = 0;
137147
uint8_t m_curattr = 0;
138148

139149
emu_timer *m_blink_timer = nullptr;
140150
uint8_t m_blink_phase;
151+
152+
void update_lights();
153+
154+
output_finder<> m_lights;
155+
output_finder<> m_variant;
156+
157+
required_ioport m_buttons_0;
158+
required_ioport m_buttons_32;
159+
required_ioport m_analog_data_entry;
160+
required_ioport m_analog_volume;
161+
141162
};
142163

143164
class esqpanel2x40_sq1_device : public esqpanel_device {

src/mame/ensoniq/esqvfd.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
#include "esq1by22.lh"
1212
#include "esq2by40.lh"
13-
#include "esq2by40_vfx.lh"
1413

1514
DEFINE_DEVICE_TYPE(ESQ1X22, esq1x22_device, "esq1x22", "Ensoniq 1x22 VFD")
1615
DEFINE_DEVICE_TYPE(ESQ2X40, esq2x40_device, "esq2x40", "Ensoniq 2x40 VFD")
@@ -424,7 +423,9 @@ void esq2x40_vfx_device::update_display()
424423

425424
void esq2x40_vfx_device::device_add_mconfig(machine_config &config)
426425
{
427-
config.set_default_layout(layout_esq2by40_vfx);
426+
// Do not set a default layout. This display must be used
427+
// within a layout that includes the VFD elements, such as
428+
// vfx.lay, vfxsd.lay or sd1.lay.
428429
}
429430

430431
void esq2x40_vfx_device::set_blink_on(bool blink_on) {

0 commit comments

Comments
 (0)