Exemple #1
0
static void data_pump()
{
	ctrl_clr_set(CTRL_INTERRUPT, 0);
	spi_set(CmdSetRXNsamps, NRX_SAMPS-1);
	evDP(EC_EVENT, EV_DPUMP, -1, "dpump_init", evprintf("INIT: SPI CTRL_INTERRUPT %d",
		GPIO_READ_BIT(GPIO0_15)));

	while (1) {

		evDP(EC_EVENT, EV_DPUMP, -1, "data_pump", evprintf("SLEEPING: SPI CTRL_INTERRUPT %d",
			GPIO_READ_BIT(GPIO0_15)));
		TaskSleep(0);
		ctrl_clr_set(CTRL_INTERRUPT, 0);		// ack interrupt, and updates spi status
		evDP(EC_EVENT, EV_DPUMP, -1, "data_pump", evprintf("WAKEUP: SPI CTRL_INTERRUPT %d",
			GPIO_READ_BIT(GPIO0_15)));

		interrupt_task_last_run = timer_us64();
		evDP(EC_EVENT, EV_DPUMP, -1, "data_pump", evprintf("interrupt last run @%.6f ",
			(float) interrupt_task_last_run / 1000000));
		
		snd_service();
		
		for (int ch=0; ch < RX_CHANS; ch++) {
			rx_chan_t *rx = &rx_chan[ch];
			if (!rx->enabled) continue;
			conn_t *c = rx->conn;
			assert(c);
			if (c->task) {
				TaskWakeup(c->task, FALSE, 0);
			}
			#ifdef SND_SEQ_CHECK
			if (audio_dropped != last_audio_dropped) {
				send_msg(c, SM_NO_DEBUG, "MSG audio_dropped=%d", audio_dropped);
			}
			#endif
		}
		#ifdef SND_SEQ_CHECK
		if (audio_dropped != last_audio_dropped) last_audio_dropped = audio_dropped;
		#endif
	}
}
void spi_dev(SPI_SEL sel, SPI_MOSI *mosi, int tx_xfers, SPI_MISO *miso, int rx_xfers)
{
    int rx=0, tx=0;
    u4_t stat;
    SPI_T *txb = mosi->msg;
    SPI_T *rxb = miso->msg;
    
    assert(init);

	if (sel == SPI_BOOT) {
		GPIO_CLR_BIT(SPI0_CS1);
	}
	
	evSpiDev(EC_EVENT, EV_SPILOOP, -1, "spi_dev", evprintf("%s(%d) T%dx R%dx", (sel != SPI_HOST)? "BOOT" : cmds[mosi->data.cmd], mosi->data.cmd, tx_xfers, rx_xfers));

	if (use_spidev) {
		int spi_bytes = SPI_X2B(MAX(tx_xfers, rx_xfers));
		struct spi_ioc_transfer spi_tr;
		memset(&spi_tr, 0, sizeof spi_tr);
		spi_tr.tx_buf = (unsigned long) txb;
		spi_tr.rx_buf = (unsigned long) rxb;
		spi_tr.len = spi_bytes;
		spi_tr.delay_usecs = 0;
		spi_tr.speed_hz = speed;
		spi_tr.bits_per_word = SPI_BPW;		// zero also means 8-bits?
		spi_tr.cs_change = 0;
	
		int actual_rxbytes;
		if ((actual_rxbytes = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &spi_tr)) < 0) sys_panic("SPI_IOC_MESSAGE");
		check(actual_rxbytes == spi_bytes);
		if (actual_rxbytes != spi_bytes) printf("actual_rxbytes %d spi_bytes %d\n", actual_rxbytes, spi_bytes);
	} else {
		SPI0_CONF = FORCE | SPI_CONF(spi_clkg, spi_speed);		// add FORCE
		SPI0_CTRL = EN;
	
		static char pbuf[65536];
		char *p = pbuf;
		int evp_spi;
		#if defined(EV_MEAS_SPI_DEV) || defined(SPI_PUMP_CHECK)
			evp_spi = (sel == SPI_HOST);
		#else
			evp_spi = 0;
		#endif
		int evp = evp_spi;
		if (evp) p += sprintf(p, "T %p %p %d R %p %p %d ", mosi, txb, tx_xfers, miso, rxb, rx_xfers);
	
		while (tx < tx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & TX_FULL)) {
				if (evp) p += sprintf(p, "TA%d:%x ", tx, txb[tx]);
				SPI0_TX = txb[tx++];		// move data only if FIFOs are able to accept
			}
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RA%d:%x ", rx-1, rxb[rx-1]);
			}
		}
		// at this point all tx data in FIFO but rx data may or may not have been moved out of FIFO
		// if necessary send dummy tx words to force larger number of rx words to be pulled through
		while (tx < rx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & TX_FULL)) {
				if (evp) p += sprintf(p, "TB%d:Z ", tx);
				SPI0_TX = 0; tx++;
			}
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RB%d:%x ", rx-1, rxb[rx-1]);
			}
			if (tx == 8 && evp) {
				p += sprintf(p, "... ");
				evp = 0;
			}
			if (tx == (rx_xfers-3)) evp = evp_spi;
		}
			evp = evp_spi;
		
		// handles the case of the FIFOs being slightly out-of-sync given that
		// tx/rx words moved must eventually be equal
		#ifdef SPI_32XXX
		int spin=0, rfull=0;
		while (rx < rx_xfers) {
			stat = SPI0_STAT;
			if (stat & RX_FULL) rfull++;
			spin++;
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RC%d:%x ", rx-1, rxb[rx-1]);
				spin=0;
			}
			if ((rx == (rx_xfers-1)) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				rxb[rx++] = SPI0_RX;	// last doesn't show in fifo flags
				if (evp) p += sprintf(p, "RL%d:%x ", rx-1, rxb[rx-1]);
			}
			if ((spin > 1024) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				printf("%s STUCK: rfull %d rx %d rx_xfers %d stat %02x\n", TaskName(), rfull, rx, rx_xfers, stat);
				while (rx < rx_xfers) {
					rxb[rx++] = SPI0_RX;
				}
				break;
			}
		}
		#else
		while (rx < rx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RC%d:%x ", rx-1, rxb[rx-1]);
			}
			if ((rx == (rx_xfers-1)) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				rxb[rx++] = SPI0_RX;	// last doesn't show in fifo flags
				if (evp) p += sprintf(p, "RL%d:%x ", rx-1, rxb[rx-1]);
			}
		}
		#endif
	
		if (evp) evSpiDev(EC_EVENT, EV_SPILOOP, -1, "spi_dev", evprintf("%s", pbuf));
	
		while ((SPI0_STAT & TX_EMPTY) == 0)		// FIXME: needed for 6 MHz case, why?
			;
	
		while ((SPI0_STAT & EOT) == 0)		// FIXME: really needed?
			;
	
		SPI0_CTRL = 0;
		SPI0_CONF = SPI_CONF(spi_clkg, spi_speed);		// remove FORCE
	}

	if (sel == SPI_BOOT) {
		GPIO_SET_BIT(SPI0_CS1);
	}
}
Exemple #3
0
static void snd_service()
{
	int j;
	
	SPI_MISO *miso = &dp_miso;

	rx_data_t *rxd = (rx_data_t *) &miso->word[0];

	#ifdef SND_SEQ_CHECK
	rxd->magic = 0;
	#endif
	
	// use noduplex here because we don't want to yield
	evDPC(EC_TRIG3, EV_DPUMP, -1, "snd_svc", "CmdGetRX..");
	spi_get_noduplex(CmdGetRX, miso, sizeof(rx_data_t));
	evDPC(EC_EVENT, EV_DPUMP, -1, "snd_svc", "..CmdGetRX");

	evDP(EC_TRIG2, EV_DPUMP, -1, "snd_service", evprintf("SERVICED SEQ %d %%%%%%%%%%%%%%%%%%%%",
		rxd->seq));
	//evDP(EC_TRIG2, EV_DPUMP, 15000, "SND", "SERVICED ----------------------------------------");
	
	#ifdef SND_SEQ_CHECK
	if (rxd->magic != 0x0ff0) {
		evDPC(EC_EVENT, EV_DPUMP, -1, "DATAPUMP", evprintf("BAD MAGIC 0x%04x", rxd->magic));
		if (ev_dump) evDP(EC_DUMP, EV_DPUMP, ev_dump, "DATAPUMP", evprintf("DUMP in %.3f sec", ev_dump/1000.0));
	}
	
	if (!initial_seq) {
		seq = rxd->seq;
		initial_seq = true;
	}
	u2_t new_seq = rxd->seq;
	if (seq != new_seq) {
		//printf("$dp %d:%d(%d)\n", seq, new_seq, new_seq-seq);
		evDPC(EC_EVENT, EV_DPUMP, -1, "SEQ DROP", evprintf("$dp %d:%d(%d)", seq, new_seq, new_seq-seq));
		audio_dropped++;
		//TaskLastRun();
		bool dump = false;
		//bool dump = true;
		//bool dump = (new_seq-seq < 0);
		//bool dump = (audio_dropped == 6);
		if (dump && ev_dump) evNT(EC_DUMP, EV_NEXTTASK, ev_dump, "NextTask", evprintf("DUMP IN %.3f SEC",
			ev_dump/1000.0));
		seq = new_seq;
	}
	seq++;
	#endif

	TYPECPX *i_samps[RX_CHANS];
	for (j=0; j < RX_CHANS; j++) {
		rx_dpump_t *rx = &rx_dpump[j];
		i_samps[j] = rx->in_samps[rx->wr_pos];
	}

	rx_iq_t *iqp = (rx_iq_t*) &rxd->iq_t;

	for (j=0; j<NRX_SAMPS; j++) {

		for (int ch=0; ch < RX_CHANS; ch++) {
			if (rx_chan[ch].enabled) {
				s4_t i, q;
				i = S24_8_16(iqp->i3, iqp->i);
				q = S24_8_16(iqp->q3, iqp->q);
				
				// NB: i&q reversed to get correct sideband polarity; fixme: why?
				// [probably because mixer NCO polarity is wrong, i.e. cos/sin should really be cos/-sin]
				i_samps[ch]->re = q * rescale;
				i_samps[ch]->im = i * rescale;
				i_samps[ch]++;
			}
			iqp++;
		}
	}

	for (int ch=0; ch < RX_CHANS; ch++) {
		if (rx_chan[ch].enabled) {
			rx_dpump_t *rx = &rx_dpump[ch];
			rx->wr_pos = (rx->wr_pos+1) & (N_DPBUF-1);
		}
	}
}