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 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