static void dtlbasic_write(int write_bit) { if (write_bit == write_status) { return; } write_status = write_bit; if (dtlbasic_state == DTLBASIC_DONGLE_SENSE_LOW && write_bit) { dtlbasic_state = DTLBASIC_DONGLE_WRITE_HIGH; return; } if (dtlbasic_state == DTLBASIC_DONGLE_WRITE_HIGH && !write_bit) { dtlbasic_state = DTLBASIC_DONGLE_ACTIVE; dtlbasic_counter = 1; return; } if (!write_bit) { if (dtlbasic_counter != -1) { if (dtlbasic_key[dtlbasic_counter]) { tapeport_trigger_flux_change(1, dtlbasic_dongle_device.id); } ++dtlbasic_counter; if (dtlbasic_counter == 20) { dtlbasic_counter = -1; } } } }
void tapelog_trigger_flux_change_passthrough(unsigned int on) { tapeport_trigger_flux_change(on, tapelog_device.id); tapelog_transition("read", (BYTE)on); tapelog_read_in = on; }
/* this is the alarm function */ 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; DBG(("datasette_read_bit(motor:%d) %d>=%d (image present:%s)", datasette_motor, maincpu_clk, motor_stop_clk, current_image ? "yes" : "no")); /* 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; } DBG(("datasette_read_bit(motor:%d)", datasette_motor)); if (!datasette_motor) { return; } if (current_image == NULL) { switch (notape_mode) { case DATASETTE_CONTROL_START: case DATASETTE_CONTROL_FORWARD: case DATASETTE_CONTROL_REWIND: case DATASETTE_CONTROL_RECORD: break; case DATASETTE_CONTROL_STOP: if (motor_stop_clk > 0) { alarm_set(datasette_alarm, motor_stop_clk); datasette_alarm_pending = 1; } break; } datasette_update_ui_counter(); return; } switch (current_image->mode) { case DATASETTE_CONTROL_START: direction = 1; speed_of_tape = DS_V_PLAY; if (!datasette_long_gap_pending) { if (datasette_list_item) { tapeport_trigger_flux_change(fullwave, datasette_device.id); } } 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(); }