IRIG Timecode (RG) Family Guide

Overview

The RG family is NAI’s line of IRIG timecode modules. IRIG (Inter-Range Instrumentation Group) is a family of time-distribution standards — a way to encode time-of-day into a single electrical signal so that every subsystem in a platform agrees on what time it is. It was created for instrumented test ranges and is now everywhere precise, shared time matters: avionics, defense systems, power-grid synchronization, telemetry, and data acquisition where samples from many sources have to be correlated on one timeline.

The RG1 is both an IRIG receiver and a generator. As a receiver it locks onto an incoming IRIG signal and hands the host SBC precise time (year/day/hour/minute/second down to sub-millisecond) in a memory register. As a generator it produces its own IRIG output — driven either by a decoded reference, by its on-board real-time clock (RTC), or by a free-running counter — so it can act as the master time source for downstream equipment. It supports IRIG Formats A, B, and G in DCLS, AM/ASK, and DC-Manchester modulation, plus a 1 PPS output, an event-capture input that timestamps external edges against the IRIG timebase, and a 10 MHz clock output.

That makes the RG1 a time-synchronization building block: the piece that either disciplines your system’s clock to an external time reference or becomes the reference other equipment locks to. It moves time, not messages — for raw pulse/clock timing and edge-timestamping (1 PPS to 10 MHz, no time-of-day encoding) see the PT family of pulse timers.

The RG family currently has a single member, the RG1, so this guide is specific to it — there are no format or channel-count variants to choose between.

This page is the starting point for the RG1 — understand what it does, wire a signal onto it, confirm it responds, and run your first generate-and-receive tests.

RG1 at a glance

The RG1 is a single-channel IRIG module — one timecode interface that both receives and generates. In software every call still takes a channel argument (use channel 1); naibrd_IRIG_GetChannelCount() reports how many the module has.

CapabilityWhat the RG1 provides
IRIG formatsFormat A (1000 pps), Format B (100 pps), Format G (10,000 pps) — selectable; higher pps = finer resolution.
ModulationDCLS (DC level shift), AM/ASK (data on a sine carrier, 100 Hz–1 MHz), and DC Manchester.
ReceiverDecodes an incoming IRIG reference into precise time (year/day/hr/min/sec, milliseconds, sub-milliseconds in 8.33 ns steps, seconds-since-midnight); tracks errored-frame count and sync status.
GeneratorDrives an IRIG output from one of three time sources — decoded IRIG, on-board RTC, or free-running — with programmable control-function bits and AM output gain.
Signal pathsSeparate digital IRIG in/out (IRIG_DI_*, RS-232 or RS-485 levels) and analog IRIG in/out (IRIG_AN_*, for AM/ASK). Plus 1PPS out, event-capture in, and a 10 MHz clock output.
Real-time clockOn-board RTC as a stable master-time reference; preserved across power loss when a keep-alive source is wired to BKUP_PWR (1.8–5.5 V).
OtherDaylight-saving-time auto-adjust, time-zone and per-format propagation-delay offsets, drift-threshold monitoring, periodic/event interrupts, background BIT.
Form factor6U VPX and 3U VPX.

Note

RG1 is the only IRIG module in the NAI catalog, and no combination module carries the IRIG function — there’s no combo-module variant to consider. If an additional IRIG member ever ships, it will use the same naibrd_IRIG_* API shown here.

View the RG1 data sheet · RG1 Manual

Physical setup

The RG1 isn’t wired onto a shared bus — it has a set of input pins (the IRIG reference and the event signal you want to receive) and a set of output pins (the IRIG signal, 1 PPS, and 10 MHz it drives out). The wiring pattern is the same as any NAI function module:

  1. Identify the RG1’s slot number on your NAI motherboard or system.
  2. Bring the signals out through the breakout board, where the slot’s pins appear as generic IO# (DATAIO) numbers.
  3. Map IO# pins to the RG1’s signals using the pin-out in the RG1 Manual appendix (or the module’s overlay card).
  4. Connect your IRIG source to the appropriate input and your downstream equipment to whichever outputs you’ve enabled.

The key thing to understand for the RG1 is that there are two physical signal paths, and which one you wire depends on the modulation you select in software:

  • Digital IRIG pathIRIG_DI_IN (p/n) and IRIG_DI_OUT (p/n). Carries the DCLS and DC-Manchester (level-based) waveforms. Selectable RS-232 (single-ended, connect the p signal, with ISO_GND as the DCLS signal return) or RS-485 (differential, connect both p and n).
  • Analog IRIG pathIRIG_AN_IN / IRIG_AN_IRET (input + return) and IRIG_AN_OUT / IRIG_AN_ORET (output + return). Carries the AM/ASK waveform — the time code amplitude-modulated onto a sine carrier. Each is a single-ended signal referenced to its own return.

