src/mess/drivers/craft.c
| r10098 | r10099 | |
| 37 | 37 | * I/O devices * |
| 38 | 38 | \****************************************************/ |
| 39 | 39 | |
| 40 | static TIMER_CALLBACK( avr8_timer0_tick ); |
| 41 | static TIMER_CALLBACK( avr8_timer1_tick ); |
| 42 | static TIMER_CALLBACK( avr8_timer2_tick ); |
| 43 | |
| 40 | 44 | class craft_state : public driver_device |
| 41 | 45 | { |
| 42 | 46 | public: |
| 43 | 47 | craft_state(running_machine &machine, const driver_device_config_base &config) |
| 44 | | : driver_device(machine, config) { } |
| 48 | : driver_device(machine, config) |
| 49 | { |
| 50 | timer0_timer = timer_alloc(&machine, avr8_timer0_tick, 0); |
| 51 | timer0_increment = 1; |
| 45 | 52 | |
| 53 | timer1_timer = timer_alloc(&machine, avr8_timer1_tick, 0); |
| 54 | timer1_increment = 1; |
| 55 | |
| 56 | timer2_timer = timer_alloc(&machine, avr8_timer2_tick, 0); |
| 57 | timer2_increment = 1; |
| 58 | } |
| 59 | |
| 46 | 60 | UINT8 regs[0x100]; |
| 47 | | INT32 tcnt1_direction; |
| 48 | 61 | |
| 49 | | emu_timer* ocr1a_timer; |
| 50 | | emu_timer* ocr1b_timer; |
| 62 | emu_timer* timer0_timer; |
| 63 | UINT8 timer0_top; |
| 64 | INT32 timer0_increment; |
| 65 | |
| 66 | emu_timer* timer1_timer; |
| 67 | UINT16 timer1_top; |
| 68 | INT32 timer1_increment; |
| 69 | |
| 70 | emu_timer* timer2_timer; |
| 71 | UINT8 timer2_top; |
| 72 | INT32 timer2_increment; |
| 51 | 73 | }; |
| 52 | 74 | |
| 53 | 75 | enum |
| r10098 | r10099 | |
| 60 | 82 | |
| 61 | 83 | static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; |
| 62 | 84 | |
| 63 | | #if 0 |
| 64 | | static UINT64 avr8_get_timer_1_frequency(craft_state *state) |
| 85 | static TIMER_CALLBACK( avr8_timer0_tick ) |
| 65 | 86 | { |
| 66 | | UINT64 frequency = 0; |
| 67 | | switch(AVR8_TCCR1B & 0x07) |
| 68 | | { |
| 69 | | case 0: // No clock source (Timer/Counter stopped). |
| 70 | | case 6: // External clock source on T1 pin. Clock on falling edge. |
| 71 | | case 7: // External clock source on T1 pin. Clock on rising edge. |
| 72 | | frequency = 0; |
| 73 | | break; |
| 87 | // TODO |
| 88 | } |
| 74 | 89 | |
| 75 | | case 1: // clk / 1 (No prescaling) |
| 76 | | frequency = MASTER_CLOCK; |
| 77 | | break; |
| 90 | static TIMER_CALLBACK( avr8_timer1_tick ) |
| 91 | { |
| 92 | /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP |
| 78 | 93 | |
| 79 | | case 2: // clk / 8 (From prescaler) |
| 80 | | frequency = MASTER_CLOCK / 8; |
| 81 | | break; |
| 94 | craft_state *state = machine->driver_data<craft_state>(); |
| 95 | UINT16 count = AVR8_TCNT1; |
| 96 | count += state->timer1_increment; |
| 82 | 97 | |
| 83 | | case 3: // clk / 64 (From prescaler) |
| 84 | | frequency = MASTER_CLOCK / 64; |
| 85 | | break; |
| 98 | for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) |
| 99 | { |
| 100 | UINT8 mode = (reg == AVR8_REG_A) ? AVR8_TCCR1A_COM1A : AVR8_TCCR1A_COM1B; |
| 101 | switch(mode) |
| 102 | { |
| 103 | case 0: |
| 104 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); |
| 105 | break; |
| 86 | 106 | |
| 87 | | case 4: // clk / 256 (From prescaler) |
| 88 | | frequency = MASTER_CLOCK / 256; |
| 89 | | break; |
| 107 | case 1: |
| 108 | switch(AVR8_WGM1) |
| 109 | { |
| 110 | case Avr8::WGM1_NORMAL: |
| 111 | case Avr8::WGM1_CTC_OCR: |
| 112 | case Avr8::WGM1_CTC_ICR: |
| 113 | case Avr8::WGM1_FAST_PWM_8: |
| 114 | case Avr8::WGM1_FAST_PWM_9: |
| 115 | case Avr8::WGM1_FAST_PWM_10: |
| 116 | case Avr8::WGM1_PWM_8_PC: |
| 117 | case Avr8::WGM1_PWM_9_PC: |
| 118 | case Avr8::WGM1_PWM_10_PC: |
| 119 | case Avr8::WGM1_PWM_PFC_ICR: |
| 120 | case Avr8::WGM1_PWM_PC_ICR: |
| 121 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); |
| 122 | break; |
| 90 | 123 | |
| 91 | | case 5: // clk / 1024 (From prescaler) |
| 92 | | frequency = MASTER_CLOCK / 1024; |
| 93 | | break; |
| 124 | case Avr8::WGM1_FAST_PWM_ICR: |
| 125 | case Avr8::WGM1_FAST_PWM_OCR: |
| 126 | case Avr8::WGM1_PWM_PFC_OCR: |
| 127 | case Avr8::WGM1_PWM_PC_OCR: |
| 128 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Toggle OC1A on compare match, OC1B disconnected\n"); |
| 129 | break; |
| 130 | } |
| 131 | break; |
| 94 | 132 | |
| 95 | | default: |
| 96 | | frequency = 0; |
| 97 | | fatalerror( "&state->tccr1b & 0x07 returned a value not in the range of 0 to 7." ); |
| 98 | | break; |
| 99 | | } |
| 133 | case 2: |
| 134 | switch(AVR8_WGM1) |
| 135 | { |
| 136 | case Avr8::WGM1_NORMAL: |
| 137 | case Avr8::WGM1_CTC_OCR: |
| 138 | case Avr8::WGM1_CTC_ICR: |
| 139 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Clear OC1%c on compare match\n", avr8_reg_name[reg]); |
| 140 | break; |
| 100 | 141 | |
| 101 | | return frequency; |
| 102 | | } |
| 142 | case Avr8::WGM1_PWM_8_PC: |
| 143 | case Avr8::WGM1_PWM_9_PC: |
| 144 | case Avr8::WGM1_PWM_10_PC: |
| 145 | case Avr8::WGM1_PWM_PFC_ICR: |
| 146 | case Avr8::WGM1_PWM_PC_ICR: |
| 147 | case Avr8::WGM1_PWM_PFC_OCR: |
| 148 | case Avr8::WGM1_PWM_PC_OCR: |
| 149 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Clear OC1%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]); |
| 150 | break; |
| 103 | 151 | |
| 104 | | static UINT16 avr8_get_tc1_top(craft_state *state) |
| 105 | | { |
| 106 | | switch(AVR8_WGM1) |
| 107 | | { |
| 108 | | case AVR8_WGM1_NORMAL: |
| 109 | | return 0xffff; |
| 152 | case Avr8::WGM1_FAST_PWM_8: |
| 153 | case Avr8::WGM1_FAST_PWM_9: |
| 154 | case Avr8::WGM1_FAST_PWM_10: |
| 155 | case Avr8::WGM1_FAST_PWM_ICR: |
| 156 | case Avr8::WGM1_FAST_PWM_OCR: |
| 157 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Clear OC1%c on compare match, set at BOTTOM\n", avr8_reg_name[reg]); |
| 158 | break; |
| 159 | } |
| 160 | break; |
| 110 | 161 | |
| 111 | | case AVR8_WGM1_PWM_8_PC: |
| 112 | | case AVR8_WGM1_FAST_PWM_8: |
| 113 | | return 0x00ff; |
| 162 | case 3: |
| 163 | switch(AVR8_WGM1) |
| 164 | { |
| 165 | case Avr8::WGM1_NORMAL: |
| 166 | case Avr8::WGM1_CTC_OCR: |
| 167 | case Avr8::WGM1_CTC_ICR: |
| 168 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Set OC1%c on compare match\n", avr8_reg_name[reg]); |
| 169 | break; |
| 114 | 170 | |
| 115 | | case AVR8_WGM1_PWM_9_PC: |
| 116 | | case AVR8_WGM1_FAST_PWM_9: |
| 117 | | return 0x01ff; |
| 171 | case Avr8::WGM1_PWM_8_PC: |
| 172 | case Avr8::WGM1_PWM_9_PC: |
| 173 | case Avr8::WGM1_PWM_10_PC: |
| 174 | case Avr8::WGM1_PWM_PFC_ICR: |
| 175 | case Avr8::WGM1_PWM_PC_ICR: |
| 176 | case Avr8::WGM1_PWM_PFC_OCR: |
| 177 | case Avr8::WGM1_PWM_PC_OCR: |
| 178 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Set OC1%c on match when up-counting, clear on match when down-counting\n", avr8_reg_name[reg]); |
| 179 | break; |
| 118 | 180 | |
| 119 | | case AVR8_WGM1_PWM_10_PC: |
| 120 | | case AVR8_WGM1_FAST_PWM_10: |
| 121 | | return 0x03ff; |
| 122 | | |
| 123 | | case AVR8_WGM1_CTC_ICR: |
| 124 | | case AVR8_WGM1_PWM_PFC_ICR: |
| 125 | | case AVR8_WGM1_PWM_PC_ICR: |
| 126 | | case AVR8_WGM1_FAST_PWM_ICR: |
| 127 | | return AVR8_ICR1; |
| 128 | | |
| 129 | | case AVR8_WGM1_CTC_OCR: |
| 130 | | case AVR8_WGM1_PWM_PFC_OCR: |
| 131 | | case AVR8_WGM1_PWM_PC_OCR: |
| 132 | | case AVR8_WGM1_FAST_PWM_OCR: |
| 133 | | return AVR8_OCR1A; |
| 134 | | |
| 135 | | case AVR8_WGM1_RESERVED: |
| 136 | | logerror("Attempting to retrieve TOP for a reserved waveform generation mode\n"); |
| 137 | | return 0xffff; |
| 138 | | } |
| 139 | | return 0xffff; |
| 140 | | } |
| 141 | | |
| 142 | | static UINT16 avr8_get_tc1_distance(craft_state *state, INT32 reg) |
| 143 | | { |
| 144 | | UINT16 top = avr8_get_tc1_top(state); |
| 145 | | UINT16 ocr = (reg == Avr8::REGIDX_A) ? AVR8_OCR1A : AVR8_OCR1B; |
| 146 | | if(AVR8_TCNT1_DIR > 0) |
| 147 | | { |
| 148 | | if(AVR8_TCNT1 < ocr) |
| 149 | | { |
| 150 | | return ocr - AVR8_TCNT1; |
| 181 | case Avr8::WGM1_FAST_PWM_8: |
| 182 | case Avr8::WGM1_FAST_PWM_9: |
| 183 | case Avr8::WGM1_FAST_PWM_10: |
| 184 | case Avr8::WGM1_FAST_PWM_ICR: |
| 185 | case Avr8::WGM1_FAST_PWM_OCR: |
| 186 | //verboselog(machine, 0, "avr8_update_timer1_compare_mode: Set OC1%c on compare match, clear at BOTTOM\n", avr8_reg_name[reg]); |
| 187 | break; |
| 188 | } |
| 189 | break; |
| 190 | default: |
| 191 | verboselog(machine, 0, "avr8_update_timer1_compare_mode: Unknown COM1%c mode setting (%d)\n", avr8_reg_name[reg], mode); |
| 192 | break; |
| 151 | 193 | } |
| 152 | | else |
| 153 | | { |
| 154 | | return top - AVR8_TCNT1; |
| 155 | | } |
| 156 | 194 | } |
| 157 | | else |
| 158 | | { |
| 159 | | if(AVR8_TCNT1 > ocr) |
| 160 | | { |
| 161 | | return AVR8_TCNT1 - ocr; |
| 162 | | } |
| 163 | | else |
| 164 | | { |
| 165 | | return ocr; |
| 166 | | } |
| 167 | | } |
| 168 | | return 0xffff; |
| 195 | */ |
| 169 | 196 | } |
| 170 | 197 | |
| 171 | | static void avr8_maybe_start_timer_1(craft_state *state) |
| 172 | | { |
| 173 | | UINT64 frequency = avr8_get_timer_1_frequency(state); |
| 174 | | if(frequency == 0) |
| 175 | | { |
| 176 | | timer_adjust_oneshot(state->ocr1a_timer, attotime_never, 0); |
| 177 | | timer_adjust_oneshot(state->ocr1b_timer, attotime_never, 0); |
| 178 | | } |
| 179 | | else |
| 180 | | { |
| 181 | | attotime period_a = attotime_mul(ATTOTIME_IN_HZ(frequency), avr8_get_tc1_distance(state, Avr8::REGIDX_A)); |
| 182 | | attotime period_b = attotime_mul(ATTOTIME_IN_HZ(frequency), avr8_get_tc1_distance(state, Avr8::REGIDX_B)); |
| 183 | | timer_adjust_oneshot(state->ocr1a_timer, period_a, 0); |
| 184 | | timer_adjust_oneshot(state->ocr1b_timer, period_b, 0); |
| 185 | | } |
| 186 | | } |
| 187 | | #endif |
| 188 | | |
| 189 | | static TIMER_CALLBACK( ocr1a_timer_compare ) |
| 190 | | { |
| 191 | | //craft_state *state = machine->driver_data<craft_state>(); |
| 192 | | //avr8_regs *regs = &state->regs; |
| 193 | | |
| 194 | | // TODO |
| 195 | | |
| 196 | | //avr8_maybe_start_timer_1(regs); |
| 197 | | //cpu_set_input_line(machine->device("maincpu"), AVR8_INT_T1COMPA, ASSERT_LINE); |
| 198 | | } |
| 199 | | |
| 200 | | static TIMER_CALLBACK( ocr1b_timer_compare ) |
| 201 | | { |
| 202 | | //craft_state *state = machine->driver_data<craft_state>(); |
| 203 | | //avr8_regs *regs = &state->regs; |
| 204 | | |
| 205 | | // TODO |
| 206 | | |
| 207 | | //avr8_maybe_start_timer_1(regs); |
| 208 | | //cpu_set_input_line(machine->device("maincpu"), AVR8_INT_T1COMPB, ASSERT_LINE); |
| 209 | | } |
| 210 | | |
| 211 | 198 | static READ8_HANDLER( avr8_read ) |
| 212 | 199 | { |
| 213 | 200 | craft_state *state = space->machine->driver_data<craft_state>(); |
| r10098 | r10099 | |
| 475 | 462 | } |
| 476 | 463 | } |
| 477 | 464 | |
| 478 | | static void avr8_update_timer1_compare_mode(running_machine *machine, int reg) |
| 479 | | { |
| 480 | | // TODO |
| 481 | | craft_state *state = machine->driver_data<craft_state>(); |
| 482 | | UINT8 mode = (reg == AVR8_REG_A) ? AVR8_TCCR1A_COM1A : AVR8_TCCR1A_COM1B; |
| 483 | | switch(mode) |
| 484 | | { |
| 485 | | case 0: |
| 486 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; OCR1%c disconnected, normal port operation\n", avr8_reg_name[reg]); |
| 487 | | break; |
| 488 | | |
| 489 | | case 1: |
| 490 | | switch(AVR8_WGM1) |
| 491 | | { |
| 492 | | case Avr8::WGM1_NORMAL: |
| 493 | | case Avr8::WGM1_CTC_OCR: |
| 494 | | case Avr8::WGM1_CTC_ICR: |
| 495 | | case Avr8::WGM1_FAST_PWM_8: |
| 496 | | case Avr8::WGM1_FAST_PWM_9: |
| 497 | | case Avr8::WGM1_FAST_PWM_10: |
| 498 | | case Avr8::WGM1_PWM_8_PC: |
| 499 | | case Avr8::WGM1_PWM_9_PC: |
| 500 | | case Avr8::WGM1_PWM_10_PC: |
| 501 | | case Avr8::WGM1_PWM_PFC_ICR: |
| 502 | | case Avr8::WGM1_PWM_PC_ICR: |
| 503 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Toggle OC1%c on compare match\n", avr8_reg_name[reg]); |
| 504 | | break; |
| 505 | | |
| 506 | | case Avr8::WGM1_FAST_PWM_ICR: |
| 507 | | case Avr8::WGM1_FAST_PWM_OCR: |
| 508 | | case Avr8::WGM1_PWM_PFC_OCR: |
| 509 | | case Avr8::WGM1_PWM_PC_OCR: |
| 510 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Toggle OC1A on compare match, OC1B disconnected\n"); |
| 511 | | break; |
| 512 | | } |
| 513 | | break; |
| 514 | | |
| 515 | | case 2: |
| 516 | | switch(AVR8_WGM1) |
| 517 | | { |
| 518 | | case Avr8::WGM1_NORMAL: |
| 519 | | case Avr8::WGM1_CTC_OCR: |
| 520 | | case Avr8::WGM1_CTC_ICR: |
| 521 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Clear OC1%c on compare match\n", avr8_reg_name[reg]); |
| 522 | | break; |
| 523 | | |
| 524 | | case Avr8::WGM1_PWM_8_PC: |
| 525 | | case Avr8::WGM1_PWM_9_PC: |
| 526 | | case Avr8::WGM1_PWM_10_PC: |
| 527 | | case Avr8::WGM1_PWM_PFC_ICR: |
| 528 | | case Avr8::WGM1_PWM_PC_ICR: |
| 529 | | case Avr8::WGM1_PWM_PFC_OCR: |
| 530 | | case Avr8::WGM1_PWM_PC_OCR: |
| 531 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Clear OC1%c on match when up-counting, set OC1%c on match when down-counting\n", avr8_reg_name[reg]); |
| 532 | | break; |
| 533 | | |
| 534 | | case Avr8::WGM1_FAST_PWM_8: |
| 535 | | case Avr8::WGM1_FAST_PWM_9: |
| 536 | | case Avr8::WGM1_FAST_PWM_10: |
| 537 | | case Avr8::WGM1_FAST_PWM_ICR: |
| 538 | | case Avr8::WGM1_FAST_PWM_OCR: |
| 539 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Clear OC1%c on compare match, set OC1%c at BOTTOM\n", avr8_reg_name[reg]); |
| 540 | | break; |
| 541 | | } |
| 542 | | break; |
| 543 | | |
| 544 | | case 3: |
| 545 | | switch(AVR8_WGM1) |
| 546 | | { |
| 547 | | case Avr8::WGM1_NORMAL: |
| 548 | | case Avr8::WGM1_CTC_OCR: |
| 549 | | case Avr8::WGM1_CTC_ICR: |
| 550 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Set OC1%c on compare match\n", avr8_reg_name[reg]); |
| 551 | | break; |
| 552 | | |
| 553 | | case Avr8::WGM1_PWM_8_PC: |
| 554 | | case Avr8::WGM1_PWM_9_PC: |
| 555 | | case Avr8::WGM1_PWM_10_PC: |
| 556 | | case Avr8::WGM1_PWM_PFC_ICR: |
| 557 | | case Avr8::WGM1_PWM_PC_ICR: |
| 558 | | case Avr8::WGM1_PWM_PFC_OCR: |
| 559 | | case Avr8::WGM1_PWM_PC_OCR: |
| 560 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Set OC1%c on match when up-counting, clear OC1%c on match when down-counting\n", avr8_reg_name[reg]); |
| 561 | | break; |
| 562 | | |
| 563 | | case Avr8::WGM1_FAST_PWM_8: |
| 564 | | case Avr8::WGM1_FAST_PWM_9: |
| 565 | | case Avr8::WGM1_FAST_PWM_10: |
| 566 | | case Avr8::WGM1_FAST_PWM_ICR: |
| 567 | | case Avr8::WGM1_FAST_PWM_OCR: |
| 568 | | verboselog(machine, 0, "avr8_update_timer1_compare_mode: TODO; Set OC1%c on compare match, clear OC1%c at BOTTOM\n", avr8_reg_name[reg]); |
| 569 | | break; |
| 570 | | } |
| 571 | | break; |
| 572 | | } |
| 573 | | } |
| 574 | | |
| 575 | 465 | static void avr8_update_timer1_waveform_gen_mode(running_machine *machine) |
| 576 | 466 | { |
| 577 | 467 | // TODO |
| 578 | | UINT16 top = 0; |
| 579 | 468 | craft_state *state = machine->driver_data<craft_state>(); |
| 469 | state->timer1_top = 0; |
| 580 | 470 | verboselog(machine, 0, "avr8_update_timer1_waveform_gen_mode: TODO; WGM1 is %d\n", AVR8_WGM1 ); |
| 581 | 471 | switch(AVR8_WGM1) |
| 582 | 472 | { |
| 583 | 473 | case Avr8::WGM1_NORMAL: |
| 584 | | top = 0xffff; |
| 474 | state->timer1_top = 0xffff; |
| 585 | 475 | break; |
| 586 | 476 | |
| 587 | 477 | case Avr8::WGM1_PWM_8_PC: |
| 588 | 478 | case Avr8::WGM1_FAST_PWM_8: |
| 589 | | top = 0x00ff; |
| 479 | state->timer1_top = 0x00ff; |
| 590 | 480 | break; |
| 591 | 481 | |
| 592 | 482 | case Avr8::WGM1_PWM_9_PC: |
| 593 | 483 | case Avr8::WGM1_FAST_PWM_9: |
| 594 | | top = 0x01ff; |
| 484 | state->timer1_top = 0x01ff; |
| 595 | 485 | break; |
| 596 | 486 | |
| 597 | 487 | case Avr8::WGM1_PWM_10_PC: |
| 598 | 488 | case Avr8::WGM1_FAST_PWM_10: |
| 599 | | top = 0x03ff; |
| 489 | state->timer1_top = 0x03ff; |
| 600 | 490 | break; |
| 601 | 491 | |
| 602 | 492 | case Avr8::WGM1_PWM_PFC_ICR: |
| 603 | 493 | case Avr8::WGM1_PWM_PC_ICR: |
| 604 | 494 | case Avr8::WGM1_CTC_ICR: |
| 605 | 495 | case Avr8::WGM1_FAST_PWM_ICR: |
| 606 | | top = AVR8_ICR1; |
| 496 | state->timer1_top = AVR8_ICR1; |
| 607 | 497 | break; |
| 608 | 498 | |
| 609 | 499 | case Avr8::WGM1_PWM_PFC_OCR: |
| 610 | 500 | case Avr8::WGM1_PWM_PC_OCR: |
| 611 | 501 | case Avr8::WGM1_CTC_OCR: |
| 612 | 502 | case Avr8::WGM1_FAST_PWM_OCR: |
| 613 | | top = AVR8_OCR1A; |
| 503 | state->timer1_top = AVR8_OCR1A; |
| 614 | 504 | break; |
| 615 | 505 | |
| 616 | 506 | default: |
| r10098 | r10099 | |
| 627 | 517 | UINT8 newtccr = data; |
| 628 | 518 | UINT8 changed = newtccr ^ oldtccr; |
| 629 | 519 | |
| 630 | | if(changed & AVR8_TCCR1A_COM1A_MASK) |
| 631 | | { |
| 632 | | // TODO |
| 633 | | avr8_update_timer1_compare_mode(machine, AVR8_REG_A); |
| 634 | | } |
| 635 | | |
| 636 | | if(changed & AVR8_TCCR1A_COM1B_MASK) |
| 637 | | { |
| 638 | | // TODO |
| 639 | | avr8_update_timer1_compare_mode(machine, AVR8_REG_B); |
| 640 | | } |
| 641 | | |
| 642 | 520 | if(changed & AVR8_TCCR1A_WGM1_10) |
| 643 | 521 | { |
| 644 | 522 | // TODO |
| r10098 | r10099 | |
| 657 | 535 | verboselog(machine, 0, "avr8_update_timer1_input_edge_select: TODO; Clocking edge is %s\n", "test"); |
| 658 | 536 | } |
| 659 | 537 | |
| 538 | static TIMER_CALLBACK( avr8_timer2_tick ) |
| 539 | { |
| 540 | /* TODO: Handle comparison, setting OC2x pins, detection of BOTTOM and TOP |
| 541 | |
| 542 | craft_state *state = machine->driver_data<craft_state>(); |
| 543 | UINT16 count = AVR8_TCNT2; |
| 544 | count += state->timer1_increment; |
| 545 | for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) |
| 546 | { |
| 547 | UINT8 mode = (reg == AVR8_REG_A) ? AVR8_TCCR2A_COM2A : AVR8_TCCR2A_COM2B; |
| 548 | |
| 549 | if(!mode) |
| 550 | { |
| 551 | // Normal port operation, OC2n disconnected |
| 552 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); |
| 553 | return; |
| 554 | } |
| 555 | |
| 556 | switch(AVR8_WGM2) |
| 557 | { |
| 558 | case Avr8::WGM2_NORMAL: |
| 559 | case Avr8::WGM2_CTC_CMP: |
| 560 | switch(mode) |
| 561 | { |
| 562 | case 1: // Toggle OC2n on Compare Match |
| 563 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on Compare Match\n", avr8_reg_name[reg]); |
| 564 | break; |
| 565 | case 2: // Clear OC2n on Compare Match |
| 566 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on Compare Match\n", avr8_reg_name[reg]); |
| 567 | break; |
| 568 | case 3: // Set OC2n on Compare Match |
| 569 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on Compare Match\n", avr8_reg_name[reg]); |
| 570 | break; |
| 571 | } |
| 572 | break; |
| 573 | |
| 574 | case Avr8::WGM2_PWM_PC: |
| 575 | switch(mode) |
| 576 | { |
| 577 | case 1: // Normal port operation, OC2n disconnected |
| 578 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); |
| 579 | break; |
| 580 | case 2: // Clear OC2n on match when up-counting, set when down-counting |
| 581 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]); |
| 582 | break; |
| 583 | case 3: // Set OC2n on match when up-counting, clear when down-counting |
| 584 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]); |
| 585 | break; |
| 586 | } |
| 587 | break; |
| 588 | |
| 589 | case Avr8::WGM2_PWM_PC_CMP: |
| 590 | switch(mode) |
| 591 | { |
| 592 | case 1: // Toggle OC2n on compare match |
| 593 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]); |
| 594 | break; |
| 595 | case 2: // Clear OC2n on match when up-counting, set when down-counting |
| 596 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]); |
| 597 | break; |
| 598 | case 3: // Set OC2n on match when up-counting, clear when down-counting |
| 599 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]); |
| 600 | break; |
| 601 | } |
| 602 | break; |
| 603 | |
| 604 | |
| 605 | case Avr8::WGM2_FAST_PWM: |
| 606 | switch(mode) |
| 607 | { |
| 608 | case 1: // Normal port operation, OC2n disconnected |
| 609 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); |
| 610 | break; |
| 611 | case 2: // Clear OC2n on match, set at BOTTOM |
| 612 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]); |
| 613 | break; |
| 614 | case 3: // Set OC2n on match, clear at BOTTOM |
| 615 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]); |
| 616 | break; |
| 617 | } |
| 618 | break; |
| 619 | |
| 620 | case Avr8::WGM2_FAST_PWM_CMP: |
| 621 | switch(mode) |
| 622 | { |
| 623 | case 1: // Toggle OC2n on compare match |
| 624 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]); |
| 625 | break; |
| 626 | case 2: // Clear OC2n on match, set at BOTTOM |
| 627 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]); |
| 628 | break; |
| 629 | case 3: // Set OC2n on match, clear at BOTTOM |
| 630 | //verboselog(machine, 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]); |
| 631 | break; |
| 632 | } |
| 633 | break; |
| 634 | |
| 635 | default: |
| 636 | break; |
| 637 | } |
| 638 | } |
| 639 | */ |
| 640 | } |
| 641 | |
| 660 | 642 | static void avr8_update_timer1_clock_source(running_machine *machine) |
| 661 | 643 | { |
| 644 | craft_state *state = machine->driver_data<craft_state>(); |
| 645 | attotime period; |
| 646 | switch(AVR8_TIMER2_CLOCK_SELECT) |
| 647 | { |
| 648 | case 0: // Counter stopped |
| 649 | period = attotime_never; |
| 650 | break; |
| 651 | case 1: // Clk/1; no prescaling |
| 652 | period = ATTOTIME_IN_HZ(MASTER_CLOCK); |
| 653 | break; |
| 654 | case 2: // Clk/8 |
| 655 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/8); |
| 656 | break; |
| 657 | case 3: // Clk/32 |
| 658 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/32); |
| 659 | break; |
| 660 | case 4: // Clk/64 |
| 661 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/64); |
| 662 | break; |
| 663 | case 5: // Clk/128 |
| 664 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/128); |
| 665 | break; |
| 666 | case 6: // T1 trigger, falling edge |
| 667 | case 7: // T1 trigger, rising edge |
| 668 | period = attotime_never; |
| 669 | verboselog(machine, 0, "avr8_update_timer1_clock_source: T1 Trigger mode not implemented yet\n"); |
| 670 | break; |
| 671 | } |
| 672 | timer_adjust_periodic(state->timer1_timer, period, 0, period); |
| 662 | 673 | } |
| 663 | 674 | |
| 664 | 675 | static void avr8_changed_tccr1b(running_machine *machine, UINT8 data) |
| r10098 | r10099 | |
| 689 | 700 | |
| 690 | 701 | if(changed & AVR8_TCCR1B_CS_MASK) |
| 691 | 702 | { |
| 692 | | // TODO |
| 693 | 703 | avr8_update_timer1_clock_source(machine); |
| 694 | 704 | } |
| 695 | 705 | } |
| 696 | 706 | |
| 707 | static void avr8_update_timer2_waveform_gen_mode(running_machine *machine) |
| 708 | { |
| 709 | craft_state *state = machine->driver_data<craft_state>(); |
| 710 | state->timer2_top = 0; |
| 711 | switch(AVR8_WGM2) |
| 712 | { |
| 713 | case Avr8::WGM2_NORMAL: |
| 714 | case Avr8::WGM2_PWM_PC: |
| 715 | case Avr8::WGM2_FAST_PWM: |
| 716 | state->timer2_top = 0x00ff; |
| 717 | break; |
| 718 | |
| 719 | case Avr8::WGM2_CTC_CMP: |
| 720 | case Avr8::WGM2_PWM_PC_CMP: |
| 721 | case Avr8::WGM2_FAST_PWM_CMP: |
| 722 | state->timer2_top = AVR8_OCR2A; |
| 723 | break; |
| 724 | |
| 725 | default: |
| 726 | verboselog(machine, 0, "avr8_update_timer2_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM2); |
| 727 | break; |
| 728 | } |
| 729 | } |
| 730 | |
| 731 | static void avr8_changed_tccr2a(running_machine *machine, UINT8 data) |
| 732 | { |
| 733 | craft_state *state = machine->driver_data<craft_state>(); |
| 734 | |
| 735 | UINT8 oldtccr = AVR8_TCCR2A; |
| 736 | UINT8 newtccr = data; |
| 737 | UINT8 changed = newtccr ^ oldtccr; |
| 738 | |
| 739 | if(changed & AVR8_TCCR2A_WGM2_10_MASK) |
| 740 | { |
| 741 | // TODO |
| 742 | avr8_update_timer2_waveform_gen_mode(machine); |
| 743 | } |
| 744 | } |
| 745 | |
| 746 | static void avr8_update_timer2_clock_source(running_machine *machine) |
| 747 | { |
| 748 | craft_state *state = machine->driver_data<craft_state>(); |
| 749 | attotime period; |
| 750 | switch(AVR8_TIMER2_CLOCK_SELECT) |
| 751 | { |
| 752 | case 0: // Counter stopped |
| 753 | period = attotime_never; |
| 754 | break; |
| 755 | case 1: // Clk/1; no prescaling |
| 756 | period = ATTOTIME_IN_HZ(MASTER_CLOCK); |
| 757 | break; |
| 758 | case 2: // Clk/8 |
| 759 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/8); |
| 760 | break; |
| 761 | case 3: // Clk/32 |
| 762 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/32); |
| 763 | break; |
| 764 | case 4: // Clk/64 |
| 765 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/64); |
| 766 | break; |
| 767 | case 5: // Clk/128 |
| 768 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/128); |
| 769 | break; |
| 770 | case 6: // Clk/256 |
| 771 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/256); |
| 772 | break; |
| 773 | case 7: // Clk/1024 |
| 774 | period = ATTOTIME_IN_HZ(MASTER_CLOCK/1024); |
| 775 | break; |
| 776 | } |
| 777 | timer_adjust_periodic(state->timer2_timer, period, 0, period); |
| 778 | } |
| 779 | |
| 780 | static void avr8_timer2_force_output_compare(running_machine *machine, int reg) |
| 781 | { |
| 782 | // TODO |
| 783 | verboselog(machine, 0, "avr8_force_output_compare: TODO; should be forcing OC2%c\n", avr8_reg_name[reg]); |
| 784 | } |
| 785 | |
| 786 | static void avr8_changed_tccr2b(running_machine *machine, UINT8 data) |
| 787 | { |
| 788 | craft_state *state = machine->driver_data<craft_state>(); |
| 789 | |
| 790 | UINT8 oldtccr = AVR8_TCCR2B; |
| 791 | UINT8 newtccr = data; |
| 792 | UINT8 changed = newtccr ^ oldtccr; |
| 793 | |
| 794 | if(changed & AVR8_TCCR2B_FOC2A_MASK) |
| 795 | { |
| 796 | // TODO |
| 797 | avr8_timer2_force_output_compare(machine, AVR8_REG_A); |
| 798 | } |
| 799 | |
| 800 | if(changed & AVR8_TCCR2B_FOC2B_MASK) |
| 801 | { |
| 802 | // TODO |
| 803 | avr8_timer2_force_output_compare(machine, AVR8_REG_B); |
| 804 | } |
| 805 | |
| 806 | if(changed & AVR8_TCCR2B_WGM2_2_MASK) |
| 807 | { |
| 808 | // TODO |
| 809 | avr8_update_timer2_waveform_gen_mode(machine); |
| 810 | } |
| 811 | |
| 812 | if(changed & AVR8_TCCR2B_CS_MASK) |
| 813 | { |
| 814 | avr8_update_timer2_clock_source(machine); |
| 815 | } |
| 816 | } |
| 817 | |
| 697 | 818 | static void avr8_update_ocr1(running_machine *machine, UINT16 newval, UINT8 reg) |
| 698 | 819 | { |
| 699 | 820 | craft_state *state = machine->driver_data<craft_state>(); |
| r10098 | r10099 | |
| 718 | 839 | switch( offset ) |
| 719 | 840 | { |
| 720 | 841 | case Avr8::REGIDX_OCR1BH: |
| 842 | verboselog(space->machine, 0, "AVR8: OCR1BH = %02x\n", data ); |
| 721 | 843 | avr8_update_ocr1(space->machine, (AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B); |
| 722 | 844 | break; |
| 723 | 845 | |
| 724 | 846 | case Avr8::REGIDX_OCR1BL: |
| 847 | verboselog(space->machine, 0, "AVR8: OCR1BL = %02x\n", data ); |
| 725 | 848 | avr8_update_ocr1(space->machine, (AVR8_OCR1B & 0xff00) | data, AVR8_REG_B); |
| 726 | 849 | break; |
| 727 | 850 | |
| 728 | 851 | case Avr8::REGIDX_OCR1AH: |
| 852 | verboselog(space->machine, 0, "AVR8: OCR1AH = %02x\n", data ); |
| 729 | 853 | avr8_update_ocr1(space->machine, (AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A); |
| 730 | 854 | break; |
| 731 | 855 | |
| 732 | 856 | case Avr8::REGIDX_OCR1AL: |
| 857 | verboselog(space->machine, 0, "AVR8: OCR1AL = %02x\n", data ); |
| 733 | 858 | avr8_update_ocr1(space->machine, (AVR8_OCR1A & 0xff00) | data, AVR8_REG_A); |
| 734 | 859 | break; |
| 735 | 860 | |
| 736 | 861 | case Avr8::REGIDX_TCCR1B: |
| 862 | verboselog(space->machine, 0, "AVR8: TCCR1B = %02x\n", data ); |
| 737 | 863 | avr8_changed_tccr1b(space->machine, data); |
| 738 | 864 | break; |
| 739 | 865 | |
| 740 | 866 | case Avr8::REGIDX_TCCR1A: |
| 867 | verboselog(space->machine, 0, "AVR8: TCCR1A = %02x\n", data ); |
| 741 | 868 | avr8_changed_tccr1a(space->machine, data); |
| 742 | 869 | break; |
| 743 | 870 | |
| 744 | 871 | case Avr8::REGIDX_TIMSK1: |
| 872 | verboselog(space->machine, 0, "AVR8: TIMSK1 = %02x\n", data ); |
| 745 | 873 | avr8_change_timsk1(space->machine, data); |
| 746 | 874 | break; |
| 747 | 875 | |
| 876 | case Avr8::REGIDX_TCCR2B: |
| 877 | verboselog(space->machine, 0, "AVR8: TCCR2B = %02x\n", data ); |
| 878 | avr8_changed_tccr2b(space->machine, data); |
| 879 | break; |
| 880 | |
| 881 | case Avr8::REGIDX_TCCR2A: |
| 882 | verboselog(space->machine, 0, "AVR8: TCCR2A = %02x\n", data ); |
| 883 | avr8_changed_tccr2a(space->machine, data); |
| 884 | break; |
| 885 | |
| 748 | 886 | case Avr8::REGIDX_SPL: |
| 749 | 887 | case Avr8::REGIDX_SPH: |
| 750 | 888 | case Avr8::REGIDX_SREG: |
| r10098 | r10099 | |
| 817 | 955 | |
| 818 | 956 | static DRIVER_INIT( craft ) |
| 819 | 957 | { |
| 820 | | craft_state *state = machine->driver_data<craft_state>(); |
| 821 | | |
| 822 | | state->ocr1a_timer = timer_alloc(machine, ocr1a_timer_compare, 0); |
| 823 | | state->ocr1b_timer = timer_alloc(machine, ocr1b_timer_compare, 0); |
| 824 | 958 | } |
| 825 | 959 | |
| 826 | 960 | static MACHINE_RESET( craft ) |