SP1000G API Usage
The sp1000gapi_transition_t
type
Captured samples are packetized and transfered between device and your application using a data type called sp1000gapi_transition_t
.
This data type allows for more optimal - compressed - transfer of captured samples. You can think of this data type as a way of timestamping each transition recorded by the device. Here is how it works: Each time the logic level on one or more channels changes, a new transition is created, and the time difference (delta_samples
) between this transition and the previous one is recorded.
Trigger configuration
In order to describe a particular trigger configuration, the sp1000gapi_trigger_description_t
structure is used.
it can be passed as a parameter to SP209’s API as it can be seen in the examples below. The definition of each member of this structure is described in the header file sp1000gapi_types.h
Please note that the trigger capabilities of the API are somewhat limited compared to what’s possible with ScanaStudio, nevertheless, it allows basic triggering options.
Usage examples
Below are some C/C++ example code snippets.
Note: in order to run those examples, it’s necessary to include the following files:
ihwapi_common_types.h
sp1000gapi_types.h
sp1000gapi.h
Also, please note those examples are created, run, and tested under Qt environment, that being said, we used standard C++ compliant syntax, without any fancy Qt specific functions
Listing the number of open devices
sp1000gapi_handle h;
int devices_count = 0;
sp1000gapi_create_new_handle(&h, sp1000gapi_model_t::sp1054g);
sp1000gapi_create_device_list(h);
sp1000gapi_get_devices_count(h, &devices_count);
sp1000gapi_free_device_list(h);
Here is a more complex example that also gets device descriptor:
#define DBG std::cout << "\n\r" << " "
sp1000gapi_handle h;
device_descriptor_t d;
int devices_count = 0;
sp1000gapi_create_new_handle(&h, sp1000gapi_model_t::sp1054g);
sp1000gapi_create_device_list(h);
sp1000gapi_get_devices_count(h, &devices_count);
if (devices_count > 0)
{
sp1000gapi_get_device_descriptor(h,0,&d);
DBG << "New device, serial number = " << d.sn << ", description = " << d.desc ;
}
sp1000gapi_free_device_list(h);
DBG << "New device, serial number = " << d.sn << ", description = " << d.desc;
Open a device
#define DBG std::cout << "\n\r" << " "
sp1000gapi_handle h;
device_descriptor_t d;
int devices_count = 0;
ihwapi_err_code_t e;
sp1000gapi_create_new_handle(&h, sp1000gapi_model_t::sp1054g);
sp1000gapi_create_device_list(h);
sp1000gapi_get_devices_count(h,&devices_count);
DBG << "Found " << devices_count << " devices" ;
if (devices_count > 0)
{
sp1000gapi_get_device_descriptor(h,0,&d);
DBG << "New device, serial number = " << d.sn << ", description = " << d.desc ;
e = sp1000gapi_device_open(h,d);
if (e == IHWAPI_OK)
{
DBG << "Device is open";
}
else
{
DBG << "Device not open! error code = " << e ;
}
}
sp1000gapi_free_device_list(h);
sp1000gapi_free(h);
Capture samples
The following examples show how to open a seek for a device, open it, and capture some samples. Then, the transitions on channel 1 are dumped to the console.
void msleep(int ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
void assert_err(ihwapi_err_code_t e)
{
if (e != ihwapi_err_code_t::IHWAPI_OK)
{
std::cout << "Error thrown by API " << uint32_t(e) << std::endl;
throw std::runtime_error("unhandled error");
}
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
std::cout << "SP1018G API Test" << std::endl;
ihwapi_err_code_t e;
sp1000gapi_handle h = nullptr;
e = sp1000gapi_create_new_handle(&h, sp1000gapi_model_t::sp1054g);
assert_err(e);
e = sp1000gapi_create_device_list(h);
assert_err(e);
e = sp1000gapi_device_open_first(h);
assert_err(e);
std::cout << "Device open and ready\n"
<< std::endl;
sp1000gapi_settings_t settings;
memset(&settings, 0, sizeof(settings));
settings.s_clk = 250e6;
settings.vcc_gen_mv[0] = 3000;
settings.vcc_gen_mv[1] = 3000;
settings.ext_trig_50r = false;
settings.timebase_src = sp1000gapi_timebase_clk_t::TIMEBASE_INTERNAL;
settings.state_clk_mode = sp1000gapi_state_clk_mode_t::SCLK_DISABLE;
settings.state_clk_src = sp1000gapi_state_clk_source_t::SCLK_CH9;
settings.sampling_depth = 10e6; // 50e6;
settings.post_trig_depth = settings.sampling_depth * 0.9; // 5000e6; //float(settings.sampling_depth)*0.1f;
settings.thresh_capture_mv[0] = 1000;
settings.thresh_capture_mv[1] = 1000;
settings.ext_in_threshold_mv = 1000;
settings.ext_trig_out_polarity = true; // rising
for (int ch = 0; ch < SP1000G_CHANNELS_COUNT; ch++)
{
settings.io_type[ch] = SP1000GAPI_IO_IN;
settings.io_pull[ch] = SP1000GAPI_PULL_DOWN;
}
sp1000gapi_trigger_description_t trig_a, trig_b;
trig_a.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_NOTRIG;
trig_a.channel = -1;
trig_b.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_NOTRIG;
trig_b.channel = -1;
e = sp1000gapi_get_last_error(h);
e = sp1000gapi_launch_new_capture_simple_trigger(h, trig_a, trig_b, settings);
e = sp1000gapi_get_last_error(h);
assert_err(e);
bool cfg_done = false;
while (cfg_done == false)
{
e = sp1000gapi_get_config_done_flag(h, &cfg_done);
assert_err(e);
msleep(10);
}
std::cout << "cfg done!\n"
<< std::endl;
bool trg_flag = false;
while (trg_flag == false)
{
std::cout << "Waiting for trigger" << std::endl;
e = sp1000gapi_get_triggered_flag(h, &trg_flag);
assert_err(e);
msleep(100);
}
std::cout << "Trigged, ready for data!" << std::endl;
int64_t total = 0;
int64_t pre = 0;
int64_t post = 0;
while (post < settings.post_trig_depth)
{
e = sp1000gapi_get_available_samples(h, &total, &post);
assert_err(e);
msleep(100);
std::cout << "retrieved transitions, pre-trig: " << pre / 1000 << +"K, post-trig:" << post / 1000 << "K" << std::endl;
}
e = sp1000gapi_get_last_error(h);
assert_err(e);
e = sp1000gapi_request_abort(h);
assert_err(e);
bool ready = false;
while (!ready)
{
std::cout << "Waiting for abort\n"
<< std::endl;
msleep(100);
e = sp1000gapi_get_ready_flag(h, &ready);
assert_err(e);
}
e = sp1000gapi_free(h);
assert_err(e);
std::cout << "device freed\n"
<< std::endl;
return 0;
}
Capture samples with trigger
And finally, let’s look at an example to capture some samples with a trigger condition.
In this example, we wait for a change on channel 1, which is defined by the lines below:
sp1000gapi_trigger_description_t trig_a, trig_b;
trig_a.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_CHANGE;
trig_a.channel = 1;
trig_b.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_NOTRIG;
trig_b.channel = -1;
SP1018G has two trigger engines (A & B), but for the sake of simplicity, we only configure and use trigger engine A.
Here is the complete example:
void msleep(int ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
void assert_err(ihwapi_err_code_t e)
{
if (e != ihwapi_err_code_t::IHWAPI_OK)
{
std::cout << "Error thrown by API " << uint32_t(e) << std::endl;
throw std::runtime_error("unhandled error");
}
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
std::cout << "SP1018G API Test" << std::endl;
ihwapi_err_code_t e;
sp1000gapi_handle h = nullptr;
e = sp1000gapi_create_new_handle(&h, sp1000gapi_model_t::sp1054g);
assert_err(e);
e = sp1000gapi_create_device_list(h);
assert_err(e);
e = sp1000gapi_device_open_first(h);
assert_err(e);
std::cout << "Device open and ready\n"
<< std::endl;
sp1000gapi_settings_t settings;
memset(&settings, 0, sizeof(settings));
settings.s_clk = 250e6;
settings.vcc_gen_mv[0] = 3000;
settings.vcc_gen_mv[1] = 3000;
settings.ext_trig_50r = false;
settings.timebase_src = sp1000gapi_timebase_clk_t::TIMEBASE_INTERNAL;
settings.state_clk_mode = sp1000gapi_state_clk_mode_t::SCLK_DISABLE;
settings.state_clk_src = sp1000gapi_state_clk_source_t::SCLK_CH9;
settings.sampling_depth = 10e6; // 50e6;
settings.post_trig_depth = settings.sampling_depth * 0.9; // 5000e6; //float(settings.sampling_depth)*0.1f;
settings.thresh_capture_mv[0] = 1000;
settings.thresh_capture_mv[1] = 1000;
settings.ext_in_threshold_mv = 1000;
settings.ext_trig_out_polarity = true; // rising
for (int ch = 0; ch < SP1000G_CHANNELS_COUNT; ch++)
{
settings.io_type[ch] = SP1000GAPI_IO_IN;
settings.io_pull[ch] = SP1000GAPI_PULL_DOWN;
}
sp1000gapi_trigger_description_t trig_a, trig_b;
trig_a.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_CHANGE;
trig_a.channel = 1;
trig_b.type = sp1000gapi_trigger_type_t::SP1000GAPI_TRG_NOTRIG;
trig_b.channel = -1;
e = sp1000gapi_get_last_error(h);
e = sp1000gapi_launch_new_capture_simple_trigger(h, trig_a, trig_b, settings);
e = sp1000gapi_get_last_error(h);
assert_err(e);
bool cfg_done = false;
while (cfg_done == false)
{
e = sp1000gapi_get_config_done_flag(h, &cfg_done);
assert_err(e);
msleep(10);
}
std::cout << "cfg done!\n"
<< std::endl;
bool trg_flag = false;
while (trg_flag == false)
{
std::cout << "Waiting for trigger" << std::endl;
e = sp1000gapi_get_triggered_flag(h, &trg_flag);
assert_err(e);
msleep(100);
}
std::cout << "Trigged, ready for data!" << std::endl;
int64_t total = 0;
int64_t pre = 0;
int64_t post = 0;
while (post < settings.post_trig_depth)
{
e = sp1000gapi_get_available_samples(h, &total, &post);
assert_err(e);
msleep(100);
std::cout << "retrieved transitions, pre-trig: " << pre / 1000 << +"K, post-trig:" << post / 1000 << "K" << std::endl;
}
e = sp1000gapi_get_last_error(h);
assert_err(e);
e = sp1000gapi_request_abort(h);
assert_err(e);
bool ready = false;
while (!ready)
{
std::cout << "Waiting for abort\n"
<< std::endl;
msleep(100);
e = sp1000gapi_get_ready_flag(h, &ready);
assert_err(e);
}
e = sp1000gapi_free(h);
assert_err(e);
std::cout << "device freed\n"
<< std::endl;
return 0;
}