From c6d553e4e4ff9ea728d023ffeb8ee66dabf7c288 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 9 May 2013 10:52:43 +0200 Subject: [PATCH] software/videomixer: interrupt-driven video passthrough --- software/include/hw/flags.h | 4 ++ software/videomixer/isr.c | 4 ++ software/videomixer/main.c | 96 ++++++++++++++++++++++++++----------- 3 files changed, 75 insertions(+), 29 deletions(-) diff --git a/software/include/hw/flags.h b/software/include/hw/flags.h index 41c6db23..fe3afd36 100644 --- a/software/include/hw/flags.h +++ b/software/include/hw/flags.h @@ -30,4 +30,8 @@ #define DVISAMPLER_DELAY_INC 0x4 #define DVISAMPLER_DELAY_DEC 0x8 +#define DVISAMPLER_SLOT_EMPTY 0 +#define DVISAMPLER_SLOT_LOADED 1 +#define DVISAMPLER_SLOT_PENDING 2 + #endif /* __HW_FLAGS_H */ diff --git a/software/videomixer/isr.c b/software/videomixer/isr.c index 36c4c7e0..19d641ec 100644 --- a/software/videomixer/isr.c +++ b/software/videomixer/isr.c @@ -2,6 +2,8 @@ #include #include +void dvisampler0_isr(void); // FIXME + void isr(void); void isr(void) { @@ -11,4 +13,6 @@ void isr(void) if(irqs & (1 << UART_INTERRUPT)) uart_isr(); + if(irqs & (1 << DVISAMPLER0_INTERRUPT)) + dvisampler0_isr(); } diff --git a/software/videomixer/main.c b/software/videomixer/main.c index 4a15b641..962623e1 100644 --- a/software/videomixer/main.c +++ b/software/videomixer/main.c @@ -7,12 +7,11 @@ #include #include -static int d0, d1, d2; -static unsigned int framebuffer[640*480] __attribute__((aligned(16))); +static int dvisampler0_d0, dvisampler0_d1, dvisampler0_d2; static void print_status(void) { - printf("Ph: %4d %4d %4d // %d%d%d [%d %d %d] // %d // %dx%d\n", d0, d1, d2, + printf("dvisampler0 ph: %4d %4d %4d // %d%d%d [%d %d %d] // %d // %dx%d\n", dvisampler0_d0, dvisampler0_d1, dvisampler0_d2, dvisampler0_data0_charsync_char_synced_read(), dvisampler0_data1_charsync_char_synced_read(), dvisampler0_data2_charsync_char_synced_read(), @@ -24,17 +23,6 @@ static void print_status(void) dvisampler0_resdetection_vres_read()); } -static void capture_fb(void) -{ - dvisampler0_dma_frame_size_write(sizeof(framebuffer)); - dvisampler0_dma_slot0_address_write((unsigned int)framebuffer); - dvisampler0_dma_slot0_status_write(1); - - printf("waiting for DMA..."); - while(dvisampler0_dma_slot0_status_read() != 2); - printf("done\n"); -} - static void calibrate_delays(void) { dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); @@ -49,7 +37,7 @@ static void calibrate_delays(void) dvisampler0_data0_cap_phase_reset_write(1); dvisampler0_data1_cap_phase_reset_write(1); dvisampler0_data2_cap_phase_reset_write(1); - d0 = d1 = d2 = 0; + dvisampler0_d0 = dvisampler0_d1 = dvisampler0_d2 = 0; printf("Delays calibrated\n"); } @@ -58,36 +46,36 @@ static void adjust_phase(void) switch(dvisampler0_data0_cap_phase_read()) { case DVISAMPLER_TOO_LATE: dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); - d0--; + dvisampler0_d0--; dvisampler0_data0_cap_phase_reset_write(1); break; case DVISAMPLER_TOO_EARLY: dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - d0++; + dvisampler0_d0++; dvisampler0_data0_cap_phase_reset_write(1); break; } switch(dvisampler0_data1_cap_phase_read()) { case DVISAMPLER_TOO_LATE: dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); - d1--; + dvisampler0_d1--; dvisampler0_data1_cap_phase_reset_write(1); break; case DVISAMPLER_TOO_EARLY: dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - d1++; + dvisampler0_d1++; dvisampler0_data1_cap_phase_reset_write(1); break; } switch(dvisampler0_data2_cap_phase_read()) { case DVISAMPLER_TOO_LATE: dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); - d2--; + dvisampler0_d2--; dvisampler0_data2_cap_phase_reset_write(1); break; case DVISAMPLER_TOO_EARLY: dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - d2++; + dvisampler0_d2++; dvisampler0_data2_cap_phase_reset_write(1); break; } @@ -95,21 +83,73 @@ static void adjust_phase(void) static int init_phase(void) { - int od0, od1, od2; + int o_d0, o_d1, o_d2; int i, j; for(i=0;i<100;i++) { - od0 = d0; - od1 = d1; - od2 = d2; + o_d0 = dvisampler0_d0; + o_d1 = dvisampler0_d1; + o_d2 = dvisampler0_d2; for(j=0;j<1000;j++) adjust_phase(); - if((abs(d0 - od0) < 4) && (abs(d1 - od1) < 4) && (abs(d2 - od2) < 4)) + if((abs(dvisampler0_d0 - o_d0) < 4) && (abs(dvisampler0_d1 - o_d1) < 4) && (abs(dvisampler0_d2 - o_d2) < 4)) return 1; } return 0; } +#define FRAMEBUFFER_COUNT 4 +#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1) + +static unsigned int dvisampler0_framebuffers[FRAMEBUFFER_COUNT][640*480] __attribute__((aligned(16))); +static int dvisampler0_fb_slot_indexes[2]; +static int dvisampler0_next_fb_index; + +static void dvisampler0_init_video(void) +{ + unsigned int mask; + + dvisampler0_dma_ev_pending_write(dvisampler0_dma_ev_pending_read()); + dvisampler0_dma_ev_enable_write(0x3); + mask = irq_getmask(); + mask |= 1 << DVISAMPLER0_INTERRUPT; + irq_setmask(mask); + + dvisampler0_dma_frame_size_write(sizeof(dvisampler0_framebuffers[0])); + dvisampler0_fb_slot_indexes[0] = 0; + dvisampler0_dma_slot0_address_write((unsigned int)dvisampler0_framebuffers[0]); + dvisampler0_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED); + dvisampler0_fb_slot_indexes[1] = 1; + dvisampler0_dma_slot1_address_write((unsigned int)dvisampler0_framebuffers[1]); + dvisampler0_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED); + dvisampler0_next_fb_index = 2; + + fb_base_write((unsigned int)dvisampler0_framebuffers[0]); +} + +void dvisampler0_isr(void) +{ + int fb_index = -1; + + if(dvisampler0_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) { + fb_index = dvisampler0_fb_slot_indexes[0]; + dvisampler0_fb_slot_indexes[0] = dvisampler0_next_fb_index; + dvisampler0_dma_slot0_address_write((unsigned int)dvisampler0_framebuffers[dvisampler0_next_fb_index]); + dvisampler0_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED); + dvisampler0_next_fb_index = (dvisampler0_next_fb_index + 1) & FRAMEBUFFER_MASK; + } + if(dvisampler0_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) { + fb_index = dvisampler0_fb_slot_indexes[1]; + dvisampler0_fb_slot_indexes[1] = dvisampler0_next_fb_index; + dvisampler0_dma_slot1_address_write((unsigned int)dvisampler0_framebuffers[dvisampler0_next_fb_index]); + dvisampler0_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED); + dvisampler0_next_fb_index = (dvisampler0_next_fb_index + 1) & FRAMEBUFFER_MASK; + } + + if(fb_index != -1) + fb_base_write((unsigned int)dvisampler0_framebuffers[fb_index]); +} + static void vmix(void) { unsigned int counter; @@ -132,8 +172,6 @@ static void vmix(void) adjust_phase(); counter = 0; } - if(readchar_nonblock() && (readchar() == 'c')) - capture_fb(); } printf("PLL unlocked\n"); } @@ -147,7 +185,7 @@ int main(void) puts("Minimal video mixer software built "__DATE__" "__TIME__"\n"); - fb_base_write((unsigned int)framebuffer); + dvisampler0_init_video(); fb_enable_write(1); vmix(); -- 2.30.2