RS232 control for TVOne products

Dependents:   SPK-DVIMXR

Committer:
tobyspark
Date:
Sun Apr 15 20:58:35 2012 +0000
Revision:
0:533cfae24a1b
Child:
1:349d6da461df
rolling files into library

Who changed what in which revision?

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