//********************************************************** // // file cf_io.c // // 8 bits i/o for Compact Flash card by Teunis van Beelen // // teuniz@gmail.com // // LBA-mode, 512 bytes per sector // // last revision 03-02-2005 // //********************************************************** #include "cf_io.h" void activate_powersave(void) { access_card(0x02, 64); // powersave after 64 * 5 mSec. access_card(0x06, 0); access_card(0x07, 0xe3); // idle mode } unsigned short cf_read_word(void) { unsigned short cf_read_word_int; unsigned char cf_read_word_byte; clear_bit(portc,3); // strobe _OE nop(); while(!(portc&32)); // RDY/_BSY cf_read_word_byte = portd; // read byte set_bit(portc,3); nop(); while(!(portc&32)); // RDY/_BSY nop(); clear_bit(portc,3); // strobe _OE nop(); while(!(portc&32)); // RDY/_BSY cf_read_word_int = portd; set_bit(portc,3); cf_read_word_int = (cf_read_word_int << 8) + cf_read_word_byte; return(cf_read_word_int); } void read_write_sector(unsigned long lba, unsigned char write, unsigned char n) { access_card(0x02, n); // sector count access_card(0x03, lba); lba >>= 8; access_card(0x04, lba); lba >>= 8; access_card(0x05, lba); lba >>= 8; lba = lba | 11100000b; // zie pagina 60 CF specification rev. 1.4 access_card(0x06, lba); if(write) access_card(0x07,0x30); // write sector else access_card(0x07, 0x20); // read sector } unsigned long get_drive_param(void) { unsigned char k; unsigned short s; unsigned long sectors; access_card(0x07,0xec); // STATUS/COMMAND, identify drive command k = cf_read_byte(); if(k!=0x8a) return(0); k = cf_read_byte(); if(k!=0x84) return(0); for(k=0; k<12; k++) cf_read_byte(); sectors = cf_read_word(); sectors <<= 16; s = cf_read_word(); sectors += s; return(sectors); } void access_card(unsigned char a_c_command, unsigned char a_c_data) { // for details see tabel 35, chapter 6.1.3 of CF-spec. trisd = 0x00; // set port D as output porte = a_c_command; // STATUS/COMMAND portd = a_c_data; // identify drive command while(!(portc&32)); // RDY/_BSY clear_bit(portc,4); // strobe _WE nop(); set_bit(portc,4); nop(); while(!(portc&32)); // RDY/_BSY porte = 0x00; // read data command trisd = 0xff; // set port D as input } void cf_write_word(unsigned short cf_write_word_temp) { trisd = 0x00; // set port D as output porte = 0x00; // even write data portd = cf_write_word_temp; // data while(!(portc&32)); // RDY/_BSY clear_bit(portc,4); // strobe _WE nop(); set_bit(portc,4); portd = cf_write_word_temp >> 8; // data while(!(portc&32)); // RDY/_BSY clear_bit(portc,4); // strobe _WE nop(); set_bit(portc,4); nop(); while(!(portc&32)); // RDY/_BSY trisd = 0xff; // set port D as input } void cf_write_byte(unsigned char cf_write_byte_temp) { trisd = 0x00; // set port D as output porte = 0x00; // even write data portd = cf_write_byte_temp; // data while(!(portc&32)); // RDY/_BSY clear_bit(portc,4); // strobe _WE nop(); set_bit(portc,4); nop(); while(!(portc&32)); // RDY/_BSY trisd = 0xff; // set port D as input } void cf_write_null(unsigned short write_cnt) { trisd = 0x00; // set port D as output porte = 0x00; // even write data portd = 0x00; // data while(write_cnt--) { clear_bit(portc,4); // strobe _WE nop(); set_bit(portc,4); while(!(portc&32)); // RDY/_BSY } trisd = 0xff; // set port D as input } unsigned char cf_read_byte(void) { unsigned char cf_read_byte_temp; clear_bit(portc,3); // strobe _OE nop(); while(!(portc&32)); // RDY/_BSY cf_read_byte_temp = portd; // read byte set_bit(portc,3); return(cf_read_byte_temp); } void reset_card(void) { while(!(portc&32)); // RDY/_BSY delay_ms(50); set_bit(portc,2); // reset line delay_ms(100); clear_bit(portc,2); delay_ms(50); while(!(portc&32)); // RDY/_BSY delay_ms(10); }