Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

TTL PWM

TTL PWM Sample Application (SSK 1.x)

Overview

The TTL PWM sample application demonstrates how to configure and generate Pulse Width Modulation (PWM) output on TTL (Transistor-Transistor Logic) channels using the NAI Software Support Kit (SSK 1.x). PWM is a technique for encoding information or controlling power delivery by switching a digital output between high and low logic states at a programmable rate. By adjusting how long the output stays high versus low within each cycle, you control the effective energy delivered to a load — this is the basis for motor speed control, LED dimming, servo positioning, and digital signal synthesis from TTL-level hardware.

Three parameters define a PWM signal:

  • Period — the total time for one complete on/off cycle, specified in milliseconds. The reciprocal of the period is the PWM frequency. A 1 ms period produces a 1 kHz signal; a 10 ms period produces 100 Hz. Your choice of period depends on the load: motor drivers typically need 1-20 kHz to avoid audible switching noise, while servo control signals use 50 Hz (20 ms period).

  • Pulse width (duty cycle) — the time the output is held in its active state within each period, also specified in milliseconds. The ratio of pulse width to period is the duty cycle. A 0.5 ms pulse width in a 1 ms period gives a 50% duty cycle — the output spends equal time high and low. A 0.1 ms pulse width in the same period gives 10% duty cycle and delivers less average power. The pulse width must always be less than or equal to the period.

  • Polarity — determines whether the active pulse is a positive-going (high) or negative-going (low) excursion from the idle state. With positive polarity, the output idles low and pulses high for the pulse width duration. With negative polarity, the output idles high and pulses low. Polarity selection depends on whether your load is active-high or active-low.

The TTL module supports two PWM operating modes:

  • Continuous mode — the channel outputs the PWM waveform indefinitely once triggered, running until explicitly stopped. Use this for steady-state applications such as motor speed control or LED brightness regulation.

  • Burst mode — the channel outputs a specific number of PWM cycles (the burst count) and then stops automatically. Use this for precise pulse generation such as stepper motor stepping, timed stimulus injection, or protocol signaling where you need an exact number of pulses. Burst mode is supported on TL2, TL4, TL6, and TL8 modules — consult your module’s manual for availability on other TTL module types.

An important difference between TTL PWM and other discrete PWM samples: TTL channels require you to explicitly set the I/O format to output mode before enabling PWM, and PWM triggering uses the enhanced trigger enable API (naibrd_TTL_SetEnhanceTriggerEnable()) rather than a dedicated start/stop call.

This sample supports the following TTL module types: D7, TL1, TL2, TL3, TL4, TL5, TL6, TL7, and TL8. For basic TTL channel configuration (I/O format, output state, input state, debounce time), see the TTL BasicOps guide. Consult your module’s manual for hardware-specific PWM timing limits and register details.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a TTL module installed (D7, TL1-TL8).

  • SSK 1.x installed on your development host.

  • The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.

How to Run

Launch the TTL_PWM executable from your build output directory. On startup the application looks for a configuration file (default_TTL_PWM.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, you select a channel and use the command menu to configure PWM parameters and trigger output.

Board Connection and Module Selection

Note
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to TTL. For details on board connection configuration, see the First Time Setup Guide.

The main() function follows a standard SSK 1.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_TTL_PWM.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleID() so downstream code can adapt to the specific TTL variant installed.

#if defined (__VXWORKS__)
int32_t TTL_PWM(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_TTL_PWM(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
                  inputBuffer, &inputResponseCnt);
      }
   }

   naiapp_access_CloseAllOpenCards();
   return 0;
}

After board connection, Run_TTL_PWM() validates that the selected module is a recognized TTL type by calling naibrd_TTL_GetChannelCount(). If the channel count is zero, the module is not a TTL module and the sample prints an error.

MaxChannel = naibrd_TTL_GetChannelCount(ModuleID);

if (MaxChannel == 0)
{
   printf(" *** Module selection not recognized as TTL module. ***\n\n");
}
else
{
   Cfg_TTL_PWM_Channel(cardIndex, module, ModuleID, MaxChannel);
}
Important

Common Connection Errors

  • No board found — verify the board is powered on and the connection interface (Ethernet, PCIe, etc.) is properly configured.

  • Connection timeout — check network settings, IP address, and that no firewall is blocking communication.

  • Invalid card/module index — card indices are 0-based; module indices are 1-based. Verify the module is physically installed in the expected slot.

  • Module not present — naibrd_TTL_GetChannelCount() returns 0 if the module ID does not match any known TTL type.

Program Structure

Application Parameters

The sample tracks connection and channel context in a naiapp_AppParameters_t struct that is passed to each command handler:

naiapp_AppParameters_t  ttl_params;
p_naiapp_AppParameters_t ttl_pwm_params = &ttl_params;
ttl_pwm_params->cardIndex = cardIndex;
ttl_pwm_params->module = module;

In your own application, you will track equivalent values — card index, module number, module ID, and channel number — however is appropriate for your architecture.

Command Menu

After selecting a channel, the sample presents a command menu. The menu system is a sample convenience — in your own code, call these API functions directly. The available commands are:

Command Description

Mode

Select PWM mode (Continuous, Burst, or Standard Input/Output)

Period

Set PWM period in milliseconds

Width

Set PWM pulse width in milliseconds

Count

Set burst count (number of pulses in burst mode)

POlarity

Set PWM polarity (positive or negative)

PM

Display current PWM configuration settings

Trigger

Start PWM output on the selected channel

Halt

Stop PWM output on the selected channel

Demo

Configure all channels with incrementing period/width/burst values

Reset

Reset all channels to initial (input) configuration

Stat

