Exemple #1
0
void datasette_set_tape_image(tap_t *image)
{
    CLOCK gap;

    DBG(("datasette_set_tape_image (image present:%s)", image ? "yes" : "no"));

    current_image = image;
    last_tap = next_tap = 0;
    datasette_internal_reset();

    if (image != NULL) {
        /* We need the length of tape for realistic counter. */
        current_image->cycle_counter_total = 0;
        do {
            gap = datasette_read_gap(1);
            current_image->cycle_counter_total += gap / 8;
        } while (gap);
        current_image->current_file_seek_position = 0;
    }
    datasette_set_tape_sense(0);

    last_tap = next_tap = 0;
    fullwave = 0;

    ui_set_tape_status(current_image ? 1 : 0);
}
Exemple #2
0
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();
}