Pick the path that matches your modulation: DCLS or Manchester → the digital pins; AM/ASK → the analog pins. The remaining signals are independent of that choice:

  • 1PPS_OUT — a once-per-second marker pulse that fires at the top of each second, for synchronizing other equipment to the RG1’s timebase. Programmable pulse width; RS-232/RS-485 level selectable.
  • EVENT_IN — an external event input. A signal edge here is timestamped against the IRIG timebase (rising or falling edge, selectable), so you can correlate an external trigger to precise time. Shares its RS-232/RS-485 level setting with the 1 PPS output.
  • 10_MHZ_OUT (p/n) — a 10 MHz differential clock output.
  • BKUP_PWR — RTC keep-alive input. Wire a 1.8–5.5 V standby source here if you want the on-board RTC to hold time across a power cycle (see the RTC reference in Features).
  • ISO_GND — isolated ground; also the signal return for the digital IRIG input in RS-232 mode.

A few things to keep in mind for wiring:

  • The RS-232 vs RS-485 choice is electrical, and it’s set in software. For a receiver/transmitter to decode a signal, both ends must agree on the level standard. The digital input level, the digital output level, and the 1 PPS-out/event-in level are configured separately (see Software and Features) — set each to match the equipment on the other end.
  • Termination is selectable. The RG1 can enable on-board termination for the analog input and for the digital input — match it to your source/cable rather than leaving an impedance mismatch on a long run.
  • Confirm pin numbers against the pin-out for your revision. The pin-out is given with respect to DATAIO; the exact module-slot pins depend on your motherboard, so use the RG1 Manual appendix and your motherboard manual rather than hard-coding pin numbers.

Software

There’s nothing RG-specific about which software stack you run. The NAI SSK (naibrd library) is identical across every OS and architecture — PetaLinux, VxWorks, DEOS, Windows — and which one you’re on is set by your motherboard/SBC, not by the RG1. The only RG-specific part is which API functions you call: the RG1 is driven by the naibrd_IRIG_* family of calls (header naibrd_irig.h).

Note

The naibrd_IRIG_* API is the same in SSK 1.x and 2.x — identical function names and signatures — so the calls below work on either version. The one difference is a type rename on the interrupt trigger-type calls: SSK 1.x uses naibrd_irig_interrupt_trigger_type_t, SSK 2.x uses naibrd_int_trigger_type_t (the enum values — edge/level — are the same). The version toggles throughout this guide show both sides so the difference is visible at a glance.

The RG1 API is stateless — there’s no Open/Init/Free lifecycle to manage. Every call takes (cardIndex, module, channel) and acts immediately, so once you’ve connected to the board you can configure, read, or generate in any order. A typical session is just: select the time reference, set the IRIG protocol, then read time (as a receiver) or set time + enable output (as a generator).

Two operations are two-step commits rather than single writes, and it’s worth knowing up front (both are detailed in Features):

  • Setting the RTC stages the time and date into holding registers, then commits them to the clock hardware with a separate call that waits for a hardware-ready bit.
  • Loading free-running time writes the time/date registers and “launches” them so the value takes effect — naibrd_IRIG_SetFreeRunningTimeAndDate() does both in one call. The launch only takes hold while the module isn’t already locked to a valid reference (IRIG or RTC).

Where to find what you need:

  • Which functions/registers to call — the RG1 Manual documents every register (measurement, protocol, reference source, free-running, RTC, DST, capture event, signal levels, status, interrupt) and is the reference behind the naibrd_IRIG_* calls.
  • Building and deploying on your platformConnecting to Boards covers the toolchain, deployment, and terminal access for PetaLinux/ARM Linux, VxWorks, DEOS, and Windows.
  • Launching the app on the board itselfRunning Applications from the Target walks through loading and launching your executable on the target.

Confirm communication

Before wiring any external IRIG source, you can prove the whole path — your board connection, the SSK, and the module — with no wiring at all, because the RG1 can be its own time source. Then, once that passes, a simple cable loopback confirms the receiver and decoder too.

Step 1 — free-running self-test (no wiring)

Put the module in free-running mode, load a known time, and read it back. With nothing connected, the RG1 has no external reference, so its free-running counter becomes the master time:

  1. Set the reference source to 7 (free-running / no reference): naibrd_IRIG_SetReferenceSource(cardIndex, module, channel, 7u).
  2. Load a known time and date with naibrd_IRIG_SetFreeRunningTimeAndDate() (this call also “launches” the value — see Software).
  3. Read the master time back a couple of times with naibrd_IRIG_GetMasterTime().

If the master time reflects what you loaded and advances between reads, the board link, the SSK, and the module are all confirmed. (The free-running launch only takes hold when the module isn’t locked to a valid reference, which is exactly the no-signal case here — naibrd_IRIG_GetActualReferenceSource() will read a value greater than 4, meaning “no valid reference / coasting”.)

Step 2 — IRIG loopback (one cable)

To prove the receiver and decoder end-to-end, loop the module’s IRIG output back to its input and have it sync to itself:

  1. Wire the module’s IRIG output to its IRIG input on the matching path — IRIG_DI_OUTIRIG_DI_IN for a DCLS/Manchester (digital) test, or IRIG_AN_OUTIRIG_AN_IN for an AM/ASK (analog) test (see Physical setup). Make sure both ends use the same protocol and the same RS-232/RS-485 level.
  2. With the generator still running (free-running master time from Step 1, a protocol selected), set the reference source to 0 (IRIG) so the module tries to lock to the signal arriving on its input.
  3. Read the status: naibrd_IRIG_GetEventMappedStatusRaw() (or the per-event naibrd_IRIG_GetEventMappedStatus()) should show Receiving IRIG Reference set and IRIG Reference Loss clear.
  4. Read the decoded time with naibrd_IRIG_GetActualIRIGDateAndTime() — it should track the master time you’re generating, and the errored-frame count should stay put.