Display channel status (BIT, overcurrent, transitions)

SETBurst

Set all channels to burst mode

SETCont

Set all channels to continuous mode

PWM Mode Selection

Before generating PWM output, you must set the channel’s operating mode and I/O format. Unlike other discrete module types, TTL channels require two configuration steps: setting the I/O format to output and setting the enhanced operating mode.

To set a channel to continuous PWM mode in your own application, call naibrd_TTL_SetIOFormat() to configure the channel as an output, then call naibrd_TTL_SetOpMode() with NAI_TTL_MODE_OUTPUT_PWM_FOREVER:

/* Continuous PWM -- set I/O to output, then set PWM continuous mode */
check_status(naibrd_TTL_SetIOFormat(cardIndex, module, chan, NAI_TTL_IOFORMAT_OUTPUT));
check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_OUTPUT_PWM_FOREVER));

To set burst mode, use NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES instead:

/* Burst PWM -- set I/O to output, then set PWM burst mode */
check_status(naibrd_TTL_SetIOFormat(cardIndex, module, chan, NAI_TTL_IOFORMAT_OUTPUT));
check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES));

To return the channel to normal TTL input operation, use NAI_TTL_MODE_STD_INPUT_OUTPUT. Note that this does not require setting the I/O format separately — the mode change returns the channel to standard behavior:

/* Standard input/output mode -- no PWM, normal TTL behavior */
check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_STD_INPUT_OUTPUT));
Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — the selected mode is not supported on this module type. Verify that your module supports PWM output.

  • Channel not outputting after mode set — setting the mode alone does not start the output. You must also enable the enhanced trigger (see Starting and Stopping PWM Output below).

  • I/O format not set to output — TTL channels default to input mode. You must call naibrd_TTL_SetIOFormat() with NAI_TTL_IOFORMAT_OUTPUT before enabling PWM output. Without this step, the channel will not drive the output pin.

PWM Timing Configuration

Setting the Period

The PWM period determines how long each complete cycle takes. To set the period on a channel, call naibrd_TTL_SetPWM_Period() with the desired value in milliseconds:

float64_t time = 1.0; /* 1 ms period = 1 kHz frequency */
check_status(naibrd_TTL_SetPWM_Period(cardIndex, module, chan, time));

The valid range depends on the module type and its timebase LSB (least significant bit resolution). The sample retrieves the LSB with naibrd_TTL_GetTimebaseLSB() to compute the range dynamically:

lsb = naibrd_TTL_GetTimebaseLSB(ModuleID);
switch (ModuleID)
{
case NAI_MODULE_ID_TL2:
case NAI_MODULE_ID_TL4:
case NAI_MODULE_ID_TL6:
case NAI_MODULE_ID_TL8:
   min = (float64_t)(0x2u * lsb);
   max = (float64_t)(0xFFFFFFFF * lsb);
default:
   break;
}

The TL2, TL4, TL6, and TL8 modules use a 32-bit period register, providing a wide timing range. Consult your module’s manual for the exact timebase LSB value and resulting timing limits for other TTL module types (D7, TL1, TL3, TL5, TL7).

Setting the Pulse Width

The pulse width determines how long the output stays in its active state during each period. The duty cycle is the ratio of pulse width to period — for example, a 0.3 ms pulse width with a 1 ms period gives a 30% duty cycle.

To set the pulse width, call naibrd_TTL_SetPWM_Pulsewidth() with the value in milliseconds:

float64_t time = 0.5; /* 0.5 ms pulse width */
check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, chan, time));

The pulse width must be less than or equal to the period. The valid range follows the same module-dependent pattern as the period. On TL2/TL4/TL6/TL8, the minimum pulse width is one LSB and the maximum is 0xFFFFFFFE * LSB:

lsb = naibrd_TTL_GetTimebaseLSB(ModuleID);
switch (ModuleID)
{
case NAI_MODULE_ID_TL2:
case NAI_MODULE_ID_TL4:
case NAI_MODULE_ID_TL6:
case NAI_MODULE_ID_TL8:
   min = (float64_t)(0x1u * lsb);
   max = (float64_t)(0xFFFFFFFE * lsb);
   break;
default:
   break;
}
Important

Common Errors

  • Entry out of range — the sample validates that period and pulse width values fall within the module’s supported range. If your value exceeds the register capacity or is below the minimum LSB, the API may silently clip the value or return an error.

  • Pulse width exceeds period — the hardware will not produce a valid waveform if the pulse width is greater than the period. Always set the period first, then set the pulse width to a value less than or equal to the period.

  • Unexpected frequency — the period register has a finite LSB resolution. The actual period written to hardware is quantized to the nearest LSB. For precise frequencies, compute the closest achievable period using naibrd_TTL_GetTimebaseLSB().

Burst Count

In burst mode, the channel outputs a specific number of PWM cycles and then stops automatically. To configure the burst count, call naibrd_TTL_SetPWM_BurstNum():

uint32_t burstcount = 10; /* Output exactly 10 PWM cycles */
check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, chan, burstcount));

The minimum burst count is 1. The sample enforces this:

if (burstcount < 1)
{
   burstcount = 1;
   printf("Setting burstcount to minimum of 1.\n");
}

Burst count configuration is supported on TL2, TL4, TL6, and TL8 modules. On other module types, the sample prints "Unsupported function for this module." If you attempt to set a burst count on an unsupported module, the call will have no effect on the output behavior.

Burst mode is useful for applications that require a precise number of output pulses — for example, stepping a motor a known number of steps, generating a timed stimulus pulse train, or producing a fixed-length protocol preamble.

Important

