Refactor all the raw buffer stuff to be less bad. Add an encoded buffer, which

will be used for assembling fluxmaps to write to the floppy.
This commit is contained in:
David Given
2018-10-09 22:49:10 +02:00
parent 40b9fbc25d
commit 5bd01d5ebc
10 changed files with 155 additions and 97 deletions

View File

@@ -5,6 +5,8 @@ SRCS = \
main.c \
usb.c \
sql.c \
encoder.c \
fluxmap.c \
cmd_rpm.c \
cmd_usbbench.c \
cmd_read.c \

View File

@@ -347,12 +347,12 @@ abandon_record:
return false;
}
static void decode_track_cb(int track, int side, const uint8_t* data, size_t len)
static void decode_track_cb(int track, int side, const struct fluxmap* fluxmap)
{
printf("Track %02d side %d: ", track, side);
inputbuffer = data;
inputlen = len;
inputbuffer = fluxmap->intervals;
inputlen = fluxmap->bytes;
cursor = 0;
int record = 0;

View File

@@ -96,22 +96,13 @@ void cmd_read(char* const* argv)
fflush(stdout);
usb_seek(t);
struct raw_data_buffer buffer;
usb_read(
struct fluxmap* fluxmap = usb_read(
(side ? SIDE_SIDEB : SIDE_SIDEA) |
(highdensity ? SIDE_HIGHDENSITY : SIDE_LOWDENSITY),
&buffer);
(highdensity ? SIDE_HIGHDENSITY : SIDE_LOWDENSITY));
sql_write_flux(db, t, side, buffer.buffer, buffer.len);
uint32_t time = 0;
for (int i=0; i<buffer.len; i++)
{
uint8_t b = buffer.buffer[i];
time += b;
}
printf("%d ms in %ld bytes\n", (time*1000)/TICK_FREQUENCY, buffer.len);
sql_write_flux(db, t, side, fluxmap);
printf("%d ms in %d bytes\n", fluxmap->length_us / 1000, fluxmap->bytes);
free_fluxmap(fluxmap);
}
}
sql_stmt(db, "COMMIT;");

View File