The RG BasicOps sample drives all of this interactively: it connects to the board, lets you set the protocol, reference source, and free-running/RTC time, and continuously displays the protocol, reference source, IRIG time, and master time for the channel — so you can watch the lock happen.

Features

Everything below acts on a channel you pass to each naibrd_IRIG_* call (the RG1 has one IRIG channel — use channel 1; naibrd_IRIG_GetChannelCount() reports the count). Every function starts from the standard connection flow (naiapp_RunBoardMenu()naiapp_query_CardIndex() / naiapp_query_ModuleNumber()cardIndex / module / channel; see Opening a Software Handle to Your Board).

The features group into the two halves of what the RG1 does — reading time (as a receiver) and producing time (as a generator) — plus the supporting configuration, event capture, and health monitoring. Full register detail for every call is in the RG1 Manual; worked call sequences are in Try it.

Note

The naibrd_IRIG_* signatures are the same in SSK 1.x and 2.x for every block below except interrupts, where the trigger-type parameter was renamed. The version toggles still show both sides; pick your version with the SSK selector and you’ll see the calls that apply to you.

Read the time

What it does / when: the core receiver operation — read the module’s authoritative master time (what it’s generating/serving), or the actual IRIG time decoded from an incoming reference, both as year/day/hour/minute/second down to sub-millisecond. The decoded read also returns an errored-frame count so you can gauge incoming signal quality.

Relevant APIs:

/* SSK 1.x */
int32_t      naibrd_IRIG_GetChannelCount(uint32_t modId);
nai_status_t naibrd_IRIG_GetMasterTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t *p_outIrigInfoStruct);
nai_status_t naibrd_IRIG_GetActualIRIGDateAndTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t *p_outIrigInfoStruct, uint32_t *p_outErroredFrameCount);
nai_status_t naibrd_IRIG_ClearErroredFrameCount(int32_t cardIndex, int32_t module, int32_t channel);
/* SSK 2.x */
int32_t      naibrd_IRIG_GetChannelCount(uint32_t modId);
nai_status_t naibrd_IRIG_GetMasterTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t *p_outIrigInfoStruct);
nai_status_t naibrd_IRIG_GetActualIRIGDateAndTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t *p_outIrigInfoStruct, uint32_t *p_outErroredFrameCount);
nai_status_t naibrd_IRIG_ClearErroredFrameCount(int32_t cardIndex, int32_t module, int32_t channel);
  • Reading the master time’s hours/minutes/seconds register freezes the companion time/date registers until the next read, so a single read gives you a coherent snapshot.
  • naibrd_irig_master_timer_info_t carries year / day / hour / minute / second / microSecond fields.

Exercise it: RG BasicOps (the configuration display reads master time, IRIG time, and reference source every cycle).

Set the IRIG protocol

What it does / when: selects how time is encoded on the wire — format (A/B/G), modulation (DCLS, AM/ASK, DC-Manchester), carrier frequency, and which fields appear in each frame (code expression). Set this first on both a generator and a receiver; both ends must use the same protocol to decode. Set the four parameters together with SetProtocol/SetProtocolByValue, or change one at a time with SetFormat / SetModulation.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_SetProtocol(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_protocol_t irigProtocol);
nai_status_t naibrd_IRIG_SetProtocolByValue(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_protocol_value_t irigProtoValue);
nai_status_t naibrd_IRIG_SetFormat(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_format_t irigFormat);
nai_status_t naibrd_IRIG_SetModulation(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_modulation_t irigModulation);
nai_status_t naibrd_IRIG_SetYear(int32_t cardIndex, int32_t module, int32_t channel, int32_t year);
/* SSK 2.x */
nai_status_t naibrd_IRIG_SetProtocol(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_protocol_t irigProtocol);
nai_status_t naibrd_IRIG_SetProtocolByValue(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_protocol_value_t irigProtoValue);
nai_status_t naibrd_IRIG_SetFormat(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_format_t irigFormat);
nai_status_t naibrd_IRIG_SetModulation(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_modulation_t irigModulation);
nai_status_t naibrd_IRIG_SetYear(int32_t cardIndex, int32_t module, int32_t channel, int32_t year);
  • FormatNAIBRD_IRIG_CTRL_MODE_IRIG_FORMAT_A (1), …_FORMAT_B (2), …_FORMAT_G (7).
  • ModulationNAIBRD_IRIG_CTRL_MODE_IRIG_MODULATION_DCLS, …_AM_ASK, …_DC_MANCHESTER.
  • Not every format/modulation/carrier/code combination is valid; an unsupported one returns NAI_ERROR_INVALID_VALUE. The header’s validIRIGProtocols[] table lists accepted values for SetProtocolByValue (e.g. 0x2120 = Format B, AM/ASK, 1 kHz carrier, BCDTOY/CF/SBS).
  • SetYear supplies the calendar year for formats whose code expression omits the BCD-year field.

