File content as of revision 0:76427232f435:
#include "mbed.h"
#include "LPC17xx.h"
#include "integer.h"
#include "diskio.h"
#include "stdarg.h"
#include "USBHost.h"
#include "Terminal.h"
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
static volatile DSTATUS Stat[3] = {STA_NOINIT | STA_NODISK}; /* Disk status */
static volatile BYTE DiskProcTimer[3]={0}; /* 100Hz decrement timer */
BYTE RAM_DISK[512];
DWORD BlockSize;
DWORD BlockCount;
//#define _CF_DEBUG_MESSAGES
//#define _CF_DEBUG_READ_ATA
#ifdef _CF_DEBUG_MESSAGES
#define CF_DEBUG(...) printf(__VA_ARGS__)
#else
#define CF_DEBUG do{}while(0);
#endif
void disk_timerproc (void);
#define LED1_MASK (uint32_t )(1<<18)
#define LED2_MASK (uint32_t )(1<<20)
#define LED3_MASK (uint32_t )(1<<21)
#define LED4_MASK (uint32_t )(1<<23)
#define LED1_ON LPC_GPIO1->FIOSET=LED1_MASK
#define LED1_OFF LPC_GPIO1->FIOCLR=LED1_MASK
#define LED1_TOGGLE LPC_GPIO1->FIOPIN^=LED1_MASK
#define LED2_ON LPC_GPIO1->FIOSET=LED2_MASK
#define LED2_OFF LPC_GPIO1->FIOCLR=LED2_MASK
#define LED2_TOGGLE LPC_GPIO1->FIOPIN^=LED2_MASK
#define LED3_ON LPC_GPIO1->FIOSET=LED3_MASK
#define LED3_OFF LPC_GPIO1->FIOCLR=LED3_MASK
#define LED3_TOGGLE LPC_GPIO1->FIOPIN^=LED3_MASK
#define LED4_ON LPC_GPIO1->FIOSET=LED4_MASK
#define LED4_OFF LPC_GPIO1->FIOCLR=LED4_MASK
#define LED4_TOGGLE LPC_GPIO1->FIOPIN^=LED4_MASK
//8-bit Data Bus is on Pins P0.4 - P0.11
#define DATA_BUS_MASK (uint32_t )((0xFF)<<4)
//3 bit address is on Port 2.0 - 2.2
#define ADDRESS_BUS_MASK (uint32_t )(0x7)
//ChipSelects are on port 2
#define CS0_MASK (uint32_t )(1<<3)
#define CS1_MASK (uint32_t )(1<<4)
//IORD and IOWR are on port 0
#define IORD_MASK (uint32_t )(1<<24)
#define IOWR_MASK (uint32_t )(1<<23)
//Reset and power enable are on port 1
#define COMPACT_FLASH_RESET_MASK (uint32_t )(1<<30)
#define COMPACT_FLASH_POWER_ENABLE_MASK (uint32_t )(0x80000000)
//Card Detect is on Port 2
#define COMPACT_FLASH_CARD_DETECT_MASK (uint32_t )(1<<5)
//Low Level Bus Operation Macros
//Note: LPC 176x have dedicate set and clear registers
#define SET_DATA_BUS_TO_INPUTS LPC_GPIO0->FIODIR &= ~(DATA_BUS_MASK);
#define SET_DATA_BUS_TO_OUTPUT LPC_GPIO0->FIODIR |= (DATA_BUS_MASK);
#define CS0_ACTIVE LPC_GPIO2->FIOCLR = CS0_MASK
#define CS0_INACTIVE LPC_GPIO2->FIOSET = CS0_MASK
#define CS1_ACTIVE LPC_GPIO2->FIOCLR = CS1_MASK
#define CS1_INACTIVE LPC_GPIO2->FIOSET = CS1_MASK
#define IORD_ACTIVE LPC_GPIO0->FIOCLR = IORD_MASK
#define IORD_INACTIVE LPC_GPIO0->FIOSET = IORD_MASK
#define IOWR_ACTIVE LPC_GPIO0->FIOCLR = IOWR_MASK
#define IOWR_INACTIVE LPC_GPIO0->FIOSET = IOWR_MASK
#define COMPACT_FLASH_RESET_ACTIVE LPC_GPIO1->FIOCLR = COMPACT_FLASH_RESET_MASK
#define COMPACT_FLASH_RESET_INACTIVE LPC_GPIO1->FIOSET = COMPACT_FLASH_RESET_MASK
#define COMPACT_FLASH_POWER_ENABLE LPC_GPIO1->FIOCLR = COMPACT_FLASH_POWER_ENABLE_MASK
#define COMPACT_FLASH_POWER_DISABLE LPC_GPIO1->FIOSET = COMPACT_FLASH_POWER_ENABLE_MASK
#define COMPACT_FLASH_CARD_DETECTED (!((LPC_GPIO2->FIOPIN)&COMPACT_FLASH_CARD_DETECT_MASK))
//To set the Address and Data Bus Lines we will use the convient Mask register in the Port I/O modules
//The Hardware will mask out pins that are set to 1 in the MASK register
#define SET_CF_ADDRESS(ADDRESS) LPC_GPIO2->FIOMASK=~(ADDRESS_BUS_MASK); \
LPC_GPIO2->FIOPIN=ADDRESS; \
LPC_GPIO2->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
#define SET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \
LPC_GPIO0->FIOPIN=(((uint32_t)DATA)<<4); \
LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
#define GET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \
(DATA) = (LPC_GPIO0->FIOPIN)>>4; \
LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
#define SET_DATA_BUS_AS_OUTPUTS LPC_GPIO0->FIODIR|=DATA_BUS_MASK
#define SET_DATA_BUS_AS_INPUTS LPC_GPIO0->FIODIR&=~DATA_BUS_MASK
/* ATA command */
#define CMD_RESET 0x08 /* DEVICE RESET */
#define CMD_READ 0x20 /* READ SECTOR(S) */
#define CMD_WRITE 0x30 /* WRITE SECTOR(S) */
#define CMD_IDENTIFY 0xEC /* DEVICE IDENTIFY */
#define CMD_SETFEATURES 0xEF /* SET FEATURES */
/* ATA register bit definitions */
#define LBA 0xE0
#define BUSY 0x80
#define DRDY 0x40
#define DF 0x20
#define DRQ 0x08
#define ERR 0x01
#define SRST 0x40
#define nIEN 0x20
/* Bit definitions for Control Port */
#define CTL_READ 0x20
#define CTL_WRITE 0x40
#define CTL_RESET 0x80
#define REG_DATA 0x0
#define REG_ERROR 0x1
#define REG_FEATURES 0x1
#define REG_COUNT 0x2
#define REG_SECTOR 0x3
#define REG_CYLL 0x4
#define REG_CYLH 0x5
#define REG_DEV 0x6
#define REG_COMMAND 0x7
#define REG_STATUS 0x7
#define REG_DEVCTRL 0xE
#define REG_ALTSTAT 0xE
void InitCompactFlashInterface()
{
SET_DATA_BUS_AS_INPUTS;
LPC_GPIO2->FIODIR |= ADDRESS_BUS_MASK | CS0_MASK | CS1_MASK;
LPC_GPIO2->FIODIR &=~(COMPACT_FLASH_CARD_DETECT_MASK);
LPC_GPIO1->FIODIR |= COMPACT_FLASH_RESET_MASK | COMPACT_FLASH_POWER_ENABLE_MASK | LED1_MASK | LED2_MASK | LED3_MASK | LED4_MASK;
LPC_GPIO0->FIODIR |= IORD_MASK | IOWR_MASK ;
COMPACT_FLASH_RESET_ACTIVE;
COMPACT_FLASH_POWER_DISABLE;
CS0_INACTIVE;
CS1_INACTIVE;
SysTick_Config(SystemCoreClock/100);
NVIC_SetVector(SysTick_IRQn, (uint32_t)(&disk_timerproc));
}
/*-----------------------------------------------------------------------*/
/* Read an ATA register */
/*-----------------------------------------------------------------------*/
static
BYTE read_ata (
BYTE reg /* Register to be read */
)
{
BYTE rd;
CS0_ACTIVE;
SET_DATA_BUS_AS_INPUTS;
SET_CF_ADDRESS(reg);
IORD_ACTIVE;
__nop();
__nop();
__nop();
__nop();
GET_CF_DATA(rd);
__nop();
__nop();
__nop();
__nop();
IORD_INACTIVE;
CS0_INACTIVE;
#ifdef _CF_DEBUG_READ_ATA
CF_DEBUG("rd 0x%2x\r\n",rd);
#endif
return rd;
}
/*-----------------------------------------------------------------------*/
/* Write a byte to an ATA register */
/*-----------------------------------------------------------------------*/
static
void write_ata (
BYTE reg, /* Register to be written */
BYTE dat /* Data to be written */
)
{
__nop();
CS0_ACTIVE;
SET_DATA_BUS_AS_OUTPUTS;
SET_CF_ADDRESS(reg);
SET_CF_DATA(dat);
IOWR_ACTIVE;
__nop();
__nop();
__nop();
__nop();
IOWR_INACTIVE;
__nop();
__nop();
__nop();
__nop();
CS0_INACTIVE;
SET_DATA_BUS_AS_INPUTS;
}
/*-----------------------------------------------------------------------*/
/* Read a part of data block */
/*-----------------------------------------------------------------------*/
static
void read_part (
BYTE *buff, /* Data buffer to store read data */
BYTE ofs, /* Offset of the part of data in unit of word */
BYTE count /* Number of word to pick up */
)
{
BYTE c = 0, dl, dh;
SET_CF_ADDRESS(REG_DATA); /* Select Data register */
__nop();
__nop();
SET_DATA_BUS_AS_INPUTS;
CS0_ACTIVE;
__nop();
__nop();
do {
IORD_ACTIVE; /* IORD = L */
__nop();
__nop();
__nop();
__nop();
GET_CF_DATA(dl); /* Read Even data */
IORD_INACTIVE; /* IORD = H */
__nop();
__nop();
__nop();
__nop();
IORD_ACTIVE; /* IORD = L */
__nop();
__nop();
__nop();
__nop();
GET_CF_DATA(dh); /* Read Odd data */
IORD_INACTIVE; /* IORD = H */
__nop();
__nop();
__nop();
__nop();
if (count && (c >= ofs)) { /* Pick up a part of block */
*buff++ = dl;
*buff++ = dh;
count--;
}
} while (++c);
CS0_INACTIVE;
read_ata(REG_ALTSTAT);
read_ata(REG_STATUS);
}
/*-----------------------------------------------------------------------*/
/* Wait for Data Ready */
/*-----------------------------------------------------------------------*/
static
int wait_data (void)
{
BYTE s;
DiskProcTimer[CF] = 100; /* Time out = 1 sec */
do {
if (!DiskProcTimer[CF]) return 0; /* Abort when timeout occured */
s = read_ata(REG_STATUS); /* Get status */
} while ((s & (BUSY|DRQ)) != DRQ); /* Wait for BUSY goes low and DRQ goes high */
read_ata(REG_ALTSTAT);
return 1;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0) */
)
{
DSTATUS RetVal;
switch(drv)
{
case COMPACT_FLASH:
Stat[CF] |= STA_NOINIT;
for (DiskProcTimer[CF] = 10; DiskProcTimer[CF]; ); /* 100ms */
if (Stat[CF] & STA_NODISK) return Stat[CF]; /* Exit when socket is empty */
COMPACT_FLASH_POWER_ENABLE; /* Initialize CFC control port */
for (DiskProcTimer[CF] = 1;DiskProcTimer[CF]; ); /* 10ms */
SET_DATA_BUS_AS_INPUTS;
for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; ); /* 50ms */
COMPACT_FLASH_RESET_INACTIVE;
for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; ); /* 50ms */
write_ata(REG_DEV, LBA); /* Select Device 0 */
DiskProcTimer[CF] = 200;
do { /* Wait for card goes ready */
if (!DiskProcTimer[CF])
{
CF_DEBUG("Timeout waiting for card BUSY to go inactive\r\n");
return Stat[CF];
}
} while (read_ata(REG_STATUS) & BUSY);
write_ata(REG_DEVCTRL, SRST | nIEN); /* Software reset */
for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; ); /* 20ms */
write_ata(REG_DEVCTRL, nIEN); /* Release software reset */
for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; ); /* 20ms */
DiskProcTimer[CF] = 200;
do { /* Wait for card goes ready */
if (!DiskProcTimer[CF])
{
CF_DEBUG("Timeout waiting for card DRDY\r\n");
return Stat[CF];
}
} while ((read_ata(REG_STATUS) & (DRDY|BUSY)) != DRDY);
CF_DEBUG("Setting to 8-bit PIO MOD\r\n");
write_ata(REG_FEATURES, 0x01); /* Select 8-bit PIO transfer mode */
write_ata(REG_COMMAND, CMD_SETFEATURES);
DiskProcTimer[CF] = 200;
do {
if (!DiskProcTimer[CF])
{
CF_DEBUG("Timeout waiting after trying to call the SETFEATURES command\r\n");
return Stat[CF];
}
} while (read_ata(REG_STATUS) & (BUSY | ERR));
Stat[CF] &= ~STA_NOINIT; /* When device goes ready, clear STA_NOINIT */
RetVal = Stat[CF];
break;
case USB:
if(USB_Disk_Detected)
{
TERMINAL_PRINTF("USB Disk Detected.\r\n");
Stat[USB] &= ~(STA_NOINIT | STA_NODISK);
}
else
{
TERMINAL_PRINTF("USB Disk not attached.\r\n");
Stat[USB] |= STA_NOINIT | STA_NODISK;
}
RetVal = Stat[USB];
break;
case RAM:
Stat[RAM] &= ~STA_NOINIT;
RetVal = Stat[RAM];
break;
default:
RetVal = STA_NOINIT;
break;
}
return RetVal;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv
)
{
DSTATUS RetVal;
switch(drv)
{
case CF:
RetVal = Stat[CF];
break;
case USB:
RetVal = Stat[USB];
break;
case RAM:
RetVal = Stat[RAM];
break;
default:
RetVal = STA_NOINIT;
break;
}
return RetVal;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
BYTE c;
DWORD i;
switch(drv)
{
case CF:
if (Stat[CF] & STA_NOINIT) return RES_NOTRDY;
/* Issue Read Setor(s) command */
write_ata(REG_COUNT, count);
write_ata(REG_SECTOR, (BYTE)sector);
write_ata(REG_CYLL, (BYTE)(sector >> 8));
write_ata(REG_CYLH, (BYTE)(sector >> 16));
write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
write_ata(REG_COMMAND, CMD_READ);
do {
if (!wait_data()) return RES_ERROR; /* Wait data ready */
SET_CF_ADDRESS(REG_DATA);
__nop();
__nop();
__nop();
__nop();
CS0_ACTIVE;
c = 0;
__nop();
__nop();
__nop();
SET_DATA_BUS_AS_INPUTS;
do {
IORD_ACTIVE; /* IORD = L */
__nop();
__nop();
__nop();
GET_CF_DATA(*buff++); /* Get even data */
__nop();
__nop();
__nop();
__nop();
__nop();
__nop();
IORD_INACTIVE; /* IORD = H */
__nop();
__nop();
__nop();
IORD_ACTIVE; /* IORD = L */
__nop();
__nop();
__nop();
GET_CF_DATA(*buff++); /* Get Odd data */
__nop();
__nop();
__nop();
__nop();
IORD_INACTIVE; /* IORD = H */
__nop();
__nop();
__nop();
} while (--c);
} while (--count);
CS0_INACTIVE;
read_ata(REG_ALTSTAT);
read_ata(REG_STATUS);
return RES_OK;
break;
case USB:
if(MassStorage_Read(sector, 1,(u8 *) buff, 512) == 0)
return RES_OK;
else
return RES_NOTRDY;
break;
case RAM:
for(i=0;i<512;i++)
{
buff[i] = RAM_DISK[i];
}
return RES_OK;
break;
default:
return RES_PARERR;
break;
}
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE drv, /* Physical drive number (0) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
BYTE s, c;
DWORD i;
DRESULT RetVal;
switch(drv)
{
case CF:
/* Issue Write Setor(s) command */
write_ata(REG_COUNT, count);
write_ata(REG_SECTOR, (BYTE)sector);
write_ata(REG_CYLL, (BYTE)(sector >> 8));
write_ata(REG_CYLH, (BYTE)(sector >> 16));
write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
write_ata(REG_COMMAND, CMD_WRITE);
do {
if (!wait_data()) return RES_ERROR;
SET_CF_ADDRESS(REG_DATA);
__nop();
__nop();
__nop();
CS0_ACTIVE;
__nop();
__nop();
__nop();
SET_DATA_BUS_AS_OUTPUTS;
c = 0;
do {
SET_CF_DATA(*buff++); /* Set even data */
__nop();
__nop();
__nop();
IOWR_ACTIVE; /* IOWR = L */
__nop();
__nop();
__nop();
IOWR_INACTIVE; /* IOWR = H */
__nop();
__nop();
__nop();
SET_CF_DATA(*buff++); /* Set odd data */
__nop();
__nop();
__nop();
IOWR_ACTIVE; /* IOWR = L */
__nop();
__nop();
__nop();
IOWR_INACTIVE; /* IOWR = H */
__nop();
__nop();
__nop();
} while (--c);
} while (--count);
SET_DATA_BUS_AS_INPUTS;
CS0_INACTIVE;
DiskProcTimer[CF] = 100;
do {
if (!DiskProcTimer[CF]) return RES_ERROR;
s = read_ata(REG_STATUS);
} while (s & BUSY);
if (s & ERR) return RES_ERROR;
read_ata(REG_ALTSTAT);
read_ata(REG_STATUS);
RetVal = RES_OK;
break;
case USB:
if( MassStorage_Write(sector, 1, (u8 *)buff, 512) == 0)
RetVal = RES_OK;
else
RetVal = RES_NOTRDY;
break;
case RAM:
for(i=0;i<512;i++)
{
RAM_DISK[i] = buff[i];
}
RetVal = RES_OK;
break;
default:
RetVal = RES_PARERR;
break;
}
return RetVal;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive data block */
)
{
BYTE n, w, ofs, dl, dh, *ptr = (BYTE *)buff;
switch(drv)
{
case CF:
switch (ctrl)
{
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
ofs = 60; w = 2; n = 0;
break;
case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */
*(DWORD*)buff = 32;
return RES_OK;
break;
case CTRL_SYNC : /* Nothing to do */
return RES_OK;
break;
case ATA_GET_REV : /* Get firmware revision (8 chars) */
ofs = 23; w = 4; n = 4;
break;
case ATA_GET_MODEL : /* Get model name (40 chars) */
ofs = 27; w = 20; n = 20;
break;
case ATA_GET_SN : /* Get serial number (20 chars) */
ofs = 10; w = 10; n = 10;
break;
default:
return RES_PARERR;
}
write_ata(REG_COMMAND, CMD_IDENTIFY);
if (!wait_data()) return RES_ERROR;
read_part(ptr, ofs, w);
while (n--)
{
dl = *ptr; dh = *(ptr+1);
*ptr++ = dh; *ptr++ = dl;
}
return RES_OK;
break;
case USB:
if (USB_Disk_Detected == 0)
{
// TERMINAL_PRINTF("USB Disk not attached\r\n");
return RES_ERROR;
}
else
{
Stat[USB] &= ~STA_NOINIT;
switch (ctrl)
{
case GET_SECTOR_COUNT:
/* if(MassStorage_ReadCapacity(USB_Disk_Device, &BlockCount, &BlockSize) == 0)
{
*(DWORD *)(buff) = BlockCount;
}
else
{
return RES_ERROR;
}*/
return RES_OK;
break;
case GET_BLOCK_SIZE :
/* if(MassStorage_ReadCapacity(USB_Disk_Device, &BlockCount, &BlockSize) == 0)
{
*(DWORD *)(buff) = BlockSize;
return RES_OK;
}
else
{
return RES_ERROR;
}*/
return RES_OK;
break;
case CTRL_SYNC :
return RES_OK;
break;
case ATA_GET_REV :
strcpy ((CHAR *)buff,"00000");
return RES_OK;
break;
case ATA_GET_MODEL :
strcpy ((CHAR *)buff, "000000");
return RES_OK;
break;
case ATA_GET_SN :
strcpy ((CHAR *)buff,"00000000");
return RES_OK;
break;
default:
return RES_PARERR;
}
}
break;
case RAM:
switch (ctrl)
{
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
*(DWORD *)(buff) = 1;
break;
case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */
*(DWORD *)(buff) = 1;
return RES_OK;
break;
case CTRL_SYNC : /* Nothing to do */
return RES_OK;
break;
case ATA_GET_REV : /* Get firmware revision (8 chars) */
strcpy ((CHAR *)buff,"Rev 0.01");
break;
case ATA_GET_MODEL : /* Get model name (40 chars) */
strcpy ((CHAR *)buff,"Wavenumber RAM Drive");
break;
case ATA_GET_SN : /* Get serial number (20 chars) */
strcpy ((CHAR *)buff,"12345");
break;
default:
return RES_PARERR;
}
return RES_OK;
break;
default:
return RES_PARERR;
break;
}
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Device timer interrupt procedure */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms */
void disk_timerproc (void)
{
static BYTE pv;
BYTE n;
n = DiskProcTimer[CF]; /* 100Hz decrement timer */
if (n) DiskProcTimer[CF] = --n;
n = DiskProcTimer[USB]; /* 100Hz decrement timer */
if (n) DiskProcTimer[USB] = --n;
n = DiskProcTimer[RAM]; /* 100Hz decrement timer */
if (n) DiskProcTimer[RAM] = --n;
n = pv;
pv = COMPACT_FLASH_CARD_DETECTED ; /* Sapmle socket switch */
//Check Compact Flash Card Detect
if (n == pv) { /* Have contacts stabled? */
if (!COMPACT_FLASH_CARD_DETECTED )
{ /* CD1 or CD2 is high (Socket empty) */
Stat[CF] |= (STA_NODISK | STA_NOINIT);
SET_DATA_BUS_TO_INPUTS; /* Float D0-D7 */
COMPACT_FLASH_RESET_ACTIVE; /* Assert RESET# */
COMPACT_FLASH_POWER_DISABLE; /* Power OFF */
LED1_OFF;
}
else
{ /* CD1 and CD2 are low (Card inserted) */
Stat[CF] &= ~STA_NODISK;
LED1_ON;
}
}
//Check to see if a USB drive is connected
if(USB_Disk_Detected>0)
LED2_ON;
else
LED2_OFF;
}
DWORD get_fattime(void)
{
time_t CurrentTimeStamp;
tm *CurrentLocalTime;
DWORD FATFSTimeCode;
CurrentTimeStamp = time(NULL);
CurrentLocalTime = localtime(&CurrentTimeStamp);
//Map the tm struct time into the FatFs time code
FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) |
((CurrentLocalTime->tm_mon+1)<<21) |
((CurrentLocalTime->tm_mday)<<16) |
((CurrentLocalTime->tm_hour)<<11) |
((CurrentLocalTime->tm_min)<<5) |
((CurrentLocalTime->tm_sec));
return FATFSTimeCode;
}