Rework SD interface and add head 4
This commit is contained in:
92
2025-09-05_17-36-29.kicad_sym
Normal file
92
2025-09-05_17-36-29.kicad_sym
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
|
||||||
|
(symbol "5031821852" (pin_names (offset 0.254)) (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (id 0) (at 25.4 10.16 0)
|
||||||
|
(effects (font (size 1.524 1.524)))
|
||||||
|
)
|
||||||
|
(property "Value" "5031821852" (id 1) (at 25.4 7.62 0)
|
||||||
|
(effects (font (size 1.524 1.524)))
|
||||||
|
)
|
||||||
|
(property "Footprint" "503182-1852_MOL" (id 2) (at 0 0 0)
|
||||||
|
(effects (font (size 1.27 1.27) italic) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "https://www.molex.com/en-us/products/part-detail-pdf/5031821852?display=pdf" (id 3) (at 0 0 0)
|
||||||
|
(effects (font (size 1.27 1.27) italic) hide)
|
||||||
|
)
|
||||||
|
(property "ki_keywords" "5031821852" (id 4) (at 0 0 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "ki_locked" "" (id 5) (at 0 0 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "ki_fp_filters" "503182-1852_MOL" (id 6) (at 0 0 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(symbol "5031821852_0_1"
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 7.62 5.08)
|
||||||
|
(xy 7.62 -12.7)
|
||||||
|
)
|
||||||
|
(stroke (width 0.127) (type default) (color 0 0 0 0))
|
||||||
|
(fill (type none))
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 7.62 -12.7)
|
||||||
|
(xy 43.18 -12.7)
|
||||||
|
)
|
||||||
|
(stroke (width 0.127) (type default) (color 0 0 0 0))
|
||||||
|
(fill (type none))
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 43.18 -12.7)
|
||||||
|
(xy 43.18 5.08)
|
||||||
|
)
|
||||||
|
(stroke (width 0.127) (type default) (color 0 0 0 0))
|
||||||
|
(fill (type none))
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 43.18 5.08)
|
||||||
|
(xy 7.62 5.08)
|
||||||
|
)
|
||||||
|
(stroke (width 0.127) (type default) (color 0 0 0 0))
|
||||||
|
(fill (type none))
|
||||||
|
)
|
||||||
|
(pin bidirectional line (at 0 0 0) (length 7.62)
|
||||||
|
(name "DATA_2" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "1" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin bidirectional line (at 0 -2.54 0) (length 7.62)
|
||||||
|
(name "CD/DAT_3" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "2" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin unspecified line (at 0 -5.08 0) (length 7.62)
|
||||||
|
(name "CMD" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "3" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin power_in line (at 0 -7.62 0) (length 7.62)
|
||||||
|
(name "VDD" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "4" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin unspecified line (at 50.8 -7.62 180) (length 7.62)
|
||||||
|
(name "CLK" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "5" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin power_out line (at 50.8 -5.08 180) (length 7.62)
|
||||||
|
(name "VSS" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "6" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin bidirectional line (at 50.8 -2.54 180) (length 7.62)
|
||||||
|
(name "DAT0" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "7" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
(pin bidirectional line (at 50.8 0 180) (length 7.62)
|
||||||
|
(name "DAT1" (effects (font (size 1.27 1.27))))
|
||||||
|
(number "8" (effects (font (size 1.27 1.27))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
31290
RTmFM.kicad_pcb
31290
RTmFM.kicad_pcb
File diff suppressed because it is too large
Load Diff
1242
RTmFM.kicad_sch
1242
RTmFM.kicad_sch
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,8 @@ BIN=bin/$(SKETCH).ino.bin
|
|||||||
#IP=$(shell avahi-resolve -n $(HOST).local | cut -f2 -d' ')
|
#IP=$(shell avahi-resolve -n $(HOST).local | cut -f2 -d' ')
|
||||||
|
|
||||||
$(BIN): $(SKETCH).ino datastream.h
|
$(BIN): $(SKETCH).ino datastream.h
|
||||||
arduino-cli compile --fqbn $(BOARD) --board-options "freq=300,arch=riscv" --output-dir bin --build-path build
|
#arduino-cli compile --fqbn $(BOARD) --board-options "freq=300,arch=riscv" --output-dir bin --build-path build
|
||||||
|
arduino-cli compile --fqbn $(BOARD) --board-options "freq=300" --output-dir bin --build-path build
|
||||||
|
|
||||||
upload: $(BIN)
|
upload: $(BIN)
|
||||||
arduino-cli upload --fqbn $(BOARD) -p $(PORT) --input-dir bin
|
arduino-cli upload --fqbn $(BOARD) -p $(PORT) --input-dir bin
|
||||||
|
|||||||
@@ -1,31 +1,54 @@
|
|||||||
#include <CLI.h>
|
#include <CLI.h>
|
||||||
|
#include <SdFat.h>
|
||||||
#include "datastream.h"
|
#include "datastream.h"
|
||||||
|
|
||||||
|
#define SDIO_CLK 16
|
||||||
|
#define SDIO_CMD 17
|
||||||
|
#define SDIO_DAT0 18
|
||||||
|
#define SDIO_DAT1 19
|
||||||
|
#define SDIO_DAT2 20
|
||||||
|
#define SDIO_DAT3 21
|
||||||
|
|
||||||
#define SECTOR_128 0
|
#define SECTOR_128 0
|
||||||
#define SECTOR_256 1
|
#define SECTOR_256 1
|
||||||
#define SECTOR_512 2
|
#define SECTOR_512 2
|
||||||
#define SECTOR_1024 3
|
#define SECTOR_1024 3
|
||||||
|
|
||||||
|
|
||||||
|
#define INDEX 13
|
||||||
|
#define DOUT 12
|
||||||
|
|
||||||
|
#define STEP 7
|
||||||
|
#define DIR 8
|
||||||
|
#define SEEK_DONE 9
|
||||||
|
#define TRACK0 10
|
||||||
|
|
||||||
|
#define HSEL0 4
|
||||||
|
#define HSEL1 5
|
||||||
|
#define HSEL2 6
|
||||||
|
#define HSEL3 7
|
||||||
|
|
||||||
static PIOProgram datastreamPgm(&datastream_program);
|
static PIOProgram datastreamPgm(&datastream_program);
|
||||||
|
|
||||||
PIO pio;
|
PIO pio;
|
||||||
int sm;
|
int sm;
|
||||||
int offset;
|
int offset;
|
||||||
|
int dma;
|
||||||
|
|
||||||
|
uint32_t loadtime;
|
||||||
|
|
||||||
|
uint32_t current_head = 0;
|
||||||
|
uint32_t current_cyl = 0;
|
||||||
|
uint32_t current_sector = 0;
|
||||||
|
|
||||||
#define POLY16 0x1021
|
#define POLY16 0x1021
|
||||||
#define POLY32 0xa00805
|
#define POLY32 0xa00805
|
||||||
|
|
||||||
#define CQ16(V, C, P) C = crc16(V, C, P); queue(mfm_encode(V))
|
|
||||||
#define CQ32(V, C, P) C = crc32(V, C, P); queue(mfm_encode(V))
|
|
||||||
|
|
||||||
#define NUM_SECTORS 17
|
#define NUM_SECTORS 17
|
||||||
|
|
||||||
#define TRACK_SIZE (512 * NUM_SECTORS)
|
#define TRACK_SIZE (512 * NUM_SECTORS)
|
||||||
|
|
||||||
uint8_t *track_data;
|
uint8_t track_data[512 * 17 * 16];
|
||||||
|
|
||||||
#define OPT_HEADER_CRC16 0x00000001
|
#define OPT_HEADER_CRC16 0x00000001
|
||||||
#define OPT_HEADER_CRC32 0x00000002
|
#define OPT_HEADER_CRC32 0x00000002
|
||||||
@@ -34,16 +57,19 @@ uint8_t *track_data;
|
|||||||
#define OPT_DATA_CRC32 0x00000008
|
#define OPT_DATA_CRC32 0x00000008
|
||||||
#define OPT_DATA_CRC_MASK 0xFFFFFFF3
|
#define OPT_DATA_CRC_MASK 0xFFFFFFF3
|
||||||
|
|
||||||
|
SdFs sd;
|
||||||
|
FsFile mounted_file;
|
||||||
|
|
||||||
struct disk_format {
|
struct disk_format {
|
||||||
uint16_t cyls;
|
uint16_t cyls;
|
||||||
uint8_t heads;
|
uint8_t heads;
|
||||||
uint8_t sectors;
|
uint8_t sectors;
|
||||||
uint8_t sector_size;
|
uint8_t sector_size;
|
||||||
uint8_t track_pregap;
|
uint32_t index_width;
|
||||||
uint8_t track_postgap;
|
uint32_t track_pregap;
|
||||||
uint8_t header_postgap;
|
uint32_t track_postgap;
|
||||||
uint8_t data_postgap;
|
uint32_t header_postgap;
|
||||||
|
uint32_t data_postgap;
|
||||||
float data_rate;
|
float data_rate;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t header_poly;
|
uint32_t header_poly;
|
||||||
@@ -64,17 +90,22 @@ struct disk_format RD54 = {
|
|||||||
15, // Heads
|
15, // Heads
|
||||||
17, // Sectors,
|
17, // Sectors,
|
||||||
SECTOR_512, // Bytes per sector
|
SECTOR_512, // Bytes per sector
|
||||||
151, // Track pregap
|
10, // Index width - how long the index pulse is low
|
||||||
151, // Track postgap
|
290, // Track pregap - Time between index pulse and first sync byte
|
||||||
16, // Header postgap
|
1100, // Track postgap - Time between last sync byte and index pulse
|
||||||
50, // Data postgap
|
41, // Header postgap - Time between header sync byte and data sync byte
|
||||||
|
911, // Data postgap - Time between data sync byte and header sync byte of next sector
|
||||||
5000000, // Data Rate
|
5000000, // Data Rate
|
||||||
OPT_HEADER_CRC16 | OPT_DATA_CRC32,
|
OPT_HEADER_CRC16 | OPT_DATA_CRC32,
|
||||||
0x1021, // Header CRC polynomial
|
0x1021, // Header CRC polynomial
|
||||||
0xa00805, // Data CRC polynomial
|
0xa00805, // Data CRC polynomial
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sector {
|
||||||
|
uint16_t header[10];
|
||||||
|
uint16_t data[520];
|
||||||
|
};
|
||||||
|
|
||||||
struct disk_format *format;
|
struct disk_format *format;
|
||||||
|
|
||||||
@@ -120,8 +151,6 @@ uint32_t crc32(uint8_t val, uint32_t crc, uint32_t poly)
|
|||||||
|
|
||||||
uint8_t last_bit = 0;
|
uint8_t last_bit = 0;
|
||||||
uint16_t mfm_encode_bit(uint8_t b) {
|
uint16_t mfm_encode_bit(uint8_t b) {
|
||||||
|
|
||||||
|
|
||||||
if (b == 0x80) {
|
if (b == 0x80) {
|
||||||
last_bit = 1;
|
last_bit = 1;
|
||||||
return 0b01;
|
return 0b01;
|
||||||
@@ -136,7 +165,10 @@ uint16_t mfm_encode_bit(uint8_t b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t mfm_encode(uint8_t b) {
|
uint16_t mfm_encode(uint8_t b, bool reset = false) {
|
||||||
|
if (reset) {
|
||||||
|
last_bit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t out = 0;
|
uint16_t out = 0;
|
||||||
|
|
||||||
@@ -149,122 +181,204 @@ uint16_t mfm_encode(uint8_t b) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void queue(uint16_t val) {
|
enum {
|
||||||
while(pio_sm_is_tx_fifo_full(pio, sm));
|
PH_INDEX_START,
|
||||||
pio->txf[sm] = val;
|
PH_INDEX_END,
|
||||||
}
|
PH_TRACK_PREGAP,
|
||||||
|
PH_SEND_HEADER,
|
||||||
void sync() {
|
PH_HEADER_POSTGAP,
|
||||||
uint16_t sync = mfm_encode(0xA1);
|
PH_SEND_DATA,
|
||||||
sync &= 0b1111111111011111;
|
PH_DATA_POSTGAP,
|
||||||
queue(sync);
|
PH_TRACK_POSTGAP
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void zero_pad() {
|
|
||||||
queue(mfm_encode(0x00));
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_header(uint16_t cyl, uint8_t head, uint8_t sector, uint8_t size) {
|
|
||||||
|
|
||||||
zero_pad();
|
|
||||||
sync();
|
|
||||||
if (format->flags & OPT_HEADER_CRC16) {
|
|
||||||
uint16_t header_crc = 0xFFFF;
|
|
||||||
header_crc = crc16(0xA1, header_crc, format->header_poly);
|
|
||||||
CQ16(0xFE, header_crc, format->header_poly);
|
|
||||||
CQ16(cyl & 0xFF, header_crc, format->header_poly);
|
|
||||||
CQ16(((cyl >> 4) & 0xF0) | (head & 0x0F), header_crc, format->header_poly);
|
|
||||||
CQ16(sector, header_crc, format->header_poly);
|
|
||||||
CQ16(size, header_crc, format->header_poly);
|
|
||||||
queue(mfm_encode((header_crc >> 8) & 0xFF));
|
|
||||||
queue(mfm_encode(header_crc & 0xFF));
|
|
||||||
} else if (format->flags & OPT_HEADER_CRC32) {
|
|
||||||
uint32_t header_crc = 0xFFFFFFFF;
|
|
||||||
header_crc = crc32(0xA1, header_crc, format->header_poly);
|
|
||||||
CQ32(0xFE, header_crc, format->header_poly);
|
|
||||||
CQ32(cyl & 0xFF, header_crc, format->header_poly);
|
|
||||||
CQ32(((cyl >> 4) & 0xF0) | (head & 0x0F), header_crc, format->header_poly);
|
|
||||||
CQ32(sector, header_crc, format->header_poly);
|
|
||||||
CQ32(size, header_crc, format->header_poly);
|
|
||||||
queue(mfm_encode((header_crc >> 24) & 0xFF));
|
|
||||||
queue(mfm_encode((header_crc >> 16) & 0xFF));
|
|
||||||
queue(mfm_encode((header_crc >> 8) & 0xFF));
|
|
||||||
queue(mfm_encode(header_crc & 0xFF));
|
|
||||||
}
|
|
||||||
zero_pad();
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_data(uint8_t *data, uint16_t len) {
|
|
||||||
zero_pad();
|
|
||||||
sync();
|
|
||||||
if (format->flags & OPT_DATA_CRC16) {
|
|
||||||
uint16_t data_crc = 0xFFFF;
|
|
||||||
data_crc = crc16(0xA1, data_crc, format->data_poly);
|
|
||||||
CQ16(0xFB, data_crc, format->data_poly);
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
CQ16(data[i], data_crc, format->data_poly);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue(mfm_encode((data_crc >> 8) & 0xFF));
|
|
||||||
queue(mfm_encode(data_crc & 0xFF));
|
|
||||||
} else if (format->flags & OPT_DATA_CRC32) {
|
|
||||||
uint32_t data_crc = 0xFFFFFFFF;
|
|
||||||
data_crc = crc32(0xA1, data_crc, format->data_poly);
|
|
||||||
CQ32(0xFB, data_crc, format->data_poly);
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
CQ32(data[i], data_crc, format->data_poly);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue(mfm_encode((data_crc >> 24) & 0xFF));
|
|
||||||
queue(mfm_encode((data_crc >> 16) & 0xFF));
|
|
||||||
queue(mfm_encode((data_crc >> 8) & 0xFF));
|
|
||||||
queue(mfm_encode(data_crc & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
zero_pad();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_sector(uint16_t cyl, uint8_t head, uint8_t sector, uint8_t size, uint8_t *data, uint8_t pad) {
|
|
||||||
send_header(cyl, head, sector, size);
|
|
||||||
|
|
||||||
for (int i = 0; i < pad; i++) {
|
|
||||||
zero_pad();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t len = 0x80 << size;
|
|
||||||
send_data(data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void second_cpu_thread() {
|
void second_cpu_thread() {
|
||||||
|
|
||||||
|
dma = dma_claim_unused_channel(true);
|
||||||
|
dma_channel_config config = dma_channel_get_default_config(dma);
|
||||||
|
channel_config_set_read_increment(&config, true);
|
||||||
|
channel_config_set_write_increment(&config, false);
|
||||||
|
channel_config_set_dreq(&config, pio_get_dreq(pio, sm, true));
|
||||||
|
channel_config_set_transfer_data_size(&config, DMA_SIZE_16);
|
||||||
|
|
||||||
|
uint32_t ts = micros();
|
||||||
|
|
||||||
|
int phase = 0;
|
||||||
|
int next_sector = 1;
|
||||||
|
current_sector = 0;
|
||||||
|
|
||||||
|
struct sector sectorA;
|
||||||
|
struct sector sectorB;
|
||||||
|
|
||||||
|
struct sector *load = §orA;
|
||||||
|
struct sector *send = §orB;
|
||||||
|
struct sector *swap;
|
||||||
|
|
||||||
|
load_sector(load, current_cyl, current_head, current_sector, &track_data[0]);
|
||||||
|
|
||||||
|
pinMode(HSEL0, INPUT);
|
||||||
|
pinMode(HSEL1, INPUT);
|
||||||
|
pinMode(HSEL2, INPUT);
|
||||||
|
pinMode(HSEL3, INPUT);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
for (int i = 0; i < format->track_postgap; i++) {
|
|
||||||
zero_pad();
|
|
||||||
}
|
|
||||||
format->idx_period = micros() - format->idx_ts;
|
|
||||||
format->idx_ts = micros();
|
|
||||||
digitalWrite(13, LOW);
|
|
||||||
zero_pad();
|
|
||||||
digitalWrite(13, HIGH);
|
|
||||||
for (int i = 0; i < format->track_pregap; i++) {
|
|
||||||
zero_pad();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int sector = 0; sector < format->sectors; sector++) {
|
current_head = digitalRead(HSEL0) | (digitalRead(HSEL1) << 1) | (digitalRead(HSEL2) << 2) | (digitalRead(HSEL3) << 3);
|
||||||
|
|
||||||
send_sector(0, 0, sector, format->sector_size, track_data + (sector * format->slen), format->header_postgap);
|
switch (phase) {
|
||||||
|
case PH_INDEX_START: // Start index pulse
|
||||||
|
ts = micros();
|
||||||
|
format->idx_period = micros() - format->idx_ts;
|
||||||
|
format->idx_ts = micros();
|
||||||
|
digitalWrite(INDEX, LOW);
|
||||||
|
phase++;
|
||||||
|
break;
|
||||||
|
|
||||||
for (int i = 0; i < format->data_postgap; i++) {
|
case PH_INDEX_END: // Index pulse timing
|
||||||
zero_pad();
|
if ((micros() - ts) >= format->index_width) {
|
||||||
}
|
ts = micros();
|
||||||
|
digitalWrite(INDEX, HIGH);
|
||||||
|
phase++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_TRACK_PREGAP: // Track pre-gap
|
||||||
|
if ((micros() - ts) >= format->track_pregap) {
|
||||||
|
ts = micros();
|
||||||
|
phase = PH_SEND_HEADER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_SEND_HEADER:
|
||||||
|
ts = micros();
|
||||||
|
|
||||||
|
swap = load;
|
||||||
|
load = send;
|
||||||
|
send = swap;
|
||||||
|
|
||||||
|
dma_channel_configure(dma, &config,
|
||||||
|
&pio->txf[sm],
|
||||||
|
send->header,
|
||||||
|
10,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
phase = PH_HEADER_POSTGAP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_HEADER_POSTGAP:
|
||||||
|
if ((micros() - ts) >= format->header_postgap) {
|
||||||
|
ts = micros();
|
||||||
|
phase = PH_SEND_DATA;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_SEND_DATA:
|
||||||
|
ts = micros();
|
||||||
|
|
||||||
|
dma_channel_configure(dma, &config,
|
||||||
|
&pio->txf[sm],
|
||||||
|
send->data,
|
||||||
|
520,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
next_sector = (current_sector + 1) % format->sectors;
|
||||||
|
load_sector(load, current_cyl, current_head, next_sector, &track_data[512 * next_sector]);
|
||||||
|
if (current_sector < format->sectors - 1) {
|
||||||
|
phase = PH_DATA_POSTGAP;
|
||||||
|
} else {
|
||||||
|
phase = PH_TRACK_POSTGAP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_DATA_POSTGAP:
|
||||||
|
if ((micros() - ts) > format->data_postgap) {
|
||||||
|
ts = micros();
|
||||||
|
current_sector++;
|
||||||
|
phase = PH_SEND_HEADER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PH_TRACK_POSTGAP:
|
||||||
|
if ((micros() - ts) > format->track_postgap) {
|
||||||
|
ts = micros();
|
||||||
|
current_sector = 0;
|
||||||
|
phase = PH_INDEX_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_sector(struct sector *s, int cno, int hno, int secno, uint8_t *data) {
|
||||||
|
|
||||||
|
uint32_t ts = micros();
|
||||||
|
|
||||||
|
uint16_t hp = format->header_poly;
|
||||||
|
uint32_t dp = format->data_poly;
|
||||||
|
|
||||||
|
s->header[0] = 0;
|
||||||
|
s->header[1] = 0xA1;
|
||||||
|
s->header[2] = 0xFE;
|
||||||
|
s->header[3] = (cno & 0xFF);
|
||||||
|
s->header[4] = ((cno & 0xF00) >> 4) | (hno & 0x0F);
|
||||||
|
s->header[5] = secno;
|
||||||
|
s->header[6] = 0x02;
|
||||||
|
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
for (int i = 1; i < 7; i++) {
|
||||||
|
crc = crc16(s->header[i], crc, hp);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->header[7] = (crc >> 8) & 0xFF;
|
||||||
|
s->header[8] = crc & 0xFF;
|
||||||
|
s->header[9] = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
s->header[i] = mfm_encode(s->header[i], i == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->header[1] &= 0b1111111111011111;
|
||||||
|
|
||||||
|
s->data[0] = 0;
|
||||||
|
s->data[1] = 0xA1;
|
||||||
|
s->data[2] = 0xFB;
|
||||||
|
for (int i = 0; i < 512; i++) {
|
||||||
|
s->data[3 + i] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t c32 = 0xFFFFFFFF;
|
||||||
|
for (int i = 1; i < 515; i++) {
|
||||||
|
c32 = crc32(s->data[i], c32, dp);
|
||||||
|
}
|
||||||
|
s->data[515] = (c32 >> 24) & 0xFF;
|
||||||
|
s->data[516] = (c32 >> 16) & 0xFF;
|
||||||
|
s->data[517] = (c32 >> 8) & 0xFF;
|
||||||
|
s->data[518] = c32 & 0xFF;
|
||||||
|
s->data[519] = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 520; i++) {
|
||||||
|
s->data[i] = mfm_encode(s->data[i], i == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->data[1] &= 0b1111111111011111;
|
||||||
|
|
||||||
|
loadtime = micros() - ts;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_cyl(FsFile file, uint8_t *data, uint32_t cyl, uint32_t heads, uint32_t sectors, uint32_t sectorsize) {
|
||||||
|
uint32_t len = 0x80 << sectorsize;
|
||||||
|
len *= sectors;
|
||||||
|
len *= heads;
|
||||||
|
|
||||||
|
uint32_t offset = cyl * len;
|
||||||
|
|
||||||
|
file.seekSet(offset);
|
||||||
|
file.read(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CLI_COMMAND(cli_status) {
|
CLI_COMMAND(cli_status) {
|
||||||
uint32_t sector_bytes = 8 + format->slen + 6 + format->header_postgap + format->data_postgap + 4;
|
uint32_t sector_bytes = 8 + format->slen + 6 + format->header_postgap + format->data_postgap + 4;
|
||||||
@@ -343,14 +457,35 @@ CLI_COMMAND(cli_status) {
|
|||||||
|
|
||||||
dev->print("Requested Data Rate: ");
|
dev->print("Requested Data Rate: ");
|
||||||
dev->print(format->data_rate);
|
dev->print(format->data_rate);
|
||||||
dev->println("MHz");
|
dev->println("Hz");
|
||||||
dev->print("Actual Data Rate: ");
|
dev->print("Actual Data Rate: ");
|
||||||
dev->print(F_CPU / format->clock_div / 20.0);
|
dev->print(F_CPU / format->clock_div / 20.0);
|
||||||
dev->println("MHz");
|
dev->println("Hz");
|
||||||
|
|
||||||
dev->print("Clock divider: ");
|
dev->print("Clock divider: ");
|
||||||
dev->println(format->clock_div);
|
dev->println(format->clock_div);
|
||||||
|
|
||||||
|
dev->println();
|
||||||
|
dev->print("PIO: ");
|
||||||
|
dev->println(PIO_NUM(pio));
|
||||||
|
dev->print("State Machine: ");
|
||||||
|
dev->println(sm);
|
||||||
|
dev->print("Offset: ");
|
||||||
|
dev->println(offset);
|
||||||
|
|
||||||
|
dev->println();
|
||||||
|
dev->print("Load time: ");
|
||||||
|
dev->print(loadtime);
|
||||||
|
dev->println("uS");
|
||||||
|
|
||||||
|
dev->println();
|
||||||
|
dev->print("Current C/H/S: ");
|
||||||
|
dev->print(current_cyl);
|
||||||
|
dev->print("/");
|
||||||
|
dev->print(current_head);
|
||||||
|
dev->print("/");
|
||||||
|
dev->println(current_sector);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,9 +593,93 @@ CLI_COMMAND(cli_set) {
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLI_COMMAND(cli_ls) {
|
||||||
|
sd.ls(LS_A | LS_DATE | LS_SIZE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLI_COMMAND(cli_create) {
|
||||||
|
if (argc != 2) {
|
||||||
|
dev->println("Usage: create <filename>");
|
||||||
|
dev->println("Create a new image file using the current disk format");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sd.exists(argv[1])) {
|
||||||
|
dev->println("File already exists");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t disk_size = 0x80 << format->sector_size;
|
||||||
|
disk_size *= format->sectors;
|
||||||
|
disk_size *= format->heads;
|
||||||
|
disk_size *= format->cyls;
|
||||||
|
|
||||||
|
dev->println("Creating new file, please wait...");
|
||||||
|
FsFile newfile;
|
||||||
|
newfile.open(argv[1], O_RDWR | O_CREAT);
|
||||||
|
newfile.preAllocate(disk_size);
|
||||||
|
newfile.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLI_COMMAND(cli_mount) {
|
||||||
|
if (argc != 2) {
|
||||||
|
dev->println("Usage: mount <filename>");
|
||||||
|
dev->println("Mount an image file as the virtual disk");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sd.exists(argv[1])) {
|
||||||
|
dev->println("File not found");
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted_file = sd.open(argv[1], O_RDWR);
|
||||||
|
current_cyl = 0;
|
||||||
|
current_head = 0;
|
||||||
|
|
||||||
|
load_cyl(mounted_file, track_data, current_cyl, format->heads, format->sectors, format->sector_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void do_step() {
|
||||||
|
digitalWrite(SEEK_DONE, LOW);
|
||||||
|
int dir = digitalRead(DIR);
|
||||||
|
|
||||||
|
if (dir == 1 && current_cyl == 0) {
|
||||||
|
// No can do.
|
||||||
|
digitalWrite(SEEK_DONE, HIGH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == 1) {
|
||||||
|
current_cyl --;
|
||||||
|
} else {
|
||||||
|
current_cyl ++;
|
||||||
|
}
|
||||||
|
if (current_cyl >= format->cyls) {
|
||||||
|
current_cyl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_cyl(mounted_file, track_data, current_cyl, format->heads, format->sectors, format->sector_size);
|
||||||
|
|
||||||
|
digitalWrite(TRACK0, current_cyl == 0);
|
||||||
|
|
||||||
|
digitalWrite(SEEK_DONE, HIGH);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
|
|
||||||
|
if (!sd.begin(SdioConfig(SDIO_CLK, SDIO_CMD, SDIO_DAT0, 1.5))) {
|
||||||
|
sd.initErrorPrint();
|
||||||
|
}
|
||||||
|
|
||||||
datastreamPgm.prepare(&pio, &sm, &offset);
|
datastreamPgm.prepare(&pio, &sm, &offset);
|
||||||
datastream_program_init(pio, sm, offset);
|
datastream_program_init(pio, sm, offset, DOUT);
|
||||||
pio_sm_set_enabled(pio, sm, true);
|
pio_sm_set_enabled(pio, sm, true);
|
||||||
|
|
||||||
pio->txf[sm] = mfm_encode(0x00);
|
pio->txf[sm] = mfm_encode(0x00);
|
||||||
@@ -474,9 +693,7 @@ void setup() {
|
|||||||
format->slen = 0x80 << format->sector_size;
|
format->slen = 0x80 << format->sector_size;
|
||||||
format->tlen = format->slen * format->sectors;
|
format->tlen = format->slen * format->sectors;
|
||||||
|
|
||||||
track_data = (uint8_t *)malloc(format->tlen);
|
for (int i = 0; i < 512 * 17; i++) {
|
||||||
|
|
||||||
for (int i = 0; i < format->tlen; i++) {
|
|
||||||
track_data[i] = rand();
|
track_data[i] = rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,6 +709,18 @@ void setup() {
|
|||||||
|
|
||||||
CLI.addCommand("status", cli_status);
|
CLI.addCommand("status", cli_status);
|
||||||
CLI.addCommand("set", cli_set);
|
CLI.addCommand("set", cli_set);
|
||||||
|
CLI.addCommand("ls", cli_ls);
|
||||||
|
CLI.addCommand("create", cli_create);
|
||||||
|
CLI.addCommand("mount", cli_mount);
|
||||||
|
|
||||||
|
pinMode(STEP, INPUT);
|
||||||
|
pinMode(DIR, INPUT);
|
||||||
|
pinMode(SEEK_DONE, OUTPUT);
|
||||||
|
digitalWrite(SEEK_DONE, HIGH);
|
||||||
|
pinMode(TRACK0, OUTPUT);
|
||||||
|
digitalWrite(TRACK0, current_cyl == 0);
|
||||||
|
|
||||||
|
attachInterrupt(STEP, do_step, RISING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
@@ -26,17 +26,17 @@ loop:
|
|||||||
|
|
||||||
|
|
||||||
% c-sdk {
|
% c-sdk {
|
||||||
static inline void datastream_program_init(PIO pio, uint sm, uint offset) {
|
static inline void datastream_program_init(PIO pio, uint sm, uint offset, int dout) {
|
||||||
pio_set_gpio_base(pio, 0);
|
pio_set_gpio_base(pio, 0);
|
||||||
pio_gpio_init(pio, 12);
|
pio_gpio_init(pio, dout);
|
||||||
pio_sm_set_consecutive_pindirs(pio, sm, 12, 1, true);
|
pio_sm_set_consecutive_pindirs(pio, sm, dout, 1, true);
|
||||||
pio_sm_config c = datastream_program_get_default_config(offset);
|
pio_sm_config c = datastream_program_get_default_config(offset);
|
||||||
sm_config_set_out_shift(&c, false, false, 0);
|
sm_config_set_out_shift(&c, false, false, 0);
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||||
sm_config_set_clkdiv(&c, 3.0);
|
sm_config_set_clkdiv(&c, 3.0);
|
||||||
sm_config_set_out_pin_base(&c, 12);
|
sm_config_set_out_pin_base(&c, dout);
|
||||||
sm_config_set_out_pin_count(&c, 1);
|
sm_config_set_out_pin_count(&c, 1);
|
||||||
sm_config_set_set_pin_base(&c, 12);
|
sm_config_set_set_pin_base(&c, dout);
|
||||||
sm_config_set_set_pin_count(&c, 1);
|
sm_config_set_set_pin_count(&c, 1);
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
}
|
}
|
||||||
|
|||||||
69
footprints.pretty/503182-1852_MOL.kicad_mod
Normal file
69
footprints.pretty/503182-1852_MOL.kicad_mod
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
(footprint "503182-1852_MOL" (version 20211014) (generator pcbnew)
|
||||||
|
(layer "F.Cu")
|
||||||
|
(tags "5031821852 ")
|
||||||
|
(attr smd)
|
||||||
|
(fp_text reference "REF**" (at 0 5.610299 unlocked) (layer F.SilkS)
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_text value 503182-1852_MOL (at 0 5.610299 unlocked) (layer F.Fab)
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_text user "${REFERENCE}" (at 0 5.610299 unlocked) (layer F.Fab)
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_line (start -1.8367 19.190798) (end -1.8367 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_arc (start -8.22544 5.991276) (mid -8.6106 5.610299) (end -8.22544 5.229321) (layer "F.SilkS") (width 0.508))
|
||||||
|
(fp_circle (center -8.2296 5.610299) (end -7.8486 5.610299) (layer "B.SilkS") (width 0.508) (fill none))
|
||||||
|
(fp_circle (center -2.794 4.064) (end -2.413 4.064) (layer "F.Fab") (width 0.508) (fill none))
|
||||||
|
(fp_line (start -7.5946 18.827898) (end -3.92204 18.827898) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start 7.5946 18.827898) (end 7.5946 7.527939) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start 7.5946 3.613299) (end -7.5946 3.613299) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start -7.5946 3.613299) (end -7.5946 4.662959) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start -7.4676 18.700898) (end 7.4676 18.700898) (layer "F.Fab") (width 0.0254))
|
||||||
|
(fp_line (start 7.4676 18.700898) (end 7.4676 3.740299) (layer "F.Fab") (width 0.0254))
|
||||||
|
(fp_line (start 7.4676 3.740299) (end -7.4676 3.740299) (layer "F.Fab") (width 0.0254))
|
||||||
|
(fp_line (start -7.4676 3.740299) (end -7.4676 18.700898) (layer "F.Fab") (width 0.0254))
|
||||||
|
(fp_line (start -1.75796 18.827898) (end 3.85796 18.827898) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start 6.02204 18.827898) (end 7.5946 18.827898) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start -7.5946 7.817639) (end -7.5946 18.827898) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start 7.5946 4.652659) (end 7.5946 3.613299) (layer "F.SilkS") (width 0.1524))
|
||||||
|
(fp_line (start -1.8367 18.954898) (end 3.9367 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 3.9367 18.954898) (end 3.9367 19.190798) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 3.9367 19.190798) (end 5.9433 19.190798) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 5.9433 19.190798) (end 5.9433 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 5.9433 18.954898) (end 7.7216 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.7216 18.954898) (end 7.7216 7.449199) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.7216 7.449199) (end 7.9705 7.449199) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.9705 7.449199) (end 7.9705 4.731399) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.9705 4.731399) (end 7.7216 4.731399) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.7216 4.731399) (end 7.7216 3.486299) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start 7.7216 3.486299) (end -7.7216 3.486299) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 3.486299) (end -7.7216 4.741699) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 4.741699) (end -7.9689 4.741699) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.9689 4.741699) (end -7.9689 7.738899) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.9689 7.738899) (end -7.7216 7.738899) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 7.738899) (end -7.7216 16.211399) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 16.211399) (end -7.970501 16.211399) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.970501 16.211399) (end -7.970501 18.929199) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.970501 18.929199) (end -6.319501 18.929199) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -6.319501 18.929199) (end -7.7216 18.929199) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 18.929199) (end -7.7216 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -7.7216 18.954898) (end -3.8433 18.954898) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -3.8433 18.954898) (end -3.8433 19.190798) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(fp_line (start -3.8433 19.190798) (end -1.8367 19.190798) (layer "F.CrtYd") (width 0.1524))
|
||||||
|
(pad "1" smd rect (at -2.899999 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "2" smd rect (at -1.800001 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "3" smd rect (at -0.700001 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "4" smd rect (at 0.399999 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "5" smd rect (at 1.5 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "6" smd rect (at 2.6 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "7" smd rect (at 3.7 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "8" smd rect (at 4.800001 5.610299) (size 0.8128 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "9" smd rect (at -2.84 18.365298) (size 1.4986 1.143) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "10" smd rect (at 4.94 18.365298) (size 1.4986 1.143) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "11" smd rect (at -7.245 6.240299) (size 0.9398 2.4892) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "15" smd rect (at 6.74 17.240299) (size 1.1684 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "13" smd rect (at -7.145001 17.570299) (size 1.143 2.2098) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "12" smd rect (at 7.145 6.090299) (size 1.143 2.2098) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
(pad "14" smd rect (at 6.74 8.240299) (size 1.1684 1.2446) (layers "F.Cu" "F.Paste" "F.Mask"))
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user