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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60dd8cb782d7e1f500a55f7cd80b77fb2fcd3d9a58388a5e2fdff25ee5c70e2c
4
- data.tar.gz: e9c54e26b412c78b10d42a3d6df532b0e58ddab7775146602b38d52ae119e5aa
3
+ metadata.gz: 1cbf09bffd2b5ac2d18ea9fb271bb1e358707b45a49bd45651129d5030598e95
4
+ data.tar.gz: f2d892f9c17f352e81b1b6236ac567a62f24b61495860b0f071975bd80446ea8
5
5
  SHA512:
6
- metadata.gz: 50f34e579557e981f7f63610dedc06959ab1109e30a65e2d34d2fd33cc29f00c5ac955785e47e7d2b7c912e13999aedeaa0c961a5505b560d0d7e7092f3eb4d0
7
- data.tar.gz: 2a3892e482b4173861a1c61c3b194589e14baa6c9d440b02004d8e519c388a88bbc527d3192fe769a36d48dad3d54f4c9bb0f6fce08a9e9cb00876a9684fc0d2
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 are currently using a modified version of it with a reworked build system for MacOS and FreeBSD. That is available under the same licensing terms at:
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
+
@@ -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
- rb_raise( rb_eRuntimeError, "could not set the network key." );
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 );
@@ -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 = NUM2USHORT( device_type );
177
- ucTransmissionType = NUM2USHORT( transmission_type );
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.set_channel_rf_freq( frequency )
598
+ * channel.send_advanced_transfer( data, packets_per_message=3 )
456
599
  *
457
- * Set the ANT RF +frequency+.
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
- rant_channel_set_channel_rf_freq( VALUE self, VALUE frequency )
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
- unsigned short ucRFFreq = NUM2USHORT( frequency );
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
- if ( ucRFFreq > 124 ) {
467
- rb_raise( rb_eArgError, "frequency must be between 0 and 124." );
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
- ANT_SetChannelRFFreq( ptr->channel_num, ucRFFreq );
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
- // rb_define_method( rant_cAntChannel, "set_channel_period",
506
- // rant_channel_set_channel_period, -1 );
507
- // rb_define_method( rant_cAntChannel, "set_channel_search_timeout",
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
 
@@ -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