software/videomixer: interrupt-driven video passthrough
This commit is contained in:
parent
fe87221d2b
commit
c6d553e4e4
|
@ -30,4 +30,8 @@
|
||||||
#define DVISAMPLER_DELAY_INC 0x4
|
#define DVISAMPLER_DELAY_INC 0x4
|
||||||
#define DVISAMPLER_DELAY_DEC 0x8
|
#define DVISAMPLER_DELAY_DEC 0x8
|
||||||
|
|
||||||
|
#define DVISAMPLER_SLOT_EMPTY 0
|
||||||
|
#define DVISAMPLER_SLOT_LOADED 1
|
||||||
|
#define DVISAMPLER_SLOT_PENDING 2
|
||||||
|
|
||||||
#endif /* __HW_FLAGS_H */
|
#endif /* __HW_FLAGS_H */
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
|
|
||||||
|
void dvisampler0_isr(void); // FIXME
|
||||||
|
|
||||||
void isr(void);
|
void isr(void);
|
||||||
void isr(void)
|
void isr(void)
|
||||||
{
|
{
|
||||||
|
@ -11,4 +13,6 @@ void isr(void)
|
||||||
|
|
||||||
if(irqs & (1 << UART_INTERRUPT))
|
if(irqs & (1 << UART_INTERRUPT))
|
||||||
uart_isr();
|
uart_isr();
|
||||||
|
if(irqs & (1 << DVISAMPLER0_INTERRUPT))
|
||||||
|
dvisampler0_isr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
#include <hw/csr.h>
|
#include <hw/csr.h>
|
||||||
#include <hw/flags.h>
|
#include <hw/flags.h>
|
||||||
|
|
||||||
static int d0, d1, d2;
|
static int dvisampler0_d0, dvisampler0_d1, dvisampler0_d2;
|
||||||
static unsigned int framebuffer[640*480] __attribute__((aligned(16)));
|
|
||||||
|
|
||||||
static void print_status(void)
|
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_data0_charsync_char_synced_read(),
|
||||||
dvisampler0_data1_charsync_char_synced_read(),
|
dvisampler0_data1_charsync_char_synced_read(),
|
||||||
dvisampler0_data2_charsync_char_synced_read(),
|
dvisampler0_data2_charsync_char_synced_read(),
|
||||||
|
@ -24,17 +23,6 @@ static void print_status(void)
|
||||||
dvisampler0_resdetection_vres_read());
|
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)
|
static void calibrate_delays(void)
|
||||||
{
|
{
|
||||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
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_data0_cap_phase_reset_write(1);
|
||||||
dvisampler0_data1_cap_phase_reset_write(1);
|
dvisampler0_data1_cap_phase_reset_write(1);
|
||||||
dvisampler0_data2_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");
|
printf("Delays calibrated\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,36 +46,36 @@ static void adjust_phase(void)
|
||||||
switch(dvisampler0_data0_cap_phase_read()) {
|
switch(dvisampler0_data0_cap_phase_read()) {
|
||||||
case DVISAMPLER_TOO_LATE:
|
case DVISAMPLER_TOO_LATE:
|
||||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||||
d0--;
|
dvisampler0_d0--;
|
||||||
dvisampler0_data0_cap_phase_reset_write(1);
|
dvisampler0_data0_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
case DVISAMPLER_TOO_EARLY:
|
case DVISAMPLER_TOO_EARLY:
|
||||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||||
d0++;
|
dvisampler0_d0++;
|
||||||
dvisampler0_data0_cap_phase_reset_write(1);
|
dvisampler0_data0_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(dvisampler0_data1_cap_phase_read()) {
|
switch(dvisampler0_data1_cap_phase_read()) {
|
||||||
case DVISAMPLER_TOO_LATE:
|
case DVISAMPLER_TOO_LATE:
|
||||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||||
d1--;
|
dvisampler0_d1--;
|
||||||
dvisampler0_data1_cap_phase_reset_write(1);
|
dvisampler0_data1_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
case DVISAMPLER_TOO_EARLY:
|
case DVISAMPLER_TOO_EARLY:
|
||||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||||
d1++;
|
dvisampler0_d1++;
|
||||||
dvisampler0_data1_cap_phase_reset_write(1);
|
dvisampler0_data1_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(dvisampler0_data2_cap_phase_read()) {
|
switch(dvisampler0_data2_cap_phase_read()) {
|
||||||
case DVISAMPLER_TOO_LATE:
|
case DVISAMPLER_TOO_LATE:
|
||||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||||
d2--;
|
dvisampler0_d2--;
|
||||||
dvisampler0_data2_cap_phase_reset_write(1);
|
dvisampler0_data2_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
case DVISAMPLER_TOO_EARLY:
|
case DVISAMPLER_TOO_EARLY:
|
||||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||||
d2++;
|
dvisampler0_d2++;
|
||||||
dvisampler0_data2_cap_phase_reset_write(1);
|
dvisampler0_data2_cap_phase_reset_write(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -95,21 +83,73 @@ static void adjust_phase(void)
|
||||||
|
|
||||||
static int init_phase(void)
|
static int init_phase(void)
|
||||||
{
|
{
|
||||||
int od0, od1, od2;
|
int o_d0, o_d1, o_d2;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for(i=0;i<100;i++) {
|
for(i=0;i<100;i++) {
|
||||||
od0 = d0;
|
o_d0 = dvisampler0_d0;
|
||||||
od1 = d1;
|
o_d1 = dvisampler0_d1;
|
||||||
od2 = d2;
|
o_d2 = dvisampler0_d2;
|
||||||
for(j=0;j<1000;j++)
|
for(j=0;j<1000;j++)
|
||||||
adjust_phase();
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
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)
|
static void vmix(void)
|
||||||
{
|
{
|
||||||
unsigned int counter;
|
unsigned int counter;
|
||||||
|
@ -132,8 +172,6 @@ static void vmix(void)
|
||||||
adjust_phase();
|
adjust_phase();
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
if(readchar_nonblock() && (readchar() == 'c'))
|
|
||||||
capture_fb();
|
|
||||||
}
|
}
|
||||||
printf("PLL unlocked\n");
|
printf("PLL unlocked\n");
|
||||||
}
|
}
|
||||||
|
@ -147,7 +185,7 @@ int main(void)
|
||||||
|
|
||||||
puts("Minimal video mixer software built "__DATE__" "__TIME__"\n");
|
puts("Minimal video mixer software built "__DATE__" "__TIME__"\n");
|
||||||
|
|
||||||
fb_base_write((unsigned int)framebuffer);
|
dvisampler0_init_video();
|
||||||
fb_enable_write(1);
|
fb_enable_write(1);
|
||||||
vmix();
|
vmix();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue