RS232 control for TVOne products
spk_tvone_mbed.cpp@0:533cfae24a1b, 2012-04-15 (annotated)
- 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?
User | Revision | Line number | New 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 | } |