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

📄 i2s.c

📁 linux 嵌入式原代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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 + -