Format disc Ipcas
Antecedents
Com que cada cop és més dificil aconseguir unitats de disquet de 3.5, Mayer ha optat per oferir als seus clients una actualització a memòria USB. Per aconseguir això han usat un emulador de unitat de disquet: Ipcas USB Floppy Emulator v3. El client substitueix la unitat de 3.5 per aquest emulador i ja pot treballar amb USB.
Emulador USB de disc de 3.5
Aquest emulador intenta simular exactament el HW d'una unitat de 3.5, i sembla que per motius de compatibilitat i/o simplificar el codi del firmware, el format de la imatge de disc l'han fet el màxim de similar possible al format físic d'un disc....
Format de la imatge
Tots els fitxers d'imatge de disc són de exactament 4250000 bytes independentment del disc que es simuli (180K,360K,720K,1440K,1220K,2880K). El fitxer internament està dividit en 170 segments de 25000 bytes cada un. Cada segment representa una de les possibles pista del disc de la següent manera:
| Offset | Bloc |
|---|---|
| 0 | Cara 0 Pista 0 |
| 25000 | Cara 0 Pista 1 |
| . . . |
. . . |
| 2100000 | Cara 0 Pista 84 |
| 2125000 | Cara 1 Pista 0 |
| 2150000 | Cara 1 Pista 1 |
| . . . |
. . . |
| 4225000 | Cara 1 Pista 84 |
Dins de cada segment hi han guardades les dades de la pista en forma d'un vector de bits. Cada bit representa si hi ha hagut un canvi de flux magnètic en el disc (1=canvi de flux, 0=no canvi).
La imatge, no conté enlloc informació sobre quin tipus de disc i/o format les dades representen. Per sort Mayer sempre utilitza discs de 3.5 de 1440K.
Codificació dels blocs/pistes
Per limitacions físiques i tecnològiques, no és pràctic guardar llargues seqüències de només 1 o només 0 en un medi magnètic. Per evitar aquest problema, el FDC (Floppy Disk Controller) codifica les dades abans d'enviar-les a l'unitat de disc, garantint un mínim de transcisions de 0->1 i de 1->0.
La codificació utilitzada és la MFM. Que funciona de la següent manera:
| Bit Dades | Codificaició MFM |
|---|---|
| 0 | 00 si BitDades anterior==1 10 Si BitDades anterior==0 |
| 1 | 01 |
Per exemple si codifiquem :
| Hex. | 0xAF | 0xF0 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Binari | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
| MFM | 01 | 01 | 01 | 01 | 00 | 01 | 00 | 01 | 00 | 10 | 10 | 10 | 01 | 01 | 01 | 01 |
Tot i això si s'intenta decodificar tota una pista del disc només tenint en compte aquesta informació, es fracasarà. Ja que el capçal no té prou precisió per poder modificar dades sense alterar les del voltant. Per solucionar aquest problema, el capçal sempre llegeix i/o escriu un bloc sencer de dades i entre el final d'un bloc i l'inici del següent, sempre hi ha un espai de separació per garantir que el capçal no alterarà les dades del boc següent.
Existeixen 2 tipus de blocs en el disc:
- Sector Identifier: Conté l'identificació del següent bloc (Nº de sector/Pista/Capçal)
- Data Block: Conté les dades guardades per l'usuari
Cada pista té el següent aspecte:
| Pista | ||||||||
|---|---|---|---|---|---|---|---|---|
| Start Gap | Sector Identifier | Identifier Gap | Data Block | Data Block Gap | Sector Identifier | .... | Data Block | Track Gap |
El motiu d'aquesta organització és per donar prou temps al capçal per conmutar de mode lectura a mode escriptura.(Per escriure un sector primer s'ha de buscar on està llegint els blocs Sector Identifier, quan es troba el capçal té temps de conmutar a mode escriptura abans que comenci el Data Block i així el pot sobreescriure sense problemes)
NOTA: Per culpa d'aquest sistema, no es pot decodificar una pista de principi a final i esperar dades coherents. Ja que no es garanteix que les dades que hi han en els Gap(s) siguin vàlides i/o que en número de bits entre 2 blocs sigui múltiple de 8. Per decodificar, s'ha de fer bloc per bloc.
Codificació Sector Index
| Sync Pattern | Data | CRC | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0xA1* | 0xA1* | 0xA1* | 0xFE | Cyl | Head | Sect | 0x02 | CRC_MSB | CRC_LSB |
| CRC-DATA | |||||||||||||||||||||
| Camp | Descripció |
|---|---|
| Cyl | Pista a la que pertany el sector (0x00...0x4f)->Pista0...Pista79 |
| Head | Cara on està guardat el sector 0x00 -> cara 0 0x01 -> cara 1 |
| Sect | Nº de sector de 1-18 (0x01...0x12) |
els bytes 0xA1* del Sync Pattern es codifiquen d'una manera especial per evitar que es pugui detectar el Sync Pattern al mig de les dades d'usuari:
| Codificació 0xA1 | ||||||||
|---|---|---|---|---|---|---|---|---|
| Binari | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| MFM | 01 | 00 | 10 | 10 | 10 | 01 | 00 | 1 |
| Sync Pattern | 01 | 00 | 10 | 00 | 10 | 01 | 00 | 1 |
El CRC es calcula a partir de tots els bytes en CRC_DATA, usant el polinomi: X^16+X^12+X^5+1 (0x1021). i inicialitzant el shift register a 0xffff. Ex:
UInt16 calc_crc(UInt16 seed,byte[] buff) {
bool carry;
for(int i=0;i<buff.Length;i++) {
seed^=buff[i]<<8;
for(int j=0;j<8;j++) {
carry=(seed & 0x80)>0;
seed<<=1;
if(carry) {
seed^=0x1021;
}
}
}
return(seed);
}
Per més informació respecte al calcul de CRCs es pot consultar la entrada de la Wikipedia Cyclic_redundancy_check
Codificació Data Block
| Sync Pattern | Data | CRC | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0xA1* | 0xA1* | 0xA1* | 0xFB | USER DATA (512Bytes) | CRC_MSB | CRC_LSB |
| CRC-DATA | ||||||||||||||||||
Com es pot veure, es pot identificar si el bloc actual és de dades o un Sector Identifier amb el primer byte després del Sync Pattern.
El calcul del CRC d'aquest bloc es fa de la mateixa manera que en el Sector Identifier.
Més informació
Per més informació es pot consultar les especificacions dels discs de 3.5 d'alta densitat en la documentació de l'estandard corresponent:
Ecma-125
.