pull/58/head
pa3gsb 2024-04-16 08:37:26 +02:00
rodzic 80f256ab91
commit 64c4cf1a13
18 zmienionych plików z 1908 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,50 @@
CC=gcc
LINK=gcc
INSTALL = install
BLDDIR = $(BUILDDIR:%=%/)
OPTIONS=-g -O3
LIBS=-lrt -lm -lpthread
COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
PROGRAM=$(BLDDIR)radioberry
SOURCES= \
measure.c \
bias.c \
register.c \
radioberry.c
HEADERS= \
measure.h \
bias.h \
radioberry.h \
radioberry_ioctl.h \
register.h
OBJS= \
register.o \
bias.o \
measure.o \
radioberry.o
all: prebuild $(PROGRAM) | $(HEADERS) $(SOURCES)
prebuild:
rm -f version.o
$(PROGRAM): $(OBJS:%.o=$(BLDDIR)%.o)
$(LINK) -o $(PROGRAM) $^ $(LIBS)
$(BLDDIR)%.o: %.c
$(COMPILE) -c -o $@ $<
clean:
-rm -f $(BLDDIR)*.o
-rm -f $(PROGRAM)
install: $(PROGRAM)
$(INSTALL) $(PROGRAM) $(DESTDIR)/usr/local/bin

Wyświetl plik

@ -0,0 +1,38 @@
#include "bias.h"
#include <sys/ioctl.h>
static int fd_i2c_bias;
static int i2c_bias_handler;
void init_I2C_bias(void) {
fd_i2c_bias = open("/dev/i2c-1", O_RDWR);
if (fd_i2c_bias < 0 ) {
fprintf(stderr, "Your SBC device is missing the following driver: '/dev/i2c-1' \n");
fprintf(stderr, "Change of Bias Setting is not possible\n");
return ;// fd_i2c_bias;
}
i2c_bias_handler = ioctl(fd_i2c_bias, I2C_SLAVE, ADDR_BIAS);
if (i2c_bias_handler < 0) close(i2c_bias_handler);
}
void write_I2C_bias(uint8_t control, uint8_t data) {
uint8_t bias_data[2];
bias_data[0] = control;
bias_data[1] = data;
int result = write(fd_i2c_bias, bias_data, 2);
if (result == 2) fprintf(stderr, "Write I2C Bias command %02X value= %02X \n", control, bias_data[1]);
else fprintf(stderr, "Write I2C Bias command failed \n");
}
void close_I2C_bias(void) {
if (fd_i2c_bias >= 0) close(fd_i2c_bias);
}
//end of source

Wyświetl plik

