videomixer: config system + store video resolution in flash
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Nov 2013 22:07:19 +0000 (23:07 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 30 Nov 2013 22:07:19 +0000 (23:07 +0100)
software/include/hw/mem.h
software/videomixer/Makefile
software/videomixer/ci.c
software/videomixer/config.c [new file with mode: 0644]
software/videomixer/config.h [new file with mode: 0644]
software/videomixer/main.c

index 5df288943112cb827f82696b6970347d3908ce90..0f83563dcced1ce8f7d1cf6bc481b76b7cd9cafc 100644 (file)
@@ -1,10 +1,13 @@
 #ifndef __HW_MEM_H
 #define __HW_MEM_H
 
+/* TODO: those FLASH_ defines are platform-dependent, generate them from SoC description */
 #define FLASH_OFFSET_BITSTREAM 0x00000000 /* 1536k */
 #define FLASH_OFFSET_BIOS              0x00180000 /* 128k */
 #define FLASH_OFFSET_APP               0x001A0000 /* remaining space */
 
+#define FLASH_BLOCK_SIZE               (128*1024)
+
 #define SDRAM_BASE                     0x40000000
 
 #define MINIMAC_RX0_BASE       0xb0000000
index 8920d60fe39655ec5240d1c4459a6a15b1094e98..b5deb32f9740ff3d45985633b0db5e6fd923ac35 100644 (file)
@@ -1,7 +1,7 @@
 MSCDIR=../..
 include $(MSCDIR)/software/common.mak
 
-OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o pll.o ci.o main.o
+OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o pll.o ci.o config.o main.o
 
 all: videomixer.bin videomixer.fbi
 
index 6b0f430446efef22e4e7dd00623f67eebb32c02d..2f91e380328a7ba9601da9a6f1dc54d23dfd13c0 100644 (file)
@@ -3,6 +3,7 @@
 #include <console.h>
 #include <generated/csr.h>
 
+#include "config.h"
 #include "dvisampler0.h"
 #include "dvisampler1.h"
 #include "processor.h"
@@ -46,8 +47,10 @@ void ci_service(void)
                        int m;
 
                        m = c - '0';
-                       if(m < PROCESSOR_MODE_COUNT)
+                       if(m < PROCESSOR_MODE_COUNT) {
+                               config_set(CONFIG_KEY_RESOLUTION, m);
                                processor_start(m);
+                       }
                }
                switch(c) {
                        case 'l':
diff --git a/software/videomixer/config.c b/software/videomixer/config.c
new file mode 100644 (file)
index 0000000..4b3d56e
--- /dev/null
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <string.h>
+#include <hw/mem.h>
+
+#include "config.h"
+
+#define FLASH_OFFSET_CONFIG (FLASH_OFFSET_APP + FLASH_BLOCK_SIZE)
+
+static volatile unsigned short *flash_config = (unsigned short *)(0x80000000 | FLASH_OFFSET_CONFIG);
+
+static void wait_program(void)
+{
+       while(!(*flash_config & 0x0080)); /* Read status register */
+       *flash_config = 0x0050; /* Clear status register */
+       *flash_config = 0x00ff; /* Go to Read Array mode */
+}
+
+static void config_erase_block(void)
+{
+       *flash_config = 0x0020; /* Setup Erase */
+       *flash_config = 0x00d0; /* Confirm Erase */
+       wait_program();
+}
+
+static void config_write(int offset, unsigned short data)
+{
+       flash_config[offset] = 0x0040; /* Word Program */
+       flash_config[offset] = data;
+       wait_program();
+}
+
+static const unsigned char config_defaults[CONFIG_KEY_COUNT] = CONFIG_DEFAULTS;
+static int config_record_count;
+static unsigned char config_values[CONFIG_KEY_COUNT];
+
+static int config_process_record(unsigned char key, unsigned char value)
+{
+       if(key >= CONFIG_KEY_COUNT)
+               return 0;
+       config_record_count++;
+       config_values[key] = value;
+       return 1;
+}
+
+void config_init(void)
+{
+       volatile unsigned int *flash_config32 = (unsigned int *)flash_config;
+       int i;
+       unsigned int flash_word;
+
+       memcpy(config_values, config_defaults, CONFIG_KEY_COUNT);
+
+       for(i=0;i<FLASH_BLOCK_SIZE/4;i++) {
+               flash_word = flash_config32[i];
+               if(!config_process_record((flash_word >> 24) & 0xff, (flash_word >> 16) & 0xff))
+                       break;
+               if(!config_process_record((flash_word >> 8) & 0xff, flash_word & 0xff))
+                       break;
+       }
+}
+
+void config_write_all(void)
+{
+       int i;
+
+       config_erase_block();
+       config_record_count = 0;
+       for(i=0;i<CONFIG_KEY_COUNT;i++) {
+               if(config_values[i] != config_defaults[i]) {
+                       config_write(config_record_count, (i << 8) | config_values[i]);
+                       config_record_count++;
+               }
+       }
+}
+
+unsigned char config_get(unsigned char key)
+{
+       return config_values[key];
+}
+
+void config_set(unsigned char key, unsigned char value)
+{
+       if(config_values[key] == value)
+               return;
+       config_values[key] = value;
+       if(config_record_count < FLASH_BLOCK_SIZE/2)
+               config_write(config_record_count++, (key << 8) | value);
+       else
+               config_write_all();
+}
diff --git a/software/videomixer/config.h b/software/videomixer/config.h
new file mode 100644 (file)
index 0000000..418d75a
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+enum {
+       CONFIG_KEY_RESOLUTION = 0,
+       CONFIG_KEY_BLEND_USER1,
+       CONFIG_KEY_BLEND_USER2,
+       CONFIG_KEY_BLEND_USER3,
+       CONFIG_KEY_BLEND_USER4,
+
+       CONFIG_KEY_COUNT
+};
+
+#define CONFIG_DEFAULTS { 6, 1, 2, 3, 4 }
+
+void config_init(void);
+void config_write_all(void);
+unsigned char config_get(unsigned char key);
+void config_set(unsigned char key, unsigned char value);
+
+#endif /* __CONFIG_H */
index 544d1837e1e5b3a6cc7b0863d20aa4d3ff102a59..f8537e63208aa388a31593d56889871da673fd32 100644 (file)
@@ -8,6 +8,7 @@
 #include <hw/flags.h>
 #include <console.h>
 
+#include "config.h"
 #include "ci.h"
 #include "processor.h"
 
@@ -92,8 +93,9 @@ int main(void)
        
        printf("Mixxeo software rev. %08x built "__DATE__" "__TIME__"\n\n", GIT_ID);
        
+       config_init();
        time_init();
-       processor_start(6);
+       processor_start(config_get(CONFIG_KEY_RESOLUTION));
 
        while(1) {
                processor_service();