diff --git a/linux-software/lib/atca-v2-daq-lib.c b/linux-software/lib/atca-v2-daq-lib.c new file mode 100644 index 0000000000000000000000000000000000000000..63118e26f68f869a250f954808d3875ee7af9f27 --- /dev/null +++ b/linux-software/lib/atca-v2-daq-lib.c @@ -0,0 +1,182 @@ +/** + * ATCA MIMO v2 Lib functions + * Project Name: + * Design Name: + * working with kernel 4.xx + * + * + * Copyright 2014 - 2019 IPFN-Instituto Superior Tecnico, Portugal + * Creation Date 2019-07-26 + * + * Licensed under the EUPL, Version 1.1 or - as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the + * Licence. + * You may obtain a copy of the Licence at: + * + * http://ec.europa.eu/idabc/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + * + */ +// For CPU_ZERO +#define _GNU_SOURCE +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ + +#include <errno.h> +#include <sched.h> +#include <stdio.h> + +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "atca-v2-daq.h" +#include "atca-v2-daq-ioctl.h" + +int bind_to_cpu(int core_id) { + // cpu_set_t: This data set is a bitset where each bit represents a CPU. + cpu_set_t cpuset; + const pthread_t pid = pthread_self(); + + // CPU_ZERO: This macro initializes the CPU set set to be the empty set. + CPU_ZERO(&cpuset); + // CPU_SET: This macro adds cpu to the CPU set set. + CPU_SET(core_id, &cpuset); + + // pthread_setaffinity_np: The pthread_setaffinity_np() function sets the CPU + // affinity mask of the thread thread to the CPU set pointed to by cpuset. If + // the call is successful, and the thread is not currently running on one of + // the CPUs in cpuset, then it is migrated to one of those CPUs. + const int set_result = + pthread_setaffinity_np(pid, sizeof(cpu_set_t), &cpuset); + if (set_result != 0) { + // errno = en; + perror("pthread_setaffinity_np"); + return set_result; + /*print_error_then_terminate(set_result, "pthread_setaffinity_np");*/ + } + // Check what is the actual affinity mask that was assigned to the thread. + // pthread_getaffinity_np: The pthread_getaffinity_np() function returns the + // CPU affinity mask of the thread thread in the buffer pointed to by cpuset. + const int get_affinity = + pthread_getaffinity_np(pid, sizeof(cpu_set_t), &cpuset); + if (get_affinity != 0) { + + perror("pthread_getaffinity_np"); + return get_affinity; + /*print_error_then_terminate(get_affinity, "pthread_getaffinity_np");*/ + } + if (CPU_ISSET(core_id, &cpuset)) + printf("pid %ld, running on core %d\n", pid, core_id); + return 0; +} +int atca_mimo_v2_get_status(int fd, unsigned int * pstatus) { + int rc; + rc = ioctl(fd, ATCA_PCIE_IOCG_STATUS, pstatus); + return rc; +} +int atca_mimo_v2_soft_trigger(int fd) { + int rc; + rc = ioctl(fd, ATCA_PCIE_IOCT_SOFT_TRIG); + return rc; +} +int atca_mimo_v2_stop_acq(int fd) { + int max_buf_count; + max_buf_count = ioctl(fd, ATCA_PCIE_IOCT_ACQ_DISABLE); + /*int rc = */ + ioctl(fd, ATCA_PCIE_IOCT_DMA_DISABLE); + return max_buf_count; +} +int atca_mimo_v2_acq_enable(int fd) { + int rc; + rc = ioctl(fd, ATCA_PCIE_IOCT_ACQ_ENABLE); + rc = ioctl(fd, ATCA_PCIE_IOCT_DMA_ENABLE); + + return rc; +} +int atca_mimo_v2_init_device_16bit(int fd, unsigned int chop_period){ + int rc; + int tmp=0; + + atca_mimo_v2_stop_acq(fd); + rc = ioctl(fd, ATCA_PCIE_IOCT_DATA32_DISABLE); + if(chop_period){ + rc = ioctl(fd, ATCA_PCIE_IOCT_CHOP_ENABLE); + tmp = ((0xFFFF & chop_period)<<16) | ((0xFFFF &chop_period/2)); + rc = ioctl(fd, ATCA_PCIE_IOCS_CHOP_PERIOD, &tmp); + } + else { + rc = ioctl(fd, ATCA_PCIE_IOCT_CHOP_DISABLE); + } + rc = ioctl(fd, ATCA_PCIE_IOCT_DMA_RESET); + rc = ioctl(fd, ATCA_PCIE_IOCT_INT_ENABLE); + + rc = ioctl(fd, ATCA_PCIE_IOCG_DMA_SIZE, &tmp); + return tmp; +} + + + +/*unsigned long int time_interval_us(tstart, tend) struct timespec *tstart, + * *tend;*/ +unsigned long int time_interval_us(struct timeval *tstart, + struct timeval *tend) { + unsigned long int duration = 1000000UL * (tend->tv_sec - tstart->tv_sec) + + (unsigned long)tend->tv_usec - + (unsigned long)tstart->tv_usec; + return duration; +} + +void get_rt_pckt_adc_data(int32_t *pAdcData, DMACH1_PCKT *pPdma) { + int j; + for (j = 0; j < ADC_CHANNELS; j++) + *pAdcData++ = pPdma->adc_decim_data.channel[j].adc_data; +} + +void get_pckt_adc_data(int32_t *pAdcData, DMA_PCKT *pPdma) { + /*Normal samples*/ + int i, j; + for (i = 0; i < PCK_N_SAMPLES; i++) { + for (j = 0; j < ADC_CHANNELS; j++) + *pAdcData++ = pPdma->samp[i].channel[j].adc_data; + } +} +unsigned int get_pckt_head_magic(DMA_PCKT *pPdma) { + unsigned int uval = 0; + int i; + for (i = 0; i < 4; i++) { + uval |= pPdma->samp[0].channel[i].data_byte << (i * 8); + } + return uval; +} +unsigned int get_pckt_foot_magic(DMA_PCKT *pPdma) { + unsigned int uval = 0; + int i; + for (i = 0; i < 4; i++) { + uval |= (pPdma->samp[PCK_N_SAMPLES - 1].channel[i].data_byte) << (i * 8); + } + return uval; +} +uint64_t get_sample_cnt(SAMPLE *pSamp) { + uint64_t uval = 0; + int i; + for (i = 0; i < 8; i++) { + uval |= (pSamp->channel[8 + i].data_byte) << (i * 8); + } + return uval; +}