From 31657834e3a44dec95a2175bf0133c1ef6d08a38 Mon Sep 17 00:00:00 2001
From: Joe Taylor <joe@princeton.edu>
Date: Thu, 10 Nov 2022 14:39:56 -0500
Subject: [PATCH] Add a feature to MAP65 for measuring antenna pointing errors.

---
 map65/astro.cpp      |  75 +++++++++++++-
 map65/astro.h        |   6 +-
 map65/astro.ui       | 236 ++++++++++++++++++++++++++++++++++++++++---
 map65/mainwindow.cpp |  19 +++-
 map65/mainwindow.h   |   1 +
 5 files changed, 321 insertions(+), 16 deletions(-)

diff --git a/map65/astro.cpp b/map65/astro.cpp
index a91c048b4..427518382 100644
--- a/map65/astro.cpp
+++ b/map65/astro.cpp
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include "SettingsGroup.hpp"
 #include "commons.h"
+#include <math.h>
 
 extern "C" {
   void astrosub_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
@@ -44,7 +45,7 @@ Astro::~Astro()
 }
 
 void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
-                        int fQSO, int nsetftx, int ntxFreq, QString azelDir)
+                        int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg)
 {
   static int ntxFreq0=-99;
   char cc[300];
@@ -86,6 +87,65 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
           ntsky,xnr,dgrd);
   ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
 
+  double azOffset=0.0;
+  double elOffset=0.0;
+  double rad=57.2957795131;
+  int iCycle=2;
+// Are we doing pointing tests?
+  bool bPointing=ui->cbPointingTests->isChecked();
+  ui->gbPointing->setVisible(bPointing);
+  if(bPointing) {
+    int nDwell=int(ui->sbDwell->value());
+    if(ui->cbAutoCycle->isChecked()) {
+      iCycle=(t.currentSecsSinceEpoch()%(6*nDwell))/nDwell + 1;
+      if(iCycle==1) {
+        azOffset = -ui->sbOffset->value()/cos(elsun/rad);
+        ui->rb1->setChecked(true);
+      }
+      if(iCycle==2 or iCycle==5) {
+        ui->rb2->setChecked(true);
+      }
+      if(iCycle==3) {
+        azOffset = +ui->sbOffset->value()/cos(elsun/rad);
+        ui->rb3->setChecked(true);
+      }
+      if(iCycle==4) {
+        elOffset = -ui->sbOffset->value();
+        ui->rb4->setChecked(true);
+      }
+      if(iCycle==6) {
+        elOffset = +ui->sbOffset->value();
+        ui->rb6->setChecked(true);
+      }
+    }
+    if(ui->cbOnOff->isChecked()) {
+      iCycle=(t.currentSecsSinceEpoch()%(2*nDwell))/nDwell + 1;
+      if(iCycle==1) {
+        azOffset = -ui->sbOffset->value()/cos(elsun/rad);
+        ui->rb1->setChecked(true);
+      }
+      if(iCycle==2) {
+        ui->rb2->setChecked(true);
+      }
+    }
+    if(ui->cbAutoCycle->isChecked() or ui->cbOnOff->isChecked()) {
+      QFile f("pointing.out");
+      if(f.open(QIODevice::WriteOnly | QIODevice::Append)) {
+        QTextStream out(&f);
+        out << t.toString("yyyy-MMM-dd hh:mm:ss");
+        sprintf(cc,"%7.1f %7.1f   %d %7.1f %7.1f %10.1f %7.2f\n",
+                azsun,elsun,iCycle,azOffset,elOffset,xavg,10.0*log10(xavg));
+        out << cc;
+        f.close();
+      }
+    }
+  } else {
+    ui->rb2->setChecked(true);
+    ui->cbAutoCycle->setChecked(false);
+    ui->cbOnOff->setChecked(false);
+  }
+
+// Write pointing data to azel.dat
   QString fname=azelDir+"/azel.dat";
   QFile f(fname);
   if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
@@ -107,7 +167,7 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
           "%3d,%1d,fQSO\n"
           "%3d,%1d,fQSO2\n",
           nhr,nmin,isec,azmoon,elmoon,