Exercise it: RG BasicOps (PR / PRV commands).

Select the time reference

What it does / when: chooses where the master time comes from — an incoming IRIG reference, the on-board RTC, or the free-running counter. This is the switch between “discipline my clock to an external source” and “be the source.” Setting RTC and free-running time also lives here.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_SetReferenceSource(int32_t cardIndex, int32_t module, int32_t channel, uint32_t refSource);
nai_status_t naibrd_IRIG_GetActualReferenceSource(int32_t cardIndex, int32_t module, int32_t channel,
   uint32_t *p_outRefSource);
nai_status_t naibrd_IRIG_SetFreeRunningTimeAndDate(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t IRIGTimerInfoStruct);
nai_status_t naibrd_IRIG_SetRTCTime(int32_t cardIndex, int32_t module, int32_t channel, naibrd_irig_rtc_time_t rtcTimeStruct);
nai_status_t naibrd_IRIG_SetRTCDate(int32_t cardIndex, int32_t module, int32_t channel, naibrd_irig_rtc_date_t rtcDateStruct);
nai_status_t naibrd_IRIG_SetRTC(int32_t cardIndex, int32_t module, int32_t channel);
/* SSK 2.x */
nai_status_t naibrd_IRIG_SetReferenceSource(int32_t cardIndex, int32_t module, int32_t channel, uint32_t refSource);
nai_status_t naibrd_IRIG_GetActualReferenceSource(int32_t cardIndex, int32_t module, int32_t channel,
   uint32_t *p_outRefSource);
nai_status_t naibrd_IRIG_SetFreeRunningTimeAndDate(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_master_timer_info_t IRIGTimerInfoStruct);
nai_status_t naibrd_IRIG_SetRTCTime(int32_t cardIndex, int32_t module, int32_t channel, naibrd_irig_rtc_time_t rtcTimeStruct);
nai_status_t naibrd_IRIG_SetRTCDate(int32_t cardIndex, int32_t module, int32_t channel, naibrd_irig_rtc_date_t rtcDateStruct);
nai_status_t naibrd_IRIG_SetRTC(int32_t cardIndex, int32_t module, int32_t channel);
  • Reference source values: 0 = IRIG (lock to the incoming reference), 3 = RTC (drive master time from the on-board clock), 7 = free-running / no reference. GetActualReferenceSource() reports what the module is actually using (it also signals “coasting” when it’s losing sync).
  • RTC is a two-step commit: stage with SetRTCTime() / SetRTCDate(), then commit with SetRTC(), which waits for a hardware-ready bit and returns NAI_ERROR_TIMEOUT if it isn’t ready (the sample retries up to five times). Wire a standby source to BKUP_PWR to keep the RTC across power cycles.
  • Free-running time is loaded (and launched) by SetFreeRunningTimeAndDate(); it only takes hold when the module isn’t locked to a valid reference (see Confirm communication).

Exercise it: RG BasicOps (RS / FRT / RTCT / RTCC commands).

Adjust the clock — DST, time zone, and offsets

What it does / when: the corrections layered on top of the raw timebase — automatic daylight-saving transitions, a time-zone offset, per-format propagation-delay offsets (to compensate for long cable runs), and a drift threshold that flags when the clock wanders from its reference.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_GetDSTStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_status_type_t* p_outstatus);
nai_status_t naibrd_IRIG_SetDSTOffset(int32_t cardIndex, int32_t module, int32_t channel, uint32_t dstOffset);
nai_status_t naibrd_IRIG_SetDSTStart(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_timer_info_t irigDSTInfoStruct);
nai_status_t naibrd_IRIG_SetDSTEnd(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_timer_info_t irigDSTInfoStruct);
nai_status_t naibrd_IRIG_SetTimeZoneOffset(int32_t cardIndex, int32_t module, int32_t channel, int32_t timeZoneOffset);
nai_status_t naibrd_IRIG_SetModeBPropOffset(int32_t cardIndex, int32_t module, int32_t channel, int32_t propOffset);
nai_status_t naibrd_IRIG_SetDriftThreshold(int32_t cardIndex, int32_t module, int32_t channel, uint32_t driftThreshold);
/* SSK 2.x */
nai_status_t naibrd_IRIG_GetDSTStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_status_type_t* p_outstatus);
nai_status_t naibrd_IRIG_SetDSTOffset(int32_t cardIndex, int32_t module, int32_t channel, uint32_t dstOffset);
nai_status_t naibrd_IRIG_SetDSTStart(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_timer_info_t irigDSTInfoStruct);
nai_status_t naibrd_IRIG_SetDSTEnd(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_dst_timer_info_t irigDSTInfoStruct);
nai_status_t naibrd_IRIG_SetTimeZoneOffset(int32_t cardIndex, int32_t module, int32_t channel, int32_t timeZoneOffset);
nai_status_t naibrd_IRIG_SetModeBPropOffset(int32_t cardIndex, int32_t module, int32_t channel, int32_t propOffset);
nai_status_t naibrd_IRIG_SetDriftThreshold(int32_t cardIndex, int32_t module, int32_t channel, uint32_t driftThreshold);
  • DST needs both a start and an end rule (naibrd_irig_dst_timer_info_t = month / week / day-of-week / hour / minute); the offset is HMM-encoded in hex (0x100 = 1 hour). GetDSTStatus() returns NAIBRD_IRIG_DST_STATUS_ENABLED / …_DISABLED.
  • Propagation offset is per format — there are separate SetModeAPropOffset / SetModeBPropOffset / SetModeGPropOffset / SetDclsPropOffset / SetRTCPropOffset calls; set the one matching the format you’re running. Range is roughly ±1.2 s in nanoseconds.
  • Time-zone offset is in minutes (−1439…+1439); there’s a separate SetRTCTimeZoneOffset for the RTC path.

