Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  565.