-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathibm_disc_format.c
148 lines (128 loc) · 2.86 KB
/
ibm_disc_format.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "ibm_disc_format.h"
/* These CRC routines inspired by:
* https://github.com/mamedev/mame/blob/master/src/devices/machine/i8271.cpp
* https://people.cs.umu.se/isak/snippets/crc-16.c
*/
/* This is the CCITT CRC 16, using the polynomial x^16 + x^12 + x^5 + 1. */
/* This has been checked against a freshly formatted standard track 0.
* CRC for track 0 sector 0 ID header is 0xF1 0xD3.
* CRC for freshly formatted sector (full of 0xE5) is 0xA4 0x0C.
*/
uint16_t
ibm_disc_format_crc_init(int is_mfm) {
if (is_mfm) {
/* MFM starts with 3x 0xA1 sync bytes added. */
return 0xCDB4;
} else {
return 0xFFFF;
}
}
uint16_t
ibm_disc_format_crc_add_byte(uint16_t crc, uint8_t byte) {
uint32_t i;
for (i = 0; i < 8; ++i) {
int bit = (byte & 0x80);
int bit_test = ((crc & 0x8000) ^ (bit << 8));
crc <<= 1;
if (bit_test) {
crc ^= 0x1021;
}
byte <<= 1;
}
return crc;
}
uint32_t
ibm_disc_format_fm_to_2us_pulses(uint8_t clocks, uint8_t data) {
uint32_t i;
uint32_t ret = 0;
for (i = 0; i < 8; ++i) {
ret <<= 4;
if (clocks & 0x80) {
ret |= 0x04;
}
if (data & 0x80) {
ret |= 0x01;
}
clocks <<= 1;
data <<= 1;
}
return ret;
}
void
ibm_disc_format_2us_pulses_to_fm(uint8_t* p_clocks,
uint8_t* p_data,
int* p_is_iffy_pulse,
uint32_t pulses) {
uint32_t i;
uint8_t clocks = 0;
uint8_t data = 0;
int is_iffy_pulse = 0;
/* This downsamples 2us resolution pulses into 4us FM pulses, splitting clocks
* from data.
*/
for (i = 0; i < 8; ++i) {
clocks <<= 1;
data <<= 1;
if (pulses & 0x80000000) {
clocks |= 1;
}
if (pulses & 0x20000000) {
data |= 1;
}
if (pulses & 0x50000000) {
is_iffy_pulse = 1;
}
pulses <<= 4;
}
*p_clocks = clocks;
*p_data = data;
*p_is_iffy_pulse = is_iffy_pulse;
}
uint16_t
ibm_disc_format_mfm_to_2us_pulses(int* p_last_mfm_bit, uint8_t byte) {
uint16_t pulses = 0;
uint32_t i;
int last_bit = *p_last_mfm_bit;
for (i = 0; i < 8; ++i) {
int bit = !!(byte & 0x80);
pulses <<= 2;
byte <<= 1;
if (bit) {
pulses |= 0x01;
} else if (!last_bit) {
pulses |= 0x02;
}
last_bit = bit;
}
*p_last_mfm_bit = last_bit;
return pulses;
}
uint8_t
ibm_disc_format_2us_pulses_to_mfm(uint16_t pulses) {
uint32_t i;
uint8_t byte = 0;
for (i = 0; i < 8; ++i) {
byte <<= 1;
if ((pulses & 0xC000) == 0x4000) {
byte |= 1;
}
pulses <<= 2;
}
return byte;
}
int
ibm_disc_format_check_pulse(float pulse_us, int is_mfm) {
if (pulse_us < 3.5) {
return 0;
}
if (pulse_us > 8.5) {
return 0;
}
if (is_mfm && (pulse_us > 5.5) && (pulse_us < 6.5)) {
return 1;
}
if ((pulse_us > 4.5) && (pulse_us < 7.5)) {
return 0;
}
return 1;
}