kopia lustrzana https://github.com/pa3gsb/Radioberry-2.x
386 wiersze
13 KiB
C
386 wiersze
13 KiB
C
#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
|
|
|