Exercise it: RG BasicOps (DST menu, plus TZO / O / D commands).

Generate and condition the output signal

What it does / when: the generator’s signal-shaping controls — AM output gain (amplitude of the AM/ASK signal), 1 PPS pulse width, the RS-232/RS-485 level of the digital input, digital output, and 1PPS-out/event-in pins, on-board input termination, and the control-function bits carried alongside the time in each frame.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_SetAMOutputGain(int32_t cardIndex, int32_t module, int32_t channel, uint8_t level);
nai_status_t naibrd_IRIG_Set1PPSPulseWidth(int32_t cardIndex, int32_t module, int32_t channel, uint32_t pulseWidthUSec);
nai_status_t naibrd_IRIG_SetDigitalInput(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_signal_level_t signalLevel);
nai_status_t naibrd_IRIG_SetDigitalLevel(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_signal_type_t signalType, naibrd_irig_signal_level_t signalLevel);
nai_status_t naibrd_IRIG_SetInputAnalogTermEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_IRIG_SetInputDigitalTermEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_IRIG_SetCtrlBitsToSend(int32_t cardIndex, int32_t module, int32_t channel, uint32_t ctrlbits);
nai_status_t naibrd_IRIG_GetCtrlBitsReceived(int32_t cardIndex, int32_t module, int32_t channel, uint32_t *p_outctrlbits);
/* SSK 2.x */
nai_status_t naibrd_IRIG_SetAMOutputGain(int32_t cardIndex, int32_t module, int32_t channel, uint8_t level);
nai_status_t naibrd_IRIG_Set1PPSPulseWidth(int32_t cardIndex, int32_t module, int32_t channel, uint32_t pulseWidthUSec);
nai_status_t naibrd_IRIG_SetDigitalInput(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_signal_level_t signalLevel);
nai_status_t naibrd_IRIG_SetDigitalLevel(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_signal_type_t signalType, naibrd_irig_signal_level_t signalLevel);
nai_status_t naibrd_IRIG_SetInputAnalogTermEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_IRIG_SetInputDigitalTermEnable(int32_t cardIndex, int32_t module, int32_t channel, bool_t enable);
nai_status_t naibrd_IRIG_SetCtrlBitsToSend(int32_t cardIndex, int32_t module, int32_t channel, uint32_t ctrlbits);
nai_status_t naibrd_IRIG_GetCtrlBitsReceived(int32_t cardIndex, int32_t module, int32_t channel, uint32_t *p_outctrlbits);
  • AM gain is 0–255 and only affects AM/ASK modulation (no effect on DCLS or Manchester).
  • Signal level is NAIBRD_IRIG_SIGNAL_LEVEL_RS232 / …_RS485. SetDigitalInput sets the input level; SetDigitalLevel sets the level for a chosen pin — NAIBRD_IRIG_SIGNAL_DIGITAL_OUT or NAIBRD_IRIG_SIGNAL_1PPS_OUT_EVENT_IN.
  • Control bits carry up to 27 bits (0–26) of application data in the frame’s control-function field; the receiver reads them with GetCtrlBitsReceived(). They only appear if the protocol’s code expression includes the CF field.

Exercise it: RG BasicOps (G / PW / DI / DO / SSL / CB / CBR commands).

Capture external events

What it does / when: timestamps an external event — a signal edge on the EVENT_IN pin — against the IRIG timebase, so you can correlate a hardware trigger to precise time (hours down to sub-millisecond). Choose which edge fires the capture, then read back the captured time and the current input state.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_SetCaptureEventEdge(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_edge_type_t captureEventEdge);
nai_status_t naibrd_IRIG_SetCaptureEventTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_time_t captureEventTimeStruct);
nai_status_t naibrd_IRIG_GetCaptureEventTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_time_t* p_outcaptureEventTimeStruct);
nai_status_t naibrd_IRIG_GetCaptureEventInputState(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_input_state_type_t* p_outcaptureEventInputState);
/* SSK 2.x */
nai_status_t naibrd_IRIG_SetCaptureEventEdge(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_edge_type_t captureEventEdge);
nai_status_t naibrd_IRIG_SetCaptureEventTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_time_t captureEventTimeStruct);
nai_status_t naibrd_IRIG_GetCaptureEventTime(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_time_t* p_outcaptureEventTimeStruct);
nai_status_t naibrd_IRIG_GetCaptureEventInputState(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_capture_event_input_state_type_t* p_outcaptureEventInputState);
  • Edge is NAIBRD_IRIG_CAPTURE_EVENT_RISING_EDGE / …_FALLING_EDGE.
  • The captured time (naibrd_irig_capture_event_time_t = hours / minutes / seconds / tenths / hundredths) can also be read in milliseconds and sub-millisecond fraction via GetCaptureEventTimeMSec() / GetCaptureEventTimeFraction().
  • The matching Event Detected status bit (and its interrupt) fires on each capture — see below.

