fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 283 lines 5.3 kB view raw
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}