trunk/src/emu/machine/pit8253.c
| r31655 | r31656 | |
| 41 | 41 | #define LOG1(msg) do { if (VERBOSE >= 1) logerror msg; } while (0) |
| 42 | 42 | #define LOG2(msg) do { if (VERBOSE >= 2) logerror msg; } while (0) |
| 43 | 43 | |
| 44 | | #define CYCLES_NEVER (0xffffffff) |
| 45 | 44 | |
| 46 | | |
| 47 | 45 | const device_type PIT8253 = &device_creator<pit8253_device>; |
| 48 | 46 | |
| 49 | 47 | |
| r31655 | r31656 | |
| 56 | 54 | m_out1_handler(*this), |
| 57 | 55 | m_out2_handler(*this) |
| 58 | 56 | { |
| 59 | | for (int i = 0; i < PIT8253_MAX_TIMER; i++) |
| 60 | | { |
| 61 | | m_timers[i].gate = 1; |
| 62 | | m_timers[i].phase = 0; |
| 63 | | m_timers[i].clock = 0; |
| 64 | | } |
| 65 | 57 | } |
| 66 | 58 | |
| 67 | 59 | pit8253_device::pit8253_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : |
| r31655 | r31656 | |
| 73 | 65 | m_out1_handler(*this), |
| 74 | 66 | m_out2_handler(*this) |
| 75 | 67 | { |
| 76 | | for (int i = 0; i < PIT8253_MAX_TIMER; i++) |
| 77 | | { |
| 78 | | m_timers[i].gate = 1; |
| 79 | | m_timers[i].phase = 0; |
| 80 | | m_timers[i].clock = 0; |
| 81 | | } |
| 82 | 68 | } |
| 83 | 69 | |
| 84 | 70 | |
| r31655 | r31656 | |
| 90 | 76 | } |
| 91 | 77 | |
| 92 | 78 | |
| 79 | pit8253_device::pit8253_timer *pit8253_device::get_timer(int which) |
| 80 | { |
| 81 | which &= 3; |
| 82 | if (which < PIT8253_MAX_TIMER) |
| 83 | return &m_timers[which]; |
| 84 | |
| 85 | return NULL; |
| 86 | } |
| 87 | |
| 88 | |
| 93 | 89 | //------------------------------------------------- |
| 94 | 90 | // device_start - device-specific startup |
| 95 | 91 | //------------------------------------------------- |
| r31655 | r31656 | |
| 107 | 103 | /* register for state saving */ |
| 108 | 104 | for (int timerno = 0; timerno < PIT8253_MAX_TIMER; timerno++) |
| 109 | 105 | { |
| 110 | | pit8253_timer *timer = &m_timers[timerno]; |
| 111 | | |
| 106 | pit8253_timer *timer = get_timer(timerno); |
| 107 | |
| 112 | 108 | /* initialize timer */ |
| 113 | 109 | timer->updatetimer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pit8253_device::update_timer_cb),this)); |
| 114 | 110 | timer->updatetimer->adjust(attotime::never, timerno); |
| r31655 | r31656 | |
| 131 | 127 | save_item(NAME(timer->phase), timerno); |
| 132 | 128 | save_item(NAME(timer->last_updated), timerno); |
| 133 | 129 | save_item(NAME(timer->clock), timerno); |
| 130 | |
| 131 | /* zerofill */ |
| 132 | timer->gate = 1; |
| 133 | timer->phase = 0; |
| 134 | timer->clock = 0; |
| 135 | |
| 136 | timer->index = timerno; |
| 137 | timer->control = timer->status = 0x30; |
| 138 | timer->rmsb = timer->wmsb = 0; |
| 139 | timer->count = timer->value = timer->latch = 0; |
| 140 | timer->lowcount = 0; |
| 141 | |
| 142 | timer->output = 0; |
| 143 | timer->latched_count = 0; |
| 144 | timer->latched_status = 0; |
| 145 | timer->null_count = 1; |
| 146 | |
| 147 | timer->last_updated = machine().time(); |
| 134 | 148 | } |
| 135 | 149 | } |
| 136 | 150 | |
| r31655 | r31656 | |
| 143 | 157 | { |
| 144 | 158 | for (int i = 0; i < PIT8253_MAX_TIMER; i++) |
| 145 | 159 | { |
| 146 | | pit8253_timer *timer = &m_timers[i]; |
| 160 | pit8253_timer *timer = get_timer(i); |
| 161 | |
| 147 | 162 | /* According to Intel's 8254 docs, the state of a timer is undefined |
| 148 | 163 | until the first mode control word is written. Here we define this |
| 149 | 164 | undefined behaviour */ |
| 150 | | timer->index = i; |
| 151 | 165 | timer->control = timer->status = 0x30; |
| 152 | 166 | timer->rmsb = timer->wmsb = 0; |
| 153 | 167 | timer->count = timer->value = timer->latch = 0; |
| 154 | 168 | timer->lowcount = 0; |
| 155 | 169 | |
| 156 | | timer->output = 2; /* output is undetermined */ |
| 170 | timer->output = 2; /* output is undetermined */ |
| 157 | 171 | timer->latched_count = 0; |
| 158 | 172 | timer->latched_status = 0; |
| 159 | 173 | timer->null_count = 1; |
| r31655 | r31656 | |
| 164 | 178 | } |
| 165 | 179 | } |
| 166 | 180 | |
| 167 | | #define CTRL_ACCESS(control) (((control) >> 4) & 0x03) |
| 168 | | #define CTRL_MODE(control) (((control) >> 1) & (((control) & 0x04) ? 0x03 : 0x07)) |
| 169 | | #define CTRL_BCD(control) (((control) >> 0) & 0x01) |
| 170 | 181 | |
| 171 | | |
| 172 | 182 | /*************************************************************************** |
| 173 | 183 | |
| 174 | 184 | Functions |
| 175 | 185 | |
| 176 | 186 | ***************************************************************************/ |
| 177 | 187 | |
| 188 | #define CTRL_ACCESS(control) (((control) >> 4) & 0x03) |
| 189 | #define CTRL_MODE(control) (((control) >> 1) & (((control) & 0x04) ? 0x03 : 0x07)) |
| 190 | #define CTRL_BCD(control) (((control) >> 0) & 0x01) |
| 178 | 191 | |
| 179 | | pit8253_timer *pit8253_device::get_timer(int which) |
| 180 | | { |
| 181 | | which &= 3; |
| 182 | | if (which < PIT8253_MAX_TIMER) |
| 183 | | return &m_timers[which]; |
| 184 | 192 | |
| 185 | | return NULL; |
| 186 | | } |
| 187 | | |
| 188 | | |
| 189 | | int pit8253_device::pit8253_gate(pit8253_timer *timer) |
| 193 | inline UINT32 pit8253_device::adjusted_count(int bcd, UINT16 val) |
| 190 | 194 | { |
| 191 | | return timer->gate; |
| 192 | | } |
| 195 | if (!bcd) |
| 196 | return (val == 0) ? 0x10000 : val; |
| 197 | else if (val == 0) |
| 198 | return 10000; |
| 193 | 199 | |
| 194 | | |
| 195 | | INLINE UINT32 decimal_from_bcd(UINT16 val) |
| 196 | | { |
| 197 | 200 | /* In BCD mode, a nybble loaded with value A-F counts down the same as in |
| 198 | 201 | binary mode, but wraps around to 9 instead of F after 0, so loading the |
| 199 | 202 | count register with 0xFFFF gives a period of |
| r31655 | r31656 | |
| 211 | 214 | } |
| 212 | 215 | |
| 213 | 216 | |
| 214 | | static UINT32 adjusted_count(int bcd, UINT16 val) |
| 215 | | { |
| 216 | | if (!bcd) |
| 217 | | return (val == 0) ? 0x10000 : val; |
| 218 | | return (val == 0) ? 10000 : decimal_from_bcd(val); |
| 219 | | } |
| 220 | | |
| 221 | | |
| 222 | 217 | /* This function subtracts 1 from timer->value "cycles" times, taking into |
| 223 | 218 | account binary or BCD operation, and wrapping around from 0 to 0xFFFF or |
| 224 | 219 | 0x9999 as necessary. */ |
| r31655 | r31656 | |
| 319 | 314 | UINT32 adjusted_value; |
| 320 | 315 | int bcd = CTRL_BCD(timer->control); |
| 321 | 316 | int mode = CTRL_MODE(timer->control); |
| 317 | static const UINT32 CYCLES_NEVER = (0xffffffff); |
| 322 | 318 | UINT32 cycles_to_output = CYCLES_NEVER; |
| 323 | 319 | |
| 324 | 320 | LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n", |
| 325 | | (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, pit8253_gate(timer), timer->output, timer->value)); |
| 321 | (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value)); |
| 326 | 322 | |
| 327 | 323 | switch (mode) |
| 328 | 324 | { |
| r31655 | r31656 | |
| 363 | 359 | load_counter_value(timer); |
| 364 | 360 | } |
| 365 | 361 | |
| 366 | | if (pit8253_gate(timer) == 0) |
| 362 | if (timer->gate == 0) |
| 367 | 363 | { |
| 368 | 364 | cycles_to_output = CYCLES_NEVER; |
| 369 | 365 | } |
| r31655 | r31656 | |
| 475 | 471 | Rising-edge reloads count and initiates counting |
| 476 | 472 | Gate high enables counting. */ |
| 477 | 473 | |
| 478 | | if (pit8253_gate(timer) == 0 || timer->phase == 0) |
| 474 | if (timer->gate == 0 || timer->phase == 0) |
| 479 | 475 | { |
| 480 | 476 | /* Gate low or mode control write forces output high */ |
| 481 | 477 | set_output(timer, 1); |
| r31655 | r31656 | |
| 555 | 551 | Rising-edge reloads count and initiates counting |
| 556 | 552 | Gate high enables counting. */ |
| 557 | 553 | |
| 558 | | if (pit8253_gate(timer) == 0 || timer->phase == 0) |
| 554 | if (timer->gate == 0 || timer->phase == 0) |
| 559 | 555 | { |
| 560 | 556 | /* Gate low or mode control write forces output high */ |
| 561 | 557 | set_output(timer, 1); |
| r31655 | r31656 | |
| 641 | 637 | Mode 4 only: Gate level sensitive only. Low disables counting, high enables it. |
| 642 | 638 | Mode 5 only: Gate rising-edge sensitive only. Rising edge initiates counting */ |
| 643 | 639 | |
| 644 | | if (pit8253_gate(timer) == 0 && mode == 4) |
| 640 | if (timer->gate == 0 && mode == 4) |
| 645 | 641 | { |
| 646 | 642 | cycles_to_output = CYCLES_NEVER; |
| 647 | 643 | } |
| r31655 | r31656 | |
| 703 | 699 | } |
| 704 | 700 | |
| 705 | 701 | LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n", |
| 706 | | (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, pit8253_gate(timer), timer->output, timer->value, cycles_to_output)); |
| 702 | (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value, cycles_to_output)); |
| 707 | 703 | } |
| 708 | 704 | |
| 709 | 705 | |
| r31655 | r31656 | |
| 755 | 751 | |
| 756 | 752 | TIMER_CALLBACK_MEMBER( pit8253_device::update_timer_cb ) |
| 757 | 753 | { |
| 758 | | pit8253_timer *timer = &m_timers[param]; |
| 754 | pit8253_timer *timer = get_timer(param); |
| 759 | 755 | |
| 760 | 756 | LOG2(("pit8253: output_changed(): timer %d\n", param)); |
| 761 | 757 | |
| r31655 | r31656 | |
| 817 | 813 | value = masked_value(timer); |
| 818 | 814 | |
| 819 | 815 | /* Read back current count */ |
| 820 | | switch(CTRL_ACCESS(timer->control)) |
| 816 | switch (CTRL_ACCESS(timer->control)) |
| 821 | 817 | { |
| 822 | 818 | case 0: |
| 823 | 819 | default: |
| r31655 | r31656 | |
| 895 | 891 | timer->latched_status = 1; |
| 896 | 892 | } |
| 897 | 893 | } |
| 894 | |
| 898 | 895 | /* Experimentally determined: the read latch command seems to have no |
| 899 | 896 | effect if we're halfway through a 16-bit read */ |
| 900 | 897 | if ((command & 2) == 0 && !timer->rmsb) |
| 901 | 898 | { |
| 902 | 899 | /* readback count command */ |
| 903 | | |
| 904 | 900 | if (timer->latched_count == 0) |
| 905 | 901 | { |
| 906 | 902 | value = masked_value(timer); |
| 907 | | switch(CTRL_ACCESS(timer->control)) |
| 903 | switch (CTRL_ACCESS(timer->control)) |
| 908 | 904 | { |
| 909 | 905 | case 0: |
| 910 | 906 | /* This should never happen */ |
| r31655 | r31656 | |
| 1001 | 997 | if (machine().time() > timer->last_updated && timer->clockin != 0) |
| 1002 | 998 | middle_of_a_cycle = 1; |
| 1003 | 999 | |
| 1004 | | switch(CTRL_ACCESS(timer->control)) |
| 1000 | switch (CTRL_ACCESS(timer->control)) |
| 1005 | 1001 | { |
| 1006 | 1002 | case 0: |
| 1007 | 1003 | /* This should never happen */ |
| r31655 | r31656 | |
| 1066 | 1062 | void pit8253_device::gate_w(int gate, int state) |
| 1067 | 1063 | { |
| 1068 | 1064 | pit8253_timer *timer = get_timer(gate); |
| 1065 | assert(timer != 0); |
| 1069 | 1066 | |
| 1070 | 1067 | LOG2(("pit8253 : gate_w(): gate=%d state=%d\n", gate, state)); |
| 1071 | 1068 | |
| r31655 | r31656 | |
| 1107 | 1104 | void pit8253_device::set_clockin(int timerno, double new_clockin) |
| 1108 | 1105 | { |
| 1109 | 1106 | pit8253_timer *timer = get_timer(timerno); |
| 1107 | assert(timer != 0); |
| 1110 | 1108 | |
| 1111 | 1109 | LOG2(("pit8253_set_clockin(): PIT timer=%d, clockin = %lf\n", timerno, new_clockin)); |
| 1112 | 1110 | |
| r31655 | r31656 | |
| 1119 | 1117 | void pit8253_device::set_clock_signal(int timerno, int state) |
| 1120 | 1118 | { |
| 1121 | 1119 | pit8253_timer *timer = get_timer(timerno); |
| 1120 | assert(timer != 0); |
| 1122 | 1121 | |
| 1123 | 1122 | LOG2(("pit8253_set_clock_signal(): PIT timer=%d, state = %d\n", timerno, state)); |
| 1124 | 1123 | |
trunk/src/emu/machine/pit8253.h
| r31655 | r31656 | |
| 46 | 46 | devcb = &pit8253_device::set_out2_handler(*device, DEVCB_##_devcb); |
| 47 | 47 | |
| 48 | 48 | |
| 49 | | struct pit8253_timer |
| 50 | | { |
| 51 | | int index; /* index number of the timer */ |
| 52 | | double clockin; /* input clock frequency in Hz */ |
| 53 | | int clock; /* clock signal when clockin is 0 */ |
| 54 | | |
| 55 | | attotime last_updated; /* time when last updated */ |
| 56 | | |
| 57 | | emu_timer *updatetimer; /* MAME timer to process updates */ |
| 58 | | |
| 59 | | UINT16 value; /* current counter value ("CE" in Intel docs) */ |
| 60 | | UINT16 latch; /* latched counter value ("OL" in Intel docs) */ |
| 61 | | UINT16 count; /* new counter value ("CR" in Intel docs) */ |
| 62 | | UINT8 control; /* 6-bit control byte */ |
| 63 | | UINT8 status; /* status byte - 8254 only */ |
| 64 | | UINT8 lowcount; /* LSB of new counter value for 16-bit writes */ |
| 65 | | int rmsb; /* 1 = Next read is MSB of 16-bit value */ |
| 66 | | int wmsb; /* 1 = Next write is MSB of 16-bit value */ |
| 67 | | int output; /* 0 = low, 1 = high */ |
| 68 | | |
| 69 | | int gate; /* gate input (0 = low, 1 = high) */ |
| 70 | | int latched_count; /* number of bytes of count latched */ |
| 71 | | int latched_status; /* 1 = status latched (8254 only) */ |
| 72 | | int null_count; /* 1 = mode control or count written, 0 = count loaded */ |
| 73 | | int phase; /* see phase definition tables in simulate2(), below */ |
| 74 | | }; |
| 75 | | |
| 76 | 49 | class pit8253_device : public device_t |
| 77 | 50 | { |
| 78 | 51 | public: |
| r31655 | r31656 | |
| 117 | 90 | virtual void device_reset(); |
| 118 | 91 | |
| 119 | 92 | // internal state |
| 93 | struct pit8253_timer |
| 94 | { |
| 95 | int index; /* index number of the timer */ |
| 96 | double clockin; /* input clock frequency in Hz */ |
| 97 | int clock; /* clock signal when clockin is 0 */ |
| 98 | |
| 99 | attotime last_updated; /* time when last updated */ |
| 100 | |
| 101 | emu_timer *updatetimer; /* MAME timer to process updates */ |
| 102 | |
| 103 | UINT16 value; /* current counter value ("CE" in Intel docs) */ |
| 104 | UINT16 latch; /* latched counter value ("OL" in Intel docs) */ |
| 105 | UINT16 count; /* new counter value ("CR" in Intel docs) */ |
| 106 | UINT8 control; /* 6-bit control byte */ |
| 107 | UINT8 status; /* status byte - 8254 only */ |
| 108 | UINT8 lowcount; /* LSB of new counter value for 16-bit writes */ |
| 109 | int rmsb; /* 1 = Next read is MSB of 16-bit value */ |
| 110 | int wmsb; /* 1 = Next write is MSB of 16-bit value */ |
| 111 | int output; /* 0 = low, 1 = high */ |
| 112 | |
| 113 | int gate; /* gate input (0 = low, 1 = high) */ |
| 114 | int latched_count; /* number of bytes of count latched */ |
| 115 | int latched_status; /* 1 = status latched (8254 only) */ |
| 116 | int null_count; /* 1 = mode control or count written, 0 = count loaded */ |
| 117 | int phase; /* see phase definition tables in simulate2(), below */ |
| 118 | }; |
| 119 | |
| 120 | 120 | void readback(pit8253_timer *timer, int command); |
| 121 | 121 | virtual void readback_command(UINT8 data); |
| 122 | 122 | pit8253_timer *get_timer(int which); |
| 123 | 123 | |
| 124 | 124 | private: |
| 125 | | int pit8253_gate(pit8253_timer *timer); |
| 125 | double m_clk0; |
| 126 | double m_clk1; |
| 127 | double m_clk2; |
| 128 | devcb_write_line m_out0_handler; |
| 129 | devcb_write_line m_out1_handler; |
| 130 | devcb_write_line m_out2_handler; |
| 131 | |
| 132 | enum |
| 133 | { |
| 134 | PIT8253_MAX_TIMER = 3 |
| 135 | }; |
| 136 | |
| 137 | pit8253_timer m_timers[PIT8253_MAX_TIMER]; |
| 138 | |
| 139 | TIMER_CALLBACK_MEMBER(update_timer_cb); |
| 140 | |
| 141 | inline UINT32 adjusted_count(int bcd, UINT16 val); |
| 126 | 142 | void decrease_counter_value(pit8253_timer *timer, INT64 cycles); |
| 127 | 143 | void load_counter_value(pit8253_timer *timer); |
| 128 | 144 | void set_output(pit8253_timer *timer, int output); |
| r31655 | r31656 | |
| 133 | 149 | void load_count(pit8253_timer *timer, UINT16 newcount); |
| 134 | 150 | void gate_w(int gate, int state); |
| 135 | 151 | void set_clock_signal(int timerno, int state); |
| 136 | | |
| 137 | | TIMER_CALLBACK_MEMBER(update_timer_cb); |
| 138 | | |
| 139 | | enum |
| 140 | | { |
| 141 | | PIT8253_MAX_TIMER = 3 |
| 142 | | }; |
| 143 | | |
| 144 | | pit8253_timer m_timers[PIT8253_MAX_TIMER]; |
| 145 | | |
| 146 | | double m_clk0; |
| 147 | | double m_clk1; |
| 148 | | double m_clk2; |
| 149 | | devcb_write_line m_out0_handler; |
| 150 | | devcb_write_line m_out1_handler; |
| 151 | | devcb_write_line m_out2_handler; |
| 152 | 152 | }; |
| 153 | 153 | |
| 154 | 154 | extern const device_type PIT8253; |