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 |