Subversion Repositories f9daq

Rev

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