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
 | 
						libdvi
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# pico_enable_stdio_uart(colour_terminal_audio 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# create map/bin/hex file etc.
 | 
					# create map/bin/hex file etc.
 | 
				
			||||||
pico_add_extra_outputs(colour_terminal_audio)
 | 
					pico_add_extra_outputs(colour_terminal_audio)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,23 +86,22 @@ audio_sample_t      audio_buffer[AUDIO_BUFFER_SIZE];
 | 
				
			||||||
struct repeating_timer audio_timer;
 | 
					struct repeating_timer audio_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool audio_timer_callback(struct repeating_timer *t) {
 | 
					bool audio_timer_callback(struct repeating_timer *t) {
 | 
				
			||||||
    int size = get_write_size(&dvi0.audio_ring, false);
 | 
						while(true) {
 | 
				
			||||||
    audio_sample_t *audio_ptr = get_write_pointer(&dvi0.audio_ring);
 | 
							int size = get_write_size(&dvi0.audio_ring, false);
 | 
				
			||||||
    audio_sample_t sample;
 | 
							if (size == 0) return true;
 | 
				
			||||||
    static uint sample_count = 0;
 | 
							audio_sample_t *audio_ptr = get_write_pointer(&dvi0.audio_ring);
 | 
				
			||||||
    for (int cnt = 0; cnt < size; cnt++) {
 | 
							audio_sample_t sample;
 | 
				
			||||||
        sample.channels[0] = commodore_argentina[sample_count % commodore_argentina_len] << 8;
 | 
							static uint sample_count = 0;
 | 
				
			||||||
        sample.channels[1] = commodore_argentina[(sample_count+1024) % commodore_argentina_len] << 8;
 | 
							for (int cnt = 0; cnt < size; cnt++) {
 | 
				
			||||||
        *audio_ptr++ = sample;
 | 
								sample.channels[0] = commodore_argentina[sample_count % commodore_argentina_len] << 8;
 | 
				
			||||||
        sample_count = sample_count + 1;
 | 
								sample.channels[1] = commodore_argentina[(sample_count+1024) % commodore_argentina_len] << 8;
 | 
				
			||||||
    }
 | 
								*audio_ptr++ = sample;
 | 
				
			||||||
    increase_write_pointer(&dvi0.audio_ring, size);
 | 
								sample_count = sample_count + 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 
 | 
							increase_write_pointer(&dvi0.audio_ring, size);
 | 
				
			||||||
    return true;
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pixel format RGB222
 | 
					// Pixel format RGB222
 | 
				
			||||||
static inline void set_colour(uint x, uint y, uint8_t fg, uint8_t bg) {
 | 
					static inline void set_colour(uint x, uint y, uint8_t fg, uint8_t bg) {
 | 
				
			||||||
	if (x >= CHAR_COLS || y >= CHAR_ROWS)
 | 
						if (x >= CHAR_COLS || y >= CHAR_ROWS)
 | 
				
			||||||
| 
						 | 
					@ -146,6 +145,8 @@ int __not_in_flash("main") main() {
 | 
				
			||||||
	// Run system at TMDS bit clock
 | 
						// Run system at TMDS bit clock
 | 
				
			||||||
	set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
 | 
						set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // setup_default_uart();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dvi0.timing = &DVI_TIMING;
 | 
						dvi0.timing = &DVI_TIMING;
 | 
				
			||||||
	dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG;
 | 
						dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG;
 | 
				
			||||||
	dvi_init(&dvi0, next_striped_spin_lock_num(), next_striped_spin_lock_num());
 | 
						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);
 | 
					    dvi_set_audio_freq(&dvi0, 44100, 28000, 6272);
 | 
				
			||||||
    add_repeating_timer_ms(-2, audio_timer_callback, NULL, &audio_timer);
 | 
					    add_repeating_timer_ms(-2, audio_timer_callback, NULL, &audio_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("starting...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	multicore_launch_core1(core1_main);
 | 
						multicore_launch_core1(core1_main);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (1)
 | 
						while (1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,14 +26,14 @@
 | 
				
			||||||
struct dvi_inst dvi0;
 | 
					struct dvi_inst dvi0;
 | 
				
			||||||
uint16_t framebuf[FRAME_WIDTH * FRAME_HEIGHT];
 | 
					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_register_irqs_this_core(&dvi0, DMA_IRQ_0);
 | 
				
			||||||
	dvi_start(&dvi0);
 | 
						dvi_start(&dvi0);
 | 
				
			||||||
	dvi_scanbuf_main_16bpp(&dvi0);
 | 
						dvi_scanbuf_main_16bpp(&dvi0);
 | 
				
			||||||
	__builtin_unreachable();
 | 
						__builtin_unreachable();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void core1_scanline_callback() {
 | 
					void __not_in_flash_func(core1_scanline_callback)() {
 | 
				
			||||||
	// Discard any scanline pointers passed back
 | 
						// Discard any scanline pointers passed back
 | 
				
			||||||
	uint16_t *bufptr;
 | 
						uint16_t *bufptr;
 | 
				
			||||||
	while (queue_try_remove_u32(&dvi0.q_colour_free, &bufptr))
 | 
						while (queue_try_remove_u32(&dvi0.q_colour_free, &bufptr))
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ void core1_scanline_callback() {
 | 
				
			||||||
	scanline = (scanline + 1) % FRAME_HEIGHT;
 | 
						scanline = (scanline + 1) % FRAME_HEIGHT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main() {
 | 
					int __not_in_flash_func(main)() {
 | 
				
			||||||
	vreg_set_voltage(VREG_VSEL);
 | 
						vreg_set_voltage(VREG_VSEL);
 | 
				
			||||||
	sleep_ms(10);
 | 
						sleep_ms(10);
 | 
				
			||||||
#ifdef RUN_FROM_CRYSTAL
 | 
					#ifdef RUN_FROM_CRYSTAL
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ struct semaphore dvi_start_sem;
 | 
				
			||||||
#define CHAR_ROWS (FRAME_HEIGHT / FONT_CHAR_HEIGHT)
 | 
					#define CHAR_ROWS (FRAME_HEIGHT / FONT_CHAR_HEIGHT)
 | 
				
			||||||
char charbuf[CHAR_ROWS * CHAR_COLS];
 | 
					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];
 | 
						static uint8_t scanbuf[FRAME_WIDTH / 8];
 | 
				
			||||||
	// First blit font into 1bpp scanline buffer, then encode scanbuf into tmdsbuf
 | 
						// First blit font into 1bpp scanline buffer, then encode scanbuf into tmdsbuf
 | 
				
			||||||
	for (uint i = 0; i < CHAR_COLS; ++i) {
 | 
						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);
 | 
						queue_add_blocking(&dvi0.q_tmds_valid, &tmdsbuf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void core1_scanline_callback() {
 | 
					void __not_in_flash_func(core1_scanline_callback)() {
 | 
				
			||||||
	static uint y = 1;
 | 
						static uint y = 1;
 | 
				
			||||||
	prepare_scanline(charbuf, y);
 | 
						prepare_scanline(charbuf, y);
 | 
				
			||||||
	y = (y + 1) % FRAME_HEIGHT;
 | 
						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);
 | 
						dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
 | 
				
			||||||
	sem_acquire_blocking(&dvi_start_sem);
 | 
						sem_acquire_blocking(&dvi_start_sem);
 | 
				
			||||||
	dvi_start(&dvi0);
 | 
						dvi_start(&dvi0);
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ void __not_in_flash("main") core1_main() {
 | 
				
			||||||
	__builtin_unreachable();
 | 
						__builtin_unreachable();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __not_in_flash("main") main() {
 | 
					int __not_in_flash_func(main)() {
 | 
				
			||||||
	vreg_set_voltage(VREG_VSEL);
 | 
						vreg_set_voltage(VREG_VSEL);
 | 
				
			||||||
	sleep_ms(10);
 | 
						sleep_ms(10);
 | 
				
			||||||
#ifdef RUN_FROM_CRYSTAL
 | 
					#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
 | 
					// 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 = {
 | 
					static const struct dvi_serialiser_cfg pico_sock_cfg = {
 | 
				
			||||||
// 	.pio = DVI_DEFAULT_PIO_INST,
 | 
						.pio = DVI_DEFAULT_PIO_INST,
 | 
				
			||||||
// 	.sm_tmds = {0, 1, 2},
 | 
						.sm_tmds = {0, 1, 2},
 | 
				
			||||||
// 	.pins_tmds = {12, 18, 16},
 | 
						.pins_tmds = {12, 18, 16},
 | 
				
			||||||
// 	.pins_clk = 14,
 | 
						.pins_clk = 14,
 | 
				
			||||||
// 	.invert_diffpairs = false
 | 
						.invert_diffpairs = false
 | 
				
			||||||
// };
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// pico-RGB2HDMI
 | 
					// pico-RGB2HDMI
 | 
				
			||||||
static const struct dvi_serialiser_cfg pico_sock_cfg = {
 | 
					static const struct dvi_serialiser_cfg pico_rgb2hdmi_cfg = {
 | 
				
			||||||
        .pio = pio0,
 | 
					        .pio = pio0,
 | 
				
			||||||
        .sm_tmds = {0, 1, 2},
 | 
					        .sm_tmds = {0, 1, 2},
 | 
				
			||||||
        .pins_tmds = {5, 7, 9},
 | 
					        .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 layout = 0;
 | 
				
			||||||
    const int samplePresent = (1 << n) - 1;
 | 
					    const int samplePresent = (1 << n) - 1;
 | 
				
			||||||
    const int B = (frameCt < n) ? (1 << frameCt) : 0;
 | 
					    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[1] = (layout << 4) | samplePresent;
 | 
				
			||||||
    data_packet->header[2] = B << 4;
 | 
					    data_packet->header[2] = B << 4;
 | 
				
			||||||
    compute_header_parity(data_packet);
 | 
					    compute_header_parity(data_packet);
 | 
				
			||||||
 | 
					    const int read_size = get_read_size(audio_ring, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < n; ++i)
 | 
					    for (int i = 0; i < n; ++i)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        uint8_t *d = data_packet->subpacket[i];
 | 
					        int16_t l, r;
 | 
				
			||||||
        const int16_t l = (*p).channels[0];
 | 
					        if (i < read_size) {
 | 
				
			||||||
        const int16_t r = (*p).channels[1];
 | 
					            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
 | 
					        const uint8_t vuc = 1; // valid
 | 
				
			||||||
 | 
					        uint8_t *d = data_packet->subpacket[i];
 | 
				
			||||||
        d[0] = 0;
 | 
					        d[0] = 0;
 | 
				
			||||||
        d[1] = l;
 | 
					        d[1] = l;
 | 
				
			||||||
        d[2] = l >> 8;
 | 
					        d[2] = l >> 8;
 | 
				
			||||||
        d[3] = 0;
 | 
					        d[3] = 0;
 | 
				
			||||||
        d[4] = r;
 | 
					        d[4] = r;
 | 
				
			||||||
        d[5] = r >> 8;
 | 
					        d[5] = r >> 8;
 | 
				
			||||||
        ++p;
 | 
					 | 
				
			||||||
        bool pl = compute8_3(d[1], d[2], vuc);
 | 
					        bool pl = compute8_3(d[1], d[2], vuc);
 | 
				
			||||||
        bool pr = compute8_3(d[4], d[5], vuc);
 | 
					        bool pr = compute8_3(d[4], d[5], vuc);
 | 
				
			||||||
        d[6] = (vuc << 0) | (pl << 3) | (vuc << 4) | (pr << 7);
 | 
					        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?)
 | 
					        // channel status (is it relevant?)
 | 
				
			||||||
        // After testing, seems better to ignore
 | 
					        // 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_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 encode_subpacket(const data_packet_t *data_packet, uint32_t *dst1, uint32_t *dst2);
 | 
				
			||||||
void set_null(void *data, int size);
 | 
					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_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_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,
 | 
					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;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    int sample_pos_24 = inst->audio_sample_pos >> 24;
 | 
					    const int sample_pos_24 = inst->audio_sample_pos >> 24;
 | 
				
			||||||
    int read_size = get_read_size(&inst->audio_ring, false);
 | 
					    const int n = MIN(4, sample_pos_24);
 | 
				
			||||||
    int n = MIN(4, MIN(sample_pos_24, read_size));
 | 
					 | 
				
			||||||
    inst->audio_sample_pos -= (n << 24);
 | 
					 | 
				
			||||||
    if (n)
 | 
					    if (n)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        audio_sample_t *audio_sample_ptr = get_read_pointer(&inst->audio_ring);
 | 
					        inst->audio_sample_pos -= (n << 24);
 | 
				
			||||||
        inst->audio_frame_count = set_audio_sample(packet, audio_sample_ptr, n, inst->audio_frame_count);
 | 
					        inst->audio_frame_count = set_audio_sample(packet, &inst->audio_ring, n, inst->audio_frame_count);
 | 
				
			||||||
        increase_read_pointer(&inst->audio_ring, n);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Ładowanie…
	
		Reference in New Issue