@ -0,0 +1,37 @@
#ifndef __RADIOBERRY_BIAS_H__
#define __RADIOBERRY_BIAS_H__
/**
MCP4662 Dual digital potentiometer.
This device is used to set both bias settings for the Radioberry preAmp.
The setting can be made permanent (non volatile) by saving the bias values in the EEPROM of the device.
The bias is a specific setting stored and determined specific per preAmp board.
The setting can be done by QUISK or SparkSDR using the extended Protocol-1 for Hermes Lite
https://github.com/softerhardware/Hermes-Lite2/wiki/Protocol
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#define ADDR_BIAS 0x2C
void openI2C_bias(void);
void write_I2C_bias(uint8_t control, uint8_t data);
void close_I2C_bias(void);
void init_I2C_bias(void);
#endif

Wyświetl plik

@ -0,0 +1,385 @@
#ifndef __RADIOBERRY_FILTERS_H__
#define __RADIOBERRY_FILTERS_H__
//***********************************************************************************
// Filters Board interface
//
// transport: I2C
// Protocols: Alex Board && VA2SAJ Generic Filters Interface && N2ADR board.
//
//***********************************************************************************
// Johan, PA3GSB modified using a i2c device; making it less platform dependent.
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <errno.h>
int fd_i2c_alex;
int fd_i2c_filter;
int fd_i2c_n2adr;
#define ADDR_N2ADR 0x20 /* N2ADR is controlled using mcp23008*/
#define ADDR_ALEX 0x21 /* PCA9555 address 1 for Alex Interface Board*/
#define ADDR_FILTERS 0x22 /* Arduino filter board interface switcher address for VA2SAJ Generic Filter Switching Board*/
int i2c_n2adr_handler = 0;
int i2c_alex_handler = 0;
int i2c_filters_board_handler = 0;
int i2c_n2adr = 0;
int i2c_alex = 0;
int i2c_filters_board = 0;
int alex_manual = 0;
uint16_t i2c_alex_data = 0;
uint16_t i2c_n2adr_data = 0;
uint16_t i2c_data = 0;
unsigned int i2c_bus = 1;
int currentfreq = 4706000;
int previousfreq = 0;
int currentMox = 0;
int previousMox = -1;
int currentCW = 0;
int previousCW = -1;
//****************************************
// Initializing Alex Interface
//****************************************
static inline void initALEX(void) {
int result = 0;
unsigned char data[3];
/* configure all pins as output */
data[0] = 0x06;
data[1] = 0x00;
data[2] = 0x00;
result = write(fd_i2c_alex, data, 3);
if (result >= 0) {
data[0] = 0x02;
data[1] = 0x00;
data[2] = 0x00;
/* set all pins to low */
result = write(fd_i2c_alex, data, 3);
}
if (result >= 0) {
i2c_alex = 1;
}
}
//*********************************************
// Initializing Generic filters Interface
//*********************************************
static inline void initGenericFilters(void) {
int result = 0;
unsigned char data[3];
/* configure all pins as output */
data[0] = 0x02;
data[1] = 0x02;
data[2] = 0x01;
result = write(fd_i2c_filter, data, 3);
if (result >= 0) {
data[0] = 0x02;
data[1] = 0x02;
data[2] = 0x03;
/* set all pins to low */
result = write(fd_i2c_filter, data, 3);
}
if (result >= 0) {
i2c_filters_board = 1;
}
}
//****************************************
// Initializing Alex Interface
//****************************************
static inline void initN2ADR(void) {
int result = 0;
unsigned char data[2];
/* configure all pins as output */
data[0] = 0x00;
data[1] = 0x00;
result = write(fd_i2c_n2adr, data, 2);
if (result >= 0) {
data[0] = 0x09;
data[1] = 0x00;
/* set all pins to low */
result = write(fd_i2c_n2adr, data, 2);
}
if (result >= 0) {
i2c_n2adr = 1;
}
}
//****************************************************************
// Handle data to N2ADR Filter Board
//
// https://github.com/softerhardware/Hermes-Lite2/wiki/Protocol
//
// Look for Filter Selection description.
//****************************************************************
static inline void handleN2ADRFilterBoard(char* buffer)
{
if (i2c_n2adr & (buffer[523] & 0xFE) == 0x00) {
i2c_n2adr_data = ((buffer[526] & 0x20) << 1) | ((buffer[525] & 0xFE) >> 1);
}
if (i2c_n2adr & (buffer[11] & 0xFE) == 0x00) {
i2c_n2adr_data = ((buffer[14] & 0x20) << 1) | ((buffer[13] & 0xFE) >> 1);
}
if (i2c_n2adr) {
if (i2c_data != i2c_n2adr_data)
{
i2c_data = i2c_n2adr_data;
unsigned char ldata[2];
ldata[0] = 0x09;
ldata[1] = i2c_n2adr_data & 0xFF;
fprintf(stderr, "Set N2ADR data = %x \n", ldata[1]);
if(write(fd_i2c_n2adr, ldata, 2) < 0)
fprintf(stderr, "Error %d setting N2ADR data\n", errno);
}
}
}
//*******************************************
// Handle data to Alex Interface Board
//*******************************************
static inline void handleALEX(char* buffer)
{
if (i2c_alex & ((buffer[523] & 0xFE) == 0x12) || ((buffer[11] & 0xFE) == 0x12)) {
if (((buffer[525] & 0x40) == 0x40) ? 1 : 0) {
i2c_alex_data = ((buffer[526] & 0x8F) << 8) | (buffer[527] & 0xFF);
} else if ((((buffer[13] & 0x40) == 0x40) ? 1 : 0)) {
i2c_alex_data = ((buffer[14] & 0x8F) << 8) | (buffer[15] & 0xFF);
}
else {
//firmware does determine the filter.
uint16_t hpf = 0, lpf = 0;
if (currentfreq < 1416000) hpf = 0x20; /* bypass */
else if (currentfreq < 6500000) hpf = 0x10; /* 1.5 MHz HPF */
else if (currentfreq < 9500000) hpf = 0x08; /* 6.5 MHz HPF */
else if (currentfreq < 13000000) hpf = 0x04; /* 9.5 MHz HPF */
else if (currentfreq < 20000000) hpf = 0x01; /* 13 MHz HPF */
else hpf = 0x02; /* 20 MHz HPF */
if (currentfreq > 32000000) lpf = 0x10; /* bypass */
else if (currentfreq > 22000000) lpf = 0x20; /* 12/10 meters */
else if (currentfreq > 15000000) lpf = 0x40; /* 17/15 meters */
else if (currentfreq > 8000000) lpf = 0x01; /* 30/20 meters */
else if (currentfreq > 4500000) lpf = 0x02; /* 60/40 meters */
else if (currentfreq > 2400000) lpf = 0x04; /* 80 meters */
else lpf = 0x08; /* 160 meters */
i2c_alex_data = hpf << 8 | lpf;
}
}
if (i2c_alex)
{
if (i2c_data != i2c_alex_data)
{
fprintf(stderr, "Set Alex data to output = %d \n", i2c_alex_data);
i2c_data = i2c_alex_data;
unsigned char ldata[3];
ldata[0] = 0x02;
ldata[1] = ((i2c_alex_data >> 8) & 0xFF);
ldata[2] = (i2c_alex_data & 0xFF);
fprintf(stderr, "Set Alex data 0 = %x \n", ldata[0]);
fprintf(stderr, "Set Alex data 1 = %x \n", ldata[1]);
fprintf(stderr, "Set Alex data 2 = %x \n", ldata[2]);
if (write(fd_i2c_alex, ldata, 3) < 0)
fprintf(stderr, "Error %d writing Alex data\n", errno);
}
}
}
//************************************************************************************************************************************
// Handle data for Generic Filters Interface Board.
// Unlike Alex Interface, generic board uses frequency as data to send.
// This allow easier integration for different lpf, bpf filter interface that didn't match Alex interface filters groups.
// This also allow easier integration for different countries band plan because the band plan is defined in the arduino firmware.
//************************************************************************************************************************************
static inline void handleFiltersBoard(char* buffer, int cw)
{
//***********************************************
// Send Band Selected Alex board Style
//***********************************************
if (i2c_filters_board & (buffer[523] & 0xFE) == 0x12) {
alex_manual = ((buffer[525] & 0x40) == 0x40) ? 1 : 0;
if (alex_manual) {
i2c_alex_data = ((buffer[526] & 0x8F) << 8) | (buffer[527] & 0xFF);
} else {
//firmware does determine the filter.
uint16_t hpf = 0, lpf = 0;
if (currentfreq < 1416000) hpf = 0x20; /* bypass */
else if (currentfreq < 6500000) hpf = 0x10; /* 1.5 MHz HPF */
else if (currentfreq < 9500000) hpf = 0x08; /* 6.5 MHz HPF */
else if (currentfreq < 13000000) hpf = 0x04; /* 9.5 MHz HPF */
else if (currentfreq < 20000000) hpf = 0x01; /* 13 MHz HPF */
else hpf = 0x02; /* 20 MHz HPF */
if (currentfreq > 32000000) lpf = 0x10; /* bypass */
else if (currentfreq > 22000000) lpf = 0x20; /* 12/10 meters */
else if (currentfreq > 15000000) lpf = 0x40; /* 17/15 meters */
else if (currentfreq > 8000000) lpf = 0x01; /* 30/20 meters */
else if (currentfreq > 4500000) lpf = 0x02; /* 60/40 meters */
else if (currentfreq > 2400000) lpf = 0x04; /* 80 meters */
else lpf = 0x08; /* 160 meters */
i2c_alex_data = hpf << 8 | lpf;
}
}
if (i2c_filters_board) {
if (i2c_data != i2c_alex_data) {
i2c_data = i2c_alex_data;
unsigned char ldata[3];
ldata[0] = 0x02;
ldata[1] = ((i2c_alex_data >> 8) & 0xFF);
ldata[2] = (i2c_alex_data & 0xFF);
if (write(fd_i2c_filter, ldata, 3) < 0)
fprintf(stderr, "Error %d writing Alex data\n", errno);
fprintf(stderr, "Set Alex data 0 = %x \n", ldata[0]);
fprintf(stderr, "Set Alex data 1 = %x \n", ldata[1]);
fprintf(stderr, "Set Alex data 2 = %x \n", ldata[2]);
}
}
//*************************************************
// Send Mox Status
//*************************************************
if (i2c_filters_board & ((buffer[11] & 0x01) == 0x01 || (buffer[11] & 0x01) == 0x00)) {
currentMox = ((buffer[11] & 0x01) == 0x01) ? 1 : 0;
currentCW = cw;
if (currentMox != previousMox || currentCW != previousCW) {
previousMox = currentMox;
previousCW = currentCW;
unsigned char ldata[3];
ldata[0] = 0x03;
ldata[1] = ((buffer[11] & 0x01) == 0x01) ? 1 : 0;
ldata[2] = currentCW;
if (write(fd_i2c_filter, ldata, 3) < 0)
fprintf(stderr, "Error %d writing Alex data\n", errno);
fprintf(stderr, "PTT data 0 = %x \n", ldata[0]);
fprintf(stderr, "PTT data 1 = %x \n", ldata[1]);
fprintf(stderr, "PTT data 2 = %x \n", ldata[2]);
}
}
//*************************************************
// Send Frenquency to filter companion
//*************************************************
if (i2c_filters_board & (buffer[523] & 0xFE) == 0x12) {
if (currentfreq != previousfreq) {
previousfreq = currentfreq;
unsigned tempFreq = currentfreq;
unsigned char ldata[9];
ldata[0] = 0x04;
ldata[1] = (tempFreq / 10000000U) % 10;
ldata[2] = (tempFreq / 1000000U) % 10;
ldata[3] = (tempFreq / 100000U) % 10;
ldata[4] = (tempFreq / 10000U) % 10;
ldata[5] = (tempFreq / 1000U) % 10;
ldata[6] = (tempFreq / 100U) % 10;
ldata[7] = (tempFreq / 10U) % 10;
ldata[8] = (tempFreq / 1U) % 10;
if (write(fd_i2c_filter, ldata, 9) < 0)
fprintf(stderr, "Error %d setting frequency \n", errno);
else
fprintf(stderr, "Set Filters frequency to = %d \n", currentfreq);
}
}
}
//*******************************************
// Convert frequency value to integer
//*******************************************
static inline int determine_freq(int base_index, char* buffer) {
return (((buffer[base_index + 1] & 0xFF) << 24) + ((buffer[base_index + 2] & 0xFF) << 16) + ((buffer[base_index + 3] & 0xFF) << 8) + (buffer[base_index + 4] & 0xFF));
}
//**********************************************************
// Determine which board to forward data - Alex or Generic
//**********************************************************
static inline void handleFilters(char* buffer, int cw) {
if ((buffer[11] & 0xFE) == 0x04) {
currentfreq = determine_freq(11, buffer);
};
if ((buffer[523] & 0xFE) == 0x04) {
currentfreq = determine_freq(523, buffer);
};
if (i2c_alex) {
handleALEX(buffer);
}
else if (i2c_filters_board) {
handleFiltersBoard(buffer,cw);
}
else if (i2c_n2adr) {
handleN2ADRFilterBoard(buffer);
}
}
//********************************************************************
// Determine which filters interface is connected to the radioberry
//********************************************************************
static inline void initFilters(void) {
fd_i2c_alex = open("/dev/i2c-1", O_RDWR);
fd_i2c_filter = open("/dev/i2c-1", O_RDWR);
fd_i2c_n2adr = open("/dev/i2c-1", O_RDWR);
if (fd_i2c_alex < 0 || fd_i2c_filter < 0 || fd_i2c_n2adr < 0) {
fprintf(stderr, "Your SBC device is missing the following driver: '/dev/i2c-1' \n");
fprintf(stderr, "To make use of an i2c speaking filterboard please load the driver first. \n");
return;
}
i2c_alex_handler = ioctl(fd_i2c_alex, I2C_SLAVE, ADDR_ALEX);
if (i2c_alex_handler >= 0) {
initALEX();
} else close(fd_i2c_alex);
i2c_filters_board_handler = ioctl(fd_i2c_filter, I2C_SLAVE, ADDR_FILTERS);
if (i2c_filters_board_handler >= 0) {
initGenericFilters();
} else close(fd_i2c_filter);
i2c_n2adr_handler = ioctl(fd_i2c_n2adr, I2C_SLAVE, ADDR_N2ADR);
if (i2c_n2adr_handler >= 0) {
initN2ADR();
} else close(fd_i2c_n2adr);
if (i2c_alex) {
fprintf(stderr, "alex interface found and initialized \n");
}
else if (i2c_filters_board) {
fprintf(stderr, "Generic filters board interface found and initialized \n");
}
else if (i2c_n2adr) {
fprintf(stderr, "N2ADR filter board interface found and initialized \n");
}
else {
fprintf(stderr, "No Alex, N2ADR or generic filters interface board connected to radioberry\n");
}
}
#endif

