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:
Tue Nov 06 00:21:38 2012 +0000
Revision:
35:d5d9f0838f99
Parent:
34:69dfe64e7e6b
Child:
36:8b5c75c8bc23
v22. EDID for breakfast.

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