-          nhr,nmin,isec,azsun,elsun,
+          nhr,nmin,isec,azsun+azOffset,elsun+elOffset,
           nhr,nmin,isec,0.0,0.0,
           nfreq,ndop,ndop00,
           fQSO,nsetftx,
@@ -120,3 +180,14 @@ void Astro::setFontSize(int n)
 {
   ui->astroTextBrowser->setFontPointSize(n);
 }
+
+void Astro::on_cbAutoCycle_clicked(bool checked)
+{
+  if(checked) ui->cbOnOff->setChecked(false);
+}
+
+void Astro::on_cbOnOff_clicked(bool checked)
+{
+  if(checked) ui->cbAutoCycle->setChecked(false);
+}
+
diff --git a/map65/astro.h b/map65/astro.h
index f425f3e73..6b574237f 100644
--- a/map65/astro.h
+++ b/map65/astro.h
@@ -15,10 +15,14 @@ class Astro : public QWidget
 public:
   explicit Astro (QString const& settings_filename, QWidget *parent = 0);
   void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
-                   int fQSO, int nsetftx, int ntxFreq, QString azelDir);
+                   int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg);
   void setFontSize(int n);
   ~Astro ();
 
+private slots:
+  void on_cbOnOff_clicked(bool checked);
+  void on_cbAutoCycle_clicked(bool checked);
+
 private:
   Ui::Astro *ui;
   QString m_settings_filename;
diff --git a/map65/astro.ui b/map65/astro.ui
index 30cce70bb..991a002f4 100644
--- a/map65/astro.ui
+++ b/map65/astro.ui
@@ -6,30 +6,242 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>262</width>
+    <width>441</width>
     <height>483</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <widget class="QTextBrowser" name="astroTextBrowser">
+  <widget class="QGroupBox" name="gbPointing">
+   <property name="geometry">
+    <rect>
+     <x>269</x>
+     <y>19</y>
+     <width>151</width>
+     <height>431</height>
+    </rect>
+   </property>
+   <property name="title">
+    <string/>
+   </property>
+   <widget class="QRadioButton" name="rb1">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>100</y>
+      <width>30</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>1</string>
+    </property>
+   </widget>
+   <widget class="QRadioButton" name="rb2">
+    <property name="geometry">
+     <rect>
+      <x>60</x>
+      <y>100</y>
+      <width>40</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>2, 5</string>
+    </property>
+    <property name="checked">
+     <bool>true</bool>
+    </property>
+   </widget>
+   <widget class="QRadioButton" name="rb3">
+    <property name="geometry">
+     <rect>
+      <x>110</x>
+      <y>100</y>
+      <width>30</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>3</string>
+    </property>
+   </widget>
+   <widget class="QRadioButton" name="rb4">
+    <property name="geometry">
+     <rect>
+      <x>60</x>
+      <y>150</y>
+      <width>30</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>4</string>
+    </property>
+   </widget>
+   <widget class="QRadioButton" name="rb6">
+    <property name="geometry">
+     <rect>
+      <x>60</x>
+      <y>50</y>
+      <width>30</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>6</string>
+    </property>
+   </widget>
+   <widget class="QDoubleSpinBox" name="sbOffset">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>230</y>
+      <width>130</width>
+      <height>22</height>
+     </rect>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+    <property name="prefix">
+     <string>Offset   </string>
+    </property>
+    <property name="suffix">
+     <string>  deg</string>
+    </property>
+    <property name="decimals">
+     <number>1</number>
+    </property>
+    <property name="minimum">
+     <double>0.500000000000000</double>
+    </property>
+    <property name="maximum">
+     <double>20.000000000000000</double>
+    </property>
+    <property name="singleStep">
+     <double>0.500000000000000</double>
+    </property>
+    <property name="value">
+     <double>2.500000000000000</double>
+    </property>
+   </widget>
+   <widget class="QCheckBox" name="cbAutoCycle">
+    <property name="geometry">
+     <rect>
+      <x>30</x>
+      <y>330</y>
+      <width>91</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>Auto Cycle</string>
+    </property>
+   </widget>
+   <widget class="QCheckBox" name="cbOnOff">
+    <property name="geometry">
+     <rect>
+      <x>30</x>
+      <y>380</y>
+      <width>70</width>
+      <height>17</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>On Off</string>
+    </property>
+   </widget>
+   <widget class="QSpinBox" name="sbDwell">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>280</y>
+      <width>130</width>
+      <height>22</height>
+     </rect>
+    </property>
+    <property name="alignment">
+     <set>Qt::AlignCenter</set>
+    </property>
+    <property name="suffix">
+     <string>   s</string>
+    </property>
+    <property name="prefix">
+     <string>Dwell   </string>
+    </property>
+    <property name="minimum">
+     <number>10</number>
+    </property>
+    <property name="maximum">
+     <number>300</number>
+    </property>
+    <property name="singleStep">
+     <number>10</number>
+    </property>
+   </widget>
+  </widget>
+  <widget class="QWidget" name="">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>10</y>
-     <width>256</width>
-     <height>451</height>
+     <width>258</width>
+     <height>471</height>
     </rect>
    </property>
