ant-wireless 0.1.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|