瀏覽代碼

usb: Place index timings in-band within the flux read stream.
This removes the low limit on max index timings per read request.

Keir Fraser 4 年之前
父節點
當前提交
9b4b69da85
共有 4 個文件被更改,包括 59 次插入47 次删除
  1. 9 5
      inc/cdc_acm_protocol.h
  2. 35 22
      scripts/greaseweazle/usb.py
  3. 13 18
      src/floppy.c
  4. 2 2
      src/fw_update.c

+ 9 - 5
inc/cdc_acm_protocol.h

@@ -41,9 +41,6 @@
 #define CMD_WRITE_FLUX      8
 /* CMD_GET_FLUX_STATUS, length=2. Last read/write status returned in ACK. */
 #define CMD_GET_FLUX_STATUS 9
-/* CMD_GET_INDEX_TIMES, length=4, first, nr.
- * Returns nr*4 bytes after ACK. */
-#define CMD_GET_INDEX_TIMES 10
 /* CMD_SWITCH_FW_MODE, length=3, <mode> */
 #define CMD_SWITCH_FW_MODE 11
 /* CMD_SELECT, length=3, drive#. Select drive# as current unit. */
@@ -98,6 +95,13 @@
 #define BAUD_CLEAR_COMMS  10000
 
 
+/*
+ * Flux stream opcodes. Preceded by 0xFF byte.
+ */
+#define FLUXOP_LONGFLUX   1
+#define FLUXOP_INDEX      2
+
+
 /*
  * COMMAND PACKETS
  */