Wyświetl plik

@ -0,0 +1,51 @@
#include "measure.h"
#include <sys/ioctl.h>
int i2c_measure_module_active;
static int fd_i2c_measure;
static int i2c_measure_handler;
int config_I2C_measure(void){
uint8_t measure_config[1];
measure_config[0] = 0x07;
int result = write(fd_i2c_measure, measure_config, 1);
if (result == 1) fprintf(stderr, "Write Config to MAX11613 a 4 Channel ADC\n");
else fprintf(stderr, "Radioberry amplifier config failed; only a problem if amplifier is installed. \n");
return result;
};
void openI2C_measure(void) {
i2c_measure_module_active = 0;
fd_i2c_measure = open("/dev/i2c-1", O_RDWR);
if (fd_i2c_measure < 0 ) {
fprintf(stderr, "Your SBC device is missing the following driver: '/dev/i2c-1' \n");
fprintf(stderr, "Measurement is not possible\n");
return;
}
i2c_measure_handler = ioctl(fd_i2c_measure, I2C_SLAVE, ADDR_MEAS);
if (i2c_measure_handler >=0) if (config_I2C_measure()==1) i2c_measure_module_active = 1; else close(i2c_measure_handler);
};
void read_I2C_measure(int *current, int *temperature){
uint8_t measure_data[8] ={0};
int result = read(fd_i2c_measure, measure_data, 8);
*temperature = (int)(((measure_data[2] & 0x0F) <<8) | measure_data[3]);
*current = (int)(((measure_data[4] & 0x0F) <<8) | measure_data[5]);
};
void close_I2C_measure(void) {
if (fd_i2c_measure >= 0) close(fd_i2c_measure);
};
//end of source

Wyświetl plik