Exercise it: RG BasicOps (CET / CEE commands).

Health, BIT, and status monitoring

What it does / when: the RG1 continuously tracks IRIG-specific events and runs background BIT. Read them on demand, or enable interrupts so the host is notified the instant something changes — reference lost/acquired, a reference pulse, 1 PPS, control-bit changes, an event capture, a DST adjust, or a BIT fault. Status is grouped into two categories, BIT and General, each with latched and realtime variants.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_IRIG_GetEventMappedStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t statusType, nai_status_bit_t* p_outstatus);
nai_status_t naibrd_IRIG_GetEventMappedStatusRaw(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, nai_status_access_type_t accessType, uint32_t *p_outStatus);
nai_status_t naibrd_IRIG_ClearEventMappedStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t statusType);
nai_status_t naibrd_IRIG_SetEventMappedInterruptEnable(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t type, bool_t enable);
nai_status_t naibrd_IRIG_SetEventMappedInterruptTriggerType(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t type, naibrd_irig_interrupt_trigger_type_t triggerType);
nai_status_t naibrd_IRIG_SetEventMappedInterruptVector(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, uint32_t vector);
nai_status_t naibrd_IRIG_SetEventMappedInterruptSteering(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, naibrd_int_steering_t steering);
/* SSK 2.x */
nai_status_t naibrd_IRIG_GetEventMappedStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t statusType, nai_status_bit_t* p_outstatus);
nai_status_t naibrd_IRIG_GetEventMappedStatusRaw(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, nai_status_access_type_t accessType, uint32_t *p_outStatus);
nai_status_t naibrd_IRIG_ClearEventMappedStatus(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t statusType);
nai_status_t naibrd_IRIG_SetEventMappedInterruptEnable(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t type, bool_t enable);
nai_status_t naibrd_IRIG_SetEventMappedInterruptTriggerType(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_status_type_t type, naibrd_int_trigger_type_t triggerType);
nai_status_t naibrd_IRIG_SetEventMappedInterruptVector(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, uint32_t vector);
nai_status_t naibrd_IRIG_SetEventMappedInterruptSteering(int32_t cardIndex, int32_t module, int32_t channel,
   naibrd_irig_event_mapped_category_type_t type, naibrd_int_steering_t steering);
  • The one 1.x→2.x difference in the whole API: the interrupt trigger-type parameter is naibrd_irig_interrupt_trigger_type_t in 1.x (values NAIBRD_IRIG_EDGE_INTERRUPT / NAIBRD_IRIG_LEVEL_INTERRUPT) and the common naibrd_int_trigger_type_t in 2.x. The edge/level meaning is unchanged.
  • Category is NAIBRD_IRIG_EVTMAP_CATEGORY_BIT or …_GENERAL; status types come in …_LATCHED / …_REALTIME pairs (e.g. NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED). Realtime reflects the current condition; latched stays set until cleared with ClearEventMappedStatus().
  • An interrupt needs all three configured: enable for the event, a vector for its category, and steering to your processor (naibrd_int_steering_t — VME, on-board, PCIe, CPCI).

Exercise it: RG BasicOps (INT menu) and RG Interrupts for a full interrupt-handling example.

Try it

The snippets below show the order of naibrd_IRIG_* calls for the three things you’ll do most — generate an IRIG output, lock onto an incoming reference, and timestamp an event. Drop them into the body of an NAI sample app (after the standard connection flow in Software) and you have a working test. Each is the conceptual sequence, not a fully-buildable program; RG BasicOps is the full reference.

Try it — generate an IRIG-B AM output

Set the protocol, make the module its own time source (free-running), load a time, and set the output amplitude. The module then emits IRIG-B on the analog output (IRIG_AN_OUT).

/* SSK 1.x */
/* 1. Protocol: Format B, AM/ASK on a 1 kHz carrier, BCDTOY/CF/SBS */
naibrd_irig_protocol_t protocol;
protocol.irigFormat     = NAIBRD_IRIG_CTRL_MODE_IRIG_FORMAT_B;
protocol.irigModulation = NAIBRD_IRIG_CTRL_MODE_IRIG_MODULATION_AM_ASK;
protocol.carrierFreq    = NAIBRD_IRIG_MODE_CARRIER_FREQUENCY_1KHZ;
protocol.codeExpression = NAIBRD_IRIG_CTRL_MODE_CODE_EXP_BCDTOY_CF_SBS;
naibrd_IRIG_SetProtocol(cardIndex, module, channel, protocol);
 
