#include <90s8515.h> #include #include #include "receive.c" #define BAUD_RATE 3 //47 // 9600 baud #define UCR_SETTING 0x10 + 0x08 + 0x80; // enable the UART and RX interrupt #define ZIPID 5 #define ID 7 #define LUN 0 #define A 0 #define D 1 #define RSTo PORTD.4 #define RSTi PIND.4 #define RSTd DDRD.4 #define REQo PORTD.7 #define REQi PIND.7 #define REQd DDRD.7 #define ACKo PORTD.3 #define ACKi PIND.3 #define ACKd DDRD.3 #define BSYo PORTD.2 #define BSYi PIND.2 #define BSYd DDRD.2 #define SELo PORTC.2 #define SELi PINC.2 #define SELd DDRC.2 #define CDo PORTC.4 #define CDi PINC.4 #define CDd DDRC.4 #define IOo PORTD.5 #define IOi PIND.5 #define IOd DDRD.5 #define MSGo PORTD.6 #define MSGi PIND.6 #define MSGd DDRD.6 #define ATNo PORTC.3 #define ATNi PINC.3 #define ATNd DDRC.3 #define DBPo PORTC.1 #define DBPi PINC.1 #define DBPd DDRC.1 #define DBo PORTB #define DBi PINB #define DBd DDRB #define OUT 1 #define IN 0 #define BUSFREE 0 #define ARBITRATION 1 #define SELECTION 2 #define RESELECTION 3 #define COMMAND 4 #define DATA_IN 6 #define DATA_OUT 7 #define STATUS 8 #define MESSAGE_IN 9 #define MESSAGE_OUT 10 //#define FAT_SIZE 188 #define BR 32 //#define FAT_1 33 //#define FAT_2 221 //#define ROOT_DIR 409 #define BUFFERSIZE 15 #define NUM_CLUSTERS 11 flash unsigned char IMAGE_EXT[] = {'R', 'A', 'W'}; flash unsigned char convert[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8' ,'9','A','B', 'C', 'D', 'E', 'F'}; unsigned int FAT_1; unsigned int FAT_2; unsigned int ROOT_DIR; unsigned int FAT_SIZE; unsigned int clusters[NUM_CLUSTERS]; unsigned char cPointer=0; unsigned char buffer[BUFFERSIZE]; unsigned char bPointer=0; unsigned char state; unsigned int cwd=ROOT_DIR; unsigned char cmdReady=0; unsigned char readDir(); unsigned char ejectMedia(); unsigned char checkBusFree(); unsigned char getBus(); unsigned char SelectDevice(unsigned char); void checkTransferState(); void programLoop(); interrupt [UART_RXC] void uartRX(void){ char temp; temp = UDR; // get the char if (temp==0x08){ // handle backspace if(bPointer>0){ bPointer--; // go back one in the buffer printf("\b \b"); // output a backspace, space, backspace so that } // the character gets erased return; } buffer[bPointer++] = temp; // place the char into the buffer and increment the pointer if(temp != '\r'){ // check for return UDR = temp; // echo the character if(bPointer == BUFFERSIZE - 1) cmdReady = 1; // if the buffer is full, force a return } else { cmdReady = 1; // don't echo the return, the command processor will handle it // just set cmdReady to 1 } if(cmdReady){ bPointer=0; cmdReady=0; printf("\r\n"); if((buffer[0] == 'd') && (buffer[1] == 'i') && (buffer[2] == 'r') && (buffer[3] == '\r')){ readDir(); } else if((buffer[0] == 'e') && (buffer[1] == 'j') && (buffer[2] == 'e') && (buffer[3] == 'c') && (buffer[4] == 't') && (buffer[5] == '\r')){ ejectMedia(); } // else if((buffer[0] == 'r') && (buffer[1] == 'e') && (buffer[2] == 's') && (buffer[3] == 'e') && (buffer[4] == 't') && (buffer[5] == '\r')){ // programLoop(); // } else{ printf("Not valid command\r\n>"); } } } void RESET(){ DDRC=0x00; DDRB=0x00; DDRD=0x00; PORTC=0xff; PORTB=0xff; PORTD=0xff; delay_ms(250); } unsigned char command(){ while(state!=BUSFREE){ checkBusFree(); } getBus(); SelectDevice(0); while(state!=COMMAND){ checkTransferState(); } return 0; } void sendByte(unsigned char b){ unsigned char temp; REQd=IN; REQo=1; while(REQi==D){ if(RSTi==A) RESET(); } temp=b&0b00000001; temp=temp^((b&0b00000010)>>1); temp=temp^((b&0b00000100)>>2); temp=temp^((b&0b00001000)>>3); temp=temp^((b&0b00010000)>>4); temp=temp^((b&0b00100000)>>5); temp=temp^((b&0b01000000)>>6); temp=temp^((b&0b10000000)>>7); //temp gives even parity, but high is low for us, so it's correct DBd = 0xff; DBPd = OUT; DBo = ~b; //DBPo = !(~DBo.7 ^ ~DBo.6 ^ ~DBo.5 ^ ~DBo.4 ^ ~DBo.3 ^ ~DBo.2 ^ ~DBo.1 ^ ~DBo.0); DBPo = temp; // wait for 1 deskew + 1 cable skew ~55ns #asm nop #endasm ACKd = OUT; ACKo = A; while(REQi == A){ if(RSTi==A) RESET(); } ACKd = IN; ACKo=1; DBd = 0x00; DBo = 0xff; DBPd = IN; DBPo = 1; } unsigned char receiveByte(){ unsigned char ret; REQd=IN; REQo=1; DBd=0x00; DBo=0xff; while(REQi==D){ if(RSTi==A) RESET(); } ret = ~DBi; ACKd=OUT; ACKo=A; while(REQi==A){ if(RSTi==A) RESET(); } ACKd=IN; ACKo=1; return ret; } void checkTransferState(){ if(MSGi==A){ if(CDi==A){ if(IOi==A) state=MESSAGE_IN; else state=MESSAGE_OUT; } } else{ if(CDi==A){ if(IOi==A) state=STATUS; else state=COMMAND; } else{ if(IOi==A) state=DATA_IN; else state=DATA_OUT; } } } void resetTarget(){ RSTd=OUT; RSTo=A; delay_us(30); //Reset hold time is 30us RSTd=IN; RSTo=1; delay_ms(250); } unsigned char checkBusFree(){ DDRC=0x00; DDRB=0x00; DDRD=0x00; PORTC=0xff; PORTB=0xff; PORTD=0xff; delay_us(100); if ((BSYi==D)&&(SELi==D)){ delay_us(1); //Wait for bus to settle if ((BSYi==D)&&(SELi==D)){ state=BUSFREE; return 0; } } return 1; } unsigned char getBus(){ char temp; temp=checkBusFree(); if (state==BUSFREE){ BSYd=OUT; BSYo=A; DBPd=OUT; DBPo=A; //Assert Parity DBd.ID=OUT; //Put SCSI ID onto DB DBo.ID=A; delay_us(2); //Arbitration delay SELd=OUT; SELo=A; delay_us(1); //Wait bus clear and bus settle delay state=ARBITRATION; return 0; } return 1; } unsigned char SelectDevice(unsigned char a){ if (state==ARBITRATION){ DBd.ID=OUT; DBd.ZIPID=OUT; DBo.ID=A; DBo.ZIPID=A; if(a){ ATNd=OUT; ATNo=A; } //wait for at least 2 deskew delays ~40ns #asm nop #endasm BSYd=IN; BSYo=1; delay_us(1); //Bus settle delay ////////////////// //NOTE may need to check 200ms abort time! //clear db, zero sel,atn //could happen from bad parity....dbl check this //RST or goto bus free...not too important //////////////// while(BSYi==D){ if(/*(count++ == 750000) ||*/ (RSTi==A)) return 1; } //wait for at least 2 deskew delays ~40ns #asm nop #endasm SELd=IN; SELo=1; state=SELECTION; return 0; } return 1; } // the identify message will prevent the Zip drive // from disconnecting // LUNTAR/LUNTRN are set to 0 unsigned char sendIdentifyMessage(){ if(state==MESSAGE_OUT){ ATNd=IN; ATNo=1; #asm nop #endasm sendByte(0x80); return 0; } return 1; } /* unsigned char startStopUnit(){ if(state==COMMAND){ sendByte(0x1B); sendByte(1); sendByte(0); sendByte(0); sendByte(1); sendByte(0); return 0; } return 1; } */ unsigned char testUnitReady(){ if(!command()){ sendByte(0); sendByte(0); sendByte(0); sendByte(0); sendByte(0); sendByte(0); return 0; } return 1; } /* unsigned char requestSense(){ if(state==COMMAND){ sendByte(0x03); sendByte(0); sendByte(0); sendByte(0); sendByte(0); sendByte(0); return 0; } return 1; } */ unsigned char waitForReady(){ testUnitReady(); while(receiveByte() != 0x00){ receiveByte(); testUnitReady(); } receiveByte(); return 0; } unsigned char read(unsigned long sector){ waitForReady(); if(!command()){ sendByte(0x08); sendByte((sector >> 16) & 0x1f); sendByte((sector >> 8) & 0xff); sendByte(sector & 0xff); sendByte(1); sendByte(0); return 0; } return 1; } unsigned char write(unsigned long sector){ waitForReady(); if(!command()){ sendByte(0x0a); sendByte((sector >> 16) & 0x1f); sendByte((sector >> 8) & 0xff); sendByte(sector & 0xff); sendByte(1); sendByte(0); return 0; } return 1; } /* void putcharNS(unsigned char x){ if(x!=' ') putchar(x); } */ void readDirHelper(){ unsigned char i,j,buffer[21],count,b; for(i=0; i<16; i++){ for(j=0; j<8; j++){ buffer[j]=receiveByte(); } count=0; buffer[8]='.'; buffer[9]=receiveByte(); buffer[10]=receiveByte(); buffer[11]=receiveByte(); if (!((buffer[9]>=48)&&(buffer[9]<=126))){ buffer[8]=' '; buffer[9]=' '; buffer[10]=' '; buffer[11]=' '; } buffer[12]='\t'; b=receiveByte(); if(b&0b00000001){ count++; buffer[20]='1'; } else{ buffer[20]='-'; } if(b&0b00000010){ count++; buffer[19]='1'; } else{ buffer[19]='-'; } if(b&0b00000100){ count++; buffer[18]='1'; } else{ buffer[18]='-'; } if(b&0b00001000){ count++; buffer[17]='1'; } else{ buffer[17]='-'; } if(b&0b00010000){ buffer[16]='1'; } else{ buffer[16]='-'; } if(b&0b00100000){ buffer[15]='1'; } else{ buffer[15]='-'; } if(b&0b01000000){ buffer[14]='1'; } else{ buffer[14]='-'; } if(b&0b10000000){ buffer[13]='1'; } else{ buffer[13]='-'; } for (j=0;j<20;j++){ receiveByte(); } // if((count<4)&&(buffer[0]>=48)&&(buffer[0]<=126)){ count=0; for(j=0;j<12;j++){ if(buffer[j] == ' '){ count++; } else { putchar(buffer[j]); } } for(j=0;j"); return 1; } if(cwd==ROOT_DIR){ for(i=0;i<8;i++){ read(cwd+i); readDirHelper(); receiveByte(); receiveByte(); } printf(">"); } return 0; } unsigned char ejectMedia(){ unsigned char i, temp; for(i=0;i<100;i++){ testUnitReady(); temp=receiveByte(); receiveByte(); } if(temp!=0x00){ printf("No disk present\r\n>"); return 1; } if(!command()){ sendByte(0x1b); sendByte(0x00); sendByte(0x00); sendByte(0x00); sendByte(0x02); sendByte(0x00); receiveByte(); receiveByte(); printf(">"); return 0; } return 1; } unsigned char addEntry(unsigned int cluster){ unsigned char i, k, temp, found=0; unsigned int j; if(cwd==ROOT_DIR){ for(i=0;(i<8) && (!found);i++){ read(cwd+i); for(j=0;j<16;j++){ temp=receiveByte(); if((!found) && ((temp == 0xE5) || (temp == 0x00))){ // throw out the rest of the DIR entry for(k=0;k<31;k++){ receiveByte(); } // write new entry to RAM for(k=0;k<8;k++){ store(name[k]); } store(IMAGE_EXT[0]); store(IMAGE_EXT[1]); store(IMAGE_EXT[2]); store(0b00100000); store(0); store(0); store(0); store(0); store(0); store(0); store(0); store(0); store(0); store(0); store(0); store(0); // timestamp store(0); store(0); // date store((cluster >> 8) & 0xff); // fat pointer store(cluster & 0xff); store(0); store(0); store(0x50); store(0xC8); // size found = 1; } else { store(temp); for(k=0;k<31;k++){ store(receiveByte()); } } } printf("done with for loop"); receiveByte(); // ignore status receiveByte(); // ignore message if(found){ printf("writing an entry"); write(cwd+i); for(j=0; j<512; j++){ sendByte(retrieve()); } receiveByte(); // ignore status receiveByte(); // ignore message } else { printf("skipping this entry"); for(j=0; j<512; j++){ retrieve(); } } } } printf("returning"); return 0; } unsigned char findFAT(){ unsigned long fat=FAT_1; unsigned char f1, f2; unsigned int current=2,i; while((cPointer < NUM_CLUSTERS) && (fat < FAT_2)){ read(fat); for(i=0; i<256; i++){ f1=receiveByte(); f2=receiveByte(); if((f1 == 0) && (f2 == 0)){ if(cPointer == 0){ store(0xff); store(0xf8); } else { store((clusters[cPointer] >> 8) & 0xff); store(clusters[cPointer] & 0xff); } clusters[cPointer++] = current; } else { store(f1); store(f2); } current++; } receiveByte(); // ignore status receiveByte(); // ignore message write(fat); for(i=0; i<512; i++){ sendByte(retrieve()); } receiveByte(); // ignore status receiveByte(); // ignore message } if(fat >= FAT_2) return 1; // not enough room on disk, suspend MCU return 0; } unsigned char noOp(){ if(state==COMMAND){ sendByte(0); sendByte(0); sendByte(0); sendByte(0); sendByte(0); sendByte(0); receiveByte(); receiveByte(); return 0; } return 1; } unsigned long sector(unsigned int cluster){ return (cluster << 2) + 441 - 2; } void programLoop(){ unsigned char temp,i,j; unsigned int a, k; printf("\r\n>"); RESET(); resetTarget(); RSTd=IN; RSTo=1; #asm sei #endasm while(state!=BUSFREE){ checkBusFree(); } temp=getBus(); temp=SelectDevice(1); while(state!=MESSAGE_OUT){ checkTransferState(); } temp=sendIdentifyMessage(); while(state!=COMMAND){ checkTransferState(); } noOp(); while(state!=BUSFREE){ checkBusFree(); } // we are now in Bus Free state /* read(0); for(k=1; k<0x01c6; k++){ receiveByte(); } receiveByte(); receiveByte(); BR = receiveByte() << 8; BR = BR | (receiveByte() & 0xff); for(k = 0x01c6 + 0x04; k<=512; k++){ receiveByte(); } receiveByte(); // ignore status receiveByte(); // ignore message */ // read our FAT structure from the boot record of partition 1 read(BR); for(k=1; k<0x0e; k++){ receiveByte(); } a = receiveByte() << 8; a = a | (receiveByte() & 0xff); FAT_1 = BR + a; for(k=0x10;k<0x16;k++){ receiveByte(); } FAT_SIZE = receiveByte() << 8; FAT_SIZE = FAT_SIZE | (receiveByte() & 0xff); for(k=0x18;k<=512;k++){ receiveByte(); } receiveByte(); receiveByte(); FAT_2 = FAT_1 + FAT_SIZE; cwd = FAT_2 + FAT_SIZE; ROOT_DIR = cwd; /* for(k=0;k<500;k++){ printf("Sector %d:", k); read(k); for(a=0;a<512;a++){ putchar(receiveByte()); } receiveByte(); receiveByte(); printf("\r\n"); } */ // bus free while(1){ // wait until an image is ready temp=receive(); // find free FAT clusters if(findFAT()){ while(1){} // no more room on zip, suspend MCU } // create a directory entry addEntry(clusters[NUM_CLUSTERS - 1]); // get the rest of the image and store it for(i=NUM_CLUSTERS-1; i>0; i--){ for(j=0;j<4;j++){ write(sector(clusters[i]) + j); for(k=0;k<512;k++){ sendByte(temp); temp=receive(); } receiveByte(); // ignore status receiveByte(); // ignore message } } // finish the last cluster write(sector(clusters[0])); sendByte(temp); for(i=0;i<199;i++){ sendByte(receive()); } for(i=0;i<312;i++){ sendByte(0); // internal fragmentation } receiveByte(); receiveByte(); } } void main(){ // set up the UART UCR = UCR_SETTING; UBRR = BAUD_RATE; receive_init(); printf("\r\n\r\n\r\nWelcome to the Zip Drive Digital Camera All-in-One System v 0.0.1"); programLoop(); }