mirror of
https://github.com/keirf/greaseweazle-firmware.git
synced 2025-10-31 11:06:44 -07:00
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.
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
38
src/floppy.c
38
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);
|
||||
|
||||
Reference in New Issue
Block a user