@ -0,0 +1,36 @@
#ifndef __RADIOBERRY_MEASURE_H__
#define __RADIOBERRY_MEASURE_H__
/**
MAX11613 4 channel ADC.
For the radioberry preAmp this devices does measure the following analog signals:
- Current of the radioberry preamp fets.
- Temperature of the radioberry preamp fets.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#define ADDR_MEAS 0x34
extern int i2c_measure_module_active;
void openI2C_measure(void);
void read_I2C_measure(int *current, int *temperature);
void close_I2C_measure(void);
#endif

Wyświetl plik

@ -0,0 +1,606 @@
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
* This programs is the c part of the firmware for the RadioBerry.
*
* The belonging gateware can be found at: https://github.com/softerhardware/Hermes-Lite2
*
* **** Device Driver version. ****
*
* By using this program you have the possibility to connect to SDR programs like:
* - pihpsdr (including TCP)
* - Quisk
* - PSDR
* - SPARK
* - SDRConsole
*
* Using the 'HPSDR UDP protocol'; also called protocol-1
*
*
* http://www.pa3gsb.nl
*
* Johan PA3GSB
*
*/
#define NR 0x04
#define HERMESLITE 0x06
#include "radioberry_ioctl.h"
#include "radioberry.h"
#include "filters.h"
#include "register.h"
#include "bias.h"
#include "measure.h"
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printIntroScreen();
if (initRadioberry() < 0){
fprintf(stderr,"Radioberry; could not be initialized. \n");
exit(-1);
}
signal(SIGINT, handle_sigint);
runRadioberry();
closeRadioberry();
}
static void start_rb_control_thread(void);
static void start_rb_measure_thread(void);
static void start_rb_register_thread(void);
static void start_timer_thread(void);
static int initRadioberry(void) {
sem_init(&mutex, 0, 1);
sem_init(&tx_empty, 0, TX_MAX);
sem_init(&tx_full, 0, 0);
sem_init(&spi_msg, 0, 0);
sem_init(&i2c_meas, 0, 0);
gettimeofday(&t20, 0);
memset(commands,0,256); // initialise the commands.
if((fd_rb = open("/dev/radioberry", O_RDWR)) < 0){
perror("Failed to open /dev/radioberry");
exit(-1);
}
int init = 0;
do {
rb_info.command_data = 0x0;
//required to retrieve gateware information.
if (ioctl(fd_rb, RADIOBERRY_IOC_COMMAND, &rb_info) == -1) {
fprintf(stderr, "RADIOBERRY_IOC_COMMAND Error.");
exit(-1);
}
if (rb_info.major == 0) sleep(1);
init++;
} while (rb_info.major == 0 && init < 10);
gateware_major_version = rb_info.major;
gateware_minor_version = rb_info.minor;
fprintf(stderr, "Radioberry gateware version %d-%d.\n", rb_info.major, rb_info.minor);
gateware_fpga_type = rb_info.fpga;
driver_version = rb_info.version;
//***********************************************
// Filters switching initialization
//***********************************************
initFilters();
//***********************************************
init_I2C_bias();
openI2C_measure();
pthread_t pid1, pid2;
pthread_create(&pid1, NULL, packetreader, NULL);
pthread_create(&pid2, NULL, txWriter, NULL);
start_rb_control_thread();
start_rb_measure_thread();
/* create a UDP socket */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket\n");
return 0;
}
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = TIMEOUT_MS;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)) < 0)
perror("setsockopt failed\n");
int optval = 7; // high priority.
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &optval, sizeof(optval))<0) {
perror("fd socket: SO_PRIORITY");
}
/* bind the socket to any valid IP address and a specific port */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(SERVICE_PORT);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
if ((sock_TCP_Server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket tcp");
return -1;
}
int tcpmaxseg = 1032;
int yes = 1;
setsockopt(sock_TCP_Server, IPPROTO_TCP, TCP_MAXSEG, (const char *)&tcpmaxseg, sizeof(int));
int sndbufsize = 65535;
int rcvbufsize = 65535;
setsockopt(sock_TCP_Server, SOL_SOCKET, SO_SNDBUF, (const char *)&sndbufsize, sizeof(int));
setsockopt(sock_TCP_Server, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbufsize, sizeof(int));
setsockopt(sock_TCP_Server, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout)); //added
setsockopt(sock_TCP_Server, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
if (setsockopt(sock_TCP_Server, SOL_SOCKET, SO_PRIORITY, &optval, sizeof(optval))<0) {
perror("sock_TCP_Server socket: SO_PRIORITY");
}
if (bind(sock_TCP_Server, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0)
{
perror("bind tcp");
return -1;
}
listen(sock_TCP_Server, 1024);
int flags = fcntl(sock_TCP_Server, F_GETFL, 0);
fcntl(sock_TCP_Server, F_SETFL, flags | O_NONBLOCK);
start_rb_register_thread();
return 0;
}
static void closeRadioberry(void) {
if (fd_rb != 0) close(fd_rb);
if (sock_TCP_Client >= 0) close(sock_TCP_Client);
if (sock_TCP_Server >= 0) close(sock_TCP_Server);
close_I2C_bias();
close_I2C_measure();
}
static void runRadioberry(void) {
fprintf(stderr, "Radioberry, Starting packet control part. \n");
start_timer_thread();
fprintf(stderr, "Radioberry, Starting packet tx part. \n");
while(!(running==0 && closerb == 1)) {
if (running) {
active = 1;
sendPacket();
} else {active = 0; usleep(20000); }
}
}
static void *packetreader(void *arg) {
int size, bytes_read, bytes_left;
unsigned char buffer[2048];
uint32_t *code0 = (uint32_t *) buffer;
fprintf(stderr, "Radioberry, Starting packet rx part. \n");
while(1) {
if (sock_TCP_Client >= 0) {
// handle TCP protocol.
bytes_read=0;
bytes_left=1032;
while (bytes_left > 0) {
size = recvfrom(sock_TCP_Client, buffer+bytes_read, (size_t) bytes_left, 0, NULL, 0);
if (size < 0 && errno == EAGAIN) continue;
if (size < 0) break;
bytes_read += size;
bytes_left -= size;
}
if (bytes_read == 1032) handlePacket(buffer); else fprintf(stderr, "tcp packet received; wrong length %d \n", bytes_read);
}
else {
// handle UDP protocol.
int recvlen = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&remaddr, &addrlen);
if (recvlen > 0) { udp_retries = 0; handlePacket(buffer); } else udp_retries++;
// If nothing has arrived via UDP for some time (defined by socket timeout * 10) , try to open TCP connection.
if (sock_TCP_Client < 0 && udp_retries > 10)
{
if((sock_TCP_Client = accept(sock_TCP_Server, NULL, NULL)) > -1)
{
fprintf(stderr, "sock_TCP_Client: %d connected to sock_TCP_Server: %d\n", sock_TCP_Client, sock_TCP_Server);
}
udp_retries=0;
}
}
}
}
static void handlePacket(char* buffer){
uint32_t code;
memcpy(&code, buffer, 4);
switch (code)
{
default:
fprintf(stderr, "Received packages not for me! \n");
break;
case 0x0002feef:
fprintf(stderr, "Discovery packet received \n");
fprintf(stderr,"SDR Program IP-address %s \n", inet_ntoa(remaddr.sin_addr));
fprintf(stderr, "Discovery Port %d \n", ntohs(remaddr.sin_port));
memset(broadcastReply, 0, 60);
unsigned char reply[22] = {0xEF, 0xFE, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, gateware_major_version, HERMESLITE, 0, 0, 0, 0, 0, 0, 0, 0, NR, 0, gateware_minor_version };
memcpy(broadcastReply, reply, 22);
if (sock_TCP_Client > -1) {
send(sock_TCP_Client, broadcastReply, 60, 0);
close(sock_TCP_Client);
sock_TCP_Client = -1;
}
else if (sendto(fd, broadcastReply, sizeof(broadcastReply), 0, (struct sockaddr *)&remaddr, addrlen) < 0) fprintf(stderr, "broadcast reply error");
break;
case 0x0004feef:
fprintf(stderr, "SDR Program sends Stop command \n");
running = 0;
while (active) usleep(1000);
last_sequence_number = 0;
if (sock_TCP_Client > -1)
{
close(sock_TCP_Client);
sock_TCP_Client = -1;
fprintf(stderr, "SDR Program sends TCP Stop command \n");
} else fprintf(stderr, "SDR Program sends UDP Stop command \n");
break;
case 0x0104feef:
case 0x0304feef:
fprintf(stderr, "Start Port %d \n", ntohs(remaddr.sin_port));
running = 1;
if (sock_TCP_Client > -1)
fprintf(stderr, "SDR Program sends TCP Start command \n");
else
fprintf(stderr, "SDR Program sends UDP Start command \n");
break;
case 0x1104feef:
fprintf(stderr, "Connect the TCP client to the server\n");
if (sock_TCP_Client < 0)
{
if((sock_TCP_Client = accept(sock_TCP_Server, NULL, NULL)) < 0)
{
fprintf(stderr, "*** ERROR TCP accept ***\n");
perror("accept");
return;
}
fprintf(stderr, "sock_TCP_Client: %d connected to sock_TCP_Server: %d\n", sock_TCP_Client, sock_TCP_Server);
running = 1;
fprintf(stderr, "SDR Program sends TCP Start command \n");
}
break;
case 0x0201feef:
processPacket(buffer);
break;
}
}
#define assign_change(a,b,c) if ((a) != b) { b = (a); fprintf(stderr, "%20s= %08lx (%10ld)\n", c, (long) b, (long) b ); }
static void handleCommand(int base_index, char* buffer) {
command = buffer[base_index];
command_data=((buffer[base_index+1]&0xFF)<<24)+((buffer[base_index+2]&0xFF)<<16)+((buffer[base_index+3]&0xFF)<<8)+(buffer[base_index+4]&0xFF);
// switch off the attached power amplifier if the current and temp could not be measured.
if (((command >> 1)&0x09) == 0x09 ) if (!i2c_measure_module_active) command_data = command_data & 0xFFF7FFFF;
// pa bias setting
if (((command >> 1)&0x3D) == 0x3D) write_I2C_bias(((command_data>>8)&0xFF), command_data & 0xFF);
if (commands[command] != command_data) {
commands[command] = command_data;
if ((command & 0x1E) == 0x1E) CWX = (command_data & 0x01000000) ? 0x01:0x00;
push(command);
sem_post(&spi_msg);
}
}
static void handleCommands(char* buffer) {
handleCommand(11, buffer);
handleCommand(523, buffer);
}
static void processPacket(char* buffer)
{
MOX = ((buffer[11] & 0x01)==0x01) ? 0x01:0x00;
handleCommands(buffer);
int frame = 0;
for (frame; frame < 2; frame++)
{
int coarse_pointer = frame * 512 + 8;
int j = 8;
for (j; j < 512; j += 8)
{
int k = coarse_pointer + j;
if (MOX || CWX) {
sem_wait(&tx_empty);
int i = 0;
for (i; i < 8; i++){
put_tx_buffer(buffer[k + i]);
}
sem_post(&tx_full);
}
}
}
//nrx for internal use required.
if ((buffer[ 11] & 0xFE) == 0x00) {
assign_change((((buffer[ 15] & 0x38) >> 3) + 1), nrx, "Receivers");
}
if ((buffer[523] & 0xFE) == 0x00) {
assign_change((((buffer[527] & 0x38) >> 3) + 1), nrx, "Receivers");
}
//**************************************************
// Handling filter change
//**************************************************
handleFilters(buffer, CWX);
//**************************************************
}
static void sendPacket(void) {
fillPacketToSend();
if (sock_TCP_Client >= 0) {
if (sendto(sock_TCP_Client, hpsdrdata, sizeof(hpsdrdata), 0, NULL, 0) != 1032) fprintf(stderr, "TCP send error");
} else {
if (sendto(fd, hpsdrdata, sizeof(hpsdrdata), 0, (struct sockaddr *)&remaddr, addrlen) != 1032) fprintf(stderr, "UDP send error");
}
}
static void read_temperature_raspberryPi(void) {
FILE *thermal;
thermal = fopen("/sys/class/thermal/thermal_zone0/temp","r");
float systemp, millideg;
if (fscanf(thermal,"%f",&millideg) == 1) {
systemp = millideg / 1000;
//fprintf(stderr, "CPU temperature is %f degrees C\n",systemp);
sys_temp = (int) (4096/3.26) * ((systemp/ 100) + 0.5);
//fprintf(stderr, "CPU temperature in protocol has value %x\n",sys_temp);
}
fclose(thermal);
}
static void fillPacketToSend(void) {
memset(hpsdrdata,0,1032);
memcpy(hpsdrdata, header_hpsdrdata, 4);
hpsdrdata[4] = ((last_sequence_number >> 24) & 0xFF);
hpsdrdata[5] = ((last_sequence_number >> 16) & 0xFF);
hpsdrdata[6] = ((last_sequence_number >> 8) & 0xFF);
hpsdrdata[7] = (last_sequence_number & 0xFF);
last_sequence_number++;
memcpy(hpsdrdata + 8, sync_hpsdrdata, 8);
memcpy(hpsdrdata + 520, sync_hpsdrdata, 8);
if (lnrx != nrx) usleep(1000);
lnrx = nrx;
int factor = (lnrx - 1) * 6;
for (int frame = 0; frame < 2; frame++) {
int coarse_pointer = frame * 512; // 512 bytes total in each frame
int nr_samples = (nrx == 1)? 63 : (nrx == 2)? 72: (nrx ==3)? 75: 76;
if (read(fd_rb , rx_buffer , nr_samples) < 0) {
fprintf(stderr, "Error %d reading frame from radioberry device\n", errno);
break;
}
rb_sample = 0;
for (int i=0; i< (504 / (8 + factor)); i++) {
int index = 16 + coarse_pointer + (i * (8 + factor));
//NR must be read from gateware.
for (int r = 0; r < MIN(lnrx, NR); r++) {
memcpy(hpsdrdata + index + (r * 6), rx_buffer + rb_sample, 6);
rb_sample+=6;
}
}
// inform the SDR about the radioberry control status.
// https://github.com/softerhardware/Hermes-Lite2/wiki/Protocol
if ( !i2c_measure_module_active & last_sequence_number % 500 == 0) read_temperature_raspberryPi();
if ( last_sequence_number % 2 == 0) {
// if i2c_measure_module_active; the temperature of module is used, otherwise the RPI temp.
hpsdrdata[11 + coarse_pointer] = 0x08 | (rb_control & 0x07);
if (i2c_measure_module_active) {
hpsdrdata[12 + coarse_pointer] = ((pa_temp >> 8) & 0xFF);
hpsdrdata[13 + coarse_pointer] = (pa_temp & 0xFF);
} else {
hpsdrdata[12 + coarse_pointer] = ((sys_temp >> 8) & 0xFF);
hpsdrdata[13 + coarse_pointer] = (sys_temp & 0xFF);
}
} else {
hpsdrdata[11 + coarse_pointer] = 0x10 | (rb_control & 0x07);
hpsdrdata[14 + coarse_pointer] = ((pa_current >> 8) & 0xFF);
hpsdrdata[15 + coarse_pointer] = (pa_current & 0xFF);
}
}
}
static void send_control(unsigned char command) {
unsigned char data[6];
uint32_t command_data = commands[command];
// if temperature could not be measured the pa is disabled
rb_info.rb_command = ( (pa_temp_ok ? 0x04 : 0x00) | ((CWX << 1) & 0x02) | (running & 0x01) );
rb_info.command = command;
rb_info.command_data = command_data;
//fprintf(stderr, "RB-Command = %02X Command = %02X command_data = %08X\n", rb_info.rb_command, command, command_data);
if (ioctl(fd_rb, RADIOBERRY_IOC_COMMAND, &rb_info) == -1) {
fprintf(stderr, "Could not sent commando to radioberry device.");
}
//fprintf(stderr, "RB Gateware control = %02X \n", rb_info.rb_command);
rb_control = rb_info.rb_command;
}
static void *rb_control_thread(void *arg) {
while(1) {
sem_wait(&spi_msg);
if (empty()) send_control(MOX); else send_control(pop());
}
fprintf(stderr,"rb_control_thread: exiting\n");
return NULL;
}
static void start_rb_control_thread(void) {
pthread_t pid1;
pthread_create(&pid1, NULL, rb_control_thread, NULL);
}
static void *rb_measure_thread(void *arg) {
// temperature == (((T*.01)+.5)/3.26)*4096 if pa temperature > 50C (=1256) switch pa off! (pa_temp_ok)
int measured_temp_ok_count = 0;
while(1) {
sem_wait(&i2c_meas);
if (i2c_measure_module_active) read_I2C_measure(&pa_current, &pa_temp);
if (pa_temp_ok && (pa_temp >= 1256)) {
fprintf(stderr, "ALERT: temperature of PA is higher than 50ºC; PA will be switched off! \n");
pa_temp_ok = 0;
}
// PA recovery after high temperature; switch PA on again if PA temp is in range for 10 seconds.
if (!pa_temp_ok && (pa_temp < 1256)) measured_temp_ok_count++;
if (measured_temp_ok_count == 100) {
measured_temp_ok_count = 0;
pa_temp_ok = 1;
fprintf(stderr, "PA temperature is ok; PA can be used! \n");
}
}
fprintf(stderr,"rb_measure_thread: exiting\n");
return NULL;
}
static void start_rb_measure_thread(void) {
pthread_t pid1;
pthread_create(&pid1, NULL, rb_measure_thread, NULL);
}
static void *rb_register_thread(void *arg) {
sleep(60);
sprintf(gatewareversion,"%d.%d", gateware_major_version, gateware_minor_version);
sprintf(firmwareversion,"%s", FIRMWAREVERSION);
sprintf(driverversion,"%.2f", driver_version/100.0);
gateware_fpga_type == 0 ? sprintf(fpgatype,"%s", "-") : gateware_fpga_type == 1 ? sprintf(fpgatype,"%s", "CL016") : sprintf(fpgatype,"%s", "CL025");
registerRadioberry();
return NULL;
}
static void start_rb_register_thread(void) {
pthread_t pid1;
pthread_create(&pid1, NULL, rb_register_thread, NULL);
}
static void *timer_thread(void *arg) {
while(1) {
usleep(100000);
if (running) sem_post(&spi_msg);
if (running) sem_post(&i2c_meas);
}
fprintf(stderr,"timer_thread: exiting\n");
return NULL;
}
static void start_timer_thread(void ) {
pthread_t pid1;
pthread_create(&pid1, NULL, timer_thread, NULL);
}
static void *txWriter(void *arg) {
gettimeofday(&t20, 0);
while(1) {
sem_wait(&tx_full);
int i = 0;
for (i; i < 4; i++){
get_tx_buffer(); //EER first 4 bytes followed by 4 bytes TX IQ.
}
for (i=0; i < 4; i++){
tx_iqdata[i] = get_tx_buffer(); //EER first 4 bytes followed by 4 bytes TX IQ.
}
//first setup without EER
if (MOX || CWX) {
//fprintf(stderr, "I = %2X - %2X Q= %2X - %2X \n", tx_iqdata[0], tx_iqdata[1], tx_iqdata[2], tx_iqdata[3]);
if (write(fd_rb , tx_iqdata , sizeof(tx_iqdata))<0)
fprintf(stderr, "Error %d writing to radioberry device\n", errno);
}
sem_post(&tx_empty);
tx_count ++;
if (tx_count == 48000) {
tx_count = 0;
gettimeofday(&t21, 0);
float elapsed = timedifference_msec(t20, t21);
fprintf(stderr, "Code tx write executed in %f milliseconds.\n", elapsed);
//fprintf(stderr, "tx_iqdata = %02X - %02X - %02X - %02X\n", tx_iqdata[4], tx_iqdata[5], tx_iqdata[6], tx_iqdata[7]);
gettimeofday(&t20, 0);
}
}
}
static void put_tx_buffer(unsigned char value) {
tx_buffer[fill_tx] = value;
fill_tx = (fill_tx + 1) % TX_MAX_BUFFER;
}
static unsigned char get_tx_buffer() {
unsigned char tmp = tx_buffer[use_tx];
use_tx = (use_tx + 1) % TX_MAX_BUFFER;
return tmp;
}
//end of source.

