Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 360 | f9daq | 1 | /** |
| 2 | * $Id: fpga_osc.c 881 2013-12-16 05:37:34Z rp_jmenart $ |
||
| 3 | * |
||
| 4 | * @brief Red Pitaya Oscilloscope FPGA controller. |
||
| 5 | * |
||
| 6 | * @Author Jure Menart <juremenart@gmail.com> |
||
| 7 | * |
||
| 8 | * (c) Red Pitaya http://www.redpitaya.com |
||
| 9 | * |
||
| 10 | * This part of code is written in C programming language. |
||
| 11 | * Please visit http://en.wikipedia.org/wiki/C_(programming_language) |
||
| 12 | * for more details on the language used herein. |
||
| 13 | */ |
||
| 14 | |||
| 15 | #include <stdio.h> |
||
| 16 | #include <stdlib.h> |
||
| 17 | #include <string.h> |
||
| 18 | #include <math.h> |
||
| 19 | #include <errno.h> |
||
| 20 | #include <sys/mman.h> |
||
| 21 | #include <sys/types.h> |
||
| 22 | #include <sys/stat.h> |
||
| 23 | #include <unistd.h> |
||
| 24 | #include <fcntl.h> |
||
| 25 | |||
| 26 | #include "fpga_osc.h" |
||
| 27 | |||
| 28 | /** |
||
| 29 | * GENERAL DESCRIPTION: |
||
| 30 | * |
||
| 31 | * This module initializes and provides for other SW modules the access to the |
||
| 32 | * FPGA OSC module. The oscilloscope memory space is divided to three parts: |
||
| 33 | * - registers (control and status) |
||
| 34 | * - input signal buffer (Channel A) |
||
| 35 | * - input signal buffer (Channel B) |
||
| 36 | * |
||
| 37 | * This module maps physical address of the oscilloscope core to the logical |
||
| 38 | * address, which can be used in the GNU/Linux user-space. To achieve this, |
||
| 39 | * OSC_FPGA_BASE_ADDR from CPU memory space is translated automatically to |
||
| 40 | * logical address with the function mmap(). After all the initialization is done, |
||
| 41 | * other modules can use this module to controll oscilloscope FPGA core. Before |
||
| 42 | * any functions or functionality from this module can be used it needs to be |
||
| 43 | * initialized with osc_fpga_init() function. When this module is no longer |
||
| 44 | * needed osc_fpga_exit() must be called. |
||
| 45 | * |
||
| 46 | * FPGA oscilloscope state machine in various modes. Basic principle is that |
||
| 47 | * SW sets the machine, 'arm' the writting machine (FPGA writes from ADC to |
||
| 48 | * input buffer memory) and then set the triggers. FPGA machine is continue |
||
| 49 | * writting to the buffers until the trigger is detected plus the amount set |
||
| 50 | * in trigger delay register. For more detauled description see the FPGA OSC |
||
| 51 | * registers description. |
||
| 52 | * |
||
| 53 | * Nice example how to use this module can be seen in worker.c module. |
||
| 54 | */ |
||
| 55 | |||
| 56 | /* internal structures */ |
||
| 57 | /** The FPGA register structure (defined in fpga_osc.h) */ |
||
| 58 | osc_fpga_reg_mem_t *g_osc_fpga_reg_mem = NULL; |
||
| 59 | /** The FPGA input signal buffer pointer for channel A */ |
||
| 60 | uint32_t *g_osc_fpga_cha_mem = NULL; |
||
| 61 | /** The FPGA input signal buffer pointer for channel B */ |
||
| 62 | uint32_t *g_osc_fpga_chb_mem = NULL; |
||
| 63 | |||
| 64 | /** The memory file descriptor used to mmap() the FPGA space */ |
||
| 65 | int g_osc_fpga_mem_fd = -1; |
||
| 66 | |||
| 67 | /* Constants */ |
||
| 68 | /** ADC number of bits */ |
||
| 69 | const int c_osc_fpga_adc_bits = 14; |
||
| 70 | /** @brief Max and min voltage on ADCs. |
||
| 71 | * Symetrical - Max Voltage = +14, Min voltage = -1 * c_osc_fpga_max_v |
||
| 72 | */ |
||
| 73 | const float c_osc_fpga_adc_max_v = +14; |
||
| 74 | /** Sampling frequency = 125Mspmpls (non-decimated) */ |
||
| 75 | const float c_osc_fpga_smpl_freq = 125e6; |
||
| 76 | /** Sampling period (non-decimated) - 8 [ns] */ |
||
| 77 | const float c_osc_fpga_smpl_period = (1. / 125e6); |
||
| 78 | |||
| 79 | /** |
||
| 80 | * @brief Internal function used to clean up memory. |
||
| 81 | * |
||
| 82 | * This function un-maps FPGA register and signal buffers, closes memory file |
||
| 83 | * descriptor and cleans all memory allocated by this module. |
||
| 84 | * |
||
| 85 | * @retval 0 Success |
||
| 86 | * @retval -1 Error happened during cleanup. |
||
| 87 | */ |
||
| 88 | int __osc_fpga_cleanup_mem(void) |
||
| 89 | { |
||
| 90 | /* If register structure is NULL we do not need to un-map and clean up */ |
||
| 91 | if(g_osc_fpga_reg_mem) { |
||
| 92 | if(munmap(g_osc_fpga_reg_mem, OSC_FPGA_BASE_SIZE) < 0) { |
||
| 93 | fprintf(stderr, "munmap() failed: %s\n", strerror(errno)); |
||
| 94 | return -1; |
||
| 95 | } |
||
| 96 | g_osc_fpga_reg_mem = NULL; |
||
| 97 | if(g_osc_fpga_cha_mem) |
||
| 98 | g_osc_fpga_cha_mem = NULL; |
||
| 99 | if(g_osc_fpga_chb_mem) |
||
| 100 | g_osc_fpga_chb_mem = NULL; |
||
| 101 | } |
||
| 102 | if(g_osc_fpga_mem_fd >= 0) { |
||
| 103 | close(g_osc_fpga_mem_fd); |
||
| 104 | g_osc_fpga_mem_fd = -1; |
||
| 105 | } |
||
| 106 | return 0; |
||
| 107 | } |
||
| 108 | |||
| 109 | /** |
||
| 110 | * @brief Maps FPGA memory space and prepares register and buffer variables. |
||
| 111 | * |
||
| 112 | * This function opens memory device (/dev/mem) and maps physical memory address |
||
| 113 | * OSC_FPGA_BASE_ADDR (of length OSC_FPGA_BASE_SIZE) to logical addresses. It |
||
| 114 | * initializes the pointers g_osc_fpga_reg_mem, g_osc_fpga_cha_mem and |
||
| 115 | * g_osc_fpga_chb_mem to point to FPGA OSC. |
||
| 116 | * If function failes FPGA variables must not be used. |
||
| 117 | * |
||
| 118 | * @retval 0 Success |
||
| 119 | * @retval -1 Failure, error is printed to standard error output. |
||
| 120 | */ |
||
| 121 | int osc_fpga_init(void) |
||
| 122 | { |
||
| 123 | /* Page variables used to calculate correct mapping addresses */ |
||
| 124 | void *page_ptr; |
||
| 125 | long page_addr, page_off, page_size = sysconf(_SC_PAGESIZE); |
||
| 126 | |||
| 127 | /* If module was already initialized once, clean all internals. */ |
||
| 128 | if(__osc_fpga_cleanup_mem() < 0) |
||
| 129 | return -1; |
||
| 130 | |||
| 131 | /* Open /dev/mem to access directly system memory */ |
||
| 132 | g_osc_fpga_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); |
||
| 133 | if(g_osc_fpga_mem_fd < 0) { |
||
| 134 | fprintf(stderr, "open(/dev/mem) failed: %s\n", strerror(errno)); |
||
| 135 | return -1; |
||
| 136 | } |
||
| 137 | |||
| 138 | /* Calculate correct page address and offset from OSC_FPGA_BASE_ADDR and |
||
| 139 | * OSC_FPGA_BASE_SIZE |
||
| 140 | */ |
||
| 141 | page_addr = OSC_FPGA_BASE_ADDR & (~(page_size-1)); |
||
| 142 | page_off = OSC_FPGA_BASE_ADDR - page_addr; |
||
| 143 | |||
| 144 | /* Map FPGA memory space to page_ptr. */ |
||
| 145 | page_ptr = mmap(NULL, OSC_FPGA_BASE_SIZE, PROT_READ | PROT_WRITE, |
||
| 146 | MAP_SHARED, g_osc_fpga_mem_fd, page_addr); |
||
| 147 | if((void *)page_ptr == MAP_FAILED) { |
||
| 148 | fprintf(stderr, "mmap() failed: %s\n", strerror(errno)); |
||
| 149 | __osc_fpga_cleanup_mem(); |
||
| 150 | return -1; |
||
| 151 | } |
||
| 152 | |||
| 153 | /* Set FPGA OSC module pointers to correct values. */ |
||
| 154 | g_osc_fpga_reg_mem = page_ptr + page_off; |
||
| 155 | g_osc_fpga_cha_mem = (uint32_t *)g_osc_fpga_reg_mem + |
||
| 156 | (OSC_FPGA_CHA_OFFSET / sizeof(uint32_t)); |
||
| 157 | g_osc_fpga_chb_mem = (uint32_t *)g_osc_fpga_reg_mem + |
||
| 158 | (OSC_FPGA_CHB_OFFSET / sizeof(uint32_t)); |
||
| 159 | |||
| 160 | return 0; |
||
| 161 | } |
||
| 162 | |||
| 163 | /** |
||
| 164 | * @brief Cleans up FPGA OSC module internals. |
||
| 165 | * |
||
| 166 | * This function closes the memory file descriptor, unmap the FPGA memory space |
||
| 167 | * and cleans also all other internal things from FPGA OSC module. |
||
| 168 | * @retval 0 Sucess |
||
| 169 | * @retval -1 Failure |
||
| 170 | */ |
||
| 171 | int osc_fpga_exit(void) |
||
| 172 | { |
||
| 173 | return __osc_fpga_cleanup_mem(); |
||
| 174 | } |
||
| 175 | |||
| 176 | // TODO: Move to a shared folder and share with scope & spectrum. |
||
| 177 | /** |
||
| 178 | * @brief Provides equalization & shaping filter coefficients. |
||
| 179 | * |
||
| 180 | * |
||
| 181 | * This function provides equalization & shaping filter coefficients, based on |
||
| 182 | * the type of use and gain settings. |
||
| 183 | * |
||
| 184 | * @param [in] equal Enable(1)/disable(0) equalization filter. |
||
| 185 | * @param [in] shaping Enable(1)/disable(0) shaping filter. |
||
| 186 | * @param [in] gain Gain setting (0 = LV, 1 = HV). |
||
| 187 | * @param [out] filt Filter coefficients. |
||
| 188 | */ |
||
| 189 | void get_equ_shape_filter(ecu_shape_filter_t *filt, uint32_t equal, |
||
| 190 | uint32_t shaping, uint32_t gain) |
||
| 191 | { |
||
| 192 | /* Equalization filter */ |
||
| 193 | if (equal) { |
||
| 194 | if (gain == 0) { |
||
| 195 | /* High gain = LV */ |
||
| 196 | filt->aa = 0x7D93; |
||
| 197 | filt->bb = 0x437C7; |
||
| 198 | } else { |
||
| 199 | /* Low gain = HV */ |
||
| 200 | filt->aa = 0x4C5F; |
||
| 201 | filt->bb = 0x2F38B; |
||
| 202 | } |
||
| 203 | } else { |
||
| 204 | filt->aa = 0; |
||
| 205 | filt->bb = 0; |
||
| 206 | } |
||
| 207 | |||
| 208 | /* Shaping filter */ |
||
| 209 | if (shaping) { |
||
| 210 | filt->pp = 0x2666; |
||
| 211 | filt->kk = 0xd9999a; |
||
| 212 | } else { |
||
| 213 | filt->pp = 0; |
||
| 214 | filt->kk = 0xffffff; |
||
| 215 | } |
||
| 216 | } |
||
| 217 | |||
| 218 | |||
| 219 | /** |
||
| 220 | * @brief Updates triggering parameters in FPGA registers. |
||
| 221 | * |
||
| 222 | * This function updates trigger related parameters in FPGA registers. |
||
| 223 | * |
||
| 224 | * @param [in] trig_imm Trigger immediately - if set to 1, FPGA state machine |
||
| 225 | * will trigger immediately and other trigger parameters |
||
| 226 | * will be ignored. |
||
| 227 | * @param [in] trig_source Trigger source, as defined in rp_main_params. |
||
| 228 | * @param [in] trig_edge Trigger edge, as defined in rp_main_params. |
||
| 229 | * @param [in] trig_delay Trigger delay in [s]. |
||
| 230 | * @param [in] trig_level Trigger level in [V]. |
||
| 231 | * @param [in] time_range Time range, as defined in rp_main_params. |
||
| 232 | * @param [in] equal Enable(1)/disable(0) equalization filter. |
||
| 233 | * @param [in] shaping Enable(1)/disable(0) shaping filter. |
||
| 234 | * @param [in] gain1 Gain setting for Channel1 (0 = LV, 1 = HV). |
||
| 235 | * @param [in] gain2 Gain setting for Channel2 (0 = LV, 1 = HV). |
||
| 236 | * |
||
| 237 | * |
||
| 238 | * @retval 0 Success |
||
| 239 | * @retval -1 Failure |
||
| 240 | * |
||
| 241 | * @see rp_main_params |
||
| 242 | */ |
||
| 243 | int osc_fpga_update_params(int trig_imm, int trig_source, int trig_edge, |
||
| 244 | float trig_delay, float trig_level, int time_range, |
||
| 245 | int equal, int shaping, int gain1, int gain2) |
||
| 246 | { |
||
| 247 | int fpga_trig_source = osc_fpga_cnv_trig_source(trig_imm, trig_source, |
||
| 248 | trig_edge); |
||
| 249 | int fpga_dec_factor = osc_fpga_cnv_time_range_to_dec(time_range); |
||
| 250 | int fpga_delay; |
||
| 251 | float after_trigger; /* how much after trigger FPGA should write */ |
||
| 252 | int fpga_trig_thr = osc_fpga_cnv_v_to_cnt(trig_level); |
||
| 253 | |||
| 254 | /* Equalization filter coefficients */ |
||
| 255 | ecu_shape_filter_t cha_filt; |
||
| 256 | ecu_shape_filter_t chb_filt; |
||
| 257 | get_equ_shape_filter(&cha_filt, equal, shaping, gain1); |
||
| 258 | get_equ_shape_filter(&chb_filt, equal, shaping, gain2); |
||
| 259 | |||
| 260 | if((fpga_trig_source < 0) || (fpga_dec_factor < 0)) { |
||
| 261 | fprintf(stderr, "osc_fpga_update_params() failed\n"); |
||
| 262 | return -1; |
||
| 263 | } |
||
| 264 | |||
| 265 | /* Pre-trigger - we need to limit after trigger acquisition so we can |
||
| 266 | * readout historic (pre-trigger) values */ |
||
| 267 | |||
| 268 | if (trig_imm) |
||
| 269 | after_trigger=OSC_FPGA_SIG_LEN* c_osc_fpga_smpl_period * fpga_dec_factor; |
||
| 270 | else |
||
| 271 | after_trigger = |
||
| 272 | ((OSC_FPGA_SIG_LEN-7) * c_osc_fpga_smpl_period * fpga_dec_factor) + |
||
| 273 | trig_delay; |
||
| 274 | |||
| 275 | if(after_trigger < 0) |
||
| 276 | after_trigger = 0; |
||
| 277 | |||
| 278 | fpga_delay = osc_fpga_cnv_time_to_smpls(after_trigger, fpga_dec_factor); |
||
| 279 | |||
| 280 | /* Trig source is written after ARM */ |
||
| 281 | /* g_osc_fpga_reg_mem->trig_source = fpga_trig_source;*/ |
||
| 282 | if(trig_source == 0) |
||
| 283 | g_osc_fpga_reg_mem->cha_thr = fpga_trig_thr; |
||
| 284 | else |
||
| 285 | g_osc_fpga_reg_mem->chb_thr = fpga_trig_thr; |
||
| 286 | |||
| 287 | g_osc_fpga_reg_mem->data_dec = fpga_dec_factor; |
||
| 288 | g_osc_fpga_reg_mem->trigger_delay = (uint32_t)fpga_delay; |
||
| 289 | |||
| 290 | /* Update equalization filter with desired coefficients. */ |
||
| 291 | g_osc_fpga_reg_mem->cha_filt_aa = cha_filt.aa; |
||
| 292 | g_osc_fpga_reg_mem->cha_filt_bb = cha_filt.bb; |
||
| 293 | g_osc_fpga_reg_mem->cha_filt_pp = cha_filt.pp; |
||
| 294 | g_osc_fpga_reg_mem->cha_filt_kk = cha_filt.kk; |
||
| 295 | |||
| 296 | g_osc_fpga_reg_mem->chb_filt_aa = chb_filt.aa; |
||
| 297 | g_osc_fpga_reg_mem->chb_filt_bb = chb_filt.bb; |
||
| 298 | g_osc_fpga_reg_mem->chb_filt_pp = chb_filt.pp; |
||
| 299 | g_osc_fpga_reg_mem->chb_filt_kk = chb_filt.kk; |
||
| 300 | |||
| 301 | return 0; |
||
| 302 | } |
||
| 303 | |||
| 304 | /** @brief OSC FPGA reset |
||
| 305 | * |
||
| 306 | * Triggers internal oscilloscope FPGA state machine reset. |
||
| 307 | * |
||
| 308 | * @retval 0 Always returns 0. |
||
| 309 | */ |
||
| 310 | int osc_fpga_reset(void) |
||
| 311 | { |
||
| 312 | g_osc_fpga_reg_mem->conf |= OSC_FPGA_CONF_RST_BIT; |
||
| 313 | return 0; |
||
| 314 | } |
||
| 315 | |||
| 316 | /** @brief OSC FPGA ARM |
||
| 317 | * |
||
| 318 | * ARM internal oscilloscope FPGA state machine to start writting input buffers. |
||
| 319 | |||
| 320 | * @retval 0 Always returns 0. |
||
| 321 | */ |
||
| 322 | int osc_fpga_arm_trigger(void) |
||
| 323 | { |
||
| 324 | g_osc_fpga_reg_mem->conf |= OSC_FPGA_CONF_ARM_BIT; |
||
| 325 | |||
| 326 | return 0; |
||
| 327 | } |
||
| 328 | |||
| 329 | /** @brief Sets the trigger source in OSC FPGA register. |
||
| 330 | * |
||
| 331 | * Sets the trigger source in oscilloscope FPGA register. |
||
| 332 | * |
||
| 333 | * @param [in] trig_source Trigger source, as defined in FPGA register |
||
| 334 | * description. |
||
| 335 | */ |
||
| 336 | int osc_fpga_set_trigger(uint32_t trig_source) |
||
| 337 | { |
||
| 338 | g_osc_fpga_reg_mem->trig_source = trig_source; |
||
| 339 | return 0; |
||
| 340 | } |
||
| 341 | |||
| 342 | /** @brief Sets the trigger delay in OSC FPGA register. |
||
| 343 | * |
||
| 344 | * Sets the trigger delay in oscilloscope FPGA register. |
||
| 345 | * |
||
| 346 | * @param [in] trig_delay Trigger delay, as defined in FPGA register |
||
| 347 | * description. |
||
| 348 | * |
||
| 349 | * @retval 0 Always returns 0. |
||
| 350 | */ |
||
| 351 | int osc_fpga_set_trigger_delay(uint32_t trig_delay) |
||
| 352 | { |
||
| 353 | g_osc_fpga_reg_mem->trigger_delay = trig_delay; |
||
| 354 | return 0; |
||
| 355 | } |
||
| 356 | |||
| 357 | /** @brief Checks if FPGA detected trigger. |
||
| 358 | * |
||
| 359 | * This function checks if trigger was detected by the FPGA. |
||
| 360 | * |
||
| 361 | * @retval 0 Trigger not detected. |
||
| 362 | * @retval 1 Trigger detected. |
||
| 363 | */ |
||
| 364 | int osc_fpga_triggered(void) |
||
| 365 | { |
||
| 366 | return ((g_osc_fpga_reg_mem->trig_source & OSC_FPGA_TRIG_SRC_MASK)==0); |
||
| 367 | } |
||
| 368 | |||
| 369 | /** @brief Returns memory pointers for both input signal buffers. |
||
| 370 | * |
||
| 371 | * This function returns pointers for input signal buffers for both channels. |
||
| 372 | * |
||
| 373 | * @param [out] cha_signal Output pointer for Channel A buffer |
||
| 374 | * @param [out] cha_signal Output pointer for Channel B buffer |
||
| 375 | * |
||
| 376 | * @retval 0 Always returns 0. |
||
| 377 | */ |
||
| 378 | int osc_fpga_get_sig_ptr(int **cha_signal, int **chb_signal) |
||
| 379 | { |
||
| 380 | *cha_signal = (int *)g_osc_fpga_cha_mem; |
||
| 381 | *chb_signal = (int *)g_osc_fpga_chb_mem; |
||
| 382 | return 0; |
||
| 383 | } |
||
| 384 | |||
| 385 | /** @brief Returns values for current and trigger write FPGA pointers. |
||
| 386 | * |
||
| 387 | * This functions returns values for current and trigger write pointers. They |
||
| 388 | * are an address of the input signal buffer and are the same for both channels. |
||
| 389 | * |
||
| 390 | * @param [out] wr_ptr_curr Current FPGA input buffer address. |
||
| 391 | * @param [out] wr_ptr_trig Trigger FPGA input buffer address. |
||
| 392 | * |
||
| 393 | * @retval 0 Always returns 0. |
||
| 394 | */ |
||
| 395 | int osc_fpga_get_wr_ptr(int *wr_ptr_curr, int *wr_ptr_trig) |
||
| 396 | { |
||
| 397 | if(wr_ptr_curr) |
||
| 398 | *wr_ptr_curr = g_osc_fpga_reg_mem->wr_ptr_cur; |
||
| 399 | if(wr_ptr_trig) |
||
| 400 | *wr_ptr_trig = g_osc_fpga_reg_mem->wr_ptr_trigger; |
||
| 401 | return 0; |
||
| 402 | } |
||
| 403 | |||
| 404 | /** @brief Convert trigger parameters to FPGA trigger source value. |
||
| 405 | * |
||
| 406 | * This function takes as an argument trigger parameters and converts it to |
||
| 407 | * trigger source value used by the FPGA trigger source reigster. |
||
| 408 | * |
||
| 409 | * @param [in] trig_imm Trigger immediately, if set to 1 other trigger parameters |
||
| 410 | * are ignored. |
||
| 411 | * @param [in] trig_source Trigger source as defined in rp_main_params |
||
| 412 | * @param [in] trig_edge Trigger edge as defined in rp_main_params |
||
| 413 | * |
||
| 414 | * @retval -1 Error |
||
| 415 | * @retval otherwise Trigger source FPGA value |
||
| 416 | */ |
||
| 417 | int osc_fpga_cnv_trig_source(int trig_imm, int trig_source, int trig_edge) |
||
| 418 | { |
||
| 419 | int fpga_trig_source = 0; |
||
| 420 | |||
| 421 | /* Trigger immediately */ |
||
| 422 | if(trig_imm) |
||
| 423 | return 1; |
||
| 424 | |||
| 425 | switch(trig_source) { |
||
| 426 | case 0: /* ChA*/ |
||
| 427 | if(trig_edge == 0) |
||
| 428 | fpga_trig_source = 2; |
||
| 429 | else |
||
| 430 | fpga_trig_source = 3; |
||
| 431 | break; |
||
| 432 | case 1: /* ChB*/ |
||
| 433 | if(trig_edge == 0) |
||
| 434 | fpga_trig_source = 4; |
||
| 435 | else |
||
| 436 | fpga_trig_source = 5; |
||
| 437 | break; |
||
| 438 | case 2: /* External */ |
||
| 439 | if(trig_edge == 0) |
||
| 440 | fpga_trig_source = 6; |
||
| 441 | else |
||
| 442 | fpga_trig_source = 7; |
||
| 443 | |||
| 444 | break; |
||
| 445 | default: |
||
| 446 | /* Error */ |
||
| 447 | return -1; |
||
| 448 | } |
||
| 449 | |||
| 450 | return fpga_trig_source; |
||
| 451 | } |
||
| 452 | |||
| 453 | /** @brief Converts time range to decimation value. |
||
| 454 | * |
||
| 455 | * This function converts time range value defined by rp_main_params to |
||
| 456 | * decimation factor value. |
||
| 457 | * |
||
| 458 | * @param [in] time_range Time range, integer between 0 and 5, as defined by |
||
| 459 | * rp_main_params. |
||
| 460 | * |
||
| 461 | * @retval -1 Error |
||
| 462 | * |
||
| 463 | * @retval otherwise Decimation factor. |
||
| 464 | */ |
||
| 465 | int osc_fpga_cnv_time_range_to_dec(int time_range) |
||
| 466 | { |
||
| 467 | /* Input: 0, 1, 2, 3, 4, 5 translates to: |
||
| 468 | * Output: 1x, 8x, 64x, 1kx, 8kx, 65kx */ |
||
| 469 | switch(time_range) { |
||
| 470 | case 0: |
||
| 471 | return 1; |
||
| 472 | break; |
||
| 473 | case 1: |
||
| 474 | return 8; |
||
| 475 | break; |
||
| 476 | case 2: |
||
| 477 | return 64; |
||
| 478 | break; |
||
| 479 | case 3: |
||
| 480 | return 1024; |
||
| 481 | break; |
||
| 482 | case 4: |
||
| 483 | return 8*1024; |
||
| 484 | break; |
||
| 485 | case 5: |
||
| 486 | return 64*1024; |
||
| 487 | break; |
||
| 488 | default: |
||
| 489 | return -1; |
||
| 490 | } |
||
| 491 | |||
| 492 | return -1; |
||
| 493 | } |
||
| 494 | |||
| 495 | /** @brief Converts time to number of samples. |
||
| 496 | * |
||
| 497 | * This function converts time in [s], based on current decimation factor to |
||
| 498 | * number of samples at ADC sampling frequency. |
||
| 499 | * |
||
| 500 | * @param [in] time Time in [s] |
||
| 501 | * @param [in] dec_factor Decimation factor |
||
| 502 | * |
||
| 503 | * @retval Number of ADC samples define dby input parameters. |
||
| 504 | */ |
||
| 505 | int osc_fpga_cnv_time_to_smpls(float time, int dec_factor) |
||
| 506 | { |
||
| 507 | /* Calculate sampling period (including decimation) */ |
||
| 508 | float smpl_p = (c_osc_fpga_smpl_period * dec_factor); |
||
| 509 | int fpga_smpls = (int)round(time / smpl_p); |
||
| 510 | |||
| 511 | return fpga_smpls; |
||
| 512 | } |
||
| 513 | |||
| 514 | /** @brief Converts voltage to ADC counts. |
||
| 515 | * |
||
| 516 | * This function converts voltage in [V] to ADC counts. |
||
| 517 | * |
||
| 518 | * @param [in] voltage Voltage in [V] |
||
| 519 | * |
||
| 520 | * @retval adc_cnts ADC counts |
||
| 521 | */ |
||
| 522 | int osc_fpga_cnv_v_to_cnt(float voltage) |
||
| 523 | { |
||
| 524 | int adc_cnts = 0; |
||
| 525 | |||
| 526 | if((voltage > c_osc_fpga_adc_max_v) || (voltage < -c_osc_fpga_adc_max_v)) |
||
| 527 | return -1; |
||
| 528 | |||
| 529 | adc_cnts = (int)round(voltage * (float)((int)(1<<c_osc_fpga_adc_bits)) / |
||
| 530 | (2*c_osc_fpga_adc_max_v)); |
||
| 531 | |||
| 532 | /* Clip highest value (+14 is calculated in int32_t to 0x2000, but we have |
||
| 533 | * only 14 bits |
||
| 534 | */ |
||
| 535 | if((voltage > 0) && (adc_cnts & (1<<(c_osc_fpga_adc_bits-1)))) |
||
| 536 | adc_cnts = (1<<(c_osc_fpga_adc_bits-1))-1; |
||
| 537 | else |
||
| 538 | adc_cnts = adc_cnts & ((1<<(c_osc_fpga_adc_bits))-1); |
||
| 539 | |||
| 540 | return adc_cnts; |
||
| 541 | } |
||
| 542 | |||
| 543 | /** @brief Converts ADC counts to voltage |
||
| 544 | * |
||
| 545 | * This function converts ADC counts to voltage (in [V]) |
||
| 546 | * |
||
| 547 | * @param [in] cnts ADC counts |
||
| 548 | * |
||
| 549 | * @retval voltage Voltage in [V] |
||
| 550 | */ |
||
| 551 | float osc_fpga_cnv_cnt_to_v(int cnts) |
||
| 552 | { |
||
| 553 | int m; |
||
| 554 | |||
| 555 | if(cnts & (1<<(c_osc_fpga_adc_bits-1))) { |
||
| 556 | /* negative number */ |
||
| 557 | m = -1 *((cnts ^ ((1<<c_osc_fpga_adc_bits)-1)) + 1); |
||
| 558 | } else { |
||
| 559 | m = cnts; |
||
| 560 | /* positive number */ |
||
| 561 | } |
||
| 562 | return m; |
||
| 563 | } |
||
| 564 |