/*------------------------------------------------------ DISK II Emulator Farmware (1 of 2) for ATMEGA328P original: 2009.11.16 by Koichi Nishida version 1.3 2011. 1.28 by Koichi Nishida ------------------------------------------------------*/ /* if the crystal on your SDISK II is 25 MHz, I recommend you to replace it with 27 MHz, or ask Nishida Radio. see also sub.S */ /* hardware information: use ATMEGA328P AVR. connect 27MHz (overclock...) crystal to the AVR. supply 3.3V power. fuse setting : LOW 11011110 connection: D0: DO (SD card) D1: CS (SD card) D2: WRITE REQUEST (APPLE II disk IF, pull up with 10K ohm) D3: EJECT SWITCH (LOW if SD card is inserted) D4: DI (SD card) D5: CLK (SD card) D6-D7: NC B0: PHASE-0 (APPLE II disk IF) B1: PHASE-1 (APPLE II disk IF) B2: PHASE-2 (APPLE II disk IF) B3: PHASE-3 (APPLE II disk IF) B4: LED (through 330 ohm) B5: NC B6-B7: connect to the crystal C0: DRIVE ENABLE (APPLE II disk IF) C1: READ PULSE (APPLE II disk IF through 74HC125 3state) C2: WRITE (APPLE II disk IF) C3: WRITE PROTECT (APPLE II disk IF through 74HC125 3state) C4-C6: NC Note that the enable input of the 3state buffer 74HC125, should be connected with DRIVE ENABLE. */ /* This is a part of the firmware for DISK II emulator by Nishida Radio. Copyright (C) 2011 Koichi NISHIDA email to Koichi NISHIDA: tulip-house@msf.biglobe.ne.jp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #define WAIT 1 #define BUF_NUM 5 #define FAT_DSK_ELEMS 18 #define FAT_NIC_ELEMS 35 #define nop() __asm__ __volatile__ ("nop") // C prototypes // cancel read void cancelRead(void); // write a byte data to the SD card void writeByteSlow(unsigned char c); void writeByteFast(unsigned char c); // read data from the SD card unsigned char readByteSlow(void); unsigned char readByteFast(void); // wait until finish a command void waitFinish(void); // issue SD card command slowly without getting response void cmd_(unsigned char cmd, unsigned long adr); // issue SD card command fast and wait normal response void cmdFast(unsigned char cmd, unsigned long adr); // get command response slowly from the SD card unsigned char getRespSlow(void); // get command response fast from the SD card unsigned char getRespFast(void); // issue command 17 and get ready for reading void cmd17Fast(unsigned long adr); // find a file extension int findExt(char *str, unsigned char *protect, unsigned char *name); // prepare the FAT table on memory void prepareFat(int i, unsigned short *fat, unsigned short len, unsigned char fatNum, unsigned char fatElemNum); // memory copy void memcp(unsigned char *dst, unsigned char *src, const unsigned short len); // duplicate FAT for FAT16 void duplicateFat(void); // write to the SD cart one by one void writeSD(unsigned long adr, unsigned char *data, unsigned short len); // create a NIC image file int createNic(unsigned char *name); // translate a NIC image into a DSK image void nic2Dsk(void); // translate a DSK image into a NIC image void dsk2Nic(void); // initialization called from check_eject void init(void); // called when the SD card is inserted or removed void check_eject(void); // write data back to a NIC image void writeBack(void); void writeBackSub(void); void writeBackSub2(unsigned char bn, unsigned char sc, unsigned char track); // buffer clear void buffClear(void); // assembler functions void wait5(unsigned short time); // SD card information unsigned long bpbAddr, rootAddr; unsigned long fatAddr; // the beginning of FAT unsigned short fileFatTop; unsigned char sectorsPerCluster, sectorsPerCluster2; // sectors per cluster unsigned short sectorsPerFat; unsigned long userAddr; // the beginning of user data // unsigned short fatDsk[FAT_DSK_ELEMS];// use writeData instead unsigned short fatNic[FAT_NIC_ELEMS]; unsigned char prevFatNumDsk, prevFatNumNic; unsigned short nicDir, dskDir; // DISK II status unsigned char ph_track; // 0 - 139 unsigned char sector; // 0 - 15 unsigned short bitbyte; // 0 - (8*512-1) unsigned char prepare; unsigned char readPulse; unsigned char inited; unsigned char magState; unsigned char protect; unsigned char formatting; const unsigned char volume = 0xfe; // write data buffer unsigned char writeData[BUF_NUM][350]; unsigned char sectors[BUF_NUM], tracks[BUF_NUM]; unsigned char buffNum; unsigned char *writePtr; // a table for head stepper moter movement PROGMEM prog_uchar stepper_table[4] = {0x0f,0xed,0x03,0x21}; // encode / decode table for a nib image PROGMEM prog_uchar encTable[] = { 0x96,0x97,0x9A,0x9B,0x9D,0x9E,0x9F,0xA6, 0xA7,0xAB,0xAC,0xAD,0xAE,0xAF,0xB2,0xB3, 0xB4,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBC, 0xBD,0xBE,0xBF,0xCB,0xCD,0xCE,0xCF,0xD3, 0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE, 0xDF,0xE5,0xE6,0xE7,0xE9,0xEA,0xEB,0xEC, 0xED,0xEE,0xEF,0xF2,0xF3,0xF4,0xF5,0xF6, 0xF7,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF }; PROGMEM prog_uchar decTable[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x03,0x00,0x04,0x05,0x06, 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x00,0x00,0x00,0x09,0x0a,0x0b,0x0c,0x0d, 0x00,0x00,0x0e,0x0f,0x10,0x11,0x12,0x13,0x00,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x1c,0x1d,0x1e, 0x00,0x00,0x00,0x1f,0x00,0x00,0x20,0x21,0x00,0x22,0x23,0x24,0x25,0x26,0x27,0x28, 0x00,0x00,0x00,0x00,0x00,0x29,0x2a,0x2b,0x00,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32, 0x00,0x00,0x33,0x34,0x35,0x36,0x37,0x38,0x00,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f }; // a table for translating logical sectors into physical sectors PROGMEM prog_uchar physicalSector[] = { 0,13,11,9,7,5,3,1,14,12,10,8,6,4,2,15}; // for bit flip PROGMEM prog_uchar FlipBit[] = { 0, 2, 1, 3 }; PROGMEM prog_uchar FlipBit1[] = { 0, 2, 1, 3 }; PROGMEM prog_uchar FlipBit2[] = { 0, 8, 4, 12 }; PROGMEM prog_uchar FlipBit3[] = { 0, 32, 16, 48 }; // buffer clear void buffClear(void) { unsigned char i; unsigned short j; for (i=0; i>= 1) { if (c&d) { PORTD = 0b00010000; wait5(WAIT); PORTD = 0b00110000; } else { PORTD = 0b00000000; wait5(WAIT); PORTD = 0b00100000; } wait5(WAIT); } PORTD = 0b00000000; } void writeByteFast(unsigned char c) { unsigned char d; for (d = 0b10000000; d; d >>= 1) { if (c&d) { PORTD = 0b00010000; PORTD = 0b00110000; } else { PORTD = 0b00000000; PORTD = 0b00100000; } } PORTD = 0b00000000; } // read data from the SD card unsigned char readByteSlow(void) { unsigned char c = 0; volatile unsigned char i; PORTD = 0b00010000; wait5(WAIT); for (i = 0; i != 8; i++) { PORTD = 0b00110000; wait5(WAIT); c = ((c<<1) | (PIND&1)); PORTD = 0b00010000; wait5(WAIT); } return c; } unsigned char readByteFast(void) { unsigned char c = 0; volatile unsigned char i; PORTD = 0b00010000; for (i = 0; i != 8; i++) { PORTD = 0b00110000; c = ((c<<1) | (PIND&1)); PORTD = 0b00010000; } return c; } // wait until data is written to the SD card void waitFinish(void) { unsigned char ch; do { ch = readByteFast(); if (bit_is_set(PIND,3)) return; } while (ch != 0xff); } // issue a SD card command slowly without getting response void cmd_(unsigned char cmd, unsigned long adr) { writeByteSlow(0xff); writeByteSlow(0x40+cmd); writeByteSlow(adr>>24); writeByteSlow((adr>>16)&0xff); writeByteSlow((adr>>8)&0xff); writeByteSlow(adr&0xff); writeByteSlow(0x95); writeByteSlow(0xff); } // issue a SD card command and wait normal response void cmdFast(unsigned char cmd, unsigned long adr) { unsigned char res; do { writeByteFast(0xff); writeByteFast(0x40+cmd); writeByteFast(adr>>24); writeByteFast((adr>>16)&0xff); writeByteFast((adr>>8)&0xff); writeByteFast(adr&0xff); writeByteFast(0x95); writeByteFast(0xff); } while (((res=getRespFast())!=0) && (res!=0xff)); } // get a command response slowly from the SD card unsigned char getRespSlow(void) { unsigned char ch; do { ch = readByteSlow(); if (bit_is_set(PIND,3)) return 0xff; } while ((ch&0x80) != 0); return ch; } // get a command response fast from the SD card unsigned char getRespFast(void) { unsigned char ch; do { ch = readByteFast(); if (bit_is_set(PIND,3)) return 0xff; } while ((ch&0x80) != 0); return ch; } // issue command 17 and get ready for reading void cmd17Fast(unsigned long adr) { unsigned char ch; cmdFast(17, adr); do { ch = readByteFast(); if (bit_is_set(PIND,3)) return; } while (ch != 0xfe); } // find a file extension int findExt(char *str, unsigned char *protect, unsigned char *name) { short i; unsigned max_file = 512; unsigned short max_time = 0, max_date = 0; // find NIC extension for (i=0; i!=512; i++) { unsigned char ext[3], d; unsigned char time[2], date[2]; if (bit_is_set(PIND,3)) return 512; // check first char cmdFast(16, 1); cmd17Fast(rootAddr+i*32); d = readByteFast(); readByteFast(); readByteFast(); // discard CRC bytes if ((d==0x00)||(d==0x05)||(d==0x2e)||(d==0xe5)) continue; if (!(((d>='A')&&(d<='Z'))||((d>='0')&&(d<='9')))) continue; cmd17Fast(rootAddr+i*32+11); d = readByteFast(); readByteFast(); readByteFast(); // discard CRC bytes if (d&0x1e) continue; if (d==0xf) continue; // check extension cmdFast(16, 4); cmd17Fast(rootAddr+i*32+8); ext[0] = readByteFast(); ext[1] = readByteFast(); ext[2] = readByteFast(); if (protect) *protect = ((readByteFast()&1)<<3); else readByteFast(); readByteFast(); readByteFast(); // discard CRC bytes // check time stamp cmdFast(16, 4); cmd17Fast(rootAddr+i*32+22); time[0] = readByteFast(); time[1] = readByteFast(); date[0] = readByteFast(); date[1] = readByteFast(); readByteFast(); readByteFast(); // discard CRC bytes if ((ext[0]==str[0])&&(ext[1]==str[1])&&(ext[2]==str[2])) { unsigned short tm = *(unsigned short *)time; unsigned short dt = *(unsigned short *)date; if ((dt>max_date)||((dt==max_date)&&(tm>=max_time))) { max_time = tm; max_date = dt; max_file = i; } } } if ((max_file != 512) && (name != 0)) { unsigned char j; cmdFast(16, 8); cmd17Fast(rootAddr+max_file*32); for (j=0; j<8; j++) name[j] = readByteFast(); readByteFast(); readByteFast(); } return max_file; // if 512 then not found... } // prepare a FAT table on memory void prepareFat(int i, unsigned short *fat, unsigned short len, unsigned char fatNum, unsigned char fatElemNum) { unsigned short ft; unsigned char fn; if (bit_is_set(PIND,3)) return; cmdFast(16, (unsigned long)2); cmd17Fast(rootAddr+i*32+26); ft = readByteFast(); ft += (unsigned short)readByteFast()*0x100; readByteFast(); readByteFast(); // discard CRC bytes if (0==fatNum) fat[0] = ft; for (i=0; i0xfff6)||(fn>fatNum)) break; } cmdFast(16, (unsigned long)512); } // memory copy void memcp(unsigned char *dst, unsigned char *src, unsigned short len) { unsigned short i; for (i=0; i>sectorsPerCluster2)); ft++) { cmdFast(16, 2); cmd17Fast(fatAddr+ft*2); d = readByteFast(); d += (unsigned short)readByteFast()*0x100; readByteFast(); readByteFast(); // discard CRC bytes if (d==0) { clusterNum++; writeSD(adr, (unsigned char *)&ft, 2); adr = fatAddr+ft*2; } } writeSD(adr, last, 2); duplicateFat(); return 1; } // translate a DSK image into a NIC image void dsk2Nic(void) { unsigned char trk, logic_sector; unsigned short i; unsigned char *dst = (&writeData[0][0]+512); unsigned short *fatDsk = (unsigned short *)(&writeData[0][0]+1024); PORTB |= 0b00010000; prevFatNumNic = prevFatNumDsk = 0xff; for (i=0; i<0x16; i++) dst[i]=0xff; // sync header dst[0x16]=0x03; dst[0x17]=0xfc; dst[0x18]=0xff; dst[0x19]=0x3f; dst[0x1a]=0xcf; dst[0x1b]=0xf3; dst[0x1c]=0xfc; dst[0x1d]=0xff; dst[0x1e]=0x3f; dst[0x1f]=0xcf; dst[0x20]=0xf3; dst[0x21]=0xfc; // address header dst[0x22]=0xd5; dst[0x23]=0xaa; dst[0x24]=0x96; dst[0x2d]=0xde; dst[0x2e]=0xaa; dst[0x2f]=0xeb; // sync header for (i=0x30; i<0x35; i++) dst[i]=0xff; // data dst[0x35]=0xd5; dst[0x36]=0xaa; dst[0x37]=0xad; dst[0x18f]= 0xde; dst[0x190]=0xaa; dst[0x191]=0xeb; for (i=0x192; i<0x1a0; i++) dst[i]=0xff; for (i=0x1a0; i<0x200; i++) dst[i]=0x00; cmdFast(16, (unsigned long)512); for (trk = 0; trk < 35; trk++) { PORTB ^= 0b00010000; for (logic_sector = 0; logic_sector < 16; logic_sector++) { unsigned char *src; unsigned short ph_sector = (unsigned short)pgm_read_byte_near(physicalSector+logic_sector); if (bit_is_set(PIND,3)) return; if ((logic_sector&1)==0) { unsigned short long_sector = (unsigned short)trk*8+(logic_sector/2); unsigned short long_cluster = long_sector>>sectorsPerCluster2; unsigned char fatNum = long_cluster/FAT_DSK_ELEMS; unsigned short ft; if (fatNum != prevFatNumDsk) { prevFatNumDsk = fatNum; prepareFat(dskDir, fatDsk, (280+sectorsPerCluster-1)>>sectorsPerCluster2, fatNum, FAT_DSK_ELEMS); } ft = fatDsk[long_cluster%FAT_DSK_ELEMS]; cmd17Fast((unsigned long)userAddr+(((unsigned long)(ft-2)<>1)|0xaa); dst[0x26]=(volume|0xaa); dst[0x27]=((trk>>1)|0xaa); dst[0x28]=(trk|0xaa); dst[0x29]=((ph_sector>>1)|0xaa); dst[0x2a]=(ph_sector|0xaa); c = (volume^trk^ph_sector); dst[0x2b]=((c>>1)|0xaa); dst[0x2c]=(c|0xaa); for (i = 0; i < 86; i++) { x = (pgm_read_byte_near(FlipBit1+(src[i]&3)) | pgm_read_byte_near(FlipBit2+(src[i+86]&3)) | ((i<=83)?pgm_read_byte_near(FlipBit3+(src[i+172]&3)):0)); dst[i+0x38] = pgm_read_byte_near(encTable+(x^ox)); ox = x; } for (i = 0; i < 256; i++) { x = (src[i] >> 2); dst[i+0x8e] = pgm_read_byte_near(encTable+(x^ox)); ox = x; } dst[0x18e]=pgm_read_byte_near(encTable+ox); } { unsigned char c, d; unsigned short long_sector = (unsigned short)trk*16+ph_sector; unsigned short long_cluster = long_sector>>sectorsPerCluster2; unsigned char fatNum = long_cluster/FAT_NIC_ELEMS; unsigned short ft; if (fatNum != prevFatNumNic) { prevFatNumNic = fatNum; prepareFat(nicDir, fatNic, (560+sectorsPerCluster-1)>>sectorsPerCluster2, fatNum, FAT_NIC_ELEMS); } ft = fatNic[long_cluster%FAT_NIC_ELEMS]; PORTD = 0b00000010; PORTD = 0b00000000; cmdFast(24, userAddr+(((unsigned long)(ft-2)<>= 1) { if (c&d) { PORTD = D1; PORTD = D2; } else { PORTD = D3; PORTD = D4; } } } PORTD = 0b00000000; writeByteFast(0xff); writeByteFast(0xff); readByteFast(); waitFinish(); PORTD = 0b00000010; PORTD = 0b00000000; } } } buffClear(); PORTB &= 0b11101111; } // initialization called from check_eject void init(void) { unsigned char ch; unsigned short i; char str[5]; unsigned char filebase[8]; inited = 0; PORTB = 0b00110000; // LED on // initialize the SD card PORTD = 0b00000010; for (i = 0; i != 200; i++) { PORTD = 0b00110010; wait5(WAIT); PORTD = 0b00010010; wait5(WAIT); } // input 200 clock PORTD = 0b000000000; cmd_(0, 0); // command 0 do { if (bit_is_set(PIND,3)) return; ch = readByteSlow(); } while (ch != 0x01); PORTD = 0b00000010; while (1) { if (bit_is_set(PIND,3)) return; PORTD = 0b00000000; cmd_(55, 0); // command 55 ch = getRespSlow(); if (ch == 0xff) return; if (ch & 0xfe) continue; // if (ch == 0x00) break; PORTD = 0b00000010; PORTD = 0b00000000; cmd_(41, 0); // command 41 if (!(ch=getRespSlow())) break; if (ch == 0xff) return; PORTD = 0b00000010; } // BPB address cmdFast(16,5); cmd17Fast(54); for (i=0; i<5; i++) str[i] = readByteFast(); readByteFast(); readByteFast(); // discard CRC if ((str[0]=='F')&&(str[1]=='A')&&(str[2]=='T')&& (str[3]=='1')&&(str[4]=='6')) { bpbAddr = 0; } else { cmdFast(16, 4); cmd17Fast((unsigned long)0x1c6); bpbAddr = readByteFast(); bpbAddr += (unsigned long)readByteFast()*0x100; bpbAddr += (unsigned long)readByteFast()*0x10000; bpbAddr += (unsigned long)readByteFast()*0x1000000; bpbAddr *= 512; readByteFast(); readByteFast(); // discard CRC bytes } if (bit_is_set(PIND,3)) return; // sectorsPerCluster and reservedSectors { unsigned short reservedSectors; volatile unsigned char k; cmdFast(16, 3); cmd17Fast(bpbAddr+0xd); sectorsPerCluster = k = readByteFast(); sectorsPerCluster2 = 0; while (k != 1) { sectorsPerCluster2++; k >>= 1; } reservedSectors = readByteFast(); reservedSectors += (unsigned short)readByteFast()*0x100; readByteFast(); readByteFast(); // discard CRC bytes // sectorsPerCluster = 0x40 at 2GB, 0x10 at 512MB // reservedSectors = 2 at 2GB fatAddr = bpbAddr + (unsigned long)512*reservedSectors; } if (bit_is_set(PIND,3)) return; { // sectorsPerFat and rootAddr cmdFast(16, 2); cmd17Fast(bpbAddr+0x16); sectorsPerFat = readByteFast(); sectorsPerFat += (unsigned short)readByteFast()*0x100; readByteFast(); readByteFast(); // discard CRC bytes // sectorsPerFat = at 512MB, 0xEF at 2GB rootAddr = fatAddr + ((unsigned long)sectorsPerFat*2*512); userAddr = rootAddr+(unsigned long)512*32; } if (bit_is_set(PIND,3)) return; // find "NIC" extension nicDir = findExt("NIC", &protect, (unsigned char *)0); if (nicDir == 512) { // create NIC file if not exists // find "DSK" extension dskDir = findExt("DSK", (unsigned char *)0, filebase); if (dskDir == 512) return; if (!createNic(filebase)) return; nicDir = findExt("NIC", &protect, (unsigned char *)0); if (nicDir == 512) return; // convert DSK image to NIC image dsk2Nic(); } if (bit_is_set(PIND,3)) return; prevFatNumNic = 0xff; prevFatNumDsk = 0xff; bitbyte = 0; readPulse = 0; magState = 0; prepare = 1; ph_track = 0; sector = 0; buffNum = 0; formatting = 0; writePtr = &(writeData[buffNum][0]); cmdFast(16, (unsigned long)512); buffClear(); inited = 1; } // called when the card is inserted or removed void check_eject(void) { unsigned long i; if (bit_is_set(PIND,3)) { // added 2010/5/28 for (i=0; i!=0x50000;i++) if (bit_is_clear(PIND,3)) return; TIMSK0 &= ~(1<>4); stp = (PINB & 0b00001111); if (stp != oldStp) { oldStp = stp; unsigned char ofs = ((stp==0b00001000)?2: ((stp==0b00000100)?4: ((stp==0b00000010)?6: ((stp==0b00000001)?0:0xff)))); if (ofs != 0xff) { ofs = ((ofs+ph_track)&7); unsigned char bt = pgm_read_byte_near(stepper_table + (ofs>>1)); oldStp = stp; if (ofs&1) bt &= 0x0f; else bt >>= 4; ph_track += ((bt & 0x08) ? (0xf8 | bt) : bt); if (ph_track > 196) ph_track = 0; if (ph_track > 139) ph_track = 139; } } if (inited && prepare) { cli(); sector = ((sector+1)&0xf); { unsigned char trk = (ph_track>>2); unsigned short long_sector = (unsigned short)trk*16+sector; unsigned short long_cluster = long_sector>>sectorsPerCluster2; unsigned char fatNum = long_cluster/FAT_NIC_ELEMS; unsigned short ft; if (fatNum != prevFatNumNic) { prevFatNumNic = fatNum; prepareFat(nicDir, fatNic, (560+sectorsPerCluster-1)>>sectorsPerCluster2, fatNum, FAT_NIC_ELEMS); } ft = fatNic[long_cluster%FAT_NIC_ELEMS]; if (((sectors[0]==sector)&&(tracks[0]==trk)) || ((sectors[1]==sector)&&(tracks[1]==trk)) || ((sectors[2]==sector)&&(tracks[2]==trk)) || ((sectors[3]==sector)&&(tracks[3]==trk)) || ((sectors[4]==sector)&&(tracks[4]==trk))) writeBackSub(); cmd17Fast(userAddr+(((unsigned long)(ft-2)<>sectorsPerCluster2; unsigned char fatNum = long_cluster/FAT_NIC_ELEMS; unsigned short ft; if (bit_is_set(PIND,3)) return; if (fatNum != prevFatNumNic) { prevFatNumNic = fatNum; prepareFat(nicDir, fatNic, (560+sectorsPerCluster-1)>>sectorsPerCluster2, fatNum, FAT_NIC_ELEMS); } ft = fatNic[long_cluster%FAT_NIC_ELEMS]; PORTD = 0b00000010; PORTD = 0b00000000; cmdFast(24, (unsigned long)userAddr+(((unsigned long)(ft-2)<>1)|0xaa); writeByteFast(volume|0xaa); writeByteFast((track>>1)|0xaa); writeByteFast(track|0xaa); writeByteFast((sc>>1)|0xaa); writeByteFast(sc|0xaa); c = (volume^track^sc); writeByteFast((c>>1)|0xaa); writeByteFast(c|0xaa); writeByteFast(0xde); writeByteFast(0xAA); writeByteFast(0xeb); // sync header writeByteFast(0xff); writeByteFast(0xff); writeByteFast(0xff); writeByteFast(0xff); writeByteFast(0xff); // data for (i = 0; i < 349; i++) { c = writeData[bn][i]; for (d = 0b10000000; d; d >>= 1) { if (c&d) { PORTD = 0b00010000; PORTD = 0b00110000; } else { PORTD = 0b00000000; PORTD = 0b00100000; } } } PORTD = 0b00000000; for (i = 0; i < 14*8; i++) { PORTD = 0b00010000; PORTD = 0b00110000; } PORTD = 0b00000000; for (i = 0; i < 96*8; i++) { PORTD = 0b00000000; PORTD = 0b00100000; } PORTD = 0b00000000; writeByteFast(0xff); writeByteFast(0xff); readByteFast(); waitFinish(); PORTD = 0b00000010; PORTD = 0b00000000; } void writeBackSub(void) { unsigned char i, j; if (bit_is_set(PIND,3)) return; for (j=0; j>2); sector=((((sector==0xf)||(sector==0xd))?(sector+2):(sector+1))&0xf); if (buffNum == (BUF_NUM-1)) { // cancel reading cancelRead(); writeBackSub(); prepare = 1; } else { buffNum++; writePtr = &(writeData[buffNum][0]); } } else { sector = sec; formatting = 0; if (sec == 0xf) { // cancel reading cancelRead(); prepare = 1; } } } if (writeData[buffNum][2]==0x96) { sec = (((writeData[buffNum][7]&0x55)<<1) | (writeData[buffNum][8]&0x55)); formatting = 1; } }