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

Committer:
tobyspark
Date:
Sun Nov 04 00:52:38 2012 +0000
Revision:
32:9f9eb3583bfa
Parent:
31:01845a2347ff
Child:
33:e6672a9bd571
Excised Self-Test, which ended up being a separate program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tobyspark 8:d46cc49f0f37 1 /* *SPARK D-FUSER
tobyspark 8:d46cc49f0f37 2 * A project by Toby Harris
tobyspark 8:d46cc49f0f37 3 *
tobyspark 8:d46cc49f0f37 4 * 'DJ' controller styke RS232 Control for TV-One products
tobyspark 8:d46cc49f0f37 5 * Good for 1T-C2-750, others will need some extra work
tobyspark 8:d46cc49f0f37 6 *
tobyspark 8:d46cc49f0f37 7 * www.sparkav.co.uk/dvimixer
tobyspark 8:d46cc49f0f37 8 */
tobyspark 0:87aab40d5806 9
tobyspark 8:d46cc49f0f37 10 /* Copyright (c) 2011 Toby Harris, MIT License
tobyspark 8:d46cc49f0f37 11 *
tobyspark 8:d46cc49f0f37 12 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
tobyspark 8:d46cc49f0f37 13 * and associated documentation files (the "Software"), to deal in the Software without restriction,
tobyspark 8:d46cc49f0f37 14 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
tobyspark 8:d46cc49f0f37 15 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
tobyspark 8:d46cc49f0f37 16 * furnished to do so, subject to the following conditions:
tobyspark 8:d46cc49f0f37 17 *
tobyspark 8:d46cc49f0f37 18 * The above copyright notice and this permission notice shall be included in all copies or
tobyspark 8:d46cc49f0f37 19 * substantial portions of the Software.
tobyspark 8:d46cc49f0f37 20 *
tobyspark 8:d46cc49f0f37 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
tobyspark 8:d46cc49f0f37 22 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
tobyspark 8:d46cc49f0f37 23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
tobyspark 8:d46cc49f0f37 24 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
tobyspark 8:d46cc49f0f37 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
tobyspark 8:d46cc49f0f37 26 */
tobyspark 8:d46cc49f0f37 27
tobyspark 8:d46cc49f0f37 28 /* ROADMAP / HISTORY
tobyspark 8:d46cc49f0f37 29 * v10 - Port to mBed, keying redux - Apr'11
tobyspark 8:d46cc49f0f37 30 * v11 - Sign callbacks, code clean-up - Apr'11
tobyspark 8:d46cc49f0f37 31 * v12 - TVOne header split into two: defines and mbed class. v002 header updates pulled down. Removed sign callbacks, rewrite of debug and signing. - Apr'11
tobyspark 8:d46cc49f0f37 32 * v13 - Menu system for Resolution + Keying implemented, it writing to debug, it sending TVOne commands - Apr'11
tobyspark 8:d46cc49f0f37 33 * v14 - Fixes for new PCB - Oct'11
tobyspark 8:d46cc49f0f37 34 * v15 - TBZ PCB, OLED - Mar'12
tobyspark 8:d46cc49f0f37 35 * v16 - Comms menu, OSC, ArtNet - April'12
tobyspark 8:d46cc49f0f37 36 * v17 - RJ45 - May'12
tobyspark 8:d46cc49f0f37 37 * v18 - DMX - July'12
tobyspark 13:3796bde6ba8f 38 * v19 - TVOne mixing comms further optimised - August'12
tobyspark 30:873979018850 39 * v20 - Keying values and resolutions load from USB mass storage - September'12
tobyspark 30:873979018850 40 * v21 - Mixing behaviour upgrade: blend-additive as continuum, test cards on startup if no valid source - October'12
tobyspark 10:c011b0e5c17e 41 * vxx - TODO: Set keying values from controller, requires a guided, step-through process for user
tobyspark 8:d46cc49f0f37 42 * vxx - TODO: Defaults load/save from USB mass storage
tobyspark 30:873979018850 43 * vxx - TODO: EDID passthrough override
tobyspark 8:d46cc49f0f37 44 * vxx - TODO: EDID upload from USB mass storage
tobyspark 8:d46cc49f0f37 45 * vxx - TODO: EDID creation from resolution
tobyspark 8:d46cc49f0f37 46 */
tobyspark 8:d46cc49f0f37 47
tobyspark 0:87aab40d5806 48 #include "mbed.h"
tobyspark 0:87aab40d5806 49
tobyspark 0:87aab40d5806 50 #include "spk_tvone_mbed.h"
tobyspark 0:87aab40d5806 51 #include "spk_utils.h"
tobyspark 0:87aab40d5806 52 #include "spk_mRotaryEncoder.h"
tobyspark 0:87aab40d5806 53 #include "spk_oled_ssd1305.h"
tobyspark 2:50043054e4f7 54 #include "spk_oled_gfx.h"
tobyspark 11:0783cfbeb746 55 #include "spk_settings.h"
tobyspark 1:f9fca21102e0 56 #include "EthernetNetIf.h"
tobyspark 1:f9fca21102e0 57 #include "mbedOSC.h"
tobyspark 3:033d2b7768f3 58 #include "DmxArtNet.h"
tobyspark 5:f8b285ca41ba 59 #include "DMX.h"
tobyspark 17:fc68d40b8b1f 60 #include "filter.h"
tobyspark 0:87aab40d5806 61
tobyspark 30:873979018850 62 #define kSPKDFSoftwareVersion "21"
tobyspark 13:3796bde6ba8f 63
tobyspark 5:f8b285ca41ba 64 // MBED PINS
tobyspark 5:f8b285ca41ba 65
tobyspark 5:f8b285ca41ba 66 #define kMBED_AIN_XFADE p20
tobyspark 5:f8b285ca41ba 67 #define kMBED_AIN_FADEUP p19
tobyspark 5:f8b285ca41ba 68 #define kMBED_DIN_TAP_L p24
tobyspark 5:f8b285ca41ba 69 #define kMBED_DIN_TAP_R p23
tobyspark 5:f8b285ca41ba 70 #define kMBED_ENC_SW p15
tobyspark 5:f8b285ca41ba 71 #define kMBED_ENC_A p16
tobyspark 5:f8b285ca41ba 72 #define kMBED_ENC_B p17
tobyspark 5:f8b285ca41ba 73
tobyspark 5:f8b285ca41ba 74 #define kMBED_RS232_TTLTX p13
tobyspark 5:f8b285ca41ba 75 #define kMBED_RS232_TTLRX p14
tobyspark 5:f8b285ca41ba 76
tobyspark 5:f8b285ca41ba 77 #define kMBED_OLED_MOSI p5
tobyspark 5:f8b285ca41ba 78 #define kMBED_OLED_SCK p7
tobyspark 5:f8b285ca41ba 79 #define kMBED_OLED_CS p8
tobyspark 5:f8b285ca41ba 80 #define kMBED_OLED_RES p9
tobyspark 5:f8b285ca41ba 81 #define kMBED_OLED_DC p10
tobyspark 5:f8b285ca41ba 82
tobyspark 5:f8b285ca41ba 83 #define kMBED_DIN_ETHLO_DMXHI p30
tobyspark 5:f8b285ca41ba 84 #define kMBED_DOUT_RS485_TXHI_RXLO p29
tobyspark 5:f8b285ca41ba 85 #define kMBED_RS485_TTLTX p28
tobyspark 5:f8b285ca41ba 86 #define kMBED_RS485_TTLRX p27
tobyspark 5:f8b285ca41ba 87
tobyspark 5:f8b285ca41ba 88 // DISPLAY
tobyspark 5:f8b285ca41ba 89
tobyspark 1:f9fca21102e0 90 #define kMenuLine1 3
tobyspark 1:f9fca21102e0 91 #define kMenuLine2 4
tobyspark 1:f9fca21102e0 92 #define kCommsStatusLine 6
tobyspark 1:f9fca21102e0 93 #define kTVOneStatusLine 7
tobyspark 1:f9fca21102e0 94
tobyspark 5:f8b285ca41ba 95 // NETWORKING
tobyspark 5:f8b285ca41ba 96
tobyspark 1:f9fca21102e0 97 #define kOSCMbedPort 10000
tobyspark 1:f9fca21102e0 98 #define kOSCMbedIPAddress 10,0,0,2
tobyspark 1:f9fca21102e0 99 #define kOSCMbedSubnetMask 255,255,255,0
tobyspark 1:f9fca21102e0 100 #define kOSCMbedGateway 10,0,0,1
tobyspark 1:f9fca21102e0 101 #define kOSCMbedDNS 10,0,0,1
tobyspark 0:87aab40d5806 102
tobyspark 3:033d2b7768f3 103 #define kArtNetBindIPAddress 2,0,0,100
tobyspark 3:033d2b7768f3 104 #define kArtNetBroadcastAddress 2,255,255,255
tobyspark 3:033d2b7768f3 105
tobyspark 5:f8b285ca41ba 106 #define kDMXInChannelXFade 0
tobyspark 5:f8b285ca41ba 107 #define kDMXInChannelFadeUp 1
tobyspark 5:f8b285ca41ba 108 #define kDMXOutChannelXFade 0
tobyspark 5:f8b285ca41ba 109 #define kDMXOutChannelFadeUp 1
tobyspark 5:f8b285ca41ba 110
tobyspark 13:3796bde6ba8f 111 // 8.3 format filename only, no subdirs
tobyspark 13:3796bde6ba8f 112 #define kSPKDFSettingsFilename "SPKDF.ini"
tobyspark 11:0783cfbeb746 113
tobyspark 26:0299f8760715 114 #define kStringBufferLength 30
tobyspark 26:0299f8760715 115
tobyspark 0:87aab40d5806 116 //// DEBUG
tobyspark 0:87aab40d5806 117
tobyspark 0:87aab40d5806 118 // Comment out one or the other...
tobyspark 32:9f9eb3583bfa 119 //Serial *debug = new Serial(USBTX, USBRX); // For debugging via USB serial
tobyspark 32:9f9eb3583bfa 120 Serial *debug = NULL; // For release (no debugging)
tobyspark 0:87aab40d5806 121
tobyspark 15:4b394c64b461 122 //// SOFT RESET
tobyspark 15:4b394c64b461 123
tobyspark 15:4b394c64b461 124 extern "C" void mbed_reset();
tobyspark 15:4b394c64b461 125
tobyspark 0:87aab40d5806 126 //// mBED PIN ASSIGNMENTS
tobyspark 0:87aab40d5806 127
tobyspark 0:87aab40d5806 128 // Inputs
tobyspark 5:f8b285ca41ba 129 AnalogIn xFadeAIN(kMBED_AIN_XFADE);
tobyspark 5:f8b285ca41ba 130 AnalogIn fadeUpAIN(kMBED_AIN_FADEUP);
tobyspark 5:f8b285ca41ba 131 DigitalIn tapLeftDIN(kMBED_DIN_TAP_L);
tobyspark 5:f8b285ca41ba 132 DigitalIn tapRightDIN(kMBED_DIN_TAP_R);
tobyspark 17:fc68d40b8b1f 133 medianFilter xFadeFilter(9);
tobyspark 17:fc68d40b8b1f 134 medianFilter fadeUpFilter(9);
tobyspark 0:87aab40d5806 135
tobyspark 5:f8b285ca41ba 136 SPKRotaryEncoder menuEnc(kMBED_ENC_A, kMBED_ENC_B, kMBED_ENC_SW);
tobyspark 5:f8b285ca41ba 137
tobyspark 5:f8b285ca41ba 138 DigitalIn rj45ModeDIN(kMBED_DIN_ETHLO_DMXHI);
tobyspark 0:87aab40d5806 139
tobyspark 0:87aab40d5806 140 // Outputs
tobyspark 0:87aab40d5806 141 PwmOut fadeAPO(LED1);
tobyspark 0:87aab40d5806 142 PwmOut fadeBPO(LED2);
tobyspark 0:87aab40d5806 143
tobyspark 5:f8b285ca41ba 144 DigitalOut dmxDirectionDOUT(kMBED_DOUT_RS485_TXHI_RXLO);
tobyspark 5:f8b285ca41ba 145
tobyspark 0:87aab40d5806 146 // SPKTVOne(PinName txPin, PinName rxPin, PinName signWritePin, PinName signErrorPin, Serial *debugSerial)
tobyspark 5:f8b285ca41ba 147 SPKTVOne tvOne(kMBED_RS232_TTLTX, kMBED_RS232_TTLRX, LED3, LED4, debug);
tobyspark 0:87aab40d5806 148
tobyspark 0:87aab40d5806 149 // SPKDisplay(PinName mosi, PinName clk, PinName cs, PinName dc, PinName res, Serial *debugSerial = NULL);
tobyspark 5:f8b285ca41ba 150 SPKDisplay screen(kMBED_OLED_MOSI, kMBED_OLED_SCK, kMBED_OLED_CS, kMBED_OLED_DC, kMBED_OLED_RES, debug);
tobyspark 0:87aab40d5806 151
tobyspark 11:0783cfbeb746 152 // Saved Settings
tobyspark 11:0783cfbeb746 153 SPKSettings settings;
tobyspark 11:0783cfbeb746 154
tobyspark 0:87aab40d5806 155 // Menu
tobyspark 0:87aab40d5806 156 SPKMenu *selectedMenu;
tobyspark 23:909928cafb95 157 SPKMenu mainMenu;
tobyspark 23:909928cafb95 158 SPKMenu resolutionMenu;
tobyspark 12:c270870bdd23 159
tobyspark 24:49c6624119ae 160 SPKMenu mixModeMenu;
tobyspark 24:49c6624119ae 161 SPKMenu mixModeAdditiveMenu;
tobyspark 30:873979018850 162 enum { mixBlend, mixAdditive, mixKey }; // additive will require custom TVOne firmware.
tobyspark 30:873979018850 163 int mixMode = mixBlend; // Start with safe mix mode, and test to get out of it. Safe mode will work with inputs missing and without hold frames.
tobyspark 29:95a7efe30527 164 float fadeCurve = 0.0f; // 0 = "X", ie. as per blend, 1 = "/\", ie. as per additive <-- pictograms!
tobyspark 22:90054fe6d86c 165
tobyspark 23:909928cafb95 166 SPKMenu commsMenu;
tobyspark 5:f8b285ca41ba 167 enum { commsNone, commsOSC, commsArtNet, commsDMXIn, commsDMXOut};
tobyspark 5:f8b285ca41ba 168 int commsMode = commsNone;
tobyspark 22:90054fe6d86c 169
tobyspark 23:909928cafb95 170 SPKMenu advancedMenu;
tobyspark 32:9f9eb3583bfa 171 enum { advancedHDCPOn, advancedHDCPOff, advancedEDIDPassthrough, advancedEDIDInternal, advancedTestSources, advancedConformProcessor, advancedLoadDefaults, advancedSetResolutions };
tobyspark 1:f9fca21102e0 172
tobyspark 5:f8b285ca41ba 173 // RJ45 Comms
tobyspark 5:f8b285ca41ba 174 enum { rj45Ethernet = 0, rj45DMX = 1}; // These values from circuit
tobyspark 5:f8b285ca41ba 175 int rj45Mode = -1;
tobyspark 1:f9fca21102e0 176 EthernetNetIf *ethernet = NULL;
tobyspark 1:f9fca21102e0 177 OSCClass *osc = NULL;
tobyspark 3:033d2b7768f3 178 OSCMessage recMessage;
tobyspark 3:033d2b7768f3 179 DmxArtNet *artNet = NULL;
tobyspark 5:f8b285ca41ba 180 DMX *dmx = NULL;
tobyspark 0:87aab40d5806 181
tobyspark 3:033d2b7768f3 182 // Fade logic constants
tobyspark 0:87aab40d5806 183 const float xFadeTolerance = 0.05;
tobyspark 0:87aab40d5806 184 const float fadeUpTolerance = 0.05;
tobyspark 0:87aab40d5806 185
tobyspark 0:87aab40d5806 186 // A&B Fade as resolved percent
tobyspark 0:87aab40d5806 187 int fadeAPercent = 0;
tobyspark 0:87aab40d5806 188 int fadeBPercent = 0;
tobyspark 17:fc68d40b8b1f 189 int oldFadeAPercent = 0;
tobyspark 17:fc68d40b8b1f 190 int oldFadeBPercent = 0;
tobyspark 0:87aab40d5806 191
tobyspark 0:87aab40d5806 192 // Tap button states
tobyspark 5:f8b285ca41ba 193 bool tapLeftWasFirstPressed = false;
tobyspark 0:87aab40d5806 194
tobyspark 0:87aab40d5806 195 // Key mode parameters
tobyspark 0:87aab40d5806 196 int keyerParamsSet = -1; // last keyParams index uploaded to unit
tobyspark 0:87aab40d5806 197
tobyspark 30:873979018850 198 // TVOne input sources stable flag
tobyspark 30:873979018850 199 bool tvOneRGB1Stable = true; // init true as this is conformed state of mixer, ie. RGB1 not SIS1
tobyspark 30:873979018850 200 bool tvOneRGB2Stable = true;
tobyspark 30:873979018850 201
tobyspark 31:01845a2347ff 202 // TVOne behaviour flags
tobyspark 31:01845a2347ff 203 bool tvOneHDCPOn = false;
tobyspark 31:01845a2347ff 204 bool tvOneEDIDPassthrough = true;
tobyspark 31:01845a2347ff 205 const int32_t EDIDPassthroughSlot = 7;
tobyspark 31:01845a2347ff 206
tobyspark 3:033d2b7768f3 207 void processOSC(float &xFade, float &fadeUp) {
tobyspark 25:3b519ef70341 208 string statusMessage;
tobyspark 3:033d2b7768f3 209
tobyspark 3:033d2b7768f3 210 if (!strcmp( recMessage.getTopAddress() , "dvimxr" ))
tobyspark 3:033d2b7768f3 211 {
tobyspark 25:3b519ef70341 212 statusMessage = "OSC: /dvimxr";
tobyspark 3:033d2b7768f3 213 if (!strcmp( recMessage.getSubAddress() , "xFade" ))
tobyspark 25:3b519ef70341 214 {
tobyspark 25:3b519ef70341 215 if (recMessage.getArgNum() == 1)
tobyspark 25:3b519ef70341 216 if (recMessage.getTypeTag(0) == 'f')
tobyspark 25:3b519ef70341 217 {
tobyspark 25:3b519ef70341 218 xFade = recMessage.getArgFloat(0);
tobyspark 25:3b519ef70341 219 char buffer[15];
tobyspark 26:0299f8760715 220 snprintf(buffer, kStringBufferLength, "/xFade %1.2f", xFade);
tobyspark 25:3b519ef70341 221 statusMessage += buffer;
tobyspark 25:3b519ef70341 222 }
tobyspark 25:3b519ef70341 223 }
tobyspark 25:3b519ef70341 224 else if (!strcmp( recMessage.getSubAddress() , "fadeUp" ))
tobyspark 25:3b519ef70341 225 {
tobyspark 3:033d2b7768f3 226 if (recMessage.getArgNum() == 1)
tobyspark 3:033d2b7768f3 227 if (recMessage.getTypeTag(0) == 'f')
tobyspark 3:033d2b7768f3 228 {
tobyspark 25:3b519ef70341 229 fadeUp = recMessage.getArgFloat(0);
tobyspark 25:3b519ef70341 230 char buffer[15];
tobyspark 26:0299f8760715 231 snprintf(buffer, kStringBufferLength, "/fadeUp %1.2f", fadeUp);
tobyspark 25:3b519ef70341 232 statusMessage += buffer;
tobyspark 3:033d2b7768f3 233 }
tobyspark 25:3b519ef70341 234 }
tobyspark 25:3b519ef70341 235 else
tobyspark 25:3b519ef70341 236 {
tobyspark 25:3b519ef70341 237 statusMessage += recMessage.getSubAddress();
tobyspark 25:3b519ef70341 238 statusMessage += " - Ignoring";
tobyspark 25:3b519ef70341 239 }
tobyspark 3:033d2b7768f3 240 }
tobyspark 3:033d2b7768f3 241 else
tobyspark 3:033d2b7768f3 242 {
tobyspark 25:3b519ef70341 243 statusMessage = "OSC: ";
tobyspark 25:3b519ef70341 244 statusMessage += recMessage.getTopAddress();
tobyspark 25:3b519ef70341 245 statusMessage += " - Ignoring";
tobyspark 3:033d2b7768f3 246 }
tobyspark 3:033d2b7768f3 247
tobyspark 3:033d2b7768f3 248 screen.clearBufferRow(kCommsStatusLine);
tobyspark 25:3b519ef70341 249 screen.textToBuffer(statusMessage, kCommsStatusLine);
tobyspark 3:033d2b7768f3 250 screen.sendBuffer();
tobyspark 25:3b519ef70341 251 if (debug) debug->printf("%s \r\n", statusMessage.c_str());
tobyspark 3:033d2b7768f3 252
tobyspark 3:033d2b7768f3 253 }
tobyspark 3:033d2b7768f3 254
tobyspark 8:d46cc49f0f37 255 void processArtNet(float &xFade, float &fadeUp)
tobyspark 8:d46cc49f0f37 256 {
tobyspark 3:033d2b7768f3 257 screen.clearBufferRow(kCommsStatusLine);
tobyspark 3:033d2b7768f3 258 screen.textToBuffer("ArtNet activity", kCommsStatusLine);
tobyspark 3:033d2b7768f3 259 screen.sendBuffer();
tobyspark 3:033d2b7768f3 260 if (debug) debug->printf("ArtNet activity");
tobyspark 3:033d2b7768f3 261 }
tobyspark 0:87aab40d5806 262
tobyspark 8:d46cc49f0f37 263 void processDMXIn(float &xFade, float &fadeUp)
tobyspark 8:d46cc49f0f37 264 {
tobyspark 26:0299f8760715 265 char statusMessageBuffer[kStringBufferLength];
tobyspark 5:f8b285ca41ba 266
tobyspark 5:f8b285ca41ba 267 int xFadeDMX = dmx->get(kDMXInChannelXFade);
tobyspark 7:e6717468c18d 268 int fadeUpDMX = dmx->get(kDMXInChannelFadeUp);
tobyspark 5:f8b285ca41ba 269
tobyspark 5:f8b285ca41ba 270 xFade = (float)xFadeDMX/255;
tobyspark 5:f8b285ca41ba 271 fadeUp = (float)fadeUpDMX/255;
tobyspark 5:f8b285ca41ba 272
tobyspark 5:f8b285ca41ba 273 screen.clearBufferRow(kCommsStatusLine);
tobyspark 26:0299f8760715 274 snprintf(statusMessageBuffer, kStringBufferLength, "DMX In: xF %3i fUp %3i", xFadeDMX, fadeUpDMX);
tobyspark 25:3b519ef70341 275 screen.textToBuffer(statusMessageBuffer, kCommsStatusLine);
tobyspark 5:f8b285ca41ba 276 screen.sendBuffer();
tobyspark 25:3b519ef70341 277 if (debug) debug->printf(statusMessageBuffer);
tobyspark 5:f8b285ca41ba 278 }
tobyspark 5:f8b285ca41ba 279
tobyspark 8:d46cc49f0f37 280 void processDMXOut(float &xFade, float &fadeUp)
tobyspark 8:d46cc49f0f37 281 {
tobyspark 26:0299f8760715 282 char statusMessageBuffer[kStringBufferLength];
tobyspark 5:f8b285ca41ba 283
tobyspark 5:f8b285ca41ba 284 int xFadeDMX = xFade*255;
tobyspark 5:f8b285ca41ba 285 int fadeUpDMX = fadeUp*255;
tobyspark 5:f8b285ca41ba 286
tobyspark 5:f8b285ca41ba 287 dmx->put(kDMXOutChannelXFade, xFadeDMX);
tobyspark 5:f8b285ca41ba 288 dmx->put(kDMXOutChannelFadeUp, fadeUpDMX);
tobyspark 5:f8b285ca41ba 289
tobyspark 5:f8b285ca41ba 290 screen.clearBufferRow(kCommsStatusLine);
tobyspark 26:0299f8760715 291 snprintf(statusMessageBuffer, kStringBufferLength, "DMX Out: xF %3i fUp %3i", xFadeDMX, fadeUpDMX);
tobyspark 25:3b519ef70341 292 screen.textToBuffer(statusMessageBuffer, kCommsStatusLine);
tobyspark 5:f8b285ca41ba 293 screen.sendBuffer();
tobyspark 25:3b519ef70341 294 if (debug) debug->printf(statusMessageBuffer);
tobyspark 5:f8b285ca41ba 295 }
tobyspark 0:87aab40d5806 296
tobyspark 8:d46cc49f0f37 297 inline float fadeCalc (const float AIN, const float tolerance)
tobyspark 8:d46cc49f0f37 298 {
tobyspark 0:87aab40d5806 299 float pos ;
tobyspark 0:87aab40d5806 300 if (AIN < tolerance) pos = 0;
tobyspark 0:87aab40d5806 301 else if (AIN > 1.0 - tolerance) pos = 1;
tobyspark 0:87aab40d5806 302 else pos = (AIN - tolerance) / (1 - 2*tolerance);
tobyspark 0:87aab40d5806 303 if (debug && false) debug->printf("fadeCalc in: %f out: %f \r\n", AIN, pos);
tobyspark 0:87aab40d5806 304 return pos;
tobyspark 0:87aab40d5806 305 }
tobyspark 0:87aab40d5806 306
tobyspark 31:01845a2347ff 307 bool handleTVOneSources(bool updateScreenOverride = false)
tobyspark 30:873979018850 308 {
tobyspark 30:873979018850 309 bool ok = true;
tobyspark 30:873979018850 310
tobyspark 30:873979018850 311 int32_t payload = 0;
tobyspark 30:873979018850 312
tobyspark 30:873979018850 313 ok = ok && tvOne.readCommand(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceSourceStable, payload);
tobyspark 30:873979018850 314 bool RGB1 = (payload == 1);
tobyspark 30:873979018850 315
tobyspark 30:873979018850 316 ok = ok && tvOne.readCommand(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceSourceStable, payload);
tobyspark 30:873979018850 317 bool RGB2 = (payload == 1);
tobyspark 30:873979018850 318
tobyspark 30:873979018850 319 string tvOneDetectString;
tobyspark 30:873979018850 320 if (!ok)
tobyspark 30:873979018850 321 {
tobyspark 30:873979018850 322 tvOneDetectString = "TVOne: link failed";
tobyspark 30:873979018850 323 }
tobyspark 30:873979018850 324 else if (!RGB1 || !RGB2)
tobyspark 30:873979018850 325 {
tobyspark 30:873979018850 326 if (!RGB1 && !RGB2) tvOneDetectString = "TVOne: no sources";
tobyspark 30:873979018850 327 else if (!RGB1) tvOneDetectString = "TVOne: no right source";
tobyspark 30:873979018850 328 else if (!RGB2) tvOneDetectString = "TVOne: no left source";
tobyspark 30:873979018850 329 }
tobyspark 30:873979018850 330 else
tobyspark 30:873979018850 331 {
tobyspark 30:873979018850 332 tvOneDetectString = "TVOne: OK";
tobyspark 30:873979018850 333 }
tobyspark 30:873979018850 334
tobyspark 30:873979018850 335 if (RGB1 && !tvOneRGB1Stable) tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceRGB1);
tobyspark 30:873979018850 336 if (RGB2 && !tvOneRGB2Stable) tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceRGB2);
tobyspark 30:873979018850 337 if (!RGB1 && tvOneRGB1Stable) tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceSIS1);
tobyspark 30:873979018850 338 if (!RGB2 && tvOneRGB2Stable) tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceSIS2);
tobyspark 31:01845a2347ff 339
tobyspark 31:01845a2347ff 340 if (updateScreenOverride || (RGB1 != tvOneRGB1Stable || RGB2 != tvOneRGB2Stable))
tobyspark 30:873979018850 341 {
tobyspark 30:873979018850 342 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 30:873979018850 343 screen.textToBuffer(tvOneDetectString, kTVOneStatusLine);
tobyspark 30:873979018850 344 screen.sendBuffer();
tobyspark 30:873979018850 345 }
tobyspark 30:873979018850 346
tobyspark 30:873979018850 347 tvOneRGB1Stable = RGB1;
tobyspark 30:873979018850 348 tvOneRGB2Stable = RGB2;
tobyspark 30:873979018850 349
tobyspark 30:873979018850 350 return ok;
tobyspark 30:873979018850 351 }
tobyspark 30:873979018850 352
tobyspark 8:d46cc49f0f37 353 bool setKeyParamsTo(int index)
tobyspark 8:d46cc49f0f37 354 {
tobyspark 0:87aab40d5806 355 // Only spend the time uploading six parameters if we need to
tobyspark 0:87aab40d5806 356 // Might want to bounds check here
tobyspark 0:87aab40d5806 357
tobyspark 9:f83eadd8917a 358 bool ok;
tobyspark 0:87aab40d5806 359
tobyspark 0:87aab40d5806 360 if (index != keyerParamsSet)
tobyspark 0:87aab40d5806 361 {
tobyspark 31:01845a2347ff 362 ok = tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinY, settings.keyerParamSet(index)[SPKSettings::minY]);
tobyspark 31:01845a2347ff 363 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxY, settings.keyerParamSet(index)[SPKSettings::maxY]);
tobyspark 31:01845a2347ff 364 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinU, settings.keyerParamSet(index)[SPKSettings::minU]);
tobyspark 31:01845a2347ff 365 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxU, settings.keyerParamSet(index)[SPKSettings::maxU]);
tobyspark 31:01845a2347ff 366 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMinV, settings.keyerParamSet(index)[SPKSettings::minV]);
tobyspark 31:01845a2347ff 367 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerMaxV, settings.keyerParamSet(index)[SPKSettings::maxV]);
tobyspark 0:87aab40d5806 368
tobyspark 0:87aab40d5806 369 keyerParamsSet = index;
tobyspark 9:f83eadd8917a 370 }
tobyspark 9:f83eadd8917a 371 else
tobyspark 9:f83eadd8917a 372 {
tobyspark 9:f83eadd8917a 373 ok = true;
tobyspark 9:f83eadd8917a 374 }
tobyspark 0:87aab40d5806 375
tobyspark 0:87aab40d5806 376 return ok;
tobyspark 0:87aab40d5806 377 }
tobyspark 0:87aab40d5806 378
tobyspark 24:49c6624119ae 379 void actionMixMode()
tobyspark 24:49c6624119ae 380 {
tobyspark 31:01845a2347ff 381 if (debug) debug->printf("Changing mix mode \r\n");
tobyspark 31:01845a2347ff 382
tobyspark 24:49c6624119ae 383 bool ok = true;
tobyspark 25:3b519ef70341 384 string sentOK;
tobyspark 26:0299f8760715 385 char sentMSGBuffer[kStringBufferLength];
tobyspark 24:49c6624119ae 386
tobyspark 24:49c6624119ae 387 // Set Keyer
tobyspark 24:49c6624119ae 388 if (mixMode < mixKey)
tobyspark 24:49c6624119ae 389 {
tobyspark 31:01845a2347ff 390 // Set Keyer Off. Quicker to set and fail than to test for on and then turn off
tobyspark 31:01845a2347ff 391 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerEnable, false);
tobyspark 31:01845a2347ff 392
tobyspark 31:01845a2347ff 393 if (mixMode == mixBlend)
tobyspark 24:49c6624119ae 394 {
tobyspark 31:01845a2347ff 395 // Turn off Additive Mixing on output
tobyspark 31:01845a2347ff 396 ok = tvOne.command(0, kTV1WindowIDA, 0x298, 0);
tobyspark 31:01845a2347ff 397 snprintf(sentMSGBuffer, kStringBufferLength, "Blend");
tobyspark 24:49c6624119ae 398 }
tobyspark 31:01845a2347ff 399 if (mixMode == mixAdditive)
tobyspark 31:01845a2347ff 400 {
tobyspark 31:01845a2347ff 401 // First set B to what you'd expect for additive; it may be left at 100 if optimised blend mixing was previous mixmode.
tobyspark 31:01845a2347ff 402 ok = tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsMaxFadeLevel, fadeBPercent);
tobyspark 31:01845a2347ff 403 // Then turn on Additive Mixing
tobyspark 31:01845a2347ff 404 ok = ok && tvOne.command(0, kTV1WindowIDA, 0x298, 1);
tobyspark 31:01845a2347ff 405 snprintf(sentMSGBuffer, kStringBufferLength, "Additive");
tobyspark 31:01845a2347ff 406 }
tobyspark 24:49c6624119ae 407 }
tobyspark 24:49c6624119ae 408 else
tobyspark 24:49c6624119ae 409 {
tobyspark 25:3b519ef70341 410 int index = mixMode - mixKey;
tobyspark 25:3b519ef70341 411
tobyspark 24:49c6624119ae 412 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustKeyerEnable, true);
tobyspark 24:49c6624119ae 413 ok = ok && setKeyParamsTo(index);
tobyspark 25:3b519ef70341 414
tobyspark 26:0299f8760715 415 snprintf(sentMSGBuffer, kStringBufferLength, "Keyer On with %i", index);
tobyspark 24:49c6624119ae 416 }
tobyspark 24:49c6624119ae 417
tobyspark 24:49c6624119ae 418 if (ok) sentOK = "Sent:";
tobyspark 24:49c6624119ae 419 else sentOK = "Send Error:";
tobyspark 24:49c6624119ae 420
tobyspark 24:49c6624119ae 421 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 25:3b519ef70341 422 screen.textToBuffer(sentOK + sentMSGBuffer, kTVOneStatusLine);
tobyspark 24:49c6624119ae 423 }
tobyspark 24:49c6624119ae 424
tobyspark 24:49c6624119ae 425
tobyspark 17:fc68d40b8b1f 426 bool conformProcessor()
tobyspark 17:fc68d40b8b1f 427 {
tobyspark 17:fc68d40b8b1f 428 bool ok = true;
tobyspark 17:fc68d40b8b1f 429
tobyspark 17:fc68d40b8b1f 430 int32_t on = 1;
tobyspark 17:fc68d40b8b1f 431 int32_t off = 0;
tobyspark 20:8b92d7922c48 432
tobyspark 20:8b92d7922c48 433 // Independent output
tobyspark 30:873979018850 434 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionMode, 2);
tobyspark 20:8b92d7922c48 435 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsOutputEnable, on);
tobyspark 20:8b92d7922c48 436 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsLockMethod, off);
tobyspark 17:fc68d40b8b1f 437
tobyspark 17:fc68d40b8b1f 438 // Make sure our windows exist
tobyspark 17:fc68d40b8b1f 439 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsEnable, on);
tobyspark 17:fc68d40b8b1f 440 ok = ok && tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsEnable, on);
tobyspark 18:ebe5da639a6a 441 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsLayerPriority, 0);
tobyspark 18:ebe5da639a6a 442 ok = ok && tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsLayerPriority, 1);
tobyspark 17:fc68d40b8b1f 443
tobyspark 17:fc68d40b8b1f 444 // Assign inputs to windows, so that left on the crossfader is left on the processor viewed from front
tobyspark 17:fc68d40b8b1f 445 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceRGB2);
tobyspark 17:fc68d40b8b1f 446 ok = ok && tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsWindowSource, kTV1SourceRGB1);
tobyspark 17:fc68d40b8b1f 447
tobyspark 17:fc68d40b8b1f 448 // Set scaling to fit source within output, maintaining aspect ratio
tobyspark 17:fc68d40b8b1f 449 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustWindowsZoomLevel, 100);
tobyspark 17:fc68d40b8b1f 450 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDB, kTV1FunctionAdjustWindowsZoomLevel, 100);
tobyspark 17:fc68d40b8b1f 451 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustWindowsShrinkEnable, off);
tobyspark 17:fc68d40b8b1f 452 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDB, kTV1FunctionAdjustWindowsShrinkEnable, off);
tobyspark 17:fc68d40b8b1f 453 int32_t fit = 1;
tobyspark 17:fc68d40b8b1f 454 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceAspectCorrect, fit);
tobyspark 17:fc68d40b8b1f 455 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceAspectCorrect, fit);
tobyspark 17:fc68d40b8b1f 456
tobyspark 17:fc68d40b8b1f 457 // On source loss, hold on the last frame received.
tobyspark 17:fc68d40b8b1f 458 int32_t freeze = 1;
tobyspark 17:fc68d40b8b1f 459 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceOnSourceLoss, freeze);
tobyspark 17:fc68d40b8b1f 460 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceOnSourceLoss, freeze);
tobyspark 17:fc68d40b8b1f 461
tobyspark 30:873979018850 462 // Set resolution and fade levels for maximum chance of being seen
tobyspark 31:01845a2347ff 463 int32_t slot = tvOneEDIDPassthrough ? EDIDPassthroughSlot : 5;
tobyspark 30:873979018850 464 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsOutputResolution, kTV1ResolutionVGA);
tobyspark 31:01845a2347ff 465 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 466 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 30:873979018850 467 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsMaxFadeLevel, 100);
tobyspark 30:873979018850 468 ok = ok && tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsMaxFadeLevel, 100);
tobyspark 30:873979018850 469
tobyspark 30:873979018850 470 // Save current state for power on
tobyspark 30:873979018850 471 ok = ok && tvOne.command(0, kTV1WindowIDA, kTV1FunctionPowerOnPresetStore, 1);
tobyspark 17:fc68d40b8b1f 472
tobyspark 17:fc68d40b8b1f 473 return ok;
tobyspark 17:fc68d40b8b1f 474 }
tobyspark 17:fc68d40b8b1f 475
tobyspark 27:27851d3d2bba 476 void setResolutionMenuItems()
tobyspark 27:27851d3d2bba 477 {
tobyspark 27:27851d3d2bba 478 resolutionMenu.clearMenuItems();
tobyspark 27:27851d3d2bba 479 for (int i=0; i < settings.resolutionsCount(); i++)
tobyspark 27:27851d3d2bba 480 {
tobyspark 27:27851d3d2bba 481 resolutionMenu.addMenuItem(SPKMenuItem(settings.resolutionName(i), settings.resolutionIndex(i), settings.resolutionEDIDIndex(i)));
tobyspark 27:27851d3d2bba 482 }
tobyspark 27:27851d3d2bba 483 resolutionMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
tobyspark 27:27851d3d2bba 484 }
tobyspark 27:27851d3d2bba 485
tobyspark 27:27851d3d2bba 486 void setMixModeMenuItems()
tobyspark 27:27851d3d2bba 487 {
tobyspark 27:27851d3d2bba 488 mixModeMenu.clearMenuItems();
tobyspark 29:95a7efe30527 489 mixModeMenu.addMenuItem(SPKMenuItem("Crossfade", &mixModeAdditiveMenu));
tobyspark 27:27851d3d2bba 490 for (int i=0; i < settings.keyerSetCount(); i++)
tobyspark 27:27851d3d2bba 491 {
tobyspark 27:27851d3d2bba 492 mixModeMenu.addMenuItem(SPKMenuItem(settings.keyerParamName(i), mixKey+i));
tobyspark 27:27851d3d2bba 493 }
tobyspark 27:27851d3d2bba 494 mixModeMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
tobyspark 27:27851d3d2bba 495 }
tobyspark 27:27851d3d2bba 496
tobyspark 27:27851d3d2bba 497 void setCommsMenuItems()
tobyspark 27:27851d3d2bba 498 {
tobyspark 27:27851d3d2bba 499 if (rj45Mode == rj45Ethernet)
tobyspark 27:27851d3d2bba 500 {
tobyspark 27:27851d3d2bba 501 commsMenu.title = "Network Mode [Ethernet]";
tobyspark 27:27851d3d2bba 502 commsMenu.clearMenuItems();
tobyspark 27:27851d3d2bba 503 commsMenu.addMenuItem(SPKMenuItem("None", commsNone));
tobyspark 27:27851d3d2bba 504 commsMenu.addMenuItem(SPKMenuItem("OSC", commsOSC));
tobyspark 27:27851d3d2bba 505 commsMenu.addMenuItem(SPKMenuItem("ArtNet", commsArtNet));
tobyspark 27:27851d3d2bba 506 commsMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
tobyspark 27:27851d3d2bba 507 }
tobyspark 27:27851d3d2bba 508 else if (rj45Mode == rj45DMX)
tobyspark 27:27851d3d2bba 509 {
tobyspark 27:27851d3d2bba 510 commsMenu.title = "Network Mode [DMX]";
tobyspark 27:27851d3d2bba 511 commsMenu.clearMenuItems();
tobyspark 27:27851d3d2bba 512 commsMenu.addMenuItem(SPKMenuItem("None", commsNone));
tobyspark 27:27851d3d2bba 513 commsMenu.addMenuItem(SPKMenuItem("DMX In", commsDMXIn));
tobyspark 27:27851d3d2bba 514 commsMenu.addMenuItem(SPKMenuItem("DMX Out", commsDMXOut));
tobyspark 27:27851d3d2bba 515 commsMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
tobyspark 27:27851d3d2bba 516 }
tobyspark 27:27851d3d2bba 517 }
tobyspark 27:27851d3d2bba 518
tobyspark 0:87aab40d5806 519 int main()
tobyspark 0:87aab40d5806 520 {
tobyspark 0:87aab40d5806 521 if (debug)
tobyspark 0:87aab40d5806 522 {
tobyspark 0:87aab40d5806 523 debug->printf("\r\n\r\n");
tobyspark 0:87aab40d5806 524 debug->printf("*spark d-fuser -----------\r\n");
tobyspark 0:87aab40d5806 525 debug->printf(" debug channel\r\n");
tobyspark 0:87aab40d5806 526 }
tobyspark 2:50043054e4f7 527
tobyspark 2:50043054e4f7 528 // Set display font
tobyspark 2:50043054e4f7 529 screen.fontStartCharacter = &characterBytesStartChar;
tobyspark 2:50043054e4f7 530 screen.fontEndCharacter = &characterBytesEndChar;
tobyspark 2:50043054e4f7 531 screen.fontCharacters = characterBytes;
tobyspark 2:50043054e4f7 532
tobyspark 0:87aab40d5806 533 // Splash screen
tobyspark 30:873979018850 534 string softwareLine = "SW ";
tobyspark 30:873979018850 535 softwareLine += kSPKDFSoftwareVersion;
tobyspark 2:50043054e4f7 536 screen.imageToBuffer(spkDisplayLogo);
tobyspark 0:87aab40d5806 537 screen.textToBuffer("SPK:D-Fuser",0);
tobyspark 30:873979018850 538 screen.textToBuffer(softwareLine,1);
tobyspark 5:f8b285ca41ba 539 screen.sendBuffer();
tobyspark 0:87aab40d5806 540
tobyspark 11:0783cfbeb746 541 // Load saved settings
tobyspark 16:52484666b323 542 bool settingsAreCustom = false;
tobyspark 16:52484666b323 543 settingsAreCustom = settings.load(kSPKDFSettingsFilename);
tobyspark 30:873979018850 544 if (settingsAreCustom)
tobyspark 30:873979018850 545 {
tobyspark 30:873979018850 546 softwareLine += "; ini OK";
tobyspark 30:873979018850 547 screen.textToBuffer(softwareLine, 1);
tobyspark 30:873979018850 548 }
tobyspark 30:873979018850 549
tobyspark 0:87aab40d5806 550 // Set menu structure
tobyspark 0:87aab40d5806 551 mixModeMenu.title = "Mix Mode";
tobyspark 27:27851d3d2bba 552 setMixModeMenuItems();
tobyspark 24:49c6624119ae 553
tobyspark 29:95a7efe30527 554 mixModeAdditiveMenu.title = "Crossfade";
tobyspark 30:873979018850 555 mixModeAdditiveMenu.addMenuItem(SPKMenuItem("[title overridden]", &mixModeMenu, true));
tobyspark 0:87aab40d5806 556
tobyspark 0:87aab40d5806 557 resolutionMenu.title = "Resolution";
tobyspark 27:27851d3d2bba 558 setResolutionMenuItems();
tobyspark 0:87aab40d5806 559
tobyspark 27:27851d3d2bba 560 commsMenu.title = "Network Mode";
tobyspark 27:27851d3d2bba 561 setCommsMenuItems();
tobyspark 23:909928cafb95 562
tobyspark 15:4b394c64b461 563 advancedMenu.title = "Troubleshooting";
tobyspark 23:909928cafb95 564 advancedMenu.addMenuItem(SPKMenuItem("HDCP Off", advancedHDCPOff));
tobyspark 23:909928cafb95 565 advancedMenu.addMenuItem(SPKMenuItem("HDCP On", advancedHDCPOn));
tobyspark 31:01845a2347ff 566 advancedMenu.addMenuItem(SPKMenuItem("EDID Passthrough", advancedEDIDPassthrough)); // have global setting of passthrough that overrides resolution sets and is saved with conform processor
tobyspark 31:01845a2347ff 567 advancedMenu.addMenuItem(SPKMenuItem("EDID Internal", advancedEDIDInternal));
tobyspark 30:873979018850 568 advancedMenu.addMenuItem(SPKMenuItem("Test Processor Sources", advancedTestSources));
tobyspark 23:909928cafb95 569 advancedMenu.addMenuItem(SPKMenuItem("Conform Processor", advancedConformProcessor));
tobyspark 30:873979018850 570 if (settingsAreCustom) advancedMenu.addMenuItem(SPKMenuItem("Revert Controller", advancedLoadDefaults));
tobyspark 24:49c6624119ae 571 advancedMenu.addMenuItem(SPKMenuItem("Back to Main Menu", &mainMenu));
tobyspark 23:909928cafb95 572
tobyspark 0:87aab40d5806 573 mainMenu.title = "Main Menu";
tobyspark 24:49c6624119ae 574 mainMenu.addMenuItem(SPKMenuItem(mixModeMenu.title, &mixModeMenu));
tobyspark 24:49c6624119ae 575 mainMenu.addMenuItem(SPKMenuItem(resolutionMenu.title, &resolutionMenu));
tobyspark 24:49c6624119ae 576 mainMenu.addMenuItem(SPKMenuItem(commsMenu.title, &commsMenu));
tobyspark 24:49c6624119ae 577 mainMenu.addMenuItem(SPKMenuItem(advancedMenu.title, &advancedMenu));
tobyspark 23:909928cafb95 578
tobyspark 0:87aab40d5806 579 selectedMenu = &mainMenu;
tobyspark 23:909928cafb95 580
tobyspark 0:87aab40d5806 581 // Misc I/O stuff
tobyspark 0:87aab40d5806 582
tobyspark 0:87aab40d5806 583 fadeAPO.period(0.001);
tobyspark 0:87aab40d5806 584 fadeBPO.period(0.001);
tobyspark 0:87aab40d5806 585
tobyspark 20:8b92d7922c48 586 // Test for TV One connectivity and determine unit type
tobyspark 30:873979018850 587 // TODO: Determine and fall back if not dfuser firmware?
tobyspark 30:873979018850 588 // TODO: Use software version to select resolution slots?
tobyspark 30:873979018850 589 // TODO: Use product / board type to select TVOne conform type?
tobyspark 21:f9d63cb7cedb 590 // kTV1FunctionReadSoftwareVersion
tobyspark 21:f9d63cb7cedb 591 // kTV1FunctionReadProductType
tobyspark 21:f9d63cb7cedb 592 // kTV1FunctionReadBoardType
tobyspark 21:f9d63cb7cedb 593
tobyspark 12:c270870bdd23 594 // Display menu and framing lines
tobyspark 0:87aab40d5806 595 screen.horizLineToBuffer(kMenuLine1*pixInPage - 1);
tobyspark 0:87aab40d5806 596 screen.clearBufferRow(kMenuLine1);
tobyspark 0:87aab40d5806 597 screen.textToBuffer(selectedMenu->title, kMenuLine1);
tobyspark 0:87aab40d5806 598 screen.clearBufferRow(kMenuLine2);
tobyspark 0:87aab40d5806 599 screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2);
tobyspark 0:87aab40d5806 600 screen.horizLineToBuffer(kMenuLine2*pixInPage + pixInPage);
tobyspark 1:f9fca21102e0 601 screen.horizLineToBuffer(kCommsStatusLine*pixInPage - 1);
tobyspark 1:f9fca21102e0 602 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 30:873979018850 603 screen.textToBuffer("TVOne: OK", kTVOneStatusLine); // handleTVOneSources may update this
tobyspark 30:873979018850 604
tobyspark 30:873979018850 605 // If we do not have two solid sources, act on this as we rely on the window having a source for crossfade behaviour
tobyspark 30:873979018850 606 // Once we've had two solid inputs, don't check any more as we're ok as the unit is set to hold on last frame.
tobyspark 31:01845a2347ff 607 // This is set to update kTVOneStatusLine and sendBuffer regardless
tobyspark 31:01845a2347ff 608 bool ok = handleTVOneSources(true);
tobyspark 0:87aab40d5806 609
tobyspark 0:87aab40d5806 610 //// CONTROLS TEST
tobyspark 0:87aab40d5806 611
tobyspark 0:87aab40d5806 612 while (0) {
tobyspark 0:87aab40d5806 613 if (debug) debug->printf("xFade: %f, fadeOut: %f, tapLeft %i, tapRight: %i encPos: %i encChange:%i encHasPressed:%i \r\n" , xFadeAIN.read(), fadeUpAIN.read(), tapLeftDIN.read(), tapRightDIN.read(), menuEnc.getPos(), menuEnc.getChange(), menuEnc.hasPressed());
tobyspark 0:87aab40d5806 614 }
tobyspark 0:87aab40d5806 615
tobyspark 0:87aab40d5806 616 //// MIXER RUN
tobyspark 0:87aab40d5806 617
tobyspark 8:d46cc49f0f37 618 while (1)
tobyspark 8:d46cc49f0f37 619 {
tobyspark 1:f9fca21102e0 620 //// Task background things
tobyspark 5:f8b285ca41ba 621 if (ethernet && rj45Mode == rj45Ethernet)
tobyspark 5:f8b285ca41ba 622 {
tobyspark 5:f8b285ca41ba 623 Net::poll();
tobyspark 5:f8b285ca41ba 624 }
tobyspark 5:f8b285ca41ba 625
tobyspark 5:f8b285ca41ba 626 //// RJ45 SWITCH
tobyspark 5:f8b285ca41ba 627
tobyspark 5:f8b285ca41ba 628 if (rj45ModeDIN != rj45Mode)
tobyspark 1:f9fca21102e0 629 {
tobyspark 23:909928cafb95 630 if (debug) debug->printf("Handling RJ45 mode change\r\n");
tobyspark 27:27851d3d2bba 631
tobyspark 5:f8b285ca41ba 632 // update state
tobyspark 5:f8b285ca41ba 633 rj45Mode = rj45ModeDIN;
tobyspark 27:27851d3d2bba 634
tobyspark 27:27851d3d2bba 635 setCommsMenuItems();
tobyspark 5:f8b285ca41ba 636
tobyspark 5:f8b285ca41ba 637 // cancel old comms
tobyspark 5:f8b285ca41ba 638 commsMode = commsNone;
tobyspark 5:f8b285ca41ba 639 commsMenu = commsMode;
tobyspark 5:f8b285ca41ba 640
tobyspark 5:f8b285ca41ba 641 // refresh display
tobyspark 23:909928cafb95 642 if (selectedMenu == &commsMenu)
tobyspark 23:909928cafb95 643 {
tobyspark 23:909928cafb95 644 screen.textToBuffer(selectedMenu->title, kMenuLine1);
tobyspark 23:909928cafb95 645 screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2);
tobyspark 23:909928cafb95 646 }
tobyspark 5:f8b285ca41ba 647 if (rj45Mode == rj45Ethernet) screen.textToBuffer("RJ45: Ethernet Engaged", kCommsStatusLine);
tobyspark 5:f8b285ca41ba 648 if (rj45Mode == rj45DMX) screen.textToBuffer("RJ45: DMX Engaged", kCommsStatusLine);
tobyspark 1:f9fca21102e0 649 }
tobyspark 1:f9fca21102e0 650
tobyspark 0:87aab40d5806 651 //// MENU
tobyspark 0:87aab40d5806 652
tobyspark 0:87aab40d5806 653 int menuChange = menuEnc.getChange();
tobyspark 0:87aab40d5806 654
tobyspark 0:87aab40d5806 655 // Update GUI
tobyspark 0:87aab40d5806 656 if (menuChange != 0)
tobyspark 0:87aab40d5806 657 {
tobyspark 24:49c6624119ae 658 if (selectedMenu->selectedItem().handlingControls)
tobyspark 24:49c6624119ae 659 {
tobyspark 24:49c6624119ae 660 if (selectedMenu == &mixModeAdditiveMenu)
tobyspark 24:49c6624119ae 661 {
tobyspark 24:49c6624119ae 662 fadeCurve += menuChange * 0.05;
tobyspark 24:49c6624119ae 663 if (fadeCurve > 1.0f) fadeCurve = 1.0f;
tobyspark 24:49c6624119ae 664 if (fadeCurve < 0.0f) fadeCurve = 0.0f;
tobyspark 29:95a7efe30527 665
tobyspark 31:01845a2347ff 666 int newMixMode = (fadeCurve > 0.0f) ? mixAdditive: mixBlend;
tobyspark 31:01845a2347ff 667
tobyspark 31:01845a2347ff 668 if (newMixMode != mixMode)
tobyspark 31:01845a2347ff 669 {
tobyspark 31:01845a2347ff 670 mixMode = newMixMode;
tobyspark 31:01845a2347ff 671 actionMixMode();
tobyspark 31:01845a2347ff 672 }
tobyspark 29:95a7efe30527 673
tobyspark 24:49c6624119ae 674 screen.clearBufferRow(kMenuLine2);
tobyspark 29:95a7efe30527 675 screen.textToBuffer("Blend [ ----- ] Add", kMenuLine2);
tobyspark 29:95a7efe30527 676 screen.characterToBuffer('X', 38 + fadeCurve*20.0f, kMenuLine2);
tobyspark 24:49c6624119ae 677
tobyspark 31:01845a2347ff 678 if (debug) debug->printf("Fade curve changed by %i to %f \r\n", menuChange, fadeCurve);
tobyspark 24:49c6624119ae 679 }
tobyspark 24:49c6624119ae 680 }
tobyspark 24:49c6624119ae 681 else
tobyspark 24:49c6624119ae 682 {
tobyspark 24:49c6624119ae 683 if (debug) debug->printf("Menu changed by %i\r\n", menuChange);
tobyspark 24:49c6624119ae 684
tobyspark 24:49c6624119ae 685 *selectedMenu = selectedMenu->selectedIndex() + menuChange;
tobyspark 24:49c6624119ae 686
tobyspark 24:49c6624119ae 687 // update OLED line 2 here
tobyspark 24:49c6624119ae 688 screen.clearBufferRow(kMenuLine2);
tobyspark 24:49c6624119ae 689 screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2);
tobyspark 24:49c6624119ae 690
tobyspark 24:49c6624119ae 691 if (debug) debug->printf("%s \r\n", selectedMenu->selectedString().c_str());
tobyspark 24:49c6624119ae 692 }
tobyspark 0:87aab40d5806 693 }
tobyspark 0:87aab40d5806 694
tobyspark 0:87aab40d5806 695 // Action menu item
tobyspark 0:87aab40d5806 696 if (menuEnc.hasPressed())
tobyspark 0:87aab40d5806 697 {
tobyspark 0:87aab40d5806 698 if (debug) debug->printf("Action Menu Item!\r\n");
tobyspark 21:f9d63cb7cedb 699
tobyspark 0:87aab40d5806 700 // Are we changing menus?
tobyspark 23:909928cafb95 701 if (selectedMenu->selectedItem().type == SPKMenuItem::changesToMenu)
tobyspark 0:87aab40d5806 702 {
tobyspark 31:01845a2347ff 703 // If we're exiting the menu, we should set its selected index back to the menu's beginning...
tobyspark 31:01845a2347ff 704 SPKMenu* menuToReset = selectedMenu->selectedItem().payload.menu == &mainMenu? selectedMenu : NULL;
tobyspark 31:01845a2347ff 705
tobyspark 31:01845a2347ff 706 // point selected menu pointer to the new menu pointer
tobyspark 23:909928cafb95 707 selectedMenu = selectedMenu->selectedItem().payload.menu;
tobyspark 0:87aab40d5806 708
tobyspark 31:01845a2347ff 709 // ...doing this, of course, after we've used the value
tobyspark 31:01845a2347ff 710 if (menuToReset) *menuToReset = 0;
tobyspark 31:01845a2347ff 711
tobyspark 0:87aab40d5806 712 // update OLED lines 1&2
tobyspark 0:87aab40d5806 713 screen.clearBufferRow(kMenuLine1);
tobyspark 0:87aab40d5806 714 screen.clearBufferRow(kMenuLine2);
tobyspark 0:87aab40d5806 715 screen.textToBuffer(selectedMenu->title, kMenuLine1);
tobyspark 0:87aab40d5806 716 screen.textToBuffer(selectedMenu->selectedString(), kMenuLine2);
tobyspark 0:87aab40d5806 717
tobyspark 0:87aab40d5806 718 if (debug)
tobyspark 0:87aab40d5806 719 {
tobyspark 0:87aab40d5806 720 debug->printf("\r\n");
tobyspark 0:87aab40d5806 721 debug->printf("%s \r\n", selectedMenu->title.c_str());
tobyspark 0:87aab40d5806 722 debug->printf("%s \r\n", selectedMenu->selectedString().c_str());
tobyspark 0:87aab40d5806 723 }
tobyspark 24:49c6624119ae 724
tobyspark 24:49c6624119ae 725 // Are we changing menus that should have a command attached?
tobyspark 24:49c6624119ae 726 if (selectedMenu == &mixModeAdditiveMenu)
tobyspark 24:49c6624119ae 727 {
tobyspark 29:95a7efe30527 728 screen.clearBufferRow(kMenuLine2);
tobyspark 29:95a7efe30527 729 screen.textToBuffer("Blend [ ----- ] Add", kMenuLine2);
tobyspark 29:95a7efe30527 730 screen.characterToBuffer('X', 38 + fadeCurve*20.0f, kMenuLine2);
tobyspark 29:95a7efe30527 731
tobyspark 29:95a7efe30527 732 mixMode = fadeCurve > 0 ? mixAdditive : mixBlend;
tobyspark 24:49c6624119ae 733 actionMixMode();
tobyspark 24:49c6624119ae 734 }
tobyspark 0:87aab40d5806 735 }
tobyspark 0:87aab40d5806 736 // With that out of the way, we should be actioning a specific menu's payload?
tobyspark 0:87aab40d5806 737 else if (selectedMenu == &mixModeMenu)
tobyspark 0:87aab40d5806 738 {
tobyspark 23:909928cafb95 739 mixMode = mixModeMenu.selectedItem().payload.command[0];
tobyspark 24:49c6624119ae 740 actionMixMode();
tobyspark 0:87aab40d5806 741 }
tobyspark 0:87aab40d5806 742 else if (selectedMenu == &resolutionMenu)
tobyspark 0:87aab40d5806 743 {
tobyspark 9:f83eadd8917a 744 bool ok = true;
tobyspark 0:87aab40d5806 745
tobyspark 23:909928cafb95 746 ok = tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsOutputResolution, resolutionMenu.selectedItem().payload.command[0]);
tobyspark 31:01845a2347ff 747
tobyspark 31:01845a2347ff 748 int32_t slot = tvOneEDIDPassthrough ? EDIDPassthroughSlot : resolutionMenu.selectedItem().payload.command[1];
tobyspark 31:01845a2347ff 749
tobyspark 31:01845a2347ff 750 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 751 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 0:87aab40d5806 752
tobyspark 25:3b519ef70341 753 string sentOK;
tobyspark 0:87aab40d5806 754 if (ok) sentOK = "Sent: ";
tobyspark 0:87aab40d5806 755 else sentOK = "Send Error: ";
tobyspark 0:87aab40d5806 756
tobyspark 26:0299f8760715 757 char sentMSGBuffer[kStringBufferLength];
tobyspark 26:0299f8760715 758 snprintf(sentMSGBuffer, kStringBufferLength,"Res %i, EDID %i", resolutionMenu.selectedItem().payload.command[0], resolutionMenu.selectedItem().payload.command[1]);
tobyspark 0:87aab40d5806 759
tobyspark 1:f9fca21102e0 760 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 25:3b519ef70341 761 screen.textToBuffer(sentOK + sentMSGBuffer, kTVOneStatusLine);
tobyspark 0:87aab40d5806 762
tobyspark 0:87aab40d5806 763 if (debug) { debug->printf("Changing resolution"); }
tobyspark 0:87aab40d5806 764 }
tobyspark 1:f9fca21102e0 765 else if (selectedMenu == &commsMenu)
tobyspark 1:f9fca21102e0 766 {
tobyspark 26:0299f8760715 767 string commsTypeString = "Network:";
tobyspark 26:0299f8760715 768 char commsStatusBuffer[kStringBufferLength] = "--";
tobyspark 1:f9fca21102e0 769
tobyspark 1:f9fca21102e0 770 // Tear down any existing comms
tobyspark 1:f9fca21102e0 771 // This is the action of commsNone
tobyspark 1:f9fca21102e0 772 // And also clears the way for other comms actions
tobyspark 26:0299f8760715 773 commsMode = commsNone;
tobyspark 5:f8b285ca41ba 774 if (osc) {delete osc; osc = NULL;}
tobyspark 5:f8b285ca41ba 775 if (ethernet) {delete ethernet; ethernet = NULL;}
tobyspark 5:f8b285ca41ba 776 if (artNet) {delete artNet; artNet = NULL;}
tobyspark 5:f8b285ca41ba 777 if (dmx) {delete dmx; dmx = NULL;}
tobyspark 5:f8b285ca41ba 778
tobyspark 5:f8b285ca41ba 779 // Ensure we can't change to comms modes the hardware isn't switched to
tobyspark 23:909928cafb95 780 if (rj45Mode == rj45DMX && (commsMenu.selectedItem().payload.command[0] == commsOSC || commsMenu.selectedItem().payload.command[0] == commsArtNet))
tobyspark 1:f9fca21102e0 781 {
tobyspark 5:f8b285ca41ba 782 commsTypeString = "RJ45 not in Ethernet mode";
tobyspark 5:f8b285ca41ba 783 }
tobyspark 23:909928cafb95 784 else if (rj45Mode == rj45Ethernet && (commsMenu.selectedItem().payload.command[0] == commsDMXIn || commsMenu.selectedItem().payload.command[0] == commsDMXOut))
tobyspark 5:f8b285ca41ba 785 {
tobyspark 5:f8b285ca41ba 786 commsTypeString = "RJ45 not in DMX mode";
tobyspark 5:f8b285ca41ba 787 }
tobyspark 5:f8b285ca41ba 788 // Action!
tobyspark 23:909928cafb95 789 else if (commsMenu.selectedItem().payload.command[0] == commsOSC)
tobyspark 5:f8b285ca41ba 790 {
tobyspark 5:f8b285ca41ba 791 commsMode = commsOSC;
tobyspark 5:f8b285ca41ba 792 commsTypeString = "OSC: ";
tobyspark 1:f9fca21102e0 793
tobyspark 1:f9fca21102e0 794 ethernet = new EthernetNetIf(
tobyspark 1:f9fca21102e0 795 IpAddr(kOSCMbedIPAddress),
tobyspark 1:f9fca21102e0 796 IpAddr(kOSCMbedSubnetMask),
tobyspark 1:f9fca21102e0 797 IpAddr(kOSCMbedGateway),
tobyspark 1:f9fca21102e0 798 IpAddr(kOSCMbedDNS)
tobyspark 1:f9fca21102e0 799 );
tobyspark 3:033d2b7768f3 800
tobyspark 1:f9fca21102e0 801 EthernetErr ethError = ethernet->setup();
tobyspark 1:f9fca21102e0 802 if(ethError)
tobyspark 1:f9fca21102e0 803 {
tobyspark 1:f9fca21102e0 804 if (debug) debug->printf("Ethernet setup error, %d", ethError);
tobyspark 26:0299f8760715 805 snprintf(commsStatusBuffer, kStringBufferLength, "Ethernet setup failed");
tobyspark 5:f8b285ca41ba 806 commsMenu = commsNone;
tobyspark 1:f9fca21102e0 807 // break out of here. this setup should be a function that returns a boolean
tobyspark 1:f9fca21102e0 808 }
tobyspark 1:f9fca21102e0 809
tobyspark 1:f9fca21102e0 810 osc = new OSCClass();
tobyspark 3:033d2b7768f3 811 osc->setReceiveMessage(&recMessage);
tobyspark 1:f9fca21102e0 812 osc->begin(kOSCMbedPort);
tobyspark 1:f9fca21102e0 813
tobyspark 26:0299f8760715 814 snprintf(commsStatusBuffer, kStringBufferLength, "Listening on %i", kOSCMbedPort);
tobyspark 1:f9fca21102e0 815 }
tobyspark 23:909928cafb95 816 else if (commsMenu.selectedItem().payload.command[0] == commsArtNet)
tobyspark 1:f9fca21102e0 817 {
tobyspark 5:f8b285ca41ba 818 commsMode = commsArtNet;
tobyspark 5:f8b285ca41ba 819 commsTypeString = "ArtNet: ";
tobyspark 3:033d2b7768f3 820
tobyspark 3:033d2b7768f3 821 artNet = new DmxArtNet();
tobyspark 1:f9fca21102e0 822
tobyspark 3:033d2b7768f3 823 artNet->BindIpAddress = IpAddr(kArtNetBindIPAddress);
tobyspark 3:033d2b7768f3 824 artNet->BCastAddress = IpAddr(kArtNetBroadcastAddress);
tobyspark 3:033d2b7768f3 825
tobyspark 3:033d2b7768f3 826 artNet->InitArtPollReplyDefaults();
tobyspark 3:033d2b7768f3 827
tobyspark 3:033d2b7768f3 828 artNet->ArtPollReply.PortType[0] = 128; // output
tobyspark 3:033d2b7768f3 829 artNet->ArtPollReply.PortType[2] = 64; // input
tobyspark 3:033d2b7768f3 830 artNet->ArtPollReply.GoodInput[2] = 4;
tobyspark 3:033d2b7768f3 831
tobyspark 3:033d2b7768f3 832 artNet->Init();
tobyspark 3:033d2b7768f3 833 artNet->SendArtPollReply(); // announce to art-net nodes
tobyspark 3:033d2b7768f3 834
tobyspark 26:0299f8760715 835 snprintf(commsStatusBuffer, kStringBufferLength, "Listening");
tobyspark 1:f9fca21102e0 836 }
tobyspark 23:909928cafb95 837 else if (commsMenu.selectedItem().payload.command[0] == commsDMXIn)
tobyspark 1:f9fca21102e0 838 {
tobyspark 5:f8b285ca41ba 839 commsMode = commsDMXIn;
tobyspark 5:f8b285ca41ba 840 commsTypeString = "DMX In: ";
tobyspark 1:f9fca21102e0 841
tobyspark 5:f8b285ca41ba 842 dmxDirectionDOUT = 0;
tobyspark 5:f8b285ca41ba 843
tobyspark 5:f8b285ca41ba 844 dmx = new DMX(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX);
tobyspark 1:f9fca21102e0 845 }
tobyspark 23:909928cafb95 846 else if (commsMenu.selectedItem().payload.command[0] == commsDMXOut)
tobyspark 5:f8b285ca41ba 847 {
tobyspark 5:f8b285ca41ba 848 commsMode = commsDMXOut;
tobyspark 5:f8b285ca41ba 849 commsTypeString = "DMX Out: ";
tobyspark 5:f8b285ca41ba 850
tobyspark 5:f8b285ca41ba 851 dmxDirectionDOUT = 1;
tobyspark 5:f8b285ca41ba 852
tobyspark 5:f8b285ca41ba 853 dmx = new DMX(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX);
tobyspark 5:f8b285ca41ba 854 }
tobyspark 5:f8b285ca41ba 855
tobyspark 1:f9fca21102e0 856 screen.clearBufferRow(kCommsStatusLine);
tobyspark 25:3b519ef70341 857 screen.textToBuffer(commsTypeString + commsStatusBuffer, kCommsStatusLine);
tobyspark 1:f9fca21102e0 858 }
tobyspark 12:c270870bdd23 859 else if (selectedMenu == &advancedMenu)
tobyspark 12:c270870bdd23 860 {
tobyspark 23:909928cafb95 861 if (advancedMenu.selectedItem().payload.command[0] == advancedHDCPOff)
tobyspark 12:c270870bdd23 862 {
tobyspark 31:01845a2347ff 863 bool ok;
tobyspark 12:c270870bdd23 864
tobyspark 15:4b394c64b461 865 ok = tvOne.setHDCPOn(false);
tobyspark 12:c270870bdd23 866
tobyspark 12:c270870bdd23 867 std::string sendOK = ok ? "Sent: HDCP Off" : "Send Error: HDCP Off";
tobyspark 12:c270870bdd23 868
tobyspark 12:c270870bdd23 869 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 12:c270870bdd23 870 screen.textToBuffer(sendOK, kTVOneStatusLine);
tobyspark 12:c270870bdd23 871 }
tobyspark 23:909928cafb95 872 else if (advancedMenu.selectedItem().payload.command[0] == advancedHDCPOn)
tobyspark 15:4b394c64b461 873 {
tobyspark 31:01845a2347ff 874 bool ok;
tobyspark 15:4b394c64b461 875
tobyspark 15:4b394c64b461 876 ok = tvOne.setHDCPOn(true);
tobyspark 15:4b394c64b461 877
tobyspark 15:4b394c64b461 878 std::string sendOK = ok ? "Sent: HDCP On" : "Send Error: HDCP On";
tobyspark 15:4b394c64b461 879
tobyspark 15:4b394c64b461 880 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 15:4b394c64b461 881 screen.textToBuffer(sendOK, kTVOneStatusLine);
tobyspark 15:4b394c64b461 882 }
tobyspark 31:01845a2347ff 883 else if (advancedMenu.selectedItem().payload.command[0] == advancedEDIDPassthrough)
tobyspark 31:01845a2347ff 884 {
tobyspark 31:01845a2347ff 885 tvOneEDIDPassthrough = true;
tobyspark 31:01845a2347ff 886
tobyspark 31:01845a2347ff 887 bool ok = true;
tobyspark 31:01845a2347ff 888
tobyspark 31:01845a2347ff 889 int32_t slot = tvOneEDIDPassthrough ? EDIDPassthroughSlot : resolutionMenu.selectedItem().payload.command[1];
tobyspark 31:01845a2347ff 890
tobyspark 31:01845a2347ff 891 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 892 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 893
tobyspark 31:01845a2347ff 894 std::string sendOK = ok ? "Sent: EDID. Next:conform?" : "Send Error: EDID";
tobyspark 31:01845a2347ff 895
tobyspark 31:01845a2347ff 896 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 31:01845a2347ff 897 screen.textToBuffer(sendOK, kTVOneStatusLine);
tobyspark 31:01845a2347ff 898 }
tobyspark 31:01845a2347ff 899 else if (advancedMenu.selectedItem().payload.command[0] == advancedEDIDInternal)
tobyspark 31:01845a2347ff 900 {
tobyspark 31:01845a2347ff 901 tvOneEDIDPassthrough = false;
tobyspark 31:01845a2347ff 902
tobyspark 31:01845a2347ff 903 bool ok = true;
tobyspark 31:01845a2347ff 904
tobyspark 31:01845a2347ff 905 int32_t slot = tvOneEDIDPassthrough ? EDIDPassthroughSlot : resolutionMenu.selectedItem().payload.command[1];
tobyspark 31:01845a2347ff 906
tobyspark 31:01845a2347ff 907 ok = ok && tvOne.command(kTV1SourceRGB1, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 908 ok = ok && tvOne.command(kTV1SourceRGB2, kTV1WindowIDA, kTV1FunctionAdjustSourceEDID, slot);
tobyspark 31:01845a2347ff 909
tobyspark 31:01845a2347ff 910 std::string sendOK = ok ? "Sent: EDID. Next:conform?" : "Send Error: EDID";
tobyspark 31:01845a2347ff 911
tobyspark 31:01845a2347ff 912 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 31:01845a2347ff 913 screen.textToBuffer(sendOK, kTVOneStatusLine);
tobyspark 31:01845a2347ff 914 }
tobyspark 30:873979018850 915 else if (advancedMenu.selectedItem().payload.command[0] == advancedTestSources)
tobyspark 29:95a7efe30527 916 {
tobyspark 31:01845a2347ff 917 handleTVOneSources(true);
tobyspark 29:95a7efe30527 918 }
tobyspark 23:909928cafb95 919 else if (advancedMenu.selectedItem().payload.command[0] == advancedConformProcessor)
tobyspark 17:fc68d40b8b1f 920 {
tobyspark 20:8b92d7922c48 921 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 20:8b92d7922c48 922 screen.textToBuffer("Conforming...", kTVOneStatusLine);
tobyspark 20:8b92d7922c48 923 screen.sendBuffer();
tobyspark 20:8b92d7922c48 924
tobyspark 17:fc68d40b8b1f 925 bool ok = conformProcessor();
tobyspark 17:fc68d40b8b1f 926
tobyspark 17:fc68d40b8b1f 927 std::string sendOK = ok ? "Conform success" : "Send Error: Conform";
tobyspark 17:fc68d40b8b1f 928
tobyspark 17:fc68d40b8b1f 929 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 17:fc68d40b8b1f 930 screen.textToBuffer(sendOK, kTVOneStatusLine);
tobyspark 17:fc68d40b8b1f 931 }
tobyspark 23:909928cafb95 932 else if (advancedMenu.selectedItem().payload.command[0] == advancedLoadDefaults)
tobyspark 16:52484666b323 933 {
tobyspark 16:52484666b323 934 settings.loadDefaults();
tobyspark 27:27851d3d2bba 935 setMixModeMenuItems();
tobyspark 27:27851d3d2bba 936 setResolutionMenuItems();
tobyspark 16:52484666b323 937
tobyspark 16:52484666b323 938 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 16:52484666b323 939 screen.textToBuffer("Controller reverted", kTVOneStatusLine);
tobyspark 16:52484666b323 940 }
tobyspark 23:909928cafb95 941 else if (advancedMenu.selectedItem().payload.command[0] == advancedSetResolutions)
tobyspark 21:f9d63cb7cedb 942 {
tobyspark 21:f9d63cb7cedb 943 bool ok;
tobyspark 21:f9d63cb7cedb 944 ok = tvOne.setCustomResolutions();
tobyspark 21:f9d63cb7cedb 945
tobyspark 21:f9d63cb7cedb 946 screen.clearBufferRow(kTVOneStatusLine);
tobyspark 21:f9d63cb7cedb 947 screen.textToBuffer(ok ? "Resolutions set" : "Res' could not be set", kTVOneStatusLine);
tobyspark 21:f9d63cb7cedb 948 }
tobyspark 12:c270870bdd23 949 }
tobyspark 0:87aab40d5806 950 else
tobyspark 0:87aab40d5806 951 {
tobyspark 0:87aab40d5806 952 if (debug) { debug->printf("Warning: No action identified"); }
tobyspark 0:87aab40d5806 953 }
tobyspark 0:87aab40d5806 954 }
tobyspark 0:87aab40d5806 955
tobyspark 2:50043054e4f7 956 // Send any updates to the display
tobyspark 2:50043054e4f7 957 screen.sendBuffer();
tobyspark 5:f8b285ca41ba 958
tobyspark 0:87aab40d5806 959
tobyspark 5:f8b285ca41ba 960 //// MIX MIX MIX MIX MIX MIX MIX MIX MIX MIX MIX MIXMIX MIX MIXMIX MIX MIX MIX MIX MIXMIX MIX MIX
tobyspark 0:87aab40d5806 961
tobyspark 0:87aab40d5806 962 bool updateFade = false;
tobyspark 3:033d2b7768f3 963 float xFade = 0;
tobyspark 3:033d2b7768f3 964 float fadeUp = 1;
tobyspark 3:033d2b7768f3 965
tobyspark 3:033d2b7768f3 966 //// TASK: Process control surface
tobyspark 3:033d2b7768f3 967
tobyspark 0:87aab40d5806 968 // Get new states of tap buttons, remembering at end of loop() assign these current values to the previous variables
tobyspark 5:f8b285ca41ba 969 const bool tapLeft = !tapLeftDIN;
tobyspark 5:f8b285ca41ba 970 const bool tapRight = !tapRightDIN;
tobyspark 0:87aab40d5806 971
tobyspark 17:fc68d40b8b1f 972 // We're taking a further median of the AINs on top of mbed libs v29.
tobyspark 17:fc68d40b8b1f 973 // This takes some values from last passes and most from now. With debug off, seem to need median size > 5
tobyspark 17:fc68d40b8b1f 974 xFadeFilter.process(xFadeAIN.read());
tobyspark 17:fc68d40b8b1f 975 fadeUpFilter.process(fadeUpAIN.read());
tobyspark 17:fc68d40b8b1f 976 xFadeFilter.process(xFadeAIN.read());
tobyspark 17:fc68d40b8b1f 977 fadeUpFilter.process(fadeUpAIN.read());
tobyspark 17:fc68d40b8b1f 978 xFadeFilter.process(xFadeAIN.read());
tobyspark 17:fc68d40b8b1f 979 fadeUpFilter.process(fadeUpAIN.read());
tobyspark 17:fc68d40b8b1f 980 xFadeFilter.process(xFadeAIN.read());
tobyspark 17:fc68d40b8b1f 981 fadeUpFilter.process(fadeUpAIN.read());
tobyspark 17:fc68d40b8b1f 982 const float xFadeAINCached = xFadeFilter.process(xFadeAIN.read());
tobyspark 17:fc68d40b8b1f 983 const float fadeUpAINCached = fadeUpFilter.process(fadeUpAIN.read());
tobyspark 0:87aab40d5806 984
tobyspark 0:87aab40d5806 985 // When a tap is depressed, we can ignore any move of the crossfader but not fade to black
tobyspark 0:87aab40d5806 986 if (tapLeft || tapRight)
tobyspark 0:87aab40d5806 987 {
tobyspark 5:f8b285ca41ba 988 // If both are pressed, take to the one that is new, ie. not the first pressed.
tobyspark 0:87aab40d5806 989 if (tapLeft && tapRight)
tobyspark 0:87aab40d5806 990 {
tobyspark 5:f8b285ca41ba 991 xFade = tapLeftWasFirstPressed ? 1 : 0;
tobyspark 0:87aab40d5806 992 }
tobyspark 5:f8b285ca41ba 993 // If just one is pressed, take to that and remember which is pressed
tobyspark 5:f8b285ca41ba 994 else if (tapLeft)
tobyspark 5:f8b285ca41ba 995 {
tobyspark 5:f8b285ca41ba 996 xFade = 0;
tobyspark 5:f8b285ca41ba 997 tapLeftWasFirstPressed = 1;
tobyspark 5:f8b285ca41ba 998 }
tobyspark 5:f8b285ca41ba 999 else if (tapRight)
tobyspark 5:f8b285ca41ba 1000 {
tobyspark 5:f8b285ca41ba 1001 xFade = 1;
tobyspark 5:f8b285ca41ba 1002 tapLeftWasFirstPressed = 0;
tobyspark 5:f8b285ca41ba 1003 }
tobyspark 5:f8b285ca41ba 1004 }
tobyspark 18:ebe5da639a6a 1005 else xFade = 1.0 - fadeCalc(xFadeAINCached, xFadeTolerance);
tobyspark 0:87aab40d5806 1006
tobyspark 0:87aab40d5806 1007 fadeUp = 1.0 - fadeCalc(fadeUpAINCached, fadeUpTolerance);
tobyspark 0:87aab40d5806 1008
tobyspark 3:033d2b7768f3 1009 //// TASK: Process Network Comms
tobyspark 5:f8b285ca41ba 1010 if (commsMode == commsOSC)
tobyspark 3:033d2b7768f3 1011 {
tobyspark 3:033d2b7768f3 1012 if (osc->newMessage)
tobyspark 3:033d2b7768f3 1013 {
tobyspark 3:033d2b7768f3 1014 osc->newMessage = false; // fixme!
tobyspark 3:033d2b7768f3 1015 processOSC(xFade, fadeUp);
tobyspark 3:033d2b7768f3 1016 }
tobyspark 3:033d2b7768f3 1017 }
tobyspark 3:033d2b7768f3 1018
tobyspark 5:f8b285ca41ba 1019 if (commsMode == commsArtNet)
tobyspark 3:033d2b7768f3 1020 {
tobyspark 3:033d2b7768f3 1021 if (artNet->Work()) processArtNet(xFade, fadeUp);
tobyspark 3:033d2b7768f3 1022 }
tobyspark 3:033d2b7768f3 1023
tobyspark 5:f8b285ca41ba 1024 if (commsMode == commsDMXIn)
tobyspark 5:f8b285ca41ba 1025 {
tobyspark 5:f8b285ca41ba 1026 processDMXIn(xFade, fadeUp);
tobyspark 5:f8b285ca41ba 1027 }
tobyspark 5:f8b285ca41ba 1028
tobyspark 5:f8b285ca41ba 1029 if (commsMode == commsDMXOut)
tobyspark 5:f8b285ca41ba 1030 {
tobyspark 5:f8b285ca41ba 1031 processDMXOut(xFade, fadeUp);
tobyspark 5:f8b285ca41ba 1032 }
tobyspark 0:87aab40d5806 1033
tobyspark 0:87aab40d5806 1034 // Calculate new A&B fade percents
tobyspark 0:87aab40d5806 1035 int newFadeAPercent = 0;
tobyspark 0:87aab40d5806 1036 int newFadeBPercent = 0;
tobyspark 0:87aab40d5806 1037
tobyspark 30:873979018850 1038 if (mixMode == mixBlend)
tobyspark 11:0783cfbeb746 1039 {
tobyspark 30:873979018850 1040 if (fadeUp < 1.0)
tobyspark 30:873979018850 1041 {
tobyspark 30:873979018850 1042 // we need to set fade level of both windows as there is no way AFAIK to implement fade to black as a further window on top of A&B
tobyspark 30:873979018850 1043 newFadeAPercent = (1.0-xFade) * fadeUp * 100.0;
tobyspark 30:873979018850 1044 newFadeBPercent = xFade * fadeUp * 100.0;
tobyspark 30:873979018850 1045 }
tobyspark 30:873979018850 1046 else
tobyspark 30:873979018850 1047 {
tobyspark 30:873979018850 1048 // we can optimise and just fade A in and out over a fully up B, doubling the rate of fadeA commands sent.
tobyspark 30:873979018850 1049 newFadeAPercent = (1.0-xFade) * 100.0;
tobyspark 30:873979018850 1050 newFadeBPercent = 100.0;
tobyspark 30:873979018850 1051 }
tobyspark 11:0783cfbeb746 1052 }
tobyspark 15:4b394c64b461 1053 else if (mixMode == mixAdditive)
tobyspark 11:0783cfbeb746 1054 {
tobyspark 22:90054fe6d86c 1055 // we need to set fade level of both windows according to the fade curve profile
tobyspark 22:90054fe6d86c 1056 float newFadeA = (1.0-xFade) * (1.0 + fadeCurve);
tobyspark 22:90054fe6d86c 1057 float newFadeB = xFade * (1 + fadeCurve);
tobyspark 22:90054fe6d86c 1058 if (newFadeA > 1.0) newFadeA = 1.0;
tobyspark 22:90054fe6d86c 1059 if (newFadeB > 1.0) newFadeB = 1.0;
tobyspark 22:90054fe6d86c 1060
tobyspark 22:90054fe6d86c 1061 newFadeAPercent = newFadeA * fadeUp * 100.0;
tobyspark 22:90054fe6d86c 1062 newFadeBPercent = newFadeB * fadeUp * 100.0;
tobyspark 11:0783cfbeb746 1063 }
tobyspark 15:4b394c64b461 1064 else if (mixMode >= mixKey)
tobyspark 11:0783cfbeb746 1065 {
tobyspark 0:87aab40d5806 1066 newFadeAPercent = (1.0-xFade) * fadeUp * 100.0;
tobyspark 0:87aab40d5806 1067 newFadeBPercent = fadeUp * 100.0;
tobyspark 0:87aab40d5806 1068 }
tobyspark 0:87aab40d5806 1069
tobyspark 17:fc68d40b8b1f 1070 //// TASK: Send to TVOne if percents have changed
tobyspark 17:fc68d40b8b1f 1071
tobyspark 17:fc68d40b8b1f 1072 // No amount of median filtering is stopping flipflopping between two adjacent percents, so...
tobyspark 17:fc68d40b8b1f 1073 bool fadeAPercentHasChanged;
tobyspark 17:fc68d40b8b1f 1074 bool fadeBPercentHasChanged;
tobyspark 17:fc68d40b8b1f 1075 if (oldFadeAPercent == newFadeAPercent && (newFadeAPercent == fadeAPercent - 1 || newFadeAPercent == fadeAPercent + 1))
tobyspark 17:fc68d40b8b1f 1076 fadeAPercentHasChanged = false;
tobyspark 17:fc68d40b8b1f 1077 else
tobyspark 17:fc68d40b8b1f 1078 fadeAPercentHasChanged = newFadeAPercent != fadeAPercent;
tobyspark 17:fc68d40b8b1f 1079 if (oldFadeBPercent == newFadeBPercent && (newFadeBPercent == fadeBPercent - 1 || newFadeBPercent == fadeBPercent + 1))
tobyspark 17:fc68d40b8b1f 1080 fadeBPercentHasChanged = false;
tobyspark 17:fc68d40b8b1f 1081 else
tobyspark 17:fc68d40b8b1f 1082 fadeBPercentHasChanged = newFadeBPercent != fadeBPercent;
tobyspark 17:fc68d40b8b1f 1083
tobyspark 9:f83eadd8917a 1084 // We want to send the higher first, otherwise black flashes can happen on taps
tobyspark 17:fc68d40b8b1f 1085 if (fadeAPercentHasChanged && newFadeAPercent >= newFadeBPercent)
tobyspark 8:d46cc49f0f37 1086 {
tobyspark 17:fc68d40b8b1f 1087 oldFadeAPercent = fadeAPercent;
tobyspark 0:87aab40d5806 1088 fadeAPercent = newFadeAPercent;
tobyspark 0:87aab40d5806 1089 updateFade = true;
tobyspark 0:87aab40d5806 1090
tobyspark 0:87aab40d5806 1091 fadeAPO = fadeAPercent / 100.0;
tobyspark 0:87aab40d5806 1092 tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsMaxFadeLevel, fadeAPercent);
tobyspark 0:87aab40d5806 1093 }
tobyspark 17:fc68d40b8b1f 1094 if (fadeBPercentHasChanged)
tobyspark 8:d46cc49f0f37 1095 {
tobyspark 17:fc68d40b8b1f 1096 oldFadeBPercent = fadeBPercent;
tobyspark 0:87aab40d5806 1097 fadeBPercent = newFadeBPercent;
tobyspark 0:87aab40d5806 1098 updateFade = true;
tobyspark 0:87aab40d5806 1099
tobyspark 0:87aab40d5806 1100 fadeBPO = fadeBPercent / 100.0;
tobyspark 0:87aab40d5806 1101 tvOne.command(0, kTV1WindowIDB, kTV1FunctionAdjustWindowsMaxFadeLevel, fadeBPercent);
tobyspark 0:87aab40d5806 1102 }
tobyspark 17:fc68d40b8b1f 1103 if (fadeAPercentHasChanged && newFadeAPercent < newFadeBPercent)
tobyspark 9:f83eadd8917a 1104 {
tobyspark 17:fc68d40b8b1f 1105 oldFadeAPercent = fadeAPercent;
tobyspark 9:f83eadd8917a 1106 fadeAPercent = newFadeAPercent;
tobyspark 9:f83eadd8917a 1107 updateFade = true;
tobyspark 9:f83eadd8917a 1108
tobyspark 9:f83eadd8917a 1109 fadeAPO = fadeAPercent / 100.0;
tobyspark 9:f83eadd8917a 1110 tvOne.command(0, kTV1WindowIDA, kTV1FunctionAdjustWindowsMaxFadeLevel, fadeAPercent);
tobyspark 9:f83eadd8917a 1111 }
tobyspark 8:d46cc49f0f37 1112 if (updateFade && debug)
tobyspark 8:d46cc49f0f37 1113 {
tobyspark 0:87aab40d5806 1114 //debug->printf("xFade = %3f fadeUp = %3f \r\n", xFadeAIN.read(), fadeUpAIN.read());
tobyspark 0:87aab40d5806 1115 debug->printf("xFade = %3f fadeUp = %3f \r\n", xFadeAINCached, fadeUpAINCached);
tobyspark 0:87aab40d5806 1116 debug->printf("xFade = %3f fadeUp = %3f fadeA% = %i fadeB% = %i \r\n", xFade, fadeUp, fadeAPercent, fadeBPercent);
tobyspark 18:ebe5da639a6a 1117 debug->printf("\r\n");
tobyspark 0:87aab40d5806 1118 }
tobyspark 30:873979018850 1119
tobyspark 30:873979018850 1120 // If we're not actively mixing, we can do any housekeeping...
tobyspark 30:873979018850 1121 if (!updateFade)
tobyspark 30:873979018850 1122 {
tobyspark 30:873979018850 1123 // We should check up on any source flagged unstable
tobyspark 30:873979018850 1124 if (!tvOneRGB1Stable || !tvOneRGB2Stable) handleTVOneSources();
tobyspark 30:873979018850 1125 }
tobyspark 0:87aab40d5806 1126 }
tobyspark 30:873979018850 1127 }