The codebase to run the *spark d-fuser controller www.sparkav.co.uk/dvimixer

Dependencies:   SPK-TVOne DMX DmxArtNet NetServicesMin OSC PinDetect mRotaryEncoder iniparser mbed spk_oled_ssd1305 filter

Revision:
51:98cc27390484
Parent:
50:e98220a71065
Child:
52:98f557fe93a3
--- a/main.cpp	Tue Dec 11 20:18:09 2012 +0000
+++ b/main.cpp	Mon Dec 17 18:22:07 2012 +0000
@@ -173,10 +173,13 @@
 enum { commsNone, commsOSC, commsArtNet, commsDMXIn, commsDMXOut};
 int commsMode = commsNone;
 
+SPKMenu troubleshootingMenu;
+SPKMenu troubleshootingMenuHDCP;
+SPKMenu troubleshootingMenuEDID;
+SPKMenu troubleshootingMenuReset;
+
 SPKMenu advancedMenu;
-SPKMenu advancedMenuHDCP;
-SPKMenu advancedMenuEDID;
-enum { advancedHDCPOn, advancedHDCPOff, advancedEDIDPassthrough, advancedEDIDInternal, advancedTestSources, advancedConformProcessor, advancedConformUploadProcessor, advancedLoadDefaults, advancedSetResolutions };
+enum { advancedConformUploadProcessor, advancedSetResolutions };
 
 // RJ45 Comms
 enum { rj45Ethernet = 0, rj45DMX = 1}; // These values from circuit
@@ -310,8 +313,8 @@
     int xFadeDMX = dmx->get(kDMXInChannelXFade);
     int fadeUpDMX = dmx->get(kDMXInChannelFadeUp);
 
-    xFade = (float)xFadeDMX/255.0f;
-    fadeUp = (float)fadeUpDMX/255.0f;
+    xFade = (float)xFadeDMX/255;
+    fadeUp = (float)fadeUpDMX/255;
 
     screen.clearBufferRow(kCommsStatusLine);
     snprintf(statusMessageBuffer, kStringBufferLength, "DMX In: xF %3i fUp %3i", xFadeDMX, fadeUpDMX);
@@ -324,8 +327,8 @@
 {
     char statusMessageBuffer[kStringBufferLength];
 
-    int xFadeDMX = xFade*255.0f;
-    int fadeUpDMX = fadeUp*255.0f;
+    int xFadeDMX = xFade*255;
+    int fadeUpDMX = fadeUp*255;
     
     dmx->put(kDMXOutChannelXFade, xFadeDMX);
     dmx->put(kDMXOutChannelFadeUp, fadeUpDMX);
@@ -407,13 +410,32 @@
         notOKCounter = 0;
         tvOne.resetCommandPeriods();
     }
-    else if (++notOKCounter == 5) 
+    else 
     {
-        printf("Handling 5x Not OK: increasing command periods\r\n");
-        tvOne.increaseCommandPeriods(1500);
+        notOKCounter++;
+        if (notOKCounter == 5)
+        {
+            tvOne.increaseCommandPeriods(200);
+        }
+        if (notOKCounter == 6)
+        {
+            tvOne.resetCommandPeriods();
+        }
+        if (notOKCounter % 15 == 0)
+        {
+            tvOneStatusMessage.addMessage("TVOne: Resetting link", 2.0f);
+            screen.textToBuffer(tvOneStatusMessage.message(), kTVOneStatusLine);
+            screen.sendBuffer();
+            
+            tvOne.increaseCommandPeriods(1000);
+        }
+        if (notOKCounter % 15 == 1)
+        {
+            tvOne.resetCommandPeriods();
+        }
     }
     
-    return ok;       
+    return ok;
 }   
 
 bool setKeyParamsTo(int index) 
@@ -730,7 +752,7 @@
     }
 }
 
-void advancedMenuHDCPHandler(int change, bool action)
+void troubleshootingMenuHDCPHandler(int change, bool action)
 {
     static int currentHDCP;
     static unsigned int state = 1;
@@ -795,7 +817,7 @@
         }
         
         // Get back to menu
-        selectedMenu = &advancedMenu;
+        selectedMenu = &troubleshootingMenu;
         
         screen.clearBufferRow(kMenuLine1);
         screen.clearBufferRow(kMenuLine2);
@@ -804,7 +826,7 @@
     }
 }
 
