equ_fuxi.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: equ.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2013-03-25
  7. 功能说明: 装置信息管理维护
  8. 其它说明:
  9. 修改记录:
  10. */
  11. /*------------------------------- 头文件 --------------------------------------
  12. */
  13. #include "head.h"
  14. /*------------------------------- 宏定义 --------------------------------------
  15. */
  16. #define EQU_SLOT_CHECK_TIMEOUT 4 // 子板检查超时,以秒为单位,不能小于4s
  17. /*------------------------------ 类型结构 -------------------------------------
  18. */
  19. //子板信息帧结构
  20. struct board_info_frame
  21. {
  22. u8 type; // 子板类型
  23. u8 status :4; // 子板状态
  24. u8 errcode:4; // 子板错误代码
  25. u16 crc; // 子板CRC
  26. u32 version; // 子板版本
  27. };
  28. /*------------------------------ 全局变量 -------------------------------------
  29. */
  30. // 控制板类型
  31. u32 g_brd_type_kz;
  32. // 模拟量对应关系
  33. static const s8 g_ac_index[BOARD_TYPE_KZ_NUM][EQU_SLOT_AC_CHN] =
  34. {
  35. {0X01, 0X03, 0X05, 0X07, 0XFF, 0XFF, 0XFF, 0XFF, 0X00, 0X02, 0X04, 0X06, 0X0E, 0X0C, 0X0A, 0X08}, // 24款分布式 lch
  36. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X04,0X0A,0X0E,0X02,0X08,0X0C,0X00,0X06,0X0F}, // KC00
  37. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // KC08
  38. {0X0C,0X0E,0X01,0X03,0X00,0X02,0X04,0X06,0X08,0X0A,0X05,0X07,0X09,0X0B,0X0D,0X0F}, // KC10,10AC
  39. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X04,0X0A,0X0E,0X02,0X08,0X0C,0X00,0X06,0X0F}, // 一体式分布式DTU控制板
  40. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // 后拔插分布式DTU控制板 FB_V3_22_12
  41. {0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00}, // 18 老版本分布式主板类型,不起作用
  42. {0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00}, // 19 老版本分布式主板类型,不起作用
  43. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // 类型 20 FB_V4_24_12
  44. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x08,0x0A,0x0C,0x0E,0x06,0x04,0x02,0x00}, //类型 21 FB_V4.1_24_12
  45. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x08,0x0A,0x0C,0x0E,0x06,0x04,0x02,0x00}, //类型 22 FB_V3.1_22_12
  46. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, //类型 23 FB_V3D_1_22_12
  47. {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, //类型 24 V4_D_30_12
  48. };
  49. //遥信转换表
  50. s8 g_change_di_index[BOARD_TYPE_KZ_NUM][EQU_DB_YX_NUM] =
  51. {
  52. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//13
  53. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//14 FB_V3_22_8 21,20,19,22,23,24,25,26,27,28,29,30,31,32}
  54. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//15
  55. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,00,00,00,00,00,00,00,00,00,00,00,00,00},//16 FBV1_19_6
  56. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//17 FB_V3_22_12
  57. { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//18 null
  58. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//19 null
  59. { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//20 FB_V4_24_12
  60. { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//21 FB_V4.1_24_12
  61. { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,24,23,21,22,25,26,27,28,29,30,31,32},//22 FB_V3.1_22_12
  62. { 2, 4, 6, 8,10,12,14,15,16, 1, 3, 5, 7, 9,11,13,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//23 FB_V3D_122_12
  63. { 1, 3, 5, 7, 9,11,13,15,19,21,25,27,29, 2, 4, 6, 8,10,12,14,16,20,22,26,28,30,17,18,23,24,00,00},//24 V4_D_30_12
  64. };
  65. // 开出对应关系
  66. static const s8 g_do_index[BOARD_TYPE_KZ_NUM][DO_NUM] =
  67. {
  68. {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1},
  69. {DO_OUT8,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,-1}, //14
  70. {DO_OUT9,DO_OUT0,DO_OUT2,DO_OUT4,DO_OUT6,DO_OUT1,DO_OUT3,DO_OUT5,DO_OUT7,-1}, //15
  71. {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1}, // 18 老版本分布式主板类型,不起作用
  72. {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1}, // 19 老版本分布式主板类型,不起作用
  73. // {DO_PWM2,DO_PWM1,DO_OUT7,DO_OUT6,DO_OUT3,DO_OUT2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT5,-1}, //20 V4 类型20
  74. // {DO_PWM2,DO_PWM1,DO_OUT7,DO_OUT6,DO_OUT3,DO_OUT2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT5,-1}, //21 V4.1 类型20
  75. // {DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,DO_PWM1,-1}, //22 FB_V3.1_22_12
  76. // {DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,DO_PWM1,-1}, //23 FB_V3D1_22_12
  77. // {DO_OUT2,DO_OUT3,DO_PWM2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT7,DO_PWM1,-1},//24 V4_D_30_12
  78. };
  79. // 采样板索引和插槽的对应关系
  80. const int g_ac_index_to_slot[EQU_SLOT_AC_NUM] = {1};
  81. // 采样板起始槽位,每种机箱不一样。
  82. u32 g_ac_slot_begin;
  83. // 记录频率对应ui通道的索引值
  84. int g_ui_freq[CFG_FREQ_NUM];
  85. /*------------------------------ 函数声明 -------------------------------------
  86. */
  87. int equ_slot_config_di(int slot);
  88. int equ_slot_config_do(int slot);
  89. unsigned int chDi;
  90. unsigned int change_di_ch(unsigned int di)
  91. {
  92. register int i,rts=0;
  93. #if 0
  94. static int di_bak;
  95. if(di_bak!=di)
  96. {
  97. rt_printf_time("change_di_ch di=%x \r\n",di);
  98. di_bak=di;
  99. }
  100. #endif
  101. for(i=0;i<EQU_DB_YX_NUM;i++)
  102. {
  103. if(g_change_di_index[g_brd_type_kz][i]!=0 && g_change_di_index[g_brd_type_kz][i]<=EQU_DB_YX_NUM)
  104. {
  105. if(di>>(g_change_di_index[g_brd_type_kz][i]-1)&0x01)
  106. rts|= (1<<i);
  107. }
  108. }
  109. //rt_printf("%d %d 。。",rts,g_brd_type_kz);
  110. return rts;
  111. }
  112. /*------------------------------ 外部函数 -------------------------------------
  113. 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
  114. */
  115. int equ_config_di(void)
  116. {
  117. u32 i;
  118. struct equ_config_di *ecd;
  119. memset(&g_di_st,0,sizeof(g_di_st));
  120. // 用户配置的保持时间、拥有者、类型
  121. ecd = g_equ_config_di;
  122. for(i=0;i<g_equ_config->di_num;i++)
  123. {
  124. // 开入扫描在156us中断,通过以下算法,得出对应不同防抖延时的最佳动态转换系数,理论误差为156us左右
  125. //g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 1000 / 156;
  126. if(ecd->filter_time>=10000)
  127. {
  128. g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 3200 / 500;
  129. g_di_st[ecd->slot][ecd->index].tm_filter -= (g_di_st[ecd->slot][ecd->index].tm_filter/10000);
  130. }
  131. else
  132. {
  133. g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 3200 / 500;
  134. }
  135. //rt_printf("filter_time[%d]=%d\r\n",i,ecd->filter_time);
  136. g_di_st[ecd->slot][ecd->index].owner = ecd->owner;
  137. g_di_st[ecd->slot][ecd->index].type = ecd->type;
  138. ecd++;
  139. }
  140. return 0;
  141. }
  142. int equ_config_do(void)
  143. {
  144. u32 i,index;
  145. struct equ_config_do *ecd;
  146. memset(&g_do_st,0,sizeof(struct do_struct)*14);
  147. // 用户配置的保持时间
  148. ecd = g_equ_config_do;
  149. for(i=0;i<g_equ_config->do_num;i++)
  150. {
  151. if(ecd->slot == EQU_SLOT_KZ)
  152. {
  153. index = equ_get_do_channel(ecd->index);
  154. g_do_st[index].us_keep = (u32)ecd->time_pulse;
  155. g_do_st[index].us_keep *= 1000; //ms转换为us
  156. }
  157. ecd++;
  158. }
  159. return 0;
  160. }
  161. int equ_config_di_yd(void)
  162. {
  163. u32 i;
  164. struct equ_config_di *ecd;
  165. // 用户配置的保持时间、拥有者、类型
  166. ecd = g_equ_config_di;
  167. for(i=0;i<g_equ_config->di_num;i++)
  168. {
  169. // 开入扫描在156us中断,通过以下算法,得出对应不同防抖延时的最佳动态转换系数,理论误差为156us左右
  170. g_di_st[ecd->slot][ecd->index].tm_filter = (u32)tRunPara.wYXFD * 1000 / 156;
  171. ecd++;
  172. }
  173. return 0;
  174. }
  175. int equ_config_do_yd(void)
  176. {
  177. #if 0
  178. int i,index;
  179. struct equ_config_do *ecd;
  180. // 用户配置的保持时间
  181. ecd = g_equ_config_do;
  182. for(i=0;i<g_equ_config->do_num;i++)
  183. {
  184. u32 dotime=(u32)ecd->time_pulse;
  185. if(ecd->slot == EQU_SLOT_KZ)
  186. {
  187. // 如果定值参数中设置了分闸时间,覆盖
  188. if(ecd->owner&&((ecd->type == (SW_DO_FZ+1))||(ecd->type == (SW_DO_BHT+1))||(ecd->type == (SW_DO_YKT+1))))
  189. {
  190. if(pRunSet->bTT_RmtPara)
  191. {
  192. dotime=tRunPara.wFZMC;
  193. }
  194. }
  195. // 如果定值参数中设置了合闸时间,覆盖
  196. if(ecd->owner&&((ecd->type == (SW_DO_HZ+1))||(ecd->type == (SW_DO_BHH+1))||(ecd->type == (SW_DO_YKH+1))))
  197. {
  198. if(pRunSet->bTT_RmtPara)
  199. {
  200. dotime=tRunPara.wHZMC;
  201. }
  202. }
  203. index = equ_get_do_channel(ecd->index);
  204. g_do_st[index].us_keep = (u32)dotime;
  205. g_do_st[index].us_keep *= 1000; //ms转换为us
  206. }
  207. ecd++;
  208. }
  209. #endif
  210. return 0;
  211. }
  212. int equ_init_later(void)
  213. {
  214. int i,ui;
  215. struct equ_config_di *ecd;
  216. // 采样板起始槽位
  217. g_ac_slot_begin = EQU_SLOT_AC_BEGIN;
  218. // 检查频率硬件通道对应的UI。
  219. g_ui_freq[0] = UI_NUM;
  220. g_ui_freq[1] = UI_NUM;
  221. for(i=0; i< g_equ_config->ac_num; i++)
  222. {
  223. // 频率通道必须是配置了的公共电压类型
  224. if(g_equ_config_ac[i].type == 0 || g_equ_config_ac[i].owner != 0)
  225. {
  226. continue;
  227. }
  228. ui = g_equ_config_ac[i].type -1;
  229. if(ui >= PUB_AC_NUM)
  230. {
  231. continue;
  232. }
  233. // 确定频率对应电压通道
  234. if(ui < PUB_AC_NUM)
  235. {
  236. if(g_equ_config_ac[i].slot == 9 && g_equ_config_ac[i].index == 0)
  237. {
  238. g_ui_freq[0] = ui;
  239. }
  240. if(g_equ_config_ac[i].slot == 10 && g_equ_config_ac[i].index == 0)
  241. {
  242. g_ui_freq[1] = ui;
  243. }
  244. }
  245. }
  246. // 初始化开入g_di_st结构
  247. memset((unsigned char*)g_di_st,0,sizeof(g_di_st));
  248. ecd = g_equ_config_di;
  249. for(i=0;i<g_equ_config->di_num;i++)
  250. {
  251. g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time;
  252. g_di_st[ecd->slot][ecd->index].owner = ecd->owner;
  253. g_di_st[ecd->slot][ecd->index].type = ecd->type;
  254. ecd++;
  255. }
  256. return 0;
  257. }
  258. /******************************************************************************
  259. 函数名称: equ_board_info_update
  260. 函数版本: 01.01
  261. 创建作者: sunxi
  262. 创建日期: 2013-08-08
  263. 函数说明: 接收到子板的对时应答帧后,更新子板信息
  264. 参数说明:
  265. can_bus 从哪条can总线接收到的帧。
  266. frame 接收帧的buf指针
  267. 返回值:
  268. 0: 成功
  269. 其它: 失败
  270. 修改记录:
  271. */
  272. int equ_board_info_update(int can_bus,u8 * frame)
  273. {
  274. struct can_frame_head *cfh;
  275. struct board_info_frame *bif;
  276. struct board_info *bi;
  277. // 检查帧内容
  278. cfh = (struct can_frame_head *)frame;
  279. #ifdef CAN_SLAVE_BOARD
  280. if(cfh->src >= (EQU_SLOT_NUM_MAX+CAN_BOARD_NUM))
  281. #else
  282. if(cfh->src >= EQU_SLOT_NUM_MAX)
  283. #endif
  284. {
  285. return -1;
  286. }
  287. if(cfh->len != 8)
  288. {
  289. return -2;
  290. }
  291. // 比较子板类型
  292. bi = &g_board_info[cfh->src];
  293. bif = (struct board_info_frame *)(frame + sizeof(cfh));
  294. if(bif->type != bi->type)
  295. {
  296. // rt_printf("board type error(no=%d,bi_type=%d,gbi_type=%d)\r\n",cfh->src,bif->type,bi->type);
  297. // print_mem("frame",frame,16);
  298. return -3;
  299. }
  300. // 得到子板信息
  301. bi->status = bif->status;
  302. bi->errcode = bif->errcode;
  303. bi->crc = bif->crc;
  304. bi->version = bif->version;
  305. //rt_printf("%02d\t%02d\t%02d\t%04x\t%08x\t",bi->type,bi->status,bi->errcode,bi->crc,bi->version);
  306. // 得到子板时间
  307. clk_time_get(&bi->update_time);
  308. bi->us0 = ustimer_get_origin();
  309. bi->is_ok = 1;
  310. bi->can_bus = can_bus;
  311. return 0;
  312. }
  313. /******************************************************************************
  314. 函数名称: equ_ac_channel_is_ok
  315. 函数版本: 01.01
  316. 创建作者: sunxi
  317. 创建日期: 2013-08-08
  318. 函数说明: 得到插槽中子板的模拟量通道对应的ADC采样通道。
  319. 参数说明:
  320. slot 插槽索引号
  321. index 子板上模拟量通道索引号
  322. 返回值: ADC采样通道索引号
  323. 修改记录:
  324. */
  325. int equ_ac_channel_is_ok(u32 index)
  326. {
  327. // 检查参数
  328. if(index >= CFG_ADC_CHANNEL)
  329. {
  330. return 0;
  331. }
  332. // 板卡不能插拔,直接返回ok
  333. return 1;
  334. // return g_ac_slot_is_ok[index/EQU_SLOT_AC_CHN];
  335. }
  336. /******************************************************************************
  337. 函数名称: equ_get_ac_channel
  338. 函数版本: 01.01
  339. 创建作者: sunxi
  340. 创建日期: 2013-08-08
  341. 函数说明: 得到插槽中子板的模拟量通道对应的ADC采样通道。
  342. 参数说明:
  343. slot 插槽索引号
  344. index 子板上模拟量通道索引号
  345. 返回值: ADC采样通道索引号
  346. 修改记录:
  347. */
  348. int equ_get_ac_channel(u32 slot,u32 index)
  349. {
  350. // 检查参数
  351. #if (0) /* 不检查 插槽索引号 lch 2025年12月5日17:29:28 */
  352. if(slot != BOARD_TYPE_FUXI_AC)
  353. {
  354. return -1;
  355. }
  356. #endif
  357. if(index >= CFG_ADC_CHANNEL)
  358. {
  359. return -2;
  360. }
  361. return g_ac_index[g_brd_type_kz][index];
  362. }
  363. /******************************************************************************
  364. 函数名称: equ_get_ac_slot
  365. 函数版本: 01.01
  366. 创建作者: xxxxxx
  367. 创建日期: 2014-10-09
  368. 函数说明: 得到采样通道对应的板卡
  369. 参数说明:
  370. owner 归属公共、开关
  371. type 采样类型
  372. 返回值: ADC采样通道索引号
  373. 修改记录:
  374. */
  375. int equ_get_ac_slot(u32 owner, u32 type)
  376. {
  377. u32 no;
  378. if (owner)
  379. {
  380. no = g_sw[owner].ac_cfg_index[type];
  381. }
  382. else
  383. {
  384. no = g_sw_pub.ac_cfg_index[type];
  385. }
  386. return g_equ_config_ac[no].slot;
  387. }
  388. /******************************************************************************
  389. 函数名称: equ_ac_index_to_slot
  390. 函数版本: 01.01
  391. 创建作者: sunxi
  392. 创建日期: 2013-08-08
  393. 函数说明: 将采样板索引号(和ADC通道号对应)转换为插槽号。
  394. 参数说明:
  395. ac_index 采样板索引号
  396. 返回值: 插槽号
  397. 修改记录:
  398. */
  399. int equ_ac_index_to_slot(int ac_index)
  400. {
  401. if((u32)ac_index >= EQU_SLOT_AC_NUM)
  402. {
  403. return 0;
  404. }
  405. return g_ac_index_to_slot[ac_index];
  406. }
  407. /******************************************************************************
  408. 函数名称: equ_slot_config_do
  409. 函数版本: 01.01
  410. 创建作者: sunxi
  411. 创建日期: 2013-08-08
  412. 函数说明: 配置子板上的开出资源
  413. 参数说明:
  414. slot 插槽索引号
  415. 返回值: 插槽号
  416. 0: 成功
  417. 其它: 失败
  418. 修改记录:
  419. */
  420. int equ_get_do_channel(u32 index)
  421. {
  422. return g_do_index[g_brd_type_kz][index];
  423. }
  424. /******************************************************************************
  425. 函数名称: equ_slot_config_di
  426. 函数版本: 01.01
  427. 创建作者: xxxxxx
  428. 创建日期: 2014-04-08
  429. 函数说明: 配置子板上的开入资源
  430. 参数说明:
  431. slot 插槽索引号
  432. 返回值: 插槽号
  433. 0: 成功
  434. 其它: 失败
  435. 修改记录:
  436. */
  437. /*------------------------------ 内部函数 -------------------------------------
  438. 内部函数以下划线‘_’开头,不需要检查参数的合法性.
  439. */
  440. /*------------------------------ 测试函数 -------------------------------------
  441. 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
  442. 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
  443. */
  444. /*------------------------------ 文件结束 -------------------------------------
  445. */