WIP
This commit is contained in:
parent
5b021bb35a
commit
6f085764b9
3 changed files with 93 additions and 0 deletions
|
|
@ -23,6 +23,9 @@
|
|||
#define clr_debug_led() ((void)0)
|
||||
#endif
|
||||
|
||||
#define MFM_IO_MMIO (1)
|
||||
#include "mfm_impl.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Create a hardware interface to a floppy drive
|
||||
|
|
@ -271,6 +274,36 @@ void Adafruit_Floppy::step(bool dir, uint8_t times) {
|
|||
/**************************************************************************/
|
||||
int8_t Adafruit_Floppy::track(void) { return _track; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Capture and decode one track of MFM data
|
||||
@param sectors A pointer to an array of memory we can use to store into, 512*n_sectors bytes
|
||||
@param n_sectors The number of sectors (e.g., 18 for a standard 3.5", 1.44MB format)
|
||||
@param sector_validity An array of values set to 1 if the sector was captured, 0 if not captured (no IDAM, CRC error, etc)
|
||||
@return Number of sectors we actually captured
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint32_t Adafruit_Floppy::read_track_mfm(uint8_t *sectors, size_t n_sectors, uint8_t *sector_validity) {
|
||||
mfm_io_t io;
|
||||
#ifdef BUSIO_USE_FAST_PINIO
|
||||
io.index_port = indexPort;
|
||||
io.index_mask = indexMask;
|
||||
io.data_port = dataPort;
|
||||
io.data_mask = dataMask;
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
io.index_port = &sio_hw->gpio_in;
|
||||
io.index_mask = 1u << _indexpin;
|
||||
io.data_port = &sio_hw->gpio_in;
|
||||
io.data_mask = 1u << _rddatapin;
|
||||
#endif
|
||||
|
||||
noInterrupts();
|
||||
int result = read_track(io, n_sectors, buf, sector_validity);
|
||||
Interrupts();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Capture one track's worth of flux transitions, between two falling
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
int8_t track(void);
|
||||
void step(bool dir, uint8_t times);
|
||||
|
||||
uint32_t read_track_mfm(uint8_t *sectors, size_t n_sectors, uint8_t *sector_validity);
|
||||
uint32_t capture_track(uint8_t *pulses, uint32_t max_pulses)
|
||||
__attribute__((optimize("O3")));
|
||||
void print_pulse_bins(uint8_t *pulses, uint32_t num_pulses,
|
||||
|
|
|
|||
59
mfm_impl.h
59
mfm_impl.h
|
|
@ -7,8 +7,66 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("-O3")
|
||||
typedef struct mfm_io mfm_io_t;
|
||||
|
||||
#ifndef MFM_IO_MMIO
|
||||
#define MFM_IO_MMIO (0)
|
||||
#endif
|
||||
|
||||
// If you have a memory mapped peripheral, define MFM_IO_MMIO to get an implementation of the mfm_io functions.
|
||||
// then, just populate the fields with the actual registers to use
|
||||
#if MFM_IO_MMIO
|
||||
struct mfm_io {
|
||||
volatile uint32_t *index_port;
|
||||
uint32_t index_mask;
|
||||
volatile uint32_t *data_port;
|
||||
uint32_t data_mask;
|
||||
unsigned index_state;
|
||||
unsigned index_count;
|
||||
};
|
||||
|
||||
#define READ_DATA() (!!(*io->data_port & io->data_mask))
|
||||
#define READ_INDEX() (!!(*io->index_port & io->index_mask))
|
||||
__attribute__((always_inline))
|
||||
static inline mfm_io_symbol_t mfm_io_read_symbol(mfm_io_t *io) {
|
||||
unsigned pulse_count = 3;
|
||||
while (!READ_DATA()) {
|
||||
pulse_count++;
|
||||
}
|
||||
|
||||
unsigned index_state = (io->index_state << 1) | READ_INDEX();
|
||||
if ((index_state & 3) == 2) { // a zero-to-one transition
|
||||
io->index_count++;
|
||||
}
|
||||
io->index_state = index_state;
|
||||
|
||||
while (READ_DATA()) {
|
||||
pulse_count++;
|
||||
}
|
||||
|
||||
mfm_io_symbol_t result = pulse_10;
|
||||
if (pulse_count > T2_5) {
|
||||
result++;
|
||||
}
|
||||
if (pulse_count > T3_5) {
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void mfm_io_reset_sync_count(mfm_io_t *io) {
|
||||
io->index_count = 0;
|
||||
}
|
||||
|
||||
__attribute__((optimize("O3"), always_inline))
|
||||
inline static int mfm_io_get_sync_count(mfm_io_t *io) {
|
||||
return io->index_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum { pulse_10, pulse_100, pulse_1000 } mfm_io_symbol_t;
|
||||
|
||||
typedef enum { odd=0, even=1 } mfm_state_t;
|
||||
|
|
@ -189,3 +247,4 @@ static int read_track(mfm_io_t io, int n_sectors, void *data, uint8_t *validity)
|
|||
}
|
||||
return n_valid;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
|
|
|||
Loading…
Reference in a new issue