-void advancedMenuEDIDHandler(int change, bool action)
+void troubleshootingMenuEDIDHandler(int change, bool action)
 {
     static int currentEDIDPassthrough;
     static unsigned int state = 1;
@@ -836,7 +858,7 @@
     char paramLine[kStringBufferLength];
     screen.clearBufferRow(kMenuLine2);
     
-    const char* current = currentEDIDPassthrough == -1 ? "Mixed" : ( currentEDIDPassthrough == 1 ? "Thru" : "Int");
+    const char* current = currentEDIDPassthrough == -1 ? "Mixed" : ( currentEDIDPassthrough == 1 ? "Thru" : "Internal");
     
     if (state % 2) snprintf(paramLine, kStringBufferLength, "%s. Set: [%s/      ]?", current, currentEDIDPassthrough == 0 ? "Thru" : "Int");
     else           snprintf(paramLine, kStringBufferLength, "%s. Set: [   /Cancel]?", current);      
@@ -869,7 +891,7 @@
         }
             
         // Get back to menu
-        selectedMenu = &advancedMenu;
+        selectedMenu = &troubleshootingMenu;
         
         screen.clearBufferRow(kMenuLine1);
         screen.clearBufferRow(kMenuLine2);
@@ -917,6 +939,12 @@
             settings.setEditingKeyerSetValue(SPKSettings::maxU, 255);
             settings.setEditingKeyerSetValue(SPKSettings::minV, 0);
             settings.setEditingKeyerSetValue(SPKSettings::maxV, 255);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinY, 0);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxY, 255);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinU, 0);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxU, 255);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinV, 0);
+            tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxV, 255);
             actionCount++;
             state = 0;
         }
@@ -1061,9 +1089,7 @@
     }
     else if (actionCount == 8)
     {
-        // Work in progress: persistence
-        bool ok = settings.saveEditingKeyerSet("keySaves.ini");
-        if (debug) debug->printf("Saved: %s\r\n", ok ? "yes" : "no");
+        // A save dialog would go here
         
         // Get back to menu
         actionCount = 0;
@@ -1075,6 +1101,131 @@
     }
 }
 
