SSK 1.x ↔ 2.x: A Translation Guide
This guide is for developers who may have a working product on one NAI Software Support Kit and now need to work in the other — a new product that ships with the other SSK, or an update that moves you across versions.
This page is a translation reference, not a recommendation. If you’re deciding which SSK to use in the first place, see Choosing the Right SSK.
The mental model carries over
Both versions work the same way: you open a handle to the board, configure the module, read or write, then close. The
cardIndex/module/channeladdressing model is identical. What changes between versions is names, folder layout, header paths, and a few function signatures — not the workflow.
The entire connection skeleton is the same code in both kits. The menu-and-connect helpers — naiapp_RunBoardMenu, naiapp_query_CardIndex, naiapp_query_ModuleNumber, naiapp_access_CloseAllOpenCards — are byte-for-byte identical across 1.x and 2.x. The differences this guide covers live in the board/module API around that skeleton.
Companion references
- What’s inside each kit: SSK 1.x Package Guide · SSK 2.x Package Guide
- How to develop with each: Software Development Guide 1.X · Software Development Guide 2.X
- Online API browser: SSK 1.x Doxygen · SSK 2.x Doxygen — convenient for browsing, but the SSK’s own per-module headers (
functions/naibrd_<fam>.h) are the complete, authoritative reference
Folder-structure mapping
SSK 1.x lays the library and the samples out in a flat tree at the package root; SSK 2.x groups everything under a base/ directory and splits the library into one folder per component. They contain the same pieces, reorganized:
SSK 1.x (naibrd_SSK_Windows_Rev1.63/)
├── App/ prebuilt sample executables
├── AppSrc/ sample source, flat by module family
│ ├── AD/AD_BasicOps/ <- the worked example below
│ ├── DA/ Discrete/ SER/ 1553/ ...
│ └── naiapp_common/ shared menu/connection helpers
├── include/ library headers (naibrd.h, nai.h, functions/, boards/, ...)
├── src/ library implementation
├── Lib/ prebuilt libraries (platform subdirs, e.g. Lib/Linux_ARM)
├── Drivers/ platform driver install (platform-specific)
└── Documentation/ offline docsSSK 2.x (Windows/ssk2/)
├── base/
│ ├── nai_libs/ libraries, one folder each (naibrd, naiether, naiif, nailib, naips)
│ │ └── <lib>/include/ + <lib>/src/
│ ├── nai_bsp/ board support package + platform config (platform-specific)
│ └── nai_sample_apps/
│ ├── naiapp_common/ shared menu/connection helpers (include/ + src/)
│ └── naiapp_src/
│ └── board_modules/ samples, lowercase, e.g. ad/ad_basic_ops/src/
├── build/ build outputs (platform-specific)
└── docs/ offline docsWhere each 1.x location ends up in 2.x:
| SSK 1.x | SSK 2.x |
|---|---|
AppSrc/<Family>/<Sample>/ | base/nai_sample_apps/naiapp_src/board_modules/<family>/<sample>/src/ |
AppSrc/naiapp_common/ | base/nai_sample_apps/naiapp_common/ |
include/ + src/ (one tree) | base/nai_libs/<lib>/include/ + …/src/ (split per library) |
Documentation/ | docs/ |
Lib/ (prebuilt) | produced under build/ |
Drivers/ | folded into base/nai_bsp/ |
Two naming conventions also flip: sample folders are PascalCase in 1.x (AD/AD_BasicOps/) and lowercase in 2.x (ad/ad_basic_ops/), and 2.x adds an extra src/ level inside each sample.
Folder layout varies slightly by platform
The trees above are the Windows packages.
Drivers/,Lib/subdirectories (1.x), andnai_bsp/config +build/(2.x) differ by OS/architecture. Onboard packages (PetaLinux/VxWorks) also add anaiapp_src/devices/folder (GPIO, RTC, watchdog) that the Windows Ethernet-host package does not include. For the authoritative per-platform layout see SSK 1.x Package Guide and SSK 2.x Package Guide.
API naming cheat sheet
Some renames are systematic — apply them mechanically across your whole file. Others are per-function and must be looked up in the API reference. Start with the systematic rules:
| What | SSK 1.x | SSK 2.x | Rule |
|---|---|---|---|
| Module function prefix | naibrd_AD_… | naibrd_AD_… | Same prefix — but specific names may differ (see below) |
| Module enum/type | nai_ad_mode_t, nai_ad_range_mode_t | naibrd_ad_mode_t, naibrd_ad_polarity_t | nai_<fam>_*_t → naibrd_<fam>_*_t |
| Module constant | NAI_AD_MODE_VOLTAGE, NAI_MODULE_ID_AD4 | NAIBRD_AD_MODE_VOLTAGE, NAIBRD_MODULE_ID_CF1 | NAI_AD_* / NAI_MODULE_ID_* → NAIBRD_AD_* / NAIBRD_MODULE_ID_* |
| Boolean literals | TRUE, FALSE | NAI_TRUE, NAI_FALSE | 1.x samples use bare TRUE/FALSE; 2.x prefixes them NAI_ (not NAIBRD_) |
| Other framework constants | NAI_QUIT_CHAR | identical | Unchanged |
| Connection helpers | naiapp_RunBoardMenu, naiapp_query_CardIndex, … | identical | Unchanged |
| Header include path | #include "functions/naibrd_ad.h" | #include "nai_libs/naibrd/include/functions/naibrd_ad.h" | short relative → fully-qualified from base/ |
The pattern to internalize: board/module-domain identifiers picked up the naibrd / NAIBRD prefix in 2.x (functions stay naibrd_…; types go nai_<fam>_*_t → naibrd_<fam>_*_t; constants go NAI_<FAM>_* → NAIBRD_<FAM>_*), while framework identifiers stayed in the NAI_ / naiapp_ namespace — booleans even gained a plain NAI_ (TRUE → NAI_TRUE), never NAIBRD_. So don’t blanket-replace NAI_ → NAIBRD_.
Not every function maps mechanically. These examples are all from the AD module and confirmed present in both kits:
| SSK 1.x | SSK 2.x | Note |
|---|---|---|
naibrd_AD_ConvertToVoltageRange | naibrd_AD_ConvertToRange | renamed |
naibrd_AD_GetBreakFrequency | naibrd_AD_GetFilterBreakFrequency | renamed |
naibrd_AD_GetFloatingPointScaleFactor + …Offset | naibrd_AD_GetFloatingPointAttribute | two getters consolidated into one (attribute selected by argument) |
| (none) | naibrd_AD_GetData, naibrd_AD_GetActiveChannel, naibrd_AD_SetActiveChannel | new in 2.x |
When a name doesn't translate mechanically
The most reliable reference is the SSK itself — open the per-module header (
functions/naibrd_<fam>.h) and search it for keywords, as described in Finding a function’s counterpart below. The online Doxygen (SSK 1.x · SSK 2.x) is fine for browsing, but it can be incomplete so when the two disagree, trust the header.
Finding a function’s counterpart
The function names won’t line up exactly, so don’t hunt by name — hunt by what the function does. Both versions organize the API the same way, which makes the match findable in a minute or two:
-
Stay in the same module family. A 1.x
naibrd_AD_*call has its counterpart among the 2.xnaibrd_AD_*calls — same family, same header (functions/naibrd_ad.h). You never search the whole API, just one module’s functions. -
Search by the operation, not the full name. Pick the distinctive noun and search the other kit’s module header for it. Looking for 1.x
naibrd_AD_GetBreakFrequencyin 2.x? Search the AD header forFrequency— you land onnaibrd_AD_GetFilterBreakFrequency. SearchVoltageafterGetVoltageand you’re nudged towardGetData, once you notice voltage became a mode argument. The header is the complete list of what the kit actually ships — more so than the online docs. -
Line up the two sample apps. The same sample ships in both kits (the AD BasicOps walkthrough below is one). Open both and read them in parallel — the call at the same point in the workflow is the equivalent, even when it’s named differently. The matching samples are the most reliable Rosetta Stone you have.
-
When in doubt, grep both trees. From each SSK root:
# 1.x grep -rn "Frequency" include/functions/naibrd_ad.h # 2.x grep -rn "Frequency" base/nai_libs/naibrd/include/functions/naibrd_ad.hlists every candidate in seconds.
Finally, when there’s no like-named function, it almost always took one of two shapes: it was consolidated (several 1.x calls became one 2.x call with a selector argument — GetFloatingPointScaleFactor + …Offset → GetFloatingPointAttribute), or redesigned (a selector moved into a parameter — GetVoltage → GetData(…, data_mode, …)). So if a direct match is missing, look for a more general function that takes an extra argument.
Worked example — AD BasicOps, side by side
The same sample ships in both kits — 1.x at AppSrc/AD/AD_BasicOps/AD_BasicOps.c, 2.x at base/nai_sample_apps/naiapp_src/board_modules/ad/ad_basic_ops/src/ad_basic_ops.c. They’re nearly line-for-line parallel. Here are the four phases of the lifecycle, side by side, with the actual source from each kit.
1. Includes — header paths get longer
The 1.x sample includes by short relative path; 2.x includes are fully qualified from base/.
/* SSK 1.x */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ad.h"
#include "boards/naibrd_gen5.h"/* SSK 2.x */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ad.h"
#include "nai_libs/naiif/include/naiif_stdio.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"What changed: only the path prefixes. The header names (naibrd.h, functions/naibrd_ad.h, the naiapp_boardaccess_* set) are the same — they just live under nai_libs/… and nai_sample_apps/… now.
2. Open the board — identical workflow
This is the connection skeleton. Apart from the boolean literal (TRUE → NAI_TRUE) and the module-id lookup call, it’s the same code.
/* SSK 1.x */
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
naiapp_query_ModuleNumber(moduleCount, 1, &module);
modId = naibrd_GetModuleID(cardIndex, module);
bQuit = ADBasicOps_run(cardIndex, module, modId);
}
}/* SSK 2.x */
if (naiapp_RunBoardMenu(CONFIG_FILE) == NAI_TRUE)
{
while (!bQuit)
{
naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
naibrd_GetModuleCount(cardIndex, &moduleCount);
naiapp_query_ModuleNumber(moduleCount, 1, &module);
naibrd_GetModuleName(cardIndex, module, &modId);
bQuit = ADBasicOps_run(cardIndex, module, modId);
}
}What changed: == TRUE → == NAI_TRUE, and the module identifier is fetched with naibrd_GetModuleID(...) (returns the id) in 1.x vs naibrd_GetModuleName(cardIndex, module, &modId) (writes it through a pointer) in 2.x. The four naiapp_* calls are byte-for-byte identical.
3. Read a channel — the rename in action
Reading a voltage is where the per-function rename shows up: 1.x calls naibrd_AD_GetVoltage, 2.x calls naibrd_AD_GetData with an explicit mode argument.
/* SSK 1.x */
nai_ad_mode_t data_mode = NAI_AD_MODE_VOLTAGE;
check_status(naibrd_AD_GetMode(cardIndex, module, channel, &data_mode));
check_status(naibrd_AD_GetVoltage(cardIndex, module, channel, &data));/* SSK 2.x */
naibrd_ad_mode_t data_mode = NAIBRD_AD_MODE_VOLTAGE;
check_status(naibrd_AD_GetMode(cardIndex, module, channel, &data_mode));
check_status(naibrd_AD_GetData(cardIndex, module, channel, data_mode, &data));What changed: the type nai_ad_mode_t → naibrd_ad_mode_t and the constant NAI_AD_MODE_VOLTAGE → NAIBRD_AD_MODE_VOLTAGE (systematic). The read itself was redesigned: naibrd_AD_GetVoltage(...) → naibrd_AD_GetData(..., data_mode, &data), which takes the mode as a parameter so one call covers voltage, current, and RMS. naibrd_AD_GetMode kept its name in both.
4. Close — identical
/* SSK 1.x */
naiapp_access_CloseAllOpenCards();/* SSK 2.x */
naiapp_access_CloseAllOpenCards();What changed: nothing. Teardown is the same call in both.
Gotchas and breaking changes
Most differences fail loudly at compile time (a renamed function just won’t link), which is the easy case. These are the ones that don’t announce themselves:
Watch out for these
- Consolidated / redesigned calls hide behavior in an argument. A renamed function (
ConvertToVoltageRange→ConvertToRange) fails to compile and you fix it. But when several calls became one —GetFloatingPointScaleFactor+…Offset→GetFloatingPointAttribute, orGetVoltage→GetData(…, data_mode, …)— the behavior moved into a parameter. Pass the wrong selector and it compiles fine but reads the wrong thing. Check the argument, not just the name.- The constant prefix is domain-specific — don’t blanket-replace
NAI_→NAIBRD_. Only board/module identifiers changed (NAI_AD_*→NAIBRD_AD_*,NAI_MODULE_ID_*→NAIBRD_MODULE_ID_*). Framework constants did not:NAI_QUIT_CHARis unchanged, and the boolean literals wentTRUE/FALSE→NAI_TRUE/NAI_FALSE(plainNAI_, neverNAIBRD_). A global search-and-replace will mangle these.- Header includes are fully qualified from
base/in 2.x. A 1.x#include "functions/naibrd_ad.h"won’t resolve as-is; it’s#include "nai_libs/naibrd/include/functions/naibrd_ad.h"in 2.x. Update the paths, not just the file names.- Onboard-only samples don’t exist in the host package. The
naiapp_src/devices/samples (GPIO, RTC, watchdog) ship only in onboard packages (PetaLinux/VxWorks), not the Windows Ethernet-host kit. If a device sample you remember isn’t there, you’re likely looking at a different-platform package — see the SSK 2.x Package Guide.
How to port your code
The sections above are the reference; here’s the procedure. Porting an application from one SSK to the other goes fastest in this order:
-
Start from the matching sample, not a blank file. Find the same sample in the kit you’re moving to (this guide used AD BasicOps; the folder map shows where samples live in each). Get it building and running first — it proves your toolchain and gives you a known-good reference to diff against.
-
Swap the includes. Repoint every
#includefrom the short relative paths to the fully-qualifiednai_libs/…/nai_sample_apps/…form (or the reverse). The header names don’t change — only the path prefixes. See the include step of the walkthrough. -
Apply the systematic renames mechanically. Run through the first cheat-sheet table: module types
nai_<fam>_*_t↔naibrd_<fam>_*_t, module constantsNAI_<FAM>_*↔NAIBRD_<FAM>_*, and booleansTRUE/FALSE↔NAI_TRUE/NAI_FALSE. These are safe find-and-replace — but scoped to module/board identifiers only, never a blanketNAI_→NAIBRD_. -
Resolve the leftover function calls. Whatever still won’t compile is a per-function difference. For each one, use Finding a function’s counterpart — search the other kit’s module header by what the call does, line it up against the matching sample, and watch for calls that were consolidated or redesigned to take an extra argument.
-
Rebuild, then run the sample again before touching your own logic. SSK 2.x builds with CMake (
CMakeLists.txtunderbase/); SSK 1.x samples ship both a Visual Studio solution and a CMake file. For the exact build and deploy commands per platform, follow the Software Development Guide 1.X or Software Development Guide 2.X, and Connecting to Boards for toolchain and target setup.
Moving the other direction works the same way
Going 2.x → 1.x uses the identical procedure — just read every mapping in this guide right-to-left. The systematic renames reverse cleanly; the per-function lookups are where you’ll spend your time either way.
Related
- Choosing the Right SSK — which SSK package to use in the first place
- SSK 1.x Package Guide · SSK 2.x Package Guide — what’s inside each kit
- Software Development Guide 1.X · Software Development Guide 2.X — how to use each SSK
- Connecting to Boards — toolchain, deployment, terminal access
- SSK 1.x Doxygen · SSK 2.x Doxygen — online API browser