@@ -3,7 +3,6 @@
#include <unistd.h>
static const char* filename = NULL;
static bool test_pattern = false;
static int start_track = 0;
static int end_track = 79;
static int start_side = 0;
@@ -14,8 +13,7 @@ static void syntax_error(void)
{
fprintf(stderr,
"syntax: fluxclient write <options>:\n"
" -o <filename> input filename (can't use with -T)\n"
" -T write a test pattern (can't use with -o)\n"
" -i <filename> input filename (can't use with -T)\n"
" -s <start track> defaults to 0\n"
" -e <end track> defaults to 79\n"
" -0 read just side 0 (defaults to both)\n"
@@ -28,19 +26,15 @@ static char* const* parse_options(char* const* argv)
{
for (;;)
{
switch (getopt(countargs(argv), argv, "+o:Ts:e:01"))
switch (getopt(countargs(argv), argv, "+i:Ts:e:01"))
{
case -1:
return argv + optind - 1;
case 'o':
case 'i':
filename = optarg;
break;
case 'T':
test_pattern = true;
break;
case 's':
start_track = atoi(optarg);
break;
@@ -74,43 +68,17 @@ static void open_file(void)
atexit(close_file);
}
static void write_data(struct raw_data_buffer* buffer, int ticks, int* cursor, uint8_t data)
{
while ((ticks > 0) && (*cursor < buffer->len))
{
buffer->buffer[(*cursor)++] = data;
ticks -= data;
}
}
static void create_test_pattern(struct raw_data_buffer* buffer)
{
int cursor = 0;
const int five_milliseconds = 5 * TICK_FREQUENCY / 1000;
int step = 0x38;
while (cursor < buffer->len)
{
write_data(buffer, five_milliseconds, &cursor, step);
write_data(buffer, five_milliseconds, &cursor, 0x30);
if (step < 0xf8)
step += 8;
}
}
void cmd_write(char* const* argv)
{
argv = parse_options(argv);
if (countargs(argv) != 1)
syntax_error();
if (!!filename == test_pattern)
error("you must specify a filename to read from, or a test pattern");
if (!filename)
error("you must specify an input filename");
if (start_track > end_track)
error("writing to track %d to track %d makes no sense", start_track, end_track);
if (filename)
open_file();
open_file();
for (int t=start_track; t<=end_track; t++)
{
for (int side=start_side; side<=end_side; side++)
@@ -119,30 +87,22 @@ void cmd_write(char* const* argv)
fflush(stdout);
usb_seek(t);
struct raw_data_buffer buffer;
buffer.len = sizeof(buffer.buffer);
if (filename)
struct fluxmap* fluxmap = sql_read_flux(db, t, side);
if (!fluxmap)
{
if (!sql_read_flux(db, t, side, buffer.buffer, &buffer.len))
continue;
printf("(no data)\n");
continue;
}
if (test_pattern)
create_test_pattern(&buffer);
buffer.len &= ~(FRAME_SIZE-1);
uint32_t time = 0;
for (int i=0; i<buffer.len; i++)
time += buffer.buffer[i];
printf("sent %dms", (time*1000)/TICK_FREQUENCY);
printf("sent %dms", fluxmap->length_us/1000);
fflush(stdout);
int bytes_actually_written = usb_write(side, &buffer);
int bytes_actually_written = usb_write(side, fluxmap);
time = 0;
int ticks = 0;
for (int i=0; i<bytes_actually_written; i++)
time += buffer.buffer[i];
printf(", wrote %dms\n", (time*1000)/TICK_FREQUENCY);
ticks += fluxmap->intervals[i];
printf(", wrote %dms\n", ticks/(TICK_FREQUENCY/1000));
}
}
}

40
encoder.c Normal file
View File

@@ -0,0 +1,40 @@
#include "globals.h"
struct encoding_buffer* create_encoding_buffer(int length_us)
{
struct encoding_buffer* buffer = calloc(1, sizeof(*buffer));
buffer->length_us = length_us;
buffer->bitmap = calloc(1, length_us);
return buffer;
}
void free_encoding_buffer(struct encoding_buffer* buffer)
{
free(buffer->bitmap);
free(buffer);
}
void encoding_buffer_pulse(struct encoding_buffer* buffer, int timestamp_us)
{
if (timestamp_us < buffer->length_us)
buffer->bitmap[timestamp_us] = 1;
}
struct fluxmap* encoding_buffer_encode(struct encoding_buffer* buffer)
{
struct fluxmap* fluxmap = create_fluxmap();
int lastpulse = 0;
int cursor = 0;
while (cursor < buffer->length_us)
{
if (buffer->bitmap[cursor])
{
uint8_t interval = cursor - lastpulse;
fluxmap_append_intervals(fluxmap, &interval, 1);
lastpulse = cursor;
}
}
return fluxmap;
}

39
fluxmap.c Normal file
View File

@@ -0,0 +1,39 @@
#include "globals.h"
struct fluxmap* create_fluxmap(void)
{
struct fluxmap* fluxmap = calloc(1, sizeof(*fluxmap));
return fluxmap;
}
void free_fluxmap(struct fluxmap* fluxmap)
{
free(fluxmap->intervals);
free(fluxmap);
}
void fluxmap_clear(struct fluxmap* fluxmap)
{
fluxmap->bytes = fluxmap->length_ticks = fluxmap->length_us = 0;
}
void fluxmap_append_intervals(struct fluxmap* fluxmap, const uint8_t* intervals, int count)
{
int newsize = fluxmap->bytes + count;
if (newsize > fluxmap->buffersize)
{
fluxmap->buffersize *= 2;
if (newsize > fluxmap->buffersize)
fluxmap->buffersize = newsize;
fluxmap->intervals = realloc(fluxmap->intervals, fluxmap->buffersize);
}
for (int i=0; i<count; i++)
{
uint8_t interval = *intervals++;
fluxmap->length_ticks += interval;
fluxmap->intervals[fluxmap->bytes++] = interval;
}
fluxmap->length_us = fluxmap->length_ticks / (TICK_FREQUENCY / 1000000);
}

View File

@@ -16,12 +16,32 @@
#include "protocol.h"
struct raw_data_buffer
struct encoding_buffer
{
size_t len;
uint8_t buffer[200*1024];
int length_us;
uint8_t* bitmap;
};
extern struct encoding_buffer* create_encoding_buffer(int length_us);
extern void free_encoding_buffer(struct encoding_buffer* buffer);
extern void encoding_buffer_pulse(struct encoding_buffer* buffer, int timestamp_us);
extern struct fluxmap* encoding_buffer_encode(struct encoding_buffer* buffer);
struct fluxmap
{
int length_ticks;
int length_us;
int bytes;
int buffersize;
uint8_t* intervals;
};
extern struct fluxmap* create_fluxmap(void);
extern void free_fluxmap(struct fluxmap* fluxmap);
extern void fluxmap_clear(struct fluxmap* fluxmap);
extern void fluxmap_append_intervals(struct fluxmap* fluxmap, const uint8_t* intervals, int count);
extern void error(const char* message, ...);
extern double gettime(void);
extern int countargs(char* const* argv);
@@ -34,8 +54,8 @@ extern int usb_get_version(void);
extern void usb_seek(int track);
extern int usb_measure_speed(void);
extern void usb_bulk_test(void);
extern void usb_read(int side, struct raw_data_buffer* buffer);
extern int usb_write(int side, struct raw_data_buffer* buffer);
extern struct fluxmap* usb_read(int side);
extern int usb_write(int side, struct fluxmap* fluxmap);
extern void cmd_rpm(char* const* argv);
extern void cmd_usbbench(char* const* argv);

24
sql.c
View File

@@ -51,7 +51,7 @@ void sql_prepare_flux(sqlite3* db)
");");
}
void sql_write_flux(sqlite3* db, int track, int side, const uint8_t* ptr, size_t len)
void sql_write_flux(sqlite3* db, int track, int side, const struct fluxmap* fluxmap)
{
sqlite3_stmt* stmt;
sql_check(db, sqlite3_prepare_v2(db,
@@ -59,14 +59,14 @@ void sql_write_flux(sqlite3* db, int track, int side, const uint8_t* ptr, size_t
-1, &stmt, NULL));
sql_bind_int(db, stmt, ":track", track);
sql_bind_int(db, stmt, ":side", side);
sql_bind_blob(db, stmt, ":data", ptr, len);
sql_bind_blob(db, stmt, ":data", fluxmap->intervals, fluxmap->bytes);
if (sqlite3_step(stmt) != SQLITE_DONE)
error("failed to write to database: %s", sqlite3_errmsg(db));
sql_check(db, sqlite3_finalize(stmt));
}
bool sql_read_flux(sqlite3* db, int track, int side, uint8_t* ptr, size_t* len)
struct fluxmap* sql_read_flux(sqlite3* db, int track, int side)
{
sqlite3_stmt* stmt;
sql_check(db, sqlite3_prepare_v2(db,
@@ -77,37 +77,39 @@ bool sql_read_flux(sqlite3* db, int track, int side, uint8_t* ptr, size_t* len)
int i = sqlite3_step(stmt);
if (i == SQLITE_DONE)
return false;
return NULL;
if (i != SQLITE_ROW)
error("failed to read from database: %s", sqlite3_errmsg(db));
const void* blobptr = sqlite3_column_blob(stmt, 0);
size_t bloblen = sqlite3_column_bytes(stmt, 0);
if (bloblen > *len)
error("buffer overflow (%d bytes in database, buffer %d bytes)", bloblen, *len);
*len = bloblen;
memcpy(ptr, blobptr, bloblen);
struct fluxmap* fluxmap = create_fluxmap();
fluxmap_append_intervals(fluxmap, blobptr, bloblen);
sql_check(db, sqlite3_finalize(stmt));
return true;
return fluxmap;
}
void sql_for_all_flux_data(sqlite3* db,
void (*cb)(int track, int side, const uint8_t* data, size_t len))
void (*cb)(int track, int side, const struct fluxmap* fluxmap))
{
sqlite3_stmt* stmt;
sql_check(db, sqlite3_prepare_v2(db,
"SELECT track, side, data FROM rawdata",
-1, &stmt, NULL));
struct fluxmap* fluxmap = create_fluxmap();
while (sqlite3_step(stmt) == SQLITE_ROW)
{
int track = sqlite3_column_int(stmt, 0);
int side = sqlite3_column_int(stmt, 1);
const void* ptr = sqlite3_column_blob(stmt, 2);
size_t len = sqlite3_column_bytes(stmt, 2);
cb(track, side, ptr, len);
fluxmap_append_intervals(fluxmap, ptr, len);
cb(track, side, fluxmap);
fluxmap_clear(fluxmap);
}
free_fluxmap(fluxmap);
sql_check(db, sqlite3_finalize(stmt));
}

6
sql.h
View File

@@ -11,9 +11,9 @@ extern void sql_bind_blob(sqlite3* db, sqlite3_stmt* stmt, const char* name,
extern void sql_bind_int(sqlite3* db, sqlite3_stmt* stmt, const char* name, int value);
extern void sql_prepare_flux(sqlite3* db);
extern void sql_write_flux(sqlite3* db, int track, int side, const uint8_t* ptr, size_t len);
extern bool sql_read_flux(sqlite3* db, int track, int side, uint8_t* ptr, size_t* len);
extern void sql_for_all_flux_data(sqlite3* db, void (*cb)(int track, int side, const uint8_t* ptr, size_t len));
extern void sql_write_flux(sqlite3* db, int track, int side, const struct fluxmap* fluxmap);
extern struct fluxmap* sql_read_flux(sqlite3* db, int track, int side);
extern void sql_for_all_flux_data(sqlite3* db, void (*cb)(int track, int side, const struct fluxmap* fluxmap));
extern void sql_prepare_record(sqlite3* db);
extern void sql_write_record(sqlite3* db, int track, int side, int record, const uint8_t* ptr, size_t len);

16
usb.c
View File

@@ -135,31 +135,35 @@ void usb_bulk_test(void)
await_reply(F_FRAME_BULK_TEST_REPLY);
}
void usb_read(int side, struct raw_data_buffer* buffer)
struct fluxmap* usb_read(int side)
{
struct read_frame f = {
.f = { .type = F_FRAME_READ_CMD, .size = sizeof(f) },
.side = side
};
struct fluxmap* fluxmap = create_fluxmap();
usb_cmd_send(&f, f.f.size);
buffer->len = large_bulk_transfer(FLUXENGINE_DATA_IN_EP,
&buffer->buffer, sizeof(buffer->buffer));
uint8_t buffer[1024*1024];
int len = large_bulk_transfer(FLUXENGINE_DATA_IN_EP, buffer, sizeof(buffer));
fluxmap_append_intervals(fluxmap, buffer, len);
await_reply(F_FRAME_READ_REPLY);
return fluxmap;
}
/* Returns number of bytes actually written */
int usb_write(int side, struct raw_data_buffer* buffer)
int usb_write(int side, struct fluxmap* fluxmap)
{
struct write_frame f = {
.f = { .type = F_FRAME_WRITE_CMD, .size = sizeof(f) },
.side = side,
.bytes_to_write = htole32(buffer->len),
.bytes_to_write = htole32(fluxmap->bytes),
};
usb_cmd_send(&f, f.f.size);
large_bulk_transfer(FLUXENGINE_DATA_OUT_EP, &buffer->buffer, buffer->len);
large_bulk_transfer(FLUXENGINE_DATA_OUT_EP, fluxmap->intervals, fluxmap->bytes);
struct write_reply_frame* r = await_reply(F_FRAME_WRITE_REPLY);
return r->bytes_actually_written;