Common Errors

  • Unsupported function for this module — burst mode is only available on TL2, TL4, TL6, and TL8. Other TTL module types may support only continuous PWM output.

  • Burst output does not start — you must set the mode to NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES, set I/O format to output, and then enable the enhanced trigger to start the burst.

  • Burst count of zero — the minimum count is 1. A zero value may produce undefined behavior on some modules.

Polarity

PWM polarity determines the direction of the active pulse relative to the idle state. With positive polarity, the output idles low and the pulse drives high. With negative polarity, the output idles high and the pulse drives low.

To set the polarity, call naibrd_TTL_SetPWM_Polarity():

/* Positive polarity: idle low, pulse high */
check_status(naibrd_TTL_SetPWM_Polarity(cardIndex, module, chan,
   (nai_ttl_pwm_polarity_t)NAI_TTL_PWMPOLARITY_POS));

/* Negative polarity: idle high, pulse low */
check_status(naibrd_TTL_SetPWM_Polarity(cardIndex, module, chan,
   (nai_ttl_pwm_polarity_t)NAI_TTL_PWMPOLARITY_NEG));

Choose polarity based on your load’s requirements. If your load is active-high (it activates when the signal goes high), use positive polarity. If your load is active-low (it activates when the signal is pulled low), use negative polarity. The polarity setting does not affect the period or pulse width — it only inverts the waveform.

Starting and Stopping PWM Output

After configuring the mode, I/O format, period, pulse width, polarity, and (optionally) burst count, you start the PWM output by enabling the enhanced trigger. Unlike other discrete module types that use dedicated StartPWM() / StopPWM() calls, the TTL module uses naibrd_TTL_SetEnhanceTriggerEnable():

/* Start PWM output */
check_status(naibrd_TTL_SetEnhanceTriggerEnable(cardIndex, module, chan,
   NAI_TTL_OUTPUT_ENHANCED_OP_ENABLE));

In continuous mode, the output runs indefinitely until you stop it. In burst mode, the output runs for the configured number of cycles and then stops automatically. To stop a running PWM output at any time, disable the enhanced trigger:

/* Stop PWM output */
check_status(naibrd_TTL_SetEnhanceTriggerEnable(cardIndex, module, chan,
   NAI_TTL_ENHANCED_OP_DISABLE));
Important

Common Errors

  • PWM does not start — verify that the I/O format is set to output (NAI_TTL_IOFORMAT_OUTPUT), the operating mode is set to a PWM mode, and the enhanced trigger is enabled. All three steps are required.

  • Using wrong start API — the TTL module does not use naibrd_TTL_StartPWM(). Instead, use naibrd_TTL_SetEnhanceTriggerEnable() with NAI_TTL_OUTPUT_ENHANCED_OP_ENABLE to trigger the PWM output.

Displaying PWM Configuration

To read back the current PWM settings for a channel, use the Get variants of the configuration API calls:

float64_t period, pulsewidth;
uint32_t burstnumber;
nai_ttl_pwm_polarity_t polaritysetting;

check_status(naibrd_TTL_GetPWM_Period(cardIndex, module, chan, &period));
check_status(naibrd_TTL_GetPWM_Pulsewidth(cardIndex, module, chan, &pulsewidth));
check_status(naibrd_TTL_GetPWM_BurstNum(cardIndex, module, chan, &burstnumber));
check_status(naibrd_TTL_GetPWM_Polarity(cardIndex, module, chan, &polaritysetting));

The period and pulse width are returned in milliseconds. The polarity is returned as NAI_TTL_PWMPOLARITY_POS (0) or NAI_TTL_PWMPOLARITY_NEG (1). Use these readback calls to verify your configuration before starting output, especially when validating that the pulse width does not exceed the period.

Channel Status Display

The sample provides a status display that reads several latched status registers for the selected channel. This information is useful for verifying that the channel is operating correctly and for diagnosing problems:

nai_status_bit_t status;

check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_BIT_LATCHED, &status));
check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_OVERCURRENT_LATCHED, &status));
check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &status));
check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &status));

The status registers include:

  • BIT — built-in test status. If this shows a fault, the channel’s output driver may have detected a mismatch between the commanded and actual output state.

  • Overcurrent (OC) — the output has exceeded the current limit. If this is set, the channel may have been automatically disabled. Consult your module’s manual for overcurrent recovery procedures.

  • Lo-Hi / Hi-Lo Transition — latched edge transition flags. When PWM output is active, you should see these toggling as the output switches between high and low states.

Channel Configuration Display

The sample also displays the current I/O format, output state, input state, and enhanced mode selection for the selected channel before each command prompt. This readback uses:

uint32_t ioformat;
nai_ttl_state_t outputstate, inputstate;
nai_ttl_enhanced_mode_t opmode;

check_status(naibrd_TTL_GetIOFormat(cardIndex, module, chan, &ioformat));
check_status(naibrd_TTL_GetOutputState(cardIndex, module, chan, &outputstate));
check_status(naibrd_TTL_GetInputState(cardIndex, module, chan, &inputstate));
check_status(naibrd_TTL_GetOpMode(cardIndex, module, chan, &opmode));

The I/O format reports whether the channel is configured as input (NAI_TTL_IOFORMAT_INPUT) or output (NAI_TTL_GEN3_IOFORMAT_OUTPUT / NAI_TTL_GEN5_IOFORMAT_OUTPUT depending on the module generation). The output state reports NAI_TTL_STATE_LO or NAI_TTL_STATE_HI. The operating mode reflects the enhanced mode setting (standard I/O, continuous PWM, burst PWM, or other enhanced modes). Verify that the I/O format shows output mode before attempting to start PWM.

Batch Operations

