MX Foundation 4
irigb_1pps.cs
/*****************************************************************************
//
// File:
// irigb_1pps.cs
//
// Copyright (c) MAX Technologies Inc. 1988-2019, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This example demonstrates how to generate the 1PPS signal, to be used
// with IRIG-B generator, with a discrete output pin.
//
// Hardware requirements:
// - MAXT Flex.
//
*****************************************************************************/
//#define LOCAL
using System;
using static MAXT.MXFoundation.mxf;
using System.Runtime.InteropServices;
using System.Text;
namespace irigb_example
{
class irigb_1pps
{
static void Main(string[] args)
{
UInt32 rc;
UInt64 server = 0;
UInt64 device = 0;
var module = new UInt64[1];
var txChannel = new UInt64[1];
UInt64 txBuffer = 0;
IntPtr recPtr = IntPtr.Zero;
UInt64 moduleCount = 0;
UInt64 channelCount = 0;
UInt64 txBufferSize = 0;
IntPtr txHostBuffer = IntPtr.Zero;
UInt64 irigbStatus = 0;
UInt64 timer = 0;
// Connects to services and initialize environment
# if LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", 0, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", 0, out server);
//rc = mxfServerConnect("10.10.10.140", "admin", "admin", 0, out server);
#endif
if (rc != MAXT_SUCCESS)
{
Console.Write("Failed to connect; rc=0{0:X8}", rc);
Console.ReadKey();
return;
}
// Initializes MX Foundation library
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting ...\n");
rc = mxfSystemInit(server);
}
// Gets the device handle
if (rc == MAXT_SUCCESS)
rc = mxfSystemDeviceGet(server, 0, out device);
// Gets handle of first discrete module
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_DIOFIFO_EH, 1, out moduleCount, module);
// Gets handle of first discrete output channel
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelAllGet(module[0], MXF_CLASS_DISCRETE, MXF_SCLASS_TX_CHANNEL, 1, out channelCount, txChannel);
// If channel not found, return an error
if (rc == MAXT_SUCCESS && channelCount == 0)
rc = MAXT_ERROR_NOT_FOUND;
// Allocate buffer for tx data
if (rc == MAXT_SUCCESS)
{
txBufferSize = (UInt64)Marshal.SizeOf(typeof(MXF_DISCRETE_DATAREC));
// Allocates TX Aperiodic static buffer for HIGH priority queue
rc = mxfTxAperiodicBufferAlloc(txChannel[0], MXF_TXAPERIODIC_PRIORITY_HIGH, txBufferSize, out txBuffer, IntPtr.Zero);
// Host buffer allocation
if (rc == MAXT_SUCCESS)
{
try
{
txHostBuffer = Marshal.AllocHGlobal((int)txBufferSize);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
}
// Configure IRIG-B
// Set IRIG-B time to current time
if (rc == MAXT_SUCCESS)
{
UInt64 bcd;
var time = DateTime.UtcNow.AddYears(-1970); //Time ellapsed since 1 jan 1970 (UTC)
rc = mxfDeviceIrigbBcdCompose((UInt64)time.Year, (UInt64)time.Day, (UInt64)time.Hour, (UInt64)time.Minute, (UInt64)time.Second, out bcd);
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_GEN_BCD_TIME, bcd);
}
// Enable IRIG-B generator
if (rc == MAXT_SUCCESS)
{
Console.Write("Configuring IRIG-B\n");
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_GEN_ENABLE, VMXF_ENABLE);
}
// Enable IRIG-B internal loopback
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_GEN_LOOPBACK_ENABLE, VMXF_ENABLE);
// Set IRIG-B input to device input
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_INPUT, VMXF_DEVICE_IRIGB_INPUT_DEVICE);
// Set IRIG-B signal to digital
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_INPUT_SIGNAL, VMXF_DEVICE_IRIGB_INPUT_SIGNAL_DIGITAL);
// Wait IRIG-B signal locked
if (rc == MAXT_SUCCESS)
{
do
{
rc = mxfDeviceIrigbStatusGet(device, out irigbStatus);
} while (rc == MAXT_SUCCESS && (irigbStatus != MXF_IRIGB_STATUS_NO_SIGNAL) && (irigbStatus != MXF_IRIGB_STATUS_LOCKED));
}
// Set timebase to IRIG-B nsec
if (rc == MAXT_SUCCESS)
{
if (irigbStatus == MXF_IRIGB_STATUS_LOCKED)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_IRIGB_NSEC);
else
{
Console.Write("No IRIG-B signal found\n\r");
rc = MAXT_ERROR_IRIGB_NO_SIGNAL;
}
}
if (rc == MAXT_SUCCESS)
{
// Prepares 1PPS
recPtr = txHostBuffer;
rec.timeTag = 0;
rec.control = MXF_DISCRETE_TX_REC_CTRL_PULSE_START;
rec.repeatCount = 0;
rec.data = 0x0001; // 1PPS will be on pin #0 High
rec.edge = 0x0001;
rec.highDuration = 500000; // 5 msec Hi
rec.lowDuration = 99500000; // 995 msec Low
rc = mxfDeviceTimerGet(device, out timer);
}
if (rc == MAXT_SUCCESS)
{
// Prepare start time
timer /= 1 * 1000 * 1000 * 1000; // Round time to second
timer *= 1 * 1000 * 1000 * 1000;
timer += 2 * 1000 * 1000 * 1000; // Add 2 seconds to be in the future
Console.Write("Starting 1PPS ...\n");
Marshal.StructureToPtr(rec, recPtr, true);
rc = mxfDiscreteTxAperiodicWrite(txBuffer, MXF_TXAPERIODIC_FLAG_ABSOLUTE_START_TIME, timer, 1, txHostBuffer);
}
// Run for 10 seconds
if (rc == MAXT_SUCCESS)
{
mxfSleep(10000);
}
// Stop 1PPS
if (rc == MAXT_SUCCESS)
{
recPtr = txHostBuffer;
// Prepares record
recPtr = txHostBuffer;
rec.timeTag = 0;
rec.control = 0;
rec.repeatCount = 1;
rec.data = 0x0000;
rec.edge = 0x0001;
rec.highDuration = 0;
rec.lowDuration = 0;
Marshal.StructureToPtr(rec, recPtr, true);
rc = mxfDiscreteTxAperiodicWrite(txBuffer, MXF_TXAPERIODIC_FLAG_DEFAULT, 0, 1, txHostBuffer);
}
// Frees device and host buffers
if (txBuffer > 0)
if (txHostBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(txHostBuffer);
if (rc != MAXT_SUCCESS)
{
StringBuilder errorString = new StringBuilder(256);
rc = mxfSystemErrorStringGet(server, rc, (UInt32)errorString.Length, errorString);
Console.WriteLine("ERROR # 0x{0:X} {1}", rc, errorString + "\n\r");
}
Console.Write("Terminating ...\n");
// Unloads MX Foundation library
// Disconnects from MX Foundation library
Console.Write("\nPress a key to terminate\n");
Console.ReadKey();
return;
}
}
}
Updated 10/23/2023