Previous 15994 Revisions Next

r14548 Monday 20th February, 2012 at 08:10:37 UTC by Miodrag Milanović
mc146818 - Set period even if timer is disabled, required for windows nt diserial - added optinal rx and tx timers and callbacks
ins8250 - serial rx line high on start and fix for msr register
bitbanger - added 19200bps
Fixes for terminal callback
All by Carl, credited in MAME (no whatsnew)
[src/emu]diserial.c diserial.h
[src/emu/imagedev]bitbngr.c
[src/emu/machine]ins8250.c ins8250.h mc146818.c microtch.c microtch.h
[src/mess/machine]null_modem.h ser_mouse.c ser_mouse.h terminal.c terminal.h

src/emu/imagedev/bitbngr.c
r14547r14548
154154UINT32 bitbanger_device::baud_value(void)
155155{
156156   static const float bauds[] = { 150.0f, 300.0f, 600.0f, 1200.0f, 2400.0f, 4800.0f, 9600.0f,
157            14400.0f, 28800.0f, 38400.0f, 57600.0f, 115200.0f};
157            14400.0f, 19200.0f, 28800.0f, 38400.0f, 57600.0f, 115200.0f};
158158   float result = tune_value() * bauds[m_baud];
159159   return (UINT32)result;
160160}
r14547r14548
167167const char *bitbanger_device::baud_string(void)
168168{
169169   static const char *const bauds[] = { "150", "300", "600", "1200", "2400", "4800",
170                     "9600", "14400", "28800", "38400", "57600", "115200"};
170                     "9600", "14400", "19200", "28800", "38400", "57600", "115200"};
171171
172172   return(bauds[m_baud]);
173173}
src/emu/diserial.c
r14547r14548
3737
3838      m_serial_parity_table[i] = sum & 0x01;
3939   }
40   m_rcv_clock = NULL;
41   m_tra_clock = NULL;
4042}
4143
4244device_serial_interface::~device_serial_interface()
4345{
4446}
4547
48void device_serial_interface::set_rcv_rate(int baud)
49{
50   if(!m_rcv_clock)
51      m_rcv_clock = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_serial_interface::rcv_timer), this));
4652
53   m_rcv_baud = baud;
54   receive_register_reset();
55   m_rcv_clock->adjust(attotime::never);
56}
57
58void device_serial_interface::set_tra_rate(int baud)
59{
60   if(!m_tra_clock)
61      m_tra_clock = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_serial_interface::tra_timer), this));
62
63   m_tra_baud = baud;
64   transmit_register_reset();
65   m_tra_clock->adjust(attotime::never);
66}
67
68void device_serial_interface::tra_timer(void *ptr, int param)
69{
70   tra_callback();
71   if(is_transmit_register_empty())
72   {
73      m_tra_clock->adjust(attotime::never);
74      tra_complete();
75   }
76}
77
78void device_serial_interface::rcv_timer(void *ptr, int param)
79{
80   rcv_callback();
81   if(is_receive_register_full())
82   {
83      m_rcv_clock->adjust(attotime::never);
84      rcv_complete();
85   }
86}
87
4788void device_serial_interface::set_data_frame(int num_data_bits, int stop_bit_count, int parity_code)
4889{
4990   m_df_word_length = num_data_bits;
r14547r14548
66107   m_rcv_flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT;
67108}
68109
110UINT8 device_serial_interface::check_for_start(UINT8 bit)
111{
112   m_rcv_line = bit;
113   if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
114      return 0;
115   receive_register_update_bit(bit);
116   if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
117   {
118      if(m_rcv_clock && m_rcv_baud)
119         // make start delay just a bit longer to make sure we are called after the sender
120         m_rcv_clock->adjust(attotime::from_hz((m_rcv_baud*2)/3), 0, attotime::from_hz(m_rcv_baud));
121      return 1;
122   }
123   return 0;
124}
125
69126/* this is generic code to be used in serial chip implementations */
70127/* the majority of serial chips work in the same way and this code will work */
71128/* for them */
r14547r14548
201258   int i;
202259   unsigned char transmit_data;
203260
261   if(m_tra_clock && m_tra_baud)
262      m_tra_clock->adjust(attotime::from_hz(m_tra_baud), 0, attotime::from_hz(m_tra_baud));
204263
205264   m_tra_bit_count_transmitted = 0;
206265   m_tra_bit_count = 0;
src/emu/diserial.h
r14547r14548
7575/* TX = Transmit data. (OUTPUT) */
7676#define SERIAL_STATE_TX_DATA   0x00020
7777
78
7978// ======================> device_serial_interface
8079class device_serial_interface : public device_interface
8180{
r14547r14548
9291   void receive_register_update_bit(int bit);
9392   void receive_register_extract();
9493
94   void set_rcv_rate(int baud);
95   void set_tra_rate(int baud);
9596
9697   void transmit_register_reset();
9798   void transmit_register_add_bit(int bit);
r14547r14548
114115   void set_other_connection(device_serial_interface *other_connection);
115116
116117   void connect(device_serial_interface *other_connection);
118   UINT8 check_for_start(UINT8 bit);
117119protected:
118120   UINT8 m_input_state;
119121   UINT8 m_connection_state;
122   virtual void tra_callback() { }
123   virtual void rcv_callback() { receive_register_update_bit(m_rcv_line); }
124   virtual void tra_complete() { }
125   virtual void rcv_complete() { }
120126private:
127   void tra_timer(void *ptr, int param);
128   void rcv_timer(void *ptr, int param);
129
121130   UINT8 m_serial_parity_table[256];
122131
123132   // Data frame
r14547r14548
150159   /* length of data to send */
151160   UINT8 m_tra_bit_count;
152161
162   emu_timer *m_rcv_clock;
163   emu_timer *m_tra_clock;
164   int m_rcv_baud;
165   int m_tra_baud;
166   UINT8 m_rcv_line;
167
153168   device_serial_interface *m_other_connection;
154169};
155170
src/emu/machine/ins8250.c
r14547r14548
169169   int baud;
170170   if(m_regs.dl == 0)
171171   {
172      m_timer->adjust(attotime::never);
172      set_tra_rate(0);
173      set_rcv_rate(0);
173174      return;
174175   }
175176   baud = clock()/(m_regs.dl*16);
176   m_timer->adjust(attotime::zero, 0, attotime::from_hz(baud));
177   set_tra_rate(baud);
178   set_rcv_rate(baud);
177179}
178180
179181WRITE8_MEMBER( ins8250_uart_device::ins8250_w )
r14547r14548
191193         else
192194         {
193195            m_regs.thr = data;
194            m_regs.lsr &= ~0x60;
196            m_regs.lsr &= ~0x20;
195197            if ( m_regs.mcr & 0x10 )
196198            {
199               m_regs.lsr &= ~0x40;
197200               m_regs.lsr |= 1;
198201               m_regs.rbr = data;
199202               trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
200203            }
204            else
205               if(m_regs.lsr & 0x40)
206                  tra_complete();
201207         }
202208         break;
203209      case 1:
r14547r14548
356362    return data;
357363}
358364
365void ins8250_uart_device::rcv_complete()
366{
367   if(m_regs.lsr & 0x01)
368   {
369      m_regs.lsr |= 0x02; //overrun
370      trigger_int(COM_INT_PENDING_RECEIVER_LINE_STATUS);
371      receive_register_reset();
372   }
373   else
374   {
375      m_regs.lsr |= 0x01;
376      receive_register_extract();
377      m_regs.rbr = get_received_char();
378      trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
379   }
380}
381
382void ins8250_uart_device::tra_complete()
383{
384   if(!(m_regs.lsr & 0x20))
385   {
386      transmit_register_setup(m_regs.thr);
387      m_regs.lsr &= ~0x40;
388      m_regs.lsr |= 0x20;
389      trigger_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
390   }
391   else
392      m_regs.lsr |= 0x40;
393}
394
395void ins8250_uart_device::tra_callback()
396{
397   m_out_tx_func(transmit_register_get_data_bit());
398}   
399
359400void ins8250_uart_device::update_msr(int bit, UINT8 state)
360401{
361402   UINT8 mask = (1<<bit);
362403   if((m_regs.msr & mask) == (state<<bit))
363404      return;
364   m_regs.msr = (m_regs.msr & ~mask) | (mask & (state<<bit));
365   m_regs.msr = (m_regs.msr & ~(mask << 4)) | (1<<(bit+4));
405   m_regs.msr |= mask;
406   m_regs.msr = (m_regs.msr & ~(mask << 4)) | (state<<(bit+4));
366407   trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER);
367408}
368409
r14547r14548
386427   update_msr(0, (state&&1));
387428}
388429
389void ins8250_uart_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
390{
391   receive_register_update_bit(m_rx_line);
392   if(is_receive_register_full())
393   {
394      if(m_regs.lsr & 0x01)
395      {
396         m_regs.lsr |= 0x02; //overrun
397         trigger_int(COM_INT_PENDING_RECEIVER_LINE_STATUS);
398      }
399      else
400      {
401         m_regs.lsr |= 0x01;
402         receive_register_extract();
403         m_regs.rbr = get_received_char();
404         trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
405      }
406      receive_register_reset();
407   }
408
409   if(is_transmit_register_empty())
410   {
411      if(!(m_regs.lsr & 0x20))
412      {
413         transmit_register_setup(m_regs.thr);
414         m_regs.lsr &= ~0x40;
415         m_regs.lsr |= 0x20;
416         trigger_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
417      }
418      else
419         m_regs.lsr |= 0x40;
420   }
421   else
422      m_out_tx_func(transmit_register_get_data_bit());
423}
424
425430void ins8250_uart_device::device_start()
426431{
427432   m_out_tx_func.resolve(m_out_tx_cb, *this);
r14547r14548
431436   m_out_out1_func.resolve(m_out_out1_cb, *this);
432437   m_out_out2_func.resolve(m_out_out2_cb, *this);
433438
434   m_timer = timer_alloc();
435439}
436440
437441void ins8250_uart_device::device_reset()
r14547r14548
443447   m_regs.mcr = 0;
444448   m_regs.lsr = (1<<5) | (1<<6);
445449   m_int_pending = 0;
446   m_rx_line = 0;
447   m_timer->adjust(attotime::never);
448450   receive_register_reset();
449451   transmit_register_reset();
450452   m_out_rts_func(0);
451453   m_out_dtr_func(0);
452454   m_out_out1_func(0);
453455   m_out_out2_func(0);
456   m_out_tx_func(1);
454457}
455458
456459void ins8250_uart_device::device_config_complete()
src/emu/machine/ins8250.h
r14547r14548
3434   DECLARE_WRITE_LINE_MEMBER( dsr_w );
3535   DECLARE_WRITE_LINE_MEMBER( ri_w );
3636   DECLARE_WRITE_LINE_MEMBER( cts_w );
37   DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_rx_line = state; }
37   DECLARE_WRITE_LINE_MEMBER( rx_w ) { check_for_start(state); }
3838   void input_callback(UINT8 state) { m_input_state = state; }
3939
4040protected:
4141   virtual void device_start();
4242   virtual void device_config_complete();
4343   virtual void device_reset();
44   virtual void rcv_complete();
45   virtual void tra_complete();
46   virtual void tra_callback();
47
4448   enum {
4549         TYPE_INS8250 = 0,
4650         TYPE_INS8250A,
r14547r14548
6468      UINT8 scr;  /* 7 RW scratch register */
6569   } m_regs;
6670   UINT8 m_int_pending;
67   UINT8 m_rx_line;
6871
6972   devcb_resolved_write_line   m_out_tx_func;
7073   devcb_resolved_write_line   m_out_dtr_func;
r14547r14548
7780   void update_clock();
7881   void trigger_int(int flag);
7982   void clear_int(int flag);
80   void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
8183   void update_msr(int bit, UINT8 state);
82
83   emu_timer *m_timer;
8484};
8585
8686class ins8250_device : public ins8250_uart_device
src/emu/machine/microtch.c
r14547r14548
308308void microtouch_serial_device::device_start()
309309{
310310   microtouch_device::device_start();
311   m_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
312311   set_data_frame(8, 1, SERIAL_PARITY_NONE); //8N1?
312   set_tra_rate(clock());
313   set_rcv_rate(clock());
313314   m_out_stx_func.resolve(m_out_stx_cb, *this);
314315   m_count = 0;
315316   m_output_valid = false;
r14547r14548
317318   save_item(NAME(m_count));
318319   save_item(NAME(m_output_valid));
319320   save_item(NAME(m_output));
320   save_item(NAME(m_rx_line));
321321}
322322
323void microtouch_serial_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
323void microtouch_serial_device::tx(UINT8 data)
324324{
325   m_output = data;
326   m_output_valid = true;
325327   if(is_transmit_register_empty())
326   {
327      if(m_output_valid)
328      {
329         transmit_register_setup(m_output);
330         m_output_valid = false;
331      }
332   }
333   else
334      m_out_stx_func(transmit_register_get_data_bit());
328      tra_complete();
329}
335330
336   receive_register_update_bit(m_rx_line);
337   if(is_receive_register_full())
331void microtouch_serial_device::tra_callback()
332{
333   m_out_stx_func(transmit_register_get_data_bit());
334}
335
336void microtouch_serial_device::tra_complete()
337{
338   if(m_output_valid)
338339   {
339      receive_register_extract();
340      microtouch_device::rx(*memory_nonspecific_space(machine()), 0, get_received_char());
341      receive_register_reset();
340      transmit_register_setup(m_output);
341      m_output_valid = false;
342342   }
343}
343344
344   if((m_count == 0) && (m_output_valid == false))
345      microtouch_device::device_timer(timer, id, param, ptr);
346
347   ++m_count %= 8;
345void microtouch_serial_device::rcv_complete()
346{
347   receive_register_extract();
348   microtouch_device::rx(*memory_nonspecific_space(machine()), 0, get_received_char());
348349}
src/emu/machine/microtch.h
r14547r14548
8080public:
8181   microtouch_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
8282
83   DECLARE_WRITE_LINE_MEMBER(rx) {m_rx_line = state;}
83   DECLARE_WRITE_LINE_MEMBER(rx) { check_for_start(state); }
8484protected:
8585   virtual void device_start();
86   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
8786   virtual void device_config_complete();
88   virtual void tx(UINT8 data) {m_output = data; m_output_valid = true;}
87   virtual void tx(UINT8 data);
8988   virtual void input_callback(UINT8 state) { m_input_state = state; }
89   virtual void tra_callback();
90   virtual void tra_complete();
91   virtual void rcv_complete();
9092private:
9193   int m_count;
9294   bool m_output_valid;
9395   UINT8 m_output;
94   UINT8 m_rx_line;
9596   devcb_resolved_write_line m_out_stx_func;
9697};
9798
src/emu/machine/mc146818.c
r14547r14548
476476      case 0x0a:
477477         // fixme: allow different time base
478478         data &= 0x0f;
479         if (m_data[0x0b] & 0x40) {
480            if (data > 2)
481               m_period = attotime::from_hz(32768 >> (data - 1));
482            else if (data > 0)
483               m_period = attotime::from_hz(32768 >> (data + 6));
484            else m_period = attotime::never;
485            rate = attotime::zero;
486         } else rate = attotime::never;
479         if (data > 2)
480            m_period = attotime::from_hz(32768 >> (data - 1));
481         else if (data > 0)
482            m_period = attotime::from_hz(32768 >> (data + 6));
483         else m_period = attotime::never;
484
485         if(m_data[0x0b] & 0x40)
486             rate = attotime::zero;
487         else rate = attotime::never;
488
487489         m_periodic_timer->adjust(rate, 0, m_period);
488490         data |= m_data[m_index % MC146818_DATA_SIZE] & 0xf0;
489491         m_data[m_index % MC146818_DATA_SIZE] = data;
src/mess/machine/ser_mouse.c
r14547r14548
3535   m_timer = timer_alloc();
3636   m_enabled = false;
3737   set_frame();
38   set_tra_rate(1200);
3839}
3940
4041void serial_mouse_device::device_reset()
r14547r14548
5152   m_owner->out_cts(0);
5253}
5354
55void serial_mouse_device::tra_complete()
56{
57   if(m_tail != m_head)
58      transmit_register_setup(unqueue_data());
59}
60
61void serial_mouse_device::tra_callback()
62{
63   m_rbit = transmit_register_get_data_bit();
64   m_owner->out_rx(m_rbit);
65}
66
5467/**************************************************************************
5568 *  Check for mouse moves and buttons. Build delta x/y packets
5669 **************************************************************************/
r14547r14548
6275   int mbc;
6376
6477   /* Do not get deltas or send packets if queue is not empty (Prevents drifting) */
65   if ((m_head==m_tail) && (m_count == 0))
78   if (m_head==m_tail)
6679   {
6780      nx = input_port_read(*this, "ser_mouse_x");
6881
r14547r14548
87100         mouse_trans(dx, dy, nb, mbc);
88101   }
89102
90   ++m_count %= 8;
91103
92   if(is_transmit_register_empty())
93   {
94      if(m_tail != m_head)
95         transmit_register_setup(unqueue_data());
96   }
97   else
98   {
99      m_rbit = transmit_register_get_data_bit();
100      m_owner->out_rx(m_rbit);
101   }
104   if(m_tail != m_head && is_transmit_register_empty())
105      transmit_register_setup(unqueue_data());
102106}
103107   
104108void microsoft_mouse_device::mouse_trans(int dx, int dy, int nb, int mbc)
r14547r14548
181185void serial_mouse_device::set_mouse_enable(bool state)
182186{
183187   if(state && !m_enabled)
184      m_timer->adjust(attotime::zero, 0, attotime::from_hz(1200));
188   {
189      m_timer->adjust(attotime::zero, 0, attotime::from_hz(240));
190      m_rbit = 1;
191      m_owner->out_rx(1);
192   }
185193   else if(!state && m_enabled)
186194   {
187195      m_timer->adjust(attotime::never);
188196      m_head = m_tail = 0;
197      m_rbit = 0;
198      m_owner->out_rx(0);
189199   }
190200   m_enabled = state;
191201
src/mess/machine/ser_mouse.h
r14547r14548
3030   void queue_data(UINT8 data) {m_queue[m_head] = data; ++m_head %= 256;}
3131   UINT8 unqueue_data() {UINT8 ret = m_queue[m_tail]; ++m_tail %= 256; return ret;}
3232   virtual void input_callback(UINT8 state) { m_input_state = state; }
33   virtual void tra_complete();
34   virtual void tra_callback();
3335private:
3436   UINT8 m_queue[256];
3537   UINT8 m_head, m_tail, m_mb;
src/mess/machine/terminal.c
r14547r14548
551551{
552552   terminal_state *term = get_safe_token(device);
553553   const terminal_interface *intf = get_interface(device);
554   if(dynamic_cast<serial_terminal_device *>(device->owner()))
555      term->terminal_keyboard_func.resolve(intf->terminal_keyboard_func, *device->owner());
556   else
557      term->terminal_keyboard_func.resolve(intf->terminal_keyboard_func, *device);
554   term->terminal_keyboard_func.resolve(intf->terminal_keyboard_func, *device);
558555
559556   if (device->clock())
560557      device->machine().scheduler().timer_pulse(attotime::from_hz(device->clock()), FUNC(serial_callback), 0, (void*)device);
r14547r14548
573570   term->last_code = 0;
574571   term->scan_line = 0;
575572   term->rx_state = START;
576   term->tx_state = STOP;
573   term->tx_state = DONE;
577574}
578575
579576/*
r14547r14548
754751}
755752
756753static const terminal_interface serial_terminal_terminal_interface = {
757      DEVCB_MEMBER(serial_terminal_device, serial_keyboard_func)
754      DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, serial_terminal_device, serial_keyboard_func)
758755};
759756
760757static MACHINE_CONFIG_FRAGMENT(serial_terminal_config)
r14547r14548
767764{
768765      return MACHINE_CONFIG_NAME(serial_terminal_config);
769766}
770
src/mess/machine/terminal.h
r14547r14548
4949
5050UINT8 terminal_keyboard_handler(running_machine &machine, UINT8 last_code, UINT8 *scan_line, UINT8 *tx_shift, int *tx_state, device_t *device);
5151
52
5352class serial_terminal_device :
5453      public device_t,
5554      public device_serial_port_interface
r14547r14548
6160   DECLARE_WRITE8_MEMBER(serial_keyboard_func) { m_rbit = data&&1; m_owner->out_rx(m_rbit); }
6261protected:
6362   virtual void device_start() { m_owner = dynamic_cast<serial_port_device *>(owner()); }
63   virtual void device_reset() { m_owner->out_rx(1); m_rbit = 1; }
6464private:
6565   required_device<device_t> m_terminal;
6666   serial_port_device *m_owner;
src/mess/machine/null_modem.h
r14547r14548
1616   virtual void tx(UINT8 state) { m_tbit = state; m_bitbanger->output(state); }
1717protected:
1818   virtual void device_start() { m_owner = dynamic_cast<serial_port_device *>(owner()); }
19   virtual void device_reset() { m_owner->out_rx(1); m_rbit = 1; }
1920private:
2021   serial_port_device *m_owner;
2122   required_device<bitbanger_device> m_bitbanger;

Previous 15994 Revisions Next


© 1998-2018 The MESS Team