The sample provides several batch commands that configure all channels at once. These are useful for quickly setting up a multi-channel test scenario.

Demo Configuration

The Demo command configures all channels with incrementing period and pulse width values. Channel 1 gets a 1 ms period with 0.1 ms pulse width, channel 2 gets 2 ms with 0.2 ms, and so on. Burst counts are set to match the channel number.

for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
{
   time = ch_loop;
   status |= check_status(naibrd_TTL_SetPWM_Period(cardIndex, module, ch_loop, time));
   time /= 10.0;
   status |= check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, ch_loop, time));
   status |= check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, ch_loop, ch_loop));
}

Reset to Initial Configuration

The Reset command returns all channels to their initial state: output state low, I/O format set to input, default pulse width (16 microseconds), burst count of 0, standard input/output mode, and zero debounce time.

for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
{
   status |= check_status(naibrd_TTL_SetOutputState(cardIndex, module, ch_loop, NAI_TTL_STATE_LO));
   status |= check_status(naibrd_TTL_SetIOFormat(cardIndex, module, ch_loop, NAI_TTL_IOFORMAT_INPUT));
   status |= check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, ch_loop, 16E-6));
   status |= check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, ch_loop, 0));
   status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop, NAI_TTL_MODE_STD_INPUT_OUTPUT));
   status |= check_status(naibrd_TTL_SetDebounceTime(cardIndex, module, ch_loop, 0.0));
}

Set All Burst / Set All Continuous

The SETBurst and SETCont commands set all channels to burst or continuous PWM mode respectively, which is convenient for quickly switching an entire module’s operating mode during testing.

/* Set all channels to burst mode */
for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
{
   status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop,
      NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES));
}

/* Set all channels to continuous mode */
for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
{
   status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop,
      NAI_TTL_MODE_OUTPUT_PWM_FOREVER));
}

Troubleshooting Reference

Note
This section summarizes errors covered in the preceding sections. Consult your module’s manual for hardware-specific diagnostics, timing limits, and overcurrent recovery procedures.
Error / Symptom Possible Causes Suggested Resolution

No board found

Board is powered off, connection interface not configured, wrong IP address.

Verify power, cabling, and network configuration. Check the board’s IP address matches your connection settings.

Module not recognized as TTL

Selected module slot does not contain a TTL module, or the module ID is not in the recognized list.

Verify the module is physically installed and select the correct slot index.

NAI_ERROR_NOT_SUPPORTED

The requested operation (burst mode, specific enhanced mode) is not supported on this module type.

Check module compatibility. Burst mode requires TL2, TL4, TL6, or TL8.

Entry out of range (period / pulse width)

The requested value exceeds the module’s register capacity or is below the minimum LSB.

Use naibrd_TTL_GetTimebaseLSB() to compute the valid range for your module type.

PWM output does not start

I/O format not set to output, mode not set to a PWM mode, or enhanced trigger not enabled.

Set I/O format to output, set the mode to Continuous or Burst, configure timing parameters, then enable the enhanced trigger with naibrd_TTL_SetEnhanceTriggerEnable().

No output signal observed

Channel I/O format may still be set to input, or output driver is disabled due to overcurrent.

Verify the I/O format is set to output (not input). Check overcurrent status and reset if needed.

Burst mode unsupported

Attempting burst count or burst mode on a module type that does not support it.

Use continuous mode, or switch to a TL2/TL4/TL6/TL8 module for burst capability.

Overcurrent fault

Output load exceeds the channel’s current limit, causing the hardware to disable the output driver.

Reduce the load, check for short circuits, and issue an overcurrent reset per the module manual.

Using wrong start/stop API

Calling naibrd_TTL_StartPWM() instead of naibrd_TTL_SetEnhanceTriggerEnable().

TTL PWM uses the enhanced trigger enable API. Call naibrd_TTL_SetEnhanceTriggerEnable() with NAI_TTL_OUTPUT_ENHANCED_OP_ENABLE to start and NAI_TTL_ENHANCED_OP_DISABLE to stop.

Full Source

Full Source — TTL_PWM.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ttl.h"
#include "advanced/nai_ether_adv.h"

static const int8_t *CONFIG_FILE = (int8_t *)"default_TTL_PWM.txt";

