OpenCores
URL https://opencores.org/ocsvn/floppyif/floppyif/trunk

Subversion Repositories floppyif

[/] [floppyif/] [trunk/] [doc/] [f.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jhallen
/* Floppy drive data separator and CRC checker simulation in C.
2
 
3
   This C program performs clock/data separation, address mark
4
   recognition and CRC checking of logic analyzer trace of floppy
5
   drive read data line.
6
 
7
   Compile: cc -o f f.c
8
   Run: ./f <example_data.txt >output.txt
9
*/
10
 
11
/* x^16 + x^12 + x^5 + 1 CRC */
12
/* Append remainder (contents of fcs) to message: MSB of remainder goes first. */
13
/* Next time through, remainder will be zero. */
14
/* fcs is typically initialized to 0xFFFF */
15
 
16
/* Update FCS after one new byte (note that the MSB is taken first even though the LSB is transmitted first) */
17
unsigned short serial_crc(unsigned short fcs,unsigned char c)
18
  {
19
  int i;
20
  for(i=0;i!=8;++i)
21
    {
22
    fcs = ((fcs&0x8000)>>15)^(c>>7) ? (fcs<<1)^0x1021 : (fcs<<1);
23
 
24
    c = (c<<1);
25
    }
26
  return fcs;
27
  }
28
 
29
/* No. samples per bit cell (two bit cells store one data bit in MFM)
30
 * times 256 */
31
 
32
#define SAMPLE_RATE 5 /* MHz */
33
 
34
#define TIME (SAMPLE_RATE*256)
35
/* Timer */
36
int count;
37
 
38
/* Shift register for data and clock bits */
39
int shift_reg[16];
40
int shift_count;
41
 
42
int capture;
43
int lead;
44
 
45
int found=0;
46
 
47
/* Call this for each time step: rd is read data line */
48
int stepno;
49
 
50
unsigned short fcs;
51
 
52
step(rd)
53
  {
54
  ++stepno;
55
 
56
  /* printf("%d\n",rd); */
57
 
58
  /* Leading edge detector */
59
  if(rd==0 && lead==1)
60
    {
61
    /* Move counter toward TIME/2 */
62
 
63
    /* Adjust count */
64
    if(count>TIME/2)
65
      /* We're early: retard */
66
      {
67
      /* printf("diff=%d\n",count-TIME/2); */
68
      count -= (count-TIME/2)/2;
69
      }
70
    else if(count<TIME/2)
71
      {
72
      /* printf("diff=%d\n",TIME/2-count); */
73
      /* We're late: advance */
74
      count += (TIME/2-count)/2;
75
      }
76
    else
77
      {
78
      /* printf("no diff\n"); */
79
      }
80
 
81
    capture=1;
82
    }
83
  lead=rd;
84
 
85
  /* Timer */
86
  count = count + 256;
87
  if(count>=TIME)
88
    {
89
    int x;
90
    int clock;
91
    int data;
92
    count -= TIME;
93
 
94
    for(x=15;x!=0;--x)
95
      shift_reg[x] = shift_reg[x-1];
96
    shift_reg[0] = capture;
97
 
98
    capture = 0;
99
 
100
    shift_count = shift_count + 1;
101
 
102
    clock = (shift_reg[15]<<7) | (shift_reg[13]<<6) | (shift_reg[11]<<5) | (shift_reg[9]<<4) |
103
            (shift_reg[7]<<3) | (shift_reg[5]<<2) | (shift_reg[3]<<1) | (shift_reg[1]);
104
 
105
    data = (shift_reg[14]<<7) | (shift_reg[12]<<6) | (shift_reg[10]<<5) | (shift_reg[8]<<4) |
106
           (shift_reg[6]<<3) | (shift_reg[4]<<2) | (shift_reg[2]<<1) | (shift_reg[0]);
107
 
108
    /* Check for address mark */
109
    if(clock==0x0A && data==0xA1)
110
      {
111
      printf("Address mark A1 found\n");
112
      shift_count=16;
113
      if(!found)
114
        {
115
        /* Initialize CRC */
116
        /* Ignore next few bytes to prevent successive address marks
117
           from restarting us again */
118
        found=4;
119
        fcs=0xFFFF;
120
        }
121
      }
122
 
123
    if(shift_count==16)
124
      {
125
      if(found)
126
        --found;
127
      fcs = serial_crc(fcs,data);
128
      printf("clock=%2.2x data=%2.2x crc=%x\n",clock,data,fcs);
129
 
130
      shift_count=0;
131
      }
132
    }
133
  }
134
 
135
main()
136
  {
137
  char buf[1024];
138
  while(gets(buf))
139
    step(buf[0]=='1');
140
  }

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.