int load_wav ( FIL *fp, /* Pointer to the open file object to play */ const char *title, /* Title (file name, etc...) */ void *work, /* Pointer to working buffer (must be-4 byte aligned) */ UINT sz_work /* Size of working buffer (must be power of 2) */ ) { UINT md, wi, br, tc, t, btr; DWORD sz, ssz, offw, szwav, wsmp, fsmp, eof; WAVFIFO fcb; BYTE k, *buff = work; char *p, nam[NBSIZE], art[NBSIZE]; //xprintf(PSTR("%s\n"), title); /* Put title */ /* Is it a WAV file? */ if (f_read(fp, buff, 12, &br) || br != 12) return -1; if (LD_DWORD(&buff[0]) != FCC('R','I','F','F')) return -1; if (LD_DWORD(&buff[8]) != FCC('W','A','V','E')) return -1; eof = LD_DWORD(&buff[4]) + 8; /* Analyze the RIFF-WAVE header and get properties */ nam[0] = art[0] = 0; md = fsmp = wsmp = offw = szwav = 0; while (f_tell(fp) < eof) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; sz = (LD_DWORD(&buff[4]) + 1) & ~1; switch (LD_DWORD(&buff[0])) { case FCC('f','m','t',' ') : if (sz > 1000 || sz < 16 || f_read(fp, buff, sz, &br) || sz != br) return -1; if (LD_WORD(&buff[0]) != 0x1) return -1; /* Check if LPCM */ if (LD_WORD(&buff[2]) == 2) { /* Channels (1 or 2) */ md = 1; wsmp = 2; } else { md = 0; wsmp = 1; } if (LD_WORD(&buff[14]) == 16) { /* Resolution (8 or 16) */ md |= 2; wsmp *= 2; } fsmp = LD_DWORD(&buff[4]); /* Sampling rate */ break; case FCC('f','a','c','t') : f_lseek(fp, f_tell(fp) + sz); break; case FCC('d','a','t','a') : offw = f_tell(fp); /* Wave data start offset */ szwav = sz; /* Wave data length [byte] */ f_lseek(fp, f_tell(fp) + sz); break; case FCC('L','I','S','T'): sz += f_tell(fp); if (f_read(fp, buff, 4, &br) || br != 4) return -1; if (LD_DWORD(buff) == FCC('I','N','F','O')) { /* LIST/INFO chunk */ while (f_tell(fp) < sz) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; ssz = (LD_DWORD(&buff[4]) + 1) & ~1; p = 0; switch (LD_DWORD(buff)) { case FCC('I','N','A','M'): /* INAM sub-chunk */ p = nam; break; case FCC('I','A','R','T'): /* IART sub-cnunk */ p = art; break; } if (p && ssz <= NBSIZE) { if (f_read(fp, p, ssz, &br) || br != ssz) return -1; } else { if (f_lseek(fp, f_tell(fp) + ssz)) return -1; } } } else { if (f_lseek(fp, sz)) return -1; /* Skip unknown sub-chunk type */ } break; default : /* Unknown chunk */ return -1; } } if (!szwav || !fsmp) return -1; /* Check if valid WAV file */ if (f_lseek(fp, offw)) return -1; /* Seek to top of wav data */ tc = (UINT)(szwav / fsmp / wsmp); /* Length (sec) */ //xprintf(PSTR("IART=%s\nINAM=%s\n"), art, nam); //xprintf(PSTR("Sample=%u.%ukHz/%ubit/%S\nLength=%u:%02u\n"), (UINT)(fsmp / 1000), (UINT)(fsmp / 100) % 10, (md & 2) ? 16 : 8, (md & 1) ? PSTR("st") : PSTR("mo"), tc / 60, tc % 60); /* Initialize stream parameters and start sound streming */ fcb.mode = md; fcb.buff = buff; fcb.sz_buff = sz_work; if (!sound_start(&fcb, fsmp)) return -1; k = 0; wi = 0; while (szwav || fcb.ct >= 4) { if (szwav && fcb.ct <= sz_work / 2) { /* Refill FIFO when it gets half empty */ btr = (szwav >= sz_work / 2) ? sz_work / 2 : szwav; f_read(fp, &buff[wi], btr, &br); if (br != btr) break; szwav -= br; wi = (wi + br) & (sz_work - 1); cli(); fcb.ct += br; sei(); } //if (uart_test()) { /* Exit if a command arrived */ // k = uart_getc(); // break; //} if (btn_check_press() == BTN2) { sound_stop(); break; } t = (f_tell(fp) - offw - fcb.ct) / fsmp / wsmp; /* Refresh time display every 1 sec */ if (t != tc) { tc = t; //xprintf(PSTR("\rTime=%u:%02u"), tc / 60, tc % 60); } } sound_stop(); /* Stop sound output */ //xputc('\n'); return k; /* Terminated due to -1:error, 0:eot, >0:key code */ }
static DWORD load_header (void) /* 0:Invalid format, 1:I/O error, >=1024:Number of samples */ { DWORD sz, f; BYTE b, al = 0; if (pf_read(Buff, 12, &rb)) return 1; /* Load file header (12 bytes) */ if (rb != 12 || LD_DWORD(Buff+8) != FCC('W','A','V','E')) return 0; for (;;) { wdt_reset(); pf_read(Buff, 8, &rb); /* Get Chunk ID and size */ if (rb != 8) return 0; sz = LD_DWORD(&Buff[4]); /* Chunk size */ switch (LD_DWORD(&Buff[0])) { /* Switch by chunk ID */ case FCC('f','m','t',' ') : /* 'fmt ' chunk */ if (sz & 1) sz++; /* Align chunk size */ if (sz > 100 || sz < 16) return 0; /* Check chunk size */ pf_read(Buff, sz, &rb); /* Get content */ if (rb != sz) return 0; if (Buff[0] != 1) return 0; /* Check coding type (LPCM) */ b = Buff[2]; if (b != 1 && b != 2) return 0; /* Check channels (1/2) */ GPIOR0 = al = b; /* Save channel flag */ b = Buff[14]; if (b != 8 && b != 16) return 0; /* Check resolution (8/16 bit) */ GPIOR0 |= b; /* Save resolution flag */ if (b & 16) al <<= 1; f = LD_DWORD(&Buff[4]); /* Check sampling freqency (8k-48k) */ if (f < 8000 || f > 48000) return 4; OCR0A = (BYTE)(F_CPU / 8 / f) - 1; /* Set sampling interval */ break; case FCC('d','a','t','a') : /* 'data' chunk */ if (!al) return 0; /* Check if format is valid */ if (sz < 1024 || (sz & (al - 1))) return 0; /* Check size */ if (Fs.fptr & (al - 1)) return 0; /* Check word alignment */ return sz; /* Start to play */ case FCC('D','I','S','P') : /* 'DISP' chunk */ case FCC('L','I','S','T') : /* 'LIST' chunk */ case FCC('f','a','c','t') : /* 'fact' chunk */ if (sz & 1) sz++; /* Align chunk size */ pf_lseek(Fs.fptr + sz); /* Skip this chunk */ break; default : /* Unknown chunk */ return 0; } } return 0; }
static DWORD loadheader (FIL* fp) /* 0:Invalid format, 1:I/O error, >=1024:Number of samples */ { DWORD sz, f; BYTE b; UINT rb; if (f_read(fp, buffer, 12, &rb) != FR_OK) return 1; /* Load file header (12 bytes) */ if (rb != 12 || LD_DWORD(buffer+8) != FCC('W','A','V','E')) return 0; for (;;) { f_read(fp, buffer, 8, &rb); /* Get Chunk ID and size */ if (rb != 8) return 0; sz = LD_DWORD(&buffer[4]); /* Chunk size */ switch (LD_DWORD(&buffer[0])) { /* Switch by chunk ID */ case FCC('f','m','t',' ') : /* 'fmt ' chunk */ if (sz & 1) sz++; /* Align chunk size */ if (sz > 100 || sz < 16) return 0; /* Check chunk size */ f_read(fp, buffer, sz, &rb); /* Get content */ if (rb != sz) return 0; if (buffer[0] != 1) return 0; /* Check coding type (LPCM) */ b = buffer[2]; if (b != 1) return 0; /* Mono Only */ b = buffer[14]; if (b != 8) return 0; /* resolution 8bit only */ f = LD_DWORD(&buffer[4]); /* Check sampling freqency (8k-48k) */ if (f != 8000) return 4; /* 8kHz only */ break; case FCC('d','a','t','a') : /* 'data' chunk */ if (sz < 1024) return 0; /* Check size */ return sz; /* Start to play */ case FCC('D','I','S','P') : /* 'DISP' chunk */ case FCC('L','I','S','T') : /* 'LIST' chunk */ case FCC('f','a','c','t') : /* 'fact' chunk */ if (sz & 1) sz++; /* Align chunk size */ f_lseek(fp, fp->fptr + sz); /* Skip this chunk */ break; default : /* Unknown chunk */ return 0; } } return 0; }
FRESULT pf_open ( const char *path /* Pointer to the file name */ ) { FRESULT res; DIR dj; BYTE sp[12], dir[32]; FATFS *fs = FatFs; if (!fs) return FR_NOT_ENABLED; /* Check file system */ fs->flag = 0; dj.fn = sp; res = follow_path(&dj, dir, path); /* Follow the file path */ if (res != FR_OK) return res; /* Follow failed */ if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */ return FR_NO_FILE; fs->org_clust = get_clust(dir); /* File start cluster */ fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ fs->fptr = 0; /* File pointer */ fs->flag = FA_OPENED; return FR_OK; }
static void get_fileinfo ( /* No return code */ DIR *dj, /* Pointer to the directory object */ BYTE *dir, /* 32-byte working buffer */ FILINFO *fno /* Pointer to store the file information */ ) { BYTE i, c; char *p; p = fno->fname; if (dj->sect) { for (i = 0; i < 8; i++) { /* Copy file name body */ c = dir[i]; if (c == ' ') break; if (c == 0x05) c = 0xE5; *p++ = c; } if (dir[8] != ' ') { /* Copy file name extension */ *p++ = '.'; for (i = 8; i < 11; i++) { c = dir[i]; if (c == ' ') break; *p++ = c; } } fno->fattrib = dir[DIR_Attr]; /* Attribute */ fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ } *p = 0; }
FRESULT pf_open ( const char *path /* Pointer to the file name */ ) { FRESULT res; DIR dj; BYTE sp[12], dir[32]; FATFS *fs = FatFs; if (!fs) /* Check file system */ return FR_NOT_ENABLED; fs->flag = 0; fs->buf = dir; dj.fn = sp; res = follow_path(&dj, path); /* Follow the file path */ if (res != FR_OK) return res; /* Follow failed */ if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */ return FR_NO_FILE; fs->org_clust = /* File start cluster */ #if _FS_FAT32 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | #endif LD_WORD(dir+DIR_FstClusLO); fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ fs->fptr = 0; /* File pointer */ fs->flag = FA_READ; return FR_OK; }
static CLUST get_cluster ( /* 0,>=2: successful, 1: failed */ CLUST clust /* Cluster# to get the link information */ ) { WORD wc, bc; DWORD fatsect; FATFS *fs = FatFs; if (clust >= 2 && clust < fs->max_clust) { /* Valid cluster# */ fatsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : bc = (WORD)clust * 3 / 2; if (!move_window(fatsect + bc / 512)) break; wc = fs->win[bc % 512]; bc++; if (!move_window(fatsect + bc / 512)) break; wc |= (WORD)fs->win[bc % 512] << 8; return (clust & 1) ? (wc >> 4) : (wc & 0xFFF); case FS_FAT16 : if (!move_window(fatsect + clust / 256)) break; return LD_WORD(&fs->win[((WORD)clust * 2) % 512]); #if _FAT32 case FS_FAT32 : if (!move_window(fatsect + clust / 128)) break; return LD_DWORD(&fs->win[((WORD)clust * 4) % 512]) & 0x0FFFFFFF; #endif } }
static DWORD get_cluster ( DWORD clust /* Cluster# to get the link information */ ) { WORD wc, bc; DWORD fatsect; FATFS *fs = FatFs; if ((clust >= 2) && (clust < fs->max_clust)) { /* Valid cluster# */ fatsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : bc = (WORD)clust * 3 / 2; if (!move_window(fatsect + bc / 512)) break; wc = fs->win[bc % 512]; bc++; if (!move_window(fatsect + bc / 512)) break; wc |= (WORD)fs->win[bc % 512] << 8; return (clust & 1) ? (wc >> 4) : (wc & 0xFFF); case FS_FAT16 : if (!move_window(fatsect + clust / 256)) break; return LD_WORD(&(fs->win[((WORD)clust * 2) % 512])); case FS_FAT32 : if (!move_window(fatsect + clust / 128)) break; return LD_DWORD(&(fs->win[((WORD)clust * 4) % 512])); } }
static DWORD load_header (void) /* 0:Invalid format, 1:I/O error, >1:Number of samples */ { DWORD sz; if (pf_read(Buff1, 12, &rb)) return 1; /* Load file header (12 bytes) */ if (rb != 12 || LD_DWORD(Buff1+8) != FCC('W','A','V','E')) return 0; for (;;) { pf_read(Buff1, 8, &rb); /* Get Chunk ID and size */ if (rb != 8) return 0; sz = LD_DWORD(&Buff1[4]); /* Chunk size */ switch (LD_DWORD(&Buff1[0])) { /* FCC */ case FCC('f','m','t',' ') : /* 'fmt ' chunk */ if (sz > 100 || sz < 16) return 0; /* Check chunk size */ pf_read(Buff1, sz, &rb); /* Get content */ if (rb != sz) return 0; if (Buff1[0] != 1) return 0; /* Check coding type (1) */ if (Buff1[2] != 1 && Buff1[2] != 2) /* Check channels (1/2) */ return 0; if (Buff1[14] != 8 && Buff1[14] != 16) /* Check resolution (8/16) */ return 0; OCR0A = (BYTE)(F_CPU/8/LD_WORD(&Buff1[4]))-1; /* Sampling freq */ break; case FCC('d','a','t','a') : /* 'data' chunk (start to play) */ return sz; case FCC('L','I','S','T') : /* 'LIST' chunk (skip) */ case FCC('f','a','c','t') : /* 'fact' chunk (skip) */ pf_lseek(Fs.fptr + sz); break; default : /* Unknown chunk (error) */ return 0; } } return 0; }
static CLUST get_fat ( /* 1:IO error, Else:Cluster status */ CLUST clst /* Cluster# to get the link information */ ) { BYTE buf[4]; FATFS *fs = FatFs; if (clst < 2 || clst >= fs->n_fatent) /* Range check */ return 1; switch (fs->fs_type) { #if _FS_FAT12 case FS_FAT12 : { UINT wc, bc, ofs; bc = (UINT)clst; bc += bc / 2; ofs = bc % 512; bc /= 512; if (ofs != 511) { if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break; } else { if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break; if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break; } wc = LD_WORD(buf); return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); } #endif #if _FS_FAT16 case FS_FAT16 : if (disk_readp(buf, fs->fatbase + clst / 256, ((UINT)clst % 256) * 2, 2)) break; return LD_WORD(buf); #endif #if _FS_FAT32 case FS_FAT32 : if (disk_readp(buf, fs->fatbase + clst / 128, ((UINT)clst % 128) * 4, 4)) break; return LD_DWORD(buf) & 0x0FFFFFFF; #endif } return 1; /* An error occured at the disk I/O layer */ }
FRESULT pf_mount ( FATFS *fs /* Pointer to new file system object */ ) { BYTE fmt, buf[36] = {0}; DWORD bsect, fsize, tsect, mclst; FatFs = 0; if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */ return FR_NOT_READY; /* Search FAT partition on the drive */ bsect = 0; fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */ if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */ /* Check a partition listed in top of the partition table */ if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */ fmt = 3; } else { if (buf[4]) { /* Is the partition existing? */ bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */ fmt = check_fs(buf, bsect); /* Check the partition */ } } } if (fmt == 3) return FR_DISK_ERR; if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */ /* Initialize the file system object */ if (disk_readp(buf, bsect, 13, sizeof (buf))) return FR_DISK_ERR; fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */ if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13); fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */ fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */ fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */ fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */ tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */ if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13); mclst = (tsect /* Last cluster# + 1 */ - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16 ) / fs->csize + 2; fs->n_fatent = (CLUST)mclst; fmt = 0; /* Determine the FAT sub type */ if (_FS_FAT12 && mclst < 0xFF7) fmt = FS_FAT12; if (_FS_FAT16 && mclst >= 0xFF8 && mclst < 0xFFF7) fmt = FS_FAT16; if (_FS_FAT32 && mclst >= 0xFFF7) fmt = FS_FAT32; if (!fmt) return FR_NO_FILESYSTEM; fs->fs_type = fmt; if (_FS_32ONLY || (_FS_FAT32 && fmt == FS_FAT32)) fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */ else fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */ fs->flag = 0; FatFs = fs; return FR_OK; }
int main (int argc, char* argv[]) { UINT csz; HANDLE wh; DWORD wb, szvol; int ai = 1, truncation = 0; const char *outfile; /* Initialize parameters */ if (argc >= 2 && *argv[ai] == '-') { if (!strcmp(argv[ai], "-t")) { truncation = 1; ai++; argc--; } else { argc = 0; } } if (argc < 3) { printf("usage: mkfatimg [-t] <source node> <output file> <volume size> [<cluster size>]\n" " -t: Truncate unused area for read only volume.\n" " <source node>: Source node\n" " <output file>: FAT volume image file\n" " <volume size>: Size of temporary volume size in unit of KiB\n" " <cluster size>: Size of cluster in unit of byte (default:512)\n" ); return 1; } strcpy(SrcPath, argv[ai++]); outfile = argv[ai++]; RamDiskSize = atoi(argv[ai++]) * 2; csz = (argc >= 5) ? atoi(argv[ai++]) : 512; /* Create an FAT volume */ f_mount(&FatFs, "", 0); if (f_mkfs("", 1, csz)) { printf("Failed to create FAT volume. Adjust volume size or cluster size.\n"); return 2; } /* Copy directory tree onto the FAT volume */ if (!maketree()) return 3; if (!Files) { printf("No file in the source directory."); return 3; } szvol = LD_WORD(RamDisk + BPB_TotSec16); if (!szvol) szvol = LD_DWORD(RamDisk + BPB_TotSec32); if (truncation) { DWORD ent, nent; DWORD szf, szfp, edf, edfp; DWORD szd, szdp, edd, eddp; /* Truncate unused root directory entries */ if (FatFs.fs_type != FS_FAT32) { printf("\nTruncating unused root directory area..."); for (nent = ent = 0; ent < FatFs.n_rootdir; ent++) { if (RamDisk[FatFs.dirbase * 512 + ent * 32]) nent = ent + 1; } szd = (nent + 15) / 16; szdp = FatFs.n_rootdir / 16; if (szd < szdp) { edd = FatFs.dirbase + szd; eddp = FatFs.database; MoveMemory(RamDisk + (edd * 512), RamDisk + (eddp * 512), (szvol - eddp) * 512); szvol -= szdp - szd; FatFs.database -= szdp - szd; ST_WORD(RamDisk + BPB_RootEntCnt, szd * 16); } } /* Truncate unused data area and FAT */ printf("\nTruncating unused data area..."); for (nent = ent = 2; ent < FatFs.n_fatent; ent++) { if (get_fat(&FatFs, ent)) nent = ent + 1; } switch (FatFs.fs_type) { case FS_FAT12: szf = (nent * 3 / 2 + (nent & 1) + 511) / 512; break; case FS_FAT16: szf = (nent * 2 + 511) / 512; if (nent - 2 < MIN_FAT16) nent = 0; break; default: szf = (nent * 4 + 511) / 512; if (nent - 2 < MIN_FAT32) nent = 0; break; } if (!nent) { printf("different FAT sub-type is needed. Adjust volume size or cluster size.\n"); return 3; } szfp = LD_WORD(RamDisk + BPB_FATSz16) * RamDisk[BPB_NumFATs]; if (!szfp) szfp = LD_DWORD(RamDisk + BPB_FATSz32) * RamDisk[BPB_NumFATs]; edf = FatFs.fatbase + szf; edfp = (FatFs.fs_type == FS_FAT32) ? FatFs.database : FatFs.dirbase; MoveMemory(RamDisk + (edf * 512), RamDisk + (edfp * 512), (szvol - edfp) * 512); szvol -= (szfp - szf) + FatFs.csize * (FatFs.n_fatent - nent); if (FatFs.fs_type == FS_FAT32) { ST_DWORD(RamDisk + BPB_FATSz32, szf); } else { ST_WORD(RamDisk + BPB_FATSz16, szf); } RamDisk[BPB_NumFATs] = 1; if (szvol < 0x10000) { ST_WORD(RamDisk + BPB_TotSec16, szvol); ST_DWORD(RamDisk + BPB_TotSec32, 0); } else { ST_WORD(RamDisk + BPB_TotSec16, 0); ST_DWORD(RamDisk + BPB_TotSec32, szvol); } } /* Output the FAT volume to the file */ printf("\nWriting output file..."); wh = CreateFile(outfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if (wh == INVALID_HANDLE_VALUE) { printf("Failed to create output file.\n"); return 4; } szvol *= 512; WriteFile(wh, RamDisk, szvol, &wb, 0); CloseHandle(wh); if (szvol != wb) { DeleteFile(argv[2]); printf("Failed to write output file.\n"); return 4; } printf("\n%u files and %u directories in a %u bytes of FAT volume.\n", Files, Dirs, szvol); return 0; }
void at_process(void) { unsigned char received; void (*worker)(void) = NULL; static unsigned char heartbeat = 0x55; ACTIVITYSTROBE(0); // port a holds the latched contents of the address bus a0-a3 // LatchAddressIn(); if (WASWRITE) LatchedAddress=LatchedAddressLast; //log0("%02X\n",LatchedAddress & ADDRESS_MASK); switch (LatchedAddress & ADDRESS_MASK) { case CMD_REG: { if (WASWRITE) { ReadDataPort(); received = LatchedData; #if (DEBUG_CMD) log0("AVR CMD=0x%02x\n", received); #endif // File Group 0x10-0x17, 0x30-0x37, 0x50-0x57, 0x70-0x77 // filenum = bits 6,5 // mask1 = 10011000 (test for file group command) // mask2 = 10011111 (remove file number) if ((received & 0x98) == 0x10) { filenum = (received >> 5) & 3; received &= 0x9F; } // Data Group 0x20-0x23, 0x24-0x27, 0x28-0x2B, 0x2C-0x2F // filenum = bits 3,2 // mask1 = 11110000 (test for data group command) // mask2 = 11110011 (remove file number) if ((received & 0xf0) == 0x20) { filenum = (received >> 2) & 3; received &= 0xF3; } #if (PLATFORM!=PLATFORM_AVR) WriteDataPort(STATUS_BUSY); // Busy handled in CPLD. #endif //log0("%02X\n",LatchedData); // Directory group, moved here 2011-05-29 PHS. // if (received == CMD_DIR_OPEN) { // reset the directory reader // // when 0x3f is read back from this register it is appropriate to // start sending cmd 1s to get items. // worker = WFN_DirectoryOpen; } else if (received == CMD_DIR_READ) { // get next directory entry // worker = WFN_DirectoryRead; } else if (received == CMD_DIR_CWD) { // set CWD // worker = WFN_SetCWDirectory; } // File group. // else if (received == CMD_FILE_CLOSE) { // close the open file, flushing any unwritten data // worker = WFN_FileClose; } else if (received == CMD_FILE_OPEN_READ) { // open the file with name in global data buffer // worker = WFN_FileOpenRead; } #ifdef INCLUDE_SDDOS else if (received == CMD_FILE_OPEN_IMG) { // open the file as backing image for virtual floppy drive // drive number in globaldata[0] followed by asciiz name. // worker = WFN_OpenSDDOSImg; } #endif else if (received == CMD_FILE_OPEN_WRITE) { // open the file with name in global data buffer for write // worker = WFN_FileOpenWrite; } else if (received == CMD_FILE_OPEN_RAF) { // open the file with name in global data buffer for write/append // worker = WFN_FileOpenRAF; } else if (received == CMD_FILE_DELETE) { // delete the file with name in global data buffer // worker = WFN_FileDelete; } else if (received == CMD_FILE_GETINFO) { // return file's status byte // worker = WFN_FileGetInfo; } else if (received == CMD_FILE_SEEK) { // seek to a location within the file // worker = WFN_FileSeek; } else if (received == CMD_INIT_READ) { // All data read requests must send CMD_INIT_READ before beggining reading // data from READ_DATA_PORT. After execution of this command the first byte // of data may be read from the READ_DATA_PORT. // WriteDataPort(globalData[0]); globalIndex = 1; LatchedAddress=READ_DATA_REG; } else if (received == CMD_INIT_WRITE) { // all data write requests must send CMD_INIT_WRITE here before poking data at // WRITE_DATA_REG // globalDataPresent is a flag to indicate whether data is present in the bfr. // globalIndex = 0; globalDataPresent = 0; } else if (received == CMD_READ_BYTES) { // Replaces READ_BYTES_REG // Must be previously written to latch reg. globalAmount = byteValueLatch; worker = WFN_FileRead; } else if (received == CMD_WRITE_BYTES) { // replaces WRITE_BYTES_REG // Must be previously written to latch reg. globalAmount = byteValueLatch; worker = WFN_FileWrite; } // // Exec a packet in the data buffer. else if (received == CMD_EXEC_PACKET) { worker = WFN_ExecuteArbitrary; } #ifdef INCLUDE_SDDOS // SDDOS/LBA operations // else if (received == CMD_LOAD_PARAM) { // load sddos parameters for read/write // globalData[0] = img num // globalData[1..4 incl] = 256 byte sector number globalCurDrive = globalData[0] & 3; globalLBAOffset = LD_DWORD(&globalData[1]); WriteDataPort(STATUS_OK); } if (received == CMD_GET_IMG_STATUS) { // retrieve sddos image status // globalData[0] = img num WriteDataPort(driveInfo[byteValueLatch & 3].attribs); } if (received == CMD_GET_IMG_NAME) { // retrieve sddos image names // worker = WFN_GetSDDOSImgNames; } else if (received == CMD_READ_IMG_SEC) { // read image sector // worker = WFN_ReadSDDOSSect; } else if (received == CMD_WRITE_IMG_SEC) { // write image sector // worker = WFN_WriteSDDOSSect; } else if (received == CMD_SER_IMG_INFO) { // serialise the current image information // worker = WFN_SerialiseSDDOSDrives; } else if (received == CMD_VALID_IMG_NAMES) { // validate the current sddos image names // worker = WFN_ValidateSDDOSDrives; } else if (received == CMD_IMG_UNMOUNT) { // unmount the selected drive // worker = WFN_UnmountSDDOSImg; } #endif // // Utility commands. // Moved here 2011-05-29 PHS else if (received == CMD_GET_CARD_TYPE) { // get card type - it's a slowcmd despite appearance disk_initialize(0); WriteDataPort(CardType); } else if (received == CMD_GET_PORT_DDR) // get portb direction register { WriteDataPort(IODDR); } else if (received == CMD_SET_PORT_DDR) // set portb direction register { IODDR = byteValueLatch; WriteEEPROM(EE_PORTBTRIS, byteValueLatch); WriteDataPort(STATUS_OK); } else if (received == CMD_READ_PORT) // read portb { WriteDataPort(IOPORT_R); } else if (received == CMD_WRITE_PORT) // write port B value { IOPORT_W = byteValueLatch; WriteEEPROM(EE_PORTBVALU, byteValueLatch); WriteDataPort(STATUS_OK); } else if (received == CMD_GET_FW_VER) // read firmware version { WriteDataPort(VSN_MAJ<<4|VSN_MIN); } else if (received == CMD_GET_BL_VER) // read bootloader version { WriteDataPort(blVersion); } else if (received == CMD_GET_CFG_BYTE) // read config byte { WriteDataPort(configByte); } else if (received == CMD_SET_CFG_BYTE) // write config byte { configByte = byteValueLatch; WriteEEPROM(EE_SYSFLAGS, configByte); WriteDataPort(STATUS_OK); } else if (received == CMD_READ_AUX) // read porta - latch & aux pin on dongle { WriteDataPort(LatchedAddress); } else if (received == CMD_GET_HEARTBEAT) { // get heartbeat - this may be important as we try and fire // an irq very early to get the OS hooked before its first // osrdch call. the psp may not be enabled by that point, // so we have to wait till it is. // WriteDataPort(heartbeat); heartbeat ^= 0xff; } } }
int load_wav ( FIL *fp, /* Pointer to the open file object to play */ const char *title, /* Title (file name, etc...) */ void *work, /* Pointer to working buffer (must be-4 byte aligned) */ uint32_t sz_work /* Size of working buffer (must be power of 2) */ ) { UINT md, wi, br, tc, t, btr; DWORD sz, ssz, offw, szwav, wsmp, fsmp, eof; WAVFIFO fcb; BYTE k, *buff = work; char *p, nam[NBSIZE], art[NBSIZE]; xprintf("**** RIFF-WAVE Player ****\nFile=%s\n", title); /* Put title */ /* Is this a WAV file? */ if (f_read(fp, buff, 12, &br) || br != 12) return -1; if (LD_DWORD(&buff[0]) != FCC('R','I','F','F')) return -1; if (LD_DWORD(&buff[8]) != FCC('W','A','V','E')) return -1; eof = LD_DWORD(&buff[4]) + 8; /* Analyze the RIFF-WAVE header and get properties */ nam[0] = art[0] = 0; md = fsmp = wsmp = offw = szwav = 0; while (f_tell(fp) < eof) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; sz = (LD_DWORD(&buff[4]) + 1) & ~1; switch (LD_DWORD(&buff[0])) { case FCC('f','m','t',' ') : /* fmt chunk */ if (sz > 1000 || sz < 16 || f_read(fp, buff, sz, &br) || sz != br) return -1; if (LD_WORD(&buff[0]) != 0x1) return -1; /* Check if LPCM or not */ if (LD_WORD(&buff[2]) == 2) { /* Check channels (1 or 2) */ md = 1; wsmp = 2; } else { md = 0; wsmp = 1; } if (LD_WORD(&buff[14]) == 16) { /* Resolution (8 or 16) */ md |= 2; wsmp *= 2; } fsmp = LD_DWORD(&buff[4]); /* Sampling rate */ break; case FCC('f','a','c','t') : /* fact chunk */ f_lseek(fp, f_tell(fp) + sz); break; case FCC('d','a','t','a') : /* data chunk */ offw = f_tell(fp); /* Wave data start offset */ szwav = sz; /* Size of wave data [byte] */ f_lseek(fp, f_tell(fp) + sz); break; case FCC('L','I','S','T'): /* LIST chunk */ sz += f_tell(fp); if (f_read(fp, buff, 4, &br) || br != 4) return -1; if (LD_DWORD(buff) == FCC('I','N','F','O')) { /* LIST/INFO sub-chunk */ while (f_tell(fp) < sz) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; ssz = (LD_DWORD(&buff[4]) + 1) & ~1; p = 0; switch (LD_DWORD(buff)) { case FCC('I','N','A','M'): /* INAM (name) field */ p = nam; break; case FCC('I','A','R','T'): /* IART (artist) field */ p = art; break; } if (p && ssz <= NBSIZE) { if (f_read(fp, p, ssz, &br) || br != ssz) return -1; } else { if (f_lseek(fp, f_tell(fp) + ssz)) return -1; } } } else { if (f_lseek(fp, sz)) return -1; /* Skip unknown sub-chunk */ } break; default : /* Unknown chunk */ return -1; } } if (!szwav || !fsmp) return -1; /* Check if valid WAV file */ if (f_lseek(fp, offw)) return -1; /* Seek to top of wav data */ tc = szwav / fsmp / wsmp; /* Length (sec) */ xprintf("IART=%s\nINAM=%s\n", art, nam); xprintf("Sample=%u.%ukHz/%ubit/%s\nLength=%u:%02u\n", fsmp / 1000, (fsmp / 100) % 10, (md & 2) ? 16 : 8, (md & 1) ? "Stereo" : "Mono", tc / 60, tc % 60); /* Initialize sound FIFO and start sound streming */ fcb.mode = md; /* Sampling: b0=mono(0)/stereo(1), b1=8bit(0)/16bit(1) */ fcb.buff = buff; /* Pointer to streaming buffer */ fcb.sz_buff = sz_work; /* Size of streaming buffer */ if (!sound_start(&fcb, fsmp)) return -1; /* Start sound streaming */ k = 0; wi = 0; while (szwav || fcb.ct >= 4) { /* Sount streaming loop */ if (szwav && fcb.ct <= sz_work / 2) { /* Refill FIFO when it gets half empty */ btr = (szwav >= sz_work / 2) ? sz_work / 2 : szwav; f_read(fp, &buff[wi], btr, &br); if (br != btr) break; /* Exit if illigal file termination or FS error */ szwav -= br; wi = (wi + br) & (sz_work - 1); IEN(CMT3, CMI3) = 0; /* Disable CMT3 compare match irq */ fcb.ct += br; IEN(CMT3, CMI3) = 1; /* Enable CMT3 compare match irq */ } if (scif_test()) { /* Exit if a user command arrived */ k = scif_getc(); break; } t = (f_tell(fp) - offw - fcb.ct) / fsmp / wsmp; /* Refresh time display every 1 sec */ if (t != tc) { tc = t; xprintf("\rTime=%u:%02u", tc / 60, tc % 60); } } sound_stop(); /* Stop sound streaming */ xputc('\n'); return k; /* Terminated due to -1:error, 0:eot, >0:key code */ }