Эх сурвалжийг харах

Introduce erase_flux command to erase a track.
Use this in 'gw write' to erase unformatted/empty tracks.
Remove the --adjust-speed option: We basically always want this.

Keir Fraser 4 жил өмнө
parent
commit
8799fda304

+ 8 - 1
inc/cdc_acm_protocol.h

@@ -53,7 +53,9 @@
 #define CMD_SET_PIN        15
 /* CMD_RESET, length=2. Reset all state to initial (power on) values. */
 #define CMD_RESET          16
-#define CMD_MAX            16
+/* CMD_ERASE_FLUX, length=6. Argument is gw_erase_flux. */
+#define CMD_ERASE_FLUX     17
+#define CMD_MAX            17
 
 
 /*
@@ -113,6 +115,11 @@ struct packed gw_write_flux {
     uint8_t terminate_at_index; /* default: 0 */
 };
 
+/* CMD_ERASE_FLUX */
+struct packed gw_erase_flux {
+    uint32_t erase_ticks;
+};
+
 /* CMD_{GET,SET}_PARAMS, index 0 */
 #define PARAMS_DELAYS 0
 struct packed gw_delay {

+ 13 - 19
scripts/greaseweazle/tools/write.py

@@ -16,12 +16,11 @@ from greaseweazle import usb as USB
 # Writes the specified image file to floppy disk.
 def write_from_image(usb, args):
 
-    if args.adjust_speed:
-        # @drive_ticks is the time in Gresaeweazle ticks between index pulses.
-        # We will adjust the flux intervals per track to allow for this.
-        flux = usb.read_track(2)
-        drive_ticks = (flux.index_list[0] + flux.index_list[1]) / 2
-        del flux
+    # @drive_ticks is the time in Gresaeweazle ticks between index pulses.
+    # We will adjust the flux intervals per track to allow for this.
+    flux = usb.read_track(2)
+    drive_ticks = (flux.index_list[0] + flux.index_list[1]) / 2
+    del flux
 
     # Read and parse the image file.
     image_class = util.get_image_class(args.file)
@@ -33,20 +32,17 @@ def write_from_image(usb, args):
     for cyl in range(args.scyl, args.ecyl+1):
         for side in range(0, args.nr_sides):
 
-            flux = image.get_track(cyl, side, writeout=True)
-            if not flux:
-                continue
-
             print("\rWriting Track %u.%u..." % (cyl, side), end="")
             usb.seek(cyl, side)
 
-            if args.adjust_speed:
-                # @factor adjusts flux times for speed variations between the
-                # read-in and write-out drives.
-                factor = drive_ticks / flux.index_list[0]
-            else:
-                # Simple ratio between the GW and image sample frequencies.
-                factor = usb.sample_freq / flux.sample_freq
+            flux = image.get_track(cyl, side, writeout=True)
+            if not flux:
+                usb.erase_track(drive_ticks * 1.1)
+                continue
+            
+            # @factor adjusts flux times for speed variations between the
+            # read-in and write-out drives.
+            factor = drive_ticks / flux.index_list[0]
 
             # Convert the flux samples to Greaseweazle sample frequency.
             rem = 0.0
@@ -75,8 +71,6 @@ def main(argv):
                         help="last cylinder to write")
     parser.add_argument("--single-sided", action="store_true",
                         help="single-sided write")
-    parser.add_argument("--adjust-speed", action="store_true",
-                        help="adjust write-flux times for drive speed")
     parser.add_argument("file", help="input filename")
     parser.add_argument("device", nargs="?", default="auto",
                         help="serial device")

+ 11 - 1
scripts/greaseweazle/usb.py

@@ -34,6 +34,7 @@ class Cmd:
     SetBusType      = 14
     SetPin          = 15
     Reset           = 16
+    EraseFlux       = 17
     str = {
         GetInfo: "GetInfo",
         Update: "Update",
@@ -51,7 +52,8 @@ class Cmd:
         Deselect: "Deselect",
         SetBusType: "SetBusType",
         SetPin: "SetPin",
-        Reset: "Reset"
+        Reset: "Reset",
+        EraseFlux: "EraseFlux"
     }
 
 