+void troubleshootingMenuResetHandler(int menuChange, bool action)
+{
+    static int actionCount = 0;
+    static unsigned int state = 0;
+    
+    if (action) actionCount++;
+    
+    if (actionCount == 0)
+    {
+        screen.clearBufferRow(kMenuLine2);
+        
+        state += menuChange;
+        switch (state % 2) 
+        {
+            case 0: screen.textToBuffer("1. Controller [Reset/    ]", kMenuLine2); break;
+            case 1: screen.textToBuffer("1. Controller [     /Skip]", kMenuLine2); break;
+        }
+    }
+    if (actionCount == 1)
+    {
+        state = state % 2;
+        
+        if (state == 0) 
+        {
+            tvOneRGB1Stable = false;
+            tvOneRGB2Stable = false;
+            handleTVOneSources();
+            
+            settings.editingKeyerSetIndex = -1;
+            keyerParamsSet = -1;
+            bool ok = settings.load(kSPKDFSettingsFilename);
+            if (!ok) settings.loadDefaults();
+            
+            setMixModeMenuItems();
+            setResolutionMenuItems();
+            
+            actionCount++;
+        }
+        else if (state == 1)
+        {
+            actionCount++;
+        }
+        
+        state = 0;
+    }
+    if (actionCount == 2)
+    {
+        screen.clearBufferRow(kMenuLine2);
+        
+        state += menuChange;
+        switch (state % 2) 
+        {
+            case 0: screen.textToBuffer("2. Processor [Reset/    ]", kMenuLine2); break;
+            case 1: screen.textToBuffer("2. Processor [     /Skip]", kMenuLine2); break;
+        }  
+    }
+    if (actionCount == 3)
+    {
+        state = state % 2;
+        
+        if (state == 0) 
+        {
+            screen.clearBufferRow(kMenuLine2);
+            screen.textToBuffer("Find MENU+STANDBY buttons", kMenuLine2);
+        }
+        else if (state == 1)
+        {
+            actionCount = actionCount + 3; // extra stage to skip
+        }
+        
+        state = 0;
+    }
+    if (actionCount == 4)
+    {
+        Timer timer;
+        timer.start();
+        
+        while (timer.read_ms() < 16000)
+        {
+            screen.clearBufferRow(kMenuLine2);
+            char messageBuffer[kStringBufferLength];
+            snprintf(messageBuffer, kStringBufferLength,"Hold buttons for [%i sec]", 15 - (timer.read_ms() / 1000));
+            screen.textToBuffer(messageBuffer, kMenuLine2);
+            screen.sendBuffer();
+        }
+        
+        screen.clearBufferRow(kMenuLine2);
+        screen.textToBuffer("Hold buttons for [NEXT]", kMenuLine2);
+    }
+    if (actionCount == 5)
+    {
+        screen.clearBufferRow(kMenuLine2);
+        screen.textToBuffer("Updating processor [---]", kMenuLine2);
+        screen.clearBufferRow(kTVOneStatusLine);
+        screen.textToBuffer("Sending...", kTVOneStatusLine);
+        screen.sendBuffer();
+    
+        bool ok = conformProcessor();
+        
+        std::string sendOK = ok ? "TVOne: Reset success" : "Send Error: Reset";
+    
+        tvOneStatusMessage.addMessage(sendOK, kTVOneStatusMessageHoldTime);
+        
+        tvOneRGB1Stable = false;
+        tvOneRGB2Stable = false;
+        handleTVOneSources();
+        
+        actionCount++;
+    }
+    if (actionCount == 6)
+    {
+        screen.textToBuffer("3. No more steps [DONE]", kMenuLine2);
+    }
+    if (actionCount == 7)
+    {
+        // Get back to menu
+        actionCount = 0;
+        selectedMenu = &troubleshootingMenu;
+        screen.clearBufferRow(kMenuLine1);
+        screen.clearBufferRow(kMenuLine2);
+        screen.textToBuffer(selectedMenu->title, kMenuLine1);
+        screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2);
+    }
+}
+
 int main() 
 {
     if (debug) 
@@ -1122,24 +1273,28 @@
     commsMenu.title = "Network Mode";
     setCommsMenuItems();
     
-    advancedMenu.title = "Troubleshooting"; 
-    advancedMenuHDCP.title = "HDCP - Can Block DVI";
-    advancedMenuHDCP.addMenuItem(SPKMenuItem(&advancedMenuHDCPHandler));
-    advancedMenu.addMenuItem(SPKMenuItem(advancedMenuHDCP.title, &advancedMenuHDCP));
-    advancedMenuEDID.title = "EDID - Advertises Res's";
-    advancedMenuEDID.addMenuItem(SPKMenuItem(advancedMenuEDIDHandler));
-    advancedMenu.addMenuItem(SPKMenuItem(advancedMenuEDID.title, &advancedMenuEDID));
-    //advancedMenu.addMenuItem(SPKMenuItem("Test Processor Sources", advancedTestSources));
-    //if (settingsAreCustom) advancedMenu.addMenuItem(SPKMenuItem("Revert Controller", advancedLoadDefaults));
-    advancedMenu.addMenuItem(SPKMenuItem("Revert Processor", advancedConformProcessor));
-    advancedMenu.addMenuItem(SPKMenuItem("Conform Processor", advancedConformUploadProcessor));
-    advancedMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
+    advancedMenu.title = "Advanced Commands";
+    advancedMenu.addMenuItem(SPKMenuItem("Processor full conform", advancedConformUploadProcessor));
+    advancedMenu.addMenuItem(SPKMenuItem("Back to Troubleshooting Menu", &troubleshootingMenu));
+    
+    troubleshootingMenu.title = "Troubleshooting"; 
+    troubleshootingMenuHDCP.title = "HDCP - Can Block DVI";
+    troubleshootingMenuHDCP.addMenuItem(SPKMenuItem(&troubleshootingMenuHDCPHandler));
+    troubleshootingMenu.addMenuItem(SPKMenuItem(troubleshootingMenuHDCP.title, &troubleshootingMenuHDCP));
+    troubleshootingMenuEDID.title = "EDID - Advertises Res's";
+    troubleshootingMenuEDID.addMenuItem(SPKMenuItem(troubleshootingMenuEDIDHandler));
+    troubleshootingMenu.addMenuItem(SPKMenuItem(troubleshootingMenuEDID.title, &troubleshootingMenuEDID));
+    troubleshootingMenuReset.title = "Output - Mixing Wrong";
+    troubleshootingMenuReset.addMenuItem(SPKMenuItem(&troubleshootingMenuResetHandler));
+    troubleshootingMenu.addMenuItem(SPKMenuItem(troubleshootingMenuReset.title, &troubleshootingMenuReset));
+    troubleshootingMenu.addMenuItem(SPKMenuItem(advancedMenu.title, &advancedMenu));
+    troubleshootingMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
     
     mainMenu.title = "Main Menu";
     mainMenu.addMenuItem(SPKMenuItem(mixModeMenu.title, &mixModeMenu));
     mainMenu.addMenuItem(SPKMenuItem(resolutionMenu.title, &resolutionMenu));
     mainMenu.addMenuItem(SPKMenuItem(commsMenu.title, &commsMenu));
-    mainMenu.addMenuItem(SPKMenuItem(advancedMenu.title, &advancedMenu));
+    mainMenu.addMenuItem(SPKMenuItem(troubleshootingMenu.title, &troubleshootingMenu));
       
     selectedMenu = &mainMenu;
       
@@ -1427,41 +1582,7 @@
             }
             else if (selectedMenu == &advancedMenu)
             {
-                if (advancedMenu.selectedItem().payload.command[0] == advancedHDCPOff)
-                {
-                    // Has handler
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedHDCPOn)
-                {
-                    // Has handler
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedEDIDPassthrough)
-                {
-                    // Has handler
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedEDIDInternal)
-                {
-                    // Has handler
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedTestSources)
-                {   
-                    tvOneRGB1Stable = false;
-                    tvOneRGB2Stable = false;
-                    handleTVOneSources();
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedConformProcessor)
-                {
-                    screen.clearBufferRow(kTVOneStatusLine);
-                    screen.textToBuffer("Reverting...", kTVOneStatusLine);
-                    screen.sendBuffer();
-                    
-                    bool ok = conformProcessor();
-                    
-                    std::string sendOK = ok ? "Reverting success" : "Send Error: Revert";
-                    
-                    tvOneStatusMessage.addMessage(sendOK, kTVOneStatusMessageHoldTime);
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedConformUploadProcessor)
+                if (advancedMenu.selectedItem().payload.command[0] == advancedConformUploadProcessor)
                 {
                     bool ok = true;
                 
@@ -1481,21 +1602,13 @@
                     
                     tvOneStatusMessage.addMessage(sendOK, kTVOneStatusMessageHoldTime);
                 }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedLoadDefaults)
