• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_sei_drv.h"
9 
sei_tranceiver_config_init(SEI_Type * ptr,uint8_t idx,sei_tranceiver_config_t * config)10 hpm_stat_t sei_tranceiver_config_init(SEI_Type *ptr, uint8_t idx, sei_tranceiver_config_t *config)
11 {
12     uint32_t tmp;
13     uint32_t baudrate;
14     uint32_t baud_div;
15     uint32_t sync_point;
16     uint8_t data_len;
17     uint32_t ck0_point;
18     uint32_t ck1_point;
19     uint32_t txd_point;
20     uint32_t rxd_point;
21 
22     tmp = SEI_CTRL_XCVR_CTRL_TRISMP_SET(config->tri_sample)
23         | SEI_CTRL_XCVR_CTRL_MODE_SET(config->mode);
24     ptr->CTRL[idx].XCVR.CTRL = tmp;
25 
26     switch (config->mode) {
27     case sei_synchronous_master_mode:
28         tmp = SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEZ_SET(config->synchronous_master_config.data_idle_high_z)
29             | SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEV_SET(config->synchronous_master_config.data_idle_state)
30             | SEI_CTRL_XCVR_TYPE_CFG_CK_IDLEZ_SET(config->synchronous_master_config.clock_idle_high_z)
31             | SEI_CTRL_XCVR_TYPE_CFG_CK_IDLEV_SET(config->synchronous_master_config.clock_idle_state);
32         ptr->CTRL[idx].XCVR.TYPE_CFG = tmp;
33 
34         baud_div = (config->src_clk_freq + (config->synchronous_master_config.baudrate >> 1u)) / config->synchronous_master_config.baudrate;
35         sync_point = baud_div >> 1u;
36         tmp = SEI_CTRL_XCVR_BAUD_CFG_SYNC_POINT_SET(sync_point)
37             | SEI_CTRL_XCVR_BAUD_CFG_BAUD_DIV_SET(baud_div - 1u);
38         ptr->CTRL[idx].XCVR.BAUD_CFG = tmp;
39 
40         ck0_point = baud_div >> 2u;
41         ck1_point = ck0_point * 3u;
42         tmp = SEI_CTRL_XCVR_CLK_CFG_CK0_POINT_SET(ck0_point)
43             | SEI_CTRL_XCVR_CLK_CFG_CK1_POINT_SET(ck1_point);
44         ptr->CTRL[idx].XCVR.CLK_CFG = tmp;
45         break;
46 
47     case sei_synchronous_slave_mode:
48         tmp = SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEZ_SET(config->synchronous_slave_config.data_idle_high_z)
49             | SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEV_SET(config->synchronous_slave_config.data_idle_state)
50             | SEI_CTRL_XCVR_TYPE_CFG_CK_IDLEZ_SET(config->synchronous_slave_config.clock_idle_high_z)
51             | SEI_CTRL_XCVR_TYPE_CFG_CK_IDLEV_SET(config->synchronous_slave_config.clock_idle_state);
52         ptr->CTRL[idx].XCVR.TYPE_CFG = tmp;
53 
54         baud_div = (config->src_clk_freq + (config->synchronous_slave_config.max_baudrate >> 1u)) / config->synchronous_slave_config.max_baudrate;
55         sync_point = (baud_div * 3u) >> 3u;
56         tmp = SEI_CTRL_XCVR_BAUD_CFG_SYNC_POINT_SET(sync_point)
57             | SEI_CTRL_XCVR_BAUD_CFG_BAUD_DIV_SET(baud_div - 1u);
58         ptr->CTRL[idx].XCVR.BAUD_CFG = tmp;
59 
60         ck0_point = config->synchronous_slave_config.ck0_timeout_us * (config->src_clk_freq / 1000000u);
61         if (ck0_point > 0x7FFFu) {
62             ck0_point = 0x7FFFu;
63         }
64         ck1_point = config->synchronous_slave_config.ck1_timeout_us * (config->src_clk_freq / 1000000u);
65         if (ck1_point > 0x7FFFu) {
66             ck1_point = 0x7FFFu;
67         }
68         ck1_point += 0x8000u;
69         tmp = SEI_CTRL_XCVR_CLK_CFG_CK0_POINT_SET(ck0_point)
70             | SEI_CTRL_XCVR_CLK_CFG_CK1_POINT_SET(ck1_point);
71         ptr->CTRL[idx].XCVR.CLK_CFG = tmp;
72     break;
73 
74     case sei_asynchronous_mode:
75     default:
76         data_len = config->asynchronous_config.data_len;
77         if (data_len > 0u) {
78             data_len--;
79         }
80         tmp = SEI_CTRL_XCVR_TYPE_CFG_WAIT_LEN_SET(config->asynchronous_config.wait_len)
81             | SEI_CTRL_XCVR_TYPE_CFG_DATA_LEN_SET(data_len)
82             | SEI_CTRL_XCVR_TYPE_CFG_PAR_POL_SET(config->asynchronous_config.parity)
83             | SEI_CTRL_XCVR_TYPE_CFG_PAR_EN_SET(config->asynchronous_config.parity_enable)
84             | SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEZ_SET(config->asynchronous_config.data_idle_high_z)
85             | SEI_CTRL_XCVR_TYPE_CFG_DA_IDLEV_SET(config->asynchronous_config.data_idle_state);
86         ptr->CTRL[idx].XCVR.TYPE_CFG = tmp;
87 
88         baudrate = (config->asynchronous_config.baudrate / 100) * 102;
89         baud_div = (config->src_clk_freq + (baudrate >> 1u)) / baudrate;
90         sync_point = (baud_div + 2u);
91         tmp = SEI_CTRL_XCVR_BAUD_CFG_SYNC_POINT_SET(sync_point)
92             | SEI_CTRL_XCVR_BAUD_CFG_BAUD_DIV_SET(baud_div - 1u);
93         ptr->CTRL[idx].XCVR.BAUD_CFG = tmp;
94 
95         txd_point = 0;
96         rxd_point = baud_div >> 1u;
97         tmp = SEI_CTRL_XCVR_DATA_CFG_TXD_POINT_SET(txd_point)
98             | SEI_CTRL_XCVR_DATA_CFG_RXD_POINT_SET(rxd_point);
99         ptr->CTRL[idx].XCVR.DATA_CFG = tmp;
100         break;
101     }
102 
103     return status_success;
104 }
105 
sei_cmd_data_format_config_init(SEI_Type * ptr,bool cmd_data_select,uint8_t idx,sei_data_format_config_t * config)106 hpm_stat_t sei_cmd_data_format_config_init(SEI_Type *ptr, bool cmd_data_select, uint8_t idx, sei_data_format_config_t *config)
107 {
108     uint32_t tmp;
109     uint8_t word_len;
110     uint8_t crc_len;
111 
112     word_len = config->word_len;
113     if (word_len > 0u) {
114         word_len--;
115     }
116     crc_len = config->crc_len;
117     if (crc_len > 0u) {
118         crc_len--;
119     }
120     tmp = SEI_DAT_MODE_MODE_SET(config->mode)
121         | SEI_DAT_MODE_SIGNED_SET(config->signed_flag)
122         | SEI_DAT_MODE_BORDER_SET(config->bit_order)
123         | SEI_DAT_MODE_WORDER_SET(config->word_order)
124         | SEI_DAT_MODE_CRC_INV_SET(config->crc_invert)
125         | SEI_DAT_MODE_CRC_SHIFT_SET(config->crc_shift_mode)
126         | SEI_DAT_MODE_WLEN_SET(word_len)
127         | SEI_DAT_MODE_CRC_LEN_SET(crc_len);
128     if (cmd_data_select) {
129         ptr->CTRL[idx].CMD.MODE = tmp;
130     } else {
131         ptr->DAT[idx].MODE = tmp;
132     }
133 
134     tmp = SEI_DAT_IDX_LAST_BIT_SET(config->last_bit)
135         | SEI_DAT_IDX_FIRST_BIT_SET(config->first_bit)
136         | SEI_DAT_IDX_MAX_BIT_SET(config->max_bit)
137         | SEI_DAT_IDX_MIN_BIT_SET(config->min_bit);
138     if (cmd_data_select) {
139         ptr->CTRL[idx].CMD.IDX = tmp;
140     } else {
141         ptr->DAT[idx].IDX = tmp;
142     }
143 
144     tmp = SEI_DAT_GOLD_GOLD_VALUE_SET(config->gold_value);
145     if (cmd_data_select) {
146         ptr->CTRL[idx].CMD.GOLD = tmp;
147     } else {
148         ptr->DAT[idx].GOLD = tmp;
149     }
150 
151     tmp = SEI_DAT_CRCINIT_CRC_INIT_SET(config->crc_init_value);
152     if (cmd_data_select) {
153         ptr->CTRL[idx].CMD.CRCINIT = tmp;
154     } else {
155         ptr->DAT[idx].CRCINIT = tmp;
156     }
157 
158     tmp = SEI_DAT_CRCPOLY_CRC_POLY_SET(config->crc_poly);
159     if (cmd_data_select) {
160         ptr->CTRL[idx].CMD.CRCPOLY = tmp;
161     } else {
162         ptr->DAT[idx].CRCPOLY = tmp;
163     }
164 
165     if (cmd_data_select) {
166         ptr->CTRL[idx].CMD.MODE |= SEI_CTRL_CMD_MODE_REWIND_MASK;
167     } else {
168         ptr->DAT[idx].MODE |= SEI_DAT_MODE_REWIND_MASK;
169     }
170 
171     return status_success;
172 }
173 
sei_cmd_table_config_init(SEI_Type * ptr,uint8_t idx,uint8_t table_idx,sei_command_table_config_t * config)174 hpm_stat_t sei_cmd_table_config_init(SEI_Type *ptr, uint8_t idx, uint8_t table_idx, sei_command_table_config_t *config)
175 {
176     uint32_t tmp;
177 
178     tmp = SEI_CTRL_CMD_TABLE_MIN_CMD_MIN_SET(config->cmd_min_value);
179     ptr->CTRL[idx].CMD_TABLE[table_idx].MIN = tmp;
180 
181     tmp = SEI_CTRL_CMD_TABLE_MAX_CMD_MAX_SET(config->cmd_max_value);
182     ptr->CTRL[idx].CMD_TABLE[table_idx].MAX = tmp;
183 
184     tmp = SEI_CTRL_CMD_TABLE_MSK_CMD_MASK_SET(config->cmd_mask_value);
185     ptr->CTRL[idx].CMD_TABLE[table_idx].MSK = tmp;
186 
187     tmp = SEI_CTRL_CMD_TABLE_PTA_PTR3_SET(config->instr_idx[3])
188         | SEI_CTRL_CMD_TABLE_PTA_PTR2_SET(config->instr_idx[2])
189         | SEI_CTRL_CMD_TABLE_PTA_PTR1_SET(config->instr_idx[1])
190         | SEI_CTRL_CMD_TABLE_PTA_PTR0_SET(config->instr_idx[0]);
191     ptr->CTRL[idx].CMD_TABLE[table_idx].PTA = tmp;
192 
193     tmp = SEI_CTRL_CMD_TABLE_PTB_PTR7_SET(config->instr_idx[7])
194         | SEI_CTRL_CMD_TABLE_PTB_PTR6_SET(config->instr_idx[6])
195         | SEI_CTRL_CMD_TABLE_PTB_PTR5_SET(config->instr_idx[5])
196         | SEI_CTRL_CMD_TABLE_PTB_PTR4_SET(config->instr_idx[4]);
197     ptr->CTRL[idx].CMD_TABLE[table_idx].PTB = tmp;
198 
199     tmp = SEI_CTRL_CMD_TABLE_PTC_PTR11_SET(config->instr_idx[11])
200         | SEI_CTRL_CMD_TABLE_PTC_PTR10_SET(config->instr_idx[10])
201         | SEI_CTRL_CMD_TABLE_PTC_PTR9_SET(config->instr_idx[9])
202         | SEI_CTRL_CMD_TABLE_PTC_PTR8_SET(config->instr_idx[8]);
203     ptr->CTRL[idx].CMD_TABLE[table_idx].PTC = tmp;
204 
205     tmp = SEI_CTRL_CMD_TABLE_PTD_PTR15_SET(config->instr_idx[15])
206         | SEI_CTRL_CMD_TABLE_PTD_PTR14_SET(config->instr_idx[14])
207         | SEI_CTRL_CMD_TABLE_PTD_PTR13_SET(config->instr_idx[13])
208         | SEI_CTRL_CMD_TABLE_PTD_PTR12_SET(config->instr_idx[12]);
209     ptr->CTRL[idx].CMD_TABLE[table_idx].PTD = tmp;
210 
211     return status_success;
212 }
213 
sei_state_transition_config_init(SEI_Type * ptr,uint8_t idx,uint8_t latch_idx,uint8_t state,sei_state_transition_config_t * config)214 hpm_stat_t sei_state_transition_config_init(SEI_Type *ptr, uint8_t idx, uint8_t latch_idx, uint8_t state, sei_state_transition_config_t *config)
215 {
216     uint32_t tmp = 0x08u;
217 
218     tmp |= SEI_CTRL_LATCH_TRAN_POINTER_SET(config->instr_ptr_value)
219         | SEI_CTRL_LATCH_TRAN_CFG_TM_SET(config->timeout_cfg)
220         | SEI_CTRL_LATCH_TRAN_CFG_TXD_SET(config->txd_cfg)
221         | SEI_CTRL_LATCH_TRAN_CFG_CLK_SET(config->clk_cfg)
222         | SEI_CTRL_LATCH_TRAN_CFG_PTR_SET(config->instr_ptr_cfg)
223         | SEI_CTRL_LATCH_TRAN_OV_TM_SET(config->disable_timeout_check)
224         | SEI_CTRL_LATCH_TRAN_OV_TXD_SET(config->disable_txd_check)
225         | SEI_CTRL_LATCH_TRAN_OV_CLK_SET(config->disable_clk_check)
226         | SEI_CTRL_LATCH_TRAN_OV_PTR_SET(config->disable_instr_ptr_check);
227     ptr->CTRL[idx].LATCH[latch_idx].TRAN[state] = tmp;
228 
229     return status_success;
230 }
231 
sei_state_transition_latch_config_init(SEI_Type * ptr,uint8_t idx,uint8_t latch_idx,sei_state_transition_latch_config_t * config)232 hpm_stat_t sei_state_transition_latch_config_init(SEI_Type *ptr, uint8_t idx, uint8_t latch_idx, sei_state_transition_latch_config_t *config)
233 {
234     uint32_t tmp;
235 
236     tmp = SEI_CTRL_LATCH_CFG_DELAY_SET(config->delay)
237         | SEI_CTRL_LATCH_CFG_SELECT_SET(config->output_select)
238         | SEI_CTRL_LATCH_CFG_EN_SET(config->enable);
239     ptr->CTRL[idx].LATCH[latch_idx].CFG = tmp;
240 
241     return status_success;
242 }
243 
sei_sample_config_init(SEI_Type * ptr,uint8_t idx,sei_sample_config_t * config)244 hpm_stat_t sei_sample_config_init(SEI_Type *ptr, uint8_t idx, sei_sample_config_t *config)
245 {
246     uint32_t tmp;
247 
248     tmp = SEI_CTRL_POS_SMP_CFG_ONCE_SET(config->sample_once)
249         | SEI_CTRL_POS_SMP_CFG_LAT_SEL_SET(config->latch_select)
250         | SEI_CTRL_POS_SMP_CFG_WINDOW_SET(config->sample_window);
251     ptr->CTRL[idx].POS.SMP_CFG = tmp;
252 
253     ptr->CTRL[idx].POS.SMP_DAT = SEI_CTRL_POS_SMP_DAT_DAT_SEL_SET(config->data_register_select);
254 
255     tmp = SEI_CTRL_POS_SMP_EN_ACC_EN_SET(config->acc_data_use_rx)
256         | SEI_CTRL_POS_SMP_EN_ACC_SEL_SET(config->acc_data_idx)
257         | SEI_CTRL_POS_SMP_EN_SPD_EN_SET(config->spd_data_use_rx)
258         | SEI_CTRL_POS_SMP_EN_SPD_SEL_SET(config->spd_data_idx)
259         | SEI_CTRL_POS_SMP_EN_REV_EN_SET(config->rev_data_use_rx)
260         | SEI_CTRL_POS_SMP_EN_REV_SEL_SET(config->rev_data_idx)
261         | SEI_CTRL_POS_SMP_EN_POS_EN_SET(config->pos_data_use_rx)
262         | SEI_CTRL_POS_SMP_EN_POS_SEL_SET(config->pos_data_idx);
263     ptr->CTRL[idx].POS.SMP_EN = tmp;
264 
265     return status_success;
266 }
267 
sei_update_config_init(SEI_Type * ptr,uint8_t idx,sei_update_config_t * config)268 hpm_stat_t sei_update_config_init(SEI_Type *ptr, uint8_t idx, sei_update_config_t *config)
269 {
270     uint32_t tmp;
271 
272     tmp = SEI_CTRL_POS_UPD_CFG_TIME_OVRD_SET(config->time_use_override)
273         | SEI_CTRL_POS_UPD_CFG_ONERR_SET(config->update_on_err)
274         | SEI_CTRL_POS_UPD_CFG_LAT_SEL_SET(config->latch_select);
275     ptr->CTRL[idx].POS.UPD_CFG = tmp;
276 
277     ptr->CTRL[idx].POS.UPD_DAT = SEI_CTRL_POS_UPD_DAT_DAT_SEL_SET(config->data_register_select);
278 
279     tmp = SEI_CTRL_POS_UPD_EN_ACC_EN_SET(config->acc_data_use_rx)
280         | SEI_CTRL_POS_UPD_EN_ACC_SEL_SET(config->acc_data_idx)
281         | SEI_CTRL_POS_UPD_EN_SPD_EN_SET(config->spd_data_use_rx)
282         | SEI_CTRL_POS_UPD_EN_SPD_SEL_SET(config->spd_data_idx)
283         | SEI_CTRL_POS_UPD_EN_REV_EN_SET(config->rev_data_use_rx)
284         | SEI_CTRL_POS_UPD_EN_REV_SEL_SET(config->rev_data_idx)
285         | SEI_CTRL_POS_UPD_EN_POS_EN_SET(config->pos_data_use_rx)
286         | SEI_CTRL_POS_UPD_EN_POS_SEL_SET(config->pos_data_idx);
287     ptr->CTRL[idx].POS.UPD_EN = tmp;
288 
289     return status_success;
290 }
291 
sei_trigger_input_config_init(SEI_Type * ptr,uint8_t idx,sei_trigger_input_config_t * config)292 hpm_stat_t sei_trigger_input_config_init(SEI_Type *ptr, uint8_t idx, sei_trigger_input_config_t *config)
293 {
294     uint32_t tmp;
295     uint32_t period;
296 
297     tmp = SEI_CTRL_TRG_PRD_CFG_ARMING_SET(config->trig_period_arming_mode)
298         | SEI_CTRL_TRG_PRD_CFG_SYNC_SET(config->trig_period_sync_enable);
299     ptr->CTRL[idx].TRG.PRD_CFG = tmp;
300 
301     period = config->trig_period_time;
302     if (period > 0) {
303         period--;
304     }
305     ptr->CTRL[idx].TRG.PRD = SEI_CTRL_TRG_PRD_PERIOD_SET(period);
306 
307     tmp = SEI_CTRL_TRG_IN_CFG_PRD_EN_SET(config->trig_period_enable)
308         | SEI_CTRL_TRG_IN_CFG_SYNC_SEL_SET(config->trig_period_sync_select)
309         | SEI_CTRL_TRG_IN_CFG_IN1_EN_SET(config->trig_in1_enable)
310         | SEI_CTRL_TRG_IN_CFG_IN1_SEL_SET(config->trig_in1_select)
311         | SEI_CTRL_TRG_IN_CFG_IN0_EN_SET(config->trig_in0_enable)
312         | SEI_CTRL_TRG_IN_CFG_IN0_SEL_SET(config->trig_in0_select);
313     ptr->CTRL[idx].TRG.IN_CFG = tmp;
314 
315     return status_success;
316 }
317 
sei_trigger_output_config_init(SEI_Type * ptr,uint8_t idx,sei_trigger_output_config_t * config)318 hpm_stat_t sei_trigger_output_config_init(SEI_Type *ptr, uint8_t idx, sei_trigger_output_config_t *config)
319 {
320     uint32_t tmp;
321 
322     tmp = ptr->CTRL[idx].TRG.OUT_CFG;
323     if (config->src_latch_select == SEI_LATCH_0) {
324         tmp &= ~(SEI_CTRL_TRG_OUT_CFG_OUT0_SEL_MASK | SEI_CTRL_TRG_OUT_CFG_OUT0_EN_MASK);
325         tmp |= SEI_CTRL_TRG_OUT_CFG_OUT0_EN_SET(config->trig_out_enable) | SEI_CTRL_TRG_OUT_CFG_OUT0_SEL_SET(config->trig_out_select);
326     } else if (config->src_latch_select == SEI_LATCH_1) {
327         tmp &= ~(SEI_CTRL_TRG_OUT_CFG_OUT1_SEL_MASK | SEI_CTRL_TRG_OUT_CFG_OUT1_EN_MASK);
328         tmp |= SEI_CTRL_TRG_OUT_CFG_OUT1_EN_SET(config->trig_out_enable) | SEI_CTRL_TRG_OUT_CFG_OUT1_SEL_SET(config->trig_out_select);
329     } else if (config->src_latch_select == SEI_LATCH_2) {
330         tmp &= ~(SEI_CTRL_TRG_OUT_CFG_OUT2_SEL_MASK | SEI_CTRL_TRG_OUT_CFG_OUT2_EN_MASK);
331         tmp |= SEI_CTRL_TRG_OUT_CFG_OUT2_EN_SET(config->trig_out_enable) | SEI_CTRL_TRG_OUT_CFG_OUT2_SEL_SET(config->trig_out_select);
332     } else if (config->src_latch_select == SEI_LATCH_3) {
333         tmp &= ~(SEI_CTRL_TRG_OUT_CFG_OUT3_SEL_MASK | SEI_CTRL_TRG_OUT_CFG_OUT3_EN_MASK);
334         tmp |= SEI_CTRL_TRG_OUT_CFG_OUT3_EN_SET(config->trig_out_enable) | SEI_CTRL_TRG_OUT_CFG_OUT3_SEL_SET(config->trig_out_select);
335     } else {
336         return status_invalid_argument;
337     }
338     ptr->CTRL[idx].TRG.OUT_CFG = tmp;
339 
340     return status_success;
341 }
342 
sei_engine_config_init(SEI_Type * ptr,uint8_t idx,sei_engine_config_t * config)343 hpm_stat_t sei_engine_config_init(SEI_Type *ptr, uint8_t idx, sei_engine_config_t *config)
344 {
345     uint32_t tmp;
346 
347     tmp = SEI_CTRL_ENGINE_PTR_CFG_DAT_CDM_SET(config->data_cdm_idx)
348         | SEI_CTRL_ENGINE_PTR_CFG_DAT_BASE_SET(config->data_base_idx)
349         | SEI_CTRL_ENGINE_PTR_CFG_POINTER_WDOG_SET(config->wdg_instr_idx)
350         | SEI_CTRL_ENGINE_PTR_CFG_POINTER_INIT_SET(config->init_instr_idx);
351     ptr->CTRL[idx].ENGINE.PTR_CFG = tmp;
352 
353     ptr->CTRL[idx].ENGINE.WDG_CFG = SEI_CTRL_ENGINE_WDG_CFG_WDOG_TIME_SET(config->wdg_time);
354 
355     tmp = SEI_CTRL_ENGINE_CTRL_WATCH_SET(config->wdg_enable)
356         | SEI_CTRL_ENGINE_CTRL_EXCEPT_SET(config->wdg_action)
357         | SEI_CTRL_ENGINE_CTRL_ARMING_SET(config->arming_mode);
358     ptr->CTRL[idx].ENGINE.CTRL = tmp;
359 
360     return status_success;
361 }
362 
sei_set_instr(SEI_Type * ptr,uint8_t idx,uint8_t op,uint8_t ck,uint8_t crc,uint8_t data,uint8_t opr)363 void sei_set_instr(SEI_Type *ptr, uint8_t idx, uint8_t op, uint8_t ck, uint8_t crc, uint8_t data, uint8_t opr)
364 {
365     uint32_t tmp;
366 
367     if ((op != SEI_INSTR_OP_HALT) && (op != SEI_INSTR_OP_JUMP) && (opr > 0)) {
368         opr--;
369     }
370     if (opr > 0x1F) {
371         opr = 0x1F;
372     }
373     tmp = SEI_INSTR_OP_SET(op)
374         | SEI_INSTR_CK_SET(ck)
375         | SEI_INSTR_CRC_SET(crc)
376         | SEI_INSTR_DAT_SET(data)
377         | SEI_INSTR_OPR_SET(opr);
378 
379     ptr->INSTR[idx] = tmp;
380 }
381