@@ -107,7 +111,7 @@
 struct packed gw_info {
     uint8_t fw_major;
     uint8_t fw_minor;
-    uint8_t max_index;
+    uint8_t is_main_firmware; /* == 0 -> update bootloader */
     uint8_t max_cmd;
     uint32_t sample_freq;
     uint8_t hw_model, hw_submodel;
@@ -126,7 +130,7 @@ struct packed gw_bw_stats {
 
 /* CMD_READ_FLUX */
 struct packed gw_read_flux {
-    uint8_t nr_idx; /* default: 2 */
+    uint16_t nr_idx; /* default: 2 */
 };
 
 /* CMD_WRITE_FLUX */

+ 35 - 22
scripts/greaseweazle/usb.py

@@ -109,6 +109,12 @@ class BusType:
     Shugart         = 2
 
 
+## Flux read stream opcodes, preceded by 0xFF byte
+class FluxOp:
+    LongFlux        = 1
+    Index           = 2
+
+
 ## CmdError: Encapsulates a command acknowledgement.
 class CmdError(Exception):
 
@@ -126,9 +132,9 @@ class Unit:
 
     ## Unit information, instance variables:
     ##  major, minor: Greaseweazle firmware version number
-    ##  max_index:    Maximum index timings for Cmd.ReadFlux
     ##  max_cmd:      Maximum Cmd number accepted by this unit
     ##  sample_freq:  Resolution of all time values passed to/from this unit
+    ##  update_mode:  True iff the Greaseweazle unit is in update mode
 
     ## Unit(ser):
     ## Accepts a Pyserial instance for Greaseweazle communications.
@@ -138,17 +144,16 @@ class Unit:
         # Copy firmware info to instance variables (see above for definitions).
         self._send_cmd(struct.pack("3B", Cmd.GetInfo, 3, GetInfo.Firmware))
         x = struct.unpack("<4BI3B21x", self.ser.read(32))
-        (self.major, self.minor, self.max_index,
+        (self.major, self.minor, is_main_firmware,
          self.max_cmd, self.sample_freq, self.hw_model,
          self.hw_submodel, self.usb_speed) = x
         # Old firmware doesn't report HW type but runs on STM32F1 only.
         if self.hw_model == 0:
             self.hw_model = 1
         # Check whether firmware is in update mode: limited command set if so.
-        self.update_mode = (self.max_index == 0)
+        self.update_mode = (is_main_firmware == 0)
         if self.update_mode:
             self.update_jumpered = (self.sample_freq & 1)
-            del self.max_index
             del self.sample_freq
             return
         # We are running main firmware: Check whether an update is needed.
@@ -228,14 +233,6 @@ class Unit:
         self._send_cmd(struct.pack("4B", Cmd.Motor, 4, unit, int(state)))
 
 
-    ## _get_index_times:
-    ## Get index timing values for the last .read_track() command.
-    def _get_index_times(self, nr):
-        self._send_cmd(struct.pack("4B", Cmd.GetIndexTimes, 4, 0, nr))
-        x = struct.unpack("<%dI" % nr, self.ser.read(4*nr))
-        return x
-
-
     ## switch_fw_mode:
     ## Switch between update bootloader and main firmware.
     def switch_fw_mode(self, mode):
@@ -264,27 +261,44 @@ class Unit:
     ## _decode_flux:
     ## Decode the Greaseweazle data stream into a list of flux samples.
     def _decode_flux(self, dat):
-        flux = []
+        flux, index = [], []
         dat_i = iter(dat)
+        ticks_since_index = 0
         try:
             while True:
                 i = next(dat_i)
                 if i < 250:
                     flux.append(i)
+                    ticks_since_index += i
                 elif i == 255:
-                    val =  (next(dat_i) & 254) >>  1
-                    val += (next(dat_i) & 254) <<  6
-                    val += (next(dat_i) & 254) << 13
-                    val += (next(dat_i) & 254) << 20
-                    flux.append(val)
+                    opcode = next(dat_i)
+                    if opcode == FluxOp.LongFlux:
+                        val =  (next(dat_i) & 254) >>  1
+                        val += (next(dat_i) & 254) <<  6
+                        val += (next(dat_i) & 254) << 13
+                        val += (next(dat_i) & 254) << 20
+                        flux.append(val)
+                        ticks_since_index += val
+                    elif opcode == FluxOp.Index:
+                        val =  (next(dat_i) & 254) >>  1
+                        val += (next(dat_i) & 254) <<  6
+                        val += (next(dat_i) & 254) << 13
+                        val += (next(dat_i) & 254) << 20
+                        index.append(ticks_since_index + val)
+                        ticks_since_index = -val
+                        pass
+                    else:
+                        raise error.Fatal("Bad opcode in flux stream (%d)"
+                                          % opcode)
                 else:
                     val = (i - 249) * 250
                     val += next(dat_i) - 1
                     flux.append(val)
+                    ticks_since_index += val
         except StopIteration:
             pass
         error.check(flux[-1] == 0, "Missing terminator on flux read stream")
-        return flux[:-1]
+        return flux[:-1], index
 
 
     ## _encode_flux:
@@ -317,7 +331,7 @@ class Unit:
 
         # Request and read all flux timings for this track.
         dat = bytearray()
-        self._send_cmd(struct.pack("3B", Cmd.ReadFlux, 3, nr_revs+1))
+        self._send_cmd(struct.pack("<2BH", Cmd.ReadFlux, 4, nr_revs+1))
         while True:
             dat += self.ser.read(1)
             dat += self.ser.read(self.ser.in_waiting)
@@ -349,8 +363,7 @@ class Unit:
                 break
 
         # Decode the flux list and read the index-times list.
-        flux_list = self._decode_flux(dat)
-        index_list = self._get_index_times(nr_revs+1)
+        flux_list, index_list = self._decode_flux(dat)
 
         # Clip the initial partial revolution.
         to_index = index_list[0]

+ 13 - 18
src/floppy.c

@@ -254,7 +254,8 @@ void floppy_init(void)
 }
 
 struct gw_info gw_info = {
-    .max_index = 15, .max_cmd = CMD_MAX,
+    .is_main_firmware = 1,
+    .max_cmd = CMD_MAX,
     .sample_freq = 72000000u,
     .hw_model = STM32F
 };
@@ -294,9 +295,7 @@ static struct {
     bool_t terminate_at_index;
     bool_t no_flux_area;
     unsigned int packet_len;
-    int ticks_since_index;
     uint32_t ticks_since_flux;
-    uint32_t index_ticks[15];
     uint8_t packet[USB_HS_MPS];
 } rw;
 
@@ -306,7 +305,6 @@ static void rdata_encode_flux(void)
     uint16_t cons = dma.cons, prod;
     timcnt_t prev = dma.prev_sample, curr, next;
     uint32_t ticks = rw.ticks_since_flux;
-    int ticks_since_index = rw.ticks_since_index;
 
     ASSERT(rw.idx < rw.nr_idx);
 
@@ -320,8 +318,14 @@ static void rdata_encode_flux(void)
         /* We have just passed the index mark: Record information about 
          * the just-completed revolution. */
         int partial_flux = ticks + (timcnt_t)(index.rdata_cnt - prev);
-        rw.index_ticks[rw.idx++] = ticks_since_index + partial_flux;
-        ticks_since_index = -partial_flux;
+        ASSERT(partial_flux >= 0);
+        u_buf[U_MASK(u_prod++)] = 0xff;
+        u_buf[U_MASK(u_prod++)] = FLUXOP_INDEX;
+        u_buf[U_MASK(u_prod++)] = 1 | (partial_flux << 1);
+        u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 6);
+        u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 13);
+        u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 20);
+        rw.idx = index.count;
     }
 
     IRQ_global_enable();
