diff --git a/software/videomixer/Makefile b/software/videomixer/Makefile index 4b6bf278f..dca4c3a18 100644 --- a/software/videomixer/Makefile +++ b/software/videomixer/Makefile @@ -1,7 +1,7 @@ M2DIR=../.. include $(M2DIR)/software/common.mak -OBJECTS=crt0.o isr.o main.o +OBJECTS=crt0.o isr.o dvisampler0.o dvisampler1.o main.o all: videomixer.bin @@ -30,6 +30,30 @@ main.o: main.c %.o: %.S $(assemble) +define gen0 +@echo " GEN " $@ +@sed -e "s/dvisamplerX/dvisampler0/g;s/DVISAMPLERX/DVISAMPLER0/g" $< > $@ +endef + +define gen1 +@echo " GEN " $@ +@sed -e "s/dvisamplerX/dvisampler1/g;s/DVISAMPLERX/DVISAMPLER1/g" $< > $@ +endef + +dvisampler0.c: dvisamplerX.c + $(gen0) +dvisampler0.h: dvisamplerX.h + $(gen0) +dvisampler1.c: dvisamplerX.c + $(gen1) +dvisampler1.h: dvisamplerX.h + $(gen1) + +isr.o: dvisampler0.h dvisampler1.h +main.o: dvisampler0.h dvisampler1.h +dvisampler0.o: dvisampler0.h +dvisampler1.o: dvisampler1.h + libs: make -C $(M2DIR)/software/libcompiler-rt make -C $(M2DIR)/software/libbase @@ -40,5 +64,6 @@ load: videomixer.bin clean: rm -f $(OBJECTS) $(OBJECTS:.o=.d) videomixer.elf videomixer.bin .*~ *~ + rm -f dvisampler0.h dvisampler0.c dvisampler1.h dvisampler1.c .PHONY: main.o clean libs load diff --git a/software/videomixer/dvisamplerX.c b/software/videomixer/dvisamplerX.c new file mode 100644 index 000000000..d7ac2a86b --- /dev/null +++ b/software/videomixer/dvisamplerX.c @@ -0,0 +1,182 @@ +#include +#include + +#include +#include +#include +#include + +#include "dvisamplerX.h" + +#define FRAMEBUFFER_COUNT 4 +#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1) + +static unsigned int dvisamplerX_framebuffers[FRAMEBUFFER_COUNT][640*480] __attribute__((aligned(16))); +static int dvisamplerX_fb_slot_indexes[2]; +static int dvisamplerX_next_fb_index; + +void dvisamplerX_isr(void) +{ + int fb_index = -1; + + if(dvisamplerX_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) { + fb_index = dvisamplerX_fb_slot_indexes[0]; + dvisamplerX_fb_slot_indexes[0] = dvisamplerX_next_fb_index; + dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_next_fb_index]); + dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED); + dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK; + } + if(dvisamplerX_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) { + fb_index = dvisamplerX_fb_slot_indexes[1]; + dvisamplerX_fb_slot_indexes[1] = dvisamplerX_next_fb_index; + dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_next_fb_index]); + dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED); + dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK; + } + + if(fb_index != -1) + fb_base_write((unsigned int)dvisamplerX_framebuffers[fb_index]); +} + +void dvisamplerX_init_video(void) +{ + unsigned int mask; + + dvisamplerX_dma_ev_pending_write(dvisamplerX_dma_ev_pending_read()); + dvisamplerX_dma_ev_enable_write(0x3); + mask = irq_getmask(); + mask |= 1 << DVISAMPLERX_INTERRUPT; + irq_setmask(mask); + + dvisamplerX_dma_frame_size_write(sizeof(dvisamplerX_framebuffers[0])); + dvisamplerX_fb_slot_indexes[0] = 0; + dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[0]); + dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED); + dvisamplerX_fb_slot_indexes[1] = 1; + dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[1]); + dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED); + dvisamplerX_next_fb_index = 2; + + fb_base_write((unsigned int)dvisamplerX_framebuffers[3]); +} + +static int dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2; + +void dvisamplerX_print_status(void) +{ + printf("dvisamplerX ph:%4d %4d %4d // charsync:%d%d%d [%d %d %d] // chansync:%d // res:%dx%d\n", + dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2, + dvisamplerX_data0_charsync_char_synced_read(), + dvisamplerX_data1_charsync_char_synced_read(), + dvisamplerX_data2_charsync_char_synced_read(), + dvisamplerX_data0_charsync_ctl_pos_read(), + dvisamplerX_data1_charsync_ctl_pos_read(), + dvisamplerX_data2_charsync_ctl_pos_read(), + dvisamplerX_chansync_channels_synced_read(), + dvisamplerX_resdetection_hres_read(), + dvisamplerX_resdetection_vres_read()); +} + +void dvisamplerX_calibrate_delays(void) +{ + dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); + dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); + dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); + while(dvisamplerX_data0_cap_dly_busy_read() + || dvisamplerX_data1_cap_dly_busy_read() + || dvisamplerX_data2_cap_dly_busy_read()); + dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); + dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); + dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); + dvisamplerX_data0_cap_phase_reset_write(1); + dvisamplerX_data1_cap_phase_reset_write(1); + dvisamplerX_data2_cap_phase_reset_write(1); + dvisamplerX_d0 = dvisamplerX_d1 = dvisamplerX_d2 = 0; +} + +void dvisamplerX_adjust_phase(void) +{ + switch(dvisamplerX_data0_cap_phase_read()) { + case DVISAMPLER_TOO_LATE: + dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); + dvisamplerX_d0--; + dvisamplerX_data0_cap_phase_reset_write(1); + break; + case DVISAMPLER_TOO_EARLY: + dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); + dvisamplerX_d0++; + dvisamplerX_data0_cap_phase_reset_write(1); + break; + } + switch(dvisamplerX_data1_cap_phase_read()) { + case DVISAMPLER_TOO_LATE: + dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); + dvisamplerX_d1--; + dvisamplerX_data1_cap_phase_reset_write(1); + break; + case DVISAMPLER_TOO_EARLY: + dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); + dvisamplerX_d1++; + dvisamplerX_data1_cap_phase_reset_write(1); + break; + } + switch(dvisamplerX_data2_cap_phase_read()) { + case DVISAMPLER_TOO_LATE: + dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); + dvisamplerX_d2--; + dvisamplerX_data2_cap_phase_reset_write(1); + break; + case DVISAMPLER_TOO_EARLY: + dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); + dvisamplerX_d2++; + dvisamplerX_data2_cap_phase_reset_write(1); + break; + } +} + +int dvisamplerX_init_phase(void) +{ + int o_d0, o_d1, o_d2; + int i, j; + + for(i=0;i<100;i++) { + o_d0 = dvisamplerX_d0; + o_d1 = dvisamplerX_d1; + o_d2 = dvisamplerX_d2; + for(j=0;j<1000;j++) + dvisamplerX_adjust_phase(); + if((abs(dvisamplerX_d0 - o_d0) < 4) && (abs(dvisamplerX_d1 - o_d1) < 4) && (abs(dvisamplerX_d2 - o_d2) < 4)) + return 1; + } + return 0; +} + +static int dvisamplerX_locked; + +void dvisamplerX_service(void) +{ + int ret; + + if(dvisamplerX_locked) { + if(dvisamplerX_clocking_locked_read()) { + dvisamplerX_adjust_phase(); + dvisamplerX_print_status(); + } else { + printf("dvisamplerX: lost PLL lock\n"); + dvisamplerX_locked = 0; + } + } else { + if(dvisamplerX_clocking_locked_read()) { + printf("dvisamplerX: PLL locked\n"); + dvisamplerX_calibrate_delays(); + printf("dvisamplerX: delays calibrated\n"); + ret = dvisamplerX_init_phase(); + if(ret) + printf("dvisamplerX: phase init OK\n"); + else + printf("dvisamplerX: phase did not settle\n"); + dvisamplerX_print_status(); + dvisamplerX_locked = 1; + } + } +} diff --git a/software/videomixer/dvisamplerX.h b/software/videomixer/dvisamplerX.h new file mode 100644 index 000000000..7d02b4231 --- /dev/null +++ b/software/videomixer/dvisamplerX.h @@ -0,0 +1,12 @@ +#ifndef __DVISAMPLERX_H +#define __DVISAMPLERX_H + +void dvisamplerX_isr(void); +void dvisamplerX_init_video(void); +void dvisamplerX_print_status(void); +void dvisamplerX_calibrate_delays(void); +void dvisamplerX_adjust_phase(void); +int dvisamplerX_init_phase(void); +void dvisamplerX_service(void); + +#endif diff --git a/software/videomixer/isr.c b/software/videomixer/isr.c index 19d641ec6..aa1139f80 100644 --- a/software/videomixer/isr.c +++ b/software/videomixer/isr.c @@ -2,7 +2,8 @@ #include #include -void dvisampler0_isr(void); // FIXME +#include "dvisampler0.h" +#include "dvisampler1.h" void isr(void); void isr(void) @@ -15,4 +16,6 @@ void isr(void) uart_isr(); if(irqs & (1 << DVISAMPLER0_INTERRUPT)) dvisampler0_isr(); + if(irqs & (1 << DVISAMPLER1_INTERRUPT)) + dvisampler1_isr(); } diff --git a/software/videomixer/main.c b/software/videomixer/main.c index 962623e16..76fc155df 100644 --- a/software/videomixer/main.c +++ b/software/videomixer/main.c @@ -3,179 +3,11 @@ #include #include -#include #include #include -static int dvisampler0_d0, dvisampler0_d1, dvisampler0_d2; - -static void print_status(void) -{ - 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(), - dvisampler0_data0_charsync_ctl_pos_read(), - dvisampler0_data1_charsync_ctl_pos_read(), - dvisampler0_data2_charsync_ctl_pos_read(), - dvisampler0_chansync_channels_synced_read(), - dvisampler0_resdetection_hres_read(), - dvisampler0_resdetection_vres_read()); -} - -static void calibrate_delays(void) -{ - dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); - dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); - dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL); - while(dvisampler0_data0_cap_dly_busy_read() - || dvisampler0_data1_cap_dly_busy_read() - || dvisampler0_data2_cap_dly_busy_read()); - dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); - dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); - dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_RST); - dvisampler0_data0_cap_phase_reset_write(1); - dvisampler0_data1_cap_phase_reset_write(1); - dvisampler0_data2_cap_phase_reset_write(1); - dvisampler0_d0 = dvisampler0_d1 = dvisampler0_d2 = 0; - printf("Delays calibrated\n"); -} - -static void adjust_phase(void) -{ - switch(dvisampler0_data0_cap_phase_read()) { - case DVISAMPLER_TOO_LATE: - dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC); - dvisampler0_d0--; - dvisampler0_data0_cap_phase_reset_write(1); - break; - case DVISAMPLER_TOO_EARLY: - dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - 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); - dvisampler0_d1--; - dvisampler0_data1_cap_phase_reset_write(1); - break; - case DVISAMPLER_TOO_EARLY: - dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - 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); - dvisampler0_d2--; - dvisampler0_data2_cap_phase_reset_write(1); - break; - case DVISAMPLER_TOO_EARLY: - dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC); - dvisampler0_d2++; - dvisampler0_data2_cap_phase_reset_write(1); - break; - } -} - -static int init_phase(void) -{ - int o_d0, o_d1, o_d2; - int i, j; - - for(i=0;i<100;i++) { - o_d0 = dvisampler0_d0; - o_d1 = dvisampler0_d1; - o_d2 = dvisampler0_d2; - for(j=0;j<1000;j++) - adjust_phase(); - 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; - - while(1) { - while(!dvisampler0_clocking_locked_read()); - printf("PLL locked\n"); - calibrate_delays(); - if(init_phase()) - printf("Phase init OK\n"); - else - printf("Phase did not settle\n"); - print_status(); - - counter = 0; - while(dvisampler0_clocking_locked_read()) { - counter++; - if(counter == 2000000) { - print_status(); - adjust_phase(); - counter = 0; - } - } - printf("PLL unlocked\n"); - } -} +#include "dvisampler0.h" +#include "dvisampler1.h" int main(void) { @@ -187,7 +19,7 @@ int main(void) dvisampler0_init_video(); fb_enable_write(1); - vmix(); + while(1) dvisampler0_service(); return 0; }