// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************
RCA CDP1863 CMOS 8-Bit Programmable Frequency Generator emulation
**********************************************************************/
/*
TODO:
- what happens if you connect both clocks?
*/
#include "emu.h"
#include "cdp1863.h"
//#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define CDP1863_DEFAULT_LATCH 0x35
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// devices
DEFINE_DEVICE_TYPE(CDP1863, cdp1863_device, "cdp1863", "RCA CDP1863")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// cdp1863_device - constructor
//-------------------------------------------------
cdp1863_device::cdp1863_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, CDP1863, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, m_stream(nullptr)
, m_clock1(clock)
, m_clock2(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void cdp1863_device::device_start()
{
// create sound stream
m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate());
// register for state saving
save_item(NAME(m_clock1));
save_item(NAME(m_clock2));
save_item(NAME(m_oe));
save_item(NAME(m_latch));
save_item(NAME(m_signal));
save_item(NAME(m_incr));
}
//-------------------------------------------------
// sound_stream_update - handle update requests for
// our sound stream
//-------------------------------------------------
void cdp1863_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
// reset the output stream
memset(outputs[0], 0, samples * sizeof(*outputs[0]));
int16_t signal = m_signal;
stream_sample_t *buffer = outputs[0];
memset( buffer, 0, samples * sizeof(*buffer) );
if (m_oe)
{
double frequency;
int rate = machine().sample_rate() / 2;
// get progress through wave
int incr = m_incr;
if (m_clock1 > 0)
{
// CLK1 is pre-divided by 4
frequency = m_clock1 / 4 / (m_latch + 1) / 2;
}
else
{
// CLK2 is pre-divided by 8
frequency = m_clock2 / 8 / (m_latch + 1) / 2;
}
if (signal < 0)
{
signal = -0x7fff;
}
else
{
signal = 0x7fff;
}
while( samples-- > 0 )
{
*buffer++ = signal;
incr -= frequency;
while( incr < 0 )
{
incr += rate;
signal = -signal;
}
}
// store progress through wave
m_incr = incr;
m_signal = signal;
}
}
//-------------------------------------------------
// oe_w - output enable write
//-------------------------------------------------
WRITE_LINE_MEMBER( cdp1863_device::oe_w )
{
m_oe = state;
}
//-------------------------------------------------
// set_clk1 - set clock 1
//-------------------------------------------------
void cdp1863_device::set_clk1(int clock)
{
m_clock1 = clock;
}
//-------------------------------------------------
// set_clk2 - set clock 2
//-------------------------------------------------
void cdp1863_device::set_clk2(int clock)
{
m_clock2 = clock;
}