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:
Sat Mar 10 19:26:44 2012 +0000
Revision:
0:87aab40d5806
v15 - PCB a la toby; OLED a la toby

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tobyspark 0:87aab40d5806 1 // THIS IS AS PER spk_dvimxr_v07 AND IS OUT OF DATE, NEEDS APHEX TWIN FIXES
tobyspark 0:87aab40d5806 2
tobyspark 0:87aab40d5806 3 // *spark audio-visual
tobyspark 0:87aab40d5806 4 // RS232 Control for TV-One products
tobyspark 0:87aab40d5806 5 // Good for 1T-C2-750, others will need some extra work
tobyspark 0:87aab40d5806 6 // Copyright *spark audio-visual 2009-2010
tobyspark 0:87aab40d5806 7
tobyspark 0:87aab40d5806 8 #include "spk_tvone_mbed.h"
tobyspark 0:87aab40d5806 9 #include "mbed.h"
tobyspark 0:87aab40d5806 10
tobyspark 0:87aab40d5806 11 SPKTVOne::SPKTVOne(PinName txPin, PinName rxPin, PinName signWritePin, PinName signErrorPin, Serial *debugSerial)
tobyspark 0:87aab40d5806 12 {
tobyspark 0:87aab40d5806 13 // Create Serial connection for TVOne unit comms
tobyspark 0:87aab40d5806 14 // Creating our own as this is exclusively for TVOne comms
tobyspark 0:87aab40d5806 15 serial = new Serial(txPin, rxPin);
tobyspark 0:87aab40d5806 16 serial->baud(57600);
tobyspark 0:87aab40d5806 17
tobyspark 0:87aab40d5806 18 if (signWritePin != NC) writeDO = new DigitalOut(signWritePin);
tobyspark 0:87aab40d5806 19 else writeDO = NULL;
tobyspark 0:87aab40d5806 20
tobyspark 0:87aab40d5806 21 if (signErrorPin != NC) errorDO = new DigitalOut(signErrorPin);
tobyspark 0:87aab40d5806 22 else errorDO = NULL;
tobyspark 0:87aab40d5806 23
tobyspark 0:87aab40d5806 24 // Link up debug Serial object
tobyspark 0:87aab40d5806 25 // Passing in shared object as debugging is shared between all DVI mixer functions
tobyspark 0:87aab40d5806 26 debug = debugSerial;
tobyspark 0:87aab40d5806 27 }
tobyspark 0:87aab40d5806 28
tobyspark 0:87aab40d5806 29 bool SPKTVOne::command(uint8_t channel, uint8_t window, int32_t func, int32_t payload)
tobyspark 0:87aab40d5806 30 {
tobyspark 0:87aab40d5806 31 char i;
tobyspark 0:87aab40d5806 32
tobyspark 0:87aab40d5806 33 // TASK: Sign start of serial command write
tobyspark 0:87aab40d5806 34 if (writeDO) *writeDO = 1;
tobyspark 0:87aab40d5806 35
tobyspark 0:87aab40d5806 36 // TASK: discard anything waiting to be read
tobyspark 0:87aab40d5806 37 while (serial->readable()) {
tobyspark 0:87aab40d5806 38 serial->getc();
tobyspark 0:87aab40d5806 39 }
tobyspark 0:87aab40d5806 40
tobyspark 0:87aab40d5806 41 // TASK: Create the bytes of command
tobyspark 0:87aab40d5806 42
tobyspark 0:87aab40d5806 43 uint8_t cmd[8];
tobyspark 0:87aab40d5806 44 uint8_t checksum = 0;
tobyspark 0:87aab40d5806 45
tobyspark 0:87aab40d5806 46 // CMD
tobyspark 0:87aab40d5806 47 cmd[0] = 1<<2; // write
tobyspark 0:87aab40d5806 48 // CHA
tobyspark 0:87aab40d5806 49 cmd[1] = channel;
tobyspark 0:87aab40d5806 50 // WINDOW
tobyspark 0:87aab40d5806 51 cmd[2] = window;
tobyspark 0:87aab40d5806 52 // OUTPUT & FUNCTION
tobyspark 0:87aab40d5806 53 // cmd[3] cmd[4]
tobyspark 0:87aab40d5806 54 // output 0 = 0000xxx xxxxxxx
tobyspark 0:87aab40d5806 55 // function = xxxXXXX XXXXXXX
tobyspark 0:87aab40d5806 56 cmd[3] = func >> 8;
tobyspark 0:87aab40d5806 57 cmd[4] = func & 0xFF;
tobyspark 0:87aab40d5806 58 // PAYLOAD
tobyspark 0:87aab40d5806 59 cmd[5] = (payload >> 16) & 0xFF;
tobyspark 0:87aab40d5806 60 cmd[6] = (payload >> 8) & 0xFF;
tobyspark 0:87aab40d5806 61 cmd[7] = payload & 0xFF;
tobyspark 0:87aab40d5806 62
tobyspark 0:87aab40d5806 63 // TASK: Write the bytes of command to RS232 as correctly packaged 20 characters of ASCII
tobyspark 0:87aab40d5806 64
tobyspark 0:87aab40d5806 65 for (i=0; i<8; i++)
tobyspark 0:87aab40d5806 66 {
tobyspark 0:87aab40d5806 67 checksum += cmd[i];
tobyspark 0:87aab40d5806 68 }
tobyspark 0:87aab40d5806 69
tobyspark 0:87aab40d5806 70 serial->printf("F%02X%02X%02X%02X%02X%02X%02X%02X%02X\r", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], checksum);
tobyspark 0:87aab40d5806 71
tobyspark 0:87aab40d5806 72 // TASK: Check the unit's return string, to enable return to main program as soon as unit is ready
tobyspark 0:87aab40d5806 73
tobyspark 0:87aab40d5806 74 // Handling the timing of this return is critical to effective control.
tobyspark 0:87aab40d5806 75 // Returning the instant something is received back overloads the processor, as does anything until the full 20 char acknowledgement.
tobyspark 0:87aab40d5806 76 // TVOne turn out to say that receipt of the ack doesn't guarantee the unit is ready for the next command.
tobyspark 0:87aab40d5806 77 // According to the manual, operations typically take 30ms, and to simplify programming you can throttle commands to every 100ms.
tobyspark 0:87aab40d5806 78 // 100ms is too slow for us. Going with returning after 30ms if we've received an acknowledgement, returning after 100ms otherwise.
tobyspark 0:87aab40d5806 79
tobyspark 0:87aab40d5806 80 int ack[20];
tobyspark 0:87aab40d5806 81 int safePeriod = 100;
tobyspark 0:87aab40d5806 82 int clearPeriod = 30;
tobyspark 0:87aab40d5806 83 bool ackReceived = false;
tobyspark 0:87aab40d5806 84 bool success = false;
tobyspark 0:87aab40d5806 85 Timer timer;
tobyspark 0:87aab40d5806 86
tobyspark 0:87aab40d5806 87 timer.start();
tobyspark 0:87aab40d5806 88 i = 0;
tobyspark 0:87aab40d5806 89 while (timer.read_ms() < safePeriod) {
tobyspark 0:87aab40d5806 90 if (serial->readable())
tobyspark 0:87aab40d5806 91 {
tobyspark 0:87aab40d5806 92 ack[i] = serial->getc();
tobyspark 0:87aab40d5806 93 i++;
tobyspark 0:87aab40d5806 94 if (i >= 20)
tobyspark 0:87aab40d5806 95 {
tobyspark 0:87aab40d5806 96 ackReceived = true;
tobyspark 0:87aab40d5806 97 if (ack[0] == 'F' && ack[1] == '4') // TVOne start of message, acknowledgement with no error, rest will be repeat of sent command
tobyspark 0:87aab40d5806 98 {
tobyspark 0:87aab40d5806 99 success = true;
tobyspark 0:87aab40d5806 100 }
tobyspark 0:87aab40d5806 101 }
tobyspark 0:87aab40d5806 102 }
tobyspark 0:87aab40d5806 103 if (ackReceived && (timer.read_ms() > clearPeriod)) break;
tobyspark 0:87aab40d5806 104 }
tobyspark 0:87aab40d5806 105 timer.stop();
tobyspark 0:87aab40d5806 106
tobyspark 0:87aab40d5806 107 // TASK: Sign end of write
tobyspark 0:87aab40d5806 108
tobyspark 0:87aab40d5806 109 if (writeDO) *writeDO = 0;
tobyspark 0:87aab40d5806 110
tobyspark 0:87aab40d5806 111 if (!success) {
tobyspark 0:87aab40d5806 112 if (errorDO) {
tobyspark 0:87aab40d5806 113 signErrorTimeout.detach();
tobyspark 0:87aab40d5806 114 signErrorTimeout.attach(this, &SPKTVOne::signErrorOff, 0.25);
tobyspark 0:87aab40d5806 115 *errorDO = 1;
tobyspark 0:87aab40d5806 116 }
tobyspark 0:87aab40d5806 117
tobyspark 0:87aab40d5806 118 if (debug) {
tobyspark 0:87aab40d5806 119 debug->printf("Serial command write error. Time from write finish: %ims \r\n", timer.read_ms());
tobyspark 0:87aab40d5806 120 }
tobyspark 0:87aab40d5806 121 };
tobyspark 0:87aab40d5806 122
tobyspark 0:87aab40d5806 123 return success;
tobyspark 0:87aab40d5806 124 }
tobyspark 0:87aab40d5806 125
tobyspark 0:87aab40d5806 126 void SPKTVOne::setCustomResolutions()
tobyspark 0:87aab40d5806 127 {
tobyspark 0:87aab40d5806 128 set1920x480(kTV1ResolutionTripleHeadVGAp60);
tobyspark 0:87aab40d5806 129 set1600x600(kTV1ResolutionDualHeadSVGAp60);
tobyspark 0:87aab40d5806 130 }
tobyspark 0:87aab40d5806 131
tobyspark 0:87aab40d5806 132 bool SPKTVOne::setHDCPOff()
tobyspark 0:87aab40d5806 133 {
tobyspark 0:87aab40d5806 134 bool ok = false;
tobyspark 0:87aab40d5806 135
tobyspark 0:87aab40d5806 136 // Turn HDCP off on the output
tobyspark 0:87aab40d5806 137 ok = command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsHDCPRequired, 0);
tobyspark 0:87aab40d5806 138 ok = ok && command(0, kTV1WindowIDA, kTV1FunctionAdjustOutputsHDCPStatus, 0);
tobyspark 0:87aab40d5806 139 // Likewise on inputs A and B
tobyspark 0:87aab40d5806 140 ok = ok && command(0, kTV1WindowIDA, kTV1FunctionAdjustSourceHDCPAdvertize, 0);
tobyspark 0:87aab40d5806 141 ok = ok && command(0, kTV1WindowIDA, kTV1FunctionAdjustSourceHDCPAdvertize, 0);
tobyspark 0:87aab40d5806 142 ok = ok && command(0, kTV1WindowIDB, kTV1FunctionAdjustSourceHDCPStatus, 0);
tobyspark 0:87aab40d5806 143 ok = ok && command(0, kTV1WindowIDB, kTV1FunctionAdjustSourceHDCPStatus, 0);
tobyspark 0:87aab40d5806 144
tobyspark 0:87aab40d5806 145 return ok;
tobyspark 0:87aab40d5806 146 }
tobyspark 0:87aab40d5806 147
tobyspark 0:87aab40d5806 148 void SPKTVOne::set1920x480(int resStoreNumber)
tobyspark 0:87aab40d5806 149 {
tobyspark 0:87aab40d5806 150 command(0, 0, kTV1FunctionAdjustResolutionImageToAdjust, resStoreNumber);
tobyspark 0:87aab40d5806 151 command(0, 0, kTV1FunctionAdjustResolutionInterlaced, 0);
tobyspark 0:87aab40d5806 152 command(0, 0, kTV1FunctionAdjustResolutionFreqCoarseH, 31400);
tobyspark 0:87aab40d5806 153 command(0, 0, kTV1FunctionAdjustResolutionFreqFineH, 31475);
tobyspark 0:87aab40d5806 154 command(0, 0, kTV1FunctionAdjustResolutionActiveH, 1920);
tobyspark 0:87aab40d5806 155 command(0, 0, kTV1FunctionAdjustResolutionActiveV, 480);
tobyspark 0:87aab40d5806 156 command(0, 0, kTV1FunctionAdjustResolutionStartH, 192);
tobyspark 0:87aab40d5806 157 command(0, 0, kTV1FunctionAdjustResolutionStartV, 32);
tobyspark 0:87aab40d5806 158 command(0, 0, kTV1FunctionAdjustResolutionCLKS, 2400);
tobyspark 0:87aab40d5806 159 command(0, 0, kTV1FunctionAdjustResolutionLines, 525);
tobyspark 0:87aab40d5806 160 command(0, 0, kTV1FunctionAdjustResolutionSyncH, 240);
tobyspark 0:87aab40d5806 161 command(0, 0, kTV1FunctionAdjustResolutionSyncV, 5);
tobyspark 0:87aab40d5806 162 command(0, 0, kTV1FunctionAdjustResolutionSyncPolarity, 0);
tobyspark 0:87aab40d5806 163 }
tobyspark 0:87aab40d5806 164
tobyspark 0:87aab40d5806 165 void SPKTVOne::set1600x600(int resStoreNumber)
tobyspark 0:87aab40d5806 166 {
tobyspark 0:87aab40d5806 167 command(0, 0, kTV1FunctionAdjustResolutionImageToAdjust, resStoreNumber);
tobyspark 0:87aab40d5806 168 command(0, 0, kTV1FunctionAdjustResolutionInterlaced, 0);
tobyspark 0:87aab40d5806 169 command(0, 0, kTV1FunctionAdjustResolutionFreqCoarseH, 37879);
tobyspark 0:87aab40d5806 170 command(0, 0, kTV1FunctionAdjustResolutionFreqFineH, 37879);
tobyspark 0:87aab40d5806 171 command(0, 0, kTV1FunctionAdjustResolutionActiveH, 1600);
tobyspark 0:87aab40d5806 172 command(0, 0, kTV1FunctionAdjustResolutionActiveV, 600);
tobyspark 0:87aab40d5806 173 command(0, 0, kTV1FunctionAdjustResolutionStartH, 160);
tobyspark 0:87aab40d5806 174 command(0, 0, kTV1FunctionAdjustResolutionStartV, 1);
tobyspark 0:87aab40d5806 175 command(0, 0, kTV1FunctionAdjustResolutionCLKS, 2112);
tobyspark 0:87aab40d5806 176 command(0, 0, kTV1FunctionAdjustResolutionLines, 628);
tobyspark 0:87aab40d5806 177 command(0, 0, kTV1FunctionAdjustResolutionSyncH, 192);
tobyspark 0:87aab40d5806 178 command(0, 0, kTV1FunctionAdjustResolutionSyncV, 14);
tobyspark 0:87aab40d5806 179 command(0, 0, kTV1FunctionAdjustResolutionSyncPolarity, 0);
tobyspark 0:87aab40d5806 180 }
tobyspark 0:87aab40d5806 181
tobyspark 0:87aab40d5806 182 void SPKTVOne::signErrorOff() {
tobyspark 0:87aab40d5806 183 *errorDO = 0;
tobyspark 0:87aab40d5806 184 }