kopia lustrzana https://github.com/pa3gsb/Radioberry-2.x
rpi-5 install
rodzic
80f256ab91
commit
64c4cf1a13
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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.
|
@ -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
|
||||
|
||||
|
|
@ -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
|
Ładowanie…
Reference in New Issue