/* Function prototypes */
static void Run_TTL_PWM(int32_t cardIndex, int32_t module, int32_t ModuleID);
static void Cfg_TTL_PWM_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
static void Display_TTL_PWM_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
static nai_status_t Display_TTL_PWM_Configuration(int32_t paramCount, int32_t* p_params);
static nai_status_t Display_TTL_Status(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_TTL_PWM_Mode(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_TTL_PWM_Period(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_TTL_PWM_Pulsewidth(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_TTL_PWM_Burstcount(int32_t paramCount, int32_t* p_params);
static nai_status_t Configure_TTL_PWM_Polarity(int32_t paramCount, int32_t* p_params);

static const int32_t DEF_TTL_CHANNEL = 1;
/****** Command Table *******/
enum ttl_pwm_commands
{
   TTL_PWM_CMD_MODE,
   TTL_PWM_CMD_PERIOD,
   TTL_PWM_CMD_PULSEWIDTH,
   TTL_PWM_CMD_BURSTCOUNT,
   TTL_PWM_CMD_POLARITY,
   TTL_PWM_CMD_PWM_CFG,
   TTL_PWM_CMD_PWM_START,
   TTL_PWM_CMD_PWM_STOP,
   TTL_PWM_CMD_PWM_DEMO,
   TTL_PWM_CMD_PWM_INITIAL,
   TTL_PWM_CMD_STATUS,
   TTL_PWM_CMD_PWM_BURST,
   TTL_PWM_CMD_PWM_CONT,
   TTL_PWM_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t TTL_PWM_MenuCmds[] = {
   {"Mode",       "    TTL Select PWM Mode",                         TTL_PWM_CMD_MODE,          Configure_TTL_PWM_Mode},
   {"Period",     "    TTL Set PWM Period",                          TTL_PWM_CMD_PERIOD,        Configure_TTL_PWM_Period},
   {"Width",      "    TTL Set PWM Pulsewidth",                      TTL_PWM_CMD_PULSEWIDTH,    Configure_TTL_PWM_Pulsewidth},
   {"Count",      "    TTL Set PWM burst count",                     TTL_PWM_CMD_BURSTCOUNT,    Configure_TTL_PWM_Burstcount},
   {"POlarity",   "    TTL Set PWM Polarity",                        TTL_PWM_CMD_POLARITY,      Configure_TTL_PWM_Polarity},
   {"PM",         "    TTL Display PWM configuration settings",      TTL_PWM_CMD_PWM_CFG,       Display_TTL_PWM_Configuration},
   {"Trigger",    "    TTL Start PWM output",                        TTL_PWM_CMD_PWM_START,     NULL},
   {"Halt",       "    TTL Stop PWM output",                         TTL_PWM_CMD_PWM_STOP,      NULL},
   {"Demo",       "    TTL Demo PWM Settings",                       TTL_PWM_CMD_PWM_DEMO,      NULL},
   {"Reset",      "    TTL Reset All Channels to Initial Settings",  TTL_PWM_CMD_PWM_INITIAL,   NULL},
   {"Stat",       "    TTL Display Status",                          TTL_PWM_CMD_STATUS,        Display_TTL_Status},
   {"SETBurst",   "    TTL Set all channels to PWM Burst",           TTL_PWM_CMD_PWM_BURST,     NULL},
   {"SETCont",    "    TTL Set all channels to PWM Continuous",      TTL_PWM_CMD_PWM_CONT,      NULL},
};

/**************************************************************************************************************/
/**
<summary>
The purpose of the TTL_PWM is to illustrate the methods to call in the naibrd library to perform configuration
 setup for output in PWM operation mode.  Pulse period, pulse width, pulse polarity settings are configurable.

The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd TTL routines.
 - ClearDeviceCfg
 - QuerySystemCfg
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t TTL_PWM(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_TTL_PWM(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
<summary>
Run_TTL_PWM prompts the user for the card, module and channel to use for the application and calls
Cfg_TTL_PWM_Channel if the card, module, channel is valid for as a discrete module.
</summary>
*/
/**************************************************************************************************************/
void Run_TTL_PWM(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
   int32_t MaxChannel;

   MaxChannel = naibrd_TTL_GetChannelCount(ModuleID);

   if (MaxChannel == 0)
   {
      printf(" *** Module selection not recognized as TTL module. ***\n\n");
   }
   else
   {
      Cfg_TTL_PWM_Channel(cardIndex, module, ModuleID, MaxChannel);
   }
}

/**************************************************************************************************************/
/**
<summary>
Display_TTL_PatternGen_ChannelCfg illustrate the methods to call in the naibrd library to retrieve the configuration states
for basic operation.
</summary>
*/
/**************************************************************************************************************/
void Display_TTL_PWM_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
   uint32_t ioformat = 0;
   nai_ttl_state_t outputstate = 0;
   nai_ttl_state_t inputstate = 0;
   nai_ttl_enhanced_mode_t opmode = 0;

   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
   check_status(naibrd_TTL_GetIOFormat(cardIndex, module, chan, &ioformat));
   check_status(naibrd_TTL_GetOutputState(cardIndex, module, chan, &outputstate));
   check_status(naibrd_TTL_GetInputState(cardIndex, module, chan, &inputstate));
   check_status(naibrd_TTL_GetOpMode(cardIndex, module, chan, &opmode));

   printf("\n === Channel %d ===\n\n", chan);

   /*read PWM configuration values here, Period, Pulsewidth, Continuous/Burst Mode, */
   {
      printf("  I/O       Output    Input                             \n");
      printf(" Format     State     State    Enhanced Mode Selection  \n");
      printf("--------   -------   -------  ------------------------- \n");
   }

   /*display configuration settings here- */
   switch (ioformat)
   {
   case NAI_TTL_IOFORMAT_INPUT:
      printf("  Input   ");
      break;
   case NAI_TTL_GEN3_IOFORMAT_OUTPUT:
   case NAI_TTL_GEN5_IOFORMAT_OUTPUT:
      printf(" High-side"); /*may want add check for proper value depending on whether gen3 or gen5; for now, assume it correctly matches module*/
      break;
   default:
      printf(" Unknown  ");
      break;
   }
   switch (outputstate)
   {
   case NAI_TTL_STATE_LO:
      printf("  LOW     ");
      break;
   case NAI_TTL_STATE_HI:
      printf("  HIGH    ");
      break;
   default:
      printf(" Unknown  ");
      break;
   }

   switch (inputstate)
   {
   case NAI_TTL_STATE_LO:
      printf(" LOW Input  ");
      break;
   case NAI_TTL_STATE_HI:
      printf("HIGH Input  ");
      break;
   default:
      printf("Unknown     ");
      break;
   }
   switch (opmode)
   {
   case NAI_TTL_MODE_STD_INPUT_OUTPUT:
      printf("STD_INPUT_OUTPUT   ");
      break;
   case NAI_TTL_MODE_MEASURE_HIGH_TIME:
      printf("NAI_TTL_MODE_MEASURE_HIGH_TIME   ");
      break;
   case NAI_TTL_MODE_MEASURE_LOW_TIME:
      printf("NAI_TTL_MODE_MEASURE_LOW_TIME   ");
      break;
   case NAI_TTL_MODE_TIMESTAMP_RISING_EDGES:
      printf("NAI_TTL_MODE_TIMESTAMP_RISING_EDGES   ");
      break;
   case NAI_TTL_MODE_TIMESTAMP_FALLING_EDGES:
      printf("NAI_TTL_MODE_TIMESTAMP_FALLING_EDGES   ");
      break;
   case NAI_TTL_MODE_TIMESTAMP_ALL_EDGES:
      printf("NAI_TTL_MODE_TIMESTAMP_ALL_EDGES   ");
      break;
   case NAI_TTL_MODE_COUNT_RISING_EDGES:
      printf("NAI_TTL_MODE_COUNT_RISING_EDGES   ");
      break;
   case NAI_TTL_MODE_COUNT_FALLING_EDGES:
      printf("NAI_TTL_MODE_COUNT_FALLING_EDGES   ");
      break;
   case NAI_TTL_MODE_COUNT_ALL_EDGES:
      printf("NAI_TTL_MODE_COUNT_ALL_EDGES   ");
      break;
   case NAI_TTL_MODE_MEASURE_PERIOD_FROM_RISING_EDGE:
      printf("NAI_TTL_MODE_MEASURE_PERIOD_FROM_RISING_EDGE   ");
      break;
   case NAI_TTL_MODE_MEASURE_FREQUENCY:
      printf("NAI_TTL_MODE_MEASURE_FREQUENCY   ");
      break;
   case NAI_TTL_MODE_OUTPUT_PWM_FOREVER:
      printf("NAI_TTL_MODE_OUTPUT_PWM_FOREVER   ");
      break;
   case NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES:
      printf("NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES   ");
      break;
   case NAI_TTL_MODE_OUTPUT_PATTERN_RAM:
      printf("NAI_TTL_MODE_OUTPUT_PATTERN_RAM   ");
      break;
   default:
      printf("Unknown    ");
      break;
   }

}
/**************************************************************************************************************/
/**
<summary>
Cfg_TTL_PWM_Channel handles calling the Display_TTL_PWM_ChannelCfg routine to display the discrete channel configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
void Cfg_TTL_PWM_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
   nai_status_t status = (nai_status_t)0;
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   int32_t defaultchan = 1;
   int32_t cmd;
   int32_t ch_loop;
   float64_t time;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   naiapp_AppParameters_t  ttl_params;
   p_naiapp_AppParameters_t ttl_pwm_params = &ttl_params;
   ttl_pwm_params->cardIndex = cardIndex;
   ttl_pwm_params->module = module;
   while (bContinue)
   {
      printf("    \r\n\r\n");
      printf("Channel selection \r\n");
      printf("================= \r\n");
      defaultchan = DEF_TTL_CHANNEL;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &ttl_pwm_params->channel);

      naiapp_utils_LoadParamMenuCommands(TTL_PWM_CMD_COUNT, TTL_PWM_MenuCmds);
      while (bContinue)
      {
         Display_TTL_PWM_ChannelCfg(cardIndex, module, ttl_pwm_params->channel, ModuleID);
         naiapp_display_ParamMenuCommands((int8_t *)"TTL PWM Menu");
         printf("\nType TTL command or %c to quit : ", NAI_QUIT_CHAR);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
               if (bCmdFound)
               {
                  switch (cmd)
                  {
                  case TTL_PWM_CMD_MODE:
                  case TTL_PWM_CMD_PERIOD:
                  case TTL_PWM_CMD_PULSEWIDTH:
                  case TTL_PWM_CMD_BURSTCOUNT:
                  case TTL_PWM_CMD_POLARITY:
                  case TTL_PWM_CMD_PWM_CFG:
                  case TTL_PWM_CMD_STATUS:
                     TTL_PWM_MenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)ttl_pwm_params);
                     break;
                  case TTL_PWM_CMD_PWM_START:
                     /* check_status(naibrd_TTL_StartPWM(cardIndex, module, chan)); */
                     check_status(naibrd_TTL_SetEnhanceTriggerEnable(cardIndex, module, ttl_pwm_params->channel, NAI_TTL_OUTPUT_ENHANCED_OP_ENABLE));
                     break;
                  case TTL_PWM_CMD_PWM_STOP:
                     /* check_status(naibrd_TTL_StopPWM(cardIndex, module, chan)); */
                     check_status(naibrd_TTL_SetEnhanceTriggerEnable(cardIndex, module, ttl_pwm_params->channel, NAI_TTL_ENHANCED_OP_DISABLE));
                     break;
                  case TTL_PWM_CMD_PWM_DEMO:
                  {
                     status = NAI_SUCCESS;
                     printf("Set up all channels in incrementing period/pulsewidths and burstcounts? \n Enter Yes to confirm: ");
                     bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                     if (!bQuit)
                     {
                        if (inputResponseCnt > 0)
                        {
                           if ((toupper(inputBuffer[0]) == 'Y'))
                           {
                              for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
                              {
                                 time = ch_loop;
                                 status |= check_status(naibrd_TTL_SetPWM_Period(cardIndex, module, ch_loop, time));
                                 time /= 10.0;
                                 status |= check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, ch_loop, time));
                                 status |= check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, ch_loop, ch_loop));
                              }
                              if (status == NAI_SUCCESS)
                                 printf("\n PWM channel configuration initialized for all channels. \n Set PWM Mode as needed. ");
                              else
                                 printf("\n Configuration not completed successfully. \n");
                           }
                        }
                     }
                  }
                  break;
                  case TTL_PWM_CMD_PWM_INITIAL:
                  {
                     status = NAI_SUCCESS;
                     printf("Reset all channels to initial configuration? \n Enter Yes to confirm: ");
                     bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                     if (!bQuit)
                     {
                        if (inputResponseCnt > 0)
                        {
                           if ((toupper(inputBuffer[0]) == 'Y'))
                           {
                              for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
                              {
                                 status |= check_status(naibrd_TTL_SetOutputState(cardIndex, module, ch_loop, NAI_TTL_STATE_LO));
                                 status |= check_status(naibrd_TTL_SetIOFormat(cardIndex, module, ch_loop, NAI_TTL_IOFORMAT_INPUT));
                                 status |= check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, ch_loop, 16E-6));
                                 status |= check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, ch_loop, 0));
                                 status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop, NAI_TTL_MODE_STD_INPUT_OUTPUT));
                                 status |= check_status(naibrd_TTL_SetDebounceTime(cardIndex, module, ch_loop, 0.0));
                                 status |= check_status(naibrd_TTL_GetDebounceTime(cardIndex, module, ch_loop, &time));
                                 if (time > 1E-10)
                                    status++;
                              }
                              if (status == NAI_SUCCESS)
                                 printf("\n PWM channel configuration initialized for all channels. \n");
                              else
                                 printf("\n Initialization not completed successfully. \n");
                           }
                        }
                     }
                  }
                  break;
                  case TTL_PWM_CMD_PWM_BURST:
                  {
                     printf("Reset all channels to PWM burst mode? \n Enter Yes to confirm: ");
                     bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                     if (!bQuit)
                     {
                        if (inputResponseCnt > 0)
                        {
                           if ((toupper(inputBuffer[0]) == 'Y'))
                           {
                              for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
                              {
                                 status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop, NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES));
                              }
                              if (status == NAI_SUCCESS)
                                 printf("\n PWM channel configuration set for PWM Burst mode for all channels. \n");
                              else
                                 printf("\n Initialization not completed successfully. \n");
                           }
                        }
                     }
                  }
                  break;
                  case TTL_PWM_CMD_PWM_CONT:
                  {
                     printf("Reset all channels to PWM continuous mode? \n Enter Yes to confirm: ");
                     bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                     if (!bQuit)
                     {
                        if (inputResponseCnt > 0)
                        {
                           if ((toupper(inputBuffer[0]) == 'Y'))
                           {
                              for (ch_loop = 1; ch_loop <= MaxChannel; ch_loop++)
                              {
                                 status |= check_status(naibrd_TTL_SetOpMode(cardIndex, module, ch_loop, NAI_TTL_MODE_OUTPUT_PWM_FOREVER));
                              }
                              if (status == NAI_SUCCESS)
                                 printf("\n PWM channel configuration set for PWM Burst mode for all channels. \n");
                              else
                                 printf("\n Initialization not completed successfully. \n");
                           }
                        }
                     }
                  }
                  break;
                  default:
                     printf("Invalid command entered\n");
                     break;
                  }
               }
               else
                  printf("Invalid command entered\n");
            }
         }
         else
            bContinue = FALSE;
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
Configure_TTL_PWM_Mode handles the user request to select the PWM mode for the selected channel
and calls the method in the naibrd library to set the mode.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_TTL_PWM_Mode(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("\n == PWM Mode Selection == \n C  Continuous PWM mode \n Burst  PWM Burst mode \n None  Basic input mode \n\n Type DSW command : ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         if ((toupper(inputBuffer[0]) == 'C'))
         {
            check_status(naibrd_TTL_SetIOFormat(cardIndex, module, chan, NAI_TTL_IOFORMAT_OUTPUT));
            check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_OUTPUT_PWM_FOREVER));
         }
         else if ((toupper(inputBuffer[0]) == 'B'))
         {
            check_status(naibrd_TTL_SetIOFormat(cardIndex, module, chan, NAI_TTL_IOFORMAT_OUTPUT));
            check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_OUTPUT_PWM_CYCLE_NUM_TIMES));
         }
         else if ((toupper(inputBuffer[0]) == 'N'))
         {
            check_status(naibrd_TTL_SetOpMode(cardIndex, module, chan, NAI_TTL_MODE_STD_INPUT_OUTPUT));
         }
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_TTL_PWM_Period handles the user request to configure the time values for period on the selected
channel and calls the method in the naibrd library to set the period.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_TTL_PWM_Period(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   float64_t time = 0.0;
   float64_t lsb = 0;
   float64_t min = 1;
   float64_t max = -1;
   uint32_t ModuleID;
   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("\nEnter the desired period in ms: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
         time = atof((const char *)inputBuffer); /*entry in milliseconds*/
         lsb = naibrd_TTL_GetTimebaseLSB(ModuleID);
         switch (ModuleID)
         {
         case NAI_MODULE_ID_TL2:
         case NAI_MODULE_ID_TL4:
         case NAI_MODULE_ID_TL6:
         case NAI_MODULE_ID_TL8:
            min = (float64_t)(0x2u * lsb);
            max = (float64_t)(0xFFFFFFFF * lsb);
         default:
            break;
         }
         if (time > max || time < min)
            printf(" Entry out of range.  Range %7.3f to %7.3f ms\n", min, max);
         else
         {
            check_status(naibrd_TTL_SetPWM_Period(cardIndex, module, chan, time));
         }
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_TTL_PWM_Pulsewidth handles the user request to configure the time values for pulsewidth on the selected
channel and calls the method in the naibrd library to set the width.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_TTL_PWM_Pulsewidth(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   float64_t time = 0.0;
   float64_t lsb = 0;
   float64_t min = 1;
   float64_t max = -1;
   uint32_t ModuleID;
   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("\nEnter the desired pulsewidth in milliseconds: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
         time = atof((const char *)inputBuffer);
         lsb = naibrd_TTL_GetTimebaseLSB(ModuleID);
         switch (ModuleID)
         {
         case NAI_MODULE_ID_TL2:
         case NAI_MODULE_ID_TL4:
         case NAI_MODULE_ID_TL6:
         case NAI_MODULE_ID_TL8:
            min = (float64_t)(0x1u * lsb);
            max = (float64_t)(0xFFFFFFFE * lsb);
            break;
         default:
            break;
         }
         if (time > max || time < min)
            printf(" Entry out of range.  Range %7.3f to %7.3f ms\n", min, max);
         else
         {
            check_status(naibrd_TTL_SetPWM_Pulsewidth(cardIndex, module, chan, time));
         }
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Handles the user request to set the burst count value for the number of pulses to be issued upon trigger in
PWM burst mode operation on the selected channel, calling the method in the naibrd library to set the burst number.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_TTL_PWM_Burstcount(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t burstcount;
   uint32_t ModuleID;
   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("\nEnter the desired burst count: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
         burstcount = atoi((const char *)inputBuffer);
         switch (ModuleID)
         {
         case NAI_MODULE_ID_TL2:
         case NAI_MODULE_ID_TL4:
         case NAI_MODULE_ID_TL6:
         case NAI_MODULE_ID_TL8:
            if (burstcount < 1)
            {
               burstcount = 1; /*minimum count is one*/
               printf("Setting burstcount to minimum of 1.\n");
            }
            check_status(naibrd_TTL_SetPWM_BurstNum(cardIndex, module, chan, burstcount));
            break;
         default:
            printf("Unsupported function for this module.\n");
            break;
         }
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Configure_TTL_PWM_Polarity handles the user request to select the PWM output polarity for the selected channel
and calls the method in the naibrd library for the setting.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_TTL_PWM_Polarity(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("\n == PWM Output Polarity Selection == \n Pos  TTL PWM positive going pulse output \n Neg  TTL PWM negative going pulse output \n\n Type TTL command : ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         if ((toupper(inputBuffer[0]) == 'P'))
            check_status(naibrd_TTL_SetPWM_Polarity(cardIndex, module, chan, (nai_ttl_pwm_polarity_t)NAI_TTL_PWMPOLARITY_POS));
         else if ((toupper(inputBuffer[0]) == 'N'))
            check_status(naibrd_TTL_SetPWM_Polarity(cardIndex, module, chan, (nai_ttl_pwm_polarity_t)NAI_TTL_PWMPOLARITY_NEG));
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Display_TTL_PWM_Configuration illustrate the methods to call in the naibrd library to retrieve the PWM
configuration settings.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Display_TTL_PWM_Configuration(int32_t paramCount, int32_t* p_params)
{
   nai_ttl_pwm_polarity_t polaritysetting;
   float64_t period;
   float64_t pulsewidth;
   uint32_t burstnumber;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   /* Available configuration settings:
         PWM period", (Value read back in milliseconds)
         PWM pulsewidth",   (Value read back in milliseconds)
         PWM burst count (Number of pulses issued upon trigger in burst mode)
         PWM polarity",     0 = positive going pulsewidth, 1 = negative going
   */
   printf("\n");
   printf("  -------------PWM Configuration Settings---------------------------- \n");
   printf("  Period (ms)       Pulsewidth (ms)     Burst Cnt         Polarity    \n");
   printf(" --------------     ----------------    -----------      -----------  \n");

   check_status(naibrd_TTL_GetPWM_Period(cardIndex, module, chan, &period));
   printf("    %10.6f   ", period);

   check_status(naibrd_TTL_GetPWM_Pulsewidth(cardIndex, module, chan, &pulsewidth));
   printf("     %10.6f   ", pulsewidth);

   check_status(naibrd_TTL_GetPWM_BurstNum(cardIndex, module, chan, &burstnumber));
   printf("     0x%08X   ", burstnumber);

   check_status(naibrd_TTL_GetPWM_Polarity(cardIndex, module, chan, &polaritysetting));
   if (polaritysetting == 0)
      printf("        POS   ");
   else
      printf("        NEG   ");

   printf("\n\n");
   return NAI_ERROR_UNKNOWN;
}

/**************************************************************************************************************/
/**
<summary>
Display_DSW_Status illustrate the methods to call in the naibrd library to retrieve the status states.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Display_TTL_Status(int32_t paramCount, int32_t* p_params)
{
   nai_status_bit_t status;
   p_naiapp_AppParameters_t p_ttl_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ttl_params->cardIndex;
   int32_t module = p_ttl_params->module;
   int32_t chan = p_ttl_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   /* Available status:
         NAI_TTL_STATUS_BIT_LATCHED,
         NAI_TTL_STATUS_OVERCURRENT_LATCHED,
         NAI_TTL_STATUS_LO_HI_TRANS_LATCHED,
         NAI_TTL_STATUS_HI_LO_TRANS_LATCHED,
   */
   printf("\n");
   printf("  ----------------- Status ----------------------------\n");
   printf("   BIT      OC    Lo-Hi   Hi-Lo  \n");
   printf(" ------- -------- ------ ------- \n");

   check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_BIT_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_OVERCURRENT_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_LO_HI_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_TTL_GetStatus(cardIndex, module, chan, NAI_TTL_STATUS_HI_LO_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   printf("\n\n");

   return NAI_ERROR_UNKNOWN;
}

Help Bot

X