📄 cf_fat.c
字号:
#include <16F877.H>#list#include "Math32.c"// Configuration bits for initial programming#fuses HS, NOPROTECT, WDT, PUT, BROWNOUT, NOLVP// clock crystal frequency#use delay (clock=16000000)#use rs232 (baud=19200, xmit=PIN_C6, rcv=PIN_C7)// Disable automatic TRIS programming for all ports#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)#use fast_io(e)// define for initial PIC programming to include the serial programming function#define InitialProgram// CompactFlash pins// 3 address lines (all others grounded) #define CF_A0 PIN_B0 #define CF_A1 PIN_B1 #define CF_A2 PIN_B2// data flow strobe signals #define CF_N_OE PIN_B3 #define CF_N_WE PIN_B4// card detect signal (high if card is not present) #define CF_CD1 PIN_B7 #define cf_out input(CF_CD1)// CF power switch #define CF_POWER PIN_B6// LED pins #define CF_LED0 PIN_C1 #define CF_LED1 PIN_C2#byte PORTA = 0x05#byte PORTB = 0x06#byte PORTC = 0x07#byte CF_DATA = 0x08 /* Port D */#byte CF_DATA_TRIS = 0x88 /* Port D TRIS */// 1-in 0-out#define TRIS_A 0xFF // 11111111#define TRIS_B 0x80 // 10000000#define TRIS_C 0xD9 // 11011001#define TRIS_C_SLEEP 0x81 // 10000001#define TRIS_E 0x01 // 0000x001#define TRIS_D_IN 0xFF // 11111111#define TRIS_D_OUT 0x00 // 00000000// Function Prototypesvoid print_prompt();void led_off();void led_red();void led_green();#separate boolean process_command();void print_help();int fromHex(char hex);void set_default_signals();void cf_task_file_read(int addr);void cf_task_file_write(int addr, int data);void cf_set_addr(int addr);// Global variablesint curData; // Holds data to be sentint curAddr; // Holds address to be read/written// self-programming function// reprograms PIC thru serial port// host sends pieces of code as:// 1 byte header 0xAB// 2 bytes start address// 2 bytes (N) number of words to program// N words (N*2 bytes) program words//// after each program word function sends back// 1 if word programmed successfully// 0 if not//// send non 0XAB byte to exit the cycle and restart Hoarder//#ifdef InitialProgram#ORG 0x1F00, 0x1FFFvoid self_program(){ long addr, count, val, i; disable_interrupts(GLOBAL); while(getc()==0xAB) { *(&addr)=getc(); *(&addr+1)=getc(); *(&count)=getc(); *(&count+1)=getc(); for (i=0; i<count; i++) { *(&val)=getc(); *(&val+1)=getc(); if (val==read_program_eeprom(addr)) putc(1); else { write_program_eeprom(addr, val); if (val==read_program_eeprom(addr)) putc(1); else putc(0); } addr++; restart_wdt(); } } #asm movlw 0 movwf 0x0A goto 0 #endasm}#endif// jumps to self_program()// normally called from command processor// Note: if you want serial programming to work make sure you can always interrupt// your program from serial port and have a command that calls this function#inlinevoid reprogram(){#ifdef InitialProgram self_program();#else #asm movlw 0x18 movwf 0x0A goto 0x700 #endasm#endif}// timer function// increments ms counter// performs timed AD conversion// can do a lot of other neat stuff!// normally interrupts 1000 times per second// Note: in multisensor boards configuration can be set to 8000 times/sec// to sample audio#int_timer2void timer2() { static int i;// resets watchdog timer// Note: if you disable timer interrupt do this periodically somewhere else// otherwise WDT will reset PIC in ~2 seconds restart_wdt();// inc32(ms); if (++ms[0]==0) if (++ms[1]==0) if (++ms[2]==0) ++ms[3]; if (ad_on) {#ifdef Tim if (ad_count==3) voltage=read_adc(); if (ad_count==0)#endif // else overflow if (audio) ad_count=0; else { ad_count++; if (ad_count>3) ad_count=0; }//#ifdef GAME// if (ad_count==1) set_adc_channel(4); else set_adc_channel(ad_count);//#else set_adc_channel(ad_count);//#endif }}// Resets AD buffervoid purge_adc_buffer(){ buf_head=0; buf_count=0; set_adc_channel(0); ad_count=0;}// Green-Red... Happy?void blink_happy(){ while (TRUE) { led_green(); delay_ms(250); led_red(); delay_ms(250); }}void blink_sad(){ while (TRUE) { led_red(); delay_ms(250); led_off(); delay_ms(250); }}void main(){ setup_adc_ports(A_ANALOG); // port A all analog inputs setup_adc(ADC_CLOCK_DIV_32); // set ADC clock setup_psp(PSP_DISABLED); set_default_signals(); // preset some of the signals SET_TRIS_A(TRIS_A); // set TRIS values SET_TRIS_B(TRIS_B); SET_TRIS_C(TRIS_C); SET_TRIS_D(TRIS_D_IN); SET_TRIS_E(TRIS_E); port_b_pullups(TRUE); // Should be enabled; Used for B6 and B7 (CF power and CF detection) setup_timer_2(T2_DIV_BY_4, 250, 5); // default timer: 1mS interval @ 20 MHz; see timer2() zero32(ms); // zero millisecond counter ad_on=FALSE; audio=FALSE; purge_adc_buffer();// enable_interrupts(INT_RB); enable_interrupts(INT_TIMER2); enable_interrupts(GLOBAL); disable_cf();// set_default_signals();// send_hello();#ifdef GAME puts("GAME"); send_player_info();#else// take_a_nap();#endif#ifdef Rochester puts("Roch"); delay_ms(5000); save_audio();#endif#ifdef ESL puts("HackFest v odno slovo");// send_data_bim();#endif#ifdef Tim puts("Tim"); send_data_Tim();#endif print_prompt(); while(TRUE) { led_off(); process_command(); led_red(); led_green(); led_green();// if (cf_out) take_a_nap(); }}// enable nice power-saving features of Microdrive (see Microdrive specs)// does nothing if used with regular CF memory cardsvoid enable_microdrive_write_cache(){ while ((cf_task_file_read(7)&0xC0)!=0x40); cf_task_file_write(1, 0x02); // 0x02 = enable write cache cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0xEF); // set features command while ((cf_read()&0xC0)!=0x40); cf_task_file_write(1, 0xAA); // 0xAA = enable read look ahead cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0xEF); // set features command while ((cf_read()&0xC0)!=0x40);#ifdef DelayedWrite cf_task_file_write(1, 0x07); // 7 = enable delayed write cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0xFA); // set delayed write command while ((cf_read()&0x80)==0x80);#endif}// put CF to sleep mode (see CF specs)#separatevoid cf_sleep()// put the card into sleep mode{ while ((cf_task_file_read(7)&0xC0)!=0x40); cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0x99); // sleep command}// put CF to standby mode (see CF specs)#separatevoid cf_standby()// put the card into stadby mode{ while ((cf_task_file_read(7)&0xC0)!=0x40); cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0x94); // standby immediate command}// put CF to idle mode (see CF specs)#separatevoid cf_idle(int delay)// put the card into idle mode, sets a delay for auto power-down{ while ((cf_task_file_read(7)&0xC0)!=0x40); cf_task_file_write(2, delay); cf_task_file_write(6, 0xE0); cf_task_file_write(7, 0x97); // idle command}void print_prompt(){ putc('>');}void led_off(){ OUTPUT_LOW(CF_LED0); OUTPUT_LOW(CF_LED1);}void led_green(){ OUTPUT_LOW(CF_LED1); OUTPUT_HIGH(CF_LED0);}void led_red(){ OUTPUT_LOW(CF_LED0); OUTPUT_HIGH(CF_LED1);}// getc() after taking care of possible overflow errorchar loadc(){ return getc();}char echoc(){ char c; c = getc(); putc(c); return c;}// Yep! It's nope. Used for short delays.#inlinevoid nop(){ #asm nop #endasm}// Well...void print_help(){ return;}/*| int fromHex(char hex)| Preconditions: hex is 1-f| Postconditions: returned int is 1-16*/int fromHex(char hex){ if(hex >= '0' && hex <= '9') return(hex - 48); // 0 --> 0 if(hex >= 'a' && hex <= 'f') return(hex - 87); // a --> 10 if(hex >= 'A' && hex <= 'F') return(hex - 55); // A --> 10 // Still here? Invalid return(20);}// Issues identify drive command (0xEC) and sends result to serial port#separatevoid identify_drive(){ unsigned int cnt; printf("identifying\n\r"); while ((cf_task_file_read(7)&0xC0)!=0x40); printf("prep..\n\r"); cf_task_file_write(6, 0xA0); // drive 0 cf_task_file_write(7, 0xEC); // identify drive command while ((cf_read()&0x80)==0x80); cf_set_addr(0); for(cnt = 0; cnt < 0xFF; cnt++) { putc(cf_read()); } for(cnt = 0; cnt < 0xFF; cnt++) { putc(cf_read()); } putc(cf_read()); putc(cf_read());}// reads sector and sends result to serial port#separatevoid read_sector(){ unsigned int cnt; sector[3]=fromHex(echoc()) * 0x10 + fromHex(echoc()); sector[2]=fromHex(echoc()) * 0x10 + fromHex(echoc()); sector[1]=fromHex(echoc()) * 0x10 + fromHex(echoc()); sector[0]=fromHex(echoc()) * 0x10 + fromHex(echoc()); printf("getting data from sector %x%x%x%x\n\r", sector[3], sector[2], sector[1], sector[0]); cf_start_sector_read(); for(cnt = 0; cnt < 0xFF; cnt++) { putc(cf_read()); } for(cnt = 0; cnt < 0xFF; cnt++) { putc(cf_read()); } putc(cf_read()); putc(cf_read());}void getdatafromcf(int32 addr);void cfread();// CF debugging:// read and print CF register#separatevoid read_register() { int temp; temp=cf_task_file_read(curAddr); //printf("%d: 0x%2X(%u)\n", curAddr, temp, temp);}// CF debugging:// write CF register#separatevoid write_register() { //printf("Writing 0x%2X(%u) to addr %u\n", curData, curData, curAddr); cf_task_file_write(curAddr, curData);}// CF debugging:// set data to write to CF register#separatevoid set_data() { int temp; printf("Data (hex): "); temp = loadc(); putc(temp); if((temp = fromHex(temp)) > 16) return; curData = (temp << 4); temp = loadc(); putc(temp); if ((temp = fromHex(temp)) > 16) return; curData |= temp; printf("\nData 0x%2X(%u)\n", curData, curData);}// CF debugging:// set CF register address#separatevoid set_address() { int temp; printf("Addr (0-7): "); temp=loadc(); putc(temp); temp = fromHex(temp); if (temp > 7) return; curAddr = temp; printf("\nAddr %u\n", curAddr);}// Find data file in root directory// If found returns TRUE and first cluster in global var cluster#separateboolean find_data_file_name() { int i, j, k, l; boolean match; char name[13]; printf("trying to find file\n\r"); move32(sector, dir_start); for (i=0; i<root_entries>>4; i++) { cf_start_sector_read(); for (j=0; j<16; j++) { match=true; for (k=0; k<11; k++) {name[k] = cf_read(); if (name[k]!=fname[k]) match=false;} name[12] = 0; printf("found file %s\n\r", name); cf_read_skip(26-11); cluster=cf_read()|((long)cf_read()<<8); if (match) return true; cf_read_skip(32-28); } inc32(sector); } return false;}// Scan FAT to determine the length of first consecutive cluster chain in the data file// Returns file chain length (number of clusters) in data_file_size// Note: Current implementationonly works with consecutive cluster chains;// if file is fragmented only first piece is used#separatevoid scan_data_file_clusters() { char tmp[4]; long ptr; long c; zero32(tmp); move32(sector, fat_start); tmp[0]=cluster>>8; add32(sector, tmp); cf_start_sector_read(); ptr=cluster&0xFF00; while (ptr++<cluster) cf_read_skip(2); zero32(data_file_size); do { c=cf_read()|((long)cf_read()<<8); inc32(data_file_size); if (ptr!=c) return; if (!(ptr&0xFF)) { inc32(sector); cf_start_sector_read(); } ptr++; } while (true);}// Finds data file and determines its length#separateboolean find_data_file() { // Find the data file if (!find_data_file_name()) return false; scan_data_file_clusters(); return true;}void cfread(){ data_lo = cf_read(); data_hi = cf_read();}void cfskip(char count){ for (count;count>0;count--){ cfread(); }}void getdatafromcf(int32 addr) { sector[0] = (int32)addr & 0xff; sector[1] = ((int32)addr >> 8)& 0xff; sector[2] = ((int32)addr >> 16)& 0xff; sector[3] = ((int32)addr >> 24)& 0xff; printf("getting data from sector %x%x%x%x\n\r", sector[3], sector[2], sector[1], sector[0]); cf_start_sector_read();}char getsongstart(int16 filenumber){ char fname[12], c, attr, startcluster; int16 filesize; getdatafromcf((Firstrootdirsecnum+(filenumber/16))+bpbstart); cfskip((filenumber & 0x000F)*16); cfread(); printf("1stc: %x ",data_lo); if(data_lo==0x00){ return(0x02); } if(data_lo != 0xe5){ fname[0]=data_lo; fname[1] = data_hi; for (c=2; c<12; c++) { cfread(); fname[c] = data_lo; c++; fname[c] = data_hi; } attr = data_hi; fname[11] = 0; printf("%s", fname); if (attr & 0b00010000) { printf(" <DIR> "); } cfread(); cfread(); cfread(); cfread(); cfread(); putc(13);putc(10); cfread(); printf("date1: %X %X ",data_hi,data_lo); cfread(); printf("_ %X %X ",data_hi,data_lo); cfread(); printf("cluster: %X%X ",data_hi,data_lo); cfread(); printf("filesize: %X%X ",data_hi,data_lo); cfread(); printf("%X%X ",data_hi,data_lo); putc(13);putc(10); putc(13);putc(10); } return(0x00);}char lsroot(){ char i, ret; ret = 0; i=0; while ((ret != 2)) { ret = getsongstart(i++); }}void printout_rootdir(void){ char ent; char sec; for (sec=0;sec<16;sec++){ getdatafromcf(FirstRootDirSecNum+sec); for (ent=0;ent<32;ent++){ printf("entry%4LX is: ",ent+(32*sec)); putc(13);putc(10); cfread(); putc(data_lo);putc(data_hi); cfread(); putc(data_lo);putc(data_hi); cfread(); putc(data_lo);putc(data_hi); cfread(); putc(data_lo);putc(data_hi); cfread(); putc(data_lo);putc(data_hi); cfread(); putc(data_lo); putc(13);putc(10); printf("attr:%X ",data_hi); putc(13);putc(10); cfread(); cfread(); cfread(); cfread(); cfread(); putc(13);putc(10); cfread(); printf("date1: %X %X ",data_hi,data_lo); cfread(); printf("_ %X %X ",data_hi,data_lo); cfread(); printf("cluster: %X%X ",data_hi,data_lo); cfread(); printf("filesize: %X%X ",data_hi,data_lo); cfread(); printf("%X%X ",data_hi,data_lo); putc(13);putc(10); putc(13);putc(10); } }}// Command processor#separateboolean process_command(){ cmd = loadc(); /* Echo the character */ putc(cmd); switch (cmd) { case 0xA5: reprogram(); break; case '=': check_cf(); break; case '$': read_sector(); break; case '@': cf_idle(100); break; case 'i': identify_drive(); break; case '.': cf_sleep(); break; case '^': cf_dump(); break; case 'b': find_bpb(); break; //case 'p': printout_rootdir(); break; case 'l': lsroot(); break; case ',': cf_standby(); break; case '!': cf_reset(); break; case 'd': set_data(); break; case 'a': set_address(); break; } print_prompt(); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -