fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/pfi/decode-bits.c *
7 * Created: 2012-01-21 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-2019 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "pfi.h"
29#include "decode-bits.h"
30
31
32int pfi_dec_init (pfi_dec_t *buf, unsigned long max)
33{
34
35 buf->buf = NULL;
36 buf->weak = NULL;
37 buf->clk = NULL;
38
39 buf->cnt = 0;
40 buf->max = 0;
41
42 buf->index = 0;
43
44 if (max > 0) {
45 if (pfi_dec_alloc_bits (buf, max)) {
46 pfi_dec_free (buf);
47 return (1);
48 }
49 }
50
51 return (0);
52}
53
54void pfi_dec_free (pfi_dec_t *buf)
55{
56 free (buf->clk);
57 free (buf->weak);
58 free (buf->buf);
59}
60
61int pfi_dec_alloc_bits (pfi_dec_t *buf, unsigned long cnt)
62{
63 unsigned long max;
64 void *tmp;
65
66 if ((buf->cnt + cnt) <= buf->max) {
67 return (0);
68 }
69
70 max = (buf->max < 4096) ? 4096 : buf->max;
71
72 while ((buf->cnt + cnt) > max) {
73 max *= 2;
74 }
75
76 if ((tmp = realloc (buf->buf, (max + 7) / 8)) == NULL) {
77 return (1);
78 }
79
80 buf->buf = tmp;
81
82 if ((tmp = realloc (buf->weak, (max + 7) / 8)) == NULL) {
83 return (1);
84 }
85
86 buf->weak = tmp;
87
88 if ((tmp = realloc (buf->clk, sizeof (unsigned long) * max)) == NULL) {
89 return (1);
90 }
91
92 buf->clk = tmp;
93
94 buf->max = max;
95
96 return (0);
97}
98
99int pfi_dec_add_bit (pfi_dec_t *buf, int val, int weak, unsigned long clk)
100{
101 unsigned long i;
102 unsigned char m;
103
104 if (pfi_dec_alloc_bits (buf, 1)) {
105 return (1);
106 }
107
108 i = buf->cnt / 8;
109 m = 0x80 >> (buf->cnt & 7);
110
111 if (val) {
112 buf->buf[i] |= m;
113 }
114 else {
115 buf->buf[i] &= ~m;
116 }
117
118 if (weak) {
119 buf->weak[i] |= m;
120 }
121 else {
122 buf->weak[i] &= ~m;
123 }
124
125 buf->clk[buf->cnt] = clk;
126
127 buf->cnt += 1;
128
129 return (0);
130}
131
132void pfi_dec_clock_average (pfi_dec_t *bit)
133{
134 unsigned long i;
135 unsigned long v[5];
136
137 v[0] = bit->clk[0];
138 v[1] = bit->clk[0];
139 v[2] = bit->clk[0];
140 v[3] = bit->clk[0];
141 v[4] = (bit->cnt >= 1) ? bit->clk[1] : bit->clk[0];
142
143 for (i = 0; i < bit->cnt; i++) {
144 v[0] = v[1];
145 v[1] = v[2];
146 v[2] = v[3];
147 v[3] = v[4];
148 v[4] = ((i + 2) < bit->cnt) ? bit->clk[i + 2] : v[4];
149
150 bit->clk[i] = (v[0] + v[1] + v[2] + v[3] + v[4] + 2) / 5;
151 }
152}
153
154void pfi_dec_clock_median (pfi_dec_t *bit)
155{
156 unsigned long i, j, k;
157 unsigned long v[3], t[3];
158
159 v[0] = bit->clk[0];
160 v[1] = bit->clk[0];
161 v[2] = bit->clk[0];
162
163 for (i = 0; i < bit->cnt; i++) {
164 v[0] = v[1];
165 v[1] = v[2];
166 v[2] = ((i + 1) < bit->cnt) ? bit->clk[i + 1] : v[2];
167
168 for (j = 0; j < 3; j++) {
169 k = j;
170
171 while ((k > 0) && (v[j] < t[k - 1])) {
172 t[k] = t[k - 1];
173 k -= 1;
174 }
175
176 t[k] = v[j];
177 }
178
179 bit->clk[i] = t[1];
180 }
181}
182
183int pfi_trk_decode_bits (pfi_trk_t *trk, pfi_dec_t *dst, unsigned long rate, unsigned rev)
184{
185 unsigned idx;
186 uint32_t val, ofs;
187 unsigned char weak;
188 double cell, cell0, pulse;
189 double adjust1, adjust2, limit1, limit2, phase;
190
191 pfi_trk_rewind (trk);
192
193 if (rev < 1) {
194 rev = 1;
195 }
196
197 cell0 = (double) trk->clock / rate;
198
199 ofs = 0;
200 idx = 0;
201
202 cell = cell0;
203 pulse = 0.0;
204
205 adjust1 = 0.9995;
206 adjust2 = 1.0005;
207
208 limit1 = 0.9 * cell0;
209 limit2 = 1.1 * cell0;
210
211 phase = 0.5;
212
213#if 0
214 phase = -0.25;
215 adjust1 *= adjust1;
216 adjust2 *= adjust2;
217 limit1 = 0.9 * cell0;
218 limit2 = 1.1 * cell0;
219#endif
220
221 weak = 0;
222
223 while (pfi_trk_get_pulse (trk, &val, &ofs) == 0) {
224 if ((val == 0) || (ofs < val)) {
225 idx += 1;
226
227 if (idx == rev) {
228 dst->cnt = 0;
229 }
230 else if (idx == (rev + 1)) {
231 dst->index = dst->cnt;
232 }
233 else if (idx > (rev + 1)) {
234 break;
235 }
236 }
237
238 if (val == 0) {
239 continue;
240 }
241
242 pulse += (double) val / cell;
243
244 while (pulse > 1.5) {
245 if (pulse < 1.6) {
246 weak = 3;
247 }
248
249 pfi_dec_add_bit (dst, 0, weak & 1, trk->clock / cell);
250
251 weak >>= 1;
252 pulse -= 1.0;
253 }
254
255 if (pulse > 1.4) {
256 weak = 3;
257 }
258
259 pfi_dec_add_bit (dst, 1, weak & 1, trk->clock / cell);
260
261 weak >>= 1;
262 pulse -= 1.0;
263
264 if (pulse < 0.0) {
265 cell *= adjust1;
266
267 if (cell < limit1) {
268 cell = limit1;
269 }
270 }
271 else if (pulse > 0.0) {
272 cell *= adjust2;
273
274 if (cell > limit2) {
275 cell = limit2;
276 }
277 }
278
279 pulse *= phase;
280 }
281
282 return (0);
283}