pavel-demin / red-pitaya-notes

Notes on the Red Pitaya Open Source Instrument
http://pavel-demin.github.io/red-pitaya-notes/
MIT License
338 stars 210 forks source link

Measure Level Issue and Enhancement request #1125

Closed zoofiftyfive closed 9 months ago

zoofiftyfive commented 10 months ago

Description of the setup:

Description of the problem:

After upgrading from alpine-3.17 image to the alpine-3.18 image the default measure-level tool included in the image does not appear to be showing any level indication via the LED's.

Also I had a modified version of measure-level tool that printed output to the console at a set interval. This version also no longer works correctly with alpine-3.18 image. The output now prints thousands of lines per second with channel 1 being a static level figure and channel 2 not showing any level information at all.

It would be great to have this tool working again and even better would be if the tool could be enhanced (officially) to print the output to the console. I suspect printing to console would be more useful for the majority of users compared with using the on device LED's.

The code I was using successfully with alpine-3.17 is below. The main enhancement came from "darksidelemm", I just added sequence count info, datetime, console colours and adjusted the time interval range from 1-30 to 0.1-30 seconds. Note I'm not familiar with C so there are likely issues with the modifications I've made which is why an official version that prints to console would be great.

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <sys/mman.h>
#include <time.h>

int interrupted = 0;

void signal_handler(int sig)
{
  interrupted = 1;
}

void usage()
{
  fprintf(stderr, "Usage: measure-level freq duration\n");
  fprintf(stderr, " freq - frequency expressed in MHz (122.88 or 125),\n");
  fprintf(stderr, " duration - measurement duration expressed in seconds (from 0.1 to 30).\n");
}

const char* getColor(double value)
{
  if (value >= 0.0)
    return "\033[31m";  // Red
  else if (value > -3.0)
    return "\033[38;5;208m";  // Dark Orange
  else if (value > -9.0)
    return "\033[33m";  // Yellow
  else if (value > -20.0)
    return "\033[32m";  // Dark Green
  else
    return "\033[92m";  // Light Green
}

int main(int argc, char *argv[])
{
  int fd;
  char *end;
  volatile void *cfg, *sts;
  volatile uint32_t *fifo;
  volatile uint8_t *rst, *led;
  volatile uint32_t *cntr;
  double freq;
  double duration;
  uint32_t buffer, scale;
  uint16_t level[2];
  uint8_t bits[2];
  char timeBuffer[80];
  int sequenceNumber = 0;

  if (argc != 3)
  {
    usage();
    return EXIT_FAILURE;
  }

  errno = 0;
  freq = strtod(argv[1], &end);
  if (errno != 0 || end == argv[1] || (freq != 122.88 && freq != 125.0))
  {
    usage();
    return EXIT_FAILURE;
  }

  duration = strtod(argv[2], &end);
  if (errno != 0 || end == argv[2] || duration < 0.1 || duration > 30)
  {
    usage();
    return EXIT_FAILURE;
  }

  if ((fd = open("/dev/mem", O_RDWR)) < 0)
  {
    fprintf(stderr, "Cannot open /dev/mem.\n");
    return EXIT_FAILURE;
  }

  sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x40040000);
  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x40041000);
  fifo = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x40043000);

  rst = (uint8_t *)(cfg + 1);
  led = (uint8_t *)(cfg + 2);
  cntr = (uint32_t *)(sts + 4);

  *(uint32_t *)(cfg + 4) = (uint32_t)floor(freq * 1.0e6 * duration + 0.5) - 1;

  *rst &= ~1;
  *rst |= 1;

  signal(SIGINT, signal_handler);

  time_t rawtime;
  struct tm *timeinfo;

  while (!interrupted)
  {
    if (*cntr < 1)
    {
      usleep(1000);
      continue;
    }

    buffer = *fifo;

    level[0] = buffer & 0xffff;
    level[1] = (buffer >> 16) & 0xffff;

    scale = (freq == 125.0) ? 8192 : 32768;

    bits[0] = 15 >> (uint8_t)floor(-5.0 * log10(1.0 * level[0] / scale));
    bits[1] = 15 >> (uint8_t)floor(-5.0 * log10(1.0 * level[1] / scale));

    *led = bits[1] << 4 | bits[0];

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(timeBuffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);

    double rx1_dB = 20.0 * log10(1.0 * level[0] / scale);
    double rx2_dB = 20.0 * log10(1.0 * level[1] / scale);

    printf("%d, %s, %sRX1: %.2f dBFS\033[0m, %sRX2: %.2f dBFS\033[0m\r\n",
           sequenceNumber, timeBuffer,
           getColor(rx1_dB), rx1_dB,
           getColor(rx2_dB), rx2_dB);

    sequenceNumber++;
  }

  *led = 0;

  *rst &= ~1;

  return EXIT_SUCCESS;
}

Steps to reproduce the problem:

  1. Run the default measure-level tool that is included in alpine-3.18 image with 'measure-level 122.88 1'
  2. Observe LED lights do not show any level information

For the modified measure-level tool that I am using, it previously output to console at a set interval ranging from 0.1 to 30 seconds. However regardless of what I use to run the modified measure-level tool, the output now has thousands of records after running for just 1 second (sample below shows over 5000 records in short time).

5565, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5566, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5567, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5568, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5569, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5570, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5571, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5572, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5573, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5574, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS 5575, 2024-01-27 01:09:46, RX1: -42.11 dBFS, RX2: -inf dBFS

pavel-demin commented 10 months ago

Thank you for finding this problem. It is now fixed with this commit. I have also added printing of measured levels with this commit.

zoofiftyfive commented 10 months ago

Thanks Pavel for the super quick response.

I have tested the new commit and can confirm it is now working perfectly.

Cheers

pavel-demin commented 9 months ago

The fixed version is now in the new release.