/* 2. Be the time source: free-running, then load a known time */
naibrd_IRIG_SetReferenceSource(cardIndex, module, channel, 7u);
 
naibrd_irig_master_timer_info_t t = {0};
t.year = 26; t.day = 169; t.hour = 14; t.minute = 30; t.second = 0; t.microSecond = 0;
naibrd_IRIG_SetFreeRunningTimeAndDate(cardIndex, module, channel, t);   /* loads + launches */
 
/* 3. Shape the AM output */
naibrd_IRIG_SetAMOutputGain(cardIndex, module, channel, 200);  /* 0-255 */
naibrd_IRIG_Set1PPSPulseWidth(cardIndex, module, channel, 1000u);  /* microseconds */
/* SSK 2.x */
/* 1. Protocol: Format B, AM/ASK on a 1 kHz carrier, BCDTOY/CF/SBS */
naibrd_irig_protocol_t protocol;
protocol.irigFormat     = NAIBRD_IRIG_CTRL_MODE_IRIG_FORMAT_B;
protocol.irigModulation = NAIBRD_IRIG_CTRL_MODE_IRIG_MODULATION_AM_ASK;
protocol.carrierFreq    = NAIBRD_IRIG_MODE_CARRIER_FREQUENCY_1KHZ;
protocol.codeExpression = NAIBRD_IRIG_CTRL_MODE_CODE_EXP_BCDTOY_CF_SBS;
naibrd_IRIG_SetProtocol(cardIndex, module, channel, protocol);
 
/* 2. Be the time source: free-running, then load a known time */
naibrd_IRIG_SetReferenceSource(cardIndex, module, channel, 7u);
 
naibrd_irig_master_timer_info_t t = {0};
t.year = 26; t.day = 169; t.hour = 14; t.minute = 30; t.second = 0; t.microSecond = 0;
naibrd_IRIG_SetFreeRunningTimeAndDate(cardIndex, module, channel, t);   /* loads + launches */
 
/* 3. Shape the AM output */
naibrd_IRIG_SetAMOutputGain(cardIndex, module, channel, 200);  /* 0-255 */
naibrd_IRIG_Set1PPSPulseWidth(cardIndex, module, channel, 1000u);  /* microseconds */

Try it — lock onto an incoming reference and read it

Match the incoming signal’s protocol, point the master timer at the IRIG input, then poll until the module reports it’s receiving, and read the decoded time.

/* SSK 1.x */
/* Match the source's protocol and input level (here: digital RS-485 input) */
naibrd_IRIG_SetDigitalInput(cardIndex, module, channel, NAIBRD_IRIG_SIGNAL_LEVEL_RS485);
naibrd_IRIG_SetReferenceSource(cardIndex, module, channel, 0u);   /* 0 = IRIG */
 
/* Poll the realtime "receiving reference" status until it sets */
nai_status_bit_t rxRef = 0;
do {
   naibrd_IRIG_GetEventMappedStatus(cardIndex, module, channel,
      NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_REALTIME, &rxRef);
} while (rxRef == 0);
 
/* Read the decoded IRIG time and the errored-frame count */
naibrd_irig_master_timer_info_t irigTime;
uint32_t erroredFrames = 0u;
naibrd_IRIG_GetActualIRIGDateAndTime(cardIndex, module, channel, &irigTime, &erroredFrames);
/* SSK 2.x */
/* Match the source's protocol and input level (here: digital RS-485 input) */
naibrd_IRIG_SetDigitalInput(cardIndex, module, channel, NAIBRD_IRIG_SIGNAL_LEVEL_RS485);
naibrd_IRIG_SetReferenceSource(cardIndex, module, channel, 0u);   /* 0 = IRIG */
 
/* Poll the realtime "receiving reference" status until it sets */
nai_status_bit_t rxRef = 0;
do {
   naibrd_IRIG_GetEventMappedStatus(cardIndex, module, channel,
      NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_REALTIME, &rxRef);
} while (rxRef == 0);
 
/* Read the decoded IRIG time and the errored-frame count */
naibrd_irig_master_timer_info_t irigTime;
uint32_t erroredFrames = 0u;
naibrd_IRIG_GetActualIRIGDateAndTime(cardIndex, module, channel, &irigTime, &erroredFrames);

Try it — timestamp an external event

Pick the edge to capture on EVENT_IN, then read the captured time after the event fires (poll the Event Detected status, or enable its interrupt as in Health, BIT, and status).

/* SSK 1.x */
naibrd_IRIG_SetCaptureEventEdge(cardIndex, module, channel,
   NAIBRD_IRIG_CAPTURE_EVENT_RISING_EDGE);
 
/* Wait for the capture (poll the realtime Event Detected status) */
nai_status_bit_t evt = 0;
do {
   naibrd_IRIG_GetEventMappedStatus(cardIndex, module, channel,
      NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_REALTIME, &evt);
} while (evt == 0);
 
