📄 i2s.c
字号:
/* * Sample program for FR400 Companion Chip I2S axLinux driver. * * Copyright (C) 2002 AXE,Inc. * */#define K480 0#include <stdio.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#if K480#include "inc/fr400cc_i2s.h"#else#include <linux/fr400cc_i2s.h>#endif#define FREQOPT 1 /* 2003/Jan/15 */#define CFGCHK 1 /* 2002/Dec/20 */#define OPTCHK 1 /* 2002/Dec/19 */#include <sys/types.h>#include <sys/stat.h>#if FREQOPT#include <linux/fr400_io.h>#endif#define ONMEM 1 /* 2002/Oct/26 */#define I2S_THROUGH 1#if ONMEM/* * [memory map] * 0x00000000 - 0x01000000 kernel * 0x01000000 - 0x01c00000 i2s.c * 0x01c00000 - 0x03c00000 (don't use, broken??) * 0x03c00000 - 0x04000000 romdisk */#define TMPBUF_BASE 0x01000000#define TMPBUF_SIZE 0x02c00000static unsigned char *local_area = (unsigned char *)TMPBUF_BASE;static unsigned char *local_next = NULL;static FILE *local_fp = NULL;#endif#if K480#define MB 1048576char* PCMB;unsigned long PCMBcount = 0;#endif#if I2S_TIMEREC#define Tmrec I2S_Tmrec#endifstatic voidtm_dif( struct timeval *a, struct timeval *b, struct timeval *re){ re->tv_sec = a->tv_sec - b->tv_sec; re->tv_usec = a->tv_usec - b->tv_usec; while(re->tv_usec < 0){ re->tv_sec--; re->tv_usec += 1000000; }}static void *mmap_fd(int fd, int sz, int num){ void *start; int length, prot, flags, offset; start = NULL; length = sz * num; prot = PROT_READ | PROT_WRITE; flags = MAP_SHARED; offset = 0; return mmap(start, length, prot, flags, fd, offset);}static intsave(char *name, unsigned char *p, int n){ FILE *fp; int x; fp = fopen(name, "w"); if(fp == NULL) return -1; while(n>0){#if ONMEM if(fp != NULL && fp == local_fp){ bcopy(p, local_next, n); local_next += n; p += x; n -= x; continue; }#endif x = fwrite(p, 1, n, fp); if(x < 0){ fprintf(stderr, "fwrite x=%d\n", x); fclose(fp); return -1; } p += x; n -= x; }#if ONMEM if(fp != NULL && fp == local_fp){ fwrite(local_area, 1, local_next-local_area, fp); }#endif fclose(fp); return 0;}static intopt_chk(int ac, char **av, char *key){ int i; for(i=1; i<ac; i++){ if(strcmp(av[i], key) == 0) return i; } return 0;}static int add_sleep_save;static voidsave_buf(struct fr400i2s_read *inf, unsigned char *area, int unit_sz, int num, FILE *fp){ int idx, x;#if K480 char *s;#endif if(fp == NULL) return;#if K480 idx = inf->count % num; s = (char *)(area + unit_sz * idx); for(x = 0; x < unit_sz; x++){ *(PCMB+PCMBcount+x) = *(s + x); } PCMBcount += unit_sz;#else fprintf(stderr, "frm_cnt=%d ... ", inf->count); fflush(stderr); idx = inf->count % num;#if ONMEM if(fp != NULL && fp == local_fp){ bcopy(area + unit_sz * idx, local_next, unit_sz); local_next += unit_sz; }#else x = fwrite(area + unit_sz * idx, 1, unit_sz, fp); if(x != unit_sz){ fprintf(stderr, "save_buf: fwrite x=%d\n", x); return; }#endif if(add_sleep_save > 0) usleep(add_sleep_save * 1000); fprintf(stderr, "\n"); fflush(stderr);#endif}static void print_i2s_config(struct fr400i2s_config *cfg) { printf("ch=%d bit=%d freq=%d LR=%d div=%d ami=%d amo=%d\n", cfg->channel_n, cfg->bit, cfg->freq, cfg->exch_lr, cfg->div, cfg->ami, cfg->amo); printf("out: ch=%d bit=%d freq=%d LR=%d\n", cfg->out_channel_n, cfg->out_bit, cfg->out_freq, cfg->out_exch_lr); printf("fs=%d fl=%d sdmi=%d sdmo=%d\n", cfg->fs, cfg->fl, cfg->sdmi, cfg->sdmo);}static void print_i2s_bufinfo(struct fr400i2s_config *cfg) { printf("in_buf=%dx%d out_buf=%dx%d out_buf_offset=%d\n", cfg->buf_unit_sz, cfg->buf_num, cfg->out_buf_unit_sz, cfg->out_buf_num, cfg->out_buf_offset);}#if CFGCHKstatic int verbose = 0;static voidconfig_show(struct fr400i2s_config *cfg, int start_cmd){ print_i2s_config(cfg); print_i2s_bufinfo(cfg);}static intioctl_start(int fd, int start_cmd, unsigned long prm){ if(verbose){ struct fr400i2s_config cfg; if(ioctl(fd, I2SIOCGCFG, &cfg) != 0){ fprintf(stderr, "ioctl get cfg err\n"); return -1; } config_show(&cfg, start_cmd); } return ioctl(fd, start_cmd, prm);}#endif /* CFGCHK */static intout_work_set_dat(FILE *fp, int fd, unsigned char *area, struct fr400i2s_config *cfg, int idx){ int sz, x; idx %= cfg->out_buf_num; area += cfg->out_buf_offset; sz = cfg->out_buf_unit_sz; area += sz * idx;#if ONMEM bcopy(local_next, area, sz); local_next += sz;#else if((x = fread(area, 1, sz, fp)) < sz){ fprintf(stderr, "fread %d/%d\n", x, sz); return -1; }#endif if(ioctl(fd, I2SIOC_OUT_SDAT, idx) < 0){ fprintf(stderr, "ioctl sdat err\n"); return -1; } return 0;}static intselect_ut(int fd){ fd_set setr; int x; FD_ZERO(&setr); FD_SET(fd, &setr); if((x = select(fd+1, &setr, NULL, NULL, NULL)) < 0){ perror("select_ut"); return x; } if(FD_ISSET(fd, &setr)) return 0; /* OK */ return 1; /* yet */}static intout_work(int ac, char **av, int fn_idx, int fd, unsigned char *area, struct fr400i2s_config *cfg){ char *fname; struct stat st; FILE *fp; int blk_n, init_n, sdat_n, fin_n, sz, x; struct fr400i2s_read inf; fname = av[fn_idx]; if(stat(fname, &st) < 0){ fprintf(stderr, "stat err %s\n", fname); return -1; } blk_n = st.st_size / cfg->out_buf_unit_sz; if((fp = fopen(fname, "r")) == NULL){ fprintf(stderr, "can't fopen %s\n", fname); return -1; }#if ONMEM sz = st.st_size; if(fread(local_area, 1, sz, fp) < sz){ fprintf(stderr, "fread err\n"); fclose(fp); return -1; } local_next = local_area;#endif init_n = cfg->buf_num; if(blk_n < init_n) init_n = blk_n; for(sdat_n=0; sdat_n<init_n; sdat_n++){ if(out_work_set_dat(fp, fd, area, cfg, sdat_n) != 0){ fclose(fp); close(fd); return -1; } }#if CFGCHK if(ioctl_start(fd, I2SIOC_OUT_START, 0) != 0){#else if(ioctl(fd, I2SIOC_OUT_START, 0) != 0){#endif fprintf(stderr, "out_start err\n"); fclose(fp); close(fd); return -1; } for(;;){ while((x = select_ut(fd)) == 1); if(x < 0){ fclose(fp); close(fd); return -1; } sz = sizeof(inf); if((x = read(fd, (void*)&inf, sz)) < sz){ fprintf(stderr, "out read err %d/%d\n", x, sz); fclose(fp); close(fd); return -1; } switch(inf.stat){ case I2S_READ_STAT_IN: fprintf(stderr, "stat in ???\n"); break; case I2S_READ_STAT_OUT: break; } fin_n = inf.count; printf("out fin count %d\n", fin_n); if(fin_n >= blk_n) break; if(sdat_n < blk_n){ if(out_work_set_dat(fp, fd, area, cfg, sdat_n) != 0){ fclose(fp); close(fd); return -1; } sdat_n++; } } fclose(fp); close(fd); printf("out ok. (^_^)/~~~\n"); return 0;}#if I2S_THROUGHstatic voiddata_copy(int fd, struct fr400i2s_config *cfg, unsigned char *area_in, int in_idx, unsigned char *area_out, int *out_idxp){ int out_idx, n, out_offset, i; unsigned char *outp; out_idx = *out_idxp; area_in += cfg->buf_unit_sz * in_idx; outp = area_out + cfg->out_buf_unit_sz * out_idx; out_offset = 0; n = cfg->buf_unit_sz / 8; for(i=0; i<n; i++){ if(out_offset >= cfg->out_buf_unit_sz){ if(ioctl(fd, I2SIOC_OUT_SDAT, out_idx) != 0){ perror("out_sdat"); } out_idx++; out_idx %= cfg->out_buf_num; outp = area_out + cfg->out_buf_unit_sz * out_idx; out_offset = 0; bzero(outp, cfg->out_buf_unit_sz); } bcopy(&area_in[i*8], outp + out_offset, 8); out_offset += 8; } if(ioctl(fd, I2SIOC_OUT_SDAT, out_idx) != 0){ perror("out_sdat"); } out_idx++; out_idx %= cfg->out_buf_num; *out_idxp = out_idx;}static intthrough_work(int ac, char **av){ int fd; struct fr400i2s_config cfg; unsigned char *area, *area_out; struct fr400i2s_read rd; int in_idx, out_idx; fd = -1; if((fd = open("/dev/fr400cc_i2s", O_RDONLY)) < 0){ perror("open"); goto ERR; } if(ioctl(fd, I2SIOCGCFG, &cfg) != 0){ perror("gcfg"); goto ERR; } area = mmap_fd(fd, cfg.out_buf_unit_sz, cfg.out_buf_num); if(area == (void*) -1 || area == NULL){ fprintf(stderr, "mmap err\n"); goto ERR; } area_out = area + cfg.out_buf_offset; cfg.channel_n = 2; cfg.bit = 32; cfg.exch_lr = 1; cfg.out_channel_n = 2; cfg.out_bit = -16; cfg.amo = 1; cfg.out_exch_lr = 1; print_i2s_config(&cfg); if(ioctl(fd, I2SIOCSCFG, &cfg) != 0){ perror("scfg"); goto ERR; } if(ioctl(fd, I2SIOCGCFG, &cfg) != 0){ perror("gcfg2"); goto ERR; } print_i2s_bufinfo(&cfg);#if CFGCHK if(ioctl_start(fd, I2SIOCSTART, 0) != 0){#else if(ioctl(fd, I2SIOCSTART, 0) != 0){#endif perror("start"); goto ERR; } out_idx = 0; for(;;){ int x, sz; while((x = select_ut(fd)) == 1); if(x < 0) perror("out_sel"); sz = sizeof(rd); if((x = read(fd, (void*)&rd, sz)) < sz){ perror("read"); goto ERR; } switch(rd.stat){ case I2S_READ_STAT_IN:#if 0 printf("in %d\n", rd.count);#endif in_idx = rd.count % cfg.buf_num; data_copy(fd, &cfg, area, in_idx, area_out, &out_idx); if(rd.count == cfg.buf_num / 2){ printf("out start\n"); if(ioctl(fd, I2SIOC_OUT_START, 0) != 0){ perror("out_start"); goto ERR; } } break; case I2S_READ_STAT_OUT:#if 0 printf("out %d\n", rd.count);#endif break; } } close(fd); return 0;ERR: if(fd != -1) close(fd); return -1;}#endif /* I2S_THROUGH */static voidhelp(){ printf("-slow-save-test N (N: add sleep msec)\n"); printf("-o <save file name> (real time)\n"); printf("-ch N (1 or 2)\n"); printf("-bit N (8,16,32,-16,-18,-20,-24)\n"); printf("-lr\n"); printf("-sec N\n"); printf("-bufsz N\n"); printf("-tmo <time rec save file name>\n"); printf("gettimeofday-test\n"); printf("double-select-test\n"); printf("-ami N (input 0=i2s, 1=justify mode)\n"); printf("-amo N (output 0=i2s, 1=justify mode)\n"); printf("-if <input file name>\n");#if I2S_THROUGH printf("-through\n");#endif printf("-div N\n");#if CFGCHK printf("-v\n");#endif#if FREQOPT printf("-freq N\n"); printf("-pdk2\n");#endif printf("--help\n");}#if OPTCHK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -