Example #1
0
void dac_pop_rate_change(void) {
	int rate_consume = dac_rate_consume;
	if (rate_consume != dac_rate_produce) {
		dac_set_rate(dac_rate_buffer[rate_consume]);
		rate_consume++;
		if (rate_consume >= DAC_RATE_BUFFER_SIZE)
			rate_consume = 0;
		dac_rate_consume = rate_consume;
	}
}
Example #2
0
static void ilda_pps_FPV_param(const char *path, int32_t v) {
	char buf[6];
	snprintf(buf, sizeof(buf), "%ldk", v / 1000);
	osc_send_string("/ilda/ppsreadout", buf);

	if (playback_src != SRC_ILDAPLAYER)
		return;

	dac_set_rate(v);
	ilda_set_fps_limit(ilda_current_fps);
}
Example #3
0
/* wav_read_file_header
 *
 * Read the header for a WAV file, and save playback information.
 */
static int wav_read_file_header(int file_size) {

	/* fmt chunk */
	struct wav_header_part2 {
		uint32_t fmt_size;
		uint16_t audio_format;
		uint16_t num_channels;
		uint32_t sample_rate;
		uint32_t byte_rate;
		uint16_t block_align;
		uint16_t bits_per_sample;
	} __attribute__((packed)) pt2;
	fplay_read_check(&pt2, sizeof(pt2));

	if (pt2.fmt_size < 16) BAILV("audio fmt chunk too short: %d bytes", pt2.fmt_size);

	int is_extended;

	if (pt2.audio_format == 1)
		is_extended = 0;
	else if (pt2.audio_format == 0xFFFE)
		is_extended = 1;
	else
		BAILV("bad audio fmt: 0x%04x", pt2.audio_format);

	if (pt2.num_channels < 5 || pt2.num_channels > 8)
		BAILV("bad channel count: %d", pt2.num_channels);
	wav_channels = pt2.num_channels;
	int point_rate = pt2.sample_rate;
	if (pt2.byte_rate != point_rate * wav_channels * 2)
		BAIL("byte rate mismatch");
	if (pt2.block_align < wav_channels * 2)
		BAILV("block align too small: %d", pt2.block_align);
	if (pt2.block_align > 16)
		BAILV("block align too large: %d", pt2.block_align);
	wav_block_align = pt2.block_align;
	if (pt2.bits_per_sample != 16)
		BAIL("16-bit samples required");

	char buf[8];
	int fmt_size_left = pt2.fmt_size - 16;

	if (fmt_size_left >= 22 && is_extended) {
		fplay_read_check(buf, 8);
		uint16_t actual_type;
		fplay_read_check(&actual_type, 2);
		if (actual_type != 1)
			BAILV("bad extended audio fmt: 0x%04x", actual_type);
		fmt_size_left -= 10;
	} else if (is_extended)
		BAILV("extended hdr too short: need 22 bytes, got %d", fmt_size_left);

	/* Consume the rest of the format block, if any */
	while (fmt_size_left > 0) {
		fplay_read_check(buf, fmt_size_left > 8 ? 8 : fmt_size_left);
		fmt_size_left -= 8;
	}

	/* Now read data header */
	fplay_read_check(buf, 8);

	/* Ignore fact chunk if present */
	if (!memcmp(buf, "fact", 4)) {
		fplay_read_check(buf, 4);
		fplay_read_check(buf, 8);
	}
	
	if (memcmp(buf, "data", 4)) BAIL("no data header");

	int data_size = *(uint32_t *)(buf + 4);
	if (data_size > file_size - 36) data_size = file_size - 36;

	fplay_points_left = data_size / wav_block_align;
	ilda_frame_pointcount = fplay_points_left;
	fplay_repeat_count = 1;
	fplay_state = STATE_WAV;

	dac_set_rate(point_rate);

	/* Phew! */
	return 1;
}
Example #4
0
/* recv_fsm
 *
 * Attempt to process some data from the buffer located at 'data'.
 *
 * If a command is succcessfully read, then this returns the number of bytes
 * consumed from the buffer. If a partial command is present in the buffer,
 * but not enough to process yet, then this will return 0; the invoking
 * function should call it later when more data is available. If an error
 * occurs such that no further data can be handled from the connection, then
 * this will call close_conn on the connection and return -1.
 */
