diff options
author | 2011-09-03 12:19:34 +0000 | |
---|---|---|
committer | 2011-09-03 12:19:34 +0000 | |
commit | 04169b13d4a9c49a04659f038f342c347d7cabd3 (patch) | |
tree | e1dce03cf819a0e8dbbdf68cae56835955034094 /src/emu/imagedev/serial.c | |
parent | 9ede250f5776f74e26a8c4e5dadd326c6e3a3ed4 (diff) |
Added serial image device, was in serial.c in mess/machine (no whatsnew)
Diffstat (limited to 'src/emu/imagedev/serial.c')
-rw-r--r-- | src/emu/imagedev/serial.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/emu/imagedev/serial.c b/src/emu/imagedev/serial.c new file mode 100644 index 00000000000..df9b07d9a87 --- /dev/null +++ b/src/emu/imagedev/serial.c @@ -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); +} + |