Wyświetl plik

@ -0,0 +1,169 @@
#ifndef __RADIOBERRY_H__
#define __RADIOBERRY_H__
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <math.h>
#include <semaphore.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#define FIRMWAREVERSION "2024.04.16"
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
void printIntroScreen() {
fprintf(stderr,"\n");
fprintf(stderr, "====================================================================\n");
fprintf(stderr, "====================================================================\n");
fprintf(stderr, "\t\t\tRadioberry V2.0\n\n\n");
fprintf(stderr, "\tSupports 4 receivers and 1 transmitter.\n\n");
fprintf(stderr, "\tBuild version: %s\n\n", FIRMWAREVERSION);
fprintf(stderr, "\tHave fun Johan PA3GSB\n\n");
fprintf(stderr, "\tReport requests or bugs to <pa3gsb@gmail.com>.\n");
fprintf(stderr, "====================================================================\n");
fprintf(stderr, "====================================================================\n");
}
int sys_temp = 0; //rpi-temperature.
int pa_temp = 0;
int pa_current = 0;
int pa_temp_ok = 1;
//ringbuffer for handling SPI commands.
#define CAPACITY 64
uint32_t spi_commands[CAPACITY] = {0};
uint32_t p_read = 0;
uint32_t p_write = 0;
static inline int size(void) { return p_write - p_read; }
static inline int empty(void) { return p_read == p_write; }
static inline int full(void) { return size() == CAPACITY; }
static inline int mask(int val) { return val & (CAPACITY - 1); }
static inline int push(int val) { assert(!full()); spi_commands[mask(p_write++)] = val; }
static inline int pop(void) { assert(!empty()); return spi_commands[mask(p_read++)]; }
char rb_control = 0x00;
int fd_rb;
char rx_buffer[512];
int rb_sample = 0;
unsigned char command = 0;
uint32_t command_data = 0;
uint32_t commands[256];
unsigned char run = 0;
int closerb = 0;
int rb_sleep = 100;
static int initRadioberry(void);
static void runRadioberry(void);
static void closeRadioberry(void);
static void sendPacket(void);
static void handlePacket(char* buffer);
static void processPacket(char* buffer);
static void fillPacketToSend(void);
static void *packetreader(void *arg);
static void *txWriter(void *arg);
static void send_control(unsigned char command);
static float timedifference_msec(struct timeval t0, struct timeval t1);
static void put_tx_buffer(unsigned char value);
static unsigned char get_tx_buffer(void);
int sock_TCP_Server = -1;
int sock_TCP_Client = -1;
int udp_retries=0;
int active = 0;
static volatile int keepRunning = 1;
#define TX_MAX 4800
#define TX_MAX_BUFFER (TX_MAX * 8)
unsigned char tx_buffer[TX_MAX_BUFFER];
int fill_tx = 0;
int use_tx = 0;
int gateware_major_version = 0;
int gateware_minor_version = 0;
int gateware_fpga_type = 0;
int driver_version = 0.0;
char CWX = 0;
char MOX = 0;
int save_mox = -1;
sem_t tx_empty;
sem_t tx_full;
sem_t mutex;
sem_t spi_msg;
sem_t i2c_meas;
int tx_count =0;
void rx_reader(unsigned char iqdata[]);
unsigned char iqdata[6];
unsigned char tx_iqdata[4];
#define SERVICE_PORT 1024
int nrx = 1; // n Receivers
int lnrx = 1;
#define SYNC 0x7F
uint32_t last_sequence_number = 0;
uint32_t last_seqnum=0xffffffff, seqnum;
unsigned char hpsdrdata[1032];
uint8_t header_hpsdrdata[4] = { 0xef, 0xfe, 1, 6 };
uint8_t sync_hpsdrdata[8] = { SYNC, SYNC, SYNC, 0, 0, 0, 0, 0};
unsigned char broadcastReply[60];
#define TIMEOUT_MS 100
int running = 0;
int fd; /* our socket */
struct sockaddr_in myaddr; /* our address */
struct sockaddr_in remaddr; /* remote address */
socklen_t addrlen = sizeof(remaddr); /* length of addresses */
struct timeval t20;
struct timeval t21;
float elapsed;
float timedifference_msec(struct timeval t0, struct timeval t1)
{
return (t1.tv_sec - t0.tv_sec) * 1000.0f + (t1.tv_usec - t0.tv_usec) / 1000.0f;
}
void handle_sigint(int sig)
{
if (running) fprintf(stderr, " SDR program is still running; please stop SDR first.\n");
closerb = 1;
}
#endif

