|  | @@ -299,12 +299,20 @@ static struct {
 | 
	
		
			
				|  |  |      uint8_t packet[USB_HS_MPS];
 | 
	
		
			
				|  |  |  } rw;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static always_inline void _write_28bit(uint32_t x)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    u_buf[U_MASK(u_prod++)] = 1 | (x << 1);
 | 
	
		
			
				|  |  | +    u_buf[U_MASK(u_prod++)] = 1 | (x >> 6);
 | 
	
		
			
				|  |  | +    u_buf[U_MASK(u_prod++)] = 1 | (x >> 13);
 | 
	
		
			
				|  |  | +    u_buf[U_MASK(u_prod++)] = 1 | (x >> 20);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void rdata_encode_flux(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      const uint16_t buf_mask = ARRAY_SIZE(dma.buf) - 1;
 | 
	
		
			
				|  |  |      uint16_t cons = dma.cons, prod;
 | 
	
		
			
				|  |  |      timcnt_t prev = dma.prev_sample, curr, next;
 | 
	
		
			
				|  |  | -    uint32_t ticks = rw.ticks_since_flux;
 | 
	
		
			
				|  |  | +    uint32_t ticks;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ASSERT(rw.idx < rw.nr_idx);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -317,14 +325,10 @@ static void rdata_encode_flux(void)
 | 
	
		
			
				|  |  |      if (rw.idx != index.count) {
 | 
	
		
			
				|  |  |          /* We have just passed the index mark: Record information about 
 | 
	
		
			
				|  |  |           * the just-completed revolution. */
 | 
	
		
			
				|  |  | -        int partial_flux = ticks + (timcnt_t)(index.rdata_cnt - prev);
 | 
	
		
			
				|  |  | -        ASSERT(partial_flux >= 0);
 | 
	
		
			
				|  |  | +        unsigned int partial_flux = (timcnt_t)(index.rdata_cnt - prev);
 | 
	
		
			
				|  |  |          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);
 | 
	
		
			
				|  |  | +        _write_28bit(partial_flux);
 | 
	
		
			
				|  |  |          rw.idx = index.count;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -336,7 +340,7 @@ static void rdata_encode_flux(void)
 | 
	
		
			
				|  |  |          curr = next - prev;
 | 
	
		
			
				|  |  |          prev = next;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        ticks += curr;
 | 
	
		
			
				|  |  | +        ticks = curr;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (ticks == 0) {
 | 
	
		
			
				|  |  |              /* 0: Skip. */
 | 
	
	
		
			
				|  | @@ -350,36 +354,31 @@ static void rdata_encode_flux(void)
 | 
	
		
			
				|  |  |                  u_buf[U_MASK(u_prod++)] = 250 + high;
 | 
	
		
			
				|  |  |                  u_buf[U_MASK(u_prod++)] = 1 + ((ticks-250) % 255);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  | -                /* 1525-(2^28-1): Six bytes */
 | 
	
		
			
				|  |  | +                /* 1525-(2^28-1): Seven 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);
 | 
	
		
			
				|  |  | -                u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 20);
 | 
	
		
			
				|  |  | +                u_buf[U_MASK(u_prod++)] = FLUXOP_NOFLUX;
 | 
	
		
			
				|  |  | +                _write_28bit(ticks - 249);
 | 
	
		
			
				|  |  | +                u_buf[U_MASK(u_prod++)] = 249;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        ticks = 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* If it has been a long time since the last flux timing, transfer some of
 | 
	
		
			
				|  |  | -     * the accumulated time from the 16-bit timestamp into the 32-bit
 | 
	
		
			
				|  |  | -     * accumulator. This avoids 16-bit overflow and because, we take care to
 | 
	
		
			
				|  |  | -     * keep the 16-bit timestamp at least 200us behind, we cannot race the next
 | 
	
		
			
				|  |  | -     * flux timestamp. */
 | 
	
		
			
				|  |  | -    if (sizeof(timcnt_t) == sizeof(uint16_t)) {
 | 
	
		
			
				|  |  | -        curr = tim_rdata->cnt - prev;
 | 
	
		
			
				|  |  | -        if (unlikely(curr > sample_us(400))) {
 | 
	
		
			
				|  |  | -            prev += sample_us(200);
 | 
	
		
			
				|  |  | -            ticks += sample_us(200);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +     * the accumulated time to the host in a "long gap" sample. This avoids
 | 
	
		
			
				|  |  | +     * timing overflow and, because we take care to keep @prev well behind the
 | 
	
		
			
				|  |  | +     * sample clock, we cannot race the next flux timestamp. */
 | 
	
		
			
				|  |  | +    curr = tim_rdata->cnt - prev;
 | 
	
		
			
				|  |  | +    if (unlikely(curr > sample_us(400))) {
 | 
	
		
			
				|  |  | +        ticks = sample_us(200);
 | 
	
		
			
				|  |  | +        u_buf[U_MASK(u_prod++)] = 0xff;
 | 
	
		
			
				|  |  | +        u_buf[U_MASK(u_prod++)] = FLUXOP_NOFLUX;
 | 
	
		
			
				|  |  | +        _write_28bit(ticks);
 | 
	
		
			
				|  |  | +        prev += ticks;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Save our progress for next time. */
 | 
	
		
			
				|  |  |      dma.cons = cons;
 | 
	
		
			
				|  |  |      dma.prev_sample = prev;
 | 
	
		
			
				|  |  | -    rw.ticks_since_flux = ticks;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
 | 
	
	
		
			
				|  | @@ -487,6 +486,16 @@ static void floppy_read(void)
 | 
	
		
			
				|  |  |   * WRITE PATH
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static always_inline uint32_t _read_28bit(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    uint32_t x;
 | 
	
		
			
				|  |  | +    x  = (u_buf[U_MASK(u_cons++)]       ) >>  1;
 | 
	
		
			
				|  |  | +    x |= (u_buf[U_MASK(u_cons++)] & 0xfe) <<  6;
 | 
	
		
			
				|  |  | +    x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 13;
 | 
	
		
			
				|  |  | +    x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 20;
 | 
	
		
			
				|  |  | +    return x;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      unsigned int todo = nr;
 | 
	
	
		
			
				|  | @@ -527,11 +536,9 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
 | 
	
		
			
				|  |  |              /* 255: Six bytes */
 | 
	
		
			
				|  |  |              if ((uint32_t)(u_prod - u_cons) < 6)
 | 
	
		
			
				|  |  |                  goto out;
 | 
	
		
			
				|  |  | -            u_cons += 2; /* skip 255, 1 */
 | 
	
		
			
				|  |  | -            x  = (u_buf[U_MASK(u_cons++)]       ) >>  1;
 | 
	
		
			
				|  |  | -            x |= (u_buf[U_MASK(u_cons++)] & 0xfe) <<  6;
 | 
	
		
			
				|  |  | -            x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 13;
 | 
	
		
			
				|  |  | -            x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 20;
 | 
	
		
			
				|  |  | +            u_cons += 2; /* skip 255, FLUXOP_NOFLUX */
 | 
	
		
			
				|  |  | +            ticks += _read_28bit();
 | 
	
		
			
				|  |  | +            continue;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          ticks += x;
 |