[Gpredict-svn] SF.net SVN: gpredict:[216] trunk/src
Real time satellite tracking and orbit prediction
Status: Beta
Brought to you by:
csete
|
From: <cs...@us...> - 2009-03-29 21:35:03
|
Revision: 216
http://gpredict.svn.sourceforge.net/gpredict/?rev=216&view=rev
Author: csete
Date: 2009-03-29 21:34:58 +0000 (Sun, 29 Mar 2009)
Log Message:
-----------
Implemented new controller (RX and TX). Pending transponder management.
Modified Paths:
--------------
trunk/src/gtk-rig-ctrl.c
trunk/src/gtk-rig-ctrl.h
Modified: trunk/src/gtk-rig-ctrl.c
===================================================================
--- trunk/src/gtk-rig-ctrl.c 2009-03-29 21:33:48 UTC (rev 215)
+++ trunk/src/gtk-rig-ctrl.c 2009-03-29 21:34:58 UTC (rev 216)
@@ -74,21 +74,29 @@
static GtkWidget *create_conf_widgets (GtkRigCtrl *ctrl);
static GtkWidget *create_count_down_widgets (GtkRigCtrl *ctrl);
-
-static void store_sats (gpointer key, gpointer value, gpointer user_data);
-
+/* callback functions */
static void sat_selected_cb (GtkComboBox *satsel, gpointer data);
static void track_toggle_cb (GtkToggleButton *button, gpointer data);
static void delay_changed_cb (GtkSpinButton *spin, gpointer data);
static void rig_selected_cb (GtkComboBox *box, gpointer data);
static void rig_locked_cb (GtkToggleButton *button, gpointer data);
static gboolean rig_ctrl_timeout_cb (gpointer data);
+
+/* radio control functions */
+static void exec_rx_cycle (GtkRigCtrl *ctrl);
+static void exec_tx_cycle (GtkRigCtrl *ctrl);
+static void exec_trx_cycle (GtkRigCtrl *ctrl);
+static void exec_duplex_cycle (GtkRigCtrl *ctrl);
static gboolean set_freq_simplex (GtkRigCtrl *ctrl, gdouble freq);
static gboolean get_freq_simplex (GtkRigCtrl *ctrl, gdouble *freq);
+static gboolean get_ptt (GtkRigCtrl *ctrl);
static void update_count_down (GtkRigCtrl *ctrl, gdouble t);
+/* misc utility functions */
+static void store_sats (gpointer key, gpointer value, gpointer user_data);
static gboolean have_conf (void);
+
static GtkVBoxClass *parent_class = NULL;
static GdkColor ColBlack = { 0, 0, 0, 0};
@@ -161,6 +169,8 @@
ctrl->delay = 1000;
ctrl->timerid = 0;
ctrl->errcnt = 0;
+ ctrl->lastrxf = 0.0;
+ ctrl->lasttxf = 0.0;
}
static void
@@ -805,6 +815,8 @@
/* close socket */
gtk_widget_set_sensitive (ctrl->DevSel, TRUE);
ctrl->engaged = FALSE;
+ ctrl->lasttxf = 0.0;
+ ctrl->lastrxf = 0.0;
}
else {
if (ctrl->conf == NULL) {
@@ -818,6 +830,36 @@
gtk_widget_set_sensitive (ctrl->DevSel, FALSE);
ctrl->engaged = TRUE;
ctrl->wrops = 0;
+
+ /* set initial frequency */
+
+ switch (ctrl->conf->type) {
+ case RIG_TYPE_RX:
+ ctrl->lastrxf = gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqDown));
+ set_freq_simplex (ctrl, ctrl->lastrxf);
+ break;
+ case RIG_TYPE_TX:
+ ctrl->lasttxf = gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqUp));
+ set_freq_simplex (ctrl, ctrl->lasttxf);
+ break;
+ case RIG_TYPE_TRX:
+ case RIG_TYPE_DUPLEX:
+ if (get_ptt (ctrl)) {
+ ctrl->lasttxf = gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqUp));
+ set_freq_simplex (ctrl, ctrl->lasttxf);
+ }
+ else {
+ ctrl->lastrxf = gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqDown));
+ set_freq_simplex (ctrl, ctrl->lastrxf);
+ }
+ break;
+ default:
+ /* this is an error! */
+ ctrl->conf->type = RIG_TYPE_RX;
+ ctrl->lastrxf = gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqDown));
+ set_freq_simplex (ctrl, ctrl->lastrxf);
+ break;
+ }
}
}
@@ -830,7 +872,6 @@
rig_ctrl_timeout_cb (gpointer data)
{
GtkRigCtrl *ctrl = GTK_RIG_CTRL (data);
- gdouble satfreq,doppler,lof,readfreq=0,lastfreq;
if (ctrl->busy) {
@@ -840,92 +881,395 @@
ctrl->busy = TRUE;
+ /* Execute controller cycle depending on radio type */
+ switch (ctrl->conf->type) {
+
+ case RIG_TYPE_RX:
+ exec_rx_cycle (ctrl);
+ break;
+
+ case RIG_TYPE_TX:
+ exec_tx_cycle (ctrl);
+ break;
+
+ case RIG_TYPE_TRX:
+ exec_trx_cycle (ctrl);
+ break;
+
+ case RIG_TYPE_DUPLEX:
+ exec_duplex_cycle (ctrl);
+ break;
+
+ default:
+ /* invalid mode */
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s: Invalid radio type %d. Setting type to RIG_TYPE_RX"),
+ __FUNCTION__, ctrl->conf->type);
+ ctrl->conf->type = RIG_TYPE_RX;
+
+ }
+ //g_print (" WROPS = %d\n", ctrl->wrops);
- // TODO
- lof = 0.0; //1.0e6*gtk_spin_button_get_value (GTK_SPIN_BUTTON (ctrl->LO));
+ ctrl->busy = FALSE;
+
+ return TRUE;
+}
+
+/** \brief Execute RX mode cycle.
+ * \param ctrl Pointer to the GtkRigCtrl widget.
+ *
+ * This function executes a controller cycle when the device is of RIG_TYPE_RX.
+ */
+static void exec_rx_cycle (GtkRigCtrl *ctrl)
+{
+ gdouble readfreq=0.0, tmpfreq, satfreqd, satfrequ, doppler;
+ gboolean ptt = FALSE;
+ gboolean dialchanged = FALSE;
+
+
/* Dial feedback:
If radio device is engaged read frequency from radio and compare it to the
last set frequency. If different, it means that user has changed frequency
on the radio dial => update transponder knob
*/
if (ctrl->engaged) {
- lastfreq = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->RigFreqDown));
+ // This is no good because it gets out of sync while PTT = ON
+ //lastfreq = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->RigFreqDown));
- /* get current frequency from rig */
- if (!get_freq_simplex (ctrl, &readfreq)) {
- /* error => use a passive value */
- readfreq = lastfreq;
+ /* check whether PTT is ON */
+ ptt = ctrl->conf->ptt ? get_ptt (ctrl) : FALSE;
+
+ if (ptt == FALSE) {
+ if (!get_freq_simplex (ctrl, &readfreq)) {
+ /* error => use a passive value */
+ readfreq = ctrl->lastrxf;
+ ctrl->errcnt++;
+ }
}
+ else {
+ readfreq = ctrl->lastrxf;
+ }
- if (fabs (readfreq - lastfreq) > 0.99) {
+ if (fabs (readfreq - ctrl->lastrxf) > 0.99) {
+ dialchanged = TRUE;
+
/* user might have altered radio frequency => update transponder knob */
gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown), readfreq);
/* doppler shift; only if we are tracking */
if (ctrl->tracking) {
- satfreq = (readfreq+lof) / (1 - (ctrl->target->range_rate/299792.4580));
+ satfreqd = (readfreq + ctrl->conf->lo) /
+ (1 - (ctrl->target->range_rate/299792.4580));
}
else {
- satfreq = readfreq + lof;
+ satfreqd = readfreq + ctrl->conf->lo;
}
- gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->SatFreqDown), satfreq);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->SatFreqDown), satfreqd);
+
+ /* TODO Update uplink if locked to downlink */
}
}
-
+
+ /* TODO: Follow with uplink if transponder is locked */
+
/* now, forward tracking */
+ if (dialchanged) {
+ /* no need to forward track */
+ return;
+ }
/* If we are tracking, calculate the radio freq by applying both dopper shift
- and tranverter LO frequency.
- If we are not tracking, apply only LO frequency.
+ and tranverter LO frequency. If we are not tracking, apply only LO frequency.
*/
+ satfreqd = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqDown));
+ satfrequ = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqUp));
if (ctrl->tracking) {
- satfreq = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqDown));
- doppler = -satfreq * (ctrl->target->range_rate / 299792.4580);
- gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown), satfreq+doppler-lof);
+ /* downlink */
+ doppler = -satfreqd * (ctrl->target->range_rate / 299792.4580);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown),
+ satfreqd + doppler - ctrl->conf->lo);
+ /* uplink */
+ doppler = -satfrequ * (ctrl->target->range_rate / 299792.4580);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqUp),
+ satfrequ + doppler - ctrl->conf->lo);
}
else {
- satfreq = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqDown));
- gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown), satfreq-lof);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown),
+ satfreqd - ctrl->conf->lo);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqUp),
+ satfrequ - ctrl->conf->lo);
}
-
+ tmpfreq = gtk_freq_knob_get_value(GTK_FREQ_KNOB(ctrl->RigFreqDown));
+
/* if device is engaged, send freq command to radio */
- if ((ctrl->engaged) &&
- (fabs (readfreq-gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqDown))) > 0.99)) {
- if (set_freq_simplex (ctrl, gtk_freq_knob_get_value (GTK_FREQ_KNOB(ctrl->RigFreqDown)))) {
+ if ((ctrl->engaged) && (ptt == FALSE) && (fabs(ctrl->lastrxf - tmpfreq) > 0.99)) {
+ if (set_freq_simplex (ctrl, tmpfreq)) {
/* reset error counter */
ctrl->errcnt = 0;
+ ctrl->lastrxf = tmpfreq;
}
else {
- if (ctrl->errcnt >= MAX_ERROR_COUNT) {
- /* disengage device */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ctrl->LockBut), FALSE);
- ctrl->engaged = FALSE;
- ctrl->errcnt = 0;
- sat_log_log (SAT_LOG_LEVEL_ERROR,
- _("%s: MAX_ERROR_COUNT (%d) reached. Disengaging device!"),
- __FUNCTION__, MAX_ERROR_COUNT);
-
- //g_print ("ERROR. WROPS = %d\n", ctrl->wrops);
+ ctrl->errcnt++;
+ }
+ }
+
+ if (ctrl->errcnt >= MAX_ERROR_COUNT) {
+ /* disengage device */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ctrl->LockBut), FALSE);
+ ctrl->engaged = FALSE;
+ ctrl->errcnt = 0;
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s: MAX_ERROR_COUNT (%d) reached. Disengaging device!"),
+ __FUNCTION__, MAX_ERROR_COUNT);
+
+ //g_print ("ERROR. WROPS = %d\n", ctrl->wrops);
+ }
+}
+
+
+/** \brief Execute TX mode cycle.
+ * \param ctrl Pointer to the GtkRigCtrl widget.
+ *
+ * This function executes a controller cycle when the device is of RIG_TYPE_TX.
+ */
+static void exec_tx_cycle (GtkRigCtrl *ctrl)
+{
+ gdouble readfreq=0.0, tmpfreq, satfreqd, satfrequ, doppler;
+ gboolean ptt = FALSE;
+ gboolean dialchanged = FALSE;
+
+
+ /* Dial feedback:
+ If radio device is engaged read frequency from radio and compare it to the
+ last set frequency. If different, it means that user has changed frequency
+ on the radio dial => update transponder knob
+ */
+ if (ctrl->engaged) {
+ // This is no good because it gets out of sync while PTT = ON
+ //lastfreq = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->RigFreqDown));
+
+ /* check whether PTT is ON */
+ ptt = ctrl->conf->ptt ? get_ptt (ctrl) : FALSE;
+
+ if (ptt == TRUE) {
+ if (!get_freq_simplex (ctrl, &readfreq)) {
+ /* error => use a passive value */
+ readfreq = ctrl->lasttxf;
+ ctrl->errcnt++;
}
+ }
+ else {
+ readfreq = ctrl->lasttxf;
+ }
+
+ if (fabs (readfreq - ctrl->lasttxf) > 0.99) {
+ dialchanged = TRUE;
+
+ /* user might have altered radio frequency => update transponder knob */
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqUp), readfreq);
+
+ /* doppler shift; only if we are tracking */
+ if (ctrl->tracking) {
+ satfrequ = (readfreq + ctrl->conf->loup) /
+ (1 - (ctrl->target->range_rate/299792.4580));
+ }
else {
- /* increment error counter */
- ctrl->errcnt++;
+ satfrequ = readfreq + ctrl->conf->loup;
}
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->SatFreqUp), satfrequ);
+
+ /* TODO Update downlink if locked to uplink */
}
}
+
+ /* TODO: Follow with downlink if transponder is locked */
+
+ /* now, forward tracking */
+ if (dialchanged) {
+ /* no need to forward track */
+ return;
+ }
- //g_print (" WROPS = %d\n", ctrl->wrops);
+ /* If we are tracking, calculate the radio freq by applying both dopper shift
+ and tranverter LO frequency. If we are not tracking, apply only LO frequency.
+ */
+ satfreqd = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqDown));
+ satfrequ = gtk_freq_knob_get_value (GTK_FREQ_KNOB (ctrl->SatFreqUp));
+ if (ctrl->tracking) {
+ /* downlink */
+ doppler = -satfreqd * (ctrl->target->range_rate / 299792.4580);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown),
+ satfreqd + doppler - ctrl->conf->lo);
+ /* uplink */
+ doppler = -satfrequ * (ctrl->target->range_rate / 299792.4580);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqUp),
+ satfrequ + doppler - ctrl->conf->lo);
+ }
+ else {
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqDown),
+ satfreqd - ctrl->conf->lo);
+ gtk_freq_knob_set_value (GTK_FREQ_KNOB (ctrl->RigFreqUp),
+ satfrequ - ctrl->conf->lo);
+ }
+
+ tmpfreq = gtk_freq_knob_get_value(GTK_FREQ_KNOB(ctrl->RigFreqUp));
+
+ /* if device is engaged, send freq command to radio */
+ if ((ctrl->engaged) && (ptt == TRUE) && (fabs(ctrl->lasttxf - tmpfreq) > 0.99)) {
+ if (set_freq_simplex (ctrl, tmpfreq)) {
+ /* reset error counter */
+ ctrl->errcnt = 0;
+ ctrl->lasttxf = tmpfreq;
+ }
+ else {
+ ctrl->errcnt++;
+ }
+ }
- ctrl->busy = FALSE;
+ if (ctrl->errcnt >= MAX_ERROR_COUNT) {
+ /* disengage device */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ctrl->LockBut), FALSE);
+ ctrl->engaged = FALSE;
+ ctrl->errcnt = 0;
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s: MAX_ERROR_COUNT (%d) reached. Disengaging device!"),
+ __FUNCTION__, MAX_ERROR_COUNT);
+
+ //g_print ("ERROR. WROPS = %d\n", ctrl->wrops);
+ }
+
+}
+
+
+/** \brief Execute simplex mode cycle.
+ * \param ctrl Pointer to the GtkRigCtrl widget.
+ *
+ * This function executes a controller cycle when the device is of RIG_TYPE_TRX (simplex).
+ */
+static void exec_trx_cycle (GtkRigCtrl *ctrl)
+{
+
+}
+
+
+/** \brief Execute duplex mode cycle.
+ * \param ctrl Pointer to the GtkRigCtrl widget.
+ *
+ * This function executes a controller cycle when the device is of RIG_TYPE_DUPLEX.
+ */
+static void exec_duplex_cycle (GtkRigCtrl *ctrl)
+{
+ //FIXME implement
+ exec_trx_cycle (ctrl);
+}
+
+
+/** \brief Get PTT status
+ * \param ctrl Pointer to the GtkRigVtrl widget.
+ * \return TRUE if PTT is ON, FALSE if PTT is OFF or an error occurred.
+ *
+ */
+static gboolean get_ptt (GtkRigCtrl *ctrl)
+{
+ gchar *buff,**vbuff;
+ gint written,size;
+ gint status;
+ struct hostent *h;
+ struct sockaddr_in ServAddr;
+ gint sock; /*!< Network socket */
+ guint64 pttstat = 0;
+
- return TRUE;
+ /* create socket */
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0) {
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s:%d: Failed to create socket"),
+ __FILE__, __LINE__);
+ return FALSE;
+ }
+ else {
+ sat_log_log (SAT_LOG_LEVEL_DEBUG,
+ _("%s:%d Network socket created successfully"),
+ __FILE__, __LINE__);
+ }
+
+ memset(&ServAddr, 0, sizeof(ServAddr)); /* Zero out structure */
+ ServAddr.sin_family = AF_INET; /* Internet address family */
+ h = gethostbyname(ctrl->conf->host);
+ memcpy((char *) &ServAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+ ServAddr.sin_port = htons(ctrl->conf->port); /* Server port */
+
+ /* establish connection */
+ status = connect(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr));
+ if (status < 0) {
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s:%d: Failed to connect to %s:%d"),
+ __FILE__, __LINE__, ctrl->conf->host, ctrl->conf->port);
+ return FALSE;
+ }
+ else {
+ sat_log_log (SAT_LOG_LEVEL_DEBUG,
+ _("%s:%d: Connection opened to %s:%d"),
+ __FILE__, __LINE__, ctrl->conf->host, ctrl->conf->port);
+ }
+
+ /* send command (get_ptt: t) */
+ buff = g_strdup_printf ("t");
+
+ size = 1;
+ written = send(sock, buff, size, 0);
+ if (written != size) {
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s:%d: SIZE ERROR %d / %d"),
+ __FILE__, __LINE__, written, size);
+ }
+ g_free (buff);
+
+
+ /* try to read answer */
+ buff = g_try_malloc (128);
+ if (buff == NULL) {
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s:%s: Failed to allocate 128 bytes (yes, this means trouble)"),
+ __FILE__, __FUNCTION__);
+ shutdown (sock, SHUT_RDWR);
+ close (sock);
+ return FALSE;
+ }
+
+ size = read (sock, buff, 127);
+ if (size == 0) {
+ sat_log_log (SAT_LOG_LEVEL_ERROR,
+ _("%s:%s: Got 0 bytes from rigctld"),
+ __FILE__, __FUNCTION__);
+ }
+ else {
+ sat_log_log (SAT_LOG_LEVEL_DEBUG,
+ _("%s:%s: Read %d bytes from rigctld"),
+ __FILE__, __FUNCTION__, size);
+
+ buff[size] = 0;
+ vbuff = g_strsplit (buff, "\n", 3);
+ pttstat = g_ascii_strtoull (vbuff[0], NULL, 0); //FIXME base = 0 ok?
+
+ g_free (buff);
+ g_strfreev (vbuff);
+ }
+
+ shutdown (sock, SHUT_RDWR);
+ close (sock);
+
+
+ return (pttstat == 1) ? TRUE : FALSE;
+
}
-/** \brief Set frequency in
+/** \brief Set frequency in simplex mode
* \param ctrl Pointer to the GtkRigCtrl structure.
* \param freq The new frequency.
* \return TRUE if the operation was successful, FALSE if a connection error
Modified: trunk/src/gtk-rig-ctrl.h
===================================================================
--- trunk/src/gtk-rig-ctrl.h 2009-03-29 21:33:48 UTC (rev 215)
+++ trunk/src/gtk-rig-ctrl.h 2009-03-29 21:34:58 UTC (rev 216)
@@ -94,7 +94,10 @@
gboolean busy; /*!< Flag set when control algorithm is busy. */
gboolean engaged; /*!< Flag indicating that rig device is engaged. */
gint errcnt; /*!< Error counter. */
-
+
+ gdouble lastrxf; /*!< Last frequency sent to receiver. */
+ gdouble lasttxf; /*!< Last frequency sent to tranmitter. */
+
/* debug related */
guint wrops;
guint rdops;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|