Wyświetl plik

@ -0,0 +1,27 @@
#ifndef __RADIOBERRY_IOCTL_H__
#define __RADIOBERRY_IOCTL_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#define RADIOBERRY_MAGIC ('x')
#define RADIOBERRY_IOC_COMMAND _IOW(RADIOBERRY_MAGIC, 1, __u8)
struct rb_info_arg_t
{
int major, minor;
int fpga;
int version;
int rb_command;
int command;
int command_data;
} ;
struct rb_info_arg_t rb_info;
#endif

Wyświetl plik

@ -0,0 +1,157 @@
#include "register.h"
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
static char macaddress[24];
static char* radiocall;
static char* radiolocator;
char gatewareversion[16];
char driverversion[16];
char firmwareversion[16];
char fpgatype[16];
#define SA struct sockaddr
#define MAXLINE 4096
#define MAXSUB 512
PROPERTY* properties=NULL;
int getMacAddress(void) {
struct ifaddrs *ifaddr=NULL;
struct ifaddrs *ifa = NULL;
int found = 0;
if (getifaddrs(&ifaddr) != -1) {
for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if ( (ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_PACKET) && !(ifa->ifa_flags & IFF_LOOPBACK) ) {
struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr;
if ((strstr(ifa->ifa_name, "eth") != NULL) || (strstr(ifa->ifa_name, "wlan") != NULL) ) {
char *macstr = "%02X:%02X:%02X:%02X:%02X:%02X";
sprintf(macaddress,macstr, s->sll_addr[0], s->sll_addr[1], s->sll_addr[2], s->sll_addr[3], s->sll_addr[4], s->sll_addr[5]);
found = 1;
break;
}
}
}
}
freeifaddrs(ifaddr);
return found;
}
void loadProperties(char* filename) {
char string[80];
char* name;
char* value;
FILE* f=fopen(filename,"r");
PROPERTY* property;
if(f) {
while(fgets(string,sizeof(string),f)) {
if(string[0]!='#') {
name=strtok(string,"=");
value=strtok(NULL,"\n");
// Beware of "illegal" lines in corrupted files
if (name != NULL && value != NULL) {
property=malloc(sizeof(PROPERTY));
property->name=malloc(strlen(name)+1);
strcpy(property->name,name);
property->value=malloc(strlen(value)+1);
strcpy(property->value,value);
property->next_property=properties;
properties=property;
}
}
}
fclose(f);
}
}
char* getProperty(char* name) {
char* value=NULL;
PROPERTY* property=properties;
while(property) {
if(strcmp(name,property->name)==0) {
value=property->value;
break;
}
property=property->next_property;
}
return value;
}
void loadRadioberryProps() {
loadProperties("/home/pi/.radioberry/radioberry.props");
radiocall = getProperty("call");
if (radiocall==NULL) radiocall="-";
if (strlen(radiocall) > 16) radiocall[16] = '\0';
radiolocator = getProperty("locator");
if (radiolocator==NULL) radiolocator="-";
if (strlen(radiolocator) > 6) radiolocator[6] = '\0';
}
ssize_t process_http(int sockfd, char *host, char *page, char *poststr)
{
char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
ssize_t n;
n = snprintf(sendline, MAXSUB,
"POST %s HTTP/1.0\r\n"
"Host: %s\r\n"
"Content-type: application/x-www-form-urlencoded\r\n"
"Content-length: %zu\r\n\r\n"
"%s", page, host, strlen(poststr), poststr);
if(write(sockfd, sendline, n) < 0)
return -errno;
//get response
while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = '\0';
//printf("%s", recvline);
}
return n;
}
int postRadioberryConfiguration() {
int result = 0;
int sockfd;
struct sockaddr_in servaddr;
char **pptr;
char *hname = "www.pa3gsb.nl";
char *page = "/radioberry/api/write.php";
char *poststr = "macaddress=%s&radiocall=%s&radiolocator=%s&gatewareversion=%s&driverversion=%s&firmwareversion=%s&fpgatype=%s\r\n";
// make message for registration.
char post_message[4096];
sprintf(post_message,poststr, macaddress, radiocall, radiolocator, gatewareversion, driverversion, firmwareversion, fpgatype);
char str[50];
struct hostent *hptr;
if ((hptr = gethostbyname(hname)) == NULL) return -1;
if (hptr->h_addrtype == AF_INET && (pptr = hptr->h_addr_list) != NULL) inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str));
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, str, &servaddr.sin_addr);
if (connect(sockfd, (SA *) & servaddr, sizeof(servaddr)) >= 0) process_http(sockfd, hname, page, post_message); else result = -1;
close(sockfd);
return result;
}
void registerRadioberry() {
if (!getMacAddress()) return;
loadRadioberryProps();
if (postRadioberryConfiguration()) fprintf(stderr, "Registering your Radioberry not registered."); else fprintf(stderr, "Your Radioberry is registered: http://www.pa3gsb.nl/radioberry/api/read.php\n");
}
//end of source

