Browse Source

Read and Write Flux commands are extended.
1. Read flux can be terminated on a number of ticks as well as number of IDX.
2. Write flux can be started immediately rather than index cued.

Keir Fraser 4 năm trước cách đây
mục cha
commit
b69b4cdef1
3 tập tin đã thay đổi với 43 bổ sung28 xóa
  1. 12 6
      inc/cdc_acm_protocol.h
  2. 9 6
      scripts/greaseweazle/usb.py
  3. 22 16
      src/floppy.c

+ 12 - 6
inc/cdc_acm_protocol.h

@@ -14,7 +14,7 @@
  * GREASEWEAZLE COMMAND SET
  */
 
-/* CMD_GET_INFO, length=3, 0. Returns 32 bytes after ACK. */
+/* CMD_GET_INFO, length=3, idx. Returns 32 bytes after ACK. */
 #define CMD_GET_INFO        0
 /* [BOOTLOADER] CMD_UPDATE, length=6, <update_len>. 
  * Host follows with <update_len> bytes.
@@ -33,10 +33,10 @@
 #define CMD_GET_PARAMS      5
 /* CMD_MOTOR, length=4, drive#, on/off. Turn on/off a drive motor. */
 #define CMD_MOTOR           6
-/* CMD_READ_FLUX, length=2-3. Optionally include all or part of gw_read_flux.
+/* CMD_READ_FLUX, length=2-8. Argument is gw_read_flux.
  * Returns flux readings until EOStream. */
 #define CMD_READ_FLUX       7
-/* CMD_WRITE_FLUX, length=2-3. Optionally include all or part of gw_write_flux.
+/* CMD_WRITE_FLUX, length=2-4. Argument is gw_write_flux.
  * Host follows with flux readings until EOStream. */
 #define CMD_WRITE_FLUX      8
 /* CMD_GET_FLUX_STATUS, length=2. Last read/write status returned in ACK. */
