mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
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:
2
Makefile
2
Makefile
@@ -5,6 +5,8 @@ SRCS = \
|
||||
main.c \
|
||||
usb.c \
|
||||
sql.c \
|
||||
encoder.c \
|
||||
fluxmap.c \
|
||||
cmd_rpm.c \
|
||||
cmd_usbbench.c \
|
||||
cmd_read.c \
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
19
cmd_read.c
19
cmd_read.c
@@ -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;");
|
||||
|
||||
70
cmd_write.c
70
cmd_write.c
@@ -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
40
encoder.c
Normal 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
39
fluxmap.c
Normal 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);
|
||||
}
|
||||
30
globals.h
30
globals.h
@@ -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
24
sql.c
@@ -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
6
sql.h
@@ -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
16
usb.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user