pwm.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /************************************************************************
  2. Project: Welling Motor Control Paltform
  3. Filename: pwm.c
  4. Partner Filename: pwm.h
  5. Description: SVPWM and over voltage modulation
  6. Complier: IAR Embedded Workbench for ARM 7.80.4
  7. CPU TYPE : GD32F3x0
  8. *************************************************************************
  9. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
  10. All rights reserved.
  11. *************************************************************************
  12. *************************************************************************
  13. Revising History (ECL of this file):
  14. ************************************************************************/
  15. /************************************************************************
  16. Beginning of File, do not put anything above here except notes
  17. Compiler Directives:
  18. ************************************************************************/
  19. #ifndef _PWM_C_
  20. #define _PWM_C_
  21. #endif
  22. /************************************************************************
  23. Include File
  24. ************************************************************************/
  25. #include "syspar.h"
  26. #include "user.h"
  27. /************************************************************************
  28. Private Variables
  29. *************************************************************************/
  30. SWORD pwm_pvt_sw1st_Cur_Smpl_Ct = 0;
  31. SWORD pwm_pvt_sw2nd_Cur_Smpl_Ct = 0;
  32. SWORD pwm_pvt_swMin_Double_Cur_Smpl_Pu = 0;
  33. SWORD pwm_pvt_swMin_Cur_Smpl_Ct = 0;
  34. SWORD pwm_pvt_swMin_Cur_Smpl_Pu = 0;
  35. /************************************************************************
  36. Constant Table:
  37. ************************************************************************/
  38. /************************************************************************
  39. Exported Functions:
  40. ************************************************************************/
  41. /************************************************************************
  42. Function: pwm_voInit;
  43. Description: pwm generation initial;
  44. Call by: functions in main loop;
  45. Input Variables: N/A;
  46. Output/Return Variables: N/A;
  47. Subroutine Call: N/A;
  48. Reference: N/A;
  49. ************************************************************************/
  50. void pwm_voInit(void)
  51. {
  52. pwm_sw1stCurSmplCt = cp_stControlPara.swPWM1STSampleCnt; // min time for ADC one channel of Current
  53. pwm_sw2ndCurSmplCt = cp_stControlPara.swPWM2NDSampleCnt; // the time of second current sample trig lag the second comparator
  54. pwm_swMinDoubleCurSmplPu = (cp_stControlPara.swPWMMinEffVectorPu << 1); // min time of Two valid voltage vector
  55. pwm_swMinCurSmplCt = cp_stControlPara.swPWMMinEffVectorCnt; // min counts of one valid voltage vector
  56. pwm_swMinCurSmplPu = cp_stControlPara.swPWMMinEffVectorCnt; // min time of one valid voltage vector
  57. pwm_pvt_sw1st_Cur_Smpl_Ct = pwm_sw1stCurSmplCt;
  58. pwm_pvt_sw2nd_Cur_Smpl_Ct = pwm_sw2ndCurSmplCt;
  59. pwm_pvt_swMin_Double_Cur_Smpl_Pu = pwm_swMinDoubleCurSmplPu;
  60. pwm_pvt_swMin_Cur_Smpl_Ct = pwm_swMinCurSmplCt;
  61. pwm_pvt_swMin_Cur_Smpl_Pu = pwm_swMinCurSmplPu;
  62. pwm_stGenOut.swUalphaPu = 0; // Q14
  63. pwm_stGenOut.swUbetaPu = 0; // Q14
  64. pwm_stGenOut.uwNewSectorNum = 0;
  65. pwm_stGenOut.uwNewTIM1COMPR[0] = HW_HHPWM_PERIOD;
  66. pwm_stGenOut.uwNewTIM1COMPR[1] = HW_HHPWM_PERIOD;
  67. pwm_stGenOut.uwNewTIM1COMPR[2] = HW_HHPWM_PERIOD;
  68. pwm_stGenOut.uwNewTIM1COMPR[3] = HW_HHPWM_PERIOD;
  69. pwm_stGenOut.uwNewTIM1COMPR[4] = HW_HHPWM_PERIOD;
  70. pwm_stGenOut.uwNewTIM1COMPR[5] = HW_HHPWM_PERIOD;
  71. pwm_stGenOut.uwFirstTrigCOMPR = HW_HHHPWM_PERIOD;
  72. pwm_stGenOut.uwSecondTrigCOMPR = HW_HHPWM_PERIOD + HW_HHHPWM_PERIOD;
  73. pwm_stGenOut.uwOldTrig = 0;
  74. pwm_stGenOut.uwNewTrig = 0;
  75. pwm_stGenOut.uwSampleArea = IgnoreNone;
  76. pwm_stGenOut.uwRDSONTrig = 129;
  77. pwm_stGenOut.uwSigRTrig = HW_HHHPWM_PERIOD;
  78. }
  79. /************************************************************************
  80. Function: pwm_voGenCoef;
  81. Description: pwm generation coefficient initial;
  82. Call by: functions in main loop;
  83. Input Variables: PWM_COF_IN;
  84. Output/Return Variables: PWM_CALC_COF;
  85. Subroutine Call: N/A;
  86. Reference: N/A;
  87. ************************************************************************/
  88. void pwm_voGenCoef(PWM_COF_IN *in, PWM_CALC_COF *coef)
  89. {
  90. if (in->uwPWMDutyMax > 1000)
  91. {
  92. in->uwPWMDutyMax = 1000;
  93. }
  94. else if (in->uwPWMDutyMax == 0)
  95. {
  96. in->uwPWMDutyMax = 1;
  97. }
  98. if (in->uwPWM7To5Duty > 1000)
  99. {
  100. in->uwPWM7To5Duty = 1000;
  101. }
  102. else if (in->uwPWM7To5Duty == 0)
  103. {
  104. in->uwPWM7To5Duty = 1;
  105. }
  106. if (in->uwOvmNo > 2)
  107. {
  108. in->uwOvmNo = 2;
  109. }
  110. if (in->uwPWMPd > 31250)
  111. {
  112. in->uwPWMPd = 31250;
  113. }
  114. else if (in->uwPWMPd < 4)
  115. {
  116. in->uwPWMPd = 4;
  117. }
  118. coef->swPWMDutyMaxPu = ((SLONG)(in->uwPWMDutyMax - 3) << 14) / 1000; // Q14
  119. coef->swPWM7To5DutyPu = ((SLONG)in->uwPWM7To5Duty << 14) / 1000; // Q14
  120. coef->swPWMMinSample1Pu = ((SLONG)in->uwPWMMinSample1Pu << 14) / 1000; // Q14, unit:Pu two zero vector
  121. coef->swPWMMinSample2Pu = ((SLONG)in->uwPWMMinSample2Pu << 14) / 1000; // Q14, unit:Pu (one zero vector + sample time)*2
  122. coef->swPWMMinSample3Pu = ((SLONG)in->uwPWMMinSample3Pu << 14) / 1000; // Q14, unit:Pu (one Singel Resistance steady time + sample time)*2
  123. coef->uwOvmNo = in->uwOvmNo;
  124. coef->uwPWMPd = in->uwPWMPd;
  125. coef->uwHPWMPd = in->uwPWMPd >> 1;
  126. coef->uwHHPWMPd = in->uwPWMPd >> 2;
  127. coef->ulPWMPerInv = (((ULONG)1 << 21) / in->uwPWMPd); // Q21, 1/PWM period
  128. coef->uwMaxCmpCt = ((SLONG)in->uwPWMDutyMax * coef->uwHPWMPd) / 1000; // Q14
  129. coef->uwSampleSteadyCt = ((SLONG)in->uwSampleSteadyPu * coef->uwHPWMPd) / 1000;
  130. coef->uwSingelResisSampleCt = ((SLONG)in->uwSingelResisSamplePu * coef->uwHPWMPd) / 1000;
  131. }
  132. /************************************************************************
  133. Function: pwm_voGen;
  134. Description: pwm generation;
  135. Call by: functions in TBC;
  136. Input Variables: PWM_GEN_IN, PWM_CALC_COF;
  137. Output/Return Variables: PWM_GEN_OUT;
  138. Subroutine Call: N/A;
  139. Reference: N/A;
  140. ************************************************************************/
  141. UWORD testkjsahfjkahj,testkjsahfjkahj1;
  142. SWORD swOvmT1, swOvmT2;
  143. void pwm_voGen(PWM_GEN_IN *in, PWM_CALC_COF *coef, PWM_GEN_OUT *out)
  144. {
  145. SLONG slL1, slL2, slL3;
  146. SLONG slKsvpwm;
  147. SLONG slX, slY, slZ;
  148. SWORD swT1, swT2;
  149. UWORD uwSector;
  150. SWORD swUaPu, swUbPu, swUcPu;
  151. SWORD swPWMPRD1, swPWMPRD2, swPWMPRD3;
  152. // SWORD swPWMPRD11,swPWMPRD21,swPWMPRD31,swPWMPRD12,swPWMPRD22,swPWMPRD32;
  153. SWORD tmp_swPeriodA, tmp_swPeriodB, tmp_swPeriodC;
  154. /*==============================================================================
  155. Sector Determination
  156. L1 = Ubeta
  157. L2 = sqrt(3)/2 * Ualfa - 1/2 * Ubeta
  158. L3 = -sqrt(3)/2 * Ualfa - 1/2 * Ubeta
  159. ==============================================================================*/
  160. slL1 = in->swUbetaPu + 1; // Q14
  161. slL2 = ((in->swUalphaPu * PWM_SQRT3 >> 14) - in->swUbetaPu) >> 1; // Q14
  162. slL3 = (-(in->swUalphaPu * PWM_SQRT3 >> 14) - in->swUbetaPu) >> 1; // Q14
  163. uwSector = 0;
  164. if (slL1 > 0)
  165. {
  166. uwSector += 1;
  167. }
  168. if (slL2 > 0)
  169. {
  170. uwSector += 2;
  171. }
  172. if (slL3 > 0)
  173. {
  174. uwSector += 4;
  175. }
  176. /*======================================================================
  177. Base Voltage Vector Period(t1/t2) calculation according to sector
  178. X = 2/sqrt(3)*Ts*slv1
  179. Y = -2/sqrt(3)*Ts*slv3
  180. Z = -2/sqrt(3)*Ts*slv2
  181. =======================================================================*/
  182. if (in->uwVdcPu < 10)
  183. {
  184. in->uwVdcPu = 10;
  185. }
  186. slKsvpwm = (PWM_SQRT3 << 15) / in->uwVdcPu; // Q15=Q14+Q15-Q14
  187. slX = slKsvpwm * (slL1 - 1) >> 15; // Q14
  188. slY = -slKsvpwm * slL3 >> 15; // Q14
  189. slZ = -slKsvpwm * slL2 >> 15; // Q14
  190. switch (uwSector)
  191. {
  192. case 3:
  193. swT1 = -slZ; // Q14, t1
  194. swT2 = slX; // Q14, t2
  195. break;
  196. case 1:
  197. swT1 = slZ; // Q14, t1
  198. swT2 = slY; // Q14, t2
  199. break;
  200. case 5:
  201. swT1 = slX; // Q14, t1
  202. swT2 = -slY; // Q14, t2
  203. break;
  204. case 4:
  205. swT1 = -slX; // Q14, t1
  206. swT2 = slZ; // Q14, t2
  207. break;
  208. case 6:
  209. swT1 = -slY; // Q14, t1
  210. swT2 = -slZ; // Q14, t2
  211. break;
  212. case 2:
  213. swT1 = slY; // Q14, t1
  214. swT2 = -slX; // Q14, t2
  215. break;
  216. default:
  217. swT1 = 0;
  218. swT2 = 0;
  219. break;
  220. }
  221. /*================================================================
  222. Over voltage modulation
  223. ================================================================*/
  224. switch (coef->uwOvmNo)
  225. {
  226. case 0:
  227. /* SVPWM over modulation: min phase error */
  228. if ((swT1 + swT2) > coef->swPWMDutyMaxPu)
  229. {
  230. swOvmT1 = (SLONG)swT1 * coef->swPWMDutyMaxPu / (swT1 + swT2); // Q14=Q14+Q14-Q14
  231. swOvmT2 = coef->swPWMDutyMaxPu - swOvmT1;
  232. out->blOvmFlag = TRUE;
  233. }
  234. else
  235. {
  236. swOvmT1 = swT1;
  237. swOvmT2 = swT2;
  238. out->blOvmFlag = FALSE;
  239. }
  240. break;
  241. case 1:
  242. /* SVPWM over modulation: min amplitude error */
  243. if ((swT1 + swT2) > coef->swPWMDutyMaxPu)
  244. {
  245. swOvmT1 = swT1 - ((swT1 + swT2 - coef->swPWMDutyMaxPu) >> 1);
  246. swOvmT2 = swT2 - ((swT1 + swT2 - coef->swPWMDutyMaxPu) >> 1);
  247. if (swOvmT1 < 0)
  248. {
  249. swOvmT1 = 0;
  250. swOvmT2 = coef->swPWMDutyMaxPu;
  251. }
  252. if (swOvmT2 < 0)
  253. {
  254. swOvmT2 = 0;
  255. swOvmT1 = coef->swPWMDutyMaxPu;
  256. }
  257. out->blOvmFlag = TRUE;
  258. }
  259. else
  260. {
  261. swOvmT1 = swT1;
  262. swOvmT2 = swT2;
  263. out->blOvmFlag = FALSE;
  264. }
  265. break;
  266. case 2:
  267. /* SVPWM over modulation: amplitude and phase optimum */
  268. if ((swT1 + swT2) > coef->swPWMDutyMaxPu)
  269. {
  270. if (swT1 > swT2)
  271. {
  272. if (swT1 > coef->swPWMDutyMaxPu)
  273. {
  274. swOvmT1 = coef->swPWMDutyMaxPu;
  275. }
  276. else
  277. {
  278. swOvmT1 = swT1;
  279. }
  280. swOvmT2 = coef->swPWMDutyMaxPu - swOvmT1;
  281. }
  282. else
  283. {
  284. if (swT2 > coef->swPWMDutyMaxPu)
  285. {
  286. swOvmT2 = coef->swPWMDutyMaxPu;
  287. }
  288. else
  289. {
  290. swOvmT2 = swT2;
  291. }
  292. swOvmT1 = coef->swPWMDutyMaxPu - swOvmT2;
  293. }
  294. out->blOvmFlag = TRUE;
  295. }
  296. else
  297. {
  298. swOvmT1 = swT1;
  299. swOvmT2 = swT2;
  300. out->blOvmFlag = FALSE;
  301. }
  302. break;
  303. default:
  304. /* SVPWM over modulation: amplitude and phase optimum */
  305. if ((swT1 + swT2) > coef->swPWMDutyMaxPu)
  306. {
  307. if (swT1 > swT2)
  308. {
  309. if (swT1 > coef->swPWMDutyMaxPu)
  310. {
  311. swOvmT1 = coef->swPWMDutyMaxPu;
  312. }
  313. else
  314. {
  315. swOvmT1 = swT1;
  316. }
  317. swOvmT2 = coef->swPWMDutyMaxPu - swOvmT1;
  318. }
  319. else
  320. {
  321. if (swT2 > coef->swPWMDutyMaxPu)
  322. {
  323. swOvmT2 = coef->swPWMDutyMaxPu;
  324. }
  325. else
  326. {
  327. swOvmT2 = swT2;
  328. }
  329. swOvmT1 = coef->swPWMDutyMaxPu - swOvmT2;
  330. }
  331. out->blOvmFlag = TRUE;
  332. }
  333. else
  334. {
  335. swOvmT1 = swT1;
  336. swOvmT2 = swT2;
  337. out->blOvmFlag = FALSE;
  338. }
  339. break;
  340. }
  341. if(cp_stFlg.CurrentSampleModelSelect == COMBINATION)
  342. {
  343. /*================================================================
  344. Calculate compare value
  345. ================================================================*/
  346. if ((swOvmT1 + swOvmT2) > coef->swPWM7To5DutyPu) /* Five SVPWM */
  347. {
  348. swPWMPRD1 = coef->uwHPWMPd;
  349. swPWMPRD2 = ((ULONG)(16384 - swOvmT2) * coef->uwHPWMPd) >> 14;
  350. swPWMPRD3 = ((ULONG)(16384 - swOvmT1 - swOvmT2) * coef->uwHPWMPd) >> 14;
  351. }
  352. else /* Seven SVPWM */
  353. {
  354. swPWMPRD1 = ((ULONG)(16384 + swOvmT1 + swOvmT2) * coef->uwHHPWMPd) >> 14;
  355. swPWMPRD2 = ((ULONG)(16384 + swOvmT1 - swOvmT2) * coef->uwHHPWMPd) >> 14;
  356. swPWMPRD3 = ((ULONG)(16384 - swOvmT1 - swOvmT2) * coef->uwHHPWMPd) >> 14;
  357. }
  358. if (swOvmT2 > coef->swPWMMinSample3Pu)
  359. {
  360. out->blSampleCalibFlag = TRUE;
  361. //out->uwSigRTrig = swPWMPRD2 + coef->uwSingelResisSampleCt;
  362. out->uwSigRTrig = swPWMPRD1 - coef->uwSingelResisSampleCt;
  363. }
  364. else
  365. {
  366. out->blSampleCalibFlag = FALSE;
  367. out->uwSigRTrig = HW_HHHPWM_PERIOD;
  368. }
  369. out->uwSingelRSampleAreaLast = out->uwSingelRSampleArea;
  370. if(1)//hw_blChrgOvrFlg == TRUE)
  371. {
  372. switch (uwSector)
  373. {
  374. case 3:
  375. out->uwNewTIM1COMPR[0] = swPWMPRD3;
  376. out->uwNewTIM1COMPR[1] = swPWMPRD2;
  377. out->uwNewTIM1COMPR[2] = swPWMPRD1;
  378. out->uwNewTIM1COMPR[3] = swPWMPRD3;
  379. out->uwNewTIM1COMPR[4] = swPWMPRD2;
  380. out->uwNewTIM1COMPR[5] = swPWMPRD1;
  381. if (out->blSampleCalibFlag == TRUE)
  382. {
  383. out->uwSingelRSampleArea = SampleC;
  384. }
  385. else
  386. {
  387. out->uwSingelRSampleArea = SampleNone;
  388. }
  389. break;
  390. case 1:
  391. out->uwNewTIM1COMPR[0] = swPWMPRD2;
  392. out->uwNewTIM1COMPR[1] = swPWMPRD3;
  393. out->uwNewTIM1COMPR[2] = swPWMPRD1;
  394. out->uwNewTIM1COMPR[3] = swPWMPRD2;
  395. out->uwNewTIM1COMPR[4] = swPWMPRD3;
  396. out->uwNewTIM1COMPR[5] = swPWMPRD1;
  397. if (out->blSampleCalibFlag == TRUE)
  398. {
  399. out->uwSingelRSampleArea = SampleC;
  400. }
  401. else
  402. {
  403. out->uwSingelRSampleArea = SampleNone;
  404. }
  405. break;
  406. case 5:
  407. out->uwNewTIM1COMPR[0] = swPWMPRD1;
  408. out->uwNewTIM1COMPR[1] = swPWMPRD3;
  409. out->uwNewTIM1COMPR[2] = swPWMPRD2;
  410. out->uwNewTIM1COMPR[3] = swPWMPRD1;
  411. out->uwNewTIM1COMPR[4] = swPWMPRD3;
  412. out->uwNewTIM1COMPR[5] = swPWMPRD2;
  413. if (out->blSampleCalibFlag == TRUE)
  414. {
  415. out->uwSingelRSampleArea = SampleA;
  416. }
  417. else
  418. {
  419. out->uwSingelRSampleArea = SampleNone;
  420. }
  421. break;
  422. case 4:
  423. out->uwNewTIM1COMPR[0] = swPWMPRD1;
  424. out->uwNewTIM1COMPR[1] = swPWMPRD2;
  425. out->uwNewTIM1COMPR[2] = swPWMPRD3;
  426. out->uwNewTIM1COMPR[3] = swPWMPRD1;
  427. out->uwNewTIM1COMPR[4] = swPWMPRD2;
  428. out->uwNewTIM1COMPR[5] = swPWMPRD3;
  429. if (out->blSampleCalibFlag == TRUE)
  430. {
  431. out->uwSingelRSampleArea = SampleA;
  432. }
  433. else
  434. {
  435. out->uwSingelRSampleArea = SampleNone;
  436. }
  437. break;
  438. case 6:
  439. out->uwNewTIM1COMPR[0] = swPWMPRD2;
  440. out->uwNewTIM1COMPR[1] = swPWMPRD1;
  441. out->uwNewTIM1COMPR[2] = swPWMPRD3;
  442. out->uwNewTIM1COMPR[3] = swPWMPRD2;
  443. out->uwNewTIM1COMPR[4] = swPWMPRD1;
  444. out->uwNewTIM1COMPR[5] = swPWMPRD3;
  445. if (out->blSampleCalibFlag == TRUE)
  446. {
  447. out->uwSingelRSampleArea = SampleB;
  448. }
  449. else
  450. {
  451. out->uwSingelRSampleArea = SampleNone;
  452. }
  453. break;
  454. case 2:
  455. out->uwNewTIM1COMPR[0] = swPWMPRD3;
  456. out->uwNewTIM1COMPR[1] = swPWMPRD1;
  457. out->uwNewTIM1COMPR[2] = swPWMPRD2;
  458. out->uwNewTIM1COMPR[3] = swPWMPRD3;
  459. out->uwNewTIM1COMPR[4] = swPWMPRD1;
  460. out->uwNewTIM1COMPR[5] = swPWMPRD2;
  461. if (out->blSampleCalibFlag == TRUE)
  462. {
  463. out->uwSingelRSampleArea = SampleB;
  464. }
  465. else
  466. {
  467. out->uwSingelRSampleArea = SampleNone;
  468. }
  469. break;
  470. default:
  471. out->uwNewTIM1COMPR[0] = coef->uwHHPWMPd;
  472. out->uwNewTIM1COMPR[1] = coef->uwHHPWMPd;
  473. out->uwNewTIM1COMPR[2] = coef->uwHHPWMPd;
  474. out->uwNewTIM1COMPR[3] = coef->uwHHPWMPd;
  475. out->uwNewTIM1COMPR[4] = coef->uwHHPWMPd;
  476. out->uwNewTIM1COMPR[5] = coef->uwHHPWMPd;
  477. out->uwSingelRSampleArea = SampleNone;
  478. break;
  479. }
  480. }
  481. /* Calculate actual output voltage */
  482. out->uwNewSectorNum = uwSector;
  483. out->uwPWMNewSectorNum = out->uwNewSectorNum;
  484. tmp_swPeriodA = coef->uwPWMPd - out->uwNewTIM1COMPR[0] - out->uwNewTIM1COMPR[3];
  485. tmp_swPeriodB = coef->uwPWMPd - out->uwNewTIM1COMPR[1] - out->uwNewTIM1COMPR[4];
  486. tmp_swPeriodC = coef->uwPWMPd - out->uwNewTIM1COMPR[2] - out->uwNewTIM1COMPR[5];
  487. swUaPu = ((((SLONG)tmp_swPeriodA * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  488. swUbPu = ((((SLONG)tmp_swPeriodB * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  489. swUcPu = ((((SLONG)tmp_swPeriodC * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  490. out->swUalphaPu = (swUaPu + swUaPu - swUbPu - swUcPu) * PWM_1DIV3 >> 14; // Q14=Q14+Q14-Q14
  491. out->swUbetaPu = (swUbPu - swUcPu) * PWM_SQRT3_INV >> 14; // Q14=Q14+Q14-Q14
  492. // if((16384-swOvmT1-swOvmT2)>coef->swPWMMinSample1Pu)
  493. // {
  494. // out->uwSampleArea = IgnoreNone;
  495. out->uwRDSONTrig = 129;
  496. // }
  497. // else
  498. // {
  499. // if(swOvmT1>coef->swPWMMinSample1Pu)
  500. // {
  501. // switch(uwSector)
  502. // {
  503. // case 3:
  504. // out->uwSampleArea = IgnoreA;
  505. // break;
  506. // case 1:
  507. // out->uwSampleArea = IgnoreB;
  508. // break;
  509. // case 5:
  510. // out->uwSampleArea = IgnoreB;
  511. // break;
  512. // case 4:
  513. // out->uwSampleArea = IgnoreC;
  514. // break;
  515. // case 6:
  516. // out->uwSampleArea = IgnoreC;
  517. // break;
  518. // case 2:
  519. // out->uwSampleArea = IgnoreA;
  520. // break;
  521. // default:
  522. // out->uwSampleArea = IgnoreNone;
  523. // break;
  524. // }
  525. // out->uwRDSONTrig = swPWMPRD3 + coef->uwSampleSteadyCt;
  526. // }
  527. // else
  528. // {
  529. // switch(uwSector)
  530. // {
  531. // case 3:
  532. // out->uwSampleArea = IgnoreAB;
  533. // break;
  534. // case 1:
  535. // out->uwSampleArea = IgnoreAB;
  536. // break;
  537. // case 5:
  538. // out->uwSampleArea = IgnoreBC;
  539. // break;
  540. // case 4:
  541. // out->uwSampleArea = IgnoreBC;
  542. // break;
  543. // case 6:
  544. // out->uwSampleArea = IgnoreAC;
  545. // break;
  546. // case 2:
  547. // out->uwSampleArea = IgnoreAC;
  548. // break;
  549. // default:
  550. // out->uwSampleArea = IgnoreNone;
  551. // break;
  552. // }
  553. // out->uwRDSONTrig = swPWMPRD2 + coef->uwSampleSteadyCt;
  554. // }
  555. // }
  556. }
  557. else if(cp_stFlg.CurrentSampleModelSelect == SINGLERESISITANCE)
  558. {
  559. SWORD swPWMPRD11=0;
  560. SWORD swPWMPRD21=0;
  561. SWORD swPWMPRD31=0;
  562. SWORD swPWMPRD12=0;
  563. SWORD swPWMPRD22=0;
  564. SWORD swPWMPRD32=0;
  565. /*1/4 of zero vector in the middle,and others apart in the beginning and ending*/
  566. swPWMPRD1 = (((SLONG)16384 * 3 + swOvmT1 + swOvmT2) * coef->uwPWMPd) >> 17; // Q14
  567. swPWMPRD2 = (((SLONG)16384 * 3 + swOvmT1 - swOvmT2 * 3) * coef->uwPWMPd) >> 17;
  568. swPWMPRD3 = (((SLONG)16384 - swOvmT1 - swOvmT2) * 3 * coef->uwPWMPd) >> 17;
  569. swPWMPRD11 = swPWMPRD1;
  570. swPWMPRD21 = swPWMPRD2;
  571. swPWMPRD31 = swPWMPRD3;
  572. swPWMPRD12 = swPWMPRD1;
  573. swPWMPRD22 = swPWMPRD2;
  574. swPWMPRD32 = swPWMPRD3;
  575. /* comparision value correction when two vectors are both too short*/
  576. testkjsahfjkahj1=0;
  577. testkjsahfjkahj=0;
  578. if ((swOvmT1 + swOvmT2) < (pwm_pvt_swMin_Double_Cur_Smpl_Pu << 1))
  579. {
  580. if ((swOvmT1 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
  581. {
  582. swPWMPRD31 = swPWMPRD2 - pwm_pvt_swMin_Cur_Smpl_Ct;
  583. swPWMPRD32 = (swPWMPRD3 << 1) - swPWMPRD31;
  584. testkjsahfjkahj1=1;
  585. }
  586. if ((swOvmT2 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
  587. {
  588. swPWMPRD11 = swPWMPRD2 + pwm_pvt_swMin_Cur_Smpl_Ct;
  589. swPWMPRD12 = (swPWMPRD1 << 1) - swPWMPRD11;
  590. testkjsahfjkahj=2;
  591. }
  592. }
  593. else
  594. {
  595. if ((swOvmT2 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
  596. {
  597. if (((coef->uwHPWMPd + swPWMPRD1 - 2 * swPWMPRD2) <= pwm_pvt_swMin_Cur_Smpl_Ct) && ((swOvmT1 + swOvmT2) > coef->swPWM7To5DutyPu))
  598. {
  599. swPWMPRD1 = (((SLONG)swOvmT1 + swOvmT2) * coef->uwPWMPd) >> 15;
  600. swPWMPRD2 = ((SLONG)swOvmT1 * coef->uwPWMPd) >> 15;
  601. swPWMPRD3 = 0;
  602. swPWMPRD11 = coef->uwHPWMPd;
  603. swPWMPRD12 = (swPWMPRD1 << 1) - swPWMPRD11;
  604. swPWMPRD31 = swPWMPRD3;
  605. swPWMPRD32 = swPWMPRD3;
  606. swPWMPRD22 = coef->uwHPWMPd;
  607. swPWMPRD21 = (swPWMPRD2 << 1) - swPWMPRD22;
  608. testkjsahfjkahj=3;
  609. }
  610. else
  611. {
  612. swPWMPRD21 = swPWMPRD1 - pwm_pvt_swMin_Cur_Smpl_Ct;
  613. swPWMPRD22 = (swPWMPRD2 << 1) - swPWMPRD21;
  614. testkjsahfjkahj=4;
  615. }
  616. }
  617. else if ((swOvmT1 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
  618. {
  619. if (((2 * swPWMPRD2 - swPWMPRD3) <= pwm_pvt_swMin_Cur_Smpl_Ct) && ((swOvmT1 + swOvmT2) > coef->swPWM7To5DutyPu))
  620. {
  621. swPWMPRD1 = coef->uwHPWMPd;
  622. swPWMPRD2 = (((SLONG)16384 - swOvmT2) * coef->uwPWMPd) >> 15;
  623. swPWMPRD3 = (((SLONG)16384 - swOvmT1 - swOvmT2) * coef->uwPWMPd) >> 15;
  624. swPWMPRD11 = swPWMPRD1;
  625. swPWMPRD12 = swPWMPRD1;
  626. swPWMPRD22 = 0;
  627. swPWMPRD21 = (swPWMPRD2 << 1) - swPWMPRD22;
  628. swPWMPRD31 = 0;
  629. swPWMPRD32 = (swPWMPRD3 << 1) - swPWMPRD31;
  630. testkjsahfjkahj=5;
  631. }
  632. else
  633. {
  634. swPWMPRD21 = swPWMPRD3 + pwm_pvt_swMin_Cur_Smpl_Ct;
  635. swPWMPRD22 = (swPWMPRD2 << 1) - swPWMPRD21;
  636. testkjsahfjkahj=6;
  637. }
  638. }
  639. else
  640. {
  641. }
  642. }
  643. out->uwOldTrig = out->uwNewTrig;
  644. out->uwNewTrig = swPWMPRD21;
  645. switch (uwSector)
  646. {
  647. case 3:
  648. out->uwNewTIM1COMPR[0] = swPWMPRD31;
  649. out->uwNewTIM1COMPR[1] = swPWMPRD21;
  650. out->uwNewTIM1COMPR[2] = swPWMPRD11;
  651. out->uwNewTIM1COMPR[3] = swPWMPRD32;
  652. out->uwNewTIM1COMPR[4] = swPWMPRD22;
  653. out->uwNewTIM1COMPR[5] = swPWMPRD12;
  654. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  655. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  656. break;
  657. case 1:
  658. out->uwNewTIM1COMPR[0] = swPWMPRD21;
  659. out->uwNewTIM1COMPR[1] = swPWMPRD31;
  660. out->uwNewTIM1COMPR[2] = swPWMPRD11;
  661. out->uwNewTIM1COMPR[3] = swPWMPRD22;
  662. out->uwNewTIM1COMPR[4] = swPWMPRD32;
  663. out->uwNewTIM1COMPR[5] = swPWMPRD12;
  664. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  665. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  666. break;
  667. case 5:
  668. out->uwNewTIM1COMPR[0] = swPWMPRD11;
  669. out->uwNewTIM1COMPR[1] = swPWMPRD31;
  670. out->uwNewTIM1COMPR[2] = swPWMPRD21;
  671. out->uwNewTIM1COMPR[3] = swPWMPRD12;
  672. out->uwNewTIM1COMPR[4] = swPWMPRD32;
  673. out->uwNewTIM1COMPR[5] = swPWMPRD22;
  674. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  675. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  676. break;
  677. case 4:
  678. out->uwNewTIM1COMPR[0] = swPWMPRD11;
  679. out->uwNewTIM1COMPR[1] = swPWMPRD21;
  680. out->uwNewTIM1COMPR[2] = swPWMPRD31;
  681. out->uwNewTIM1COMPR[3] = swPWMPRD12;
  682. out->uwNewTIM1COMPR[4] = swPWMPRD22;
  683. out->uwNewTIM1COMPR[5] = swPWMPRD32;
  684. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  685. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  686. break;
  687. case 6:
  688. out->uwNewTIM1COMPR[0] = swPWMPRD21;
  689. out->uwNewTIM1COMPR[1] = swPWMPRD11;
  690. out->uwNewTIM1COMPR[2] = swPWMPRD31;
  691. out->uwNewTIM1COMPR[3] = swPWMPRD22;
  692. out->uwNewTIM1COMPR[4] = swPWMPRD12;
  693. out->uwNewTIM1COMPR[5] = swPWMPRD32;
  694. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  695. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  696. break;
  697. case 2:
  698. out->uwNewTIM1COMPR[0] = swPWMPRD31;
  699. out->uwNewTIM1COMPR[1] = swPWMPRD11;
  700. out->uwNewTIM1COMPR[2] = swPWMPRD21;
  701. out->uwNewTIM1COMPR[3] = swPWMPRD32;
  702. out->uwNewTIM1COMPR[4] = swPWMPRD12;
  703. out->uwNewTIM1COMPR[5] = swPWMPRD22;
  704. out->uwFirstTrigCOMPR = swPWMPRD21 - pwm_pvt_sw1st_Cur_Smpl_Ct;
  705. out->uwSecondTrigCOMPR = swPWMPRD21 + pwm_pvt_sw2nd_Cur_Smpl_Ct;
  706. break;
  707. default:
  708. out->uwNewTIM1COMPR[0] = coef->uwHHPWMPd;
  709. out->uwNewTIM1COMPR[1] = coef->uwHHPWMPd;
  710. out->uwNewTIM1COMPR[2] = coef->uwHHPWMPd;
  711. out->uwNewTIM1COMPR[3] = coef->uwHHPWMPd;
  712. out->uwNewTIM1COMPR[4] = coef->uwHHPWMPd;
  713. out->uwNewTIM1COMPR[5] = coef->uwHHPWMPd;
  714. out->uwFirstTrigCOMPR = coef->uwHHPWMPd >> 1;
  715. out->uwSecondTrigCOMPR = coef->uwHPWMPd - coef->uwHHPWMPd >> 1;
  716. break;
  717. }
  718. out->uwNewSectorNum = uwSector;
  719. out->uwPWMNewSectorNum = out->uwNewSectorNum;
  720. tmp_swPeriodA = coef->uwPWMPd - out->uwNewTIM1COMPR[0] - out->uwNewTIM1COMPR[3];
  721. tmp_swPeriodB = coef->uwPWMPd - out->uwNewTIM1COMPR[1] - out->uwNewTIM1COMPR[4];
  722. tmp_swPeriodC = coef->uwPWMPd - out->uwNewTIM1COMPR[2] - out->uwNewTIM1COMPR[5];
  723. swUaPu = ((((SLONG)tmp_swPeriodA * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  724. swUbPu = ((((SLONG)tmp_swPeriodB * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  725. swUcPu = ((((SLONG)tmp_swPeriodC * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  726. out->swUalphaPu = (swUaPu + swUaPu - swUbPu - swUcPu) * PWM_1DIV3 >> 14; // Q14=Q14+Q14-Q14
  727. out->swUbetaPu = (swUbPu - swUcPu) * PWM_SQRT3_INV >> 14; // Q14=Q14+Q14-Q14
  728. }
  729. else if(cp_stFlg.CurrentSampleModelSelect == RDSON)
  730. {
  731. /*================================================================
  732. Calculate compare value
  733. ================================================================*/
  734. if ((swOvmT1 + swOvmT2) > coef->swPWM7To5DutyPu) /* Five SVPWM */
  735. {
  736. swPWMPRD1 = coef->uwHPWMPd;
  737. swPWMPRD2 = ((ULONG)(16384 - swOvmT2) * coef->uwHPWMPd) >> 14;
  738. swPWMPRD3 = ((ULONG)(16384 - swOvmT1 - swOvmT2) * coef->uwHPWMPd) >> 14;
  739. }
  740. else /* Seven SVPWM */
  741. {
  742. swPWMPRD1 = ((ULONG)(16384 + swOvmT1 + swOvmT2) * coef->uwHHPWMPd) >> 14;
  743. swPWMPRD2 = ((ULONG)(16384 + swOvmT1 - swOvmT2) * coef->uwHHPWMPd) >> 14;
  744. swPWMPRD3 = ((ULONG)(16384 - swOvmT1 - swOvmT2) * coef->uwHHPWMPd) >> 14;
  745. }
  746. switch (uwSector)
  747. {
  748. case 3:
  749. out->uwNewTIM1COMPR[0] = swPWMPRD3;
  750. out->uwNewTIM1COMPR[1] = swPWMPRD2;
  751. out->uwNewTIM1COMPR[2] = swPWMPRD1;
  752. out->uwNewTIM1COMPR[3] = swPWMPRD3;
  753. out->uwNewTIM1COMPR[4] = swPWMPRD2;
  754. out->uwNewTIM1COMPR[5] = swPWMPRD1;
  755. break;
  756. case 1:
  757. out->uwNewTIM1COMPR[0] = swPWMPRD2;
  758. out->uwNewTIM1COMPR[1] = swPWMPRD3;
  759. out->uwNewTIM1COMPR[2] = swPWMPRD1;
  760. out->uwNewTIM1COMPR[3] = swPWMPRD2;
  761. out->uwNewTIM1COMPR[4] = swPWMPRD3;
  762. out->uwNewTIM1COMPR[5] = swPWMPRD1;
  763. break;
  764. case 5:
  765. out->uwNewTIM1COMPR[0] = swPWMPRD1;
  766. out->uwNewTIM1COMPR[1] = swPWMPRD3;
  767. out->uwNewTIM1COMPR[2] = swPWMPRD2;
  768. out->uwNewTIM1COMPR[3] = swPWMPRD1;
  769. out->uwNewTIM1COMPR[4] = swPWMPRD3;
  770. out->uwNewTIM1COMPR[5] = swPWMPRD2;
  771. break;
  772. case 4:
  773. out->uwNewTIM1COMPR[0] = swPWMPRD1;
  774. out->uwNewTIM1COMPR[1] = swPWMPRD2;
  775. out->uwNewTIM1COMPR[2] = swPWMPRD3;
  776. out->uwNewTIM1COMPR[3] = swPWMPRD1;
  777. out->uwNewTIM1COMPR[4] = swPWMPRD2;
  778. out->uwNewTIM1COMPR[5] = swPWMPRD3;
  779. break;
  780. case 6:
  781. out->uwNewTIM1COMPR[0] = swPWMPRD2;
  782. out->uwNewTIM1COMPR[1] = swPWMPRD1;
  783. out->uwNewTIM1COMPR[2] = swPWMPRD3;
  784. out->uwNewTIM1COMPR[3] = swPWMPRD2;
  785. out->uwNewTIM1COMPR[4] = swPWMPRD1;
  786. out->uwNewTIM1COMPR[5] = swPWMPRD3;
  787. break;
  788. case 2:
  789. out->uwNewTIM1COMPR[0] = swPWMPRD3;
  790. out->uwNewTIM1COMPR[1] = swPWMPRD1;
  791. out->uwNewTIM1COMPR[2] = swPWMPRD2;
  792. out->uwNewTIM1COMPR[3] = swPWMPRD3;
  793. out->uwNewTIM1COMPR[4] = swPWMPRD1;
  794. out->uwNewTIM1COMPR[5] = swPWMPRD2;
  795. break;
  796. default:
  797. out->uwNewTIM1COMPR[0] = coef->uwHHPWMPd;
  798. out->uwNewTIM1COMPR[1] = coef->uwHHPWMPd;
  799. out->uwNewTIM1COMPR[2] = coef->uwHHPWMPd;
  800. out->uwNewTIM1COMPR[3] = coef->uwHHPWMPd;
  801. out->uwNewTIM1COMPR[4] = coef->uwHHPWMPd;
  802. out->uwNewTIM1COMPR[5] = coef->uwHHPWMPd;
  803. break;
  804. }
  805. /* Calculate actual output voltage */
  806. out->uwNewSectorNum = uwSector;
  807. out->uwPWMNewSectorNum = out->uwNewSectorNum;
  808. tmp_swPeriodA = coef->uwPWMPd - out->uwNewTIM1COMPR[0] - out->uwNewTIM1COMPR[3];
  809. tmp_swPeriodB = coef->uwPWMPd - out->uwNewTIM1COMPR[1] - out->uwNewTIM1COMPR[4];
  810. tmp_swPeriodC = coef->uwPWMPd - out->uwNewTIM1COMPR[2] - out->uwNewTIM1COMPR[5];
  811. swUaPu = ((((SLONG)tmp_swPeriodA * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  812. swUbPu = ((((SLONG)tmp_swPeriodB * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  813. swUcPu = ((((SLONG)tmp_swPeriodC * coef->ulPWMPerInv) >> 5) * in->uwVdcPu) >> 16; // Q21-Q5+Q14-Q16=Q14
  814. out->swUalphaPu = (swUaPu + swUaPu - swUbPu - swUcPu) * PWM_1DIV3 >> 14; // Q14=Q14+Q14-Q14
  815. out->swUbetaPu = (swUbPu - swUcPu) * PWM_SQRT3_INV >> 14; // Q14=Q14+Q14-Q14
  816. if ((16384 - swOvmT1 - swOvmT2) > coef->swPWMMinSample1Pu)
  817. {
  818. out->uwSampleArea = IgnoreNone;
  819. out->uwRDSONTrig = 129;
  820. }
  821. else
  822. {
  823. if (swOvmT1 > coef->swPWMMinSample1Pu)
  824. {
  825. switch (uwSector)
  826. {
  827. case 3:
  828. out->uwSampleArea = IgnoreA;
  829. break;
  830. case 1:
  831. out->uwSampleArea = IgnoreB;
  832. break;
  833. case 5:
  834. out->uwSampleArea = IgnoreB;
  835. break;
  836. case 4:
  837. out->uwSampleArea = IgnoreC;
  838. break;
  839. case 6:
  840. out->uwSampleArea = IgnoreC;
  841. break;
  842. case 2:
  843. out->uwSampleArea = IgnoreA;
  844. break;
  845. default:
  846. out->uwSampleArea = IgnoreNone;
  847. break;
  848. }
  849. out->uwRDSONTrig = swPWMPRD3 + coef->uwSampleSteadyCt;
  850. }
  851. else
  852. {
  853. switch (uwSector)
  854. {
  855. case 3:
  856. out->uwSampleArea = IgnoreAB;
  857. break;
  858. case 1:
  859. out->uwSampleArea = IgnoreAB;
  860. break;
  861. case 5:
  862. out->uwSampleArea = IgnoreBC;
  863. break;
  864. case 4:
  865. out->uwSampleArea = IgnoreBC;
  866. break;
  867. case 6:
  868. out->uwSampleArea = IgnoreAC;
  869. break;
  870. case 2:
  871. out->uwSampleArea = IgnoreAC;
  872. break;
  873. default:
  874. out->uwSampleArea = IgnoreNone;
  875. break;
  876. }
  877. out->uwRDSONTrig = swPWMPRD2 + coef->uwSampleSteadyCt;
  878. }
  879. }
  880. }
  881. else
  882. {}
  883. // hw_uwPWMCmpr[0] = out->uwNewTIM1COMPR[0];
  884. // hw_uwPWMCmpr[1] = out->uwNewTIM1COMPR[1];
  885. // hw_uwPWMCmpr[2] = out->uwNewTIM1COMPR[2];
  886. // hw_uwPWMCmpr[3] = out->uwNewTIM1COMPR[3];
  887. // hw_uwPWMCmpr[4] = out->uwNewTIM1COMPR[4];
  888. // hw_uwPWMCmpr[5] = out->uwNewTIM1COMPR[5];
  889. }
  890. /************************************************************************
  891. Local Functions: N/A
  892. ************************************************************************/
  893. /************************************************************************
  894. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
  895. All rights reserved.
  896. ************************************************************************/
  897. #ifdef _PWM_C_
  898. #undef _PWM_C_
  899. #endif
  900. /************************************************************************
  901. End of this File (EOF)!
  902. Do not put anything after this part!
  903. ************************************************************************/