software/videomixer: interrupt-driven video passthrough
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 9 May 2013 08:52:43 +0000 (10:52 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 9 May 2013 08:52:43 +0000 (10:52 +0200)
software/include/hw/flags.h
software/videomixer/isr.c
software/videomixer/main.c

index 41c6db23c236b754aea1538a54d19a360fd13e80..fe3afd36fd5fb5ae3f0097ab0af8fc782007b129 100644 (file)
@@ -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 */
index 36c4c7e07268a7caeb3a588a47b4a3af77ee61d3..19d641ec63d632708db650e1f138e1117a7a01bb 100644 (file)
@@ -2,6 +2,8 @@
 #include <irq.h>
 #include <uart.h>
 
+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();
 }
index 4a15b6413e37c50e7f6ad7678803c0dca8faa3ba..962623e16def6e8f111d9fffc4acca7b78e0c108 100644 (file)
@@ -7,12 +7,11 @@
 #include <hw/csr.h>
 #include <hw/flags.h>
 
-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();