-   <property name="font">
-    <font>
-     <family>Courier New</family>
-     <pointsize>20</pointsize>
-     <weight>75</weight>
-     <bold>true</bold>
-    </font>
-   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QTextBrowser" name="astroTextBrowser">
+      <property name="font">
+       <font>
+        <family>Courier New</family>
+        <pointsize>20</pointsize>
+        <weight>75</weight>
+        <bold>true</bold>
+       </font>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="cbPointingTests">
+        <property name="text">
+         <string>Pointing Tests</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </item>
+   </layout>
   </widget>
  </widget>
  <resources/>
diff --git a/map65/mainwindow.cpp b/map65/mainwindow.cpp
index 2a8bb4705..99dd59527 100644
--- a/map65/mainwindow.cpp
+++ b/map65/mainwindow.cpp
@@ -520,6 +520,8 @@ void MainWindow::dataSink(int k)
   static int nkhz;
   static int nfsample=96000;
   static int nxpol=0;
+  static int nsec0=0;
+  static int nsum=0;
   static float fgreen;
   static int ndiskdat;
   static int nb;
@@ -529,6 +531,7 @@ void MainWindow::dataSink(int k)
   static float rejectx;
   static float rejecty;
   static float slimit;
+  static double xsum=0.0;
 
   if(m_diskData) {
     ndiskdat=1;
@@ -551,8 +554,22 @@ void MainWindow::dataSink(int k)
            &nfsample, &fgreen, &m_adjustIQ, &m_applyIQcal,
            &m_gainx, &m_gainy, &m_phasex, &m_phasey, &rejectx, &rejecty,
            &px, &py, s, &nkhz, &ihsym, &nzap, &slimit, lstrong);
+
+  int nsec=QDateTime::currentSecsSinceEpoch();
+  if(nsec==nsec0) {
+    xsum+=pow(10.0,0.1*px);
+    nsum+=1;
+  } else {
+    m_xavg=0.0;
+    if(nsum>0) m_xavg=xsum/nsum;
+    xsum=pow(10.0,0.1*px);
+    nsum=1;
+  }
+  nsec0=nsec;
+
   QString t;
   m_pctZap=nzap/178.3;
+  ui->yMeterFrame->setVisible(m_xpol);
   if(m_xpol) {
     lab4->setText (
                   QString {" Rx noise: %1  %2 %3 %% "}
@@ -1693,7 +1710,7 @@ void MainWindow::guiUpdate()
     QDateTime t = QDateTime::currentDateTimeUtc();
     int fQSO=m_wide_graph_window->QSOfreq();
     m_astro_window->astroUpdate(t, m_myGrid, m_hisGrid, fQSO, m_setftx,
-                          m_txFreq, m_azelDir);
+                          m_txFreq, m_azelDir, m_xavg);
     m_setftx=0;
     QString utc = t.date().toString(" yyyy MMM dd \n") + t.time().toString();
     ui->labUTC->setText(utc);
diff --git a/map65/mainwindow.h b/map65/mainwindow.h
index 46e6f0775..bbf3e707c 100644
--- a/map65/mainwindow.h
+++ b/map65/mainwindow.h
@@ -200,6 +200,7 @@ private:
   //    double  m_IQphase;
   double  m_cal570;
   double  m_TxOffset;
+  double  m_xavg;
 
   bool    m_monitoring;
   bool    m_transmitting;