Wyświetl plik

@ -0,0 +1,39 @@
#ifndef __RADIOBERRY_REGISTER_H__
#define __RADIOBERRY_REGISTER_H__
#include <linux/if.h>
#include <ifaddrs.h>
#include <netpacket/packet.h>
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <netdb.h>
typedef struct _PROPERTY PROPERTY;
struct _PROPERTY {
char* name;
char* value;
PROPERTY* next_property;
};
extern char gatewareversion[16];
extern char driverversion[16];
extern char firmwareversion[16];
extern char fpgatype[16];
int getMacAddress(void);
void loadProperties(char* filename);
char* getProperty(char* name);
void loadRadioberryProps(void);
ssize_t process_http(int sockfd, char *host, char *page, char *poststr);
int postRadioberryConfiguration(void);
extern void registerRadioberry(void);
#endif

Wyświetl plik

@ -0,0 +1,40 @@
## Running Radioberry
The radioberry-SDR image is setup using a service in combination with a daemon process.
The service is installed in /etc/systemd/systemd/radioberry.service
The daemon is place in /etc/init.d/radioberryd
Now you have control to the radioberry by using systemctl functions.
'''
sudo systemctl enable radioberry
sudo systemctl disable radioberry
sudo systemctl start radioberry
sudo systemctl stop radioberry
sudo systemctl restart radioberry
sudo systemctl status radioberry
'''
Using:
sudo journalctl -u radioberry
gives you logging information.
Like to know the process id of the daemon: sudo /bin/pidof radioberry
gives you the process id.

