ant-wireless 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.md +31 -0
- data/README.md +11 -1
- data/ext/ant_ext/ant_ext.c +178 -1
- data/ext/ant_ext/channel.c +198 -16
- data/ext/ant_ext/extconf.rb +10 -0
- data/lib/ant/bitvector.rb +197 -0
- data/lib/ant/channel/event_callbacks.rb +13 -17
- data/lib/ant/channel.rb +52 -5
- data/lib/ant/response_callbacks.rb +156 -323
- data/lib/ant.rb +76 -1
- data/spec/ant_spec.rb +9 -0
- data/spec/bitvector_spec.rb +141 -0
- data/spec/spec_helper.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cbf09bffd2b5ac2d18ea9fb271bb1e358707b45a49bd45651129d5030598e95
|
4
|
+
data.tar.gz: f2d892f9c17f352e81b1b6236ac567a62f24b61495860b0f071975bd80446ea8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ecd19b9d5c711fe0e71be58e5fa3c1386fa340bc9cafa0279e08ba52b48ebe8f7169386faf93fe5b7a900a8ee70d84d049f31db3405dc2c7e957fa5126fce2c
|
7
|
+
data.tar.gz: 83aa2b97810514c2279182d1853efeed48087e270cb6db2533b151cae046370a6071c7fa2ed164cf6558c79b1f970a3d18526c2188ea281dc4493ec8313ebec5
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/History.md
CHANGED
@@ -1,6 +1,37 @@
|
|
1
1
|
# Release History for ruby-ant
|
2
2
|
|
3
3
|
---
|
4
|
+
## v0.4.0 [2021-11-05] Michael Granger <ged@FaerieMUD.org>
|
5
|
+
|
6
|
+
Enhancements:
|
7
|
+
|
8
|
+
- Add advanced burst support (with a customized ANT-SDK).
|
9
|
+
|
10
|
+
|
11
|
+
## v0.3.0 [2021-10-11] Michael Granger <ged@FaerieMUD.org>
|
12
|
+
|
13
|
+
Enhancements:
|
14
|
+
|
15
|
+
- Add frequency agility config to Channel
|
16
|
+
- Add tunable transmit power knob
|
17
|
+
|
18
|
+
|
19
|
+
## v0.2.1 [2021-09-30] Michael Granger <ged@FaerieMUD.org>
|
20
|
+
|
21
|
+
Bugfixes:
|
22
|
+
|
23
|
+
- Add missing files to the manifest
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
## v0.2.0 [2021-09-22] Michael Granger <ged@FaerieMUD.org>
|
28
|
+
|
29
|
+
Enhancements:
|
30
|
+
|
31
|
+
- Add channel period, search timeout, and introspection methods
|
32
|
+
- Add Ant.initialized? predicate
|
33
|
+
- Make the default response and event callback modules more useful.
|
34
|
+
|
4
35
|
|
5
36
|
## v0.1.0 [2021-08-26] Michael Granger <ged@FaerieMUD.org>
|
6
37
|
|
data/README.md
CHANGED
@@ -24,7 +24,10 @@ manner.
|
|
24
24
|
* [Garmin USB ANT Stick][antstick]
|
25
25
|
* [ANT SDK][antsdk]
|
26
26
|
|
27
|
-
Note that we had trouble compiling the latest ANT SDK on some platforms, so we
|
27
|
+
Note that we had trouble compiling the latest ANT SDK on some platforms, so we
|
28
|
+
are currently using a modified version of it with a reworked build system for
|
29
|
+
MacOS and FreeBSD, and with implementations for advanced burst and checking
|
30
|
+
initialization status. That is available under the same licensing terms at:
|
28
31
|
|
29
32
|
https://github.com/RavnGroup/Garmin-ANT-SDK
|
30
33
|
|
@@ -57,6 +60,12 @@ This task will install dependencies, and do any other necessary setup for develo
|
|
57
60
|
|
58
61
|
## License
|
59
62
|
|
63
|
+
Portions of this code are from StaticCling, and are used under the
|
64
|
+
terms of the 3-Clause BSD License. Specifics can be found in the
|
65
|
+
appropriate files.
|
66
|
+
|
67
|
+
This software is:
|
68
|
+
|
60
69
|
Copyright (c) 2021, Ravn Group
|
61
70
|
|
62
71
|
Permission is hereby granted, free of charge, to any person obtaining
|
@@ -82,3 +91,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
82
91
|
[ant]: https://www.thisisant.com/
|
83
92
|
[antstick]: https://buy.garmin.com/en-US/US/p/10997/pn/010-01058-00
|
84
93
|
[antsdk]: https://www.thisisant.com/developer/resources/downloads/#software_tab
|
94
|
+
|
data/ext/ant_ext/ant_ext.c
CHANGED
@@ -225,6 +225,26 @@ rant_s_init( int argc, VALUE *argv, VALUE _module )
|
|
225
225
|
}
|
226
226
|
|
227
227
|
|
228
|
+
/*
|
229
|
+
* call-seq:
|
230
|
+
* Ant.initialized? -> true or false
|
231
|
+
*
|
232
|
+
* Returns +true+ if the ANT library has been initialized.
|
233
|
+
*
|
234
|
+
* Note: this requires a modified version of the Garmin ANT-SDK.
|
235
|
+
*
|
236
|
+
*/
|
237
|
+
static VALUE
|
238
|
+
rant_s_initialized_p( VALUE _module )
|
239
|
+
{
|
240
|
+
#ifdef HAVE_ANT_ISINITIALIZED
|
241
|
+
const bool initialized = ANT_IsInitialized();
|
242
|
+
return initialized ? Qtrue : Qfalse;
|
243
|
+
#else
|
244
|
+
rb_notimplement();
|
245
|
+
#endif
|
246
|
+
}
|
247
|
+
|
228
248
|
|
229
249
|
/*
|
230
250
|
* call-seq:
|
@@ -291,13 +311,39 @@ rant_s_set_network_key( VALUE _module, VALUE network_number, VALUE key )
|
|
291
311
|
}
|
292
312
|
|
293
313
|
if ( !ANT_SetNetworkKey(ucNetNumber, (unsigned char *)pucKey) ) {
|
294
|
-
|
314
|
+
rant_log( "error", "could not set the network key." );
|
295
315
|
}
|
296
316
|
|
297
317
|
return Qtrue;
|
298
318
|
}
|
299
319
|
|
300
320
|
|
321
|
+
/*
|
322
|
+
* call-seq:
|
323
|
+
* Ant.transmit_power = 4
|
324
|
+
*
|
325
|
+
* Set the transmit power level for all channels. Valid values are 0-4; default
|
326
|
+
* is 3 = 0dBm.
|
327
|
+
*
|
328
|
+
* # Set transmit power to -5 dBm
|
329
|
+
* Ant.transmit_power = 2
|
330
|
+
*/
|
331
|
+
static VALUE
|
332
|
+
rant_s_transmit_power_eq( VALUE _module, VALUE power )
|
333
|
+
{
|
334
|
+
const unsigned char ucTransmitPower = NUM2CHR( power );
|
335
|
+
BOOL rval;
|
336
|
+
|
337
|
+
if ( ucTransmitPower < 0 || ucTransmitPower > 4 ) {
|
338
|
+
rb_raise( rb_eArgError, "expected a value between 0 and 4, got %d", ucTransmitPower );
|
339
|
+
}
|
340
|
+
|
341
|
+
rval = ANT_SetTransmitPower( ucTransmitPower );
|
342
|
+
|
343
|
+
return rval ? Qtrue : Qfalse;
|
344
|
+
}
|
345
|
+
|
346
|
+
|
301
347
|
/*
|
302
348
|
* call-seq:
|
303
349
|
* Ant.assign_channel( channel, channel_type, network_number=0, extended_options=0x0, timeout=0 ) -> channel
|
@@ -381,6 +427,56 @@ rant_s_use_extended_messages_eq( VALUE _module, VALUE true_false )
|
|
381
427
|
}
|
382
428
|
|
383
429
|
|
430
|
+
/*
|
431
|
+
* call-seq:
|
432
|
+
* Ant.configure_advanced_burst( enabled, max_packet_length, required_fields, optional_fields,
|
433
|
+
* stall_count=3210, retry_count=4 )
|
434
|
+
*
|
435
|
+
* Enable/disable and configure advanced burst. This is the lower-level method; the
|
436
|
+
* higher-level methods are: #enable_advanced_burst and #disable_advanced_burst.
|
437
|
+
*
|
438
|
+
*/
|
439
|
+
static VALUE
|
440
|
+
rant_s_configure_advanced_burst( int argc, VALUE *argv, VALUE _module )
|
441
|
+
{
|
442
|
+
VALUE enabled,
|
443
|
+
max_packet_length,
|
444
|
+
required_fields,
|
445
|
+
optional_fields,
|
446
|
+
stall_count = Qnil,
|
447
|
+
retry_count = Qnil;
|
448
|
+
bool bEnable;
|
449
|
+
unsigned char ucMaxPacketLength,
|
450
|
+
ucRetryCount = 0;
|
451
|
+
unsigned long ulRequiredFields,
|
452
|
+
ulOptionalFields;
|
453
|
+
unsigned short usStallCount = 0;
|
454
|
+
bool rval;
|
455
|
+
|
456
|
+
rb_scan_args( argc, argv, "42", &enabled, &max_packet_length, &required_fields,
|
457
|
+
&optional_fields, &stall_count, &retry_count );
|
458
|
+
|
459
|
+
bEnable = RTEST( enabled );
|
460
|
+
ucMaxPacketLength = NUM2CHR( max_packet_length );
|
461
|
+
ulRequiredFields = NUM2ULONG( required_fields );
|
462
|
+
ulOptionalFields = NUM2ULONG( optional_fields );
|
463
|
+
|
464
|
+
if ( RTEST(stall_count) ) {
|
465
|
+
usStallCount = NUM2USHORT( stall_count );
|
466
|
+
}
|
467
|
+
if ( RTEST(retry_count) ) {
|
468
|
+
ucRetryCount = NUM2CHR( retry_count );
|
469
|
+
}
|
470
|
+
|
471
|
+
rant_log( "warn", "Configuring advanced burst: enable = %d, maxpacketlength = %d",
|
472
|
+
bEnable, ucMaxPacketLength );
|
473
|
+
rval = ANT_ConfigureAdvancedBurst_ext( bEnable, ucMaxPacketLength, ulRequiredFields,
|
474
|
+
ulOptionalFields, usStallCount, ucRetryCount );
|
475
|
+
|
476
|
+
return rval ? Qtrue : Qfalse;
|
477
|
+
}
|
478
|
+
|
479
|
+
|
384
480
|
// Buffer for response data.
|
385
481
|
// static UCHAR pucResponseBuffer[ MESG_RESPONSE_EVENT_SIZE ];
|
386
482
|
static UCHAR pucResponseBuffer[ MESG_MAX_SIZE_VALUE ];
|
@@ -463,6 +559,73 @@ rant_s_on_response( int argc, VALUE *argv, VALUE module )
|
|
463
559
|
}
|
464
560
|
|
465
561
|
|
562
|
+
/*
|
563
|
+
* call-seq:
|
564
|
+
* Ant.request_capabilities
|
565
|
+
*
|
566
|
+
* Request the current ANT device's capabilities. These will be delivered
|
567
|
+
* via a callback to the #on_capabilities response callback, which by default
|
568
|
+
* extracts them into a Hash which is stored at Ant.capabilities.
|
569
|
+
*
|
570
|
+
*/
|
571
|
+
static VALUE
|
572
|
+
rant_s_request_capabilities( VALUE _module )
|
573
|
+
{
|
574
|
+
bool rval = ANT_RequestMessage( 0, MESG_CAPABILITIES_ID );
|
575
|
+
return rval ? Qtrue : Qfalse;
|
576
|
+
}
|
577
|
+
|
578
|
+
|
579
|
+
/*
|
580
|
+
* call-seq:
|
581
|
+
* Ant.request_serial_num
|
582
|
+
*
|
583
|
+
* Request the current ANT device's serial number. The result will be delivered
|
584
|
+
* via a callback to the #on_get_serial_num response callback, which by default
|
585
|
+
* extracts it and stores it at Ant.serial_number.
|
586
|
+
*
|
587
|
+
*/
|
588
|
+
static VALUE
|
589
|
+
rant_s_request_serial_num( VALUE _module )
|
590
|
+
{
|
591
|
+
bool rval = ANT_RequestMessage( 0, MESG_GET_SERIAL_NUM_ID );
|
592
|
+
return rval ? Qtrue : Qfalse;
|
593
|
+
}
|
594
|
+
|
595
|
+
|
596
|
+
/*
|
597
|
+
* call-seq:
|
598
|
+
* Ant.request_version
|
599
|
+
*
|
600
|
+
* Request the current device's ANT version. The result will be delivered
|
601
|
+
* via a callback to the #on_version response callback, which by default
|
602
|
+
* extracts it and stores it at Ant.hardware_version.
|
603
|
+
*
|
604
|
+
*/
|
605
|
+
static VALUE
|
606
|
+
rant_s_request_version( VALUE _module )
|
607
|
+
{
|
608
|
+
bool rval = ANT_RequestMessage( 0, MESG_VERSION_ID );
|
609
|
+
return rval ? Qtrue : Qfalse;
|
610
|
+
}
|
611
|
+
|
612
|
+
|
613
|
+
/*
|
614
|
+
* call-seq:
|
615
|
+
* Ant.request_advanced_burst_capabilities
|
616
|
+
*
|
617
|
+
* Request the current device's advanced burst capabilities. The result will
|
618
|
+
* be delivered via a callback to the #on_version response callback, which by
|
619
|
+
* default extracts it and stores it at Ant.advanced_burst_capabilities.
|
620
|
+
*
|
621
|
+
*/
|
622
|
+
static VALUE
|
623
|
+
rant_s_request_advanced_burst_capabilities( VALUE _module )
|
624
|
+
{
|
625
|
+
bool rval = ANT_RequestMessage( 0, MESG_CONFIG_ADV_BURST_ID );
|
626
|
+
return rval ? Qtrue : Qfalse;
|
627
|
+
}
|
628
|
+
|
466
629
|
|
467
630
|
/*
|
468
631
|
* call-seq:
|
@@ -508,19 +671,29 @@ Init_ant_ext()
|
|
508
671
|
rb_define_singleton_method( rant_mAnt, "device_serial_number", rant_s_device_serial_number, 0 );
|
509
672
|
|
510
673
|
rb_define_singleton_method( rant_mAnt, "init", rant_s_init, -1 );
|
674
|
+
rb_define_singleton_method( rant_mAnt, "initialized?", rant_s_initialized_p, 0 );
|
511
675
|
// rb_define_singleton_method( rant_mAnt, "init_ext", rant_s_init_ext, 4 );
|
512
676
|
rb_define_singleton_method( rant_mAnt, "close", rant_s_close, 0 );
|
513
677
|
rb_define_singleton_method( rant_mAnt, "reset", rant_s_reset, 0 );
|
514
678
|
|
515
679
|
rb_define_singleton_method( rant_mAnt, "set_network_key", rant_s_set_network_key, 2 );
|
680
|
+
rb_define_singleton_method( rant_mAnt, "transmit_power=", rant_s_transmit_power_eq, 1 );
|
516
681
|
rb_define_singleton_method( rant_mAnt, "assign_channel", rant_s_assign_channel, -1 );
|
517
682
|
|
518
683
|
rb_define_singleton_method( rant_mAnt, "use_extended_messages=",
|
519
684
|
rant_s_use_extended_messages_eq, 1 );
|
685
|
+
rb_define_singleton_method( rant_mAnt, "configure_advanced_burst",
|
686
|
+
rant_s_configure_advanced_burst, -1 );
|
520
687
|
|
521
688
|
rb_define_singleton_method( rant_mAnt, "on_response", rant_s_on_response, -1 );
|
522
689
|
// EXPORT void ANT_UnassignAllResponseFunctions(); //Unassigns all response functions
|
523
690
|
|
691
|
+
rb_define_singleton_method( rant_mAnt, "request_capabilities", rant_s_request_capabilities, 0 );
|
692
|
+
rb_define_singleton_method( rant_mAnt, "request_serial_num", rant_s_request_serial_num, 0 );
|
693
|
+
rb_define_singleton_method( rant_mAnt, "request_version", rant_s_request_version, 0 );
|
694
|
+
rb_define_singleton_method( rant_mAnt, "request_advanced_burst_capabilities",
|
695
|
+
rant_s_request_advanced_burst_capabilities, 0 );
|
696
|
+
|
524
697
|
rb_define_singleton_method( rant_mAnt, "log_directory=", rant_s_log_directory_eq, 1 );
|
525
698
|
|
526
699
|
|
@@ -536,6 +709,7 @@ Init_ant_ext()
|
|
536
709
|
EXPOSE_CONST( ANT_EXT_STRING_SIZE );
|
537
710
|
EXPOSE_CONST( ANT_EXT_MESG_BITFIELD_DEVICE_ID );
|
538
711
|
EXPOSE_CONST( ANT_EXT_MESG_BIFIELD_EXTENSION );
|
712
|
+
rb_define_const( rant_mAnt, "ANT_EXT_MESG_BITFIELD_EXTENSION", INT2FIX(ANT_EXT_MESG_BIFIELD_EXTENSION) );
|
539
713
|
EXPOSE_CONST( ANT_EXT_MESG_BITFIELD_OVERWRITE_SHARED_ADR );
|
540
714
|
EXPOSE_CONST( ANT_EXT_MESG_BITFIELD_TRANSMISSION_TYPE );
|
541
715
|
|
@@ -617,6 +791,9 @@ Init_ant_ext()
|
|
617
791
|
EXPOSE_CONST( CAPABILITIES_SELECTIVE_DATA_UPDATE_ENABLED );
|
618
792
|
EXPOSE_CONST( CAPABILITIES_ENCRYPTED_CHANNEL_ENABLED );
|
619
793
|
|
794
|
+
// Not in the header; this is taken from 9.5.7.4, ANT Message Protocol and Usage v5.1
|
795
|
+
rb_define_const( rant_mAnt, "CAPABILITIES_RFACTIVE_NOTIFICATION_ENABLED", INT2FIX(0) );
|
796
|
+
|
620
797
|
EXPOSE_CONST( CHANNEL_NUMBER_MASK );
|
621
798
|
EXPOSE_CONST( SEQUENCE_NUMBER_MASK );
|
622
799
|
EXPOSE_CONST( SEQUENCE_NUMBER_ROLLOVER );
|
data/ext/ant_ext/channel.c
CHANGED
@@ -9,6 +9,9 @@
|
|
9
9
|
|
10
10
|
#include "ant_ext.h"
|
11
11
|
|
12
|
+
#define DEFAULT_ADV_PACKETS 3
|
13
|
+
#define ADVANCED_BURST_TIMEOUT 5
|
14
|
+
|
12
15
|
VALUE rant_cAntChannel;
|
13
16
|
|
14
17
|
VALUE rant_mAntDataUtilities;
|
@@ -128,6 +131,12 @@ rant_channel_init( VALUE self, VALUE channel_number, VALUE channel_type, VALUE n
|
|
128
131
|
rb_iv_set( self, "@network_number", network_number );
|
129
132
|
rb_iv_set( self, "@extended_options", extended_options );
|
130
133
|
|
134
|
+
rb_iv_set( self, "@device_type", Qnil );
|
135
|
+
rb_iv_set( self, "@device_number", Qnil );
|
136
|
+
rb_iv_set( self, "@transmission_type", Qnil );
|
137
|
+
rb_iv_set( self, "@rf_frequency", Qnil );
|
138
|
+
rb_iv_set( self, "@agility_frequencies", Qnil );
|
139
|
+
|
131
140
|
rb_hash_aset( registry, channel_number, self );
|
132
141
|
|
133
142
|
return self;
|
@@ -173,8 +182,8 @@ rant_channel_set_channel_id( int argc, VALUE *argv, VALUE self )
|
|
173
182
|
rb_scan_args( argc, argv, "31", &device_number, &device_type, &transmission_type, &timeout );
|
174
183
|
|
175
184
|
usDeviceNumber = NUM2USHORT( device_number );
|
176
|
-
ucDeviceType =
|
177
|
-
ucTransmissionType =
|
185
|
+
ucDeviceType = NUM2CHR( device_type );
|
186
|
+
ucTransmissionType = NUM2CHR( transmission_type );
|
178
187
|
|
179
188
|
if ( RTEST(timeout) )
|
180
189
|
ulResponseTime = NUM2UINT( timeout );
|
@@ -186,13 +195,147 @@ rant_channel_set_channel_id( int argc, VALUE *argv, VALUE self )
|
|
186
195
|
rb_raise( rb_eRuntimeError, "Failed to set the channel id." );
|
187
196
|
}
|
188
197
|
|
198
|
+
rb_iv_set( self, "@device_type", device_type );
|
199
|
+
rb_iv_set( self, "@device_number", device_number );
|
200
|
+
rb_iv_set( self, "@transmission_type", transmission_type );
|
201
|
+
|
202
|
+
return Qtrue;
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
/*
|
207
|
+
* call-seq:
|
208
|
+
* channel.set_channel_period( period, timeout=0 )
|
209
|
+
*
|
210
|
+
* This message configures the messaging +period+ of a specific channel where:
|
211
|
+
* Messaging period = channel period time +period+ * 32768.
|
212
|
+
*
|
213
|
+
* E.g.: To send or receive a message at 4Hz, set the channel period to 8192 (32768/4).
|
214
|
+
*
|
215
|
+
* Note: The minimum acceptable channel period is difficult to specify as it is
|
216
|
+
* system dependent and depends on the number of configured channels and their use.
|
217
|
+
* Caution should be used to appropriately test the system when high data rates are
|
218
|
+
* used, especially in combination with multiple channels.
|
219
|
+
*
|
220
|
+
*/
|
221
|
+
static VALUE
|
222
|
+
rant_channel_set_channel_period( int argc, VALUE *argv, VALUE self )
|
223
|
+
{
|
224
|
+
rant_channel_t *ptr = rant_get_channel( self );
|
225
|
+
VALUE period, timeout;
|
226
|
+
unsigned int ulResponseTime = 0;
|
227
|
+
unsigned short usMesgPeriod;
|
228
|
+
bool result;
|
229
|
+
|
230
|
+
rb_scan_args( argc, argv, "11", &period, &timeout );
|
231
|
+
|
232
|
+
usMesgPeriod = NUM2USHORT( period );
|
233
|
+
if ( RTEST(timeout) )
|
234
|
+
ulResponseTime = NUM2UINT( timeout );
|
235
|
+
|
236
|
+
result = ANT_SetChannelPeriod_RTO( ptr->channel_num, usMesgPeriod, ulResponseTime );
|
237
|
+
|
238
|
+
if ( !result )
|
239
|
+
rb_raise( rb_eRuntimeError, "Failed to set the channel period." );
|
240
|
+
|
241
|
+
return Qtrue;
|
242
|
+
}
|
243
|
+
|
244
|
+
|
245
|
+
/*
|
246
|
+
* call-seq:
|
247
|
+
* channel.set_channel_search_timeout( search_timeout, timeout=0 )
|
248
|
+
*
|
249
|
+
* Configure the length of time that the receiver will search for a channel
|
250
|
+
* before timing out. Note that a value of zero will disable high priority
|
251
|
+
* search mode, and a value of 255 sets an infinite search time-out. The
|
252
|
+
* exception to this is the AP1 module, which has only a high priority search
|
253
|
+
* mode. For AP1 only, a value of 0 is an immediate search timeout, and a value
|
254
|
+
* of 255 corresponds to approximately 10.5 minutes.
|
255
|
+
*
|
256
|
+
*/
|
257
|
+
static VALUE
|
258
|
+
rant_channel_set_channel_search_timeout( int argc, VALUE *argv, VALUE self )
|
259
|
+
{
|
260
|
+
rant_channel_t *ptr = rant_get_channel( self );
|
261
|
+
VALUE search_timeout, timeout;
|
262
|
+
unsigned int ulResponseTime = 0;
|
263
|
+
unsigned char ucSearchTimeout;
|
264
|
+
bool result;
|
265
|
+
|
266
|
+
rb_scan_args( argc, argv, "11", &search_timeout, &timeout );
|
267
|
+
|
268
|
+
ucSearchTimeout = NUM2CHR( search_timeout );
|
269
|
+
if ( RTEST(timeout) )
|
270
|
+
ulResponseTime = NUM2UINT( timeout );
|
271
|
+
|
272
|
+
result = ANT_SetChannelSearchTimeout_RTO( ptr->channel_num, ucSearchTimeout, ulResponseTime );
|
273
|
+
|
274
|
+
if ( !result )
|
275
|
+
rb_raise( rb_eRuntimeError, "Failed to set the channel search timeout." );
|
276
|
+
|
277
|
+
return Qtrue;
|
278
|
+
}
|
279
|
+
|
280
|
+
|
281
|
+
/*
|
282
|
+
* call-seq:
|
283
|
+
* channel.set_channel_rf_freq( frequency )
|
284
|
+
*
|
285
|
+
* Set the ANT RF +frequency+.
|
286
|
+
*
|
287
|
+
*/
|
288
|
+
static VALUE
|
289
|
+
rant_channel_set_channel_rf_freq( VALUE self, VALUE frequency )
|
290
|
+
{
|
291
|
+
rant_channel_t *ptr = rant_get_channel( self );
|
292
|
+
unsigned short ucRFFreq = NUM2USHORT( frequency );
|
293
|
+
|
294
|
+
if ( ucRFFreq > 124 ) {
|
295
|
+
rb_raise( rb_eArgError, "frequency must be between 0 and 124." );
|
296
|
+
}
|
297
|
+
|
298
|
+
ANT_SetChannelRFFreq( ptr->channel_num, ucRFFreq );
|
299
|
+
|
300
|
+
rb_iv_set( self, "@rf_frequency", frequency );
|
301
|
+
|
302
|
+
return Qtrue;
|
303
|
+
}
|
304
|
+
|
305
|
+
|
306
|
+
/*
|
307
|
+
* call-seq:
|
308
|
+
* channel.set_frequency_agility( freq1, freq2, freq3 )
|
309
|
+
*
|
310
|
+
* Set the frequencies to use in frequency agility (integers between 0 and 124). These values
|
311
|
+
* use the same convention as the +rf_frequency+ setting; i.e., they're offsets from 2400 MHz.
|
312
|
+
*
|
313
|
+
*/
|
314
|
+
static VALUE
|
315
|
+
rant_channel_set_frequency_agility( VALUE self, VALUE freq1, VALUE freq2, VALUE freq3 )
|
316
|
+
{
|
317
|
+
rant_channel_t *ptr = rant_get_channel( self );
|
318
|
+
unsigned char ucFreq1 = NUM2CHR( freq1 ),
|
319
|
+
ucFreq2 = NUM2CHR( freq2 ),
|
320
|
+
ucFreq3 = NUM2CHR( freq3 );
|
321
|
+
VALUE frequencies = rb_ary_new_from_args( 3, freq1, freq2, freq3 );
|
322
|
+
|
323
|
+
if ( ucFreq1 > 124 || ucFreq2 > 124 || ucFreq3 > 124 ) {
|
324
|
+
rb_raise( rb_eArgError, "frequencies must be between 0 and 124." );
|
325
|
+
}
|
326
|
+
|
327
|
+
rant_log_obj( self, "info",
|
328
|
+
"Configuring channel %d to use frequency agility on %d, %d, and %d MHz.",
|
329
|
+
ptr->channel_num, ucFreq1 + 2400, ucFreq2 + 2400, ucFreq3 + 2400 );
|
330
|
+
ANT_ConfigFrequencyAgility( ptr->channel_num, ucFreq1, ucFreq2, ucFreq3 );
|
331
|
+
|
332
|
+
rb_ary_freeze( frequencies );
|
333
|
+
rb_iv_set( self, "@agility_frequencies", frequencies );
|
334
|
+
|
189
335
|
return Qtrue;
|
190
336
|
}
|
191
337
|
|
192
338
|
|
193
|
-
// ANT_SetChannelPeriod_RTO(UCHAR ucANTChannel_, USHORT usMesgPeriod_, ULONG ulResponseTime_);
|
194
|
-
// ANT_SetChannelSearchTimeout_RTO(UCHAR ucANTChannel_, UCHAR ucSearchTimeout_, ULONG ulResponseTime_);
|
195
|
-
// ANT_SetChannelRFFreq_RTO(UCHAR ucANTChannel_, UCHAR ucRFFreq_, ULONG ulResponseTime_);
|
196
339
|
|
197
340
|
|
198
341
|
/*
|
@@ -452,24 +595,56 @@ rant_channel_send_broadcast_data( VALUE self, VALUE data )
|
|
452
595
|
|
453
596
|
/*
|
454
597
|
* call-seq:
|
455
|
-
* channel.
|
598
|
+
* channel.send_advanced_transfer( data, packets_per_message=3 )
|
456
599
|
*
|
457
|
-
*
|
600
|
+
* Send the given +data+ as one or more advanced burst packets. The +packets_per_message+
|
601
|
+
* may be set to a value between 1 and 3 to control how many 8-byte packets are send with
|
602
|
+
* each message.
|
458
603
|
*
|
459
604
|
*/
|
460
605
|
static VALUE
|
461
|
-
|
606
|
+
rant_channel_send_advanced_transfer( int argc, VALUE *argv, VALUE self )
|
462
607
|
{
|
608
|
+
#ifdef HAVE_ANT_SENDADVANCEDBURST
|
463
609
|
rant_channel_t *ptr = rant_get_channel( self );
|
464
|
-
|
610
|
+
VALUE data = Qnil, packets = Qnil;
|
611
|
+
unsigned char *data_s;
|
612
|
+
long data_len;
|
613
|
+
unsigned short usNumDataPackets, remainingBytes;
|
614
|
+
unsigned char ucStdPcktsPerSerialMsg = DEFAULT_ADV_PACKETS;
|
615
|
+
|
616
|
+
rb_scan_args( argc, argv, "11", &data, &packets );
|
617
|
+
data_len = RSTRING_LEN( data );
|
618
|
+
usNumDataPackets = data_len / 8;
|
619
|
+
remainingBytes = data_len % 8;
|
620
|
+
if ( RTEST(packets) ) {
|
621
|
+
ucStdPcktsPerSerialMsg = NUM2CHR(packets);
|
622
|
+
}
|
465
623
|
|
466
|
-
|
467
|
-
|
624
|
+
data_s = ALLOC_N( unsigned char, data_len );
|
625
|
+
strncpy( (char *)data_s, StringValuePtr(data), data_len );
|
626
|
+
|
627
|
+
// Pad it to 8-byte alignment
|
628
|
+
if ( remainingBytes ) {
|
629
|
+
int pad_bytes = (8 - remainingBytes);
|
630
|
+
REALLOC_N( data_s, unsigned char, data_len + pad_bytes );
|
631
|
+
memset( data_s + data_len, 0, pad_bytes );
|
632
|
+
|
633
|
+
usNumDataPackets += 1;
|
468
634
|
}
|
469
635
|
|
470
|
-
|
636
|
+
rant_log_obj( self, "warn", "Sending advanced burst packets (%d-byte messages): %s",
|
637
|
+
ucStdPcktsPerSerialMsg * 8, data_s );
|
638
|
+
if ( !ANT_SendAdvancedBurst_RTO(ptr->channel_num, data_s, usNumDataPackets,
|
639
|
+
ucStdPcktsPerSerialMsg, ADVANCED_BURST_TIMEOUT) )
|
640
|
+
{
|
641
|
+
rant_log_obj( self, "error", "failed to send advanced burst transfer." );
|
642
|
+
}
|
471
643
|
|
472
644
|
return Qtrue;
|
645
|
+
#else
|
646
|
+
rb_notimplement();
|
647
|
+
#endif
|
473
648
|
}
|
474
649
|
|
475
650
|
|
@@ -501,12 +676,18 @@ init_ant_channel()
|
|
501
676
|
rb_attr( rant_cAntChannel, rb_intern("network_number"), 1, 0, 0 );
|
502
677
|
rb_attr( rant_cAntChannel, rb_intern("extended_options"), 1, 0, 0 );
|
503
678
|
|
679
|
+
rb_attr( rant_cAntChannel, rb_intern("device_number"), 1, 0, 0 );
|
680
|
+
rb_attr( rant_cAntChannel, rb_intern("device_type"), 1, 0, 0 );
|
681
|
+
rb_attr( rant_cAntChannel, rb_intern("transmission_type"), 1, 0, 0 );
|
682
|
+
rb_attr( rant_cAntChannel, rb_intern("rf_frequency"), 1, 0, 0 );
|
683
|
+
rb_attr( rant_cAntChannel, rb_intern("agility_frequencies"), 1, 0, 0 );
|
684
|
+
|
504
685
|
rb_define_method( rant_cAntChannel, "set_channel_id", rant_channel_set_channel_id, -1 );
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
// rant_channel_set_channel_search_timeout, -1 );
|
686
|
+
rb_define_method( rant_cAntChannel, "set_channel_period", rant_channel_set_channel_period, -1 );
|
687
|
+
rb_define_method( rant_cAntChannel, "set_channel_search_timeout",
|
688
|
+
rant_channel_set_channel_search_timeout, -1 );
|
509
689
|
rb_define_method( rant_cAntChannel, "set_channel_rf_freq", rant_channel_set_channel_rf_freq, 1 );
|
690
|
+
rb_define_method( rant_cAntChannel, "set_frequency_agility", rant_channel_set_frequency_agility, 3 );
|
510
691
|
|
511
692
|
rb_define_method( rant_cAntChannel, "open", rant_channel_open, -1 );
|
512
693
|
rb_define_method( rant_cAntChannel, "close", rant_channel_close, -1 );
|
@@ -515,6 +696,7 @@ init_ant_channel()
|
|
515
696
|
rb_define_method( rant_cAntChannel, "send_burst_transfer", rant_channel_send_burst_transfer, 1 );
|
516
697
|
rb_define_method( rant_cAntChannel, "send_acknowledged_data", rant_channel_send_acknowledged_data, 1 );
|
517
698
|
rb_define_method( rant_cAntChannel, "send_broadcast_data", rant_channel_send_broadcast_data, 1 );
|
699
|
+
rb_define_method( rant_cAntChannel, "send_advanced_transfer", rant_channel_send_advanced_transfer, -1 );
|
518
700
|
|
519
701
|
rb_define_method( rant_cAntChannel, "on_event", rant_channel_on_event, -1 );
|
520
702
|
|
data/ext/ant_ext/extconf.rb
CHANGED
@@ -14,9 +14,19 @@ have_header( 'ruby/thread.h' ) or
|
|
14
14
|
abort "Your Ruby is too old!"
|
15
15
|
|
16
16
|
have_func( 'ANT_Init', 'libant.h' )
|
17
|
+
have_func( 'ANT_IsInitialized', 'libant.h' )
|
17
18
|
have_func( 'ANT_LibVersion', 'libant.h' )
|
18
19
|
have_func( 'ANT_GetDeviceSerialNumber', 'libant.h' )
|
19
20
|
|
21
|
+
# Look for a custom advanced burst function, as the official SDK has it in the
|
22
|
+
# header but doesn't actually implement it.
|
23
|
+
have_func( 'ANT_SendAdvancedBurst', 'libant.h' )
|
24
|
+
|
25
|
+
# Ref: https://bugs.ruby-lang.org/issues/17865
|
26
|
+
$CPPFLAGS << " -Wno-compound-token-split-by-macro "
|
27
|
+
|
28
|
+
$CFLAGS << " -g "
|
29
|
+
|
20
30
|
create_header()
|
21
31
|
create_makefile( 'ant_ext' )
|
22
32
|
|