static int recv_fsm(struct tcp_pcb *pcb, uint8_t * data, int len) {
	uint8_t cmd = *data;
	int npoints;

	switch (ps_state) {
	case MAIN:
		switch (cmd) {
		case 'p':
			/* Prepare stream. */
			if (dac_prepare() < 0) {
				return send_resp(pcb, RESP_NAK_INVL, cmd, 1);
			} else {
				return send_resp(pcb, RESP_ACK, cmd, 1);
			}

		case 'b':
			/* Make sure we have all of this packet... */
			if (len < sizeof(struct begin_command))
				return 0;

			struct begin_command *bc = (struct begin_command *)data;

			if (bc->point_rate > DAC_MAX_POINT_RATE)
				return send_resp(pcb, RESP_NAK_INVL, cmd, 1);

// XXX			set_low_water_mark(bc->low_water_mark);
			dac_set_rate(bc->point_rate);
			dac_start();

			return send_resp(pcb, RESP_ACK, cmd,
					 sizeof(struct begin_command));

		case 'u':
			/* Update and Begin use the same packet format */
			if (len < sizeof(struct begin_command))
				return 0;

			struct begin_command *uc = (struct begin_command *)data;

			if (uc->point_rate > DAC_MAX_POINT_RATE)
				return send_resp(pcb, RESP_NAK_INVL, cmd, 1);

			dac_set_rate(uc->point_rate);
// XXX			set_low_water_mark(uc->low_water_mark);

			return send_resp(pcb, RESP_ACK, cmd, 
					 sizeof(struct begin_command));

		case 'q':
			if (len < sizeof(struct queue_command))
				return 0;

			struct queue_command *qc = (struct queue_command *)data;

			if (qc->point_rate > DAC_MAX_POINT_RATE)
				return send_resp(pcb, RESP_NAK_INVL, cmd, 1);

			dac_rate_queue(qc->point_rate);

			return send_resp(pcb, RESP_ACK, cmd, 
					 sizeof(struct queue_command));

		case 'd':
			/* Data: switch into the DATA state to start reading
			 * points into the buffer. */
			if (len < sizeof(struct data_command))
				return 0;

			struct data_command *h = (struct data_command *) data;

			if (h->npoints) {
				ps_state = DATA;
				ps_pointsleft = h->npoints;

				/* We'll send a response once we've read all
				 * of the data. */
				return sizeof(struct data_command);
			} else {
				/* 0-length data packets are legit. */
				return send_resp(pcb, RESP_ACK, cmd,
					sizeof(struct data_command));
			}

		case 's':
			/* Stop */
			if (dac_get_state() == DAC_IDLE) {
				return send_resp(pcb, RESP_NAK_INVL, cmd, 1);
			} else {
				dac_stop(0);
				return send_resp(pcb, RESP_ACK, cmd, 1);
			}

		case 0:
		case 0xFF:
			/* Emergency-stop. */
			le_estop(ESTOP_PACKET);
			return send_resp(pcb, RESP_ACK, cmd, 1);

		case 'c':
			/* Clear e-stop. */
			le_estop_clear(ESTOP_CLEAR_ALL);
			if (le_get_state() == LIGHTENGINE_READY)
				return send_resp(pcb, RESP_ACK, cmd, 1);
			else
				return send_resp(pcb, RESP_NAK_ESTOP, cmd, 1);

		case '?':
			/* Ping */
			return send_resp(pcb, RESP_ACK, cmd, 1);

		default:
			outputf("unknown cmd 0x%02x", cmd);
			return close_conn(pcb, CONNCLOSED_UNKNOWNCMD, -1);
		}

		return -1;

	case DATA:
		ASSERT_NOT_EQUAL(ps_pointsleft, 0);

		/* We can only write a complete point at a time. */
		if (len < sizeof(struct dac_point))
			return 0;

		/* How many bytes of data is it our business to write? */
		npoints = len / sizeof(struct dac_point);
		if (npoints > ps_pointsleft)
			npoints = ps_pointsleft;

		/* How much do we have room for now? Note that dac_prepare
		 * is a ring buffer, so it's OK if it returns less than the
		 * number of points we have ready for it. We'll just have
		 * the FSM invoke us again. */
		int nready = dac_request();
		packed_point_t *addr = dac_request_addr();

		/* On the other hand, if the DAC isn't ready for *any* data,
		 * then ignore the rest of this write command and NAK when
		 * it's over. The FSM will take care of us... */
		if (nready <= 0) {
			if (nready == 0) {
				outputf("overflow: wanted to write %d", npoints);
			} else {
				outputf("underflow: pl %d np %d r %d", ps_pointsleft, npoints, nready);
			}
			ps_state = DATA_ABORTING;

			/* Danger: goto. This could probably be structured
			 * better... */
			goto handle_aborted_data;
		}

		if (npoints > nready)
			npoints = nready;

		dac_point_t *pdata = (dac_point_t *)data;

		int i;
		for (i = 0; i < npoints; i++) {
			dac_pack_point(addr + i, pdata + i);
		}

		/* Let the DAC know we've given it more data */
		dac_advance(npoints);

		ps_pointsleft -= npoints;

		if (!ps_pointsleft) {
			ps_state = MAIN;
			return send_resp(pcb, RESP_ACK, 'd',
					 npoints * sizeof(struct dac_point));
		} else {
			return (npoints * sizeof(struct dac_point));
		}

	case DATA_ABORTING:
		ASSERT_NOT_EQUAL(ps_pointsleft, 0);

		/* We can only consume a complete point at a time. */
		if (len < sizeof(struct dac_point))
			return 0;

		/* How many points do we have? */
		npoints = len / sizeof(struct dac_point);
		if (npoints > ps_pointsleft)
			npoints = ps_pointsleft;

handle_aborted_data:
		ps_pointsleft -= npoints;

		if (!ps_pointsleft) {
			ps_state = MAIN;
			return send_resp(pcb, RESP_NAK_INVL, 'd',
					 npoints * sizeof(struct dac_point));
		} else {
			return (npoints * sizeof(struct dac_point));
		}

	default:
		break;
	}

	panic("invalid state in recv_dfa");
	return -1;
}
Example #5
0
int main(int argc, char **argv) {
	__disable_irq();

	LPC_GPIO2->FIODIR &= ~(1 << 8);
	LPC_SC->PCLKSEL0 = PCLKSEL0_INIT_VALUE;
	LPC_SC->PCLKSEL1 = PCLKSEL1_INIT_VALUE;
	LPC_SC->PCONP = PCONP_INIT_VALUE;
	clock_init();
	serial_init();

	/* Enable bus, usage, and mem faults. */
	SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk
		| SCB_SHCSR_USGFAULTENA_Msk;

#if 0
	/* Disable write buffers. This is useful for debugging - wild writes
	 * are imprecise exceptions unless the Cortex's write buffering is
	 * disabled. However, this has a significant performance hit, so it
	 * should only be set if necessary. */
	*((uint32_t *)0xE000E008) |= (1<<1);
#endif

	debugf("\r\n###############\r\n");
	debugf("# Ether Dream #\r\n");
	debugf("###############\r\n");
	debugf("Firmware: %s\r\n", build);

	debugf("RSID: %d\r\n", LPC_SC->RSID);
	LPC_SC->RSID = 0xF;

	hw_get_board_rev();
	debugf("Hardware Revision %d\n", hw_board_rev);

	debugf("Starting up: led");
	led_init();
	led_set_frontled(1);

	debugf(" skub");
	skub_init();

	debugf(" lwip\r\n");
	lwip_init();

	clock.time = 0;
	clock.mtime = 0;
	SysTick_Config(SystemCoreClock / 10000);

	/* Initialize hardware */
	FPA_init();

	outputf("Entering main loop...");
	watchdog_init();

	/* Startup might have taken some time, so reset the periodic event
	 * timers. */
	int i;
	for (i = 0; i < (sizeof(events) / sizeof(events[0])); i++) {
		events_last[i] = events[i].start + clock.time;
	}

	__enable_irq();

	playback_set_src(SRC_NETWORK);

	/* Default values */
	dac_set_rate(30000);
	ilda_set_fps_limit(30);

	while (1) {
		watchdog_feed();

		/* Check the stuff we check on each loop iteration. */
		for (i = 0; i < TABLE_LENGTH(poll); i++) {
			poll_table[i].f();
		}

		/* Check for periodic events */
		check_periodic_timers();

		if (f0ad_flag) {
			/* Re-enter the bootloader. */
			outputf("Reentering bootloader...");
			dac_stop(0);
			FORCE_BOOTLOAD_FLAG = FORCE_BOOTLOAD_VALUE;
			__disable_irq();

			/* The watchdog timer will kick us soon... */
			while(1);
		}
	}
}
Example #6
0
int main(int argc, char **argv) {
	time = 0;

	int i;

	SysTick_Config(SystemCoreClock / 10000);
	serial_init();

	/* LEDs */
	LPC_GPIO0->FIODIR |= (1 << 0);
	LPC_GPIO1->FIODIR |= (1 << 28);
	LPC_GPIO1->FIOSET = (1 << 28);
	LPC_GPIO1->FIODIR |= (1 << 29);

	outputf("=== j4cDAC ===");

	outputf("skub_init()");
	skub_init();

	outputf("lwip_init()");
	lwip_init();

	outputf("== hardware ==");

	for (i = 0; i < TABLE_LENGTH(hardware); i++) {
		outputf("%s()", hardware_table[i].name);
		hardware_table[i].f();
	}

	outputf("== protocol ==");

	for (i = 0; i < TABLE_LENGTH(protocol); i++) {
		outputf("%s()", protocol_table[i].name);
		protocol_table[i].f();
	}

	outputf("ilda player");
	ilda_open("ildatest.ild");

	outputf("Entering main loop...");

/*
	playback_src = SRC_ILDAPLAYER;
	playback_source_flags = ILDA_PLAYER_PLAYING | ILDA_PLAYER_REPEAT;
*/

	__enable_irq();

	int status = 0;

	for (i = 0; i < (sizeof(events) / sizeof(events[0])); i++) {
		events_last[i] = events[i].start + time;
	}

	dac_set_rate(12000);
	ilda_set_fps_limit(30);

	while (1) {
		/* If we're playing from something other than the network,
		 * refill the point buffer. */
		if (playback_src != SRC_NETWORK)
			playback_refill();

		if (!(LPC_GPIO1->FIOPIN & (1 << 26))) {
			outputf("Blocking...");
			while (!(LPC_GPIO1->FIOPIN & (1 << 26)));
		}


//		LPC_GPIO1->FIOCLR = (1 << 28);

		if (status) {
			LPC_GPIO0->FIOPIN = 1;
			LPC_GPIO1->FIOPIN = 0;
			status = 0;
		} else {
			LPC_GPIO0->FIOPIN = 0;
			LPC_GPIO1->FIOPIN = (1 << 29);
			status = 1;
		}

//		LPC_GPIO1->FIOSET = (1 << 28);

		/* Check for periodic events */
		for (i = 0; i < (sizeof(events) / sizeof(events[0])); i++) {
			if (time > events_last[i] + events[i].period) {
				events[i].f();
				events_last[i] += events[i].period;
			}
		}

		/* Check the stuff we check on each loop iteration. */
		for (i = 0; i < TABLE_LENGTH(poll); i++) {
			poll_table[i].f();
		}
	}
}