|
10 | 10 | /* Hardware requirement, to get n shifts SHIFTCNTB register has to be set to n-1*/ |
11 | 11 | #define SHIFTCNTB_VALUE(shift_count) (shift_count - 1) |
12 | 12 |
|
| 13 | +#define SPI_INPUT_PIN_NUM 2 |
| 14 | +#define CNT1_INIT_VALUE 1 |
| 15 | + |
| 16 | +#define INPUT_SHIFT_COUNT (BITS_IN_WORD - BITS_IN_BYTE) |
| 17 | + |
| 18 | +#define CNT1_TOP_CALCULATE(cnt0_top) (2 * ((cnt0_top) + 1) - 1) |
| 19 | + |
13 | 20 | /** @brief Shift control configuration. */ |
14 | 21 | typedef struct { |
15 | 22 | uint8_t shift_count; |
@@ -189,3 +196,121 @@ void hrt_write(hrt_xfer_t *hrt_xfer_params) |
189 | 196 | } |
190 | 197 | } |
191 | 198 | } |
| 199 | + |
| 200 | +static void hrt_tx_rx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, uint16_t cnt0_val, uint16_t cnt1_val, bool *counter_running) |
| 201 | +{ |
| 202 | + if(xfer_data->word_count == 0) |
| 203 | + { |
| 204 | + return; |
| 205 | + } |
| 206 | + |
| 207 | + nrf_vpr_csr_vio_shift_ctrl_t shift_ctrl = { |
| 208 | + .shift_count = BITS_IN_BYTE - 1, |
| 209 | + .out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, |
| 210 | + .frame_width = frame_width, |
| 211 | + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_SHIFT, |
| 212 | + }; |
| 213 | + |
| 214 | + for (uint32_t i = 0; i < xfer_data->word_count; i++) { |
| 215 | + |
| 216 | + switch (xfer_data->word_count - i) { |
| 217 | + case 1: /* Last transfer */ |
| 218 | + shift_ctrl.shift_count = xfer_data->last_word_clocks - 1; |
| 219 | + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); |
| 220 | + |
| 221 | + xfer_data->vio_out_set(xfer_data->last_word); |
| 222 | + break; |
| 223 | + case 2: /* Last but one transfer.*/ |
| 224 | + shift_ctrl.shift_count = |
| 225 | + xfer_data->penultimate_word_clocks - 1; |
| 226 | + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); |
| 227 | + xfer_data->vio_out_set(((uint32_t *)xfer_data->data)[i]); |
| 228 | + break; |
| 229 | + default: |
| 230 | + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); |
| 231 | + xfer_data->vio_out_set(((uint32_t *)xfer_data->data)[i]); |
| 232 | + } |
| 233 | + |
| 234 | + if ((i == 0) && (!*counter_running)) { |
| 235 | + /* Start both counters */ |
| 236 | + nrf_vpr_csr_vtim_combined_counter_set( |
| 237 | + (cnt0_val << VPRCSR_NORDIC_CNT_CNT0_Pos) + |
| 238 | + (cnt1_val << VPRCSR_NORDIC_CNT_CNT1_Pos)); |
| 239 | + *counter_running = true; |
| 240 | + } |
| 241 | + } |
| 242 | +} |
| 243 | + |
| 244 | +void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) |
| 245 | +{ |
| 246 | + uint16_t out; |
| 247 | + bool counter_running = false; |
| 248 | + nrf_vpr_csr_vio_shift_ctrl_t shift_ctrl = { |
| 249 | + .out_mode = NRF_VPR_CSR_VIO_SHIFT_NONE, |
| 250 | + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS, |
| 251 | + }; |
| 252 | + nrf_vpr_csr_vio_mode_out_t out_mode = { |
| 253 | + .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, |
| 254 | + .frame_width = 1, |
| 255 | + }; |
| 256 | + |
| 257 | + /* Enable CS */ |
| 258 | + out = nrf_vpr_csr_vio_out_get(); |
| 259 | + if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { |
| 260 | + WRITE_BIT(out, hrt_xfer_params->ce_vio, VPRCSR_NORDIC_OUT_LOW); |
| 261 | + } else { |
| 262 | + WRITE_BIT(out, hrt_xfer_params->ce_vio, VPRCSR_NORDIC_OUT_HIGH); |
| 263 | + } |
| 264 | + nrf_vpr_csr_vio_out_set(out); |
| 265 | + |
| 266 | + /* Configure clock and pins */ |
| 267 | + /* Set DQ1 as input */ |
| 268 | + WRITE_BIT(hrt_xfer_params->tx_direction_mask, SPI_INPUT_PIN_NUM, VPRCSR_NORDIC_DIR_INPUT); |
| 269 | + nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask); |
| 270 | + |
| 271 | + /* Initial configuration */ |
| 272 | + nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_SHIFT); |
| 273 | + nrf_vpr_csr_vio_mode_out_set(&out_mode); |
| 274 | + nrf_vpr_csr_vio_shift_cnt_out_set(hrt_xfer_params->xfer_data[HRT_FE_COMMAND].word_count * BITS_IN_BYTE); |
| 275 | + |
| 276 | + /* Counter settings */ |
| 277 | + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); |
| 278 | + nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_RELOAD); |
| 279 | + |
| 280 | + /* Set top counters value. Trigger data capture every two clock cycles */ |
| 281 | + nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); |
| 282 | + nrf_vpr_csr_vtim_simple_counter_top_set(1, CNT1_TOP_CALCULATE(hrt_xfer_params->counter_value)); |
| 283 | + |
| 284 | + /* Transfer command */ |
| 285 | + hrt_tx_rx(&hrt_xfer_params->xfer_data[HRT_FE_COMMAND], hrt_xfer_params->bus_widths.command, hrt_xfer_params->counter_value, |
| 286 | + CNT1_INIT_VALUE, &counter_running); |
| 287 | + |
| 288 | + for (uint8_t i = 0; i < hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count; i++) |
| 289 | + { |
| 290 | + hrt_xfer_params->xfer_data[HRT_FE_DATA].rx_data[i] = hrt_xfer_params->xfer_data[HRT_FE_DATA].vio_inb_get() >> INPUT_SHIFT_COUNT; |
| 291 | + } |
| 292 | + |
| 293 | + /* Final configuration */ |
| 294 | + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); |
| 295 | + nrf_vpr_csr_vio_out_buffered_reversed_word_set(0); |
| 296 | + |
| 297 | + /* Stop counters */ |
| 298 | + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP); |
| 299 | + nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_STOP); |
| 300 | + |
| 301 | + /* Disable CS */ |
| 302 | + if (!hrt_xfer_params->ce_hold) { |
| 303 | + out = nrf_vpr_csr_vio_out_get(); |
| 304 | + |
| 305 | + if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { |
| 306 | + WRITE_BIT(out, hrt_xfer_params->ce_vio, VPRCSR_NORDIC_OUT_HIGH); |
| 307 | + } else { |
| 308 | + WRITE_BIT(out, hrt_xfer_params->ce_vio, VPRCSR_NORDIC_OUT_LOW); |
| 309 | + } |
| 310 | + nrf_vpr_csr_vio_out_set(out); |
| 311 | + } |
| 312 | + |
| 313 | + /* Set DQ1 back as output. */ |
| 314 | + WRITE_BIT(hrt_xfer_params->tx_direction_mask, SPI_INPUT_PIN_NUM, VPRCSR_NORDIC_DIR_OUTPUT); |
| 315 | + nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask); |
| 316 | +} |
0 commit comments