@@ -346,8 +350,9 @@ static void rdata_encode_flux(void)
                 u_buf[U_MASK(u_prod++)] = 249 + high;
                 u_buf[U_MASK(u_prod++)] = 1 + (ticks % 250);
             } else {
-                /* 1500-(2^28-1): Five bytes */
+                /* 1500-(2^28-1): Six bytes */
                 u_buf[U_MASK(u_prod++)] = 0xff;
+                u_buf[U_MASK(u_prod++)] = FLUXOP_LONGFLUX;
                 u_buf[U_MASK(u_prod++)] = 1 | (ticks << 1);
                 u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 6);
                 u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 13);
@@ -355,7 +360,6 @@ static void rdata_encode_flux(void)
             }
         }
 
-        ticks_since_index += ticks;
         ticks = 0;
     }
 
@@ -376,12 +380,11 @@ static void rdata_encode_flux(void)
     dma.cons = cons;
     dma.prev_sample = prev;
     rw.ticks_since_flux = ticks;
-    rw.ticks_since_index = ticks_since_index;
 }
 
 static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
 {
-    if ((rf->nr_idx == 0) || (rf->nr_idx > gw_info.max_index))
+    if (rf->nr_idx == 0)
         return ACK_BAD_COMMAND;
 
     /* Prepare Timer & DMA. */
@@ -1035,14 +1038,6 @@ static void process_command(void)
         u_buf[1] = rw.status;
         goto out;
     }
-    case CMD_GET_INDEX_TIMES: {
-        uint8_t f = u_buf[2], n = u_buf[3];
-        if ((len != 4) || (n > 15) || ((f+n) > gw_info.max_index))
-            goto bad_command;
-        memcpy(&u_buf[2], rw.index_ticks+f, n*4);
-        resp_sz += n*4;
-        break;
-    }
     case CMD_SELECT: {
         uint8_t unit = u_buf[2];
         if (len != 3)

+ 2 - 2
src/fw_update.c

@@ -38,8 +38,8 @@ static uint32_t u_prod;
 static bool_t upd_strapped;
 
 struct gw_info gw_info = {
-    /* Max Index == 0 signals that this is the Bootloader. */
-    .max_index = 0, .max_cmd = CMD_MAX,
+    .is_main_firmware = 0,
+    .max_cmd = CMD_MAX,
     .hw_model = STM32F
 };