Skip to content

Commit

Permalink
Merge pull request #16 from jepler/applefloppyflux
Browse files Browse the repository at this point in the history
Add Apple Disk ][ Flux Writing for rp2040
  • Loading branch information
jepler authored Apr 16, 2022
2 parents 7f66508 + 2629a97 commit 1841d0f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 25 deletions.
8 changes: 6 additions & 2 deletions examples/greaseweazle/greaseweazle.ino
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ uint32_t captured_pulses;
// WARNING! there are 100K max flux pulses per track!
uint8_t flux_transitions[MAX_FLUX_PULSE_PER_TRACK];
bool motor_state = false; // we can cache whether the motor is spinning
bool flux_status; // result of last flux read or write command


void loop() {
Expand Down Expand Up @@ -484,6 +485,7 @@ void loop() {

// THE END
Serial.write((byte)0);
flux_status = true;
}
else if (cmd == GW_CMD_WRITEFLUX) {
if (!floppy) goto needfloppy;
Expand All @@ -497,6 +499,7 @@ void loop() {
} else {
//uint8_t cue_at_index = cmd_buffer[2];
//uint8_t terminate_at_index = cmd_buffer[3];
// send an ACK to request data
reply_buffer[i++] = GW_ACK_OK;
Serial.write(reply_buffer, 2);

Expand All @@ -511,14 +514,15 @@ void loop() {
Serial1.println("*** FLUX OVERRUN ***");
while (1) yield();
}
floppy->write_track(flux_transitions, fluxors - 7, true);
flux_status = floppy->write_track(flux_transitions, fluxors - 7, true);
Serial1.println("wrote fluxors");
Serial.write((byte)0);

}
}
else if (cmd == GW_CMD_GETFLUXSTATUS) {
Serial1.println("get flux status");
reply_buffer[i++] = GW_ACK_OK;
reply_buffer[i++] = flux_status ? GW_ACK_OK : GW_ACK_BADPIN;
Serial.write(reply_buffer, 2);
}

Expand Down
26 changes: 18 additions & 8 deletions src/Adafruit_Floppy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ extern volatile bool g_writing_pulses;
@param wrdatapin A pin connected to the floppy Write Data input
@param wrgatepin A pin connected to the floppy Write Gate input
@param rddatapin A pin connected to the floppy Read Data output
@param is_apple2 True if the flux write waveform is like Apple Disk ][
*/
/**************************************************************************/
Adafruit_FloppyBase::Adafruit_FloppyBase(int indexpin, int wrdatapin,
int wrgatepin, int rddatapin)
int wrgatepin, int rddatapin,
bool is_apple2)
: _indexpin(indexpin), _wrdatapin(wrdatapin), _wrgatepin(wrgatepin),
_rddatapin(rddatapin) {}
_rddatapin(rddatapin), _is_apple2(is_apple2) {}

/**************************************************************************/
/*!
Expand Down Expand Up @@ -648,15 +650,19 @@ uint32_t Adafruit_FloppyBase::capture_track(volatile uint8_t *pulses,
@param pulses An array of timer-count pulses
@param num_pulses How many bytes are in the pulse array
@param store_greaseweazle If true, long pulses are 'packed' in gw format
@returns False if the data could not be written (samd51 cannot write apple
flux format)
*/
/**************************************************************************/
void Adafruit_FloppyBase::write_track(uint8_t *pulses, uint32_t num_pulses,
bool Adafruit_FloppyBase::write_track(uint8_t *pulses, uint32_t num_pulses,
bool store_greaseweazle) {
#if defined(ARDUINO_ARCH_RP2040)
rp2040_flux_write(_indexpin, _wrgatepin, _wrdatapin, pulses,
pulses + num_pulses, store_greaseweazle);
return rp2040_flux_write(_indexpin, _wrgatepin, _wrdatapin, pulses,
pulses + num_pulses, store_greaseweazle, _is_apple2);
#elif defined(__SAMD51__)

if (_is_apple2) {
return false;
}
pinMode(_wrdatapin, OUTPUT);
digitalWrite(_wrdatapin, HIGH);

Expand Down Expand Up @@ -696,7 +702,11 @@ void Adafruit_FloppyBase::write_track(uint8_t *pulses, uint32_t num_pulses,
disable_generate();
deinit_generate();

return true;
#else // bitbang it!
if (_is_apple2) {
return false;
}
uint8_t *pulses_ptr = pulses;

#ifdef BUSIO_USE_FAST_PINIO
Expand Down Expand Up @@ -743,8 +753,8 @@ void Adafruit_FloppyBase::write_track(uint8_t *pulses, uint32_t num_pulses,
digitalWrite(_wrgatepin, HIGH);
digitalWrite(_wrdatapin, HIGH);
interrupts();
return true;
#endif
return;
}

/**************************************************************************/
Expand Down Expand Up @@ -911,7 +921,7 @@ Adafruit_Apple2Floppy::Adafruit_Apple2Floppy(int8_t indexpin, int8_t selectpin,
int8_t wrdatapin, int8_t wrgatepin,
int8_t protectpin,
int8_t rddatapin)
: Adafruit_FloppyBase{indexpin, wrdatapin, wrgatepin, rddatapin},
: Adafruit_FloppyBase{indexpin, wrdatapin, wrgatepin, rddatapin, true},
_selectpin{selectpin}, _phase1pin{phase1pin}, _phase2pin{phase2pin},
_phase3pin{phase3pin}, _phase4pin{phase4pin}, _protectpin{protectpin} {}

Expand Down
7 changes: 4 additions & 3 deletions src/Adafruit_Floppy.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ typedef enum {
/**************************************************************************/
class Adafruit_FloppyBase {
protected:
Adafruit_FloppyBase(int indexpin, int wrdatapin, int wrgatepin,
int rddatapin);
Adafruit_FloppyBase(int indexpin, int wrdatapin, int wrgatepin, int rddatapin,
bool is_apple2 = false);

public:
bool begin(void);
Expand Down Expand Up @@ -121,7 +121,7 @@ class Adafruit_FloppyBase {
uint32_t capture_ms = 0)
__attribute__((optimize("O3")));

void write_track(uint8_t *pulses, uint32_t num_pulses,
bool write_track(uint8_t *pulses, uint32_t num_pulses,
bool store_greaseweazle = false)
__attribute__((optimize("O3")));
void print_pulse_bins(uint8_t *pulses, uint32_t num_pulses,
Expand Down Expand Up @@ -169,6 +169,7 @@ class Adafruit_FloppyBase {
void wait_for_index_pulse_low(void);

int8_t _indexpin, _wrdatapin, _wrgatepin, _rddatapin;
bool _is_apple2;

#ifdef BUSIO_USE_FAST_PINIO
BusIO_PortReg *indexPort;
Expand Down
45 changes: 35 additions & 10 deletions src/arch_rp2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ static const pio_program_t fluxread_struct = {.instructions = fluxread,
sizeof(fluxread[0]),
.origin = -1};

static const int fluxwrite_sideset_pin_count = 1;
static const bool fluxwrite_sideset_enable = 1;
static const int fluxwrite_sideset_pin_count = 0;
static const bool fluxwrite_sideset_enable = 0;
static const uint16_t fluxwrite[] = {
// loop_flux:
0xe000, // set pins, 0 ; drive pin low
Expand All @@ -69,8 +69,28 @@ static const pio_program_t fluxwrite_struct = {.instructions = fluxwrite,
sizeof(fluxwrite[0]),
.origin = -1};

static const int fluxwrite_apple2_sideset_pin_count = 0;
static const bool fluxwrite_apple2_sideset_enable = 0;
static const uint16_t fluxwrite_apple2[] = {
0x6030, // out x, 16 ; get the next timing pulse information, may block
0xe001, // set pins, 1 ; drive pin high
0xb042, // nop [16]
// loop_high:
0x0043, // jmp x--, loop_high
0x6030, // out x, 16 ; get the next timing pulse information, may block
0xe000, // set pins, 0 ; drive pin low
0xb042, // nop [16]
// loop_low:
0x0047, // jmp x--, loop_low
};
static const pio_program_t fluxwrite_apple2_struct = {
.instructions = fluxwrite_apple2,
.length = sizeof(fluxwrite_apple2) / sizeof(fluxwrite_apple2[0]),
.origin = -1};

typedef struct floppy_singleton {
PIO pio;
const pio_program_t *program;
unsigned sm;
uint16_t offset;
uint16_t half;
Expand Down Expand Up @@ -229,12 +249,16 @@ static uint8_t *capture_foreground(int index_pin, uint8_t *start, uint8_t *end,

static void enable_capture_fifo() { start_common(); }

static bool init_write(int wrdata_pin) {
static bool init_write(int wrdata_pin, bool is_apple2) {
if (g_writer.pio) {
return true;
}

if (!allocate_pio_set_program(&g_writer, &fluxwrite_struct)) {
const pio_program_t *program =
is_apple2 ? &fluxwrite_apple2_struct : &fluxwrite_struct;
g_writer.program = program;

if (!allocate_pio_set_program(&g_writer, program)) {
return false;
}

Expand All @@ -250,7 +274,7 @@ static bool init_write(int wrdata_pin) {

pio_sm_config c{};
sm_config_set_wrap(&c, g_writer.offset,
g_writer.offset + fluxwrite_struct.length - 1);
g_writer.offset + program->length - 1);
sm_config_set_set_pins(&c, wrdata_pin, 1);
sm_config_set_out_shift(&c, true, true, 16);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
Expand Down Expand Up @@ -332,7 +356,7 @@ static void free_write() {
}
disable_write();
pio_sm_unclaim(g_writer.pio, g_writer.sm);
pio_remove_program(g_writer.pio, &fluxwrite_struct, g_writer.offset);
pio_remove_program(g_writer.pio, g_writer.program, g_writer.offset);
memset(&g_writer, 0, sizeof(g_writer));
}

Expand Down Expand Up @@ -384,15 +408,16 @@ uint16_t mfm_io_sample_flux(bool *index) {
return delta / 2;
}

void rp2040_flux_write(int index_pin, int wrgate_pin, int wrdata_pin,
bool 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(wrdata_pin)) {
return;
bool store_greaseweazle, bool is_apple2) {
if (!init_write(wrdata_pin, is_apple2)) {
return false;
}
write_foreground(index_pin, wrgate_pin, (uint8_t *)pulses,
(uint8_t *)pulse_end, store_greaseweazle);
free_write();
return true;
}

#endif
Expand Down
4 changes: 2 additions & 2 deletions src/arch_rp2.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern uint32_t
rp2040_flux_capture(int indexpin, int rdpin, volatile uint8_t *pulses,
volatile uint8_t *end, int32_t *falling_index_offset,
bool store_greaseweazle, uint32_t capture_counts);
extern void rp2040_flux_write(int index_pin, int wrgate_pin, int wrdata_pin,
extern bool rp2040_flux_write(int index_pin, int wrgate_pin, int wrdata_pin,
uint8_t *pulses, uint8_t *pulse_end,
bool store_greaseweazel);
bool store_greaseweazel, bool is_apple2);
#endif

0 comments on commit 1841d0f

Please sign in to comment.