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; } }
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); }
/* 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; }
/* 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; }
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); } } }
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(); } } }