summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/imagedev/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/imagedev/serial.c')
-rw-r--r--trunk/src/emu/imagedev/serial.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/trunk/src/emu/imagedev/serial.c b/trunk/src/emu/imagedev/serial.c
new file mode 100644
index 00000000000..3e102af2390
--- /dev/null
+++ b/trunk/src/emu/imagedev/serial.c
@@ -0,0 +1,313 @@
+/****************************************************************************
+
+ 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();
+
+ device_serial_interface *intf = NULL;
+ if (m_tag_connected) {
+ 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);
+ set_transmit_state(m_transmit_on_start ? 1 :0);
+ 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);
+}
+