mirror of
https://github.com/holub/mame
synced 2025-05-22 21:58:57 +03:00
Added serial image device, was in serial.c in mess/machine (no whatsnew)
This commit is contained in:
parent
9ede250f57
commit
04169b13d4
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -717,6 +717,8 @@ src/emu/imagedev/multcart.c svneol=native#text/plain
|
||||
src/emu/imagedev/multcart.h svneol=native#text/plain
|
||||
src/emu/imagedev/printer.c svneol=native#text/plain
|
||||
src/emu/imagedev/printer.h svneol=native#text/plain
|
||||
src/emu/imagedev/serial.c svneol=native#text/plain
|
||||
src/emu/imagedev/serial.h svneol=native#text/plain
|
||||
src/emu/imagedev/snapquik.c svneol=native#text/plain
|
||||
src/emu/imagedev/snapquik.h svneol=native#text/plain
|
||||
src/emu/info.c svneol=native#text/plain
|
||||
|
@ -293,6 +293,7 @@ EMUIMAGEDEVOBJS = \
|
||||
$(EMUIMAGEDEV)/harddriv.o \
|
||||
$(EMUIMAGEDEV)/multcart.o \
|
||||
$(EMUIMAGEDEV)/printer.o \
|
||||
$(EMUIMAGEDEV)/serial.o \
|
||||
$(EMUIMAGEDEV)/snapquik.o \
|
||||
|
||||
|
||||
|
312
src/emu/imagedev/serial.c
Normal file
312
src/emu/imagedev/serial.c
Normal file
@ -0,0 +1,312 @@
|
||||
/****************************************************************************
|
||||
|
||||
serial.c
|
||||
|
||||
Code for handling serial port image devices
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
// device type definition
|
||||
const device_type SERIAL = &device_creator<serial_image_device>;
|
||||
|
||||
//-------------------------------------------------
|
||||
// serial_image_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
serial_image_device::serial_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, SERIAL, "Serial", tag, owner, clock),
|
||||
device_serial_interface(mconfig, *this),
|
||||
device_image_interface(mconfig, *this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// serial_image_device - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
serial_image_device::~serial_image_device()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void serial_image_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const serial_image_interface *intf = reinterpret_cast<const serial_image_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<serial_image_interface *>(this) = *intf;
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
m_baud_rate = 2400;
|
||||
m_data_bits = 8;
|
||||
m_stop_bits = 2;
|
||||
m_parity = SERIAL_PARITY_NONE;
|
||||
m_transmit_on_start = FALSE;
|
||||
m_tag_connected = NULL;
|
||||
}
|
||||
|
||||
// set brief and instance name
|
||||
update_names();
|
||||
}
|
||||
|
||||
static TIMER_CALLBACK(serial_device_baud_rate_callback)
|
||||
{
|
||||
reinterpret_cast<serial_image_device *>(ptr)->timer_callback();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
input_callback - called when other side
|
||||
has updated state
|
||||
-------------------------------------------------*/
|
||||
void serial_image_device::input_callback(UINT8 state)
|
||||
{
|
||||
m_input_state = state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void serial_image_device::device_start()
|
||||
{
|
||||
set_data_frame(m_data_bits, m_stop_bits,m_parity);
|
||||
|
||||
m_timer = machine().scheduler().timer_alloc(FUNC(serial_device_baud_rate_callback), this);
|
||||
|
||||
/* signal to other end it is clear to send! */
|
||||
/* data is initially high state */
|
||||
/* set /rts */
|
||||
m_connection_state |= SERIAL_STATE_RTS;
|
||||
/* signal to other end data is ready to be accepted */
|
||||
/* set /dtr */
|
||||
m_connection_state |= SERIAL_STATE_DTR;
|
||||
|
||||
set_out_data_bit(1);
|
||||
serial_connection_out();
|
||||
transmit_register_reset();
|
||||
receive_register_reset();
|
||||
|
||||
set_transmit_state(m_transmit_on_start ? 1 :0);
|
||||
|
||||
device_serial_interface *intf = NULL;
|
||||
device_t *dev = machine().device(m_tag_connected);
|
||||
if (dev!=NULL && dev->interface(intf)) {
|
||||
intf->connect(this);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
IMPLEMENTATION
|
||||
***************************************************************************/
|
||||
|
||||
/* reset position in stream */
|
||||
void serial_image_device::data_stream_reset(serial_data_stream *stream)
|
||||
{
|
||||
/* reset byte offset */
|
||||
stream->ByteCount= 0;
|
||||
/* reset bit count */
|
||||
stream->BitCount = 0;
|
||||
}
|
||||
|
||||
/* free stream */
|
||||
void serial_image_device::data_stream_free(serial_data_stream *stream)
|
||||
{
|
||||
if (stream->pData!=NULL)
|
||||
{
|
||||
free(stream->pData);
|
||||
stream->pData = NULL;
|
||||
}
|
||||
stream->DataLength = 0;
|
||||
}
|
||||
|
||||
/* initialise stream */
|
||||
void serial_image_device::data_stream_init(serial_data_stream *stream, unsigned char *pData, unsigned long DataLength)
|
||||
{
|
||||
stream->pData = pData;
|
||||
stream->DataLength = DataLength;
|
||||
data_stream_reset(stream);
|
||||
}
|
||||
|
||||
/* get a bit from input stream */
|
||||
|
||||
int serial_image_device::data_stream_get_data_bit_from_data_byte(serial_data_stream *stream)
|
||||
{
|
||||
int data_bit;
|
||||
int data_byte;
|
||||
|
||||
if (stream->ByteCount<stream->DataLength)
|
||||
{
|
||||
/* get data from buffer */
|
||||
data_byte= stream->pData[stream->ByteCount];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* over end of buffer, so return 0 */
|
||||
data_byte= 0;
|
||||
}
|
||||
|
||||
/* get bit from data */
|
||||
data_bit = (data_byte>>(7-stream->BitCount)) & 0x01;
|
||||
|
||||
/* update bit count */
|
||||
stream->BitCount++;
|
||||
/* ripple overflow onto byte count */
|
||||
stream->ByteCount+=stream->BitCount>>3;
|
||||
/* lock bit count into range */
|
||||
stream->BitCount &=0x07;
|
||||
|
||||
/* do not let it read over end of data */
|
||||
if (stream->ByteCount>=stream->DataLength)
|
||||
{
|
||||
stream->ByteCount = stream->DataLength-1;
|
||||
}
|
||||
|
||||
return data_bit;
|
||||
}
|
||||
|
||||
|
||||
void serial_image_device::set_transmit_state(int state)
|
||||
{
|
||||
int previous_state = m_transmit_state;
|
||||
|
||||
m_transmit_state = state;
|
||||
|
||||
if ((state^previous_state)!=0)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
/* start timer */
|
||||
m_timer->adjust(attotime::zero, 0, attotime::from_hz(m_baud_rate));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* remove timer */
|
||||
m_timer->reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void serial_image_device::sent_char()
|
||||
{
|
||||
int bit;
|
||||
UINT8 data_byte;
|
||||
|
||||
/* generate byte to transmit */
|
||||
data_byte = 0;
|
||||
for (int i=0; i< m_data_bits; i++)
|
||||
{
|
||||
data_byte = data_byte<<1;
|
||||
bit = data_stream_get_data_bit_from_data_byte(&m_transmit);
|
||||
data_byte = data_byte|bit;
|
||||
}
|
||||
/* setup register */
|
||||
transmit_register_setup(data_byte);
|
||||
|
||||
logerror("serial device transmitted char: %02x\n",data_byte);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
timer_callback
|
||||
-------------------------------------------------*/
|
||||
void serial_image_device::timer_callback()
|
||||
{
|
||||
/* receive data into receive register */
|
||||
receive_register_update_bit(get_in_data_bit());
|
||||
|
||||
if (is_receive_register_full())
|
||||
{
|
||||
//logerror("SERIAL DEVICE\n");
|
||||
receive_register_extract();
|
||||
|
||||
logerror("serial device receive char: %02x\n",get_received_char());
|
||||
}
|
||||
|
||||
/* is transmit empty? */
|
||||
if (is_transmit_register_empty())
|
||||
{
|
||||
/* char has been sent, execute callback */
|
||||
sent_char();
|
||||
}
|
||||
|
||||
/* other side says it is clear to send? */
|
||||
if (m_connection_state & SERIAL_STATE_CTS)
|
||||
{
|
||||
/* send bit */
|
||||
transmit_register_send_bit();
|
||||
}
|
||||
}
|
||||
|
||||
int serial_image_device::load_internal(unsigned char **ptr, int *pDataSize)
|
||||
{
|
||||
int datasize;
|
||||
unsigned char *data;
|
||||
|
||||
/* get file size */
|
||||
datasize = length();
|
||||
|
||||
if (datasize!=0)
|
||||
{
|
||||
/* malloc memory for this data */
|
||||
data = (unsigned char *)malloc(datasize);
|
||||
|
||||
if (data!=NULL)
|
||||
{
|
||||
/* read whole file */
|
||||
fread(data, datasize);
|
||||
|
||||
*ptr = data;
|
||||
*pDataSize = datasize;
|
||||
|
||||
logerror("File loaded!\r\n");
|
||||
|
||||
/* ok! */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
call_load
|
||||
-------------------------------------------------*/
|
||||
bool serial_image_device::call_load()
|
||||
{
|
||||
int data_length;
|
||||
unsigned char *data;
|
||||
/* load file and setup transmit data */
|
||||
if (load_internal(&data, &data_length))
|
||||
{
|
||||
data_stream_init(&m_transmit, data, data_length);
|
||||
return IMAGE_INIT_PASS;
|
||||
}
|
||||
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
call_unload
|
||||
-------------------------------------------------*/
|
||||
void serial_image_device::call_unload()
|
||||
{
|
||||
/* stop transmit */
|
||||
set_transmit_state(0);
|
||||
|
||||
/* free streams */
|
||||
data_stream_free(&m_transmit);
|
||||
data_stream_free(&m_receive);
|
||||
}
|
||||
|
110
src/emu/imagedev/serial.h
Normal file
110
src/emu/imagedev/serial.h
Normal file
@ -0,0 +1,110 @@
|
||||
/****************************************************************************
|
||||
|
||||
serial.h
|
||||
|
||||
Code for handling serial port image devices
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
#include "diimage.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
// ======================> serial_data_stream
|
||||
struct serial_data_stream
|
||||
{
|
||||
/* pointer to buffer */
|
||||
UINT8 *pData;
|
||||
/* length of buffer */
|
||||
unsigned long DataLength;
|
||||
|
||||
/* bit offset within current byte */
|
||||
unsigned long BitCount;
|
||||
/* byte offset within data */
|
||||
unsigned long ByteCount;
|
||||
};
|
||||
|
||||
// ======================> serial_image_interface
|
||||
|
||||
struct serial_image_interface
|
||||
{
|
||||
int m_baud_rate;
|
||||
int m_data_bits;
|
||||
int m_stop_bits;
|
||||
int m_parity;
|
||||
bool m_transmit_on_start;
|
||||
const char *m_tag_connected;
|
||||
};
|
||||
|
||||
// ======================> serial_image_device
|
||||
|
||||
class serial_image_device : public device_t,
|
||||
public serial_image_interface,
|
||||
public device_serial_interface,
|
||||
public device_image_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
serial_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~serial_image_device();
|
||||
|
||||
// image-level overrides
|
||||
virtual bool call_load();
|
||||
virtual void call_unload();
|
||||
|
||||
virtual iodevice_t image_type() const { return IO_SERIAL; }
|
||||
|
||||
virtual bool is_readable() const { return 1; }
|
||||
virtual bool is_writeable() const { return 1; }
|
||||
virtual bool is_creatable() const { return 1; }
|
||||
virtual bool must_be_loaded() const { return 0; }
|
||||
virtual bool is_reset_on_load() const { return 0; }
|
||||
virtual const char *image_interface() const { return NULL; }
|
||||
virtual const char *file_extensions() const { return ""; }
|
||||
virtual const option_guide *create_option_guide() const { return NULL; }
|
||||
|
||||
// specific implementation
|
||||
void timer_callback();
|
||||
virtual void input_callback(UINT8 state);
|
||||
void sent_char();
|
||||
void set_transmit_state(int state);
|
||||
int load_internal(unsigned char **ptr, int *pDataSize);
|
||||
|
||||
// data stream
|
||||
int data_stream_get_data_bit_from_data_byte(serial_data_stream *stream);
|
||||
void data_stream_reset(serial_data_stream *stream);
|
||||
void data_stream_free(serial_data_stream *stream);
|
||||
void data_stream_init(serial_data_stream *stream, unsigned char *pData, unsigned long DataLength) ;
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
|
||||
private:
|
||||
/* transmit data bit-stream */
|
||||
serial_data_stream m_transmit;
|
||||
/* receive data bit-stream */
|
||||
serial_data_stream m_receive;
|
||||
|
||||
int m_transmit_state;
|
||||
|
||||
/* baud rate timer */
|
||||
emu_timer *m_timer;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SERIAL;
|
||||
|
||||
|
||||
#define MCFG_SERIAL_ADD(_tag,_config) \
|
||||
MCFG_DEVICE_ADD(_tag, SERIAL, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config) \
|
||||
|
||||
#endif /* __SERIAL_H__ */
|
Loading…
Reference in New Issue
Block a user