WIP
This commit is contained in:
parent
fefdb6667e
commit
63a67ca062
4 changed files with 341 additions and 75 deletions
129
examples/floppy_write_test/floppy_write_test.ino
Normal file
129
examples/floppy_write_test/floppy_write_test.ino
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#include <Adafruit_Floppy.h>
|
||||
|
||||
// If using SAMD51, turn on TINYUSB USB stack
|
||||
#if defined(ADAFRUIT_FEATHER_M4_EXPRESS)
|
||||
#define DENSITY_PIN A0 // IDC 2
|
||||
#define INDEX_PIN A1 // IDC 8
|
||||
#define SELECT_PIN A2 // IDC 12
|
||||
#define MOTOR_PIN A3 // IDC 16
|
||||
#define DIR_PIN A4 // IDC 18
|
||||
#define STEP_PIN A5 // IDC 20
|
||||
#define WRDATA_PIN 13 // IDC 22 (not used during read)
|
||||
#define WRGATE_PIN 12 // IDC 24 (not used during read)
|
||||
#define TRK0_PIN 11 // IDC 26
|
||||
#define PROT_PIN 10 // IDC 28
|
||||
#define READ_PIN 9 // IDC 30
|
||||
#define SIDE_PIN 6 // IDC 32
|
||||
#define READY_PIN 5 // IDC 34
|
||||
#elif defined (ARDUINO_ADAFRUIT_FEATHER_RP2040)
|
||||
#define DENSITY_PIN A0 // IDC 2
|
||||
#define INDEX_PIN A1 // IDC 8
|
||||
#define SELECT_PIN A2 // IDC 12
|
||||
#define MOTOR_PIN A3 // IDC 16
|
||||
#define DIR_PIN 24 // IDC 18
|
||||
#define STEP_PIN 25 // IDC 20
|
||||
#define WRDATA_PIN 13 // IDC 22 (not used during read)
|
||||
#define WRGATE_PIN 12 // IDC 24 (not used during read)
|
||||
#define TRK0_PIN 11 // IDC 26
|
||||
#define PROT_PIN 10 // IDC 28
|
||||
#define READ_PIN 9 // IDC 30
|
||||
#define SIDE_PIN 6 // IDC 32
|
||||
#define READY_PIN 5 // IDC 34
|
||||
#elif defined (ARDUINO_RASPBERRY_PI_PICO)
|
||||
#define DENSITY_PIN 2 // IDC 2
|
||||
#define INDEX_PIN 3 // IDC 8
|
||||
#define SELECT_PIN 4 // IDC 12
|
||||
#define MOTOR_PIN 5 // IDC 16
|
||||
#define DIR_PIN 6 // IDC 18
|
||||
#define STEP_PIN 7 // IDC 20
|
||||
#define WRDATA_PIN 8 // IDC 22 (not used during read)
|
||||
#define WRGATE_PIN 9 // IDC 24 (not used during read)
|
||||
#define TRK0_PIN 10 // IDC 26
|
||||
#define PROT_PIN 11 // IDC 28
|
||||
#define READ_PIN 12 // IDC 30
|
||||
#define SIDE_PIN 13 // IDC 32
|
||||
#define READY_PIN 14 // IDC 34
|
||||
#else
|
||||
#error "Please set up pin definitions!"
|
||||
#endif
|
||||
|
||||
Adafruit_Floppy floppy(DENSITY_PIN, INDEX_PIN, SELECT_PIN,
|
||||
MOTOR_PIN, DIR_PIN, STEP_PIN,
|
||||
WRDATA_PIN, WRGATE_PIN, TRK0_PIN,
|
||||
PROT_PIN, READ_PIN, SIDE_PIN, READY_PIN);
|
||||
|
||||
// WARNING! there are 150K max flux pulses per track!
|
||||
uint8_t flux_transitions[MAX_FLUX_PULSE_PER_TRACK];
|
||||
|
||||
uint32_t time_stamp = 0;
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(100);
|
||||
|
||||
Serial.println("its time for a nice floppy transfer!");
|
||||
floppy.debug_serial = &Serial;
|
||||
|
||||
if (!floppy.begin()) {
|
||||
Serial.println("Failed to initialize floppy interface");
|
||||
while (1) yield();
|
||||
}
|
||||
|
||||
floppy.select(true);
|
||||
if (! floppy.spin_motor(true)) {
|
||||
Serial.println("Failed to spin up motor & find index pulse");
|
||||
while (1) yield();
|
||||
}
|
||||
|
||||
Serial.print("Seeking track...");
|
||||
if (! floppy.goto_track(0)) {
|
||||
Serial.println("Failed to seek to track");
|
||||
while (1) yield();
|
||||
}
|
||||
Serial.println("done!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint32_t index_pulse_offset;
|
||||
uint32_t captured_flux = floppy.capture_track(flux_transitions, sizeof(flux_transitions), &index_pulse_offset, true);
|
||||
|
||||
Serial.print("Captured ");
|
||||
Serial.print(captured_flux);
|
||||
Serial.println(" flux transitions");
|
||||
|
||||
//floppy.print_pulses(flux_transitions, captured_flux);
|
||||
floppy.print_pulse_bins(flux_transitions, captured_flux, 255, true);
|
||||
|
||||
if ((millis() - time_stamp) > 1000) {
|
||||
Serial.print("Ready? ");
|
||||
Serial.println(digitalRead(READY_PIN) ? "No" : "Yes");
|
||||
Serial.print("Write Protected? ");
|
||||
Serial.println(digitalRead(PROT_PIN) ? "No" : "Yes");
|
||||
Serial.print("Track 0? ");
|
||||
Serial.println(digitalRead(TRK0_PIN) ? "No" : "Yes");
|
||||
time_stamp = millis();
|
||||
}
|
||||
|
||||
unsigned T_2 = floppy.getSampleFrequency() * 2 / 1000000;
|
||||
unsigned T_3 = floppy.getSampleFrequency() * 3 / 1000000;
|
||||
unsigned T_4 = floppy.getSampleFrequency() * 4 / 1000000;
|
||||
|
||||
for(size_t i=0; i<sizeof(flux_transitions); i+=3) {
|
||||
flux_transitions[i] = T_2;
|
||||
}
|
||||
for(size_t i=1; i<sizeof(flux_transitions); i+=3) {
|
||||
flux_transitions[i] = T_3;
|
||||
}
|
||||
for(size_t i=2; i<sizeof(flux_transitions); i+=3) {
|
||||
flux_transitions[i] = T_4;
|
||||
}
|
||||
|
||||
floppy.print_pulse_bins(flux_transitions, captured_flux, 255, true);
|
||||
|
||||
Serial.println("Writing track with T234234...");
|
||||
Serial.printf("T2 = %d T3 = %d T4 = %d\n", T_2, T_3, T_4);
|
||||
floppy.write_track(flux_transitions, sizeof(flux_transitions), true);
|
||||
|
||||
yield();
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ extern uint32_t rp2040_flux_capture(int indexpin, int rdpin,
|
|||
volatile uint8_t *end,
|
||||
uint32_t *falling_index_offset,
|
||||
bool store_greaseweazle);
|
||||
extern void rp2040_flux_write(int index_pin, int wrgate_pin, int wrdata_pin, uint8_t *pulses, uint8_t *pulse_end, bool store_greaseweazel);
|
||||
#endif
|
||||
|
||||
#if !DEBUG_FLOPPY
|
||||
|
|
@ -154,8 +155,7 @@ void Adafruit_Floppy::soft_reset(void) {
|
|||
digitalWrite(_wrdatapin, HIGH);
|
||||
}
|
||||
if (_wrgatepin >= 0) {
|
||||
pinMode(_wrgatepin, OUTPUT);
|
||||
digitalWrite(_wrgatepin, HIGH);
|
||||
pinMode(_wrgatepin, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
#ifdef BUSIO_USE_FAST_PINIO
|
||||
|
|
@ -524,7 +524,9 @@ uint32_t Adafruit_Floppy::capture_track(volatile uint8_t *pulses,
|
|||
|
||||
void Adafruit_Floppy::write_track(uint8_t *pulses, uint32_t num_pulses,
|
||||
bool store_greaseweazle) {
|
||||
#if defined(__SAMD51__)
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
rp2040_flux_write(_indexpin, _wrgatepin, _wrdatapin, pulses, pulses + num_pulses, store_greaseweazle);
|
||||
#elif defined(__SAMD51__)
|
||||
|
||||
pinMode(_wrdatapin, OUTPUT);
|
||||
digitalWrite(_wrdatapin, HIGH);
|
||||
|
|
|
|||
234
src/arch_rp2.cpp
234
src/arch_rp2.cpp
|
|
@ -44,17 +44,18 @@ static const uint16_t fluxread[] = {
|
|||
// vs wrapping.
|
||||
0x0040, // jmp x--, wait_one
|
||||
};
|
||||
pio_program_t fluxread_struct = {.instructions = fluxread,
|
||||
static const pio_program_t fluxread_struct = {.instructions = fluxread,
|
||||
.length =
|
||||
sizeof(fluxread) / sizeof(fluxread[0]),
|
||||
.origin = -1};
|
||||
|
||||
static const int fluxwrite_sideset_pin_count = 0;
|
||||
static const bool fluxwrite_sideset_enable = 0;
|
||||
static const int fluxwrite_sideset_pin_count = 1;
|
||||
static const bool fluxwrite_sideset_enable = 1;
|
||||
static const uint16_t fluxwrite[] = {
|
||||
// start:
|
||||
// ;; ensure wgate is deasserted then wait for FIFO to be loaded
|
||||
0xe001, // set pins, 1
|
||||
// .side_set 1 opt
|
||||
// start:
|
||||
// ;; ensure wgate is deasserted then wait for FIFO to be loaded
|
||||
0xb842, // nop side 1
|
||||
0x80e0, // pull ifempty
|
||||
// ; Wait for a falling edge on the index pin
|
||||
// wait_index_high:
|
||||
|
|
@ -63,32 +64,29 @@ static const uint16_t fluxwrite[] = {
|
|||
// wait_index_low:
|
||||
0x00c4, // jmp pin wait_index_low
|
||||
// ; Enable gate 2us before writing
|
||||
0xb042, // nop side 0
|
||||
0xe033, // set x 19
|
||||
// loop_gate:
|
||||
0x0146, // jmp x--, loop_gate [1]
|
||||
0x0147, // jmp x--, loop_gate [1]
|
||||
// loop_flux:
|
||||
0xe000, // set pins, 0 ; drive pin low
|
||||
0x6030, // out x, 16 ; get the next timing pulse information
|
||||
// ;; If x is zero here, either a 0 was explicitly put into the flux timing
|
||||
// stream,
|
||||
// ;; OR the data ended naturally OR there was an under-run. In any case,
|
||||
// jump back
|
||||
// ;; to the beginning to wait for available data and then an index pulse --
|
||||
// we're done.
|
||||
// ;; If x is zero here, either a 0 was explicitly put into the flux timing stream,
|
||||
// ;; OR the data ended naturally OR there was an under-run. In any case, jump back
|
||||
// ;; to the beginning to wait for available data and then an index pulse -- we're done.
|
||||
0x0020, // jmp !x, start
|
||||
// ;; output the fixed on time. 10 cycles (preload reg with 6) is about
|
||||
// 0.5us.
|
||||
// ;; note that wdc1772 has varying low times, from 570 to 1380us
|
||||
// ;; output the fixed on time. 10 cycles (preload reg with 6) is about 0.5us.
|
||||
// ;; note that wdc1772 has varying low times, from 570 to 1380us
|
||||
0xe046, // set y, 6 ; fixed on time
|
||||
// loop_low:
|
||||
0x008b, // jmp y--, loop_low
|
||||
0x008c, // jmp y--, loop_low
|
||||
0xe001, // set pins, 1 ; drive pin high
|
||||
0x80c0, // pull ifempty noblock
|
||||
// loop_high:
|
||||
0x004e, // jmp x--, loop_high
|
||||
0x0007, // jmp loop_flux
|
||||
0x004f, // jmp x--, loop_high
|
||||
0x0008, // jmp loop_flux
|
||||
};
|
||||
pio_program_t fluxwrite_struct = {.instructions = fluxwrite,
|
||||
static const pio_program_t fluxwrite_struct = {.instructions = fluxwrite,
|
||||
.length =
|
||||
sizeof(fluxwrite) / sizeof(fluxwrite[0]),
|
||||
.origin = -1};
|
||||
|
|
@ -100,19 +98,22 @@ typedef struct floppy_singleton {
|
|||
uint16_t half;
|
||||
} floppy_singleton_t;
|
||||
|
||||
static floppy_singleton_t g_floppy;
|
||||
static floppy_singleton_t g_reader, g_writer;
|
||||
|
||||
const static PIO pio_instances[2] = {pio0, pio1};
|
||||
static bool allocate_pio_set_program() {
|
||||
static bool allocate_pio_set_program(floppy_singleton_t *info, const pio_program_t *program) {
|
||||
memset(info, 0, sizeof(*info));
|
||||
for (size_t i = 0; i < NUM_PIOS; i++) {
|
||||
PIO pio = pio_instances[i];
|
||||
if (!pio_can_add_program(pio, &fluxread_struct)) {
|
||||
if (!pio_can_add_program(pio, program)) {
|
||||
continue;
|
||||
}
|
||||
int sm = pio_claim_unused_sm(pio, false);
|
||||
if (sm != -1) {
|
||||
g_floppy.pio = pio;
|
||||
g_floppy.sm = sm;
|
||||
info->pio = pio;
|
||||
info->sm = sm;
|
||||
// cannot fail, we asked nicely already
|
||||
info->offset = pio_add_program(pio, program);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -120,89 +121,72 @@ static bool allocate_pio_set_program() {
|
|||
}
|
||||
|
||||
static bool init_capture(int index_pin, int read_pin) {
|
||||
if (g_floppy.pio) {
|
||||
if (g_reader.pio) {
|
||||
return true;
|
||||
}
|
||||
Serial.println("init capture");
|
||||
memset(&g_floppy, 0, sizeof(g_floppy));
|
||||
|
||||
if (!allocate_pio_set_program()) {
|
||||
if (!allocate_pio_set_program(&g_reader, &fluxread_struct)) {
|
||||
return false;
|
||||
}
|
||||
// cannot fail, we asked nicely already
|
||||
g_floppy.offset = pio_add_program(g_floppy.pio, &fluxread_struct);
|
||||
|
||||
pio_gpio_init(g_floppy.pio, index_pin);
|
||||
pio_gpio_init(g_floppy.pio, read_pin);
|
||||
gpio_pull_up(index_pin);
|
||||
|
||||
pio_sm_config c = {0, 0, 0};
|
||||
sm_config_set_wrap(&c, g_floppy.offset,
|
||||
g_floppy.offset + fluxread_struct.length - 1);
|
||||
sm_config_set_wrap(&c, g_reader.offset,
|
||||
g_reader.offset + fluxread_struct.length - 1);
|
||||
sm_config_set_jmp_pin(&c, read_pin);
|
||||
sm_config_set_in_pins(&c, index_pin);
|
||||
sm_config_set_in_shift(&c, true, true, 32);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
pio_sm_set_pins_with_mask(g_floppy.pio, g_floppy.sm, 1 << read_pin,
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, 1 << read_pin,
|
||||
1 << read_pin);
|
||||
float div = (float)clock_get_hz(clk_sys) / (3 * 24e6);
|
||||
sm_config_set_clkdiv(&c, div); // 72MHz capture clock / 24MHz sample rate
|
||||
|
||||
pio_sm_init(g_floppy.pio, g_floppy.sm, g_floppy.offset, &c);
|
||||
pio_sm_init(g_reader.pio, g_reader.sm, g_reader.offset, &c);
|
||||
|
||||
// g_floppy.dreq = pio_get_dreq(g_floppy.pio, g_floppy.sm, false);
|
||||
// g_floppy.dma = dma_claim_unused_channel(false);
|
||||
// rx_source = g_floppy.pio->rxf[g_floppy.sm];
|
||||
// dma_channel_configure(g_floppy.dma, &c, tx_destination,
|
||||
// g_reader.dreq = pio_get_dreq(g_reader.pio, g_reader.sm, false);
|
||||
// g_reader.dma = dma_claim_unused_channel(false);
|
||||
// rx_source = g_reader.pio->rxf[g_reader.sm];
|
||||
// dma_channel_configure(g_reader.dma, &c, tx_destination,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void start_common() {
|
||||
pio_sm_exec(g_floppy.pio, g_floppy.sm, g_floppy.offset);
|
||||
pio_sm_restart(g_floppy.pio, g_floppy.sm);
|
||||
pio_sm_exec(g_reader.pio, g_reader.sm, g_reader.offset);
|
||||
pio_sm_restart(g_reader.pio, g_reader.sm);
|
||||
}
|
||||
|
||||
static uint16_t read_fifo() {
|
||||
if (g_floppy.half) {
|
||||
uint16_t result = g_floppy.half;
|
||||
g_floppy.half = 0;
|
||||
if (g_reader.half) {
|
||||
uint16_t result = g_reader.half;
|
||||
g_reader.half = 0;
|
||||
return result;
|
||||
}
|
||||
uint32_t value = pio_sm_get_blocking(g_floppy.pio, g_floppy.sm);
|
||||
g_floppy.half = value >> 16;
|
||||
uint32_t value = pio_sm_get_blocking(g_reader.pio, g_reader.sm);
|
||||
g_reader.half = value >> 16;
|
||||
return value & 0xffff;
|
||||
}
|
||||
|
||||
static void disable_capture(void) {
|
||||
pio_sm_set_enabled(g_floppy.pio, g_floppy.sm, false);
|
||||
pio_sm_set_enabled(g_reader.pio, g_reader.sm, false);
|
||||
}
|
||||
|
||||
static void free_capture(void) {
|
||||
if (!g_floppy.pio) {
|
||||
if (!g_reader.pio) {
|
||||
// already deinit
|
||||
return;
|
||||
}
|
||||
disable_capture();
|
||||
pio_sm_unclaim(g_floppy.pio, g_floppy.sm);
|
||||
pio_remove_program(g_floppy.pio, &fluxwrite_struct, g_floppy.offset);
|
||||
memset(&g_floppy, 0, sizeof(g_floppy));
|
||||
pio_sm_unclaim(g_reader.pio, g_reader.sm);
|
||||
pio_remove_program(g_reader.pio, &fluxwrite_struct, g_reader.offset);
|
||||
memset(&g_reader, 0, sizeof(g_reader));
|
||||
}
|
||||
|
||||
static void capture_foreground(int indexpin, uint8_t *start, uint8_t *end,
|
||||
static void capture_foreground(int index_pin, uint8_t *start, uint8_t *end,
|
||||
bool wait_index, bool stop_index,
|
||||
uint32_t *falling_index_offset,
|
||||
bool store_greaseweazle) {
|
||||
// g_floppy.store_greaseweazle = store_greaseweazle;
|
||||
|
||||
// c = dma_channel_get_default_config(g_floppy.dma);
|
||||
// channel_config_set_data_transfer_size(&c, DMA_SIZE_32);
|
||||
// channel_config_set_dreq(&c, g_floppy.dreq);
|
||||
// channel_config_set_read_increment(false);
|
||||
// channel_config_set_write_increment(true);
|
||||
|
||||
// dma_channel_configure(g_floppy.dma, &c, start, (end-start) / 4, false);
|
||||
// dma_start_channel_mask(1u << g_floppy.dma);
|
||||
|
||||
if (falling_index_offset) {
|
||||
*falling_index_offset = ~0u;
|
||||
}
|
||||
|
|
@ -210,13 +194,13 @@ static void capture_foreground(int indexpin, uint8_t *start, uint8_t *end,
|
|||
|
||||
// wait for a falling edge of index pin, then enable the capture peripheral
|
||||
if (wait_index) {
|
||||
while (!gpio_get(indexpin)) { /* NOTHING */
|
||||
while (!gpio_get(index_pin)) { /* NOTHING */
|
||||
}
|
||||
while (gpio_get(indexpin)) { /* NOTHING */
|
||||
while (gpio_get(index_pin)) { /* NOTHING */
|
||||
}
|
||||
}
|
||||
|
||||
pio_sm_set_enabled(g_floppy.pio, g_floppy.sm, true);
|
||||
pio_sm_set_enabled(g_reader.pio, g_reader.sm, true);
|
||||
int last = read_fifo();
|
||||
int i = 0;
|
||||
while (start != end) {
|
||||
|
|
@ -247,15 +231,109 @@ static void capture_foreground(int indexpin, uint8_t *start, uint8_t *end,
|
|||
|
||||
static void enable_capture_fifo() { start_common(); }
|
||||
|
||||
static bool init_write(int index_pin, int wrgate_pin, int wrdata_pin) {
|
||||
if (g_reader.pio) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!allocate_pio_set_program(&g_reader, &fluxread_struct)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t wrgate_bit = 1u << wrgate_pin;
|
||||
uint32_t wrdata_bit = 1u << wrdata_pin;
|
||||
uint32_t index_bit = 1u << index_pin;
|
||||
pio_sm_set_pindirs_with_mask(g_reader.pio, g_reader.sm, wrgate_bit | wrdata_bit, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, wrgate_bit | wrdata_bit | index_bit, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, 0, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, wrgate_bit | wrdata_bit | index_bit, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_gpio_init(g_reader.pio, wrgate_pin);
|
||||
pio_gpio_init(g_reader.pio, wrdata_pin);
|
||||
gpio_pull_up(index_pin);
|
||||
|
||||
pio_sm_config c = {0, 0, 0, 0};
|
||||
sm_config_set_wrap(&c, g_writer.offset,
|
||||
g_writer.offset + fluxread_struct.length - 1);
|
||||
sm_config_set_jmp_pin(&c, index_pin);
|
||||
sm_config_set_set_pins(&c, wrdata_pin, 1);
|
||||
sm_config_set_sideset_pins(&c, wrgate_pin);
|
||||
sm_config_set_sideset(&c, fluxwrite_sideset_pin_count, fluxwrite_sideset_enable, false);
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
float div = (float)clock_get_hz(clk_sys) / (24e6);
|
||||
sm_config_set_clkdiv(&c, div); // 24MHz output clock
|
||||
|
||||
pio_sm_init(g_writer.pio, g_writer.sm, g_writer.offset, &c);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define OVERHEAD (15) // minimum pulse length due to PIO overhead, about 0.625us
|
||||
static void write_fifo(unsigned value) {
|
||||
if (value < OVERHEAD) { value = 1; }
|
||||
else { value -= OVERHEAD; if(value > 0xffff) value = 0xffff; }
|
||||
if (g_writer.half) {
|
||||
unsigned write_val = (g_writer.half << 16) | value;
|
||||
pio_sm_put_blocking(g_writer.pio, g_writer.sm, write_val);
|
||||
g_writer.half = 0;
|
||||
} else {
|
||||
g_writer.half = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_write() {
|
||||
pio_sm_exec(g_writer.pio, g_writer.sm, g_writer.offset);
|
||||
pio_sm_restart(g_writer.pio, g_writer.sm);
|
||||
}
|
||||
|
||||
static void write_foreground(int index_pin, uint8_t *pulses, uint8_t *pulse_end, bool store_greaseweazle) {
|
||||
int old_index_state = gpio_get(index_pin);
|
||||
int index_count = 0;
|
||||
|
||||
pio_sm_exec(g_writer.pio, g_writer.sm, g_writer.offset);
|
||||
pio_sm_restart(g_writer.pio, g_writer.sm);
|
||||
|
||||
Serial.printf("write_foreground pulses=%p pulse_end=%p\n", pulses, pulse_end);
|
||||
while(pulses != pulse_end) {
|
||||
unsigned value = greaseunpack(&pulses, pulse_end, store_greaseweazle);
|
||||
write_fifo(value);
|
||||
do {
|
||||
int index_state = gpio_get(index_pin);
|
||||
if(old_index_state && !index_state) {
|
||||
index_count ++;
|
||||
// A full revolution has occurred, stop writing immediately
|
||||
if(index_count == 2) {
|
||||
disable_write();
|
||||
Serial.printf("disable_write pulses=%p pulse_end=%p\n", pulses, pulse_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(pio_sm_is_tx_fifo_full(g_writer.pio, g_writer.sm));
|
||||
}
|
||||
Serial.printf("end of write pulses=%p pulse_end=%p\n", pulses, pulse_end);
|
||||
}
|
||||
|
||||
static void free_write() {
|
||||
if (!g_writer.pio) {
|
||||
// already deinit
|
||||
return;
|
||||
}
|
||||
disable_write();
|
||||
pio_sm_unclaim(g_writer.pio, g_writer.sm);
|
||||
pio_remove_program(g_writer.pio, &fluxread_struct, g_writer.offset);
|
||||
memset(&g_writer, 0, sizeof(g_writer));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Adafruit_Floppy.h>
|
||||
|
||||
uint32_t rp2040_flux_capture(int indexpin, int rdpin, volatile uint8_t *pulses,
|
||||
uint32_t rp2040_flux_capture(int index_pin, int rdpin, volatile uint8_t *pulses,
|
||||
volatile uint8_t *pulse_end,
|
||||
uint32_t *falling_index_offset,
|
||||
bool store_greaseweazle) {
|
||||
init_capture(indexpin, rdpin);
|
||||
capture_foreground(indexpin, (uint8_t *)pulses, (uint8_t *)pulse_end, true,
|
||||
init_capture(index_pin, rdpin);
|
||||
capture_foreground(index_pin, (uint8_t *)pulses, (uint8_t *)pulse_end, true,
|
||||
false, falling_index_offset, store_greaseweazle);
|
||||
free_capture();
|
||||
return pulse_end - pulses;
|
||||
|
|
@ -271,7 +349,7 @@ bool Adafruit_Floppy::start_polled_capture(void) {
|
|||
if (!init_capture())
|
||||
return false;
|
||||
start_common();
|
||||
pio_sm_set_enabled(g_floppy.pio, g_floppy.sm, true);
|
||||
pio_sm_set_enabled(g_reader.pio, g_reader.sm, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -290,5 +368,17 @@ uint16_t mfm_io_sample_flux(bool *index) {
|
|||
return delta / 2;
|
||||
}
|
||||
|
||||
void rp2040_flux_write(int index_pin, int wrgate_pin, int wrdata_pin, uint8_t *pulses, uint8_t *pulse_end, bool store_greaseweazle) {
|
||||
if (!init_write(index_pin, wrgate_pin, wrdata_pin)) { return; }
|
||||
write_foreground(index_pin, (uint8_t *)pulses, (uint8_t *)pulse_end, store_greaseweazle);
|
||||
uint32_t wrgate_bit = 1u << wrgate_pin;
|
||||
uint32_t wrdata_bit = 1u << wrdata_pin;
|
||||
uint32_t index_bit = 1u << index_pin;
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, wrgate_bit | wrdata_bit | index_bit, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, 0, wrgate_bit | wrdata_bit | index_bit);
|
||||
pio_sm_set_pins_with_mask(g_reader.pio, g_reader.sm, wrgate_bit | wrdata_bit | index_bit, wrgate_bit | wrdata_bit | index_bit);
|
||||
free_write();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
// Encoding flux of duration T:
|
||||
// 0: Impossible
|
||||
|
|
@ -53,3 +54,47 @@ static inline uint8_t *greasepack(uint8_t *buf, uint8_t *end, unsigned value) {
|
|||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline unsigned greaseunpack(uint8_t **buf_, uint8_t *end, bool store_greaseweazel) {
|
||||
#define BUF (*buf_)
|
||||
if (!store_greaseweazel) {
|
||||
if (!BUF || BUF == end) {
|
||||
return 0xffff;
|
||||
}
|
||||
return *BUF++;
|
||||
}
|
||||
|
||||
while(true) {
|
||||
// already no data left
|
||||
if (!BUF || BUF == end) {
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
size_t left = end-BUF;
|
||||
uint8_t data = *BUF++;
|
||||
size_t need = data == 255 ? 6 :
|
||||
data >= cutoff_1byte ? 2 : 1;
|
||||
if(left < need) {
|
||||
BUF = end;
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
if (need == 1) {
|
||||
return data;
|
||||
}
|
||||
if (need == 2) {
|
||||
uint8_t data2 = *BUF++;
|
||||
return (data - cutoff_1byte) * 250 + data2;
|
||||
}
|
||||
uint8_t data2 = *BUF++;
|
||||
if (data2 != 2) { BUF += 4; continue; } // something other than FluxOp.Space
|
||||
uint32_t value = (*BUF++ & 254) >> 1;
|
||||
value += (*BUF++ & 254) << 6;
|
||||
value += (*BUF++ & 254) << 13;
|
||||
value += (*BUF++ & 254) << 20;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
#undef BUF
|
||||
|
|
|
|||
Loading…
Reference in a new issue