MainForm.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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 in compliance
  4. with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2012
  6. All rights reserved.
  7. */
  8. #include "stdafx.h"
  9. #include "MainForm.h"
  10. #include "ANTPlus.h"
  11. #include "SimTypes.h"
  12. using namespace ANTPlusSim;
  13. /**************************************************************************
  14. * MainForm
  15. *
  16. * Constructor for MainForm class.
  17. *
  18. *
  19. * Params:
  20. *
  21. * ucSimType_: Type of simulator this is (DISPLAY or SENSOR)
  22. *
  23. * returns: N/A
  24. *
  25. **************************************************************************/
  26. MainForm::MainForm(UCHAR ucSimType_)
  27. {
  28. System::Windows::Forms::Control::CheckForIllegalCrossThreadCalls = FALSE;
  29. InitializeComponent();
  30. bMyConnected = FALSE;
  31. eMyANTPlatform = PLATFORM_UNKNOWN;
  32. sMyCapabilities.ucStandardOptions = 0xff;
  33. sMyCapabilities.ucAdvancedOptions = 0x00;
  34. sMyCapabilities.ucAdvancedOptions2 = 0x00;
  35. numChannels = 2;
  36. ucSimType = ucSimType_;
  37. switch(ucSimType)
  38. {
  39. case SIM_SENSOR:
  40. strTitle = "ANT+ Sensor Simulator - v"SW_VER_NUM SW_VER_DEV SW_VER_SUFFIX SW_DESCR;
  41. strAbout = "ANT+ Sensor Simulator - v"SW_VER_NUM SW_VER_DEV SW_VER_SUFFIX;
  42. break;
  43. case SIM_DISPLAY:
  44. strTitle = "ANT+ Display Simulator - v"SW_VER_NUM SW_VER_DEV SW_VER_SUFFIX SW_DESCR;
  45. strAbout = "ANT+ Display Simulator - v"SW_VER_NUM SW_VER_DEV SW_VER_SUFFIX;
  46. break;
  47. default:
  48. // Should assert here.
  49. strTitle = "ANT+ Simulator";
  50. strAbout = "ANT+ Simulator";
  51. break;
  52. }
  53. this->Text = strTitle;
  54. }
  55. /**************************************************************************
  56. * ~MainForm
  57. *
  58. * Destructor for MainForm class.
  59. *
  60. * Params: N/A
  61. *
  62. * returns: N/A
  63. *
  64. **************************************************************************/
  65. MainForm::~MainForm()
  66. {
  67. if(channelList)
  68. {
  69. while(numChannels)
  70. {
  71. delete channelList[--numChannels];
  72. }
  73. delete channelList;
  74. }
  75. if (components)
  76. {
  77. delete components;
  78. }
  79. }
  80. /**************************************************************************
  81. * createDevicePanel
  82. *
  83. * Create panel after connecting to ANT
  84. *
  85. * returns: N/A
  86. *
  87. **************************************************************************/
  88. void MainForm::CreateDevicePanel()
  89. {
  90. panel_devicePanel_1 = (gcnew System::Windows::Forms::Panel());
  91. richTextBox_deviceReport_1 = (gcnew System::Windows::Forms::RichTextBox());
  92. panel_devicePanel_1->Controls->Add(richTextBox_deviceReport_1);
  93. panel_devicePanel_1->Location = System::Drawing::Point(3, 3);
  94. panel_devicePanel_1->Name = L"panel_devicePanel1";
  95. panel_devicePanel_1->Size = System::Drawing::Size(398, 117);
  96. panel_devicePanel_1->TabIndex = 0;
  97. panel_devicePanel_1->TabStop = false;
  98. richTextBox_deviceReport_1->BackColor = System::Drawing::Color::LightYellow;
  99. richTextBox_deviceReport_1->Location = System::Drawing::Point(0, 0);
  100. richTextBox_deviceReport_1->Name = L"richTextBox_deviceReport1";
  101. richTextBox_deviceReport_1->ReadOnly = true;
  102. richTextBox_deviceReport_1->Size = System::Drawing::Size(395, 114);
  103. richTextBox_deviceReport_1->TabIndex = 0;
  104. richTextBox_deviceReport_1->TabStop = false;
  105. richTextBox_deviceReport_1->Text = L"";
  106. richTextBox_deviceReport_1->Text = System::String::Concat("Device 1: ", comboBox_DeviceSelect->SelectedItem);
  107. flowLayoutPanel_ActiveDeviceList->Controls->Add(this->panel_devicePanel_1);
  108. }
  109. /**************************************************************************
  110. * removeDevicePanel
  111. *
  112. * Remove panel
  113. *
  114. * returns: N/A
  115. *
  116. **************************************************************************/
  117. void MainForm::RemoveDevicePanel()
  118. {
  119. panel_devicePanel_1->Controls->Remove(richTextBox_deviceReport_1);
  120. delete richTextBox_deviceReport_1;
  121. flowLayoutPanel_ActiveDeviceList->Controls->Remove(panel_devicePanel_1);
  122. delete panel_devicePanel_1;
  123. }
  124. /**************************************************************************
  125. * interpretCapabilities
  126. *
  127. * Decode capabilities message returned by ANT
  128. *
  129. * returns: N/A
  130. *
  131. **************************************************************************/
  132. void MainForm::InterpretCapabilities(UCHAR* pcBuffer_)
  133. {
  134. capabilityDefs basicCapDefs[] =
  135. {
  136. { CAPABILITIES_NO_RX_CHANNELS, "No Rx Channels"},
  137. { CAPABILITIES_NO_TX_CHANNELS, "No Tx Channels"},
  138. { CAPABILITIES_NO_RX_MESSAGES, "No Rx Messages"},
  139. { CAPABILITIES_NO_TX_MESSAGES, "No Tx Messages"},
  140. { CAPABILITIES_NO_ACKD_MESSAGES, "No Ack Messages"},
  141. { CAPABILITIES_NO_BURST_TRANSFER, "No Burst Transfer"}
  142. };
  143. capabilityDefs extendedCapDefs1[] =
  144. {
  145. { CAPABILITIES_NETWORK_ENABLED, "Private Networks"},
  146. { CAPABILITIES_SERIAL_NUMBER_ENABLED, "Serial Number"},
  147. { CAPABILITIES_PER_CHANNEL_TX_POWER_ENABLED, "Per Channel Tx Power"},
  148. { CAPABILITIES_LOW_PRIORITY_SEARCH_ENABLED, "Low Priority Search"},
  149. { CAPABILITIES_SENSRCORE_ENABLED, "SensRcore Mode"},
  150. { CAPABILITIES_SEARCH_LIST_ENABLED, "Search List"}
  151. };
  152. capabilityDefs extendedCapDefs2[] =
  153. {
  154. { CAPABILITIES_LED_ENABLED, "Onboard LED"},
  155. { CAPABILITIES_EXT_MESSAGE_ENABLED, "Extended Message Support"},
  156. { CAPABILITIES_SCAN_CHANNEL_ENABLED, "Scan Channel"},
  157. { CAPABILITIES_TX_SEARCH_CMD_ENABLED, "Tx Search on Next"},
  158. { CAPABILITIES_PROX_SEARCH_ENABLED, "Proximity Search"},
  159. { CAPABILITIES_EXT_ASSIGN_ENABLED, "Extended Assign"},
  160. { CAPABILITIES_FS_ANTFS, "ANTFS"}
  161. };
  162. int i;
  163. //Now we handle the flags
  164. richTextBox_MainStatus->AppendText("\nDevice Sent Capabilities Info");
  165. richTextBox_deviceReport_1->AppendText(System::String::Concat("\n Max ANT Channels: ", pcBuffer_[0]));
  166. numChannels = pcBuffer_[0];
  167. // Store the capabilities bytes
  168. sMyCapabilities.ucStandardOptions = pcBuffer_[2];
  169. sMyCapabilities.ucAdvancedOptions = pcBuffer_[3];
  170. sMyCapabilities.ucAdvancedOptions2 = pcBuffer_[4];
  171. // Need to call CreateChannels here using Invoke to avoid cross-thread issues.
  172. MethodInvoker^ CreateChannelsDelegate = gcnew MethodInvoker(this, &MainForm::CreateChannels);
  173. this->Invoke(CreateChannelsDelegate);
  174. richTextBox_deviceReport_1->AppendText(System::String::Concat("\n Max Networks: ", pcBuffer_[1]));
  175. richTextBox_deviceReport_1->AppendText(System::String::Concat("\n Max Data Channels: ", pcBuffer_[5]));
  176. richTextBox_deviceReport_1->AppendText("\nBasic Disabilities: ");
  177. for(i=NUM_BASIC_CAPS-1; i>=0; --i)
  178. {
  179. if(pcBuffer_[2] & basicCapDefs[i].ucBitMask)
  180. {
  181. richTextBox_deviceReport_1->AppendText("\n -");
  182. richTextBox_deviceReport_1->AppendText(gcnew System::String(basicCapDefs[i].flagDefinition));
  183. }
  184. }
  185. if(!pcBuffer_[2])
  186. richTextBox_deviceReport_1->AppendText("None");
  187. richTextBox_deviceReport_1->AppendText("\nExtended Capabilities: ");
  188. for(i=NUM_EXTD_CAPS1-1; i>=0; --i)
  189. {
  190. if(pcBuffer_[3] & extendedCapDefs1[i].ucBitMask)
  191. {
  192. richTextBox_deviceReport_1->AppendText("\n -");
  193. richTextBox_deviceReport_1->AppendText(gcnew System::String(extendedCapDefs1[i].flagDefinition));
  194. }
  195. }
  196. for(i=NUM_EXTD_CAPS2-1; i>=0; --i)
  197. {
  198. if(pcBuffer_[4] & extendedCapDefs2[i].ucBitMask)
  199. {
  200. richTextBox_deviceReport_1->AppendText("\n -");
  201. richTextBox_deviceReport_1->AppendText(gcnew System::String(extendedCapDefs2[i].flagDefinition));
  202. }
  203. }
  204. if(!pcBuffer_[3] && !pcBuffer_[4])
  205. richTextBox_deviceReport_1->AppendText("None");
  206. }
  207. /**************************************************************************
  208. * createChannels
  209. *
  210. * Creates an array of channels, based on the device capabilities
  211. *
  212. * returns: N/A
  213. *
  214. **************************************************************************/
  215. void MainForm::CreateChannels()
  216. {
  217. int i;
  218. channelList = gcnew array<ANTChannel^, 1>(numChannels);
  219. for(i=0; i<numChannels; ++i)
  220. {
  221. channelList[i] = gcnew ANTChannel((UCHAR) i, ucSimType, eMyANTPlatform, sMyCapabilities);
  222. tabControl_Channels->Controls->Add(channelList[i]->getTab());
  223. }
  224. }
  225. /**************************************************************************
  226. * Connect
  227. *
  228. * If not connected, attempt to connect to ANT device. Will initialize ANT
  229. * library, connect at selected baud rate, set non channel specific parameters
  230. * (like ANT+ network key) and create the device GUI. If already connected,
  231. * will disconnect from device and library and remove device panel GUI. IF
  232. * fail, message will be reported. This function does not block pending
  233. * responses from ANT.
  234. *
  235. * Params: N/A
  236. *
  237. * returns: N/A
  238. *
  239. **************************************************************************/
  240. void MainForm::Connect()
  241. {
  242. UCHAR aucANTSportNetworkKey[] = ANTPLUS_NETWORK_KEY;
  243. this->button_Connect->Enabled = false;
  244. this->comboBox_DeviceSelect->Enabled = false;
  245. this->numericUpDown_USBSelect->Enabled = false;
  246. this->textBox_baudRate->Enabled = false;
  247. if(!bMyConnected)
  248. {
  249. ULONG ulBaud;
  250. UCHAR ucUSB;
  251. UCHAR portType = PORT_TYPE_USB;
  252. UCHAR framerType = FRAMER_TYPE_BASIC;
  253. try
  254. {
  255. if(comboBox_DeviceSelect->SelectedItem->Equals("AP2/USB2/AT3"))
  256. {
  257. ulBaud = 57600;
  258. eMyANTPlatform = PLATFORM_AP2_USB2_AT3;
  259. }
  260. else if(comboBox_DeviceSelect->SelectedItem->Equals("C7"))
  261. {
  262. ulBaud = 57600;
  263. eMyANTPlatform = PLATFORM_C7;
  264. }
  265. else if(comboBox_DeviceSelect->SelectedItem->Equals("AP1/USB1"))
  266. {
  267. ulBaud = 50000;
  268. eMyANTPlatform = PLATFORM_AP1_ANT11TR;
  269. }
  270. else
  271. {
  272. try
  273. {
  274. ulBaud = System::UInt32::Parse(this->textBox_baudRate->Text);
  275. }
  276. catch(...)
  277. {
  278. this->richTextBox_MainStatus->AppendText("\nCould not parse baud rate. Try again using a valid unsigned long in decimal format.");
  279. }
  280. if(comboBox_DeviceSelect->SelectedItem->Equals("Custom USB"))
  281. {
  282. eMyANTPlatform = PLATFORM_UNKNOWN;
  283. }
  284. else
  285. {
  286. throw "Invalid selection";
  287. }
  288. }
  289. }
  290. catch(...)
  291. {
  292. this->richTextBox_MainStatus->AppendText("\nPlease select a valid device before connecting.");
  293. this->button_Connect->Enabled = true;
  294. this->comboBox_DeviceSelect->Enabled = true;
  295. this->numericUpDown_USBSelect->Enabled = true;
  296. this->textBox_baudRate->Enabled = true;
  297. return;
  298. }
  299. ucUSB = (UCHAR)numericUpDown_USBSelect->Value;
  300. // Load ANT Library
  301. if( !ANTClass::LibInit((ANT_EVENT_RESPONSE_FUNC )UnmanagedEventSender) )
  302. {
  303. MessageBox::Show("Failed to load ANT DLL", "Error", MessageBoxButtons::OK,MessageBoxIcon::Error, MessageBoxDefaultButton::Button1);
  304. return;
  305. }
  306. // Get library version
  307. const UCHAR* aucVerBuffer = ANTClass::GetLibVersion();
  308. if(aucVerBuffer)
  309. strLibVersion = gcnew System::String((char*) aucVerBuffer);
  310. else
  311. strLibVersion = nullptr;
  312. // Initialize the ANT Library
  313. if (ANTClass::Init(safe_cast<UCHAR>(numericUpDown_USBSelect->Value),ulBaud, portType, framerType) == TRUE)
  314. {
  315. ANTClass::ResetSystem(); // Will sleep for 600 ms
  316. // Update the GUI
  317. button_Connect->Text = "Disconnect";
  318. bMyConnected = TRUE;
  319. richTextBox_MainStatus->AppendText("\n...Connecting");
  320. CreateDevicePanel();
  321. // Set the Network Key
  322. {
  323. UCHAR aucANTSportNetworkKey[] = ANTPLUS_NETWORK_KEY;
  324. ANTClass::SetNetworkKey(ANTPLUS_NETWORK_NUMBER, aucANTSportNetworkKey);
  325. }
  326. }
  327. else
  328. {
  329. this->comboBox_DeviceSelect->Enabled = true;
  330. this->numericUpDown_USBSelect->Enabled = true;
  331. this->textBox_baudRate->Enabled = true;
  332. MessageBox::Show("ANT Initialization failed", "Error", MessageBoxButtons::OK,MessageBoxIcon::Error, MessageBoxDefaultButton::Button1);
  333. }
  334. }
  335. else
  336. {
  337. ANTClass::Disconnect();
  338. // Update GUI
  339. button_Connect->Text = "Connect";
  340. bMyConnected = FALSE;
  341. richTextBox_MainStatus->AppendText("\n...Disconnecting");
  342. RemoveDevicePanel();
  343. if(channelList){
  344. while(numChannels)
  345. delete channelList[--numChannels];
  346. delete channelList;
  347. }
  348. this->Height = 553;
  349. numChannels=0;
  350. this->comboBox_DeviceSelect->Enabled = true;
  351. this->numericUpDown_USBSelect->Enabled = true;
  352. this->textBox_baudRate->Enabled = true;
  353. }
  354. this->button_Connect->Enabled = true;
  355. }
  356. /**************************************************************************
  357. * ProcessChannelEvent
  358. *
  359. * Process ANT channel events by passing them off to the appropriate channel
  360. *
  361. * ucChannel_: ANT channel
  362. * ucMessageCode_: message code returned from ANT
  363. * pucBuffer_: Buffer of message recieved from ANT
  364. *
  365. * returns: N/A
  366. *
  367. **************************************************************************/
  368. void MainForm::ProcessChannelEvent(UCHAR ucChannel_, UCHAR ucMessageCode_, UCHAR* pucBuffer_)
  369. {
  370. if(channelList && ucChannel_ < numChannels)
  371. channelList[ucChannel_]->ANTChannelEvent(ucMessageCode_, pucBuffer_);
  372. }
  373. /**************************************************************************
  374. * ProcessProtocolEvent
  375. *
  376. * Process ANT protocol responses.
  377. *
  378. * ucChannel_: channel number
  379. * ucMessageCode_: message code received from ANT
  380. * pucBuffer_: Buffer of message recieved from ANT
  381. *
  382. * returns: N/A
  383. *
  384. **************************************************************************/
  385. void MainForm::ProcessProtocolEvent(UCHAR ucChannel_, UCHAR ucMessageCode_, UCHAR* pucBuffer_)
  386. {
  387. BOOL bPassOn = FALSE;
  388. switch(ucMessageCode_)
  389. {
  390. case MESG_CAPABILITIES_ID:
  391. {
  392. InterpretCapabilities(&pucBuffer_[0]);
  393. ANTClass::AssignChannelEventFunctions(numChannels, (ANT_RESPONSE_FUNC) UnmanagedSender);
  394. // Check if serial number available, if it is then
  395. // request it.
  396. if(pucBuffer_[3] & CAPABILITIES_SERIAL_NUMBER_ENABLED)
  397. ANTClass::RequestMessage(0,MESG_GET_SERIAL_NUM_ID);
  398. break;
  399. }
  400. case MESG_GET_SERIAL_NUM_ID:
  401. {
  402. int iSerialNum = (pucBuffer_[0] | (pucBuffer_[1] << 8) | (pucBuffer_[2] << 16) | (pucBuffer_[3] << 24));
  403. richTextBox_MainStatus->AppendText("\nDevice Sent Serial Number");
  404. richTextBox_deviceReport_1->AppendText(System::String::Concat("\n Serial Number: ", iSerialNum));
  405. // If serial number avialable, assume that version is
  406. // as well so request it.
  407. ANTClass::RequestMessage(0,MESG_VERSION_ID);
  408. break;
  409. }
  410. case MESG_VERSION_ID:
  411. {
  412. richTextBox_MainStatus->AppendText("\nDevice Sent Version Info");
  413. richTextBox_deviceReport_1->AppendText(System::String::Concat("\n RF Protocol Software Version: ", gcnew System::String((char*)pucBuffer_)));
  414. break;
  415. }
  416. case MESG_RESPONSE_EVENT_ID:
  417. {
  418. // Handle responses to non-channel specific commands here
  419. // Pass the other events to individual channels to handle.
  420. if(pucBuffer_[2] == RESPONSE_NO_ERROR)
  421. {
  422. switch (pucBuffer_[1])
  423. {
  424. case MESG_NETWORK_KEY_ID:
  425. {
  426. // Request capabilites from the ANT device.
  427. ANTClass::RequestMessage(0,MESG_CAPABILITIES_ID);
  428. break;
  429. }
  430. case MESG_RADIO_TX_POWER_ID:
  431. {
  432. richTextBox_MainStatus->AppendText("\nDevice Changed Transmit Power");
  433. break;
  434. }
  435. default:
  436. {
  437. bPassOn = TRUE;
  438. break;
  439. }
  440. }
  441. }
  442. else
  443. {
  444. String^ strError = gcnew String ("\nError Response " + pucBuffer_[2].ToString() + " to command " + pucBuffer_[1].ToString() + "\n");
  445. richTextBox_MainStatus->AppendText(strError);
  446. if( pucBuffer_[2] == EVENT_COMMAND_TIMEOUT)
  447. {
  448. richTextBox_MainStatus->AppendText("COMMAND TIMEOUT!!!\n");
  449. }
  450. }
  451. break;
  452. }
  453. default:
  454. {
  455. bPassOn = TRUE;
  456. break;
  457. }
  458. }
  459. // If not handled here, pass it off to the individual channel.
  460. if(bPassOn && channelList && ucChannel_ < numChannels)
  461. channelList[ucChannel_]->ANTProtocolEvent(ucMessageCode_, pucBuffer_);
  462. }