ANT_Device.cs 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982
  1. /*
  2. This software is subject to the license described in the License.txt file
  3. included with this software distribution. You may not use this file except
  4. in compliance with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2016
  6. All rights reserved.
  7. */
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Runtime.InteropServices;
  13. using System.Management;
  14. namespace ANT_Managed_Library
  15. {
  16. /// <summary>
  17. /// Control class for a given ANT device. An instance of this class is an open connection to the given ANT USB device.
  18. /// Handles creating channels and device setup.
  19. /// </summary>
  20. public class ANT_Device : IDisposable
  21. {
  22. #region variables
  23. ANT_ReferenceLibrary.FramerType frameType;
  24. ANT_ReferenceLibrary.PortType portType;
  25. IntPtr unmanagedANTSerialPtr = IntPtr.Zero;
  26. IntPtr unmanagedANTFramerPtr = IntPtr.Zero;
  27. IntPtr unmanagedCancelBool = IntPtr.Zero; //The bool type def in the unmanaged code is an int, so 4 bytes
  28. bool? cancelTxFlag //Handles accessing the unmanged bool as a normal nullable bool
  29. {
  30. get
  31. {
  32. if(unmanagedCancelBool == IntPtr.Zero)
  33. return null;
  34. return Convert.ToBoolean(Marshal.ReadInt32(unmanagedCancelBool));
  35. }
  36. set //TODO: Should we send out a deviceNotification when this occurs?
  37. {
  38. if (unmanagedCancelBool != IntPtr.Zero)
  39. Marshal.WriteInt32(unmanagedCancelBool, Convert.ToInt32(value));
  40. }
  41. }
  42. bool initializedUSB = false;
  43. byte USBDeviceNum = 255; //Device num of instance
  44. uint USBBaudRate = 0;
  45. ANT_DeviceCapabilities capabilities = null;
  46. bool pollingOn;
  47. int numDeviceChannels;
  48. ANT_Channel[] antChannels;
  49. #endregion
  50. #region DeviceCallback variables
  51. //This struct is used by the unmanaged code to pass response messages
  52. [StructLayout(LayoutKind.Sequential)]
  53. struct ANTMessageItem
  54. {
  55. public byte dataSize;
  56. public ANTMessage antMsgData;
  57. }
  58. /// <summary>
  59. /// ANTMessage struct as defined in unmanaged code for marshalling ant messages with unmanaged code
  60. /// </summary>
  61. [StructLayout(LayoutKind.Sequential)]
  62. public struct ANTMessage
  63. {
  64. /// <summary>
  65. /// Message ID byte
  66. /// </summary>
  67. public byte msgID;
  68. /// <summary>
  69. /// Data buffer
  70. /// </summary>
  71. [MarshalAs(UnmanagedType.ByValArray, SizeConst = ANT_ReferenceLibrary.MAX_MESG_SIZE)] //We have to make sure the marshalling knows the unmanaged equivalent is a fixed array of the maximum ANT message size
  72. public byte[] ucharBuf; //The size of this should match the SizeConst
  73. }
  74. /// <summary>
  75. /// Codes for the device notification event
  76. /// </summary>
  77. public enum DeviceNotificationCode : byte
  78. {
  79. /// <summary>
  80. /// The device is being reset
  81. /// </summary>
  82. Reset = 0x01,
  83. /// <summary>
  84. /// The device is being shutdown
  85. /// </summary>
  86. Shutdown = 0x02,
  87. }
  88. System.Threading.Thread responsePoller; //This thread is in charge of monitoring the device for new messages and forwards them to the appropriate handler function
  89. /// <summary>
  90. /// Delegate for device response event
  91. /// </summary>
  92. /// <param name="response">Message details received from device</param>
  93. public delegate void dDeviceResponseHandler(ANT_Response response); //The delegate for the managed callback functions
  94. /// <summary>
  95. /// The channel callback event. Triggered every time a message is received from the ANT device.
  96. /// Examples include requested responses and setup status messages.
  97. /// </summary>
  98. public event dDeviceResponseHandler deviceResponse; //The event to assign callback functions to in a managed application
  99. /// <summary>
  100. /// Function to handle ANT_Device serial errors
  101. /// </summary>
  102. /// <param name="sender">The ANT_Device reporting the error</param>
  103. /// <param name="error">The serial error that occured</param>
  104. /// <param name="isCritical">If true, the communication with the device is lost and this device object should be disposed</param>
  105. public delegate void dSerialErrorHandler(ANT_Device sender, serialErrorCode error, bool isCritical); //The delegate for the serialError callback function
  106. /// <summary>
  107. /// This event is triggered when there is a serial communication error with the ANT Device.
  108. /// If the error is critical all communication with the device is dead and the
  109. /// device reference is sent in this function to allow the application
  110. /// to know which device is dead and to dispose of it.
  111. /// </summary>
  112. public event dSerialErrorHandler serialError;
  113. /// <summary>
  114. /// ANT Device Serial Error Codes
  115. /// </summary>
  116. public enum serialErrorCode
  117. {
  118. /// <summary>
  119. /// A write command to the device failed, could be a usb communication issue or due to invalid paramters passed to the write function.
  120. /// If it is a device communication failure, a serial read error will most likely occur shortly.
  121. /// </summary>
  122. SerialWriteError,
  123. /// <summary>
  124. /// A failure occured reading data from the device.
  125. /// </summary>
  126. SerialReadError,
  127. /// <summary>
  128. /// Communication with the device has been lost.
  129. /// </summary>
  130. DeviceConnectionLost,
  131. /// <summary>
  132. /// A message received by the device failed the crc check and was discarded.
  133. /// </summary>
  134. MessageLost_CrcError,
  135. /// <summary>
  136. /// The message queue for received messages has overflowed and one or more messages were lost.
  137. /// </summary>
  138. MessageLost_QueueOverflow,
  139. /// <summary>
  140. /// A message received was over the maximum message size, and the message was discarded.
  141. /// This is usually due to a communication error or an error in the library or library compilation settings.
  142. /// </summary>
  143. MessageLost_TooLarge,
  144. /// <summary>
  145. /// A channel event was received for a channel which does not exist and the message was dropped (but will still appear in the logs)
  146. /// </summary>
  147. MessageLost_InvalidChannel,
  148. /// <summary>
  149. /// Unspecified error, most likely a new or changed error definition
  150. /// </summary>
  151. Unknown
  152. }
  153. #endregion
  154. #region ANT_DLL Imports
  155. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  156. private static extern int ANT_Init(byte ucUSBDeviceNum, UInt32 usBaudrate, ref IntPtr returnSerialPtr, ref IntPtr returnFramerPtr, byte ucPortType, byte ucHCIFrameTpye);
  157. //Note: Before uncommenting this read todo comment on constructor, we don't use this now because we want to know the device number we opened
  158. //[DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  159. //private static extern int ANT_AutoInit(ref IntPtr returnSerialPtr, ref IntPtr returnFramerPtr);
  160. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  161. private static extern void ANT_Close(IntPtr SerialPtr, IntPtr FramerPtr);
  162. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  163. private static extern int ANT_USBReset(IntPtr SerialPtr);
  164. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  165. private static extern int ANT_ResetSystem(IntPtr FramerPtr, UInt32 ulResponseTime_);
  166. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  167. private static extern void ANT_SetCancelParameter(IntPtr FramerPtr, IntPtr pbCancel);
  168. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetNetworkKey_RTO", CallingConvention=CallingConvention.Cdecl)]
  169. private static extern int ANT_SetNetworkKey(IntPtr FramerPtr, byte ucNetNumber, byte[] pucKey, UInt32 ulResponseTime_);
  170. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_EnableLED_RTO", CallingConvention=CallingConvention.Cdecl)]
  171. private static extern int ANT_EnableLED(IntPtr FramerPtr, byte ucEnable, UInt32 ulResponseTime_);
  172. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  173. private static extern int ANT_GetDeviceUSBPID(IntPtr FramerPtr, ref UInt16 usbPID);
  174. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  175. private static extern int ANT_GetDeviceUSBVID(IntPtr FramerPtr, ref UInt16 usbVID);
  176. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  177. private static extern int ANT_ConfigureSplitAdvancedBursts(IntPtr FramerPtr, int bEnabelSplitBursts);
  178. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_ConfigureAdvancedBurst_RTO", CallingConvention = CallingConvention.Cdecl)]
  179. private static extern int ANT_ConfigureAdvancedBurst(IntPtr FramerPtr, int enable, byte ucMaxPacketLength, UInt32 ulRequiredFields, UInt32 ulOptionalFields, UInt32 ulResponseTime_);
  180. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_ConfigureAdvancedBurst_ext_RTO", CallingConvention = CallingConvention.Cdecl)]
  181. private static extern int ANT_ConfigureAdvancedBurst_ext(IntPtr FramerPtr, int enable, byte ucMaxPacketLength, UInt32 ulRequiredFields, UInt32 ulOptionalFields, UInt16 usStallCount, byte ucRetryCount, UInt32 ulResponseTime_);
  182. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCryptoKey_RTO", CallingConvention = CallingConvention.Cdecl)]
  183. private static extern int ANT_SetCryptoKey(IntPtr FramerPtr, byte ucVolatileKeyIndex, byte[] pucKey, UInt32 ulResponseTime_);
  184. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCryptoID_RTO", CallingConvention = CallingConvention.Cdecl)]
  185. private static extern int ANT_SetCryptoID(IntPtr FramerPtr, byte[] pucData, UInt32 ulResponseTime_);
  186. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCryptoUserInfo_RTO", CallingConvention = CallingConvention.Cdecl)]
  187. private static extern int ANT_SetCryptoUserInfo(IntPtr FramerPtr, byte[] pucData, UInt32 ulResponseTime_);
  188. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCryptoRNGSeed_RTO", CallingConvention = CallingConvention.Cdecl)]
  189. private static extern int ANT_SetCryptoRNGSeed(IntPtr FramerPtr, byte[] pucData, UInt32 ulResponseTime_);
  190. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCryptoInfo_RTO", CallingConvention = CallingConvention.Cdecl)]
  191. private static extern int ANT_SetCryptoInfo(IntPtr FramerPtr, byte ucParameter, byte[] pucData, UInt32 ulResponseTime_);
  192. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_LoadCryptoKeyNVMOp_RTO", CallingConvention = CallingConvention.Cdecl)]
  193. private static extern int ANT_LoadCryptoKeyNVMOp(IntPtr FramerPtr, byte ucNVMKeyIndex, byte ucVolatileKeyIndex, UInt32 ulResponseTime_);
  194. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_StoreCryptoKeyNVMOp_RTO", CallingConvention = CallingConvention.Cdecl)]
  195. private static extern int ANT_StoreCryptoKeyNVMOp(IntPtr FramerPtr, byte ucNVMKeyIndex, byte[] pucKey, UInt32 ulResponseTime_);
  196. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_CryptoKeyNVMOp_RTO", CallingConvention = CallingConvention.Cdecl)]
  197. private static extern int ANT_CryptoKeyNVMOp(IntPtr FramerPtr, byte ucOperation, byte ucNVMKeyIndex, byte[] pucData, UInt32 ulResponseTime_);
  198. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  199. private static extern uint ANT_GetDeviceSerialNumber(IntPtr SerialPtr);
  200. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  201. private static extern int ANT_GetDeviceUSBInfo(IntPtr FramerPtr, byte ucDeviceNum_,
  202. [MarshalAs(UnmanagedType.LPArray)] byte[] pucProductString_,
  203. [MarshalAs(UnmanagedType.LPArray)] byte[] pucSerialString_);
  204. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetTransmitPower_RTO", CallingConvention=CallingConvention.Cdecl)]
  205. private static extern int ANT_SetTransmitPower(IntPtr FramerPtr, byte ucTransmitPower_, UInt32 ulResponseTime_);
  206. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  207. private static extern int ANT_ConfigEventFilter(IntPtr FramerPtr, UInt16 usFilter_, UInt32 ulResponseTime_);
  208. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  209. private static extern int ANT_ConfigEventBuffer(IntPtr FramerPtr, byte ucConfig_, UInt16 usSize_, UInt16 usTime_, UInt32 ulResponseTime_);
  210. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  211. private static extern int ANT_ConfigHighDutySearch(IntPtr FramerPtr, byte ucEnable_, byte ucSuppressionCycles_, UInt32 ulResponseTime_);
  212. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  213. private static extern int ANT_SetSelectiveDataUpdateMask(IntPtr FramerPtr, byte ucMaskNumber_, byte[] ucSduMask_, UInt32 ulResponseTime_);
  214. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  215. private static extern int ANT_ConfigUserNVM(IntPtr FramerPtr, UInt16 usAddress_, byte[] pucData_, byte ucSize_, UInt32 ulResponseTime_);
  216. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  217. private static extern int ANT_RequestMessage(IntPtr FramerPtr, byte ucANTChannel, byte ucMessageID, ref ANTMessageItem ANT_MESSAGE_ITEM_response, UInt32 ulResponseTime_);
  218. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  219. private static extern int ANT_RequestUserNvmMessage(IntPtr FramerPtr, byte ucANTChannel, byte ucMessageID, ref ANTMessageItem ANT_MESSAGE_ITEM_response, UInt16 usAddress, byte ucSize, UInt32 ulResponseTime_);
  220. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  221. private static extern UInt16 ANT_WaitForMessage(IntPtr FramerPtr, UInt32 ulMilliseconds_);
  222. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  223. private static extern UInt16 ANT_GetMessage(IntPtr FramerPtr, ref ANTMessage ANT_MESSAGE_response);
  224. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  225. private static extern byte ANT_GetChannelNumber(IntPtr FramerPtr, ref ANTMessage pstANTMessage);
  226. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  227. private static extern int ANT_GetCapabilities(IntPtr FramerPtr,
  228. [MarshalAs(UnmanagedType.LPArray)] byte[] pucCapabilities_,
  229. UInt32 ulResponseTime_);
  230. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_InitCWTestMode_RTO", CallingConvention = CallingConvention.Cdecl)]
  231. private static extern int ANT_InitCWTestMode(IntPtr FramerPtr, UInt32 ulResponseTime_);
  232. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_SetCWTestMode_RTO", CallingConvention=CallingConvention.Cdecl)]
  233. private static extern int ANT_SetCWTestMode(IntPtr FramerPtr, byte ucTransmitPower_, byte ucRFChannel_, UInt32 ulResponseTime_);
  234. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_OpenRxScanMode_RTO", CallingConvention=CallingConvention.Cdecl)]
  235. private static extern int ANT_OpenRxScanMode(IntPtr FramerPtr, UInt32 ulResponseTime_);
  236. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_Write_RTO", CallingConvention=CallingConvention.Cdecl)]
  237. private static extern int ANT_Script_Write(IntPtr FramerPtr, byte ucSize_, byte[] pucData_, UInt32 ulResponseTime_);
  238. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_Clear_RTO", CallingConvention=CallingConvention.Cdecl)]
  239. private static extern int ANT_Script_Clear(IntPtr FramerPtr, UInt32 ulResponseTime_);
  240. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_SetDefaultSector_RTO", CallingConvention=CallingConvention.Cdecl)]
  241. private static extern int ANT_Script_SetDefaultSector(IntPtr FramerPtr, byte ucSectNumber_, UInt32 ulResponseTime_);
  242. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_EndSector_RTO", CallingConvention=CallingConvention.Cdecl)]
  243. private static extern int ANT_Script_EndSector(IntPtr FramerPtr, UInt32 ulResponseTime_);
  244. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_Dump_RTO", CallingConvention=CallingConvention.Cdecl)]
  245. private static extern int ANT_Script_Dump(IntPtr FramerPtr, UInt32 ulResponseTime_);
  246. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_Script_Lock_RTO", CallingConvention=CallingConvention.Cdecl)]
  247. private static extern int ANT_Script_Lock(IntPtr FramerPtr, UInt32 ulResponseTimeout_);
  248. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "ANT_RxExtMesgsEnable_RTO", CallingConvention=CallingConvention.Cdecl)]
  249. private static extern int ANT_RxExtMesgsEnable(IntPtr FramerPtr, byte ucEnable_, UInt32 ulResponseTimeout_);
  250. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  251. private static extern int ANT_CrystalEnable(IntPtr FramerPtr, UInt32 ulResponseTime_);
  252. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  253. private static extern int ANT_WriteMessage(IntPtr FramerPtr, ANTMessage pstANTMessage, UInt16 usMessageSize);
  254. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention=CallingConvention.Cdecl)]
  255. private static extern int ANT_SetLibConfig(IntPtr FramerPtr, byte ucLibConfigFlags_, UInt32 ulResponseTime_);
  256. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "FIT_SetFEState_RTO", CallingConvention=CallingConvention.Cdecl)]
  257. private static extern int FIT_SetFEState(IntPtr FramerPtr, byte ucFEState_, UInt32 ulResponseTime_);
  258. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, EntryPoint = "FIT_AdjustPairingSettings_RTO", CallingConvention=CallingConvention.Cdecl)]
  259. private static extern int FIT_AdjustPairingSettings(IntPtr FramerPtr, byte ucSearchLv_, byte ucPairLv_, byte ucTrackLv_, UInt32 ulResponseTime_);
  260. #endregion
  261. #region Constructors and Destructor
  262. /// <overloads>
  263. /// Opens a connection to an ANT device attached by USB.
  264. /// Throws exception if a connection can not be established.
  265. /// </overloads>
  266. /// <summary>
  267. /// Attempts to open a connection to an ANT device attached by USB using the given deviceNum and baud rate
  268. /// Throws exception if a connection can not be established.
  269. /// </summary>
  270. /// <param name="USBDeviceNum">The device number of the ANT USB device (the first connected device starts at 0 and so on)</param>
  271. /// <param name="baudRate">The baud rate to connect at (AP2/AT3=57600, AP1=50000)</param>
  272. public ANT_Device(byte USBDeviceNum, uint baudRate)
  273. :this(ANT_ReferenceLibrary.PortType.USB, USBDeviceNum, baudRate, ANT_ReferenceLibrary.FramerType.basicANT)
  274. {
  275. }
  276. /// <overloads>
  277. /// Opens a connection to an ANT device attached by USB.
  278. /// Throws exception if a connection can not be established.
  279. /// </overloads>
  280. /// <summary>
  281. /// Attempts to open a connection to an ANT device attached by USB using the given deviceNum and baud rate
  282. /// Throws exception if a connection can not be established.
  283. /// </summary>
  284. /// <param name="portType">The type of connection to use when talking to the device</param>
  285. /// <param name="USBDeviceNum">If port type is USB, device number of the ANT USB device.
  286. /// If port type is COM this is the COM port number</param>
  287. /// <param name="baudRate">The baud rate to connect at (USB: AP2/AT3=57600, AP1=50000)</param>
  288. /// <param name="frameType">The framing method to use for the connection to the chip.
  289. /// Needed for multimode chips and currently only supported on COM connections.</param>
  290. public ANT_Device(ANT_ReferenceLibrary.PortType portType, byte USBDeviceNum, uint baudRate, ANT_ReferenceLibrary.FramerType frameType)
  291. {
  292. try
  293. {
  294. ANT_Common.checkUnmanagedLibrary(); // First check if the unmanaged library is there, otherwise, we cannot connect to ANT anyway
  295. startUp(USBDeviceNum, baudRate, frameType, portType, false); // Let exceptions propagate
  296. }
  297. catch
  298. {
  299. // If constructor throws an exception, release acquired resources and suppress finalization
  300. this.Dispose();
  301. throw;
  302. }
  303. }
  304. /// <summary>
  305. /// Automatically connects to first availiable ANTDevice.
  306. /// Throws exception if a connection can not be established.
  307. /// Will not auto find COM-connected devices.
  308. /// </summary>
  309. public ANT_Device() //TODO: Need to change this to use the c++ library auto open, so it will check device strings, etc. NOT as now where it could open any SI device...the problem is that currently if the autoinit is used the device number is not accessible which we want to keep for ANTWare II
  310. {
  311. ANT_Common.checkUnmanagedLibrary(); // First check if the unmanaged library is there, otherwise, we cannot connect to ANT anyway
  312. ulong numDevices = ANT_Common.getNumDetectedUSBDevices();
  313. if (numDevices == 0)
  314. {
  315. String detail = ": ensure an ANT device is connected to your system and try again";
  316. try
  317. {
  318. // If we cannot see any devices, it might be because of missing dependencies
  319. ANT_Common.checkUSBLibraries();
  320. }
  321. catch(ANT_Exception ex)
  322. {
  323. detail = ": " + ex.Message.Remove(0,21);
  324. }
  325. throw new ANT_Exception("No ANT devices detected" + detail);
  326. }
  327. bool fail = true;
  328. for (byte i = 0; i < numDevices && fail; ++i)
  329. {
  330. try
  331. {
  332. //Try 57600 baud first
  333. startUp(i, 57600, ANT_ReferenceLibrary.FramerType.basicANT, ANT_ReferenceLibrary.PortType.USB, true); //If this fails it will throw an exception, and we'll try 50000
  334. fail = false; //If no exception is thrown we are good to go
  335. }
  336. catch (Exception)
  337. {
  338. //Try 50000 baudRate then
  339. try
  340. {
  341. startUp(i, 50000, ANT_ReferenceLibrary.FramerType.basicANT, ANT_ReferenceLibrary.PortType.USB, true);
  342. fail = false; //If no exception is thrown we are good to go
  343. }
  344. catch (Exception)
  345. {
  346. fail = true; //Both baud rates failed
  347. }
  348. }
  349. }
  350. if (fail)
  351. {
  352. // If constructor throws an exception, release acquired resources and suppress finalization
  353. this.Dispose();
  354. throw new ANT_Exception("Failed to connect to any ANT devices");
  355. }
  356. }
  357. //This is all the initialization, pulled out to this method so it could be called by both constructors
  358. private void startUp(byte USBDeviceNum, uint baudRate, ANT_ReferenceLibrary.FramerType frameType, ANT_ReferenceLibrary.PortType portType, bool calledByAutoInit)
  359. {
  360. // The SI libraries are not required for USB2, so attempt to connect first and only throw an
  361. // exception if this fails.
  362. int ret = ANT_Init(USBDeviceNum, baudRate, ref unmanagedANTSerialPtr, ref unmanagedANTFramerPtr, (byte)portType, (byte)frameType);
  363. if (ret != 0)
  364. {
  365. switch(ret)
  366. {
  367. case -1:
  368. throw new ANT_Exception("Unexpected init library error. This is typically a problem with the c++ library");
  369. case -2:
  370. throw new ANT_Exception("Unrecognized type parameters");
  371. case -3:
  372. if (!calledByAutoInit) //Auto-init checks only after checking all devices
  373. ANT_Common.checkUSBLibraries(); // throws exception if libraries are missing
  374. throw new ANT_Exception("Unable to initialize USB:" + USBDeviceNum + " at Baud:" + baudRate + ", probably device not present or already in use, or drivers not installed");
  375. default:
  376. throw new ANT_Exception("Unrecognized error code received from c++ library");
  377. }
  378. }
  379. initializedUSB = true; //Keep track of whether device is connected or not
  380. this.USBDeviceNum = USBDeviceNum; //Keep the parameters for reference
  381. this.USBBaudRate = baudRate;
  382. this.frameType = frameType;
  383. this.portType = portType;
  384. #if (ANTFS_DEBUGGING)
  385. //This logging is used in the ANT-FS libraries. Will not create any files if logging not enabled
  386. ANT_Common.initDebugLogThread("Device" + USBDeviceNum + "_Application");
  387. ANT_Common.ANT_DebugResetTime();
  388. ANT_Common.writeToDebugLog("ANT_NET.DLL " + ANT_VersionInfo.getManagedLibraryVersion() + " with ANT_WrappedLib.DLL " + ANT_VersionInfo.getUnmanagedLibraryVersion() + " - current unix time: " + (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
  389. #endif
  390. try
  391. {
  392. responsePoller = new System.Threading.Thread(responsePollFunc);
  393. responsePoller.Name = this.ToString() + " Receive Thread";
  394. responsePoller.IsBackground = true; //Make this a background thread so it will terminate when a program closes
  395. responsePoller.Start();
  396. //Get capabilities so we know how many channels we have
  397. //If this throws an exception it is probably connected at the wrong baud rate, so we send a descriptive exception
  398. try
  399. {
  400. getDeviceCapabilities(true, 200);
  401. }
  402. catch (ANT_Exception ex)
  403. {
  404. throw new ANT_Exception(ex.Message.Remove(0, 22) + ", probably connecting at wrong baud rate");
  405. }
  406. if(ANT_Common.autoResetIsEnabled)
  407. ANT_ResetSystem(unmanagedANTFramerPtr, 200); //Send a reset so by the time the user gets this handle the device is viable
  408. numDeviceChannels = capabilities.maxANTChannels;
  409. // Set up the channel list to the right size
  410. antChannels = new ANT_Channel[numDeviceChannels];
  411. unmanagedCancelBool = Marshal.AllocHGlobal(4);
  412. cancelTxFlag = false;
  413. ANT_SetCancelParameter(unmanagedANTFramerPtr, unmanagedCancelBool);
  414. }
  415. catch (Exception) // clean up
  416. {
  417. shutdown();
  418. throw; //Forward the error to caller
  419. }
  420. }
  421. /// <summary>
  422. /// Destructor closes all opened resources
  423. /// </summary>
  424. ~ANT_Device()
  425. {
  426. shutdown();
  427. }
  428. /// <summary>
  429. /// Dispose method for explicit resource cleanup. Same as shutdownDeviceInstance() but doesn't nullify reference.
  430. /// </summary>
  431. public void Dispose()
  432. {
  433. shutdown();
  434. GC.SuppressFinalize(this);
  435. }
  436. //This function cleans up all opened resources
  437. //This is accessed externally by calling Dispose()
  438. private void shutdown()
  439. {
  440. try
  441. {
  442. lock (this) //To prevent multiple threads calling shutdown concurrently...not sure why because none of our other code is really thread safe
  443. {
  444. if (initializedUSB) //if reference is already disposed, there is no cleanup to do
  445. {
  446. //Notify and Close the channels first
  447. if (antChannels != null)
  448. {
  449. NotifyDeviceEvent(DeviceNotificationCode.Shutdown, null);
  450. foreach (ANT_Channel i in antChannels)
  451. {
  452. //We dispose any channel references because since the c++ framer is being destroyed dereferencing it later will blow it up,
  453. //By disposing the channel the user will know from the ObjectDisposed exceptions instead of an undeterministic c++ explosion
  454. if (i != null)
  455. i.Dispose(); //Since this nullifies all the list references, it will stop all further feedback to the channels
  456. }
  457. }
  458. //Now shutdown all the device resources
  459. //Set cancel so if we are in a transfer it has a chance to shutdown gracefully
  460. cancelTxFlag = true;
  461. //Exit the response polling thread
  462. pollingOn = false;
  463. if (!responsePoller.Join(1500)) //Wait for the poll thread to terminate
  464. {
  465. responsePoller.Abort(); //Abort poll thread if it doesn't join
  466. System.Diagnostics.Debug.Fail("Response poll thread did not join in timeout and was aborted. Was the application slow/stalling, or should we increase the join timeout?");
  467. }
  468. //We call reset directly, because we don't care about notifying the mgd channels because we just closed them
  469. //If capabilities is null, it means init failed and we don't have an open line of communication to send a reset
  470. if (capabilities != null && ANT_Common.autoResetIsEnabled)
  471. ANT_ResetSystem(unmanagedANTFramerPtr, 0);
  472. //This is the most important part: clean up the big unmanged objects
  473. ANT_Close(unmanagedANTSerialPtr, unmanagedANTFramerPtr);
  474. if (unmanagedCancelBool != IntPtr.Zero)
  475. {
  476. Marshal.FreeHGlobal(unmanagedCancelBool);
  477. unmanagedCancelBool = IntPtr.Zero;
  478. }
  479. //Mark as disposed
  480. initializedUSB = false;
  481. }
  482. }
  483. }
  484. catch (Exception ex)
  485. {
  486. //Ignore all exceptions because this is only called on destruction or critical failure anyway
  487. System.Diagnostics.Debug.Fail("Exception on shutdown: " + ex.Message);
  488. }
  489. }
  490. /// <summary>
  491. /// Shuts down all open resources, calls reset on the physical device, and nullifies the given ANTDevice and all its channels
  492. /// </summary>
  493. /// <param name="deviceToShutdown">ANTDevice to shutdown</param>
  494. public static void shutdownDeviceInstance(ref ANT_Device deviceToShutdown)
  495. {
  496. if (deviceToShutdown != null)
  497. {
  498. deviceToShutdown.Dispose();
  499. deviceToShutdown = null;
  500. }
  501. }
  502. //Allows a disposed channel to nullify its list reference, so the next call to getChannel() can get a new un-disposed reference
  503. internal void channelDisposed(byte channelNumber)
  504. {
  505. antChannels[channelNumber] = null;
  506. }
  507. #endregion
  508. #region non-ANTdll Functions
  509. /// <summary>
  510. /// Convert instance to a string including the USB device number the connection is on
  511. /// </summary>
  512. public override string ToString()
  513. {
  514. return base.ToString()+ " on USBdeviceNum: " + USBDeviceNum.ToString();
  515. }
  516. /// <summary>
  517. /// Returns the pointer to the underlying C++ ANT Framer used for messaging
  518. /// </summary>
  519. /// <returns>Pointer to C++ ANT Framer</returns>
  520. internal IntPtr getFramerPtr()
  521. {
  522. if (!initializedUSB)
  523. throw new ObjectDisposedException("ANTDevice object has been disposed");
  524. return unmanagedANTFramerPtr;
  525. }
  526. /// <summary>
  527. /// Returns the device number used when this instance was opened
  528. /// Note: For some device types this number is not static and can change whenever new devices are enumerated in the system
  529. /// </summary>
  530. public int getOpenedUSBDeviceNum()
  531. {
  532. return USBDeviceNum;
  533. }
  534. /// <summary>
  535. /// Returns the baud rate used when this instance was opened
  536. /// </summary>
  537. public uint getOpenedUSBBaudRate()
  538. {
  539. return USBBaudRate;
  540. }
  541. /// <summary>
  542. /// Returns the Frame Type used to open the device
  543. /// </summary>
  544. public ANT_ReferenceLibrary.FramerType getOpenedFrameType()
  545. {
  546. return frameType;
  547. }
  548. /// <summary>
  549. /// Returns the Port Type used to open the device
  550. /// </summary>
  551. public ANT_ReferenceLibrary.PortType getOpenedPortType()
  552. {
  553. return portType;
  554. }
  555. /// <summary>
  556. /// Returns the requested ANTChannel or throws an exception if channel doesn't exist.
  557. /// </summary>
  558. /// <param name="num">Channel number requested</param>
  559. public ANT_Channel getChannel(int num)
  560. {
  561. if (!initializedUSB)
  562. throw new ObjectDisposedException("ANTDevice object has been disposed");
  563. if(num > antChannels.Length-1 || num < 0)
  564. throw new ANT_Exception("Channel number invalid");
  565. if(antChannels[num] == null)
  566. antChannels[num] = new ANT_Channel(this, (byte)num);
  567. return antChannels[num];
  568. }
  569. /// <summary>
  570. /// Returns the number of ANTChannels owned by this device
  571. /// </summary>
  572. /// <returns>Number of ant channels on device</returns>
  573. public int getNumChannels()
  574. {
  575. if (!initializedUSB)
  576. throw new ObjectDisposedException("ANTDevice object has been disposed");
  577. return antChannels.Length;
  578. }
  579. void NotifyDeviceEvent(DeviceNotificationCode notification, Object notificationInfo)
  580. {
  581. foreach (ANT_Channel i in antChannels)
  582. {
  583. if(i != null)
  584. i.NotifyDeviceEvent(notification, notificationInfo);
  585. }
  586. }
  587. private void responsePollFunc()
  588. {
  589. ushort messageSize = 0;
  590. byte channelNum;
  591. bool isMsgForChannel;
  592. pollingOn = true; //Set to false on shutdown to terminate the thread
  593. #if (ANTFS_DEBUGGING)
  594. ANT_Common.initDebugLogThread("Device" + USBDeviceNum + "_ANTReceive"); // We still need this for ANT-FS! Will not be created if debug disabled
  595. #endif
  596. while (initializedUSB && pollingOn) //check continuously; this thread is terminated on destruction of the class
  597. {
  598. // We only wait in the unmanged code for 100 ms because we want this thread to be responsive on our side.
  599. // It does mean that we are running through a lot more cycles than we need to
  600. messageSize = ANT_WaitForMessage(unmanagedANTFramerPtr, 100);
  601. if (messageSize == (ushort)0xFFFE) //DSI_FRAMER_TIMEDOUT
  602. continue; //Expected, just keep looping
  603. ANTMessage newMessage = new ANTMessage();
  604. messageSize = ANT_GetMessage(unmanagedANTFramerPtr, ref newMessage);
  605. if (messageSize == (ushort)0xFFFF) // DSI_FRAMER_ERROR - in current library could be from CRC error, Write error, Read error, or DeviceGone
  606. {
  607. serialErrorCode error;
  608. bool isCritical = false;
  609. switch(newMessage.msgID)
  610. {
  611. case 0x02: //DSI_FRAMER_ANT_ESERIAL
  612. switch(newMessage.ucharBuf[0])
  613. {
  614. case 0x04: //ESERIAL -> DSI_FRAMER_ANT_CRC_ERROR
  615. error = serialErrorCode.MessageLost_CrcError;
  616. break;
  617. case 0x02: //ESERIAL -> DSI_SERIAL_EWRITE
  618. error = serialErrorCode.SerialWriteError;
  619. break;
  620. case 0x03: //ESERIAL -> DSI_SERIAL_EREAD
  621. error = serialErrorCode.SerialReadError;
  622. isCritical = true;
  623. break;
  624. case 0x01: //ESERIAL -> DSI_SERIAL_DEVICE_GONE
  625. error = serialErrorCode.DeviceConnectionLost;
  626. isCritical = true;
  627. break;
  628. default:
  629. error = serialErrorCode.Unknown;
  630. System.Diagnostics.Debug.Fail("Unknown serial failure, why isn't this known?");
  631. break;
  632. }
  633. break;
  634. case 0x01: //DSI_FRAMER_ANT_EQUEUE_OVERFLOW
  635. error = serialErrorCode.MessageLost_QueueOverflow;
  636. break;
  637. case 0x03: //DSI_FRAMER_ANT_EINVALID_SIZE
  638. error = serialErrorCode.MessageLost_TooLarge;
  639. break;
  640. default:
  641. error = serialErrorCode.Unknown;
  642. System.Diagnostics.Debug.Fail("Unknown serial failure, why isn't this known?");
  643. break;
  644. }
  645. if(isCritical)
  646. {
  647. //System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(x => shutdown())); //Clean up all resources on another thread to allow this one to close cleanly
  648. pollingOn = false; //Just stop polling, since we will never get new messages now. Allow the user to dispose of the device.
  649. }
  650. //If application has subscribed to the event we can inform them
  651. if (serialError != null)
  652. serialError(this, error, isCritical);
  653. else //Debug.Fail is a no-op in release mode, so we will only see this in debugging, in release mode we don't want to do anything intrusive (ie:message box, exception)
  654. System.Diagnostics.Debug.Fail("Device Serial Communication Failure, HandleSerialError not handled by application");
  655. if (isCritical)
  656. break; //If the device is dead, exit the polling loop
  657. else
  658. continue;
  659. }
  660. isMsgForChannel = false;
  661. channelNum = Byte.MaxValue;
  662. switch (newMessage.msgID) //Check if we send to channel or protocol response func
  663. {
  664. // Send on Channel event
  665. case (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
  666. if (newMessage.ucharBuf[1] == (byte)ANT_ReferenceLibrary.ANTMessageID.EVENT_0x01)
  667. isMsgForChannel = true;
  668. break;
  669. // or any of the transmission events
  670. case (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E:
  671. case (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
  672. case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D:
  673. case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E:
  674. case (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50:
  675. case (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F:
  676. case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_BROADCAST_DATA_0xC1:
  677. case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_ACKNOWLEDGED_DATA_0xC2:
  678. case (byte)ANT_ReferenceLibrary.ANTMessageID.RSSI_BURST_DATA_0xC3:
  679. isMsgForChannel = true;
  680. break;
  681. }
  682. ANT_Response newResponse;
  683. //Now dispatch to appropriate event
  684. //The messages are buffered in the ant library so we just dispatch with current thread
  685. //then no matter how long the event call takes we still won't miss messages
  686. if (isMsgForChannel)
  687. {
  688. channelNum = (byte)(newMessage.ucharBuf[0] & 0x1F); //Mask out what channel this is for. [We can eventually switch to use the c++ code to determine the channel, but we should do it all together with getMessage to avoid extra marshalling and copying and remove the processing in C# above]
  689. if (antChannels != null && channelNum < antChannels.Length)
  690. {
  691. if (antChannels[channelNum] != null)
  692. antChannels[channelNum].MessageReceived(newMessage, messageSize);
  693. }
  694. else
  695. {
  696. if (serialError != null)
  697. serialError(this, serialErrorCode.MessageLost_InvalidChannel, false);
  698. }
  699. }
  700. else
  701. {
  702. newResponse = new ANT_Response(this, newMessage.ucharBuf[0], DateTime.Now, newMessage.msgID, newMessage.ucharBuf.Take(messageSize).ToArray());
  703. if (deviceResponse != null) //Ensure events are assigned before we call the event
  704. deviceResponse(newResponse);
  705. }
  706. }
  707. }
  708. /// <summary>
  709. /// Sets the cancel flag on all acknowledged and burst transfers in progress for the given amount of time.
  710. /// When these transmissions see the flag they will abort their operation and return as cancelled.
  711. /// </summary>
  712. /// <param name="cancelWaitTime">Time to set cancel flag for</param>
  713. public void cancelTransfers(int cancelWaitTime)
  714. {
  715. if (!initializedUSB)
  716. throw new ObjectDisposedException("ANTDevice object has been disposed");
  717. cancelTxFlag = true;
  718. System.Threading.Thread.Sleep(cancelWaitTime);
  719. cancelTxFlag = false;
  720. }
  721. /// <overloads>Returns the device capabilities</overloads>
  722. /// <summary>
  723. /// Returns the capabilities of this device.
  724. /// Throws an exception if capabilities are not received.
  725. /// </summary>
  726. /// <param name="forceNewCopy">Force function to send request message to device</param>
  727. /// <param name="responseWaitTime">Time to wait for device success response</param>
  728. /// <returns>Last device capabilities received or a new copy if forceNewCopy is true</returns>
  729. public ANT_DeviceCapabilities getDeviceCapabilities(bool forceNewCopy, UInt32 responseWaitTime)
  730. {
  731. if (!initializedUSB)
  732. throw new ObjectDisposedException("ANTDevice object has been disposed");
  733. if (forceNewCopy || capabilities == null)
  734. {
  735. try
  736. {
  737. ANT_DeviceCapabilities newCaps = null;
  738. ANT_Response response = requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.CAPABILITIES_0x54, responseWaitTime);
  739. if (response != null && response.responseID == (byte)ANT_ReferenceLibrary.RequestMessageID.CAPABILITIES_0x54)
  740. {
  741. byte[] padding = new byte[16 - response.messageContents.Length];
  742. newCaps = new ANT_DeviceCapabilities(response.messageContents.Concat(padding).ToArray());
  743. }
  744. capabilities = newCaps; //We replace the old capabilities because that is what forceNewCopy means
  745. }
  746. catch (Exception)
  747. {
  748. //If we timeout receiving the message or the interpretation fails
  749. throw new ANT_Exception("Retrieving Device Capabilities Failed");
  750. }
  751. }
  752. return capabilities;
  753. }
  754. /// <summary>
  755. /// Returns the device capabilities of this device.
  756. /// Throws an exception if capabilities are not received.
  757. /// </summary>
  758. public ANT_DeviceCapabilities getDeviceCapabilities() { return getDeviceCapabilities(false, 1500); }
  759. /// <summary>
  760. /// Returns the device capabilities of this device.
  761. /// Throws an exception if capabilities are not received.
  762. /// </summary>
  763. public ANT_DeviceCapabilities getDeviceCapabilities(UInt32 responseWaitTime) { return getDeviceCapabilities(false, responseWaitTime); }
  764. #endregion
  765. #region ANT Device Functions
  766. /// <overloads>Resets the USB device</overloads>
  767. /// <summary>
  768. /// Resets this USB device at the driver level
  769. /// </summary>
  770. public void ResetUSB()
  771. {
  772. if (portType != ANT_ReferenceLibrary.PortType.USB)
  773. throw new ANT_Exception("Can't call ResetUSB on non-USB devices");
  774. if (!initializedUSB)
  775. throw new ObjectDisposedException("ANTDevice object has been disposed");
  776. ANT_USBReset(unmanagedANTSerialPtr);
  777. }
  778. /// <overloads>Resets the device and all its channels</overloads>
  779. /// <summary>
  780. /// Reset this device and all associated channels
  781. /// </summary>
  782. /// <param name="responseWaitTime">Time to wait for device success response</param>
  783. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  784. public bool ResetSystem(UInt32 responseWaitTime)
  785. {
  786. if (!initializedUSB)
  787. throw new ObjectDisposedException("ANTDevice object has been disposed");
  788. // Notify channels
  789. NotifyDeviceEvent(DeviceNotificationCode.Reset, null);
  790. return (ANT_ResetSystem(unmanagedANTFramerPtr, responseWaitTime) == 1);
  791. }
  792. /// <summary>
  793. /// Reset this device and all associated channels
  794. /// </summary>
  795. public void ResetSystem(){ ResetSystem(500);}
  796. /// <overloads>Sets a network key</overloads>
  797. /// <summary>
  798. /// Set the network key for the given network
  799. /// Throws exception if net number is invalid or network key is not 8-bytes in length
  800. /// </summary>
  801. /// <param name="netNumber">The network number to set the key for</param>
  802. /// <param name="networkKey">The 8-byte network key</param>
  803. /// <param name="responseWaitTime">Time to wait for device success response</param>
  804. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  805. public bool setNetworkKey(byte netNumber, byte[] networkKey, UInt32 responseWaitTime)
  806. {
  807. if (!initializedUSB)
  808. throw new ObjectDisposedException("ANTDevice object has been disposed");
  809. if (capabilities != null)
  810. {
  811. if (netNumber >= capabilities.maxNetworks)
  812. throw new ANT_Exception("Network number must be less than the maximum capable networks of the device");
  813. }
  814. if (networkKey.Length != 8)
  815. throw new ANT_Exception("Network key must be 8 bytes");
  816. bool result = (ANT_SetNetworkKey(unmanagedANTFramerPtr, netNumber, networkKey, responseWaitTime) == 1);
  817. return result;
  818. }
  819. /// <summary>
  820. /// Set the network key for the given network
  821. /// Throws exception if net number is invalid or network key is not 8-bytes in length
  822. /// </summary>
  823. /// <param name="netNumber">The network number to set the key for</param>
  824. /// <param name="networkKey">The 8-byte network key</param>
  825. public void setNetworkKey(byte netNumber, byte[] networkKey) { setNetworkKey(netNumber, networkKey, 0); }
  826. /// <overloads>Sets the transmit power for all channels</overloads>
  827. /// <summary>
  828. /// Set the transmit power for all channels of this device
  829. /// </summary>
  830. /// <param name="transmitPower">Transmission power to set to</param>
  831. /// <param name="responseWaitTime">Time to wait for device success response</param>
  832. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  833. public bool setTransmitPowerForAllChannels(ANT_ReferenceLibrary.TransmitPower transmitPower, UInt32 responseWaitTime)
  834. {
  835. if (!initializedUSB)
  836. throw new ObjectDisposedException("ANTDevice object has been disposed");
  837. return (ANT_SetTransmitPower(unmanagedANTFramerPtr, (byte)transmitPower, responseWaitTime) == 1);
  838. }
  839. /// <summary>
  840. /// Set the transmit power for all channels of this device
  841. /// </summary>
  842. /// <param name="transmitPower">Transmission power to set to</param>
  843. public void setTransmitPowerForAllChannels(ANT_ReferenceLibrary.TransmitPower transmitPower) { setTransmitPowerForAllChannels(transmitPower, 0); }
  844. /// <summary>
  845. /// When enabled advanced burst messages will be split into standard burst packets when received.
  846. /// This is disabled by default.
  847. /// </summary>
  848. /// <param name="splitBursts">Whether to split advanced burst messages.</param>
  849. /// <returns>True on success.</returns>
  850. public bool configureAdvancedBurstSplitting(bool splitBursts)
  851. {
  852. if (!initializedUSB)
  853. throw new ObjectDisposedException("ANTDevice object has been disposed");
  854. return (ANT_ConfigureSplitAdvancedBursts(unmanagedANTFramerPtr, (splitBursts ? 1 : 0)) == 1);
  855. }
  856. /// <summary>
  857. /// Configure advanced bursting for this device.
  858. /// </summary>
  859. /// <param name="enable">Whether to enable advanced bursting messages</param>
  860. /// <param name="maxPacketLength">Maximum packet length allowed for bursting messages (valid values are 1-3)</param>
  861. /// <param name="requiredFields">Features that the application requires the device to use</param>
  862. /// <param name="optionalFields">Features that the device should use if it supports them</param>
  863. /// <param name="responseWaitTime">Time to wait for device success response</param>
  864. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  865. public bool configureAdvancedBursting(bool enable, byte maxPacketLength, ANT_ReferenceLibrary.AdvancedBurstConfigFlags requiredFields,
  866. ANT_ReferenceLibrary.AdvancedBurstConfigFlags optionalFields, UInt32 responseWaitTime)
  867. {
  868. if (!initializedUSB)
  869. throw new ObjectDisposedException("ANTDevice object has been disposed");
  870. return (ANT_ConfigureAdvancedBurst(unmanagedANTFramerPtr, (enable ? 1 : 0), maxPacketLength,
  871. (UInt32)requiredFields, (UInt32)optionalFields, responseWaitTime) == 1);
  872. }
  873. /// <summary>
  874. /// Configure advanced bursting for this device.
  875. /// </summary>
  876. /// <param name="enable">Whether to enable advanced bursting messages</param>
  877. /// <param name="maxPacketLength">Maximum packet length allowed for bursting messages (valid values are 1-3)</param>
  878. /// <param name="requiredFields">Features that the application requires the device to use</param>
  879. /// <param name="optionalFields">Features that the device should use if it supports them</param>
  880. public void configureAdvancedBursting(bool enable, byte maxPacketLength, ANT_ReferenceLibrary.AdvancedBurstConfigFlags requiredFields,
  881. ANT_ReferenceLibrary.AdvancedBurstConfigFlags optionalFields)
  882. {
  883. configureAdvancedBursting(enable, maxPacketLength, requiredFields, optionalFields, (UInt32)0);
  884. }
  885. /// <summary>
  886. /// Configure advanced bursting for this device including extended parameters.
  887. /// </summary>
  888. /// <param name="enable">Whether to enable advanced bursting messages</param>
  889. /// <param name="maxPacketLength">Maximum packet length allowed for bursting messages (valid values are 1-3)</param>
  890. /// <param name="requiredFields">Features that the application requires the device to use</param>
  891. /// <param name="optionalFields">Features that the device should use if it supports them</param>
  892. /// <param name="stallCount">Maximum number of burst periods (~3.1ms) to stall for while waiting for the next message</param>
  893. /// <param name="retryCount">Number of times (multiplied by 5) to retry burst</param>
  894. /// <param name="responseWaitTime">Time to wait for device success response</param>
  895. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  896. public bool configureAdvancedBursting_ext(bool enable, byte maxPacketLength, ANT_ReferenceLibrary.AdvancedBurstConfigFlags requiredFields,
  897. ANT_ReferenceLibrary.AdvancedBurstConfigFlags optionalFields, UInt16 stallCount, byte retryCount, UInt32 responseWaitTime)
  898. {
  899. if (!initializedUSB)
  900. throw new ObjectDisposedException("ANTDevice object has been disposed");
  901. return (ANT_ConfigureAdvancedBurst_ext(unmanagedANTFramerPtr, (enable ? 1 : 0), maxPacketLength,
  902. (UInt32)requiredFields, (UInt32)optionalFields, stallCount, retryCount, responseWaitTime) == 1);
  903. }
  904. /// <summary>
  905. /// Configure advanced bursting for this device including extended parameters.
  906. /// </summary>
  907. /// <param name="enable">Whether to enable advanced bursting messages</param>
  908. /// <param name="maxPacketLength">Maximum packet length allowed for bursting messages (valid values are 1-3)</param>
  909. /// <param name="requiredFields">Features that the application requires the device to use</param>
  910. /// <param name="optionalFields">Features that the device should use if it supports them</param>
  911. /// <param name="stallCount">Maximum number of burst periods (~3.1ms) to stall for while waiting for the next message</param>
  912. /// <param name="retryCount">Number of times (multiplied by 5) to retry burst</param>
  913. public void configureAdvancedBursting_ext(bool enable, byte maxPacketLength, ANT_ReferenceLibrary.AdvancedBurstConfigFlags requiredFields,
  914. ANT_ReferenceLibrary.AdvancedBurstConfigFlags optionalFields, UInt16 stallCount, byte retryCount)
  915. {
  916. configureAdvancedBursting_ext(enable, maxPacketLength, requiredFields, optionalFields, stallCount, retryCount, 0);
  917. }
  918. /// <summary>
  919. /// Set the encryption key in volatile memory.
  920. /// </summary>
  921. /// <param name="volatileKeyIndex">The key index in volatile memory to load the memory key into</param>
  922. /// <param name="encryptionKey">The 128-bit encryption key</param>
  923. /// <param name="responseWaitTime">Time to wait for device success response</param>
  924. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  925. public bool setCryptoKey(byte volatileKeyIndex, byte[] encryptionKey, UInt32 responseWaitTime)
  926. {
  927. if (!initializedUSB)
  928. throw new ObjectDisposedException("ANTDevice object has been disposed");
  929. return (ANT_SetCryptoKey(unmanagedANTFramerPtr, volatileKeyIndex, encryptionKey, responseWaitTime) == 1);
  930. }
  931. /// <summary>
  932. /// Set the encryption key in volatile memory.
  933. /// </summary>
  934. /// <param name="volatileKeyIndex">The key index in volatile memory to load the memory key into</param>
  935. /// <param name="encryptionKey">The 128-bit encryption key</param>
  936. public void setCryptoKey(byte volatileKeyIndex, byte[] encryptionKey)
  937. {
  938. setCryptoKey(volatileKeyIndex, encryptionKey, 0);
  939. }
  940. /// <summary>
  941. /// Set the 4-byte encryption ID of the device.
  942. /// </summary>
  943. /// <param name="encryptionID">4-byte encryption ID</param>
  944. /// <param name="responseWaitTime">Time to wait for device success response</param>
  945. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  946. public bool setCryptoID(byte[] encryptionID, UInt32 responseWaitTime)
  947. {
  948. if (!initializedUSB)
  949. throw new ObjectDisposedException("ANTDevice object has been disposed");
  950. return (ANT_SetCryptoID(unmanagedANTFramerPtr, encryptionID, responseWaitTime) == 1);
  951. }
  952. /// <summary>
  953. /// Set the 4-byte encryption ID of the device.
  954. /// </summary>
  955. /// <param name="encryptionID">4-byte encryption ID</param>
  956. public void setCryptoID(byte[] encryptionID)
  957. {
  958. setCryptoID(encryptionID, 0);
  959. }
  960. /// <summary>
  961. /// Set the 19-byte user information string of the device.
  962. /// </summary>
  963. /// <param name="userInfoString">19-byte user information string</param>
  964. /// <param name="responseWaitTime">Time to wait for device success response</param>
  965. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  966. public bool setCryptoUserInfo(byte[] userInfoString, UInt32 responseWaitTime)
  967. {
  968. if (!initializedUSB)
  969. throw new ObjectDisposedException("ANTDevice object has been disposed");
  970. return (ANT_SetCryptoUserInfo(unmanagedANTFramerPtr, userInfoString, responseWaitTime) == 1);
  971. }
  972. /// <summary>
  973. /// Set the 19-byte user information string of the device.
  974. /// </summary>
  975. /// <param name="userInfoString">19-byte user information string</param>
  976. public void setCryptoUserInfo(byte[] userInfoString)
  977. {
  978. setCryptoUserInfo(userInfoString, 0);
  979. }
  980. /// <summary>
  981. /// Set the 16-byte random number seed for the device. To ensure cryptographic security,
  982. /// some devices require the random number seed to be inputed from a cryptographically secure RNG.
  983. /// </summary>
  984. /// <param name="cryptoRNGSeed">Cryptographically secure 16-byte RGN</param>
  985. /// <param name="responseWaitTime">Time to wait for device success response</param>
  986. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  987. public bool setCryptoRNGSeed(byte[] cryptoRNGSeed, UInt32 responseWaitTime)
  988. {
  989. if (!initializedUSB)
  990. throw new ObjectDisposedException("ANTDevice object has been disposed");
  991. return (ANT_SetCryptoRNGSeed(unmanagedANTFramerPtr, cryptoRNGSeed, responseWaitTime) == 1);
  992. }
  993. /// <summary>
  994. /// Set the 16-byte random number seed for the device. To ensure cryptographic security,
  995. /// some devices require the random number seed to be inputed from a cryptographically secure RNG.
  996. /// </summary>
  997. /// <param name="cryptoRNGSeed">Cryptographically secure 16-byte RGN</param>
  998. public void setCryptoRNGSeed(byte[] cryptoRNGSeed)
  999. {
  1000. setCryptoRNGSeed(cryptoRNGSeed, 0);
  1001. }
  1002. /// <summary>
  1003. /// Set encryption information parameters.
  1004. /// </summary>
  1005. /// <param name="encryptionParameter">0 - Encryption ID, 1 - User Information String, 2 - Random Number Seed</param>
  1006. /// <param name="parameterData">4-byte Encryption ID or 19-byte User Information String or 16-byte Random Number Seed</param>
  1007. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1008. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1009. public bool setCryptoInfo(ANT_ReferenceLibrary.EncryptionInfo encryptionParameter, byte[] parameterData, UInt32 responseWaitTime)
  1010. {
  1011. if (!initializedUSB)
  1012. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1013. return (ANT_SetCryptoInfo(unmanagedANTFramerPtr, (byte)encryptionParameter, parameterData, responseWaitTime) == 1);
  1014. }
  1015. /// <summary>
  1016. /// Set encryption information parameters.
  1017. /// </summary>
  1018. /// <param name="encryptionParameter">0 - Encryption ID, 1 - User Information String, 2 - Random Number Seed</param>
  1019. /// <param name="parameterData">4-byte Encryption ID or 19-byte User Information String or 16-byte Random Number Seed</param>
  1020. public void setCryptoInfo(ANT_ReferenceLibrary.EncryptionInfo encryptionParameter, byte[] parameterData)
  1021. {
  1022. setCryptoInfo(encryptionParameter, parameterData, 0);
  1023. }
  1024. /// <summary>
  1025. /// Load a saved encryption key from NVM into the volatile memory.
  1026. /// </summary>
  1027. /// <param name="nonVolatileKeyIndex">Index of NVM stored encryption key to load from (0..3)</param>
  1028. /// <param name="volatileKeyIndex">Index of volatile stored encryption key to copy to</param>
  1029. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1030. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1031. public bool loadCryptoKeyFromNVM(byte nonVolatileKeyIndex, byte volatileKeyIndex, UInt32 responseWaitTime)
  1032. {
  1033. if (!initializedUSB)
  1034. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1035. return (ANT_LoadCryptoKeyNVMOp(unmanagedANTFramerPtr, nonVolatileKeyIndex, volatileKeyIndex, responseWaitTime) == 1);
  1036. }
  1037. /// <summary>
  1038. /// Load a saved encryption key from NVM into the volatile memory.
  1039. /// </summary>
  1040. /// <param name="nonVolatileKeyIndex">Index of NVM stored encryption key to load from (0..3)</param>
  1041. /// <param name="volatileKeyIndex">Index of volatile stored encryption key to copy to</param>
  1042. public void loadCryptoKeyFromNVM(byte nonVolatileKeyIndex, byte volatileKeyIndex)
  1043. {
  1044. loadCryptoKeyFromNVM(nonVolatileKeyIndex, volatileKeyIndex, 0);
  1045. }
  1046. /// <summary>
  1047. /// Save an encryption key to NVM.
  1048. /// </summary>
  1049. /// <param name="nonVolatileKeyIndex">Index of NVM stored encryption key to store to (0..3)</param>
  1050. /// <param name="encryptionKey">16-byte encryption key</param>
  1051. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1052. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1053. public bool storeCryptoKeyToNVM(byte nonVolatileKeyIndex, byte[] encryptionKey, UInt32 responseWaitTime)
  1054. {
  1055. if (!initializedUSB)
  1056. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1057. return (ANT_StoreCryptoKeyNVMOp(unmanagedANTFramerPtr, nonVolatileKeyIndex, encryptionKey, responseWaitTime) == 1);
  1058. }
  1059. /// <summary>
  1060. /// Save an encryption key to NVM.
  1061. /// </summary>
  1062. /// <param name="nonVolatileKeyIndex">Index of NVM stored encryption key to store to (0..3)</param>
  1063. /// <param name="encryptionKey">16-byte encryption key</param>
  1064. public void storeCryptoKeyToNVM(byte nonVolatileKeyIndex, byte[] encryptionKey)
  1065. {
  1066. storeCryptoKeyToNVM(nonVolatileKeyIndex, encryptionKey, 0);
  1067. }
  1068. /// <summary>
  1069. /// Load/Store Encryption Key from/in NVM
  1070. /// </summary>
  1071. /// <param name="memoryOperation">0 - Load encryption key from NVM or 1 - Store encryption key in NVM</param>
  1072. /// <param name="nonVolatileKeyIndex">The index of the Encryption Key in NVM to be loaded or stored to
  1073. /// depending on the selected operation (0..3)</param>
  1074. /// <param name="operationData">When Operation is set to 0x00: The index of the volatile key location that should be loaded with the NVM stored encryption key.
  1075. /// When Operation is set to 0x01: The 128-bit Encryption Key to be stored to NVM</param>
  1076. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1077. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1078. public bool cryptoKeyNVMOp(ANT_ReferenceLibrary.EncryptionNVMOp memoryOperation, byte nonVolatileKeyIndex, byte[] operationData, UInt32 responseWaitTime)
  1079. {
  1080. if (!initializedUSB)
  1081. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1082. return (ANT_CryptoKeyNVMOp(unmanagedANTFramerPtr, (byte)memoryOperation, nonVolatileKeyIndex, operationData, responseWaitTime) == 1);
  1083. }
  1084. /// <summary>
  1085. /// Load/Store Encryption Key from/in NVM
  1086. /// </summary>
  1087. /// <param name="memoryOperation">0 - Load encryption key from NVM or 1 - Store encryption key in NVM</param>
  1088. /// <param name="nonVolatileKeyIndex">The index of the Encryption Key in NVM to be loaded or stored to
  1089. /// depending on the selected operation (0..3)</param>
  1090. /// <param name="operationData">When Operation is set to 0x00: The index of the volatile key location that should be loaded with the NVM stored encryption key.
  1091. /// When Operation is set to 0x01: The 128-bit Encryption Key to be stored to NVM</param>
  1092. public void cryptoKeyNVMOp(ANT_ReferenceLibrary.EncryptionNVMOp memoryOperation, byte nonVolatileKeyIndex, byte[] operationData)
  1093. {
  1094. cryptoKeyNVMOp(memoryOperation, nonVolatileKeyIndex, operationData, 0);
  1095. }
  1096. /// <overloads>Enables/Disables the device's LED</overloads>
  1097. /// <summary>
  1098. /// Enables/Disables the LED flashing when a transmission event occurs
  1099. /// </summary>
  1100. /// <param name="IsEnabled">Desired state</param>
  1101. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1102. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1103. public bool EnableLED(bool IsEnabled, UInt32 responseWaitTime)
  1104. {
  1105. if (!initializedUSB)
  1106. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1107. return (ANT_EnableLED(unmanagedANTFramerPtr, Convert.ToByte(IsEnabled), responseWaitTime) == 1);
  1108. }
  1109. /// <summary>
  1110. /// Enables/Disables the LED flashing when a transmission event occurs
  1111. /// </summary>
  1112. /// <param name="IsEnabled">Desired state</param>
  1113. public void EnableLED(bool IsEnabled) { EnableLED(IsEnabled, 0); }
  1114. /// <overloads>Configures Event Buffering</overloads>
  1115. /// <summary>
  1116. /// Allows buffering of ANT events. Preset groups of events may be selected for buffering.
  1117. /// Events may be buffered by size or time and buffering can be used in conjunction with filtering.
  1118. /// </summary>
  1119. /// <param name="config">Selects which events are buffered</param>
  1120. /// <param name="size">Number of bytes that will be stored before a buffer flush occurs. Set to 0 to disable.</param>
  1121. /// <param name="time">Maximum time (in 10ms units) before a buffer flush occurs. Set to 0 to disable.
  1122. /// Buffer size must also be set to a non zero value.</param>
  1123. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1124. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1125. public bool configureEventBuffer(ANT_ReferenceLibrary.EventBufferConfig config, UInt16 size, UInt16 time, UInt32 responseWaitTime)
  1126. {
  1127. if (!initializedUSB)
  1128. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1129. return ANT_ConfigEventBuffer(unmanagedANTFramerPtr, (byte)config, size, time, responseWaitTime) == 1;
  1130. }
  1131. /// <summary>
  1132. /// Allows buffering of ANT events. Preset groups of events may be selected for buffering.
  1133. /// Events may be buffered by size or time and buffering can be used in conjunction with filtering.
  1134. /// </summary>
  1135. /// <param name="config">Selects which events are buffered</param>
  1136. /// <param name="size">Number of bytes that will be stored before a buffer flush occurs. Set to 0 to disable.</param>
  1137. /// <param name="time">Maximum time (in 10ms units) before a buffer flush occurs. Set to 0 to disable.
  1138. /// Buffer size must also be set to a non zero value.</param>
  1139. public void configureEventBuffer(ANT_ReferenceLibrary.EventBufferConfig config, UInt16 size, UInt16 time) { configureEventBuffer(config, size, time, 0); }
  1140. /// <overloads>Configures Event Filtering</overloads>
  1141. /// <summary>
  1142. /// Allows filtering of specified ANT events. Filtering can be used in conjunction with buffering.
  1143. /// </summary>
  1144. /// <param name="eventFilter">Bitfield of events to filter. Set Bit0 to filter event 0 etc.</param>
  1145. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1146. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1147. public bool configureEventFilter(UInt16 eventFilter, UInt32 responseWaitTime)
  1148. {
  1149. if (!initializedUSB)
  1150. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1151. return ANT_ConfigEventFilter(unmanagedANTFramerPtr, eventFilter, responseWaitTime) == 1;
  1152. }
  1153. /// <summary>
  1154. /// Allows filtering of specified ANT events. Filtering can be used in conjunction with buffering.
  1155. /// </summary>
  1156. /// <param name="eventFilter">Bitfield of events to filter. Set Bit0 to filter event 0 etc.</param>
  1157. public void configureEventFilter(UInt16 eventFilter) { configureEventFilter(eventFilter, 0); }
  1158. /// <overloads>Configures High Duty Search</overloads>
  1159. /// <summary>
  1160. /// Allows configuring High Duty Search if no channels have been opened yet
  1161. /// </summary>
  1162. /// <param name="enable">Enable or disable High Duty Search</param>
  1163. /// <param name="suppressionCycles">Search period to suppress high duty search in units of 250ms. 0=Allow full time, 5=Suppress entirely</param>
  1164. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1165. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1166. public bool configureHighDutySearch(bool enable, byte suppressionCycles, UInt32 responseWaitTime)
  1167. {
  1168. if (!initializedUSB)
  1169. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1170. return ANT_ConfigHighDutySearch(unmanagedANTFramerPtr, (enable ? (byte)1 : (byte)0), suppressionCycles, responseWaitTime) == 1;
  1171. }
  1172. /// <summary>
  1173. /// Allows configuring High Duty Search if no channels have been opened yet
  1174. /// </summary>
  1175. /// <param name="enable">Enable or disable High Duty Search</param>
  1176. /// <param name="suppressionCycles">Search period to suppress high duty search in units of 250ms. 0=Allow full time, 5=Suppress entirely</param>
  1177. public void configureHighDutySearch(bool enable, byte suppressionCycles) { configureHighDutySearch(enable, suppressionCycles, 0); }
  1178. /// <overloads>Allows defining a new Selective Data Update Mask</overloads>
  1179. /// <summary>
  1180. /// Allows defining a new Selective Data Update Mask
  1181. /// </summary>
  1182. /// <param name="maskNumber">Identifier for the SDU Mask</param>
  1183. /// <param name="mask">Rx Data Message Mask, 0=Ignore, 1=Update on Change</param>
  1184. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1185. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1186. public bool setSduMask(byte maskNumber, byte[] mask, UInt32 responseWaitTime)
  1187. {
  1188. if (!initializedUSB)
  1189. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1190. return ANT_SetSelectiveDataUpdateMask(unmanagedANTFramerPtr, maskNumber, mask, responseWaitTime) == 1;
  1191. }
  1192. /// <summary>
  1193. /// Allows defining a new Selective Data Update Mask
  1194. /// </summary>
  1195. /// <param name="maskNumber">Identifier for the SDU Mask</param>
  1196. /// <param name="mask">Rx Data Message Mask, 0=Ignore, 1=Update on Change</param>
  1197. public void setSduMask(byte maskNumber, byte[] mask) { setSduMask(maskNumber, mask, 0); }
  1198. /// <overloads>Configures User NVM</overloads>
  1199. /// <summary>
  1200. /// Allows configuring User NVM if available.
  1201. /// </summary>
  1202. /// <param name="address"> Nvm starting address</param>
  1203. /// <param name="data">Data block to write</param>
  1204. /// <param name="size">Size of data block</param>
  1205. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1206. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1207. public bool configureUserNvm(UInt16 address, byte[] data, byte size, UInt32 responseWaitTime)
  1208. {
  1209. if (!initializedUSB)
  1210. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1211. return ANT_ConfigUserNVM(unmanagedANTFramerPtr, address, data, size, responseWaitTime) == 1;
  1212. }
  1213. /// <summary>
  1214. /// Allows configuring User Nvm if available.
  1215. /// </summary>
  1216. /// <param name="address"> Nvm starting address</param>
  1217. /// <param name="data">Data block to write</param>
  1218. /// <param name="size">Size of data block</param>
  1219. public void configureUserNvm(UInt16 address, byte[] data, byte size) { configureUserNvm(address, data, size, 0); }
  1220. /// <overloads>Requests a message from the device and returns the response</overloads>
  1221. /// <summary>
  1222. /// Read User Nvm by sending Request Mesg capturing the response.
  1223. /// Throws exception on timeout.
  1224. /// </summary>
  1225. /// <param name="address">NVM Address to read from</param>
  1226. /// <param name="size">Number of bytes to read</param>
  1227. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1228. public ANT_Response readUserNvm(UInt16 address, byte size, UInt32 responseWaitTime)
  1229. {
  1230. if (!initializedUSB)
  1231. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1232. ANTMessageItem response = new ANTMessageItem();
  1233. if (ANT_RequestUserNvmMessage(unmanagedANTFramerPtr, 0, (byte)ANT_ReferenceLibrary.RequestMessageID.USER_NVM_0x7C, ref response, address, size, responseWaitTime) == 0)
  1234. throw new ANT_Exception("Timed out waiting for requested message");
  1235. ANT_Response retVal = new ANT_Response(this, 0, DateTime.Now, response.antMsgData.msgID, response.antMsgData.ucharBuf.Take(response.dataSize).ToArray());
  1236. return retVal;
  1237. }
  1238. /// <summary>
  1239. /// Read User Nvm by sending Request Mesg capturing the response.
  1240. /// Throws exception on timeout.
  1241. /// </summary>
  1242. /// <param name="address">NVM Address to read from</param>
  1243. /// <param name="size">Number of bytes to read</param>
  1244. public ANT_Response readUserNvm(UInt16 address, byte size)
  1245. {
  1246. return readUserNvm(address, size, 500);
  1247. }
  1248. /// <summary>
  1249. /// Obtains the PID (Product ID) of the USB device.
  1250. /// Throws an exception if the PID is not received.
  1251. /// </summary>
  1252. /// <returns>PID of the USB device.</returns>
  1253. public UInt16 getDeviceUSBPID()
  1254. {
  1255. if (!initializedUSB)
  1256. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1257. UInt16 returnPID = 0;
  1258. if(ANT_GetDeviceUSBPID(unmanagedANTFramerPtr, ref returnPID) != 1)
  1259. throw new ANT_Exception("Retrieving Device USB PID failed");
  1260. return (returnPID);
  1261. }
  1262. /// <summary>
  1263. /// Obtains the VID (Vendor ID) of the USB device
  1264. /// </summary>
  1265. /// <returns>VID of the USB device</returns>
  1266. public UInt16 getDeviceUSBVID()
  1267. {
  1268. if (!initializedUSB)
  1269. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1270. UInt16 returnVID = 0;
  1271. if (ANT_GetDeviceUSBVID(unmanagedANTFramerPtr, ref returnVID) != 1)
  1272. throw new ANT_Exception("Retrieving Device USB VID failed");
  1273. return (returnVID);
  1274. }
  1275. /// <summary>
  1276. /// Returns the USB device serial number.
  1277. /// This can be used to figure out the serial number if the option to use the USB device
  1278. /// serial number was selected.
  1279. /// </summary>
  1280. /// <returns>Client serial number</returns>
  1281. public uint getSerialNumber()
  1282. {
  1283. if (!initializedUSB)
  1284. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1285. return ANT_GetDeviceSerialNumber(unmanagedANTSerialPtr);
  1286. }
  1287. /// <overloads>Obtains the device USB Information</overloads>
  1288. /// <summary>
  1289. /// Obtains the USB information for the device
  1290. /// Throws an exception if no information is received
  1291. /// </summary>
  1292. /// <param name="deviceNum">USB Device Number</param>
  1293. /// <returns>USB Device Information</returns>
  1294. public ANT_DeviceInfo getDeviceUSBInfo(byte deviceNum)
  1295. {
  1296. if (!initializedUSB)
  1297. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1298. byte[] returnProdDescription = new byte[256]; // size should match that defined on the Unmanaged Wrapper
  1299. byte[] returnSerialString = new byte[256];
  1300. if (ANT_GetDeviceUSBInfo(unmanagedANTFramerPtr, deviceNum, returnProdDescription, returnSerialString) != 1)
  1301. throw new ANT_Exception("Retrieving USB device information failed");
  1302. return (new ANT_DeviceInfo(returnProdDescription, returnSerialString));
  1303. }
  1304. /// <summary>
  1305. /// Obtains the USB information for the device
  1306. /// Throws an exception if no information is received
  1307. /// </summary>
  1308. /// <returns>USB Device Information</returns>
  1309. public ANT_DeviceInfo getDeviceUSBInfo()
  1310. {
  1311. if (!initializedUSB)
  1312. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1313. return getDeviceUSBInfo(USBDeviceNum);
  1314. }
  1315. /// <overloads>Requests a message from the device and returns the response</overloads>
  1316. /// <summary>
  1317. /// Request a message from device and returns the response.
  1318. /// Throws exception on timeout.
  1319. /// </summary>
  1320. /// <param name="channelNum">Channel to send request on</param>
  1321. /// <param name="messageID">Request to send</param>
  1322. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1323. public ANT_Response requestMessageAndResponse(byte channelNum, ANT_ReferenceLibrary.RequestMessageID messageID, UInt32 responseWaitTime)
  1324. {
  1325. if (!initializedUSB)
  1326. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1327. ANTMessageItem response = new ANTMessageItem();
  1328. if (ANT_RequestMessage(unmanagedANTFramerPtr, channelNum, (byte)messageID, ref response, responseWaitTime) == 0)
  1329. throw new ANT_Exception("Timed out waiting for requested message");
  1330. ANT_Response retVal = new ANT_Response(this, channelNum, DateTime.Now, response.antMsgData.msgID, response.antMsgData.ucharBuf.Take(response.dataSize).ToArray());
  1331. return retVal;
  1332. }
  1333. /// <summary>
  1334. /// Request a message from device on channel 0 and returns the response.
  1335. /// Throws exception on timeout.
  1336. /// </summary>
  1337. /// <param name="messageID">Request to send</param>
  1338. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1339. public ANT_Response requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID messageID, UInt32 responseWaitTime)
  1340. {
  1341. return requestMessageAndResponse(0, messageID, responseWaitTime);
  1342. }
  1343. /// <overloads>Requests a message from the device</overloads>
  1344. /// <summary>
  1345. /// Request a message from device
  1346. /// </summary>
  1347. /// <param name="channelNum">Channel to send request on</param>
  1348. /// <param name="messageID">Request to send</param>
  1349. public void requestMessage(byte channelNum, ANT_ReferenceLibrary.RequestMessageID messageID)
  1350. {
  1351. if (!initializedUSB)
  1352. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1353. ANTMessageItem dummystruct = new ANTMessageItem();
  1354. ANT_RequestMessage(unmanagedANTFramerPtr, channelNum, (byte)messageID, ref dummystruct, 0);
  1355. }
  1356. /// <summary>
  1357. /// Request a message from device
  1358. /// </summary>
  1359. /// <param name="messageID">Request to send</param>
  1360. public void requestMessage(ANT_ReferenceLibrary.RequestMessageID messageID)
  1361. {
  1362. requestMessage(0, messageID);
  1363. }
  1364. /// <overloads>Set device in continuous scanning mode</overloads>
  1365. /// <summary>
  1366. /// Starts operation in continuous scanning mode.
  1367. /// This allows the device to receive all messages matching the configured channel ID mask in an asynchronous manner.
  1368. /// This feature is not available on all ANT devices.
  1369. /// </summary>
  1370. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1371. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1372. public bool openRxScanMode(UInt32 responseWaitTime)
  1373. {
  1374. if (!initializedUSB)
  1375. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1376. return ANT_OpenRxScanMode(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1377. }
  1378. /// <summary>
  1379. /// Starts operation in continuous scanning mode.
  1380. /// This allows the device to receive all messages matching the configured channel ID mask in an asynchronous manner.
  1381. /// </summary>
  1382. public void openRxScanMode() { openRxScanMode(0); }
  1383. /// <overloads>Initializes and starts CW test mode</overloads>
  1384. /// <summary>
  1385. /// Initialize and start CW test mode. This mode is to test your implementation for RF frequency requirements.
  1386. /// The device will transmit an unmodulated carrier wave at the RF frequency of 2400Mhz + RFFreqOffset at the specified power level.
  1387. /// This mode can then only be exited by a system reset.
  1388. /// Note: When this function call returns false, the system will be reset automatically.
  1389. /// </summary>
  1390. /// <param name="transmitPower">Transmission power to test at</param>
  1391. /// <param name="RFFreqOffset">Offset to add to 2400Mhz</param>
  1392. /// <param name="responseWaitTime">Time to wait for response, used for both initialization and start command</param>
  1393. /// <returns>False if initialization or starting of CW test mode fails. On false, the system is automatically reset.</returns>
  1394. /// <remarks>
  1395. /// This function encapsulates both ANT_InitCWTestMode and ANT_SetCWTestMode from the old library.
  1396. /// It will automatically reset the system if either call fails.
  1397. /// The given response time is used for both calls and the reset time is 500ms.
  1398. /// So max wait time = responseTime*2 + 500ms
  1399. /// </remarks>
  1400. public bool startCWTest(ANT_ReferenceLibrary.TransmitPower transmitPower, byte RFFreqOffset, UInt32 responseWaitTime)
  1401. {
  1402. if (!initializedUSB)
  1403. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1404. bool retVal = true;
  1405. ResetSystem(); //CW Mode is only supposed to be set up after a reset
  1406. if (ANT_InitCWTestMode(unmanagedANTFramerPtr, responseWaitTime) != 1)
  1407. retVal = false;
  1408. if (ANT_SetCWTestMode(unmanagedANTFramerPtr, (byte)transmitPower, RFFreqOffset, responseWaitTime) != 1)
  1409. retVal = false;
  1410. if (retVal == false && ANT_Common.autoResetIsEnabled) //If we messed up we want to make sure the module doesn't get messed up in CW mode, so we reset
  1411. ResetSystem(500);
  1412. return retVal;
  1413. }
  1414. /// <overloads>Enables extended message reception</overloads>
  1415. /// <summary>
  1416. /// Enables extended message receiving. When enabled, messages received will contain extended data.
  1417. /// </summary>
  1418. /// <param name="IsEnabled">Desired State</param>
  1419. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1420. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1421. public bool enableRxExtendedMessages(bool IsEnabled, UInt32 responseWaitTime)
  1422. {
  1423. if (!initializedUSB)
  1424. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1425. return ANT_RxExtMesgsEnable(unmanagedANTFramerPtr, Convert.ToByte(IsEnabled), responseWaitTime) == 1;
  1426. }
  1427. /// <summary>
  1428. /// Enables extended message receiving. When enabled, messages received will contain extended data.
  1429. /// </summary>
  1430. /// <param name="IsEnabled">Desired State</param>
  1431. public void enableRxExtendedMessages(bool IsEnabled) { enableRxExtendedMessages(IsEnabled, 0); }
  1432. /// <overloads>Enables the use of external 32kHz crystal</overloads>
  1433. /// <summary>
  1434. /// If the use of an external 32kHz crystal input is desired, this message must be sent once, each time a startup message is received
  1435. /// </summary>
  1436. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1437. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1438. /// <remarks> Enabling an external 32kHz crystal input as a low power clock source saves ~85uA while ANT is active when compared to using the internal clock source. </remarks>
  1439. public bool crystalEnable(UInt32 responseWaitTime)
  1440. {
  1441. if (!initializedUSB)
  1442. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1443. return ANT_CrystalEnable(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1444. }
  1445. /// <summary>
  1446. /// If the use of an external 32kHz crystal input is desired, this message must be sent once, each time a startup message is received
  1447. /// </summary>
  1448. /// <remarks> Enabling an external 32kHz crystal input as a low power clock source saves ~85uA while ANT is active when compared to using the internal clock source. </remarks>
  1449. public void crystalEnable() { crystalEnable(0); }
  1450. /// <summary>
  1451. /// Writes a message to the device, this function allows sending manually formatted messages.
  1452. /// </summary>
  1453. /// <param name="msgID">msgID to write</param>
  1454. /// <param name="msgData">data buffer to write</param>
  1455. /// <returns>False if writing bytes to device fails</returns>
  1456. public bool writeRawMessageToDevice(byte msgID, byte[] msgData)
  1457. {
  1458. if (!initializedUSB)
  1459. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1460. //Create ANT_MESSAGE
  1461. ANTMessage aMsg = new ANTMessage();
  1462. aMsg.msgID = msgID;
  1463. //We create an array of max size, because the struct sizing expects a constant size array
  1464. int padNum = ANT_ReferenceLibrary.MAX_MESG_SIZE - msgData.Length;
  1465. if(padNum < 0)
  1466. throw new ANT_Exception("msgData max length is " + ANT_ReferenceLibrary.MAX_MESG_SIZE + " bytes");
  1467. aMsg.ucharBuf = msgData.Concat(new byte[padNum]).ToArray();
  1468. return ANT_WriteMessage(unmanagedANTFramerPtr, aMsg, (UInt16)msgData.Length) == 1;
  1469. }
  1470. /// <overloads>Configure the device ANT library, ie: to send extra msg info</overloads>
  1471. /// <summary>
  1472. /// Configure the device ANT library, ie: to send extra msg info
  1473. /// </summary>
  1474. /// <param name="libConfigFlags">Config flags</param>
  1475. /// <param name="responseWaitTime">Time to wait for response</param>
  1476. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1477. public bool setLibConfig(ANT_ReferenceLibrary.LibConfigFlags libConfigFlags, UInt32 responseWaitTime)
  1478. {
  1479. if (!initializedUSB)
  1480. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1481. return ANT_SetLibConfig(unmanagedANTFramerPtr, (byte)libConfigFlags, responseWaitTime) == 1;
  1482. }
  1483. /// <summary>
  1484. /// Configure the device ANT library, ie: to send extra msg info
  1485. /// </summary>
  1486. /// <param name="libConfigFlags">Config flags</param>
  1487. public void setLibConfig(ANT_ReferenceLibrary.LibConfigFlags libConfigFlags) { setLibConfig(libConfigFlags, 0); }
  1488. #region SensRcore NVM script commands
  1489. /// <overloads>Writes a SensRCore command to non-volatile memory</overloads>
  1490. /// <summary>
  1491. /// Writes a SensRcore command to non-volatile memory.
  1492. /// Throws exception if command string length > 255, although commands will be much smaller
  1493. /// </summary>
  1494. /// <param name="commandString">SensRcore command to write: [Cmd][CmdData0]...[CmdDataN], must be less than 256 bytes</param>
  1495. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1496. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1497. public bool script_Write(byte[] commandString, UInt32 responseWaitTime)
  1498. {
  1499. if (!initializedUSB)
  1500. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1501. if(!(commandString.Length < 256)) //We are casting to byte, so we need to be safe
  1502. throw new ANT_Exception("commandString max size is 255");
  1503. return ANT_Script_Write(unmanagedANTFramerPtr, (byte)commandString.Length, commandString, responseWaitTime) == 1;
  1504. }
  1505. /// <summary>
  1506. /// Writes a SensRcore command to non-volatile memory.
  1507. /// Throws exception if command string length > 255.
  1508. /// </summary>
  1509. /// <param name="commandString">SensRcore command to write: [Cmd][CmdData0]...[CmdDataN], must be less than 256 bytes</param>
  1510. public void script_Write(byte[] commandString) { script_Write(commandString, 0); }
  1511. /// <overloads>Clears the NVM</overloads>
  1512. /// <summary>
  1513. /// Clears the non-volatile memory. NVM should be cleared before beginning write operations.
  1514. /// </summary>
  1515. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1516. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1517. public bool script_Clear(UInt32 responseWaitTime)
  1518. {
  1519. if (!initializedUSB)
  1520. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1521. return ANT_Script_Clear(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1522. }
  1523. /// <summary>
  1524. /// Clears the non-volatile memory. NVM should be cleared before beginning write operations.
  1525. /// </summary>
  1526. public void script_Clear() { script_Clear(0); }
  1527. /// <overloads>Sets the default SensRCore sector</overloads>
  1528. /// <summary>
  1529. /// Set the default sector which will be executed after mandatory execution of sector 0.
  1530. /// This command has no effect if it is set to 0 or the Read Pins for Sector command appears in sector 0.
  1531. /// </summary>
  1532. /// <param name="sectorNum">sector number to set as default</param>
  1533. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1534. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1535. public bool script_setDefaultSector(byte sectorNum, UInt32 responseWaitTime)
  1536. {
  1537. if (!initializedUSB)
  1538. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1539. return ANT_Script_SetDefaultSector(unmanagedANTFramerPtr, sectorNum, responseWaitTime) == 1;
  1540. }
  1541. /// <summary>
  1542. /// Set the default sector which will be executed after mandatory execution of sector 0.
  1543. /// This command has no effect if it is set to 0 or the Read Pins for Sector command appears in sector 0.
  1544. /// </summary>
  1545. /// <param name="sectorNum">sector number to set as default</param>
  1546. public void script_setDefaultSector(byte sectorNum) { script_setDefaultSector(sectorNum, 0); }
  1547. /// <overloads>Writes a sector break to NVM</overloads>
  1548. /// <summary>
  1549. /// Writes a sector break in the NVM image
  1550. /// </summary>
  1551. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1552. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1553. public bool script_endSector(UInt32 responseWaitTime)
  1554. {
  1555. if (!initializedUSB)
  1556. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1557. return ANT_Script_EndSector(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1558. }
  1559. /// <summary>
  1560. /// Writes a sector break in the NVM image
  1561. /// </summary>
  1562. public void script_endSector() { script_endSector(0); }
  1563. /// <overloads>Request a dump of the device's script memory</overloads>
  1564. /// <summary>
  1565. /// Requests the device to return the current NVM contents through the device callback function.
  1566. /// The end of the dump is signified by a 0x57 NVM_Cmd msg, which contains 0x04 EndDump code followed by
  1567. /// a byte signifying how many instructions were read and returned.
  1568. /// </summary>
  1569. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1570. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1571. public bool script_requestNVMDump(UInt32 responseWaitTime)
  1572. {
  1573. if (!initializedUSB)
  1574. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1575. return ANT_Script_Dump(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1576. }
  1577. /// <summary>
  1578. /// Requests the device to return the current NVM contents through the device callback function.
  1579. /// The end of the dump is signified by a 0x57 NVM_Cmd msg, which contains 0x04 EndDump code followed by
  1580. /// a byte signifying how many instructions were read and returned.
  1581. /// </summary>
  1582. public void script_requestNVMDump() { script_requestNVMDump(0); }
  1583. /// <overloads>Locks the NVM contents</overloads>
  1584. /// <summary>
  1585. /// Locks the NVM so that it can not be read by the dump function.
  1586. /// Can only be disabled by clearing the NVM.
  1587. /// </summary>
  1588. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1589. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1590. public bool script_lockNVM(UInt32 responseWaitTime)
  1591. {
  1592. if (!initializedUSB)
  1593. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1594. return ANT_Script_Lock(unmanagedANTFramerPtr, responseWaitTime) == 1;
  1595. }
  1596. /// <summary>
  1597. /// Locks the NVM so that it can not be read by the dump function.
  1598. /// Can only be disabled by clearing the NVM.
  1599. /// </summary>
  1600. public void script_lockNVM() { script_lockNVM(0); }
  1601. ///<overloads>Sets the equipment state</overloads>
  1602. /// <summary>
  1603. /// Sets the equipment state.
  1604. /// This command is specifically for use with the FIT1e module.
  1605. /// </summary>
  1606. /// <param name="feState">Fitness equipment state</param>
  1607. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1608. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1609. public bool fitSetFEState(byte feState, UInt32 responseWaitTime)
  1610. {
  1611. if (!initializedUSB)
  1612. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1613. if (!capabilities.FIT) // Check this is a FIT1e module
  1614. return false;
  1615. return FIT_SetFEState(unmanagedANTFramerPtr, feState, responseWaitTime) == 1;
  1616. }
  1617. /// <summary>
  1618. /// Sets the equipment state.
  1619. /// This command is specifically for use with the FIT1e module.
  1620. /// </summary>
  1621. /// <param name="feState">Fitness equipment state</param>
  1622. public void fitSetFEState(byte feState) { fitSetFEState(feState, 0);}
  1623. /// <summary>
  1624. /// Adjusts the pairing distance settings.
  1625. /// This command is specifically for use with the FIT1e module.
  1626. /// </summary>
  1627. /// <param name="searchLv">Minimum signal strength for a signal to be considered for pairing.</param>
  1628. /// <param name="pairLv">Signal strength required for the FIT1e to pair with an ANT+ HR strap or watch</param>
  1629. /// <param name="trackLv">An ANT+ device will unpair if the signal strength drops below this setting while in
  1630. /// READY state or within the first 30 secons of the IN_USE state</param>
  1631. /// <param name="responseWaitTime">Time to wait for device success response</param>
  1632. /// <returns>True on success. Note: Always returns true with a response time of 0</returns>
  1633. public bool fitAdjustPairingSettings(byte searchLv, byte pairLv, byte trackLv, UInt32 responseWaitTime)
  1634. {
  1635. if (!initializedUSB)
  1636. throw new ObjectDisposedException("ANTDevice object has been disposed");
  1637. if (!capabilities.FIT) // Check this is a FIT1e module
  1638. return false;
  1639. return FIT_AdjustPairingSettings(unmanagedANTFramerPtr, searchLv, pairLv, trackLv, responseWaitTime) == 1;
  1640. }
  1641. /// <summary>
  1642. /// Adjusts the pairing distance settings.
  1643. /// This command is specifically for use with the FIT1e module.
  1644. /// </summary>
  1645. /// <param name="searchLv">Minimum signal strength for a signal to be considered for pairing.</param>
  1646. /// <param name="pairLv">Signal strength required for the FIT1e to pair with an ANT+ HR strap or watch</param>
  1647. /// <param name="trackLv">An ANT+ device will unpair if the signal strength drops below this setting while in
  1648. /// READY state or within the first 30 secons of the IN_USE state</param>
  1649. public void fitAdjustPairingSettings(byte searchLv, byte pairLv, byte trackLv)
  1650. {
  1651. fitAdjustPairingSettings(searchLv, pairLv, trackLv, 0);
  1652. }
  1653. #endregion
  1654. #endregion
  1655. }
  1656. }