/* Read the timestamp captured against the IRIG timebase */
naibrd_irig_capture_event_time_t evtTime;
naibrd_IRIG_GetCaptureEventTime(cardIndex, module, channel, &evtTime);
/* SSK 2.x */
naibrd_IRIG_SetCaptureEventEdge(cardIndex, module, channel,
   NAIBRD_IRIG_CAPTURE_EVENT_RISING_EDGE);
 
/* Wait for the capture (poll the realtime Event Detected status) */
nai_status_bit_t evt = 0;
do {
   naibrd_IRIG_GetEventMappedStatus(cardIndex, module, channel,
      NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_REALTIME, &evt);
} while (evt == 0);
 
/* Read the timestamp captured against the IRIG timebase */
naibrd_irig_capture_event_time_t evtTime;
naibrd_IRIG_GetCaptureEventTime(cardIndex, module, channel, &evtTime);

Building and running the SSK samples. The snippets above are condensed for orientation. For full, buildable programs see RG BasicOps and RG Interrupts, and Using NAI SSK 2.x Sample Applications for build/run instructions across platforms.

Hardware capabilities and status monitoring

This section covers what the hardware provides and what you can monitor — for how to drive each function, see Features and Try it above.

Timebase. A continuously running master timer provides precise time as year / day / hour / minute / second, milliseconds, sub-milliseconds (in 8.33 ns steps), and seconds-since-midnight. It can be driven from a decoded IRIG reference, the on-board RTC, or a free-running counter, and it coasts (holds and flags deviation) if a locked reference is lost rather than jumping.

Receiver and generator. The module decodes incoming IRIG-A/B/G in DCLS, AM/ASK, or DC-Manchester, tracking an errored-frame count for signal quality, and generates the same formats on its digital and analog outputs with programmable AM gain, 1 PPS pulse width, and per-frame control bits.

Real-time clock. An on-board RTC provides a stable, drift-resistant master-time reference that offloads the host from updating the timer; with a keep-alive source on BKUP_PWR (1.8–5.5 V) it preserves time across power loss.

Event capture. A signal edge on EVENT_IN is timestamped against the IRIG timebase with sub-millisecond resolution, for correlating external triggers to precise time.

Background BIT. Automatic background built-in test runs transparently and flags a software-fault condition in the BIT status without interrupting normal operation.

Statuses you can monitor programmatically (each event has Dynamic/realtime, Latched, Interrupt Enable, and Set Edge/Level Interrupt variants, read via naibrd_IRIG_GetEventMappedStatus() / …Raw()):

CategoryWhat it tells you
BITSoftware fault — the background-BIT health indicator.
General — syncIRIG reference loss, receiving IRIG reference, and IRIG reference pulse received — the core lock/quality indicators for a receiver.
General — timing events1 PPS output went high, change in reference source, event detected (an EVENT_IN capture), and did a DST adjust.
General — control bitsControl bits received and received control bits changed — for the per-frame control-function field.
General — user/testProgrammable-duration user interrupt and test interrupt (software-settable, useful for verifying the interrupt path).

Latched status bits are write-1-to-clear — clear them with naibrd_IRIG_ClearEventMappedStatus() (one event) or …ClearEventMappedStatusRaw() (a whole category). The module-common registers (revisions, serial number, temperature/voltage/current monitoring) are also available per the RG1 Manual.

Common pitfalls

  • Protocol mismatch between ends. A receiver only decodes a signal whose format, modulation, carrier, and code expression match what it’s configured for. After changing the generator’s protocol, update the receiver to match (and vice versa).
  • Wrong signal path for the modulation. DCLS/Manchester use the digital pins (IRIG_DI_*); AM/ASK uses the analog pins (IRIG_AN_*). Wiring AM/ASK to the digital input (or DCLS to the analog input) won’t decode.
  • RS-232 vs RS-485 level mismatch. The digital input, digital output, and 1PPS-out/event-in levels are set independently; if either end expects a different standard the signal won’t be read. Match them.
  • Free-running time “not taking.” SetFreeRunningTimeAndDate() only loads to the master timer when the module isn’t locked to a valid reference (Actual Reference Source > 4). If it’s currently synced to IRIG or RTC, switch the reference source to 7 first.
  • RTC set returns NAI_ERROR_TIMEOUT. SetRTC() waits for a hardware-ready bit; if it isn’t ready the commit times out. Stage the time/date first, then retry the commit (the sample retries up to five times).
  • Propagation offset applied to the wrong format. Each format has its own offset register — setting the Mode A offset has no effect while you’re running Format B. Use the call matching your active format.
  • AM gain with no visible effect. Gain only shapes the AM/ASK output; it does nothing under DCLS or DC-Manchester modulation.
  • Control bits read as zero. The control-function field is only present when the protocol’s code expression includes CF (e.g. …CODE_EXP_BCDTOY_CF_SBS), and only if the transmitter is loading them.
  • Latched status stays set. Latched bits don’t auto-clear when the condition resolves — clear them explicitly. A “reference loss” latched at startup is normal before a source is connected.
  • Year reads zero. Formats whose code expression omits BCD-year encode only day-of-year; call SetYear() to supply the calendar year for those protocols.