AJA NTV2 SDK  17.5.0.1242
NTV2 SDK 17.5.0.1242
ntv2serialcontrol.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2serialcontrol.h"
9 #include "ntv2devicescanner.h"
10 #include "ntv2devicefeatures.h"
12 #include <assert.h>
13 
14 
15 
16 // NOTE!!! first byte is command length
17 static UByte playCommand[] = { 0x2, 0x20, 0x01 };
18 static UByte stopCommand[] = { 0x2, 0x20, 0x00 };
19 static UByte fastForwardCommand[] = { 0x2, 0x20, 0x10 };
20 static UByte rewindCommand[] = { 0x2, 0x20, 0x20 };
21 static UByte reversePlayCommand[] = { 0x3, 0x21, 0x21, 0x40 };
22 // static UByte deviceTypeCommand = { 0x2, 0x00, 0x11 }; // Unused, suppress warning
23 static UByte ltcTimeDataCommand[] = { 0x3, 0x61, 0x0C, 0x01 };
24 
25 
26 CNTV2SerialControl::CNTV2SerialControl (const UWord inDeviceIndexNumber, const UWord inSerialPortIndexNum)
27  : _controlRegisterNum (kRegRS422Control),
28  _receiveRegisterNum (kRegRS422Receive),
29  _transmitRegisterNum(kRegRS422Transmit)
30 {
31  if (CNTV2DeviceScanner::GetDeviceAtIndex(inDeviceIndexNumber, _ntv2Card))
32  {
33  if (inSerialPortIndexNum < ::NTV2DeviceGetNumSerialPorts (_ntv2Card.GetDeviceID ()))
34  {
35  if (inSerialPortIndexNum > 0)
36  {
40  } // if using 2nd serial port
41 
42  // Verify that the device can do RS422...
43  ULWord value (0);
45  assert (value & kRegMaskRS422Present && "UART must be present!");
46 
47  // Flush the FIFO's and enable TX and RX...
50 
51  // Used for receive response from machine...
56  }
57  else // Desired serial port not present
58  _ntv2Card.Close ();
59  }
61 
62 } // constructor
63 
64 
66 {
67  ULWord value = 0;
68 
69  if (_ntv2Card.IsOpen ())
70  {
71  // Flush the FIFO's and disable TX and RX...
72  value |= kRegMaskRS422Flush;
75 
78  _ntv2Card.Close (); // Unsubscribe happens in destructor
79  }
80 } // destructor
81 
82 
84 {
85  WriteCommand (playCommand, true);
86  return GotACK ();
87 }
88 
89 
91 {
93  return GotACK ();
94 }
95 
96 
98 {
99  WriteCommand (stopCommand, true);
100  return GotACK ();
101 }
102 
103 
105 {
107  return GotACK ();
108 }
109 
110 
112 {
113  WriteCommand (rewindCommand, true);
114  return GotACK ();
115 }
116 
117 
119 {
120  SByte timecodeString [12];
121  GetTimecodeString (timecodeString);
122 
123  const SerialMachineResponse & lastResponse (GetLastResponse ());
124  UByte hoursBCD = lastResponse.buffer[5];
125  UByte minutesBCD = lastResponse.buffer[4];
126  UByte secondsBCD = lastResponse.buffer[3];
127  UByte framesBCD = lastResponse.buffer[2]&0x3F;
128  UByte hours = (hoursBCD>>4)*10 + (hoursBCD&0xF);
129  UByte minutes = (minutesBCD>>4)*10 + (minutesBCD&0xF);
130  UByte seconds = (secondsBCD>>4)*10 + (secondsBCD&0xF);
131  UByte frames = (framesBCD>>4)*10 + (framesBCD&0xF);
132 
133 
134  frames++;
135  if ( frames > 29 )
136  {
137  frames = 0;
138  seconds++;
139  if ( seconds > 59 )
140  {
141  seconds = 0;
142  minutes++;
143  if ( minutes > 59 )
144  hours++; // don't even try to check for a wrap here
145  }
146  }
147 
148  GotoFrameByHMS (hours, minutes, seconds, frames);
149 
150  return true;
151 }
152 
153 
155 {
156  SByte timecodeString[12];
157  GetTimecodeString(timecodeString);
158  const SerialMachineResponse & lastResponse (GetLastResponse ());
159  UByte hoursBCD = lastResponse.buffer[5];
160  UByte minutesBCD = lastResponse.buffer[4];
161  UByte secondsBCD = lastResponse.buffer[3];
162  UByte framesBCD = lastResponse.buffer[2]&0x3F;
163  UByte hours = (hoursBCD>>4)*10 + (hoursBCD&0xF);
164  UByte minutes = (minutesBCD>>4)*10 + (minutesBCD&0xF);
165  UByte seconds = (secondsBCD>>4)*10 + (secondsBCD&0xF);
166  UByte frames = (framesBCD>>4)*10 + (framesBCD&0xF);
167 
168  frames--;
169  if ( frames == 255 )
170  {
171  frames = 29;
172  seconds--;
173  if ( seconds == 255 )
174  {
175  seconds = 59;
176  minutes--;
177  if ( minutes == 255 )
178  {
179  minutes = 59;
180  if ( hours > 0 )
181  hours--;
182  }
183  }
184  }
185 
186  GotoFrameByHMS (hours, minutes, seconds, frames);
187 
188  return true;
189 
190 } // BackFrame
191 
192 
194 {
195  static char bcd [] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '0', '0', '0', '0', '0'};
196 
198 
199  const SerialMachineResponse & lastResponse (GetLastResponse ());
200  if (lastResponse.length)
201  {
202  UByte hours = lastResponse.buffer [5];
203  UByte minutes = lastResponse.buffer [4];
204  UByte seconds = lastResponse.buffer [3];
205  UByte frames = lastResponse.buffer [2] & 0x3F;
206 
207  timecodeString [0] = bcd[hours>>4];
208  timecodeString [1] = bcd[hours&0xF];
209  timecodeString [2] = ':';
210  timecodeString [3] = bcd[minutes>>4];
211  timecodeString [4] = bcd[minutes&0xF];
212  timecodeString [5] = ':';
213  timecodeString [6] = bcd[seconds>>4];
214  timecodeString [7] = bcd[seconds&0xF];
215  timecodeString [8] = ':';
216  timecodeString [9] = bcd[frames>>4];
217  timecodeString [10] = bcd[frames&0xF];
218  timecodeString [11] = '\0';
219  //printf("%s\n", timecodeString);
220  }
221 
222  return true;
223 
224 } // GetTimecodeString
225 
226 
227 //GotoFrameByHoursMinutesSeconds
228 // NOTE no error checking.
230 {
231  UByte cueUpWithDataCommand [] = {0x6, 0x24, 0x31, 0x00, 0x00, 0x00, 0x00};
232 
233  cueUpWithDataCommand [6] = ((hours / 10) << 4) + (hours % 10);
234  cueUpWithDataCommand [5] = ((minutes / 10) << 4) + (minutes % 10);
235  cueUpWithDataCommand [4] = ((seconds / 10) << 4) + (seconds % 10);
236  cueUpWithDataCommand [3] = ((frames / 10) << 4) + (frames % 10);
237 
238  WriteCommand (cueUpWithDataCommand, true);
239  return GotACK ();
240 
241 } // GotoFrameByHoursMinutesSeconds
242 
243 
244 //
245 // WriteCommand
246 // If response == true, then go read received bytes back from machine
247 //
248 // It would work just as well to poll here to receive characters. The
249 // WaitForRxInterrupt is used only to demonstrate that it works.
250 bool CNTV2SerialControl::WriteCommand (const UByte * txBuffer, bool response)
251 {
252  ULWord val;
253  ULWord data;
254  UByte commandLength = txBuffer [0];
255  int i;
256 
257  _serialMachineResponse.length = 0; // Reset response length even if response isn't requested
258 
259  if (commandLength == 0 || commandLength > 14)
260  return false;
261 
262  if ( _ntv2Card.IsOpen ())
263  {
264  // Transmit command and checksum...
265  UByte checkSum = 0;
266  for (UWord count = 1; count <= commandLength; count++)
267  {
268  UByte value = txBuffer [count];
270  checkSum += value;
271  }
273 
274  // Wait for transmit FIFO empty (timeout = 1 byte / ms)
275  for (i = 0; i < 3; i++)
276  {
277  _ntv2Card.WaitForInterrupt (eUartTx, commandLength + 1);
278 
279  // Make sure the TX FIFO is empty...
281  if ((val & BIT_1) != 0)
282  break;
283  }
284 
285  if (!response)
286  return true;
287 
288  // Wait for the first byte from the deck...
289  for (i = 0; i < 3; i++)
290  {
292  // Make sure that there is data in the RX FIFO...
294  if (val & BIT_4)
295  {
296  // Wait for all the data...
298  break;
299  }
300  }
301 
302  // Read the response (and everything else) from the FIFO...
303  for (i = 0; i < 1000; i++)
304  {
306  if ((val & BIT_4) == 0)
307  break;
308 
312  }
313 
315  return false;
316 
317  return true;
318  } // if board open
319 
320  return false; // couldn't open board.
321 
322 } // WriteCommand
323 
324 
325 // GotACK()
326 // Test if last response was the expected ACK
327 // For some commands this will NOT be the case.
329 {
330  bool status = false;
332  {
333  if (_serialMachineResponse.buffer [0] == 0x10 &&
334  _serialMachineResponse.buffer [1] == 0x01 &&
335  _serialMachineResponse.buffer [2] == 0x11)
336  status = true;
337  }
338 
339  return status;
340 
341 } // GotACK
342 
343 
344 bool CNTV2SerialControl::WriteTxBuffer (const UByte * txBuffer, UWord length)
345 {
346  bool status = false;
347  if (_ntv2Card.IsOpen ())
348  {
349  for (UWord count = 0; count < length; count++)
350  _ntv2Card.WriteRegister (_transmitRegisterNum, txBuffer [count]);
351 
352  if (WaitForTxInterrupt ())
353  status = true;
354  }
355  return status;
356 
357 } // WriteTxBuffer
358 
359 
360 bool CNTV2SerialControl::ReadRxBuffer (UByte * rxBuffer, UWord & actualLength, UWord maxLength)
361 {
362  bool status = false;
363  if (_ntv2Card.IsOpen ())
364  {
365  ULWord val;
366  ULWord numRead = 0;
368 
369  while (val & BIT_4 && numRead < maxLength)
370  {
371  ULWord data;
373  rxBuffer [numRead++] = data & 0xFF;
375  }
376  actualLength = numRead;
377  }
378 
379  return status;
380 
381 } // ReadRxBuffer
382 
383 
385 {
386  if (_ntv2Card.IsOpen ())
388  else
389  return false;
390 }
391 
392 
394 {
395  if (_ntv2Card.IsOpen ())
397  else
398  return false;
399 }
eUart2Rx
@ eUart2Rx
Definition: ntv2publicinterface.h:3775
SByte
int8_t SByte
Definition: ajatypes.h:251
kRegRS4222Control
@ kRegRS4222Control
Definition: ntv2publicinterface.h:369
CNTV2SerialControl::GotACK
virtual bool GotACK(void)
Definition: ntv2serialcontrol.cpp:328
kRegRS4222Transmit
@ kRegRS4222Transmit
Definition: ntv2publicinterface.h:367
CNTV2SerialControl::GetTimecodeString
virtual ULWord GetTimecodeString(SByte *timecodeString)
Definition: ntv2serialcontrol.cpp:193
stopCommand
static UByte stopCommand[]
Definition: ntv2serialcontrol.cpp:18
ntv2devicefeatures.h
Declares device capability functions.
eUartTx
@ eUartTx
Definition: ntv2publicinterface.h:3758
eUart1Rx
@ eUart1Rx
Definition: ntv2publicinterface.h:3761
CNTV2MacDriverInterface::ReadRegister
virtual bool ReadRegister(const ULWord inRegNum, ULWord &outValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Reads all or part of the 32-bit contents of a specific register (real or virtual) on the AJA device....
Definition: ntv2macdriverinterface.cpp:389
playCommand
static UByte playCommand[]
Definition: ntv2serialcontrol.cpp:17
CBaseMachineControl::_controlType
ControlType _controlType
Definition: basemachinecontrol.h:61
ntv2serialcontrol.h
CNTV2SerialControl::FastForward
virtual ULWord FastForward(void)
Definition: ntv2serialcontrol.cpp:104
systemtime.h
Declares the AJATime class.
NTV2_SERIAL_RESPONSE_SIZE
#define NTV2_SERIAL_RESPONSE_SIZE
Definition: ntv2serialcontrol.h:15
kRegRS422Receive
@ kRegRS422Receive
Definition: ntv2publicinterface.h:174
CBaseMachineControl::CONTROLTYPE_NTV2
@ CONTROLTYPE_NTV2
Definition: basemachinecontrol.h:26
CNTV2SerialControl::_serialMachineResponse
SerialMachineResponse _serialMachineResponse
Definition: ntv2serialcontrol.h:69
BIT_4
#define BIT_4
Definition: ajatypes.h:576
eUart1Tx
@ eUart1Tx
Definition: ntv2publicinterface.h:3759
CNTV2SerialControl::ReversePlay
virtual ULWord ReversePlay(void)
Definition: ntv2serialcontrol.cpp:90
kRegMaskRS422Present
@ kRegMaskRS422Present
Definition: ntv2publicinterface.h:1420
CNTV2MacDriverInterface::WaitForInterrupt
virtual bool WaitForInterrupt(const INTERRUPT_ENUMS type, const ULWord timeout=50)
Definition: ntv2macdriverinterface.cpp:726
NTV2DeviceGetNumSerialPorts
UWord NTV2DeviceGetNumSerialPorts(const NTV2DeviceID inDeviceID)
Definition: ntv2devicefeatures.hpp:11927
ltcTimeDataCommand
static UByte ltcTimeDataCommand[]
Definition: ntv2serialcontrol.cpp:23
CNTV2SerialControl::Play
virtual ULWord Play(void)
Definition: ntv2serialcontrol.cpp:83
fastForwardCommand
static UByte fastForwardCommand[]
Definition: ntv2serialcontrol.cpp:19
CNTV2Card::EnableInterrupt
virtual bool EnableInterrupt(const INTERRUPT_ENUMS inEventCode)
Definition: ntv2interrupts.cpp:21
AJATime::Sleep
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
CNTV2SerialControl::ReadRxBuffer
virtual bool ReadRxBuffer(UByte *rxBuffer, UWord &actualLength, UWord maxlength)
Definition: ntv2serialcontrol.cpp:360
CNTV2SerialControl::~CNTV2SerialControl
virtual ~CNTV2SerialControl()
Definition: ntv2serialcontrol.cpp:65
ULWord
uint32_t ULWord
Definition: ajatypes.h:255
CNTV2Card::SubscribeEvent
virtual bool SubscribeEvent(const INTERRUPT_ENUMS inEventCode)
Causes me to be notified when the given event/interrupt is triggered for the AJA device.
Definition: ntv2subscriptions.cpp:19
ntv2devicescanner.h
Declares the CNTV2DeviceScanner class.
bcd
static char bcd[]
Definition: ntv2rp188.cpp:367
kRegRS422Control
@ kRegRS422Control
Definition: ntv2publicinterface.h:175
kRegMaskRS422TXEnable
@ kRegMaskRS422TXEnable
Definition: ntv2publicinterface.h:1411
CNTV2SerialControl::GetLastResponse
virtual const SerialMachineResponse & GetLastResponse(void) const
Definition: ntv2serialcontrol.h:54
CNTV2SerialControl::Stop
virtual ULWord Stop(void)
Definition: ntv2serialcontrol.cpp:97
UWord
uint16_t UWord
Definition: ajatypes.h:253
eUart2Tx
@ eUart2Tx
Definition: ntv2publicinterface.h:3773
kRegMaskRS422RXEnable
@ kRegMaskRS422RXEnable
Definition: ntv2publicinterface.h:1414
SerialMachineResponse::buffer
UByte buffer[64]
Definition: ntv2serialcontrol.h:21
CNTV2SerialControl::WriteCommand
virtual bool WriteCommand(const UByte *txBuffer, bool response=(!(0)))
Definition: ntv2serialcontrol.cpp:250
BIT_1
#define BIT_1
Definition: ajatypes.h:573
kRegRS4222Receive
@ kRegRS4222Receive
Definition: ntv2publicinterface.h:368
rewindCommand
static UByte rewindCommand[]
Definition: ntv2serialcontrol.cpp:20
CNTV2SerialControl::AdvanceFrame
virtual ULWord AdvanceFrame(void)
Definition: ntv2serialcontrol.cpp:118
CNTV2SerialControl::WriteTxBuffer
virtual bool WriteTxBuffer(const UByte *txBuffer, UWord length)
Definition: ntv2serialcontrol.cpp:344
CNTV2SerialControl::_controlRegisterNum
RegisterNum _controlRegisterNum
Which UART control register to use: kRegRS422Control (72) or kRegRS4222Control (246)
Definition: ntv2serialcontrol.h:70
CNTV2SerialControl::CNTV2SerialControl
CNTV2SerialControl(const UWord inDeviceIndex=0, const UWord inSerialPortIndexNum=0)
Definition: ntv2serialcontrol.cpp:26
SerialMachineResponse
Definition: ntv2serialcontrol.h:18
CNTV2DeviceScanner::GetDeviceAtIndex
static bool GetDeviceAtIndex(const ULWord inDeviceIndexNumber, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device having the given zero-bas...
Definition: ntv2devicescanner.cpp:274
UByte
uint8_t UByte
Definition: ajatypes.h:250
kRegMaskRS422Flush
@ kRegMaskRS422Flush
Definition: ntv2publicinterface.h:1419
CNTV2SerialControl::_transmitRegisterNum
RegisterNum _transmitRegisterNum
Which UART transmit data register to use: kRegRS422Transmit (70) or kRegRS4222Transmit (244)
Definition: ntv2serialcontrol.h:72
CNTV2SerialControl::WaitForRxInterrupt
virtual bool WaitForRxInterrupt(void)
Definition: ntv2serialcontrol.cpp:384
CNTV2SerialControl::WaitForTxInterrupt
virtual bool WaitForTxInterrupt(void)
Definition: ntv2serialcontrol.cpp:393
reversePlayCommand
static UByte reversePlayCommand[]
Definition: ntv2serialcontrol.cpp:21
CNTV2DriverInterface::GetDeviceID
virtual NTV2DeviceID GetDeviceID(void)
Definition: ntv2driverinterface.cpp:407
CNTV2SerialControl::_ntv2Card
CNTV2Card _ntv2Card
Definition: ntv2serialcontrol.h:68
kRegRS422Transmit
@ kRegRS422Transmit
Definition: ntv2publicinterface.h:173
CNTV2SerialControl::Rewind
virtual ULWord Rewind(void)
Definition: ntv2serialcontrol.cpp:111
SerialMachineResponse::length
UByte length
Definition: ntv2serialcontrol.h:20
CNTV2SerialControl::GotoFrameByHMS
virtual ULWord GotoFrameByHMS(UByte inHrs, UByte inMins, UByte inSecs, UByte inFrames)
Definition: ntv2serialcontrol.cpp:229
CNTV2Card::DisableInterrupt
virtual bool DisableInterrupt(const INTERRUPT_ENUMS inEventCode)
Definition: ntv2interrupts.cpp:33
CNTV2MacDriverInterface::WriteRegister
virtual bool WriteRegister(const ULWord inRegNum, const ULWord inValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Updates or replaces all or part of the 32-bit contents of a specific register (real or virtual) on th...
Definition: ntv2macdriverinterface.cpp:430
CNTV2SerialControl::_receiveRegisterNum
RegisterNum _receiveRegisterNum
Which UART receive data register to use: kRegRS422Receive (71) or kRegRS4222Receive (245)
Definition: ntv2serialcontrol.h:71
CNTV2DriverInterface::Close
virtual bool Close(void)
Closes me, releasing host resources that may have been allocated in a previous Open call.
Definition: ntv2driverinterface.cpp:227
CNTV2SerialControl::BackFrame
virtual ULWord BackFrame(void)
Definition: ntv2serialcontrol.cpp:154