Wyświetl plik

@ -0,0 +1,16 @@
[Unit]
Description=Radioberry SDR
Wants=network-online.target
After=network-online.target
[Service]
Type=forking
User=root
Group=root
ExecStart=/etc/init.d/radioberryd start
ExecStop=/etc/init.d/radioberryd stop
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

Wyświetl plik

@ -0,0 +1,48 @@
#!/bin/sh
RADIOBERRYD=radioberry
RADIOBERRYD_EXEC=/usr/local/bin/$RADIOBERRYD
case "$1" in
start)
echo -n "Start radioberry firmware daemon: "
sudo chmod 666 /dev/radioberry
start-stop-daemon --start --background --exec $RADIOBERRYD_EXEC
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
echo "OK"
else
echo "FAIL TO START"
fi
date
;;
stop)
echo -n "Stopping radioberry daemon: "
start-stop-daemon --stop --exec $RADIOBERRYD
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
echo "OK"
else
echo "FAIL TO STOP"
fi
;;
status)
if [ -n "`/bin/pidof $RADIOBERRYD`" ] ; then
echo "radioberry daemon is running."
else
echo "radioberry daemon is not running."
fi
;;
restart)
$0 stop && sleep 1 && $0 start
;;
*)
echo "Usage: /etc/init.d/radioberryd {start|stop|status|restart}"
exit 1
esac

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,23 @@
## Radioberry software installation script
This is a developement release of versions of the Radioberry sofware.
Initialy it was a script where you could select the individual software components.
Nowadays people have to choose too much...hi, the whole software stack will be installed.
https://github.com/pa3gsb/Radioberry-2.x/wiki/Radioberry-Software-stack
This avoids possible problems by selecting the wrong set of software components.
Installation is easy:
Open a command window and executing the following commands:
cd /tmp
wget https://raw.githubusercontent.com/pa3gsb/Radioberry-2.x/master/SBC/rpi-5/releases/dev/radioberry_install.sh
sudo chmod +x radioberry_install.sh
./radioberry_install.sh

Wyświetl plik

@ -0,0 +1,186 @@
#!/bin/bash
echo ""
echo ""
echo "============================================"
echo "Radioberry software installation @RPI-5"
echo ""
echo "You will install the following versions: "
echo ""
echo " Gateware version 73.3"
echo " Driver version 5.01"
echo " Firmware version 2024.04.16"
echo "============================================"
echo ""
echo ""
fpgatype=2; #default
while true; do
read -p "Install CL016 or CL025 radioberry version: 1 = CL016 or 2 = CL025? " type
case $type in
[1]* ) fpgatype=1; break;;
[2]* ) fpgatype=2; break;;
* ) echo "Please answer 1 or 2 for the FPGA used in your radioberry.";
esac
done
function install_dependency {
echo "--- Installing dependency: $1"
sudo apt-get -y install $1
}
install_dependency raspberrypi-kernel-headers
install_dependency linux-headers-rpi
install_dependency git
install_dependency device-tree-compiler
install_dependency pigpio
if [ -d "Radioberry-2.x" ]; then
DO_CLEANUP=false
else
DO_CLEANUP=true
git clone --depth=1 https://github.com/pa3gsb/Radioberry-2.x
fi
sudo systemctl stop radioberry
sudo systemctl disable radioberry
#-----------------------------------------------------------------------------
if [[ $fpgatype == 1 ]]; then
echo "Installing Radioberry gateware Cyclone 10 CL016..."
cd Radioberry-2.x/SBC/rpi-5/releases/dev/CL016
sudo cp ./radioberry.rbf /lib/firmware
cd ../../../../../..
echo ""
echo "Radioberry gateware Cyclone 10 CL016 installed."
fi
if [[ $fpgatype == 2 ]]; then
echo "Installing Radioberry gateware Cyclone 10 CL025..."
cd Radioberry-2.x/SBC/rpi-5/releases/dev/CL025
sudo cp ./radioberry.rbf /lib/firmware
cd ../../../../../..
echo ""
echo "Radioberry gateware Cyclone 10 CL025 installed."
fi
#-----------------------------------------------------------------------------
echo "Installing Radioberry driver..."
#unregister radioberry driver
sudo modprobe -r radioberry
# new raspios uses /boot/firmware instead of /boot
if [ -d "/boot/firmware" ]; then
BOOT_PATH="/boot/firmware"
else
BOOT_PATH="/boot"
fi
if [ ! -d "/lib/modules/$(uname -r)/kernel/drivers/sdr" ]; then
sudo mkdir /lib/modules/$(uname -r)/kernel/drivers/sdr
fi
cd Radioberry-2.x/SBC/rpi-5/device_driver/driver
make
if [ $? -eq 0 ]; then
sudo cp radioberry.ko /lib/modules/$(uname -r)/kernel/drivers/sdr
sudo cp radioberry.dtbo "$BOOT_PATH/overlays"
#add driver to config.txt
sudo grep -Fxq "dtoverlay=radioberry" "$BOOT_PATH/config.txt" || sudo sed -i '$ a dtoverlay=radioberry' "$BOOT_PATH/config.txt"
cd ../../../../..
sudo depmod
#register radioberry driver
sudo modprobe radioberry
sudo chmod 666 /dev/radioberry
#show radioberry driver info.
sudo modinfo radioberry
echo ""
echo "Radioberry driver installed."
else
echo "Radioberry driver installation failed."
echo ""
echo "You are using a linux version without linux header files; choose an other distro."
if [ "$DO_CLEANUP" = true ]; then
echo "Cleaning up..."
sudo rm -rf Radioberry-2.x
fi
exit 1
fi
#-----------------------------------------------------------------------------
echo "Installing Radioberry firmware..."
cd Radioberry-2.x/SBC/rpi-5/device_driver/firmware
sudo make
if [ $? -eq 0 ]; then
sudo cp radioberry /usr/local/bin
sudo chmod +x /usr/local/bin/radioberry
cd ../../../../..
echo ""
echo "Radioberry firmware installed."
else
echo "Radioberry firmware installation failed."
echo ""
echo "Looking into the log and try to find out what is wrong."
if [ "$DO_CLEANUP" = true ]; then
echo "Cleaning up..."
sudo rm -rf Radioberry-2.x
fi
exit 1
fi
#-----------------------------------------------------------------------------
echo "Installing radioberry service ..."
cd Radioberry-2.x/SBC/rpi-5/device_driver/systemd
sudo cp radioberry.service /etc/systemd/system/radioberry.service
sudo cp radioberryd /etc/init.d/radioberryd
sudo chmod +x /etc/init.d/radioberryd
cd ../../../../..
echo "Radioberry service installed."
#-----------------------------------------------------------------------------
if [ "$DO_CLEANUP" = true ]; then
echo "Cleaning up..."
sudo rm -rf Radioberry-2.x
fi
sudo systemctl enable radioberry
sudo systemctl start radioberry
echo ""
echo ""
echo "============================================"
echo "Radioberry software is installed!"
echo "Have fun using the SDR Radioberry"
echo ""
echo "73 Johan PA3GSB"
echo "============================================"
echo ""
echo ""
exit 0