@@ -370,6 +372,14 @@ class Unit:
                 break
 
 
+    ## erase_track:
+    ## Erase the current track via Greaseweazle.
+    def erase_track(self, ticks):
+        self._send_cmd(struct.pack("<2BI", Cmd.EraseFlux, 6, int(ticks)))
+        self.ser.read(1) # Sync with Greaseweazle
+        self._send_cmd(struct.pack("2B", Cmd.GetFluxStatus, 2))
+
+
     ##
     ## Delay-property public getters and setters:
     ##  select_delay:      Delay (usec) after asserting drive select

+ 52 - 4
src/floppy.c

@@ -83,6 +83,7 @@ static enum {
     ST_write_flux_wait_index,
     ST_write_flux,
     ST_write_flux_drain,
+    ST_erase_flux,
 } floppy_state = ST_inactive;
 
 static uint8_t u_buf[8192];
@@ -271,7 +272,10 @@ static void floppy_end_command(void *ack, unsigned int ack_len)
  */
 
 static struct {
-    time_t start;
+    union {
+        time_t start; /* read, write: Time at which read/write started. */
+        time_t end;   /* erase: Time at which to end the erasure. */
+    };
     uint8_t status;
     uint8_t idx, nr_idx;
     bool_t packet_ready;
@@ -364,7 +368,7 @@ static void rdata_encode_flux(void)
     rw.ticks_since_index = ticks_since_index;
 }
 
-static uint8_t floppy_read_prep(struct gw_read_flux *rf)
+static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
 {
     if ((rf->nr_idx == 0) || (rf->nr_idx > gw_info.max_index))
         return ACK_BAD_COMMAND;
@@ -583,7 +587,7 @@ static void floppy_process_write_packet(void)
     }
 }
 
-static uint8_t floppy_write_prep(struct gw_write_flux *wf)
+static uint8_t floppy_write_prep(const struct gw_write_flux *wf)
 {
     if (get_wrprot() == LOW)
         return ACK_WRPROT;
@@ -734,6 +738,39 @@ static void floppy_write_drain(void)
     floppy_end_command(u_buf, 1);
 }
 
+
+/*
+ * ERASE PATH
+ */
+
+static uint8_t floppy_erase_prep(const struct gw_erase_flux *ef)
+{
+    if (get_wrprot() == LOW)
+        return ACK_WRPROT;
+
+    write_pin(wgate, TRUE);
+
+    floppy_state = ST_erase_flux;
+    memset(&rw, 0, sizeof(rw));
+    rw.status = ACK_OKAY;
+    rw.end = time_now() + time_from_samples(ef->erase_ticks);
+
+    return ACK_OKAY;
+}
+
+static void floppy_erase(void)
+{
+    if (time_since(rw.end) < 0)
+        return;
+
+    write_pin(wgate, FALSE);
+
+    /* ACK with Status byte. */
+    u_buf[0] = rw.status;
+    floppy_state = ST_command_wait;
+    floppy_end_command(u_buf, 1);
+}
+
 static void process_command(void)
 {
     uint8_t cmd = u_buf[0];
@@ -809,7 +846,6 @@ static void process_command(void)
         memcpy(&wf, &u_buf[2], len-2);
         u_buf[1] = floppy_write_prep(&wf);
         goto out;
-
     }
     case CMD_GET_FLUX_STATUS: {
         if (len != 2)
@@ -864,6 +900,14 @@ static void process_command(void)
         write_pin(densel, FALSE);
         break;
     }
+    case CMD_ERASE_FLUX: {
+        struct gw_erase_flux ef;
+        if (len != (2 + sizeof(ef)))
+            goto bad_command;
+        memcpy(&ef, &u_buf[2], len-2);
+        u_buf[1] = floppy_erase_prep(&ef);
+        goto out;
+    }
     case CMD_SWITCH_FW_MODE: {
         uint8_t mode = u_buf[2];
         if ((len != 3) || (mode & ~1))
@@ -958,6 +1002,10 @@ void floppy_process(void)
         floppy_write_drain();
         break;
 
+    case ST_erase_flux:
+        floppy_erase();
+        break;
+
     default:
         break;