Monthly Archives: February 2026

Bandmaster V info widget

Wrote the following info widget for Bandmaster V (Linux):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <qt6/libqt6c.h>

// Define the antenna names
#define ANTENNA1 "6m beam"
#define ANTENNA2 "WARC beam"
#define ANTENNA3 "Stack"
#define ANTENNA4 "40m beam"
#define ANTENNA5 "No antenna"
#define ANTENNA6 "No antenna"
#define ANTENNA7 "No antenna"
#define ANTENNA8 "No antenna"
#define ANTENNA9 "No antenna"
#define ANTENNA10 "No antenna"
#define ANTENNA11 "No antenna"
#define ANTENNA12 "No antenna"

#define DEVICE "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_B003ISA1-if00-port0"

int fd;
void *widget, *label;

int read_untilcr(int fd, char *buf, int maxlen) {

int pos = 0, bytes_rd;

while(1) {
if((bytes_rd = read(fd, buf + pos, 1)) < 0) return -1;
if(bytes_rd == 0) {
sleep(1); // could be less than 1sec
continue;
}
if(!pos && (*buf == '\r' || *buf == '\n')) continue;
if(pos == maxlen) return -1;
if(buf[pos] == '\r') break;
pos++;
}
buf[pos] = '\0';
return pos;
}

void set_tty() {

struct termios param;

if(tcgetattr(fd, &param) < 0) {
fprintf(stderr, "Status get failed.\n");
exit(1);
}

param.c_cflag &= ~PARENB;
param.c_cflag &= ~CSTOPB;
param.c_cflag |= CS8;
param.c_cflag &= ~CRTSCTS;
param.c_cflag |= CREAD | CLOCAL;
param.c_lflag &= ~ICANON;
param.c_lflag &= ~ECHO;
param.c_lflag &= ~ECHOE;
param.c_lflag &= ~ECHONL;
param.c_lflag &= ~ISIG;
param.c_iflag &= ~(IXON | IXOFF | IXANY);
param.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
param.c_oflag &= ~OPOST;
param.c_oflag &= ~ONLCR;
cfsetispeed(&param, B57600);
cfsetospeed(&param, B57600);

if(tcsetattr(fd, TCSANOW, &param) < 0) {
fprintf(stderr, "Status set failed.\n");
exit(1);
}
}

char *txt_noant = "<b><font color='red'>No antenna.</font></b>",
*txt_40m = "<b><font color='blue'>40m beam.</font></b>",
*txt_warc = "<b><font color='blue'>WARC beam.</font></b>",
*txt_stack = "<b><font color='blue'>Stack.</font></b>",
*txt_6m = "<b><font color='blue'>6m beam.</font></b>";

void update_band_info(void *asd) {

int len, antenna, relay;
char buf[512];

if((len = read_untilcr(fd, buf, sizeof(buf))) < 0) {
fprintf(stderr, "Read error.\n");
exit(1);
}
if(sscanf(buf, "[TC4RFA29H00M0%1d01EEEEEEEEEEEE%4d]", &antenna, &relay) != 2) return; // Some other mesg

switch(antenna) {
case 1:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA1, relay);
q_label_set_text(label, buf);
break;
case 2:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA2, relay);
q_label_set_text(label, buf);
break;
case 3:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA3, relay);
q_label_set_text(label, buf);
break;
case 4:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA4, relay);
q_label_set_text(label, buf);
break;
case 5:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA5, relay);
q_label_set_text(label, buf);
break;
case 6:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA6, relay);
q_label_set_text(label, buf);
break;
case 7:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA7, relay);
q_label_set_text(label, buf);
break;
case 8:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA8, relay);
q_label_set_text(label, buf);
break;
case 9:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA9, relay);
q_label_set_text(label, buf);
break;
case 10:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA10, relay);
q_label_set_text(label, buf);
break;
case 11:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA11, relay);
q_label_set_text(label, buf);
break;
case 12:
sprintf(buf, "<b><font color='blue'>%s (%d)</font></b>", ANTENNA12, relay);
q_label_set_text(label, buf);
break;
default:
q_label_set_text(label, "<b><font color='red'>Unknown antennan.</font></b>");
}
}

int main(int argc, char *argv[]) {

QApplication *app;
QTimer *timer;

if((fd = open(DEVICE, O_RDONLY)) < 0) {
fprintf(stderr, "Can't open device.\n");
exit(1);
}
set_tty();

app = q_application_new(&argc, argv);
widget = q_widget_new2();
timer = q_timer_new2(widget);
q_widget_set_window_title(widget, "Antenna selection");
q_widget_resize(widget, 150, 30);
label = q_label_new5("------------------------------", widget);
q_label_set_alignment(label, QT_ALIGNMENTFLAG_ALIGNCENTER);
q_label_set_text_format(label, QT_TEXTFORMAT_RICHTEXT);
q_timer_start(timer, 100);
q_timer_on_timeout(timer, update_band_info);
q_widget_show(widget);
(void) q_application_exec();
q_widget_delete(widget);
q_application_delete(app);

close(fd);
}

Uses libqt6c (QT bindings for C).