This is the continuation of Measuring Floppy Drive rotation speed. We need a better machine program to measure the exact duration between two index hole detections. The plan is, that we first wait, until the index is detection, then start to count until the index is detected again.

Just to verify, we should have a short look at the floppy controller spec. With “IN 54H”, we read the status register. The floppy controller in the Alphatronic is “SAB 1791 02-C”. A search on datasheetarchive reveals this as “Floppy-Disk-Controller, SS” and “40-DIC/DIP” casing. After a search for the terms “floppy-disk-controller” it turns out, that this chip has been produced by Siemens - and there is the actual data sheet. It says “Compatible with Industry Standard 179X”, so you could also use any other datasheet for the 179X family of floppy disk controllers.

The status register has 8 bits. The second bit (bit “S1”) is the index bit and described as “When set, indicates index mark detected from drive. This bit is an inverted copy of the #IP input”. We use a bit mask of “0x40” to check whether the index bit is set or not (via ANA B - A = A & B). Since the status register has this layout:

                      (Bits)
+-----+-----+-----+-----+-----+-----+-----+-----+
|  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
+-----+-----+-----+-----+-----+-----+-----+-----+
| S7  | S6  | S5  | S4  | S3  | S2  | S1  | S0  |
+-----+-----+-----+-----+-----+-----+-----+-----+

I would now have expected, that we need the bitmask “0x02”… In the datasheet, there is mentioned the feature “inverted data bus”. The data of the status register read is transmitted through the data bus. If it is inverted, then yes, it’s actually bit 6 we are interested and that is bitmask “0x40”.

Ok, so far so good. Let’s just try it. I’ll start at a different origin for ease of counting.

                                       ORG     FF00H
                                       PUBLIC  READ_INDEX_DURATION
FF00'  3E D4      READ_INDEX_DURATION: MVI     A,D4H    ;FORCE-INTERRUPT command with IP (index pulse)
FF02'  D3 50                           OUT     50H      ;execute command
FF04'  06 40                           MVI     B,40H    ;Mask for index detected flag in status register
FF06'  11 0000                         LXI     D,0      ;init counter in D
FF09'  DB 50                           IN      50H      ;reading the command register?? apparently clearing the IRQ flag
FF0B'  DB 54                   LOOP1:  IN      54H      ;reading status register into A
FF0D'  A0                              ANA     B        ;check if index is set
FF0E'  CA 0BFF'                        JZ      LOOP1    ;if no index yet, busy wait...
FF11'  DB 50                           IN      50H      ;clearing the INDEX flag for next index detection
FF13'  13                      LOOP2:  INX     D        ;counting now...
FF14'  DB 54                           IN      54H      ;reading status register into A
FF16'  A0                              ANA     B        ;check if index is set
FF17'  CA 13FF'                        JZ      LOOP2    ;jump back, if no index and keep counting
FF1A'  73                              MOV     M,E      ;copy counter (low Byte) to memory at [H]
FF1B'  23                              INX     H        ;
FF1C'  72                              MOV     M,D      ;copy counter (high Byte) to memory at [H]
FF1D'  C9                              RET

That should give us the counter of exactly one disk rotation - that is LOOP2. We need 5 (INX) + 10 (IN) + 4 (ANA) + 10 (JZ) = 29 CPU cycles. We have a 16 bit counter in register D. Will it overflow? Let’s assume the rotation speed is at the standard 300 rpm, that means one rotation takes 0.2 seconds. At 3 MHz, these are 600,000 CPU cycles. Divided by 29 we get 20,690 which is smaller than 64k - good. No problem here.

Now the BASIC program. I keep it a bit simpler, no fancy graphics output of the histogram. But it’s faster to type in, because it’s shorter.

100 '************** DRIVEROT
110 CLEAR , &HFF00
120 DEFINT D
130 GOSUB 500
140 PRINT"In the last used drive a floppy has to be inserted!"
150 INPUT"How many measurements should be taken"; COUNT
160 DIM DAT%(COUNT)
170 FOR D=0 TO COUNT-1
175     PRINT"  Start measurement ";D
180     CALL RID(LOOPS%)
190     DAT%(D)=LOOPS%
195     PRINT"    result:";D;"->";DAT%(D)
200 NEXT
210 PRINT"Data ready"
220 MIN=DAT(0) :MAX=MIN :SUM=0
230 FOR D=0 TO COUNT-1
240     IF DAT(D)<MIN THEN MIN=DAT(D)
250     IF DAT(D)>MAX THEN MAX=DAT(D)
260     SUM=SUM+DAT(D)
270 NEXT
280 MEAN=SUM/COUNT
290 LPS=103448! 'loops per second: 3 MHz/29 cycles - dur. of one loop
300 RPM=INT(60*LPS/MEAN+.5)
310 DIF=MAX-MIN
320 PRINT"  Minimum:";MIN/LPS;"s"
330 PRINT"  Maximum:";MAX/LPS;"s"
340 PRINT"     Mean:";MEAN/LPS;"s"
350 PRINT"Rotations:";RPM;"rpm"
360 PRINT" Accuracy:";DIF*1000/LPS;"ms"
370 END
500 ' Machine program RID (=read_index_duration)
510 I=&HFF00
520 RID=&HFF00
530    READ D$
540    D=VAL("&H"+D$)
550    IF D>255 THEN RETURN
560    POKE I,D
570    I=I+1
580 GOTO 530
590 DATA 3E,D4,D3,50,06,40,11,00,00,DB,50,DB,54
600 DATA A0,CA,0B,FF,DB,50,13,DB,54,A0,CA,13,FF
610 DATA 73,23,72,C9,E0F

Type this program in as usual (NEW, line by line, LIST) and store it to floppy (SAVE"DRIVEROT").

Then RUN:

I measured the rotation 100 times, the numbers are consistent. However, I’m still at 388rpm, which is too high for a real floppy drive. I’m definitely missing here something. The floppy drive is working, so I don’t think, the numbers are correct.