@@ -152,17 +152,23 @@ struct packed gw_bw_stats {
 
 /* CMD_READ_FLUX */
 struct packed gw_read_flux {
-    uint16_t nr_idx; /* default: 2 */
+    /* Maximum ticks to read for (or 0, for no limit). */
+    uint32_t ticks;
+    /* Maximum index pulses to read (or 0, for no limit). */
+    uint16_t max_index;
 };
 
 /* CMD_WRITE_FLUX */
 struct packed gw_write_flux {
-    uint8_t terminate_at_index; /* default: 0 */
+    /* If non-zero, start the write at the index pulse. */
+    uint8_t cue_at_index;
+    /* If non-zero, terminate the write at the next index pulse. */
+    uint8_t terminate_at_index;
 };
 
 /* CMD_ERASE_FLUX */
 struct packed gw_erase_flux {
-    uint32_t erase_ticks;
+    uint32_t ticks;
 };
 
 /* CMD_SINK_SOURCE_BYTES */

+ 9 - 6
scripts/greaseweazle/usb.py

@@ -355,11 +355,12 @@ class Unit:
 
     ## _read_track:
     ## Private helper which issues command requests to Greaseweazle.
-    def _read_track(self, nr_revs):
+    def _read_track(self, revs, ticks):
 
         # Request and read all flux timings for this track.
         dat = bytearray()
-        self._send_cmd(struct.pack("<2BH", Cmd.ReadFlux, 4, nr_revs+1))
+        self._send_cmd(struct.pack("<2BIH", Cmd.ReadFlux, 8,
+                                   ticks, revs+1))
         while True:
             dat += self.ser.read(1)
             dat += self.ser.read(self.ser.in_waiting)
@@ -374,12 +375,12 @@ class Unit:
 
     ## read_track:
     ## Read and decode flux and index timings for the current track.
-    def read_track(self, nr_revs, nr_retries=5):
+    def read_track(self, revs, ticks=0, nr_retries=5):
 
         retry = 0
         while True:
             try:
-                dat = self._read_track(nr_revs)
+                dat = self._read_track(revs, ticks)
             except CmdError as error:
                 # An error occurred. We may retry on transient overflows.
                 if error.code == Ack.FluxOverflow and retry < nr_retries:
@@ -412,7 +413,8 @@ class Unit:
 
     ## write_track:
     ## Write the given flux stream to the current track via Greaseweazle.
-    def write_track(self, flux_list, terminate_at_index, nr_retries=5):
+    def write_track(self, flux_list, terminate_at_index,
+                    cue_at_index=True, nr_retries=5):
 
         # Create encoded data stream.
         dat = self._encode_flux(flux_list)
@@ -421,7 +423,8 @@ class Unit:
         while True:
             try:
                 # Write the flux stream to the track via Greaseweazle.
-                self._send_cmd(struct.pack("3B", Cmd.WriteFlux, 3,
+                self._send_cmd(struct.pack("4B", Cmd.WriteFlux, 4,
+                                           int(cue_at_index),
                                            int(terminate_at_index)))
                 self.ser.write(dat)
                 self.ser.read(1) # Sync with Greaseweazle

+ 22 - 16
src/floppy.c

@@ -324,7 +324,9 @@ static void floppy_end_command(void *ack, unsigned int ack_len)
  */
 
 static struct {
-    unsigned int idx, nr_idx;
+    unsigned int nr_index;
+    unsigned int max_index;
+    time_t deadline;
 } read;
 
 static void _write_28bit(uint32_t x)
@@ -342,7 +344,7 @@ static void rdata_encode_flux(void)
     timcnt_t prev = dma.prev_sample, curr, next;
     uint32_t ticks;
 
-    ASSERT(read.idx < read.nr_idx);
+    ASSERT(read.nr_index < read.max_index);
 
     /* We don't want to race the Index IRQ handler. */
     IRQ_global_disable();
@@ -350,10 +352,10 @@ static void rdata_encode_flux(void)
     /* Find out where the DMA engine's producer index has got to. */
     prod = ARRAY_SIZE(dma.buf) - dma_rdata.ndtr;
 
-    if (read.idx != index.count) {
+    if (read.nr_index != index.count) {
         /* We have just passed the index mark: Record information about 
          * the just-completed revolution. */
-        read.idx = index.count;
+        read.nr_index = index.count;
         ticks = (timcnt_t)(index.rdata_cnt - prev);
         IRQ_global_enable(); /* we're done reading ISR variables */
         u_buf[U_MASK(u_prod++)] = 0xff;
@@ -415,9 +417,6 @@ static void rdata_encode_flux(void)
 
 static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
 {
-    if (rf->nr_idx == 0)
-        return ACK_BAD_COMMAND;
-
     /* Prepare Timer & DMA. */
     dma_rdata.mar = (uint32_t)(unsigned long)dma.buf;
     dma_rdata.ndtr = ARRAY_SIZE(dma.buf);    
@@ -437,7 +436,9 @@ static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
     flux_op.start = time_now();
     flux_op.status = ACK_OKAY;
     memset(&read, 0, sizeof(read));
-    read.nr_idx = rf->nr_idx;
+    read.max_index = rf->max_index ?: INT_MAX;
+    read.deadline = flux_op.start;
+    read.deadline += rf->ticks ? time_from_samples(rf->ticks) : INT_MAX;
 
     return ACK_OKAY;
 }
@@ -476,9 +477,10 @@ static void floppy_read(void)
             floppy_state = ST_read_flux_drain;
             u_cons = u_prod = avail = 0;
 
-        } else if (read.idx >= read.nr_idx) {
+        } else if ((read.nr_index >= read.max_index)
+                   || (time_since(read.deadline) >= 0)) {
 
-            /* Read all requested revolutions. */
+            /* Read all requested data. */
             floppy_flux_end();
             floppy_state = ST_read_flux_drain;
 
@@ -523,6 +525,7 @@ static void floppy_read(void)
 
 static struct {
     bool_t is_finished;
+    bool_t cue_at_index;
     bool_t terminate_at_index;
     uint32_t astable_period;
     uint32_t ticks;
@@ -745,6 +748,7 @@ static uint8_t floppy_write_prep(const struct gw_write_flux *wf)
     flux_op.status = ACK_OKAY;
     memset(&write, 0, sizeof(write));
     write.flux_mode = FLUXMODE_idle;
+    write.cue_at_index = wf->cue_at_index;
     write.terminate_at_index = wf->terminate_at_index;
 
     return ACK_OKAY;
@@ -792,7 +796,7 @@ static void floppy_write_wait_data(void)
 
 static void floppy_write_wait_index(void)
 {
-    if (index.count == 0) {
+    if (write.cue_at_index && (index.count == 0)) {
         if (time_since(flux_op.start) > time_ms(2000)) {
             /* Timeout */
             floppy_flux_end();
@@ -900,7 +904,7 @@ static uint8_t floppy_erase_prep(const struct gw_erase_flux *ef)
 
     floppy_state = ST_erase_flux;
     flux_op.status = ACK_OKAY;
-    flux_op.end = time_now() + time_from_samples(ef->erase_ticks);
+    flux_op.end = time_now() + time_from_samples(ef->ticks);
 
     return ACK_OKAY;
 }
@@ -1145,16 +1149,18 @@ static void process_command(void)
         goto out;
     }
     case CMD_READ_FLUX: {
-        struct gw_read_flux rf = { .nr_idx = 2 };
-        if ((len < 2) || (len > (2 + sizeof(rf))))
+        struct gw_read_flux rf;
+        if (len != (2 + sizeof(rf)))
             goto bad_command;
         memcpy(&rf, &u_buf[2], len-2);
         u_buf[1] = floppy_read_prep(&rf);
         goto out;
     }
     case CMD_WRITE_FLUX: {
-        struct gw_write_flux wf = { 0 };
-        if ((len < 2) || (len > (2 + sizeof(wf))))
+        struct gw_write_flux wf = {
+            .cue_at_index = 1,
+            .terminate_at_index = 0 };
+        if (len != (2 + sizeof(wf)))
             goto bad_command;
         memcpy(&wf, &u_buf[2], len-2);
         u_buf[1] = floppy_write_prep(&wf);