diff --git a/SBC/rpi-4/SoapyRadioberrySDR/CMakeLists.txt b/SBC/rpi-4/SoapyRadioberrySDR/CMakeLists.txt index 0e0607d..7e09b3b 100644 --- a/SBC/rpi-4/SoapyRadioberrySDR/CMakeLists.txt +++ b/SBC/rpi-4/SoapyRadioberrySDR/CMakeLists.txt @@ -29,7 +29,7 @@ if (NOT SoapySDR_FOUND) message(WARNING "SoapySDR development files not found - skipping support") return() endif () -set(CMAKE_CXX_STANDARD 14) + #include_directories(${MY_DEVICE_INCLUDE_DIRS}) SOAPY_SDR_MODULE_UTIL( TARGET SoapyRadioberrySDR diff --git a/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberry.hpp b/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberry.hpp index 09426b3..0a7432b 100644 --- a/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberry.hpp +++ b/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberry.hpp @@ -16,7 +16,6 @@ #define TX_MAX 4800 #define TX_MAX_BUFFER (TX_MAX * 8) -const int npackages = 4; typedef enum radioberrysdrStreamFormat { RADIOBERRY_SDR_CF32, diff --git a/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberryStreaming.cpp b/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberryStreaming.cpp index b5c9581..592a7e3 100644 --- a/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberryStreaming.cpp +++ b/SBC/rpi-4/SoapyRadioberrySDR/SoapyRadioberryStreaming.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "SoapyRadioberry.hpp" void SoapyRadioberry::setSampleRate( const int direction, const size_t channel, const double rate ) { @@ -113,6 +114,7 @@ SoapySDR::Stream *SoapyRadioberry::setupStream( if (format == SOAPY_SDR_CF32) { SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32."); ptr->set_stream_format(RADIOBERRY_SDR_CF32); + mox = true; } else if(format == SOAPY_SDR_CS16 && direction == SOAPY_SDR_TX) { @@ -158,7 +160,8 @@ int SoapyRadioberry::readStream( const long timeoutUs ) { int nr_samples, no_bytes, iq=0; - + int npackages = numElems / 63; + void *buff_base = buffs[0]; float *target_buffer = (float *) buff_base; int16_t *itarget_buffer = (int16_t *) buff_base; @@ -202,16 +205,11 @@ int SoapyRadioberry::readStream( itarget_buffer[iq++] = (int16_t)(right_sample >> 8); // 16 bit sample } } - //printf("nr_samples %d sample: %d %d \n", nr_samples, left_sample, right_sample); + //printf("nr_samples %d sample: %f %f \n", nr_samples, (float)left_sample / 8388608.0, (float)right_sample / 8388608.0); } return (npackages * nr_samples); //return the number of IQ samples } -union uTxBuffer -{ - std::uint16_t i16TxBuffer[2]; - unsigned char i8TxBuffer[4]; -}; int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *buffs, const size_t numElems, int &flags, const long long timeNs, const long timeoutUs) { @@ -222,16 +220,26 @@ int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *b void const *buff_base = buffs[0]; float *target_buffer = (float *) buff_base; int16_t *itarget_buffer = (int16_t *) buff_base; - uTxBuffer tx; sdr_stream *ptr = (sdr_stream *)stream; + unsigned char i8TxBuffer[6]; if (ptr->get_stream_format() == RADIOBERRY_SDR_CF32) { for (int ii = 0; ii < numElems; ii++) { - tx.i16TxBuffer[0] = (int16_t)(target_buffer[iq++] * 16384.0f); - tx.i16TxBuffer[1] = (int16_t)(target_buffer[iq++] * 16384.0f); - ret = write(fd_rb, &tx, 4 * sizeof(uint8_t)); + const float gain = 8388608.0f; + int isample = target_buffer[iq] >= 0.0 ? (long)floor(target_buffer[iq] * gain + 0.5) : (long)ceil(target_buffer[iq] * gain - 0.5); + int qsample = target_buffer[iq + 1] >= 0.0 ? (long)floor(target_buffer[iq + 1] * gain + 0.5) : (long)ceil(target_buffer[iq + 1] * gain - 0.5); + + //printf("nr_samples %d sample: %d %d \n", iq, isample,qsample ); + + i8TxBuffer[0] = isample >> 16; + i8TxBuffer[1] = isample >> 8; + i8TxBuffer[2] = qsample >> 16; + i8TxBuffer[3] = qsample >> 8; + ret = write(fd_rb, i8TxBuffer, 4); + iq++; + iq++; } } if (ptr->get_stream_format() == RADIOBERRY_SDR_CS16) @@ -240,12 +248,11 @@ int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *b for (int ii = 0; ii < numElems; ii++) { - tx.i8TxBuffer[0] = (unsigned char)((itarget_buffer[j] & 0xff00) >> 8); - tx.i8TxBuffer[1] = (unsigned char)(itarget_buffer[j] & 0xff); - tx.i8TxBuffer[2] = (unsigned char)(((-1 * itarget_buffer[j + 1]) & 0xff00) >> 8); - tx.i8TxBuffer[3] = (unsigned char)((-1 * itarget_buffer[j + 1]) & 0xff); - - ret = write(fd_rb, &tx, sizeof(uint32_t)); + i8TxBuffer[0] = (unsigned char)((itarget_buffer[j] & 0xff00) >> 8); + i8TxBuffer[1] = (unsigned char)(itarget_buffer[j] & 0xff); + i8TxBuffer[2] = (unsigned char)(((itarget_buffer[j + 1]) & 0xff00) >> 8); + i8TxBuffer[3] = (unsigned char)((itarget_buffer[j + 1]) & 0xff); + ret = write(fd_rb, i8TxBuffer, 4); j += 2; } } diff --git a/SBC/rpi-4/device_driver/driver/Makefile b/SBC/rpi-4/device_driver/driver/Makefile index da38a71..4249dc3 100644 --- a/SBC/rpi-4/device_driver/driver/Makefile +++ b/SBC/rpi-4/device_driver/driver/Makefile @@ -1,3 +1,5 @@ +CCFLAGS += -Wcast-function-type + KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build obj-m := radioberry.o diff --git a/SBC/rpi-4/device_driver/driver/radioberry.c b/SBC/rpi-4/device_driver/driver/radioberry.c index 572312c..0be65a9 100644 --- a/SBC/rpi-4/device_driver/driver/radioberry.c +++ b/SBC/rpi-4/device_driver/driver/radioberry.c @@ -79,14 +79,14 @@ static struct device* radioberryCharDevice = NULL; static int _nrx = 1; static unsigned int irqNumber; -static unsigned int gpioRxSamplesiPin = 25; +static struct gpio_desc *gpio_desc = NULL; static irq_handler_t radioberry_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs){ wake_up_interruptible(&rx_sample_queue); return (irq_handler_t) IRQ_HANDLED; } -static void firmware_load(char *firmware, int size) { +static void firmware_load(const char *firmware, int size) { printk(KERN_INFO "inside %s function \n", __FUNCTION__); u8 *buf = kmalloc(size + 1, GFP_KERNEL); @@ -150,7 +150,7 @@ static int radioberry_open(struct inode *inode, struct file *filep) { return -EBUSY; } int *minor = (int *)kmalloc(sizeof(int), GFP_KERNEL); - int major = MAJOR(inode->i_rdev); + // not used int major = MAJOR(inode->i_rdev); *minor = MINOR(inode->i_rdev); filep->private_data = (void *)minor; @@ -230,8 +230,30 @@ static struct file_operations radioberry_fops = { static int radioberry_probe(struct platform_device *pdev) { - printk(KERN_INFO "inside %s function \n", __FUNCTION__); - struct device *dev = &pdev->dev; + printk(KERN_INFO "inside %s function \n", __FUNCTION__); + if(!device_property_present(&pdev->dev, "rx-sample-gpio")) + printk("radioberry - Error! Device property 'rx-sample-gpio' not found!\n"); + else + printk("radioberry - Device property 'rx-sample-gpio' found!\n"); + + gpio_desc = gpiod_get(&pdev->dev, "rx-sample", GPIOD_ASIS); + if(IS_ERR(gpio_desc)) { + printk("Failed to get GPIO rx-sample-gpio\n"); + return -1 * IS_ERR(gpio_desc); + } + printk("Got GPIO rx-sample-gpio\n"); + + int retval = gpiod_direction_input(gpio_desc); + if (retval) { + printk("Failed to set GPIO pin direction\n"); + return retval; + } + irqNumber = gpiod_to_irq(gpio_desc); + if (irqNumber < 0) { + printk("Failed to get IRQ number for GPIO pin\n"); + return irqNumber; + } + printk(KERN_INFO "Radioberry: The rx samples pin is mapped to IRQ: %d\n", irqNumber); return 0; } @@ -259,9 +281,6 @@ static struct platform_driver radioberry_driver = { }; static int __init radioberry_init(void) { - int retval; - size_t size; - printk(KERN_INFO "inside %s function \n", __FUNCTION__); printk(KERN_INFO "%s loading...\n", DRIVER_NAME); @@ -277,7 +296,7 @@ static int __init radioberry_init(void) { printk(KERN_INFO "Radioberry: registered correctly with major number %d\n", majorNumber); // Register the device class - radioberryCharClass = class_create(THIS_MODULE, CLASS_NAME); + radioberryCharClass = class_create(CLASS_NAME); if (IS_ERR(radioberryCharClass)){ unregister_chrdev(majorNumber, DEVICE_NAME); printk(KERN_ALERT "Failed to register device class\n"); @@ -294,27 +313,27 @@ static int __init radioberry_init(void) { return PTR_ERR(radioberryCharDevice); } printk(KERN_INFO "Radioberry char: device class created correctly\n"); - + mutex_init(&radioberry_mutex); init_waitqueue_head(&rx_sample_queue); - //configure irq. - gpio_request(gpioRxSamplesiPin, "sysfs"); - gpio_direction_input(gpioRxSamplesiPin); - gpio_export(gpioRxSamplesiPin, false); - - printk(KERN_INFO "Radioberry: The rx sample state is currently: %d\n", gpio_get_value(gpioRxSamplesiPin)); + + printk(KERN_INFO "Radioberry: The rx sample state is currently: %d\n", gpiod_get_value(gpio_desc)); // GPIO numbers and IRQ numbers are not the same! This function performs the mapping for us - irqNumber = gpio_to_irq(gpioRxSamplesiPin); + // Get the IRQ number for the GPIO pin + + printk(KERN_INFO "Radioberry: The rx samples pin is mapped to IRQ: %d\n", irqNumber); // This next call requests an interrupt line + if (irqNumber > 0) { result = request_irq(irqNumber, (irq_handler_t) radioberry_irq_handler, IRQF_TRIGGER_RISING, // Interrupt on rising edge RQF_TRIGGER_RISING "radioberry_rx_irq", // Used in /proc/interrupts to identify the owner - NULL); + NULL); + } printk(KERN_INFO "Radioberry: The interrupt request result is: %d\n", result); @@ -328,14 +347,13 @@ static int __init radioberry_init(void) { } static void __exit radioberry_exit(void) { - int i; - dev_t devno; - dev_t devno_top; printk(KERN_INFO "inside %s function \n", __FUNCTION__); - free_irq(irqNumber, NULL); - gpio_unexport(gpioRxSamplesiPin); + if (irqNumber > 0) + free_irq(irqNumber, NULL); + if (gpio_desc != NULL) + gpiod_put(gpio_desc); platform_driver_unregister(&radioberry_driver);