Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

CCFUtilsBinary.cpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. // =STS=> CCFUtilsBinary.cpp[4874].aa02 open SMID:2
  2. //////////////////////////////////////////////////////////////////////
  3. //
  4. // (c) Copyright 2012-2013 Blackrock Microsystems
  5. //
  6. // $Workfile: CCFUtilsBinary.cpp $
  7. // $Archive: /Cerebus/Human/WindowsApps/cbhwlib/CCFUtilsBinary.cpp $
  8. // $Revision: 1 $
  9. // $Date: 4/10/12 1:40p $
  10. // $Author: Ehsan $
  11. //
  12. // $NoKeywords: $
  13. //
  14. //////////////////////////////////////////////////////////////////////
  15. #include "StdAfx.h"
  16. #include "CCFUtilsBinary.h"
  17. #include <stddef.h>
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[]=__FILE__;
  21. #endif
  22. using namespace ccf;
  23. const char CCFUtilsBinary::m_szConfigFileHeader[7] = "cbCCF ";
  24. const char CCFUtilsBinary::m_szConfigFileVersion[11] = "1234567890"; // room for 9
  25. // Author & Date: Ehsan Azar 11 April 2012
  26. // Purpose: CCF binary constructor
  27. CCFUtilsBinary::CCFUtilsBinary()
  28. {
  29. memset(&m_data, 0, sizeof(m_data));
  30. // This is the internal version of the format we binary is stored
  31. m_nInternalVersion = CCFUTILSBINARY_LASTVERSION;
  32. }
  33. // Author & Date: Ehsan Azar 10 June 2012
  34. // Purpose: Read binary CCF file version
  35. // Inputs:
  36. // szFileName - the name of the file to read
  37. ccfResult CCFUtilsBinary::ReadVersion(LPCSTR szFileName)
  38. {
  39. FILE * hSettingsFile = 0;
  40. ccfResult res = CCFRESULT_SUCCESS;
  41. m_szFileName = szFileName;
  42. // Open the file
  43. hSettingsFile = fopen(szFileName, "rb");
  44. if (hSettingsFile == NULL)
  45. return CCFRESULT_ERR_OPENFAILEDREAD;
  46. // Check header and version in file
  47. // Initializing strings in a way that will set elements to zero
  48. char szID[sizeof(m_szConfigFileHeader)] = {0};
  49. char szVersion[sizeof(m_szConfigFileVersion)] = {0};
  50. fread(&szID, sizeof(szID) - 1, 1, hSettingsFile); // -1 'cuz of NULL termination
  51. fread(&szVersion, sizeof(szVersion) - 1, 1, hSettingsFile); // -1 'cuz of NULL termination
  52. // check for previous supported configuration files to convert from
  53. if ((strcmp("cb2003", szID) == 0) && (strncmp("1.0", szVersion, 3) == 0))
  54. m_nInternalOriginalVersion = 1;
  55. else if ((strcmp("cb2005", szID) == 0) && (strcmp("2.5", szVersion) == 0))
  56. m_nInternalOriginalVersion = 2;
  57. else if ((strcmp("cb2005", szID) == 0) && (strcmp("3.0", szVersion) == 0))
  58. m_nInternalOriginalVersion = 3;
  59. else if ((strcmp("cb2005", szID) == 0) && (strcmp("3.1", szVersion) == 0))
  60. m_nInternalOriginalVersion = 4;
  61. else if ((strcmp("cb2005", szID) == 0) && (strcmp("3.2", szVersion) == 0))
  62. m_nInternalOriginalVersion = 5;
  63. else if ((strcmp("cb2005", szID) == 0) && (strcmp("3.3", szVersion) == 0))
  64. m_nInternalOriginalVersion = 6;
  65. else if ((strcmp("cb2005", szID) == 0) && (strcmp("3.4", szVersion) == 0))
  66. m_nInternalOriginalVersion = 7;
  67. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.5", szVersion) == 0))
  68. m_nInternalOriginalVersion = 8;
  69. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.6", szVersion) == 0))
  70. m_nInternalOriginalVersion = 9;
  71. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.7", szVersion) == 0))
  72. m_nInternalOriginalVersion = 10;
  73. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.8", szVersion) == 0))
  74. m_nInternalOriginalVersion = 11;
  75. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.9", szVersion) == 0))
  76. m_nInternalOriginalVersion = 11;
  77. else if ((strcmp("cbCCF ", szID) == 0) && (strcmp("3.10", szVersion) == 0))
  78. m_nInternalOriginalVersion = 12;
  79. else
  80. m_nInternalOriginalVersion = 0;
  81. fclose(hSettingsFile);
  82. if (m_nInternalOriginalVersion == 0)
  83. res = CCFRESULT_ERR_FORMAT;
  84. else
  85. m_bBinaryOriginal = TRUE;
  86. return res;
  87. }
  88. // Author & Date: Hyrum L. Sessions 10 July 2006
  89. // Purpose: Read in a binary CCF file. Check for the correct version of the file
  90. // and convert if necessary and possible
  91. // Inputs:
  92. // szFileName - the name of the file to read
  93. // bConvert - if convertion can happen
  94. ccfResult CCFUtilsBinary::ReadCCF(LPCSTR szFileName, bool bConvert)
  95. {
  96. ccfResult res = CCFRESULT_SUCCESS;
  97. // First read the version
  98. res = ReadVersion(szFileName);
  99. if (res)
  100. return res;
  101. m_szFileName = szFileName;
  102. // Open the file
  103. FILE * hSettingsFile = fopen(szFileName, "rb");
  104. if (hSettingsFile == NULL)
  105. return CCFRESULT_ERR_OPENFAILEDREAD;
  106. // Check header and version in file
  107. // Initializing strings in a way that will set elements to zero
  108. char szID[sizeof(m_szConfigFileHeader)] = {0};
  109. char szVersion[sizeof(m_szConfigFileVersion)] = {0};
  110. fread(&szID, sizeof(szID) - 1, 1, hSettingsFile); // -1 'cuz of NULL termination
  111. fread(&szVersion, sizeof(szVersion) - 1, 1, hSettingsFile); // -1 'cuz of NULL termination
  112. // These versions require conversion to 3.10
  113. if (m_nInternalOriginalVersion >= 1 && m_nInternalOriginalVersion <= 11)
  114. {
  115. if (!bConvert)
  116. {
  117. res = CCFRESULT_WARN_CONVERT;
  118. fclose(hSettingsFile);
  119. return res;
  120. }
  121. }
  122. // Now read and convert
  123. switch (m_nInternalOriginalVersion)
  124. {
  125. case 0:
  126. res = CCFRESULT_ERR_FORMAT;
  127. break;
  128. case 1:
  129. res = ReadCCFData_cb2003_10(hSettingsFile);
  130. break;
  131. case 2:
  132. res = ReadCCFData_cb2005_25(hSettingsFile);
  133. break;
  134. case 3:
  135. res = ReadCCFData_cb2005_30(hSettingsFile);
  136. break;
  137. case 4:
  138. res = ReadCCFData_cb2005_31(hSettingsFile); // Unit override was added
  139. break;
  140. case 5:
  141. res = ReadCCFData_cb2005_31(hSettingsFile); // chaninfo packets are the same as 3.1, so call it...
  142. break;
  143. case 6:
  144. res = ReadCCFData_cb2005_31(hSettingsFile); // chaninfo packets are the same as 3.1, so call it...
  145. break;
  146. case 7:
  147. res = ReadCCFData_cb2005_34(hSettingsFile); // unit override changed to ellipse
  148. break;
  149. case 8:
  150. res = ReadCCFData_cb2005_35(hSettingsFile); // added lncdispmax & refelecchan
  151. break;
  152. case 9:
  153. res = ReadCCFData_cb2005_36(hSettingsFile); // manual unit mapping dimension changed to 3
  154. break;
  155. case 10:
  156. res = ReadCCFData_cb2005_37(hSettingsFile); // manual unit mapping changed from float to int16
  157. break;
  158. case 11:
  159. res = ReadCCFData_cb2005_37(hSettingsFile); // chaninfo packets are the same as 3.7, so call it...
  160. break;
  161. case 12:
  162. res = ReadCCFData_cb2005_310(hSettingsFile); // added trigtype, trigchan, and trigval
  163. break;
  164. default:
  165. res = CCFRESULT_ERR_FORMAT;
  166. break;
  167. }
  168. fclose(hSettingsFile);
  169. return res;
  170. }
  171. // Author & Date: Ehsan Azar 12 April 2012
  172. // Purpose: Convert from older version
  173. CCFUtils * CCFUtilsBinary::Convert(CCFUtils * pOldConfig)
  174. {
  175. // Nothing to convert
  176. return NULL;
  177. }
  178. // Author & Date: Hyrum L. Sessions 9 June 2008
  179. // Purpose: load the default channel information
  180. // Inputs: isChan - structure to fill with the default information
  181. void CCFUtilsBinary::SetChannelDefaults(cbPKT_CHANINFO &isChan)
  182. {
  183. memset(&isChan, 0, sizeof(isChan));
  184. isChan.time = 0;
  185. isChan.chid = 0x8000;
  186. isChan.type = cbPKTTYPE_CHANSET;
  187. isChan.dlen = cbPKTDLEN_CHANINFO_CB2005_37;
  188. isChan.lncdispmax = 511;
  189. isChan.refelecchan = 0;
  190. // set unit overrides to default values
  191. for (int i = 0; i < cbLEGACY_MAXUNITS; ++i)
  192. isChan.unitmapping[i].nOverride = i;
  193. }
  194. // Author & Date: Hyrum L. Sessions 11 Jul 2006
  195. // Purpose: load the channel configuration from the file
  196. // convert the data from cb2005 v2.5 to the current
  197. // Inputs: hFile - the file, positioned at the beginning of the channel data
  198. ccfResult CCFUtilsBinary::ReadCCFData_cb2003_10(FILE * hFile)
  199. {
  200. // there were 2 different versions of cb2003 v1.0 When anagain was added to the
  201. // protocol, the version wasn't changed as it should have been. We can differenciate
  202. // between the 2 by the file size. I've called the first version A and the second one B
  203. // position file pointer to the end of the file and get it's position
  204. fseek(hFile, 0, SEEK_END);
  205. long lFileSize = ftell(hFile);
  206. // position file pointer to just after the header info. For cb2003 v1.0, the
  207. // version string was only 3 chars wide
  208. fseek(hFile, sizeof(m_szConfigFileHeader) - 1 + 3, SEEK_SET);
  209. // check for "A" type file based on size
  210. if ((lFileSize - m_iPreviousHeaderSize - sizeof(cbPKT_ADAPTFILTINFO) == sizeof(cbPKT_CHANINFO_CB2003_10A) * cbLEGACY_MAXCHANS) ||
  211. (lFileSize - m_iPreviousHeaderSize == sizeof(cbPKT_CHANINFO_CB2003_10A) * cbLEGACY_MAXCHANS))
  212. return ReadCCFData_cb2003_10_a(hFile);
  213. // check for "B" type file based on size -- it is the same chaninfo as cb2005 3.0
  214. else if (lFileSize - m_iPreviousHeaderSize - sizeof(cbPKT_ADAPTFILTINFO) == sizeof(cbPKT_CHANINFO_CB2005_30) * cbLEGACY_MAXCHANS)
  215. return ReadCCFData_cb2003_10_b(hFile);
  216. else
  217. return CCFRESULT_ERR_FORMAT;
  218. }
  219. // Author & Date: Hyrum L. Sessions 11 Jul 2006
  220. // Purpose: load the channel configuration from the file
  221. // convert the data from cb2003 v1.0 type A to the current
  222. // Inputs: hFile - the file, positioned at the beginning of the channel data
  223. ccfResult CCFUtilsBinary::ReadCCFData_cb2003_10_a(FILE * hFile)
  224. {
  225. // Copy data into buffer
  226. cbPKT_CHANINFO_CB2003_10A isChanFile;
  227. // Read configuration
  228. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  229. {
  230. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  231. SetChannelDefaults(isChan);
  232. memset(&isChanFile, 0, sizeof(isChanFile));
  233. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  234. // We only need to read packets for valid channels. There could be an
  235. // error reading the file, or we could be past the end of valid chans
  236. if (isChanFile.chan != 0)
  237. {
  238. // copy the data from the structure read from the file to the current chaninfo structure
  239. isChan.chan = isChanFile.chan;
  240. isChan.proc = isChanFile.proc;
  241. isChan.bank = isChanFile.bank;
  242. isChan.term = isChanFile.term;
  243. isChan.chancaps = isChanFile.chancaps;
  244. isChan.doutcaps = isChanFile.doutcaps;
  245. isChan.dinpcaps = isChanFile.dinpcaps;
  246. isChan.aoutcaps = isChanFile.aoutcaps;
  247. isChan.ainpcaps = isChanFile.ainpcaps;
  248. isChan.spkcaps = isChanFile.spkcaps;
  249. cpyScaling(isChan.physcalin, isChanFile.physcalin);
  250. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  251. cpyScaling(isChan.physcalout, isChanFile.physcalout);
  252. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  253. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  254. isChan.userflags = isChanFile.userflags;
  255. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  256. cpyScaling(isChan.scalin, isChanFile.scalin);
  257. cpyScaling(isChan.scalout, isChanFile.scalout);
  258. isChan.doutopts = isChanFile.doutopts;
  259. isChan.dinpopts = isChanFile.dinpopts;
  260. isChan.aoutopts = isChanFile.aoutopts;
  261. isChan.eopchar = isChanFile.eopchar;
  262. isChan.monsource = isChanFile.monsource;
  263. isChan.outvalue = isChanFile.outvalue;
  264. isChan.ainpopts = isChanFile.lncmode;
  265. isChan.lncrate = isChanFile.lncrate;
  266. isChan.smpfilter = isChanFile.smpfilter;
  267. isChan.smpgroup = isChanFile.smpgroup;
  268. isChan.smpdispmin = isChanFile.smpdispmin;
  269. isChan.smpdispmax = isChanFile.smpdispmax;
  270. isChan.spkfilter = isChanFile.spkfilter;
  271. isChan.spkdispmax = isChanFile.spkdispmax;
  272. isChan.spkopts = isChanFile.spkopts;
  273. isChan.spkthrlevel = isChanFile.spkthrlevel;
  274. isChan.spkthrlimit = isChanFile.spkthrlimit;
  275. isChan.spkgroup = isChanFile.spkgroup;
  276. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  277. }
  278. }
  279. // now read the rest of the file as individual packets and transmit it to the NSP
  280. ReadAsPackets(hFile);
  281. if (m_bAutoSort)
  282. {
  283. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  284. {
  285. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  286. if (isChan.chan)
  287. {
  288. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  289. isChan.spkfilter = 2;
  290. }
  291. }
  292. }
  293. return CCFRESULT_SUCCESS;
  294. }
  295. // Author & Date: Hyrum L. Sessions 11 Jul 2006
  296. // Purpose: load the channel configuration from the file
  297. // convert the data from cb2003 v1.0 type B to the current
  298. // Inputs: hFile - the file, positioned at the beginning of the channel data
  299. ccfResult CCFUtilsBinary::ReadCCFData_cb2003_10_b(FILE * hFile)
  300. {
  301. // data is the same as cb2005 3.0, so just load it...
  302. return ReadCCFData_cb2005_30(hFile);
  303. }
  304. // Author & Date: Hyrum L. Sessions 11 Jul 2006
  305. // Purpose: load the channel configuration from the file
  306. // convert the data from cb2005 v2.5 to the current
  307. // Inputs: hFile - the file, positioned at the beginning of the channel data
  308. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_25(FILE * hFile)
  309. {
  310. // Copy data into buffer
  311. cbPKT_CHANINFO_CB2005_25 isChanFile;
  312. // Read configuration to Cerebus
  313. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  314. {
  315. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  316. SetChannelDefaults(isChan);
  317. memset(&isChanFile, 0, sizeof(isChanFile));
  318. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  319. // We only need to read packets for valid channels. There could be an
  320. // error reading the file, or we could be past the end of valid chans
  321. if (isChanFile.chan != 0)
  322. {
  323. // copy the data from the structure read from the file to the current chaninfo structure
  324. isChan.chan = isChanFile.chan;
  325. isChan.proc = isChanFile.proc;
  326. isChan.bank = isChanFile.bank;
  327. isChan.term = isChanFile.term;
  328. isChan.chancaps = isChanFile.chancaps;
  329. isChan.doutcaps = isChanFile.doutcaps;
  330. isChan.dinpcaps = isChanFile.dinpcaps;
  331. isChan.aoutcaps = isChanFile.aoutcaps;
  332. isChan.ainpcaps = isChanFile.ainpcaps;
  333. isChan.spkcaps = isChanFile.spkcaps;
  334. cpyScaling(isChan.physcalin, isChanFile.physcalin);
  335. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  336. cpyScaling(isChan.physcalout, isChanFile.physcalout);
  337. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  338. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  339. isChan.userflags = isChanFile.userflags;
  340. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  341. cpyScaling(isChan.scalin, isChanFile.scalin);
  342. cpyScaling(isChan.scalout, isChanFile.scalout);
  343. isChan.doutopts = isChanFile.doutopts;
  344. isChan.dinpopts = isChanFile.dinpopts;
  345. isChan.aoutopts = isChanFile.aoutopts;
  346. isChan.eopchar = isChanFile.eopchar;
  347. isChan.monsource = isChanFile.monsource;
  348. isChan.outvalue = isChanFile.outvalue;
  349. isChan.ainpopts = isChanFile.lncmode;
  350. isChan.lncrate = isChanFile.lncrate;
  351. isChan.smpfilter = isChanFile.smpfilter;
  352. isChan.smpgroup = isChanFile.smpgroup;
  353. isChan.smpdispmin = isChanFile.smpdispmin;
  354. isChan.smpdispmax = isChanFile.smpdispmax;
  355. isChan.spkfilter = isChanFile.spkfilter;
  356. isChan.spkdispmax = isChanFile.spkdispmax;
  357. isChan.spkopts = isChanFile.spkopts;
  358. isChan.spkthrlevel = isChanFile.spkthrlevel;
  359. isChan.spkthrlimit = isChanFile.spkthrlimit;
  360. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  361. }
  362. }
  363. // now read the rest of the file as individual packets and transmit it to the NSP
  364. ReadAsPackets(hFile);
  365. if (m_bAutoSort)
  366. {
  367. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  368. {
  369. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  370. if (isChan.chan)
  371. {
  372. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  373. isChan.spkfilter = 2;
  374. }
  375. }
  376. }
  377. return CCFRESULT_SUCCESS;
  378. }
  379. // Author & Date: Hyrum L. Sessions 15 Sept 2006
  380. // Purpose: load the channel configuration from the file
  381. // convert the data from cb2005 v3.0 to the current
  382. // Inputs: hFile - the file, positioned at the beginning of the channel data
  383. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_30(FILE * hFile)
  384. {
  385. // Copy data into buffer
  386. cbPKT_CHANINFO_CB2005_30 isChanFile;
  387. // Read configuration to Cerebus
  388. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  389. {
  390. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  391. SetChannelDefaults(isChan);
  392. memset(&isChanFile, 0, sizeof(isChanFile));
  393. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  394. // We only need to read packets for valid channels. There could be an
  395. // error reading the file, or we could be past the end of valid chans
  396. if (isChanFile.chan != 0)
  397. {
  398. // copy the data from the structure read from the file to the current chaninfo structure
  399. isChan.chan = isChanFile.chan;
  400. isChan.proc = isChanFile.proc;
  401. isChan.bank = isChanFile.bank;
  402. isChan.term = isChanFile.term;
  403. isChan.chancaps = isChanFile.chancaps;
  404. isChan.doutcaps = isChanFile.doutcaps;
  405. isChan.dinpcaps = isChanFile.dinpcaps;
  406. isChan.aoutcaps = isChanFile.aoutcaps;
  407. isChan.ainpcaps = isChanFile.ainpcaps;
  408. isChan.spkcaps = isChanFile.spkcaps;
  409. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  410. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  411. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  412. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  413. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  414. isChan.userflags = isChanFile.userflags;
  415. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  416. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  417. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  418. isChan.doutopts = isChanFile.doutopts;
  419. isChan.dinpopts = isChanFile.dinpopts;
  420. isChan.aoutopts = isChanFile.aoutopts;
  421. isChan.eopchar = isChanFile.eopchar;
  422. isChan.monsource = isChanFile.monsource;
  423. isChan.outvalue = isChanFile.outvalue;
  424. isChan.ainpopts = isChanFile.lncmode;
  425. isChan.lncrate = isChanFile.lncrate;
  426. isChan.smpfilter = isChanFile.smpfilter;
  427. isChan.smpgroup = isChanFile.smpgroup;
  428. isChan.smpdispmin = isChanFile.smpdispmin;
  429. isChan.smpdispmax = isChanFile.smpdispmax;
  430. isChan.spkfilter = isChanFile.spkfilter;
  431. isChan.spkdispmax = isChanFile.spkdispmax;
  432. isChan.spkopts = isChanFile.spkopts;
  433. isChan.spkthrlevel = isChanFile.spkthrlevel;
  434. isChan.spkthrlimit = isChanFile.spkthrlimit;
  435. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  436. }
  437. }
  438. // now read the rest of the file as individual packets and transmit it to the NSP
  439. ReadAsPackets(hFile);
  440. if (m_bAutoSort)
  441. {
  442. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  443. {
  444. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  445. if (isChan.chan)
  446. {
  447. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  448. isChan.spkfilter = 2;
  449. }
  450. }
  451. }
  452. return CCFRESULT_SUCCESS;
  453. }
  454. // Author & Date: Hyrum L. Sessions 4 Jun 2008
  455. // Purpose: load the channel configuration from the file
  456. // convert the data from cb2005 v3.1 to the current
  457. // Inputs: hFile - the file, positioned at the beginning of the channel data
  458. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_31(FILE * hFile)
  459. {
  460. // Copy data into buffer
  461. cbPKT_CHANINFO_CB2005_31 isChanFile;
  462. // Read configuration to Cerebus
  463. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  464. {
  465. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  466. SetChannelDefaults(isChan);
  467. memset(&isChanFile, 0, sizeof(isChanFile));
  468. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  469. // We only need to read packets for valid channels. There could be an
  470. // error reading the file, or we could be past the end of valid chans
  471. if (isChanFile.chan != 0)
  472. {
  473. // copy the data from the structure read from the file to the current chaninfo structure
  474. isChan.chan = isChanFile.chan;
  475. isChan.proc = isChanFile.proc;
  476. isChan.bank = isChanFile.bank;
  477. isChan.term = isChanFile.term;
  478. isChan.chancaps = isChanFile.chancaps;
  479. isChan.doutcaps = isChanFile.doutcaps;
  480. isChan.dinpcaps = isChanFile.dinpcaps;
  481. isChan.aoutcaps = isChanFile.aoutcaps;
  482. isChan.ainpcaps = isChanFile.ainpcaps;
  483. isChan.spkcaps = isChanFile.spkcaps;
  484. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  485. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  486. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  487. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  488. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  489. isChan.userflags = isChanFile.userflags;
  490. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  491. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  492. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  493. isChan.doutopts = isChanFile.doutopts;
  494. isChan.dinpopts = isChanFile.dinpopts;
  495. isChan.aoutopts = isChanFile.aoutopts;
  496. isChan.eopchar = isChanFile.eopchar;
  497. isChan.monsource = isChanFile.monsource;
  498. isChan.outvalue = isChanFile.outvalue;
  499. isChan.ainpopts = isChanFile.lncmode;
  500. isChan.lncrate = isChanFile.lncrate;
  501. isChan.smpfilter = isChanFile.smpfilter;
  502. isChan.smpgroup = isChanFile.smpgroup;
  503. isChan.smpdispmin = isChanFile.smpdispmin;
  504. isChan.smpdispmax = isChanFile.smpdispmax;
  505. isChan.spkfilter = isChanFile.spkfilter;
  506. isChan.spkdispmax = isChanFile.spkdispmax;
  507. isChan.spkopts = isChanFile.spkopts;
  508. isChan.spkthrlevel = isChanFile.spkthrlevel;
  509. isChan.spkthrlimit = isChanFile.spkthrlimit;
  510. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  511. for (int unit = 0; unit < cbLEGACY_MAXUNITS; ++unit)
  512. {
  513. float radius;
  514. isChan.unitmapping[unit].nOverride = isChanFile.unitmapping[unit].nOverride;
  515. isChan.unitmapping[unit].afOrigin[0] = isChanFile.unitmapping[unit].xOrigin;
  516. isChan.unitmapping[unit].afOrigin[1] = isChanFile.unitmapping[unit].yOrigin;
  517. isChan.unitmapping[unit].afOrigin[2] = 0;
  518. radius = float(isChanFile.unitmapping[unit].radius);
  519. if (radius != 0)
  520. {
  521. isChan.unitmapping[unit].bValid = 1;
  522. isChan.unitmapping[unit].afShape[0][0] = int16_t(1 / (radius * radius));
  523. isChan.unitmapping[unit].afShape[1][1] = int16_t(1 / (radius * radius));
  524. isChan.unitmapping[unit].afShape[2][2] = int16_t(1 / (radius * radius));
  525. }
  526. }
  527. }
  528. }
  529. // now read the rest of the file as individual packets and transmit it to the NSP
  530. ReadAsPackets(hFile);
  531. if (m_bAutoSort)
  532. {
  533. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  534. {
  535. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  536. if (isChan.chan)
  537. {
  538. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  539. isChan.spkfilter = 2;
  540. }
  541. }
  542. }
  543. return CCFRESULT_SUCCESS;
  544. }
  545. // Author & Date: Hyrum L. Sessions 4 Jun 2008
  546. // Purpose: load the channel configuration from the file
  547. // convert the data from cb2005 v3.4 to the current
  548. // Inputs: hFile - the file, positioned at the beginning of the channel data
  549. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_34(FILE * hFile)
  550. {
  551. // Copy data into buffer
  552. cbPKT_CHANINFO_CB2005_34 isChanFile;
  553. // Read configuration to Cerebus
  554. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  555. {
  556. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  557. SetChannelDefaults(isChan);
  558. memset(&isChanFile, 0, sizeof(isChanFile));
  559. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  560. // We only need to read packets for valid channels. There could be an
  561. // error reading the file, or we could be past the end of valid chans
  562. if (isChanFile.chan != 0)
  563. {
  564. // copy the data from the structure read from the file to the current chaninfo structure
  565. isChan.chan = isChanFile.chan;
  566. isChan.proc = isChanFile.proc;
  567. isChan.bank = isChanFile.bank;
  568. isChan.term = isChanFile.term;
  569. isChan.chancaps = isChanFile.chancaps;
  570. isChan.doutcaps = isChanFile.doutcaps;
  571. isChan.dinpcaps = isChanFile.dinpcaps;
  572. isChan.aoutcaps = isChanFile.aoutcaps;
  573. isChan.ainpcaps = isChanFile.ainpcaps;
  574. isChan.spkcaps = isChanFile.spkcaps;
  575. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  576. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  577. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  578. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  579. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  580. isChan.userflags = isChanFile.userflags;
  581. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  582. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  583. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  584. isChan.doutopts = isChanFile.doutopts;
  585. isChan.dinpopts = isChanFile.dinpopts;
  586. isChan.aoutopts = isChanFile.aoutopts;
  587. isChan.eopchar = isChanFile.eopchar;
  588. isChan.monsource = isChanFile.monsource;
  589. isChan.outvalue = isChanFile.outvalue;
  590. isChan.ainpopts = isChanFile.lncmode;
  591. isChan.lncrate = isChanFile.lncrate;
  592. isChan.smpfilter = isChanFile.smpfilter;
  593. isChan.smpgroup = isChanFile.smpgroup;
  594. isChan.smpdispmin = isChanFile.smpdispmin;
  595. isChan.smpdispmax = isChanFile.smpdispmax;
  596. isChan.spkfilter = isChanFile.spkfilter;
  597. isChan.spkdispmax = isChanFile.spkdispmax;
  598. isChan.spkopts = isChanFile.spkopts;
  599. isChan.spkthrlevel = isChanFile.spkthrlevel;
  600. isChan.spkthrlimit = isChanFile.spkthrlimit;
  601. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  602. for (int unit = 0; unit < cbLEGACY_MAXUNITS; ++unit)
  603. {
  604. isChan.unitmapping[unit].nOverride = isChanFile.unitmapping[unit].nOverride;
  605. isChan.unitmapping[unit].afOrigin[0] = int16_t(isChanFile.unitmapping[unit].afOrigin[0]);
  606. isChan.unitmapping[unit].afOrigin[1] = int16_t(isChanFile.unitmapping[unit].afOrigin[1]);
  607. isChan.unitmapping[unit].afOrigin[2] = 0;
  608. isChan.unitmapping[unit].afShape[0][0] = int16_t(isChanFile.unitmapping[unit].afShape[0][0]);
  609. isChan.unitmapping[unit].afShape[0][1] = int16_t(isChanFile.unitmapping[unit].afShape[0][1]);
  610. isChan.unitmapping[unit].afShape[1][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  611. isChan.unitmapping[unit].afShape[1][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  612. isChan.unitmapping[unit].afShape[2][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  613. isChan.unitmapping[unit].afShape[2][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  614. isChan.unitmapping[unit].aPhi = int16_t(isChanFile.unitmapping[unit].aPhi);
  615. isChan.unitmapping[unit].bValid = int16_t(isChanFile.unitmapping[unit].bValid);
  616. }
  617. }
  618. }
  619. // now read the rest of the file as individual packets and transmit it to the NSP
  620. ReadAsPackets(hFile);
  621. if (m_bAutoSort)
  622. {
  623. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  624. {
  625. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  626. if (isChan.chan)
  627. {
  628. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  629. isChan.spkfilter = 2;
  630. }
  631. }
  632. }
  633. return CCFRESULT_SUCCESS;
  634. }
  635. // Author & Date: Hyrum L. Sessions 13 Nov 2009
  636. // Purpose: load the channel configuration from the file
  637. // convert the data from cb2005 v3.5 to the current
  638. // Inputs: hFile - the file, positioned at the beginning of the channel data
  639. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_35(FILE * hFile)
  640. {
  641. // Copy data into buffer
  642. cbPKT_CHANINFO_CB2005_35 isChanFile;
  643. // Read configuration to Cerebus
  644. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  645. {
  646. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  647. SetChannelDefaults(isChan);
  648. memset(&isChanFile, 0, sizeof(isChanFile));
  649. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  650. // We only need to read packets for valid channels. There could be an
  651. // error reading the file, or we could be past the end of valid chans
  652. if (isChanFile.chan != 0)
  653. {
  654. // copy the data from the structure read from the file to the current chaninfo structure
  655. isChan.chan = isChanFile.chan;
  656. isChan.proc = isChanFile.proc;
  657. isChan.bank = isChanFile.bank;
  658. isChan.term = isChanFile.term;
  659. isChan.chancaps = isChanFile.chancaps;
  660. isChan.doutcaps = isChanFile.doutcaps;
  661. isChan.dinpcaps = isChanFile.dinpcaps;
  662. isChan.aoutcaps = isChanFile.aoutcaps;
  663. isChan.ainpcaps = isChanFile.ainpcaps;
  664. isChan.spkcaps = isChanFile.spkcaps;
  665. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  666. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  667. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  668. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  669. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  670. isChan.userflags = isChanFile.userflags;
  671. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  672. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  673. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  674. isChan.doutopts = isChanFile.doutopts;
  675. isChan.dinpopts = isChanFile.dinpopts;
  676. isChan.aoutopts = isChanFile.aoutopts;
  677. isChan.eopchar = isChanFile.eopchar;
  678. isChan.monsource = isChanFile.monsource;
  679. isChan.outvalue = isChanFile.outvalue;
  680. isChan.ainpopts = isChanFile.lncmode;
  681. isChan.lncrate = isChanFile.lncrate;
  682. isChan.smpfilter = isChanFile.smpfilter;
  683. isChan.smpgroup = isChanFile.smpgroup;
  684. isChan.smpdispmin = isChanFile.smpdispmin;
  685. isChan.smpdispmax = isChanFile.smpdispmax;
  686. isChan.spkfilter = isChanFile.spkfilter;
  687. isChan.spkdispmax = isChanFile.spkdispmax;
  688. isChan.spkopts = isChanFile.spkopts;
  689. isChan.spkthrlevel = isChanFile.spkthrlevel;
  690. isChan.spkthrlimit = isChanFile.spkthrlimit;
  691. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  692. for (int unit = 0; unit < cbLEGACY_MAXUNITS; ++unit)
  693. {
  694. isChan.unitmapping[unit].nOverride = isChanFile.unitmapping[unit].nOverride;
  695. isChan.unitmapping[unit].afOrigin[0] = int16_t(isChanFile.unitmapping[unit].afOrigin[0]);
  696. isChan.unitmapping[unit].afOrigin[1] = int16_t(isChanFile.unitmapping[unit].afOrigin[1]);
  697. isChan.unitmapping[unit].afOrigin[2] = 0;
  698. isChan.unitmapping[unit].afShape[0][0] = int16_t(isChanFile.unitmapping[unit].afShape[0][0]);
  699. isChan.unitmapping[unit].afShape[0][1] = int16_t(isChanFile.unitmapping[unit].afShape[0][1]);
  700. isChan.unitmapping[unit].afShape[1][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  701. isChan.unitmapping[unit].afShape[1][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  702. isChan.unitmapping[unit].afShape[2][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  703. isChan.unitmapping[unit].afShape[2][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  704. isChan.unitmapping[unit].aPhi = int16_t(isChanFile.unitmapping[unit].aPhi);
  705. isChan.unitmapping[unit].bValid = int16_t(isChanFile.unitmapping[unit].bValid);
  706. }
  707. }
  708. }
  709. // now read the rest of the file as individual packets and transmit it to the NSP
  710. ReadAsPackets(hFile);
  711. if (m_bAutoSort)
  712. {
  713. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  714. {
  715. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  716. if (isChan.chan)
  717. {
  718. isChan.smpfilter = TranslateAutoFilter(isChanFile.smpfilter);
  719. isChan.spkfilter = 2;
  720. }
  721. }
  722. }
  723. return CCFRESULT_SUCCESS;
  724. }
  725. // Author & Date: Hyrum L. Sessions 29 Nov 2010
  726. // Purpose: load the channel configuration from the file
  727. // convert the data from cb2005 v3.6 to the current
  728. // Inputs: hFile - the file, positioned at the beginning of the channel data
  729. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_36(FILE * hFile)
  730. {
  731. // Copy data into buffer
  732. cbPKT_CHANINFO_CB2005_36 isChanFile;
  733. // Read configuration to Cerebus
  734. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  735. {
  736. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  737. SetChannelDefaults(isChan);
  738. memset(&isChanFile, 0, sizeof(isChanFile));
  739. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  740. // We only need to read packets for valid channels. There could be an
  741. // error reading the file, or we could be past the end of valid chans
  742. if (isChanFile.chan != 0)
  743. {
  744. // copy the data from the structure read from the file to the current chaninfo structure
  745. isChan.chan = isChanFile.chan;
  746. isChan.proc = isChanFile.proc;
  747. isChan.bank = isChanFile.bank;
  748. isChan.term = isChanFile.term;
  749. isChan.chancaps = isChanFile.chancaps;
  750. isChan.doutcaps = isChanFile.doutcaps;
  751. isChan.dinpcaps = isChanFile.dinpcaps;
  752. isChan.aoutcaps = isChanFile.aoutcaps;
  753. isChan.ainpcaps = isChanFile.ainpcaps;
  754. isChan.spkcaps = isChanFile.spkcaps;
  755. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  756. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  757. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  758. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  759. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  760. isChan.userflags = isChanFile.userflags;
  761. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  762. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  763. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  764. isChan.doutopts = isChanFile.doutopts;
  765. isChan.dinpopts = isChanFile.dinpopts;
  766. isChan.aoutopts = isChanFile.aoutopts;
  767. isChan.eopchar = isChanFile.eopchar;
  768. isChan.monsource = isChanFile.monsource;
  769. isChan.outvalue = isChanFile.outvalue;
  770. isChan.ainpopts = isChanFile.ainpopts;
  771. isChan.lncrate = isChanFile.lncrate;
  772. isChan.smpfilter = isChanFile.smpfilter;
  773. isChan.smpgroup = isChanFile.smpgroup;
  774. isChan.smpdispmin = isChanFile.smpdispmin;
  775. isChan.smpdispmax = isChanFile.smpdispmax;
  776. isChan.spkfilter = isChanFile.spkfilter;
  777. isChan.spkdispmax = isChanFile.spkdispmax;
  778. isChan.spkopts = isChanFile.spkopts;
  779. isChan.spkthrlevel = isChanFile.spkthrlevel;
  780. isChan.spkthrlimit = isChanFile.spkthrlimit;
  781. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  782. for (int unit = 0; unit < cbLEGACY_MAXUNITS; ++unit)
  783. {
  784. isChan.unitmapping[unit].nOverride = isChanFile.unitmapping[unit].nOverride;
  785. isChan.unitmapping[unit].afOrigin[0] = int16_t(isChanFile.unitmapping[unit].afOrigin[0]);
  786. isChan.unitmapping[unit].afOrigin[1] = int16_t(isChanFile.unitmapping[unit].afOrigin[1]);
  787. isChan.unitmapping[unit].afOrigin[2] = int16_t(isChanFile.unitmapping[unit].afOrigin[2]);
  788. isChan.unitmapping[unit].afShape[0][0] = int16_t(isChanFile.unitmapping[unit].afShape[0][0]);
  789. isChan.unitmapping[unit].afShape[0][1] = int16_t(isChanFile.unitmapping[unit].afShape[0][1]);
  790. isChan.unitmapping[unit].afShape[0][2] = int16_t(isChanFile.unitmapping[unit].afShape[0][2]);
  791. isChan.unitmapping[unit].afShape[1][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  792. isChan.unitmapping[unit].afShape[1][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  793. isChan.unitmapping[unit].afShape[1][2] = int16_t(isChanFile.unitmapping[unit].afShape[1][2]);
  794. isChan.unitmapping[unit].afShape[2][0] = int16_t(isChanFile.unitmapping[unit].afShape[2][0]);
  795. isChan.unitmapping[unit].afShape[2][1] = int16_t(isChanFile.unitmapping[unit].afShape[2][1]);
  796. isChan.unitmapping[unit].afShape[2][2] = int16_t(isChanFile.unitmapping[unit].afShape[2][2]);
  797. isChan.unitmapping[unit].aPhi = int16_t(isChanFile.unitmapping[unit].aPhi);
  798. isChan.unitmapping[unit].bValid = int16_t(isChanFile.unitmapping[unit].bValid);
  799. }
  800. }
  801. }
  802. // now read the rest of the file as individual packets and transmit it to the NSP
  803. ReadAsPackets(hFile);
  804. return CCFRESULT_SUCCESS;
  805. }
  806. // Author & Date: Hyrum L. Sessions 29 Nov 2010
  807. // Purpose: load the channel configuration from the file
  808. // convert the data from cb2005 v3.7 to the current
  809. // Inputs: hFile - the file, positioned at the beginning of the channel data
  810. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_37(FILE * hFile)
  811. {
  812. // Copy data into buffer
  813. cbPKT_CHANINFO_CB2005_37 isChanFile;
  814. // Read configuration to Cerebus
  815. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  816. {
  817. cbPKT_CHANINFO & isChan = m_data.isChan[i];
  818. SetChannelDefaults(isChan);
  819. memset(&isChanFile, 0, sizeof(isChanFile));
  820. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  821. // We only need to read packets for valid channels. There could be an
  822. // error reading the file, or we could be past the end of valid chans
  823. if (isChanFile.chan != 0)
  824. {
  825. // copy the data from the structure read from the file to the current chaninfo structure
  826. isChan.chan = isChanFile.chan;
  827. isChan.proc = isChanFile.proc;
  828. isChan.bank = isChanFile.bank;
  829. isChan.term = isChanFile.term;
  830. isChan.chancaps = isChanFile.chancaps;
  831. isChan.doutcaps = isChanFile.doutcaps;
  832. isChan.dinpcaps = isChanFile.dinpcaps;
  833. isChan.aoutcaps = isChanFile.aoutcaps;
  834. isChan.ainpcaps = isChanFile.ainpcaps;
  835. isChan.spkcaps = isChanFile.spkcaps;
  836. memcpy(&isChan.physcalin, &isChanFile.physcalin, sizeof(isChan.physcalin));
  837. memcpy(&isChan.phyfiltin, &isChanFile.phyfiltin, sizeof(isChan.phyfiltin));
  838. memcpy(&isChan.physcalout, &isChanFile.physcalout, sizeof(isChan.phyfiltout));
  839. memcpy(&isChan.phyfiltout, &isChanFile.phyfiltout, sizeof(isChan.phyfiltout));
  840. memcpy(&isChan.label, &isChanFile.label, sizeof(isChan.label));
  841. isChan.userflags = isChanFile.userflags;
  842. memcpy(isChan.position, isChanFile.position, sizeof(isChan.position));
  843. memcpy(&isChan.scalin, &isChanFile.scalin, sizeof(isChan.scalin));
  844. memcpy(&isChan.scalout, &isChanFile.scalout, sizeof(isChan.scalout));
  845. isChan.doutopts = isChanFile.doutopts;
  846. isChan.dinpopts = isChanFile.dinpopts;
  847. isChan.aoutopts = isChanFile.aoutopts;
  848. isChan.eopchar = isChanFile.eopchar;
  849. isChan.monsource = isChanFile.monsource;
  850. isChan.outvalue = isChanFile.outvalue;
  851. isChan.ainpopts = isChanFile.ainpopts;
  852. isChan.lncrate = isChanFile.lncrate;
  853. isChan.smpfilter = isChanFile.smpfilter;
  854. isChan.smpgroup = isChanFile.smpgroup;
  855. isChan.smpdispmin = isChanFile.smpdispmin;
  856. isChan.smpdispmax = isChanFile.smpdispmax;
  857. isChan.spkfilter = isChanFile.spkfilter;
  858. isChan.spkdispmax = isChanFile.spkdispmax;
  859. isChan.spkopts = isChanFile.spkopts;
  860. isChan.spkthrlevel = isChanFile.spkthrlevel;
  861. isChan.spkthrlimit = isChanFile.spkthrlimit;
  862. memcpy(isChan.spkhoops, isChanFile.spkhoops, sizeof(isChan.spkhoops));
  863. for (int unit = 0; unit < cbLEGACY_MAXUNITS; ++unit)
  864. {
  865. isChan.unitmapping[unit].nOverride = isChanFile.unitmapping[unit].nOverride;
  866. isChan.unitmapping[unit].afOrigin[0] = int16_t(isChanFile.unitmapping[unit].afOrigin[0]);
  867. isChan.unitmapping[unit].afOrigin[1] = int16_t(isChanFile.unitmapping[unit].afOrigin[1]);
  868. isChan.unitmapping[unit].afOrigin[2] = int16_t(isChanFile.unitmapping[unit].afOrigin[2]);
  869. isChan.unitmapping[unit].afShape[0][0] = int16_t(isChanFile.unitmapping[unit].afShape[0][0]);
  870. isChan.unitmapping[unit].afShape[0][1] = int16_t(isChanFile.unitmapping[unit].afShape[0][1]);
  871. isChan.unitmapping[unit].afShape[0][2] = int16_t(isChanFile.unitmapping[unit].afShape[0][2]);
  872. isChan.unitmapping[unit].afShape[1][0] = int16_t(isChanFile.unitmapping[unit].afShape[1][0]);
  873. isChan.unitmapping[unit].afShape[1][1] = int16_t(isChanFile.unitmapping[unit].afShape[1][1]);
  874. isChan.unitmapping[unit].afShape[1][2] = int16_t(isChanFile.unitmapping[unit].afShape[1][2]);
  875. isChan.unitmapping[unit].afShape[2][0] = int16_t(isChanFile.unitmapping[unit].afShape[2][0]);
  876. isChan.unitmapping[unit].afShape[2][1] = int16_t(isChanFile.unitmapping[unit].afShape[2][1]);
  877. isChan.unitmapping[unit].afShape[2][2] = int16_t(isChanFile.unitmapping[unit].afShape[2][2]);
  878. isChan.unitmapping[unit].aPhi = int16_t(isChanFile.unitmapping[unit].aPhi);
  879. isChan.unitmapping[unit].bValid = int16_t(isChanFile.unitmapping[unit].bValid);
  880. }
  881. }
  882. }
  883. // now read the rest of the file as individual packets and transmit it to the NSP
  884. ReadAsPackets(hFile);
  885. return CCFRESULT_SUCCESS;
  886. }
  887. // Author & Date: Hyrum L. Sessions 25 Aug 2011
  888. // Purpose: load the channel configuration from the file
  889. // v3.7 is the last binary CCF
  890. // Inputs: hFile - the file, positioned at the beginning of the channel data
  891. ccfResult CCFUtilsBinary::ReadCCFData_cb2005_310(FILE * hFile)
  892. {
  893. // Copy data into buffer
  894. for (int i = 0; i < cbLEGACY_MAXCHANS; ++i)
  895. {
  896. cbPKT_CHANINFO & isChanFile = m_data.isChan[i];
  897. memset(&isChanFile, 0, sizeof(isChanFile));
  898. fread(&isChanFile, 1, sizeof(isChanFile), hFile);
  899. // We only need to read packets for valid channels. There could be an
  900. // error reading the file, or we could be past the end of valid chans
  901. if (isChanFile.chan != 0)
  902. {
  903. // We might as well use this RAM to set the packet types.
  904. // The space is already allocated, and won't be used later
  905. isChanFile.chid = 0x8000;
  906. isChanFile.type = cbPKTTYPE_CHANSET;
  907. isChanFile.dlen = cbPKTDLEN_CHANINFO_CB2005_37;
  908. }
  909. } // end for(int i = 0
  910. // now read the rest of the file as individual packets and transmit it to the NSP
  911. ReadAsPackets(hFile);
  912. return CCFRESULT_SUCCESS;
  913. }
  914. // Author & Date: Hyrum L. Sessions 16 Dec 2009
  915. // Purpose: Autosorting filters didn't line up with the manual sorting filters.
  916. // The latest binary format is the same as the manual sorting so
  917. // if this file was saved with autosorting, translate to the new filter number
  918. // Inputs:
  919. // nFilter - filter number saved in the configuration file as autosort filter
  920. // Outputs: returns the new filter number
  921. uint32_t CCFUtilsBinary::TranslateAutoFilter(uint32_t nFilter)
  922. {
  923. uint32_t nReturn = 0;
  924. if (1 == nFilter) nReturn = 6; // LFP Wide
  925. if (2 == nFilter) nReturn = 7; // LFP XWide
  926. if (3 == nFilter) nReturn = 2; // Spike Medium
  927. if (4 == nFilter) nReturn = 9; // EMG
  928. if (5 == nFilter) nReturn = 8; // EEG
  929. if (6 == nFilter) nReturn = 10; // Activity
  930. return nReturn;
  931. }
  932. // Author & Date: Kirk Korver 28 Nov 2005
  933. // Purpose: Given this file, read each "packet"
  934. // Inputs:
  935. // hFile - the file is positioned at the beginning of a packet.
  936. // Outputs:
  937. // settings - binary settings
  938. void CCFUtilsBinary::ReadAsPackets(FILE * hFile)
  939. {
  940. BYTE abyData[4096]= {0};
  941. cbPKT_GENERIC_CB2003_10 * pPkt = reinterpret_cast<cbPKT_GENERIC_CB2003_10 *>(&abyData[0]);
  942. const uint32_t cbHdrSize = (uint32_t)offsetof(cbPKT_GENERIC_CB2003_10, data[0]);
  943. BYTE * pbyPayload = abyData + cbHdrSize; // point to first byte of payload
  944. m_bAutoSort = false;
  945. // Read in the header
  946. while (1 == fread(pPkt, cbHdrSize, 1, hFile))
  947. {
  948. memset(pbyPayload, 0, sizeof(abyData) - cbHdrSize);
  949. uint32_t cbPayload = pPkt->dlen * 4;
  950. if (cbPayload != fread(pbyPayload, 1, cbPayload, hFile))
  951. return; // actually an error
  952. // Also an error, but don't read
  953. if (pPkt->type == 0)
  954. return;
  955. // Convert from NSP->PC to PC->NSP
  956. pPkt->type |= 0x80;
  957. if (0xD0 == (pPkt->type & 0xD8)) // sorting packets processed separately
  958. {
  959. m_bAutoSort = true;
  960. ReadSpikeSortingPackets(pPkt);
  961. }
  962. else if (cbPKTTYPE_SYSSET == (pPkt->type & 0xF0))
  963. { // only set spike len and pre trigger len
  964. pPkt->type = cbPKTTYPE_SYSSETSPKLEN;
  965. cbPKT_SYSINFO_CB2005_37 * pPktSysInfo = reinterpret_cast<cbPKT_SYSINFO_CB2005_37 *>(pPkt);
  966. m_data.isSysInfo = *pPktSysInfo;
  967. }
  968. else if (cbPKTTYPE_SETNTRODEINFO == pPkt->type)
  969. {
  970. cbPKT_NTRODEINFO_CB2005_37 * pPktNTrode = reinterpret_cast<cbPKT_NTRODEINFO_CB2005_37 *>(pPkt);
  971. if (pPktNTrode->ntrode > 0 && pPktNTrode->ntrode <= cbLEGACY_MAXNTRODES)
  972. {
  973. int idx = pPktNTrode->ntrode - 1;
  974. m_data.isNTrodeInfo[idx] = *pPktNTrode;
  975. }
  976. }
  977. else if (cbPKTTYPE_ADAPTFILTSET == pPkt->type)
  978. {
  979. cbPKT_ADAPTFILTINFO_CB2005_37 * pPktAdaptInfo= reinterpret_cast<cbPKT_ADAPTFILTINFO_CB2005_37 *>(pPkt);
  980. m_data.isAdaptInfo = * pPktAdaptInfo;
  981. }
  982. }
  983. if ((m_nInternalOriginalVersion < 8) && !m_bAutoSort)
  984. {
  985. m_data.isSS_Status.type = cbPKTTYPE_SS_STATUSSET;
  986. m_data.isSS_Status.dlen = cbPKTDLEN_SS_STATUS;
  987. m_data.isSS_Status.cntlNumUnits.fElapsedMinutes = 99;
  988. m_data.isSS_Status.cntlUnitStats.fElapsedMinutes = 99;
  989. }
  990. }
  991. void CCFUtilsBinary::ReadSpikeSortingPackets(cbPKT_GENERIC_CB2003_10 *pPkt)
  992. {
  993. cbPKT_SS_STATISTICS_CB2005_37 & isSSStatistics = m_data.isSS_Statistics;
  994. switch (pPkt->type)
  995. {
  996. case cbPKTTYPE_SS_STATISTICSSET: // handle statistics packet changes
  997. switch (m_nInternalOriginalVersion)
  998. {
  999. case 1:
  1000. case 2:
  1001. case 3:
  1002. {
  1003. cbPKT_SS_STATISTICS_CB2005_30 * pPktSSStatistics = reinterpret_cast<cbPKT_SS_STATISTICS_CB2005_30 *>(pPkt);
  1004. isSSStatistics.set(pPktSSStatistics->nUpdateSpikes, cbAUTOALG_HIST_PEAK_COUNT_MAJ, cbAUTOALG_MODE_APPLY,
  1005. pPktSSStatistics->fMinClusterSpreadFactor, pPktSSStatistics->fMaxSubclusterSpreadFactor,
  1006. 0.80f, 0.94f,
  1007. 0.50f, 0.50f, 0.016f,
  1008. 250, 0);
  1009. }
  1010. break;
  1011. case 4:
  1012. {
  1013. cbPKT_SS_STATISTICS_CB2005_31 * pPktSSStatistics = reinterpret_cast<cbPKT_SS_STATISTICS_CB2005_31 *>(pPkt);
  1014. isSSStatistics.set(pPktSSStatistics->nUpdateSpikes, pPktSSStatistics->nAutoalg, cbAUTOALG_MODE_APPLY,
  1015. pPktSSStatistics->fMinClusterPairSpreadFactor, pPktSSStatistics->fMaxSubclusterSpreadFactor,
  1016. pPktSSStatistics->fMinClusterHistCorrMajMeasure, pPktSSStatistics->fMaxClusterPairHistCorrMajMeasure,
  1017. pPktSSStatistics->fClusterHistMajValleyPercentage, pPktSSStatistics->fClusterHistMajPeakPercentage,
  1018. 0.016f, 250, 0);
  1019. }
  1020. break;
  1021. case 5:
  1022. case 6:
  1023. case 7:
  1024. case 8:
  1025. {
  1026. cbPKT_SS_STATISTICS_CB2005_32 * pPktSSStatistics = reinterpret_cast<cbPKT_SS_STATISTICS_CB2005_32 *>(pPkt);
  1027. isSSStatistics.set(pPktSSStatistics->nUpdateSpikes, pPktSSStatistics->nAutoalg, cbAUTOALG_MODE_APPLY,
  1028. pPktSSStatistics->fMinClusterPairSpreadFactor, pPktSSStatistics->fMaxSubclusterSpreadFactor,
  1029. pPktSSStatistics->fMinClusterHistCorrMajMeasure, pPktSSStatistics->fMaxClusterPairHistCorrMajMeasure,
  1030. pPktSSStatistics->fClusterHistValleyPercentage, pPktSSStatistics->fClusterHistClosePeakPercentage,
  1031. 0.016f, 250, 0);
  1032. }
  1033. break;
  1034. case 9:
  1035. case 10:
  1036. case 11:
  1037. cbPKT_SS_STATISTICS_CB2005_37 * pPktSSStatistics = reinterpret_cast<cbPKT_SS_STATISTICS_CB2005_37 *>(pPkt);
  1038. isSSStatistics = *pPktSSStatistics;
  1039. break;
  1040. }
  1041. break;
  1042. case cbPKTTYPE_SS_NOISE_BOUNDARYSET: // handle noise boundary changes
  1043. uint32_t nChan;
  1044. switch (m_nInternalOriginalVersion)
  1045. {
  1046. case 1: // previously noise line which doesn't translate to boundry, so use default
  1047. case 2:
  1048. case 3:
  1049. for(nChan = 1; nChan <= cbLEGACY_NUM_ANALOG_CHANS; nChan++) // channels are 1 based
  1050. {
  1051. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 & isNoiseBoundary = m_data.isSS_NoiseBoundary[nChan - 1];
  1052. isNoiseBoundary.set(nChan, float(0.0), float(0.0),
  1053. float(1.0/(300*300)), float(0.0),
  1054. float(0.0), float(1.0/(300*300)), float(0.0));
  1055. }
  1056. break;
  1057. case 4: // theta was added
  1058. case 5:
  1059. {
  1060. cbPKT_SS_NOISE_BOUNDARY_CB2005_31 * pPktSSNoiseBoundary = reinterpret_cast<cbPKT_SS_NOISE_BOUNDARY_CB2005_31 *>(pPkt);
  1061. for(nChan = 1; nChan <= cbLEGACY_NUM_ANALOG_CHANS; nChan++) // channels are 1 based
  1062. {
  1063. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 & isNoiseBoundary = m_data.isSS_NoiseBoundary[nChan - 1];
  1064. isNoiseBoundary.set(nChan, pPktSSNoiseBoundary->afc[0], pPktSSNoiseBoundary->afc[1],
  1065. pPktSSNoiseBoundary->afS[0][0], pPktSSNoiseBoundary->afS[0][1],
  1066. pPktSSNoiseBoundary->afS[1][0], pPktSSNoiseBoundary->afS[1][1], 0);
  1067. }
  1068. }
  1069. break;
  1070. case 6: // added boundary per channel
  1071. {
  1072. cbPKT_SS_NOISE_BOUNDARY_CB2005_33 * pPktSSNoiseBoundary = reinterpret_cast<cbPKT_SS_NOISE_BOUNDARY_CB2005_33 *>(pPkt);
  1073. for(nChan = 1; nChan <= cbLEGACY_NUM_ANALOG_CHANS; nChan++) // channels are 1 based
  1074. {
  1075. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 & isNoiseBoundary = m_data.isSS_NoiseBoundary[nChan - 1];
  1076. isNoiseBoundary.set(nChan, pPktSSNoiseBoundary->afc[0], pPktSSNoiseBoundary->afc[1],
  1077. pPktSSNoiseBoundary->afS[0][0], pPktSSNoiseBoundary->afS[0][1],
  1078. pPktSSNoiseBoundary->afS[1][0], pPktSSNoiseBoundary->afS[1][1],
  1079. pPktSSNoiseBoundary->aTheta);
  1080. }
  1081. }
  1082. break;
  1083. case 7: // added 3rd dimension
  1084. case 8:
  1085. {
  1086. cbPKT_SS_NOISE_BOUNDARY_CB2005_34 * pPktSSNoiseBoundary = reinterpret_cast<cbPKT_SS_NOISE_BOUNDARY_CB2005_34 *>(pPkt);
  1087. nChan = pPktSSNoiseBoundary->chan;
  1088. if (nChan > 0 && nChan <= cbLEGACY_NUM_ANALOG_CHANS)
  1089. {
  1090. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 & isNoiseBoundary = m_data.isSS_NoiseBoundary[nChan - 1];
  1091. isNoiseBoundary.set(nChan, pPktSSNoiseBoundary->afc[0], pPktSSNoiseBoundary->afc[1],
  1092. pPktSSNoiseBoundary->afS[0][0], pPktSSNoiseBoundary->afS[0][1],
  1093. pPktSSNoiseBoundary->afS[1][0], pPktSSNoiseBoundary->afS[1][1],
  1094. pPktSSNoiseBoundary->aTheta);
  1095. }
  1096. }
  1097. break;
  1098. case 9:
  1099. case 10:
  1100. case 11:
  1101. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 * pPktSSNoiseBoundary = reinterpret_cast<cbPKT_SS_NOISE_BOUNDARY_CB2005_37 *>(pPkt);
  1102. nChan = pPktSSNoiseBoundary->chan;
  1103. if (nChan > 0 && nChan <= cbLEGACY_NUM_ANALOG_CHANS)
  1104. {
  1105. cbPKT_SS_NOISE_BOUNDARY_CB2005_37 & isNoiseBoundary = m_data.isSS_NoiseBoundary[nChan - 1];
  1106. isNoiseBoundary = * pPktSSNoiseBoundary;
  1107. }
  1108. break;
  1109. }
  1110. break;
  1111. default:
  1112. // if we got here, we didn't process the packet so we'll do some global processing
  1113. // block autosorting restarting
  1114. if (cbPKTTYPE_SS_STATUSSET == pPkt->type)
  1115. {
  1116. cbPKT_SS_STATUS_CB2005_37 * pPktSSStatus = reinterpret_cast<cbPKT_SS_STATUS_CB2005_37 *>(pPkt);
  1117. pPktSSStatus->cntlNumUnits.fElapsedMinutes = 99;
  1118. pPktSSStatus->cntlUnitStats.fElapsedMinutes = 99;
  1119. m_data.isSS_Status = * pPktSSStatus;
  1120. }
  1121. else if (cbPKTTYPE_SS_DETECTSET == pPkt->type)
  1122. {
  1123. cbPKT_SS_DETECT_CB2005_37 * pPktSSStatus = reinterpret_cast<cbPKT_SS_DETECT_CB2005_37 *>(pPkt);
  1124. m_data.isSS_Detect = * pPktSSStatus;
  1125. }
  1126. else if (cbPKTTYPE_SS_ARTIF_REJECTSET == pPkt->type)
  1127. {
  1128. cbPKT_SS_ARTIF_REJECT_CB2005_37 * pPktSSStatus = reinterpret_cast<cbPKT_SS_ARTIF_REJECT_CB2005_37 *>(pPkt);
  1129. m_data.isSS_ArtifactReject = * pPktSSStatus;
  1130. }
  1131. }
  1132. }
  1133. // Author & Date: Kirk Korver 22 Sep 2004
  1134. // Purpose: Write out a binary CCF file. Overwrite any other file by this name.
  1135. // Do NOT prompt for the file to write out.
  1136. // Inputs:
  1137. // szFileName - the name of the file to write
  1138. ccfResult CCFUtilsBinary::WriteCCFNoPrompt(LPCSTR szFileName)
  1139. {
  1140. m_szFileName = szFileName;
  1141. // Open a file
  1142. FILE *hSettingsFile;
  1143. hSettingsFile = fopen(szFileName, "wb");
  1144. if (hSettingsFile == NULL)
  1145. return CCFRESULT_ERR_OPENFAILEDWRITE;
  1146. // Write a header and version to file
  1147. // The version now is the version from the protocol
  1148. fwrite(m_szConfigFileHeader, strlen(m_szConfigFileHeader), 1, hSettingsFile);
  1149. char szVer[sizeof(m_szConfigFileVersion)] = {0}; // ANSI - all 0
  1150. _snprintf(szVer, sizeof(szVer) - 1, "%d.%d", cbVERSION_MAJOR, cbVERSION_MINOR);
  1151. fwrite(szVer, sizeof(szVer) - 1, 1, hSettingsFile);
  1152. // Write channel info
  1153. fwrite(&m_data.isChan[0], 1, sizeof(m_data.isChan), hSettingsFile);
  1154. // Also write out the "adaptive filter" settings
  1155. fwrite(&m_data.isAdaptInfo, sizeof(m_data.isAdaptInfo), 1, hSettingsFile);
  1156. /////////// Now do the spike sorting parameters /////////////////////////////
  1157. // The "model" isn't really stored until it is asked for, so I need to skip it,
  1158. // and the "model", will always be the very 1st item in the sorting options area,
  1159. // so I just have to move over it, before I write it out.
  1160. // Sorting
  1161. {
  1162. fwrite(&m_data.isSS_Detect, sizeof(m_data.isSS_Detect), 1, hSettingsFile);
  1163. fwrite(&m_data.isSS_ArtifactReject, sizeof(m_data.isSS_ArtifactReject), 1, hSettingsFile);
  1164. for (int i = 0; i < cbLEGACY_NUM_ANALOG_CHANS; ++i)
  1165. fwrite(&m_data.isSS_NoiseBoundary[i], sizeof(m_data.isSS_NoiseBoundary[i]), 1, hSettingsFile);
  1166. fwrite(&m_data.isSS_Statistics, sizeof(m_data.isSS_Statistics), 1, hSettingsFile);
  1167. fwrite(&m_data.isSS_Status, sizeof(m_data.isSS_Status), 1, hSettingsFile);
  1168. }
  1169. // Write sys info (spike length and pretrigger length)
  1170. fwrite(&m_data.isSysInfo, sizeof(m_data.isSysInfo), 1, hSettingsFile);
  1171. // Write nTrode info
  1172. fwrite(&m_data.isNTrodeInfo[0], sizeof(m_data.isNTrodeInfo), 1, hSettingsFile);
  1173. // Close the file
  1174. fclose(hSettingsFile);
  1175. return CCFRESULT_SUCCESS;
  1176. }