kopia lustrzana https://github.com/Wren6991/PicoDVI
Allow audio underrun (#1)
* Allow audio underrun * HDMI audio * Allow audio underrun * Allow audio underrunpull/94/head
rodzic
dd7ba281ee
commit
21869f0460
|
|
@ -21,5 +21,7 @@ target_link_libraries(colour_terminal_audio
|
|||
libdvi
|
||||
)
|
||||
|
||||
# pico_enable_stdio_uart(colour_terminal_audio 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(colour_terminal_audio)
|
||||
|
|
|
|||
|
|
@ -86,23 +86,22 @@ audio_sample_t audio_buffer[AUDIO_BUFFER_SIZE];
|
|||
struct repeating_timer audio_timer;
|
||||
|
||||
bool audio_timer_callback(struct repeating_timer *t) {
|
||||
int size = get_write_size(&dvi0.audio_ring, false);
|
||||
audio_sample_t *audio_ptr = get_write_pointer(&dvi0.audio_ring);
|
||||
audio_sample_t sample;
|
||||
static uint sample_count = 0;
|
||||
for (int cnt = 0; cnt < size; cnt++) {
|
||||
sample.channels[0] = commodore_argentina[sample_count % commodore_argentina_len] << 8;
|
||||
sample.channels[1] = commodore_argentina[(sample_count+1024) % commodore_argentina_len] << 8;
|
||||
*audio_ptr++ = sample;
|
||||
sample_count = sample_count + 1;
|
||||
}
|
||||
increase_write_pointer(&dvi0.audio_ring, size);
|
||||
|
||||
|
||||
return true;
|
||||
while(true) {
|
||||
int size = get_write_size(&dvi0.audio_ring, false);
|
||||
if (size == 0) return true;
|
||||
audio_sample_t *audio_ptr = get_write_pointer(&dvi0.audio_ring);
|
||||
audio_sample_t sample;
|
||||
static uint sample_count = 0;
|
||||
for (int cnt = 0; cnt < size; cnt++) {
|
||||
sample.channels[0] = commodore_argentina[sample_count % commodore_argentina_len] << 8;
|
||||
sample.channels[1] = commodore_argentina[(sample_count+1024) % commodore_argentina_len] << 8;
|
||||
*audio_ptr++ = sample;
|
||||
sample_count = sample_count + 1;
|
||||
}
|
||||
increase_write_pointer(&dvi0.audio_ring, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pixel format RGB222
|
||||
static inline void set_colour(uint x, uint y, uint8_t fg, uint8_t bg) {
|
||||
if (x >= CHAR_COLS || y >= CHAR_ROWS)
|
||||
|
|
@ -146,6 +145,8 @@ int __not_in_flash("main") main() {
|
|||
// Run system at TMDS bit clock
|
||||
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||
|
||||
// setup_default_uart();
|
||||
|
||||
dvi0.timing = &DVI_TIMING;
|
||||
dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG;
|
||||
dvi_init(&dvi0, next_striped_spin_lock_num(), next_striped_spin_lock_num());
|
||||
|
|
@ -166,6 +167,8 @@ int __not_in_flash("main") main() {
|
|||
dvi_set_audio_freq(&dvi0, 44100, 28000, 6272);
|
||||
add_repeating_timer_ms(-2, audio_timer_callback, NULL, &audio_timer);
|
||||
|
||||
printf("starting...\n");
|
||||
|
||||
multicore_launch_core1(core1_main);
|
||||
|
||||
while (1)
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@
|
|||
struct dvi_inst dvi0;
|
||||
uint16_t framebuf[FRAME_WIDTH * FRAME_HEIGHT];
|
||||
|
||||
void core1_main() {
|
||||
void __not_in_flash_func(core1_main)() {
|
||||
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
|
||||
dvi_start(&dvi0);
|
||||
dvi_scanbuf_main_16bpp(&dvi0);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void core1_scanline_callback() {
|
||||
void __not_in_flash_func(core1_scanline_callback)() {
|
||||
// Discard any scanline pointers passed back
|
||||
uint16_t *bufptr;
|
||||
while (queue_try_remove_u32(&dvi0.q_colour_free, &bufptr))
|
||||
|
|
@ -45,7 +45,7 @@ void core1_scanline_callback() {
|
|||
scanline = (scanline + 1) % FRAME_HEIGHT;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int __not_in_flash_func(main)() {
|
||||
vreg_set_voltage(VREG_VSEL);
|
||||
sleep_ms(10);
|
||||
#ifdef RUN_FROM_CRYSTAL
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct semaphore dvi_start_sem;
|
|||
#define CHAR_ROWS (FRAME_HEIGHT / FONT_CHAR_HEIGHT)
|
||||
char charbuf[CHAR_ROWS * CHAR_COLS];
|
||||
|
||||
static inline void prepare_scanline(const char *chars, uint y) {
|
||||
static inline void __not_in_flash_func(prepare_scanline)(const char *chars, uint y) {
|
||||
static uint8_t scanbuf[FRAME_WIDTH / 8];
|
||||
// First blit font into 1bpp scanline buffer, then encode scanbuf into tmdsbuf
|
||||
for (uint i = 0; i < CHAR_COLS; ++i) {
|
||||
|
|
@ -86,13 +86,13 @@ static inline void prepare_scanline(const char *chars, uint y) {
|
|||
queue_add_blocking(&dvi0.q_tmds_valid, &tmdsbuf);
|
||||
}
|
||||
|
||||
void core1_scanline_callback() {
|
||||
void __not_in_flash_func(core1_scanline_callback)() {
|
||||
static uint y = 1;
|
||||
prepare_scanline(charbuf, y);
|
||||
y = (y + 1) % FRAME_HEIGHT;
|
||||
}
|
||||
|
||||
void __not_in_flash("main") core1_main() {
|
||||
void __not_in_flash_func(core1_main)() {
|
||||
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
|
||||
sem_acquire_blocking(&dvi_start_sem);
|
||||
dvi_start(&dvi0);
|
||||
|
|
@ -104,7 +104,7 @@ void __not_in_flash("main") core1_main() {
|
|||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
int __not_in_flash("main") main() {
|
||||
int __not_in_flash_func(main)() {
|
||||
vreg_set_voltage(VREG_VSEL);
|
||||
sleep_ms(10);
|
||||
#ifdef RUN_FROM_CRYSTAL
|
||||
|
|
|
|||
|
|
@ -61,16 +61,16 @@ static const struct dvi_serialiser_cfg micromod_cfg = {
|
|||
};
|
||||
|
||||
// Pico DVI Sock (small hat on the bottom) which solders to the end of a Pico
|
||||
// static const struct dvi_serialiser_cfg pico_sock_cfg = {
|
||||
// .pio = DVI_DEFAULT_PIO_INST,
|
||||
// .sm_tmds = {0, 1, 2},
|
||||
// .pins_tmds = {12, 18, 16},
|
||||
// .pins_clk = 14,
|
||||
// .invert_diffpairs = false
|
||||
// };
|
||||
static const struct dvi_serialiser_cfg pico_sock_cfg = {
|
||||
.pio = DVI_DEFAULT_PIO_INST,
|
||||
.sm_tmds = {0, 1, 2},
|
||||
.pins_tmds = {12, 18, 16},
|
||||
.pins_clk = 14,
|
||||
.invert_diffpairs = false
|
||||
};
|
||||
|
||||
// pico-RGB2HDMI
|
||||
static const struct dvi_serialiser_cfg pico_sock_cfg = {
|
||||
static const struct dvi_serialiser_cfg pico_rgb2hdmi_cfg = {
|
||||
.pio = pio0,
|
||||
.sm_tmds = {0, 1, 2},
|
||||
.pins_tmds = {5, 7, 9},
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ void __not_in_flash_func(set_null)(void *data, int size) {
|
|||
}
|
||||
}
|
||||
|
||||
int __not_in_flash_func(set_audio_sample)(data_packet_t *data_packet, const audio_sample_t *p, int n, int frameCt) {
|
||||
int __not_in_flash_func(set_audio_sample)(data_packet_t *data_packet, audio_ring_t *audio_ring, const int n, int frameCt) {
|
||||
const int layout = 0;
|
||||
const int samplePresent = (1 << n) - 1;
|
||||
const int B = (frameCt < n) ? (1 << frameCt) : 0;
|
||||
|
|
@ -214,24 +214,34 @@ int __not_in_flash_func(set_audio_sample)(data_packet_t *data_packet, const aud
|
|||
data_packet->header[1] = (layout << 4) | samplePresent;
|
||||
data_packet->header[2] = B << 4;
|
||||
compute_header_parity(data_packet);
|
||||
const int read_size = get_read_size(audio_ring, true);
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
uint8_t *d = data_packet->subpacket[i];
|
||||
const int16_t l = (*p).channels[0];
|
||||
const int16_t r = (*p).channels[1];
|
||||
int16_t l, r;
|
||||
if (i < read_size) {
|
||||
audio_sample_t *audio_sample_ptr = get_read_pointer(audio_ring);
|
||||
l = (*audio_sample_ptr).channels[0];
|
||||
r = (*audio_sample_ptr).channels[1];
|
||||
increase_read_pointer(audio_ring, 1);
|
||||
}
|
||||
else {
|
||||
l = (int16_t)0;
|
||||
r = (int16_t)0;
|
||||
}
|
||||
|
||||
const uint8_t vuc = 1; // valid
|
||||
uint8_t *d = data_packet->subpacket[i];
|
||||
d[0] = 0;
|
||||
d[1] = l;
|
||||
d[2] = l >> 8;
|
||||
d[3] = 0;
|
||||
d[4] = r;
|
||||
d[5] = r >> 8;
|
||||
++p;
|
||||
bool pl = compute8_3(d[1], d[2], vuc);
|
||||
bool pr = compute8_3(d[4], d[5], vuc);
|
||||
d[6] = (vuc << 0) | (pl << 3) | (vuc << 4) | (pr << 7);
|
||||
compute_subpacket_parity(data_packet, i);
|
||||
d[7] = encode_BCH_7(d);
|
||||
|
||||
// channel status (is it relevant?)
|
||||
// After testing, seems better to ignore
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ void compute_info_frame_checkSum(data_packet_t *data_packet);
|
|||
void encode_header(const data_packet_t *data_packet, uint32_t *dst, int hv, bool firstPacket);
|
||||
void encode_subpacket(const data_packet_t *data_packet, uint32_t *dst1, uint32_t *dst2);
|
||||
void set_null(void *data, int size);
|
||||
int set_audio_sample(data_packet_t *data_packet, const audio_sample_t *p, int n, int frameCt);
|
||||
int set_audio_sample(data_packet_t *data_packet, audio_ring_t *audio_ring, const int n, int frameCt);
|
||||
void set_audio_clock_regeneration(data_packet_t *data_packet, int CTS, int N);
|
||||
void set_audio_info_frame(data_packet_t *data_packet, int freq);
|
||||
void set_AVI_info_frame(data_packet_t *data_packet, scan_info s, pixel_format y, colorimetry c, picture_aspect_ratio m,
|
||||
|
|
|
|||
|
|
@ -412,16 +412,12 @@ bool __dvi_func(dvi_update_data_packet_)(struct dvi_inst *inst, data_packet_t *p
|
|||
return true;
|
||||
}
|
||||
}
|
||||
int sample_pos_24 = inst->audio_sample_pos >> 24;
|
||||
int read_size = get_read_size(&inst->audio_ring, false);
|
||||
int n = MIN(4, MIN(sample_pos_24, read_size));
|
||||
inst->audio_sample_pos -= (n << 24);
|
||||
const int sample_pos_24 = inst->audio_sample_pos >> 24;
|
||||
const int n = MIN(4, sample_pos_24);
|
||||
if (n)
|
||||
{
|
||||
audio_sample_t *audio_sample_ptr = get_read_pointer(&inst->audio_ring);
|
||||
inst->audio_frame_count = set_audio_sample(packet, audio_sample_ptr, n, inst->audio_frame_count);
|
||||
increase_read_pointer(&inst->audio_ring, n);
|
||||
|
||||
inst->audio_sample_pos -= (n << 24);
|
||||
inst->audio_frame_count = set_audio_sample(packet, &inst->audio_ring, n, inst->audio_frame_count);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue