PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

FlexCAN_T4FDTimings.tpp 38KB

3 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. #include <FlexCAN_T4.h>
  2. #include "imxrt_flexcan.h"
  3. #include "Arduino.h"
  4. FCTPFD_FUNC bool FCTPFD_OPT::setBaudRateAdvanced(CANFD_timings_t config, uint8_t nominal_choice, uint8_t flexdata_choice, FLEXCAN_RXTX listen_only) {
  5. return setBaudRate(config, nominal_choice, flexdata_choice, listen_only, 1);
  6. }
  7. FCTPFD_FUNC bool FCTPFD_OPT::setBaudRate(CANFD_timings_t config, FLEXCAN_RXTX listen_only) {
  8. return setBaudRate(config, 1, 1, listen_only, 0);
  9. }
  10. FCTPFD_FUNC bool FCTPFD_OPT::setBaudRate(CANFD_timings_t config, uint8_t nominal_choice, uint8_t flexdata_choice, FLEXCAN_RXTX listen_only, bool advanced) {
  11. uint32_t result = 0, result_old = 0;
  12. double results[10][12] = { { 0 } , { 0 } };
  13. double baudrate = config.baudrate, propdelay = config.propdelay, bus_length = config.bus_length, req_smp = config.sample;
  14. double cpi_clock = config.clock;
  15. baudrate /= 1000;
  16. double ratio = cpi_clock * 1000 / baudrate;
  17. double nbt_min = 8, nbt_max = 129, propseg_max = 64, propseg = 0, pseg_1, pseg_2;
  18. propdelay = (propdelay * 2) + (bus_length * 10);
  19. uint32_t ipt = 2;
  20. double temp = 0, pseg1 = 32, pseg2 = 32, rjw = 16, prescaler_min = 1, prescaler_max = 1024;
  21. if ( advanced ) Serial.println("\n\n #########################################################################################################################################");
  22. if ( advanced ) Serial.println(" #\t\t\t\t\t\t\t\t*** CAN NOMINAL CONFIGURATION ***\t\t\t\t\t #");
  23. if ( advanced ) Serial.println(" #########################################################################################################################################\n");
  24. for ( uint32_t prescaler = prescaler_min; prescaler < prescaler_max; prescaler++ ) {
  25. temp = ratio / prescaler;
  26. for ( double nbt = nbt_min; nbt < nbt_max; nbt++ ) {
  27. if ( temp == nbt ) {
  28. propseg = ceil(propdelay / 1000 * cpi_clock / prescaler);
  29. if ( propseg <= propseg_max ) {
  30. for ( double pseg = 1; pseg <= pseg1; pseg++ ) {
  31. if ( req_smp != 0 ) {
  32. pseg_1 = round((nbt * req_smp / 100) - 1 - propseg);
  33. pseg_2 = nbt - 1 - propseg - pseg_1;
  34. if ( pseg_2 >= ipt && pseg_2 <= pseg2 && pseg_1 > 0 && pseg_1 <= pseg1 ) {
  35. result = result_old + 1;
  36. rjw = ( pseg_2 <= rjw ) ? pseg_2 : rjw;
  37. double error = (double) rjw / 20 / nbt * 100;
  38. double error1 = (double)( ( pseg_1 <= pseg_2 ) ? pseg_1 : pseg_2 ) / 2 / (13 * nbt - pseg_2) * 100;
  39. double sclk = (cpi_clock / prescaler);
  40. double tq = (1000 / (cpi_clock / prescaler));
  41. double smp = 100 - pseg_2 / nbt * 100;
  42. results[result - 1][0] = prescaler;
  43. results[result - 1][1] = sclk;
  44. results[result - 1][2] = tq;
  45. results[result - 1][3] = nbt;
  46. results[result - 1][4] = propseg;
  47. results[result - 1][5] = pseg_1;
  48. results[result - 1][6] = pseg_2;
  49. results[result - 1][7] = rjw;
  50. results[result - 1][8] = (error <= error1) ? error : error1;
  51. results[result - 1][9] = smp;
  52. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) ?f(%) Sample Point(%) CBT Register\n");
  53. if ( advanced ) Serial.printf(" %2u)", result);
  54. if ( advanced ) Serial.printf(" %4u", prescaler);
  55. if ( advanced ) Serial.printf(" %6.2f", sclk);
  56. if ( advanced ) Serial.printf(" %7.2f", tq);
  57. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  58. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  59. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg_1);
  60. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg_2);
  61. if ( advanced ) Serial.printf(" %2u", (uint32_t)rjw);
  62. if ( advanced ) Serial.printf(" %6.2f", ((error <= error1) ? error : error1));
  63. if ( advanced ) Serial.printf(" %6.2f", smp);
  64. uint32_t cbt = ((uint32_t)(results[result - 1][4] - 1) << 10); // EPROPSEG
  65. cbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // EPSEG2
  66. cbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // EPSEG1
  67. cbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // ERJW
  68. cbt |= ((uint32_t)(results[result - 1][0] - 1) << 21); // EPRESDIV
  69. cbt |= (1UL << 31); // BTF /* use CBT register instead of CTRL1 for FD */
  70. if ( advanced ) Serial.printf(" 0x%8.08X",cbt);
  71. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Arbitration phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  72. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  73. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  74. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  75. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  76. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  77. char _sync[(scale*124/1000) + 1] = "";
  78. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  79. _sync[(scale*124/1000)] = '\0';
  80. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  81. char _prop[(scale*124/1000) + 1] = "";
  82. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  83. _prop[(scale*124/1000)] = '\0';
  84. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  85. char _pseg1[(scale*124/1000) + 1] = "";
  86. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  87. _pseg1[(scale*124/1000)] = '\0';
  88. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  89. char _pseg2[(scale*124/1000) + 1] = "";
  90. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  91. _pseg2[(scale*124/1000)] = '\0';
  92. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  93. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  94. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  95. }
  96. if ( result == result_old ) {
  97. pseg = nbt - 1 - propseg;
  98. if ( pseg == 3 && ipt == 2 ) {
  99. result = result + 1;
  100. double error = (double) rjw / 20 / nbt * 100;
  101. double error1 = ( ( pseg_1 <= pseg_2 ) ? (double)pseg_1 : (double)pseg_2 ) / 2 / (13 * nbt - pseg_2) * 100;
  102. double sclk = (cpi_clock / prescaler);
  103. double tq = (1000 / (cpi_clock / prescaler));
  104. double smp = 100 - 2 / nbt * 100;
  105. results[result - 1][0] = prescaler;
  106. results[result - 1][1] = sclk;
  107. results[result - 1][2] = tq;
  108. results[result - 1][3] = nbt;
  109. results[result - 1][4] = propseg;
  110. results[result - 1][5] = 1;
  111. results[result - 1][6] = 2;
  112. results[result - 1][7] = 1;
  113. results[result - 1][8] = (error <= error1) ? error : error1;
  114. results[result - 1][9] = smp;
  115. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) ?f(%) Sample Point(%) CBT Register\n");
  116. if ( advanced ) Serial.printf(" %2u)", result);
  117. if ( advanced ) Serial.printf(" %4u", prescaler);
  118. if ( advanced ) Serial.printf(" %6.2f", sclk);
  119. if ( advanced ) Serial.printf(" %7.2f", tq);
  120. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  121. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  122. if ( advanced ) Serial.printf(" %2u", (uint32_t)1);
  123. if ( advanced ) Serial.printf(" %2u", (uint32_t)2);
  124. if ( advanced ) Serial.printf(" %2u", (uint32_t)1);
  125. if ( advanced ) Serial.printf(" %6.2f", ((error <= error1) ? error : error1));
  126. if ( advanced ) Serial.printf(" %6.2f", smp);
  127. uint32_t cbt = ((uint32_t)(results[result - 1][4] - 1) << 10); // EPROPSEG
  128. cbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // EPSEG2
  129. cbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // EPSEG1
  130. cbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // ERJW
  131. cbt |= ((uint32_t)(results[result - 1][0] - 1) << 21); // EPRESDIV
  132. cbt |= (1UL << 31); // BTF /* use CBT register instead of CTRL1 for FD */
  133. if ( advanced ) Serial.printf(" 0x%8.08X",cbt);
  134. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Arbitration phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  135. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  136. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  137. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  138. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  139. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  140. char _sync[(scale*124/1000) + 1] = "";
  141. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  142. _sync[(scale*124/1000)] = '\0';
  143. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  144. char _prop[(scale*124/1000) + 1] = "";
  145. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  146. _prop[(scale*124/1000)] = '\0';
  147. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  148. char _pseg1[(scale*124/1000) + 1] = "";
  149. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  150. _pseg1[(scale*124/1000)] = '\0';
  151. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  152. char _pseg2[(scale*124/1000) + 1] = "";
  153. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  154. _pseg2[(scale*124/1000)] = '\0';
  155. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  156. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  157. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  158. }
  159. if ( pseg > (ipt + 1) && pseg <= (pseg1 * 2) ) {
  160. if ( (uint32_t)pseg % 2 != 0 ) propseg++;
  161. pseg = (nbt - 1 - propseg) / 2;
  162. result = result + 1;
  163. rjw = ( pseg <= rjw ) ? pseg : rjw;
  164. double pseg_val = nbt - 1 - propseg - pseg;
  165. double error = (double)rjw / 20 / nbt * 100;
  166. double error1 = (((pseg <= pseg_val) ? (double)pseg : (double)pseg_val ) / 2 / (13 * nbt - pseg_val) * 100);
  167. double sclk = (cpi_clock / prescaler);
  168. double tq = (1000 / (cpi_clock / prescaler));
  169. double smp = 100 - pseg / nbt * 100;
  170. results[result - 1][0] = prescaler;
  171. results[result - 1][1] = sclk;
  172. results[result - 1][2] = tq;
  173. results[result - 1][3] = nbt;
  174. results[result - 1][4] = propseg;
  175. results[result - 1][5] = pseg;
  176. results[result - 1][6] = pseg_val;
  177. results[result - 1][7] = rjw;
  178. results[result - 1][8] = (error <= error1) ? error : error1;
  179. results[result - 1][9] = smp;
  180. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) ?f(%) Sample Point(%) CBT Register\n");
  181. if ( advanced ) Serial.printf(" %2u)", result);
  182. if ( advanced ) Serial.printf(" %4u", prescaler);
  183. if ( advanced ) Serial.printf(" %6.2f", sclk);
  184. if ( advanced ) Serial.printf(" %7.2f", tq);
  185. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  186. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  187. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg);
  188. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg_val);
  189. if ( advanced ) Serial.printf(" %2u", (uint32_t)rjw);
  190. if ( advanced ) Serial.printf(" %6.2f", ((error <= error1) ? error : error1));
  191. if ( advanced ) Serial.printf(" %6.2f", smp);
  192. uint32_t cbt = ((uint32_t)(results[result - 1][4] - 1) << 10); // EPROPSEG
  193. cbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // EPSEG2
  194. cbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // EPSEG1
  195. cbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // ERJW
  196. cbt |= ((uint32_t)(results[result - 1][0] - 1) << 21); // EPRESDIV
  197. cbt |= (1UL << 31); // BTF /* use CBT register instead of CTRL1 for FD */
  198. if ( advanced ) Serial.printf(" 0x%8.08X",cbt);
  199. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Arbitration phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  200. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  201. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  202. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  203. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  204. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  205. char _sync[(scale*124/1000) + 1] = "";
  206. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  207. _sync[(scale*124/1000)] = '\0';
  208. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  209. char _prop[(scale*124/1000) + 1] = "";
  210. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  211. _prop[(scale*124/1000)] = '\0';
  212. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  213. char _pseg1[(scale*124/1000) + 1] = "";
  214. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  215. _pseg1[(scale*124/1000)] = '\0';
  216. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  217. char _pseg2[(scale*124/1000) + 1] = "";
  218. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  219. _pseg2[(scale*124/1000)] = '\0';
  220. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  221. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  222. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  223. }
  224. }
  225. result_old = result;
  226. break;
  227. }
  228. }
  229. }
  230. }
  231. }
  232. }
  233. if ( advanced ) Serial.println("\n\n\n");
  234. if ( nominal_choice && flexdata_choice ) {
  235. if ( nominal_choice > result ) {
  236. if ( advanced ) Serial.println("\n\t*** ERROR: Nominal rate selection out of bounds!\n");
  237. return 0;
  238. }
  239. uint32_t cbt = ((uint32_t)(results[nominal_choice - 1][4] - 1) << 10); // EPROPSEG
  240. cbt |= ((uint32_t)(results[nominal_choice - 1][6] - 1) << 0); // EPSEG2
  241. cbt |= ((uint32_t)(results[nominal_choice - 1][5] - 1) << 5); // EPSEG1
  242. cbt |= ((uint32_t)(results[nominal_choice - 1][7] - 1) << 16); // ERJW
  243. cbt |= ((uint32_t)(results[nominal_choice - 1][0] - 1) << 21); // EPRESDIV
  244. cbt |= (1UL << 31); // BTF
  245. uint32_t fdcbt_setting = setBaudRateFD(config, flexdata_choice, advanced);
  246. if ( fdcbt_setting ) { // SET BOTH CBT AND FDCBT HERE
  247. FLEXCAN_EnterFreezeMode();
  248. setClock(config.clock);
  249. if ( listen_only == LISTEN_ONLY ) {
  250. FLEXCANb_CBT(_bus) &= ~(1UL << 31); /* clear BTE bit to edit CTRL1 register */
  251. FLEXCANb_CTRL1(_bus) |= FLEXCAN_CTRL_LOM;
  252. }
  253. else {
  254. FLEXCANb_CBT(_bus) &= ~(1UL << 31); /* clear BTE bit to edit CTRL1 register */
  255. FLEXCANb_CTRL1(_bus) &= ~FLEXCAN_CTRL_LOM;
  256. }
  257. FLEXCANb_CBT(_bus) = cbt;
  258. FLEXCANb_FDCBT(_bus) = fdcbt_setting;
  259. if ( advanced ) Serial.print("CTRL1: 0x");
  260. if ( advanced ) Serial.println(FLEXCANb_CTRL1(_bus),HEX);
  261. if ( advanced ) Serial.print("CBT: 0x");
  262. if ( advanced ) Serial.println(FLEXCANb_CBT(_bus),HEX);
  263. if ( advanced ) Serial.print("FDCBT: 0x");
  264. if ( advanced ) Serial.println(FLEXCANb_FDCBT(_bus) ,HEX);
  265. if ( advanced ) Serial.print("FDCTRL: 0x");
  266. if ( advanced ) Serial.println(FLEXCANb_FDCTRL(_bus) ,HEX);
  267. FLEXCAN_ExitFreezeMode();
  268. return 1;
  269. }
  270. else return 0;
  271. }
  272. else setBaudRateFD(config, 0, advanced); /* continue list printout for FD */
  273. while ( Serial.read() != 'c' );
  274. return 1;
  275. }
  276. FCTPFD_FUNC uint32_t FCTPFD_OPT::setBaudRateFD(CANFD_timings_t config, uint32_t flexdata_choice, bool advanced) {
  277. uint32_t result = 0, result_old = 0;
  278. double results[10][12] = { { 0 } , { 0 } };
  279. double baudrate = config.baudrateFD, propdelay = config.propdelay, req_smp = config.sample;
  280. double cpi_clock = config.clock;
  281. baudrate /= 1000;
  282. double ratio = cpi_clock * 1000 / baudrate;
  283. double nbt_min = 5, nbt_max = 48, propseg_max = 32, propseg = 0, pseg_1, pseg_2;
  284. uint32_t tdcen = 0, ipt = 2;
  285. double temp = 0, ppsegmin, ppsegmax, pseg1 = 8, pseg2 = 8, rjw = 8, prescaler_min = 1, prescaler_max = 1024;
  286. if ( advanced ) Serial.println(" ####################################################################################################################################################");
  287. if ( advanced ) Serial.println(" #\t\t\t\t\t\t\t\t*** CAN FLEXDATA CONFIGURATION ***\t\t\t\t\t\t #");
  288. if ( advanced ) Serial.println(" ####################################################################################################################################################\n");
  289. for ( uint32_t prescaler = prescaler_min; prescaler < prescaler_max; prescaler++ ) {
  290. temp = ratio / prescaler;
  291. for ( double nbt = nbt_min; nbt < nbt_max; nbt++ ) {
  292. if ( temp == nbt ) {
  293. propseg = ceil(propdelay / 1000 * cpi_clock / prescaler);
  294. tdcen = 0;
  295. if ( propseg >= (nbt - 2)) { // finished with debug
  296. ppsegmax = nbt - 3;
  297. ppsegmin = nbt - 1 - pseg1 - pseg2;
  298. if ( ppsegmin < 1 ) ppsegmin = 1;
  299. propseg = round((ppsegmax - ppsegmin) / 2);
  300. tdcen = 1;
  301. }
  302. if ( propseg <= propseg_max ) {
  303. for ( double pseg = 1; pseg <= pseg1; pseg++ ) {
  304. pseg_1 = round((nbt * req_smp / 100) - 1 - propseg);
  305. pseg_2 = nbt - 1 - propseg - pseg_1;
  306. if ( pseg_2 >= ipt && pseg_2 <= pseg2 && pseg_1 > 0 && pseg_1 <= pseg1 ) {
  307. result = result_old + 1;
  308. rjw = ( pseg_2 <= rjw ) ? pseg_2 : rjw;
  309. double sclk = (cpi_clock / prescaler);
  310. double tq = (1000 / (cpi_clock / prescaler));
  311. double smp = 100 - pseg_2 / nbt * 100;
  312. double tdcoff_val = (!tdcen) ? 0 : cpi_clock / (2 * baudrate / 1000);
  313. results[result - 1][0] = prescaler;
  314. results[result - 1][1] = sclk;
  315. results[result - 1][2] = tq;
  316. results[result - 1][3] = nbt;
  317. results[result - 1][4] = propseg;
  318. results[result - 1][5] = pseg_1;
  319. results[result - 1][6] = pseg_2;
  320. results[result - 1][7] = rjw;
  321. results[result - 1][8] = tdcen;
  322. results[result - 1][9] = tdcoff_val;
  323. results[result - 1][10] = smp;
  324. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) TDCEN TDCOFF Sample Point(%) FDCBT Register\n");
  325. if ( advanced ) Serial.printf(" %2u)", result);
  326. if ( advanced ) Serial.printf(" %4u", prescaler);
  327. if ( advanced ) Serial.printf(" %6.2f", sclk);
  328. if ( advanced ) Serial.printf(" %7.2f", tq);
  329. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  330. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  331. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg_1);
  332. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg_2);
  333. if ( advanced ) Serial.printf(" %2u", (uint32_t)rjw);
  334. if ( advanced ) Serial.printf(" %2u", (uint32_t)tdcen);
  335. if ( advanced ) Serial.printf(" %4.2f", tdcoff_val);
  336. if ( advanced ) Serial.printf(" %6.2f", smp);
  337. uint32_t fdcbt = 0;
  338. fdcbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // FPSEG2
  339. fdcbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // FPSEG1
  340. fdcbt |= ((uint32_t)(results[result - 1][4] - 0) << 10); // FPROPSEG
  341. fdcbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // FRJW
  342. fdcbt |= ((uint32_t)(results[result - 1][0] - 1) << 20); // FPRESDIV
  343. if ( advanced ) Serial.printf(" 0x%8.08X",fdcbt);
  344. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Data phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  345. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  346. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  347. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  348. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  349. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  350. char _sync[(scale*124/1000) + 1] = "";
  351. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  352. _sync[(scale*124/1000)] = '\0';
  353. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  354. char _prop[(scale*124/1000) + 1] = "";
  355. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  356. _prop[(scale*124/1000)] = '\0';
  357. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  358. char _pseg1[(scale*124/1000) + 1] = "";
  359. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  360. _pseg1[(scale*124/1000)] = '\0';
  361. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  362. char _pseg2[(scale*124/1000) + 1] = "";
  363. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  364. _pseg2[(scale*124/1000)] = '\0';
  365. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  366. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  367. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  368. }
  369. if ( result == result_old ) {
  370. pseg = nbt - 1 - propseg;
  371. if ( pseg == 3 && ipt == 2 ) {
  372. result = result + 1;
  373. double sclk = (cpi_clock / prescaler);
  374. double tq = (1000 / (cpi_clock / prescaler));
  375. double smp = 100 - 2 / nbt * 100;
  376. double tdcoff_val = (!tdcen) ? 0 : cpi_clock / (2 * baudrate / 1000);
  377. results[result - 1][0] = prescaler;
  378. results[result - 1][1] = sclk;
  379. results[result - 1][2] = tq;
  380. results[result - 1][3] = nbt;
  381. results[result - 1][4] = propseg;
  382. results[result - 1][5] = 1;
  383. results[result - 1][6] = 2;
  384. results[result - 1][7] = 1;
  385. results[result - 1][8] = tdcen;
  386. results[result - 1][9] = tdcoff_val;
  387. results[result - 1][10] = smp;
  388. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) TDCEN TDCOFF Sample Point(%) FDCBT Register\n");
  389. if ( advanced ) Serial.printf(" %2u)", result);
  390. if ( advanced ) Serial.printf(" %4u", prescaler);
  391. if ( advanced ) Serial.printf(" %6.2f", sclk);
  392. if ( advanced ) Serial.printf(" %7.2f", tq);
  393. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  394. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  395. if ( advanced ) Serial.printf(" %2u", (uint32_t)1);
  396. if ( advanced ) Serial.printf(" %2u", (uint32_t)2);
  397. if ( advanced ) Serial.printf(" %2u", (uint32_t)1);
  398. if ( advanced ) Serial.printf(" %2u", (uint32_t)tdcen);
  399. if ( advanced ) Serial.printf(" %4.2f", tdcoff_val);
  400. if ( advanced ) Serial.printf(" %6.2f", smp);
  401. uint32_t fdcbt = 0;
  402. fdcbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // FPSEG2
  403. fdcbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // FPSEG1
  404. fdcbt |= ((uint32_t)(results[result - 1][4] - 0) << 10); // FPROPSEG
  405. fdcbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // FRJW
  406. fdcbt |= ((uint32_t)(results[result - 1][0] - 1) << 20); // FPRESDIV
  407. if ( advanced ) Serial.printf(" 0x%8.08X",fdcbt);
  408. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Data phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  409. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  410. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  411. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  412. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  413. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  414. char _sync[(scale*124/1000) + 1] = "";
  415. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  416. _sync[(scale*124/1000)] = '\0';
  417. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  418. char _prop[(scale*124/1000) + 1] = "";
  419. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  420. _prop[(scale*124/1000)] = '\0';
  421. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  422. char _pseg1[(scale*124/1000) + 1] = "";
  423. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  424. _pseg1[(scale*124/1000)] = '\0';
  425. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  426. char _pseg2[(scale*124/1000) + 1] = "";
  427. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  428. _pseg2[(scale*124/1000)] = '\0';
  429. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  430. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  431. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  432. }
  433. if ( pseg > (ipt + 1) && pseg <= (pseg1 * 2) ) {
  434. if ( (uint32_t)pseg % 2 != 0 ) propseg++;
  435. pseg = (nbt - 1 - propseg) / 2;
  436. result++;
  437. rjw = ( pseg <= rjw ) ? pseg : rjw;
  438. double sclk = (cpi_clock / prescaler);
  439. double tq = (1000 / (cpi_clock / prescaler));
  440. double smp = 100 - pseg / nbt * 100;
  441. double tdcoff_val = (!tdcen) ? 0 : cpi_clock / (2 * baudrate / 1000);
  442. results[result - 1][0] = prescaler;
  443. results[result - 1][1] = sclk;
  444. results[result - 1][2] = tq;
  445. results[result - 1][3] = nbt;
  446. results[result - 1][4] = propseg;
  447. results[result - 1][5] = pseg;
  448. results[result - 1][6] = pseg;
  449. results[result - 1][7] = rjw;
  450. results[result - 1][8] = tdcen;
  451. results[result - 1][9] = tdcoff_val;
  452. results[result - 1][10] = smp;
  453. if ( advanced ) Serial.print(" Prescaler Sclk(MHz) Tq(ns) NBT(#Tq) Propseg(#Tq) Pseg1(#Tq) Pseg2(#Tq) RJW(#Tq) TDCEN TDCOFF Sample Point(%) FDCBT Register\n");
  454. if ( advanced ) Serial.printf(" %2u)", result);
  455. if ( advanced ) Serial.printf(" %4u", prescaler);
  456. if ( advanced ) Serial.printf(" %6.2f", sclk);
  457. if ( advanced ) Serial.printf(" %7.2f", tq);
  458. if ( advanced ) Serial.printf(" %2u", (uint32_t)nbt);
  459. if ( advanced ) Serial.printf(" %2u", (uint32_t)propseg);
  460. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg);
  461. if ( advanced ) Serial.printf(" %2u", (uint32_t)pseg);
  462. if ( advanced ) Serial.printf(" %2u", (uint32_t)rjw);
  463. if ( advanced ) Serial.printf(" %2u", (uint32_t)tdcen);
  464. if ( advanced ) Serial.printf(" %4.2f", tdcoff_val);
  465. if ( advanced ) Serial.printf(" %6.2f", smp);
  466. uint32_t fdcbt = 0;
  467. fdcbt |= ((uint32_t)(results[result - 1][6] - 1) << 0); // FPSEG2
  468. fdcbt |= ((uint32_t)(results[result - 1][5] - 1) << 5); // FPSEG1
  469. fdcbt |= ((uint32_t)(results[result - 1][4] - 0) << 10); // FPROPSEG
  470. fdcbt |= ((uint32_t)(results[result - 1][7] - 1) << 16); // FRJW
  471. fdcbt |= ((uint32_t)(results[result - 1][0] - 1) << 20); // FPRESDIV
  472. if ( advanced ) Serial.printf(" 0x%8.08X",fdcbt);
  473. if ( advanced ) Serial.printf("\n\t%8s%s%.2f%s%u%s%.2f%s", "", "*** Data phase bit time = ", (results[result - 1][2] * results[result - 1][3] / 1000), "us (", (int)results[result - 1][3], "Tq, Tq=", results[result - 1][2], ")\n");
  474. if ( advanced ) Serial.printf("\t%8s%s%.2f%s", "", "a) Sync: ", results[result - 1][2], "ns\t");
  475. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "b) Propseg: ", results[result - 1][2] * results[result - 1][4], "ns\t");
  476. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "c) Pseg1: ", results[result - 1][2] * results[result - 1][5], "ns\t");
  477. if ( advanced ) Serial.printf("%8s%s%.2f%s", "", "d) Pseg2: ", results[result - 1][2] * results[result - 1][6], "ns\n");
  478. uint32_t scale = (uint32_t)ceil(results[result - 1][2]);
  479. char _sync[(scale*124/1000) + 1] = "";
  480. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _sync[i] = 'a';
  481. _sync[(scale*124/1000)] = '\0';
  482. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][4]);
  483. char _prop[(scale*124/1000) + 1] = "";
  484. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _prop[i] = 'b';
  485. _prop[(scale*124/1000)] = '\0';
  486. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][5]);
  487. char _pseg1[(scale*124/1000) + 1] = "";
  488. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg1[i] = 'c';
  489. _pseg1[(scale*124/1000)] = '\0';
  490. scale = (uint32_t)ceil(results[result - 1][2] * results[result - 1][6]);
  491. char _pseg2[(scale*124/1000) + 1] = "";
  492. for ( uint32_t i = 0; i < (scale*149/1200) + 1; i++ ) _pseg2[i] = 'd';
  493. _pseg2[(scale*124/1000)] = '\0';
  494. if ( advanced ) Serial.printf("%9s%s%-s%s%-s%s%-s%s%-s", "[", _sync, "|", _prop, "|", _pseg1, "|", _pseg2, "]\n");
  495. if ( advanced ) Serial.printf("%8s%-s%-s%-s%-s%-s%-s", "", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________", "|________________________|");
  496. if ( advanced ) Serial.printf("\n%8s%u%*s%u%*s%u%*s%u%*s%u%*s%u%*s%u%s\n\n\n\n", "", 0, 23, "", 200, 22, "", 400, 22, "", 600, 22, "", 800, 22, "", 1000, 22, "", 1200, "(ns)\n\n\n");
  497. }
  498. }
  499. result_old = result;
  500. break;
  501. }
  502. }
  503. }
  504. }
  505. }
  506. if ( flexdata_choice ) {
  507. if ( flexdata_choice > result ) {
  508. if ( advanced ) Serial.println("\n\t*** ERROR: FD rate selection out of bounds!\n");
  509. return 0;
  510. }
  511. uint32_t fdcbt = 0;
  512. fdcbt |= ((uint32_t)(results[flexdata_choice - 1][6] - 1) << 0); // FPSEG2
  513. fdcbt |= ((uint32_t)(results[flexdata_choice - 1][5] - 1) << 5); // FPSEG1
  514. fdcbt |= ((uint32_t)(results[flexdata_choice - 1][4] - 0) << 10); // FPROPSEG
  515. fdcbt |= ((uint32_t)(results[flexdata_choice - 1][7] - 1) << 16); // FRJW
  516. fdcbt |= ((uint32_t)(results[flexdata_choice - 1][0] - 1) << 20); // FPRESDIV
  517. FLEXCANb_FDCTRL(_bus) = (FLEXCANb_FDCTRL(_bus) & 0xFFFF60FF); /* clear TDC values */
  518. if ( ((uint32_t)(results[flexdata_choice - 1][8])) ) { /* enable TDC if available */
  519. FLEXCANb_FDCTRL(_bus) |= (1UL << 15) | (((uint32_t)(results[flexdata_choice - 1][9])) << 8);
  520. }
  521. return fdcbt;
  522. }
  523. return 0;
  524. }