void datasette_set_motor(int flag) { DBG(("datasette_set_motor(%d) (image present:%s)", flag, current_image ? "yes" : "no")); if (datasette_alarm == NULL) { DBG(("datasette_set_motor (datasette_alarm == NULL)")); return; } if (flag) { /* abort pending motor stop */ motor_stop_clk = 0; if (!datasette_motor) { last_write_clk = (CLOCK)0; datasette_start_motor(); ui_display_tape_motor_status(1); datasette_motor = 1; } } if (!flag && datasette_motor && motor_stop_clk == 0) { motor_stop_clk = maincpu_clk + MOTOR_DELAY; DBG(("datasette_set_motor(maincpu_clk:%d motor_stop_clk:%d)", maincpu_clk, motor_stop_clk)); if (!datasette_alarm_pending) { /* make sure that the motor will stop */ alarm_set(datasette_alarm, motor_stop_clk); datasette_alarm_pending = 1; } } }
void datasette_set_motor(int flag) { if (current_image != NULL) { if (flag) { /* abort pending motor stop */ motor_stop_clk = 0; if (!datasette_motor) { last_write_clk = (CLOCK)0; datasette_start_motor(); ui_display_tape_motor_status(1); datasette_motor = 1; } } if (!flag && datasette_motor && motor_stop_clk == 0) { motor_stop_clk = maincpu_clk + MOTOR_DELAY; if (!datasette_alarm_pending) { /* make sure that the motor will stop */ alarm_set(datasette_alarm, motor_stop_clk); datasette_alarm_pending = 1; } } } }
static void datasette_read_bit(CLOCK offset, void *data) { double speed_of_tape = DS_V_PLAY; int direction = 1; long gap; alarm_unset(datasette_alarm); datasette_alarm_pending = 0; if (current_image == NULL) return; /* check for delay of motor stop */ if (motor_stop_clk > 0 && maincpu_clk >= motor_stop_clk) { motor_stop_clk = 0; ui_display_tape_motor_status(0); datasette_motor = 0; } if (!datasette_motor) return; switch (current_image->mode) { case DATASETTE_CONTROL_START: direction = 1; speed_of_tape = DS_V_PLAY; if (!datasette_long_gap_pending) datasette_trigger_flux_change(fullwave); break; case DATASETTE_CONTROL_FORWARD: direction = 1; speed_of_tape = DS_RPS_FAST / DS_G * sqrt(4 * PI * DS_D * DS_V_PLAY / datasette_cycles_per_second * 8 * current_image->cycle_counter + 4 * PI * PI * DS_R * DS_R); break; case DATASETTE_CONTROL_REWIND: direction = -1; speed_of_tape = DS_RPS_FAST / DS_G * sqrt(4 * PI * DS_D * DS_V_PLAY / datasette_cycles_per_second * 8 * (current_image->cycle_counter_total - current_image->cycle_counter) + 4 * PI * PI * DS_R * DS_R); break; case DATASETTE_CONTROL_RECORD: case DATASETTE_CONTROL_STOP: return; default: log_error(datasette_log, "Unknown datasette mode."); return; } if (direction + datasette_last_direction == 0) { /* the direction changed; read the gap from file, but use use only the elapsed gap */ gap = datasette_read_gap(direction); datasette_long_gap_pending = datasette_long_gap_elapsed; datasette_long_gap_elapsed = gap - datasette_long_gap_elapsed; } if (datasette_long_gap_pending) { gap = datasette_long_gap_pending; datasette_long_gap_pending = 0; } else { gap = datasette_read_gap(direction); if (gap) datasette_long_gap_elapsed = 0; } if (!gap) { datasette_control(DATASETTE_CONTROL_STOP); return; } if (gap > DATASETTE_MAX_GAP) { datasette_long_gap_pending = gap - DATASETTE_MAX_GAP; gap = DATASETTE_MAX_GAP; } datasette_long_gap_elapsed += gap; datasette_last_direction = direction; if (direction > 0) current_image->cycle_counter += gap / 8; else current_image->cycle_counter -= gap / 8; gap -= offset; if (gap > 0) { alarm_set(datasette_alarm, maincpu_clk + (CLOCK)(gap * (DS_V_PLAY / speed_of_tape))); datasette_alarm_pending = 1; } else { /* If the offset is geater than the gap to the next flux change, the change happend during DMA. Schedule it now. */ alarm_set(datasette_alarm, maincpu_clk); datasette_alarm_pending = 1; } datasette_update_ui_counter(); }