⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cf_fat.c

📁 Build ourself a MP3 Player
💻 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 + -