Skip to content

Commit 9cdce30

Browse files
authored
act/victor9k.cpp: Get audio working on Victor 9000 (victor9k) (#13549)
* 6522via: Don't generate a signal on PB7 when the timer 1 latch is programmed with 0. On the Victor 9000, the clock for the audio codec is generated by a via6522. PB7 is connected to the codec's clock input. Non-speech sounds (e.g. beeps, musical notes) are produced by outputting a cyclical waveform from the codec, with the pitch determined by the frequency of the codec clock. Software running on the Victor 9000 has been observed to attempt to silence the audio by writing 0 to the T1 timer latch (not by turning off continuous mode or PB7 output). With the emulated via6522, this resulted in a high-frequency clock signal being output on PB7, causing a high-pitched squeal whenever notes are not being played. From this observed behavior we could infer that the original 6522 HW does not output a signal on PB7 when the latch value is 0, and that the Victor 9000 software was relying on this behaviour to silence the audio output (one would have to assume that the real hardware didn't produce a squeal). * mc6852: fix various transmit-related issues which were preventing victor9k Audio output from working. The expected behavior of mc6852 is to write the data received in the FIFO register serially via tx_data_callback(). However, this was not implemented, and the only way data in the transmit FIFO could be removed and transmitted was by calling get_tx_byte(), and to then serially transmit the data by some external mechanism. Only m68sfdc.cpp calls get_tx_byte(), so it's hard to see how any other device using the mc6852 would have been able to transmit data. Software running on victor9k attempting to play audio would hang, since it would block waiting for the TX FIFO to empty. With these changes, Victor 9000 audio playback works as expected, with the data getting sent serially to the Audio codec. In order to avoid breaking m68sfdc, a new API call is added to allow data to be sent the "old" way. m68sfdc now calls set_tx_pull_mode(true), to get the previous behavior. As I understand it, other devices using mc6852 must be broken, and would need to be revisited. * victor9k: complete Audio support, adding a low-pass filter after the HC-55516 codec. Mark victor9k Audio as working.
1 parent 8c5e73a commit 9cdce30

File tree

5 files changed

+100
-16
lines changed

5 files changed

+100
-16
lines changed

src/devices/machine/6522via.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,14 @@ TIMER_CALLBACK_MEMBER(via6522_device::t1_tick)
535535
if (T1_CONTINUOUS (m_acr))
536536
{
537537
m_t1_pb7 = !m_t1_pb7;
538-
m_t1->adjust(clocks_to_attotime(TIMER1_VALUE + IFR_DELAY));
538+
if (TIMER1_VALUE > 0)
539+
{
540+
m_t1->adjust(clocks_to_attotime(TIMER1_VALUE + IFR_DELAY));
541+
}
542+
else
543+
{
544+
m_t1_active = 0;
545+
}
539546
}
540547
else
541548
{
@@ -934,8 +941,15 @@ void via6522_device::write(offs_t offset, u8 data)
934941
output_pb();
935942
}
936943

937-
m_t1->adjust(clocks_to_attotime(TIMER1_VALUE + IFR_DELAY));
938-
m_t1_active = 1;
944+
if (TIMER1_VALUE > 0)
945+
{
946+
m_t1->adjust(clocks_to_attotime(TIMER1_VALUE + IFR_DELAY));
947+
m_t1_active = 1;
948+
}
949+
else
950+
{
951+
m_t1_active = 0;
952+
}
939953
break;
940954

941955
case VIA_T2CL:

src/devices/machine/m68sfdc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ void m68sfdc_device::device_add_mconfig(machine_config &config)
842842
m_pia->irqb_handler().set(FUNC(m68sfdc_device::handle_irq));
843843

844844
MC6852(config, m_ssda, 0);
845+
m_ssda->set_tx_pull_mode(true);
845846
}
846847

847848
DEFINE_DEVICE_TYPE(M68SFDC, m68sfdc_device, "m68sfdc", "M68SFDC")

src/devices/machine/mc6852.cpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ mc6852_device::mc6852_device(const machine_config &mconfig, const char *tag, dev
5151
m_write_irq(*this),
5252
m_write_sm_dtr(*this),
5353
m_write_tuf(*this),
54+
m_tx_pull_mode(false),
55+
m_tx_active(false),
5456
m_rx_clock(0),
5557
m_tx_clock(0),
5658
m_cts(1),
@@ -84,6 +86,8 @@ void mc6852_device::device_start()
8486
save_item(NAME(m_sm_dtr));
8587
save_item(NAME(m_tuf));
8688
save_item(NAME(m_in_sync));
89+
save_item(NAME(m_tx_active));
90+
save_item(NAME(m_tx_pull_mode));
8791
}
8892

8993

@@ -125,7 +129,39 @@ void mc6852_device::tra_callback()
125129

126130
void mc6852_device::tra_complete()
127131
{
128-
// TODO
132+
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
133+
int available = 3 - m_tx_fifo.size();
134+
uint8_t byte_to_send;
135+
136+
if (available < 3)
137+
{
138+
// FIFO not empty - send the next byte.
139+
byte_to_send = m_tx_fifo.front();
140+
m_tx_fifo.pop();
141+
available++;
142+
}
143+
else
144+
{
145+
// TX underflow
146+
if (m_cr[1] & C2_TX_SYNC)
147+
{
148+
m_status |= S_TUF;
149+
byte_to_send = m_scr; // Send Sync Code
150+
151+
// TODO assert TUF pin for "approximately one Tx CLK high period"
152+
}
153+
else
154+
{
155+
byte_to_send = 0xff; // Send a "Mark"
156+
}
157+
}
158+
159+
transmit_register_setup(byte_to_send);
160+
161+
if (available >= trigger)
162+
{
163+
m_status |= S_TDRA;
164+
}
129165
}
130166

131167
//-------------------------------------------------
@@ -234,7 +270,7 @@ uint8_t mc6852_device::read(offs_t offset)
234270
// TODO this might not be quite right, the datasheet
235271
// states that the RX overrun flag is cleared by
236272
// reading the status, and the RX data fifo?
237-
m_status &= S_RX_OVRN;
273+
m_status &= ~S_RX_OVRN;
238274
}
239275
}
240276

@@ -311,9 +347,9 @@ void mc6852_device::write(offs_t offset, uint8_t data)
311347

312348
int data_bit_count = 0;
313349
parity_t parity = PARITY_NONE;
314-
stop_bits_t stop_bits = STOP_BITS_1;
350+
stop_bits_t stop_bits = STOP_BITS_0;
315351

316-
switch (data & C2_WS_MASK)
352+
switch ((data & C2_WS_MASK) >> C2_WS_SHIFT)
317353
{
318354
case 0: data_bit_count = 6; parity = PARITY_EVEN; break;
319355
case 1: data_bit_count = 6; parity = PARITY_ODD; break;
@@ -325,7 +361,7 @@ void mc6852_device::write(offs_t offset, uint8_t data)
325361
case 7: data_bit_count = 8; parity = PARITY_ODD; break;
326362
}
327363

328-
set_data_frame(1, data_bit_count, parity, stop_bits);
364+
set_data_frame(0, data_bit_count, parity, stop_bits);
329365

330366
// The fifo trigger levels may have changed, so update
331367
// the status bits.
@@ -374,8 +410,17 @@ void mc6852_device::write(offs_t offset, uint8_t data)
374410
if (available > 0)
375411
{
376412
LOG("MC6852 Transmit FIFO %02x\n", data);
377-
m_tx_fifo.push(data);
378-
available--;
413+
if (!m_tx_pull_mode && !m_tx_active) {
414+
// transfer is idle: this emulates moving the first byte
415+
// into the shift register, and kicking off transmission.
416+
// tra_complete() will be called when the byte has been
417+
// sent.
418+
m_tx_active = true;
419+
transmit_register_setup(data);
420+
} else {
421+
m_tx_fifo.push(data);
422+
available--;
423+
}
379424
}
380425
else
381426
{
@@ -426,6 +471,7 @@ void mc6852_device::write(offs_t offset, uint8_t data)
426471
m_status &= ~(S_TUF | S_CTS);
427472
m_status |= S_TDRA;
428473
m_tx_fifo = std::queue<uint8_t>();
474+
m_tx_active = false;
429475

430476
transmit_register_reset();
431477
}

src/devices/machine/mc6852.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class mc6852_device : public device_t,
4747
void set_rx_clock(int clock) { m_rx_clock = clock; }
4848
void set_tx_clock(int clock) { m_tx_clock = clock; }
4949

50+
void set_tx_pull_mode(bool tx_pull_mode) { m_tx_pull_mode = tx_pull_mode; }
51+
5052
auto tx_data_callback() { return m_write_tx_data.bind(); }
5153
auto irq_callback() { return m_write_irq.bind(); }
5254
auto sm_dtr_callback() { return m_write_sm_dtr.bind(); }
@@ -120,7 +122,8 @@ class mc6852_device : public device_t,
120122
C2_1_2_BYTE = 0x04,
121123
C2_PC_MASK = 0x03,
122124
C2_PC2 = 0x02,
123-
C2_PC1 = 0x01
125+
C2_PC1 = 0x01,
126+
C2_WS_SHIFT = 3
124127
};
125128