-                {
-                    settings.loadDefaults();
-                    setMixModeMenuItems();
-                    setResolutionMenuItems();
-                    
-                    tvOneStatusMessage.addMessage("Controller Reverted", kTVOneStatusMessageHoldTime);
-                }
-                else if (advancedMenu.selectedItem().payload.command[0] == advancedSetResolutions)
-                {
-                    bool ok;
-                    ok = tvOne.uploadCustomResolutions();
-                    
-                    tvOneStatusMessage.addMessage(ok ? "Resolutions set" : "Res' could not be set", kTVOneStatusMessageHoldTime);
-                }
+//                else if (advancedMenu.selectedItem().payload.command[0] == advancedSetResolutions)
+//                {
+//                    bool ok;
+//                    ok = tvOne.uploadCustomResolutions();
+//                    
+//                    tvOneStatusMessage.addMessage(ok ? "Resolutions set" : "Res' could not be set", kTVOneStatusMessageHoldTime);
+//                }
             }
             else
             {
@@ -1588,9 +1701,20 @@
 
         if (mixMode == mixBlend) 
         {
-            // window A occludes B. this is fast as only A changes with xFade.
-            newFadeAPercent = (1.0-xFade) * fadeUp * 100.0;
-            newFadeBPercent = fadeUp * 100.0;
+            // This is the correct algorithm for blend where window A occludes B.
+            // Who knew a crossfade could be so tricky. The level of B has to be factored by what A is letting through.
+            // ie. if fully faded up, top window = xfade, bottom window = 100%
+            // This will however look very wrong if A is not occluding B, ie. mismatched aspect ratios.
+            if (xFade > 0) // avoids div by zero (if xFade = 0 and fadeUp = 1, B sum = 0 / 0)
+            {
+                newFadeAPercent = (1.0-xFade) * fadeUp * 100.0;
+                newFadeBPercent = (xFade*fadeUp) / (1.0 - fadeUp + xFade*fadeUp) * 100.0;
+            }
+            else
+            {
+                newFadeAPercent = fadeUp * 100.0;
+                newFadeBPercent = 0;
+            }
         }
         else if (mixMode == mixAdditive)
         {