126129
enum
@@ -147,6 +150,13 @@ class mc6852_device : public device_t,
147150
std::queue<uint8_t> m_rx_fifo;
148151
std::queue<uint8_t> m_tx_fifo;
149152

153+
// If m_tx_pull_mode is true, get_tx_byte() must be called to retrieve
154+
// the next byte to transmit, and the actual transmission must be
155+
// carried out by some external mechanism.
156+
bool m_tx_pull_mode;
157+
158+
bool m_tx_active;
159+
150160
int m_rx_clock;
151161
int m_tx_clock;
152162
int m_cts; // clear to send

src/mame/act/victor9k.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@
3434
#include "machine/pit8253.h"
3535
#include "machine/pic8259.h"
3636
#include "machine/ram.h"
37+
#include "machine/rescap.h"
3738
#include "victor9k_kb.h"
3839
#include "victor9k_fdc.h"
3940
#include "machine/z80sio.h"
4041
#include "sound/hc55516.h"
42+
#include "sound/flt_biquad.h"
4143
#include "video/mc6845.h"
4244
#include "emupal.h"
4345
#include "screen.h"
@@ -104,6 +106,8 @@ class victor9k_state : public driver_device
104106
m_cvsd(*this, HC55516_TAG),
105107
m_crtc(*this, HD46505S_TAG),
106108
m_ram(*this, RAM_TAG),
109+
m_cvsd_filter(*this, "cvsd_filter"),
110+
m_cvsd_filter2(*this, "cvsd_filter2"),
107111
m_kb(*this, KB_TAG),
108112
m_fdc(*this, "fdc"),
109113
m_centronics(*this, "centronics"),
@@ -138,6 +142,8 @@ class victor9k_state : public driver_device
138142
required_device<hc55516_device> m_cvsd;
139143
required_device<mc6845_device> m_crtc;
140144
required_device<ram_device> m_ram;
145+
optional_device<filter_biquad_device> m_cvsd_filter;
146+
optional_device<filter_biquad_device> m_cvsd_filter2;
141147
required_device<victor_9000_keyboard_device> m_kb;
142148
required_device<victor_9000_fdc_device> m_fdc;
143149
required_device<centronics_device> m_centronics;
@@ -391,7 +397,12 @@ void victor9k_state::ssda_sm_dtr_w(int state)
391397
{
392398
m_ssda->cts_w(state);
393399
m_ssda->dcd_w(!state);
394-
//m_cvsd->enc_dec_w(!state);
400+
401+
/* ___
402+
* We're supposed to set the ENC/DEC input of the HC55516 to !state,
403+
* but only playback/decode is currently supported, and that input
404+
* is not implemenented.
405+
*/
395406
}
396407

397408

@@ -733,10 +744,12 @@ void victor9k_state::victor9k(machine_config &config)
733744
m_crtc->set_begin_update_callback(FUNC(victor9k_state::crtc_begin_update));
734745

735746
// sound hardware
747+
FILTER_BIQUAD(config, m_cvsd_filter2).opamp_mfb_lowpass_setup(RES_K(27), RES_K(15), RES_K(27), CAP_P(4700), CAP_P(1200));
748+
FILTER_BIQUAD(config, m_cvsd_filter).opamp_mfb_lowpass_setup(RES_K(43), RES_K(36), RES_K(180), CAP_P(1800), CAP_P(180));
749+
HC55516(config, m_cvsd, 0).add_route(ALL_OUTPUTS, m_cvsd_filter, 1.0);
750+
m_cvsd_filter->add_route(ALL_OUTPUTS, m_cvsd_filter2, 1.0);
751+
m_cvsd_filter2->add_route(ALL_OUTPUTS, "mono", 0.25);
736752
SPEAKER(config, "mono").front_center();
737-
HC55516(config, m_cvsd, 0);
738-
//MCFG_HC55516_DIG_OUT_CB(WRITELINE(MC6852_TAG, mc6852_device, rx_w))
739-
m_cvsd->add_route(ALL_OUTPUTS, "mono", 0.25);
740753

741754
// devices
742755
IEEE488(config, m_ieee488, 0);
@@ -853,4 +866,4 @@ ROM_END
853866
//**************************************************************************
854867

855868
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
856-
COMP( 1982, victor9k, 0, 0, victor9k, victor9k, victor9k_state, empty_init, "Victor Business Products", "Victor 9000", MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
869+
COMP( 1982, victor9k, 0, 0, victor9k, victor9k, victor9k_state, empty_init, "Victor Business Products", "Victor 9000", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE )

0 commit comments

Comments
 (0)