AFC, calling mode, logging, better display

pull/3/head
Dave Akerman 2015-06-11 10:49:00 +00:00
rodzic 74caab7383
commit 6f8e08210f
6 zmienionych plików z 391 dodań i 79 usunięć

1
.gitignore vendored
Wyświetl plik

@ -6,3 +6,4 @@ desktop.ini
*.bin
*.BIN
gateway
telemetry.txt

Wyświetl plik

@ -60,19 +60,39 @@ Configuration
The configuration is in the file gateway.txt. Example:
tracker=M0RPI
EnableHabitat=N
EnableSSDV=Y
LogTelemetry=Y
CallingTimeout=60
frequency_0=434.451
mode_0=2
frequency_0=434.347
mode_0=1
DIO0_0=31
DIO5_0=26
AFC_0=N
#frequency_1=434.450
#mode_1=0
frequency_1=434.475
mode_1=5
DIO0_1=6
DIO5_1=5
AFC_1=Y
The options are:
tracker=<callsign>. This is whatever callsign you want to appear as on the tracking map and/or SSDV page.
EnableHabitat=<Y/N>. Enables uploading of telemetry packets to Habitat.
EnableSSDV=<Y/N>. Enables uploading of SSDV image packets to the SSDV server.
LogTelemetry=<Y/N>. Enables logging of telemetry packets (ASCII only at present) to telemetry.txt.
CallingTimeout=<seconds>. Sets a timeout for returning to calling mode after a period with no received packets.
frequency_<n>=<freq in MHz>. This sets the frequency for LoRa module <n> (0 for first, 1 for second). e.g. frequency_0=434.450
AFC_<n>=<Y/N>. Enables or disables automatic frequency control (retunes by the frequency error of last received packet).
mode_<n>=<mode>. Sets the "mode" for the selected LoRa module. This offers a simple way of setting the various
LoRa parameters (SF etc.) in one go. The modes are:
@ -80,6 +100,8 @@ The options are:
1 = (normal for SSDV) Implicit mode, Error coding 4:5, Bandwidth 20.8kHz, SF 6, Low data rate optimize off
2 = (normal for repeater) Explicit mode, Error coding 4:8, Bandwidth 62.5kHz, SF 8, Low data rate optimize off
3 = (normal for fast SSDV) Explicit mode, Error coding 4:6, Bandwidth 250kHz, SF 7, Low data rate optimize off
4 = Test mode not for normal use.
5 = (normal for calling mode) Explicit mode, Error coding 4:8, Bandwidth 41.7kHz, SF 11, Low data rate optimize off
SF_<n>=<Spreading Factor> e.g. SF_0=7
@ -100,3 +122,19 @@ Run with:
sudo ./gateway
Interactive Features
====================
The following key presses are available. Where appropriate unshifted keys affect Channel 0 and shifted keys affect Channel 1.
Many thanks to David Brooke for coding this feature and the AFC.
q quit
a increase frequency by 100kHz
z decrease frequency by 100kHz
s increase frequency by 10kHz
x decrease frequency by 10kHz
d increase frequency by 1kHz
c decrease frequency by 1kHz
f toggle AFC

BIN
gateway

Plik binarny nie jest wyświetlany.

403
gateway.c
Wyświetl plik

@ -16,6 +16,7 @@
#include <stdarg.h>
#include <pthread.h>
#include <curses.h>
#include <math.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
@ -25,6 +26,7 @@
#include "ssdv.h"
#include "global.h"
bool run = TRUE;
// RFM98
uint8_t currentMode = 0x81;
@ -128,7 +130,7 @@ struct TBinaryPacket
uint16_t Altitude;
};
const char *Modes[5] = {"slow", "SSDV", "repeater", "turbo", "TurboX"};
const char *Modes[6] = {"Slow", "SSDV", "Repeater", "Turbo", "TurboX", "Calling"};
void writeRegister(int Channel, uint8_t reg, uint8_t val)
{
@ -229,6 +231,24 @@ void setMode(int Channel, uint8_t newMode)
return;
}
void setFrequency(int Channel, double Frequency)
{
unsigned long FrequencyValue;
FrequencyValue = (unsigned long)(Frequency * 7110656 / 434);
writeRegister(Channel, 0x06, (FrequencyValue >> 16) & 0xFF); // Set frequency
writeRegister(Channel, 0x07, (FrequencyValue >> 8) & 0xFF);
writeRegister(Channel, 0x08, FrequencyValue & 0xFF);
Config.LoRaDevices[Channel].activeFreq = Frequency;
// LogMessage("Set Frequency to %lf\n", Frequency);
ChannelPrintf(Channel, 1, 1, "Channel %d %8.4lfMHz ", Channel, Frequency);
// ChannelPrintf(Channel, 1, 1, "Channel %d %8.4lfMHz %s mode", Channel, Frequency, Modes[Config.LoRaDevices[Channel].SpeedMode]);
// ChannelPrintf(Channel, 1, 11, "%8.4fMHz", Frequency);
}
void setLoRaMode(int Channel)
{
@ -243,14 +263,54 @@ void setLoRaMode(int Channel)
if (sscanf(Config.LoRaDevices[Channel].Frequency, "%lf", &Frequency))
{
FrequencyValue = (unsigned long)(Frequency * 7110656 / 434);
// LogMessage("FrequencyValue = %06Xh\n", FrequencyValue);
writeRegister(Channel, 0x06, (FrequencyValue >> 16) & 0xFF); // Set frequency
writeRegister(Channel, 0x07, (FrequencyValue >> 8) & 0xFF);
writeRegister(Channel, 0x08, FrequencyValue & 0xFF);
// LogMessage("Set Default Frequency\n");
setFrequency(Channel, Frequency);
}
}
// LogMessage("Mode = %d\n", readRegister(Channel, REG_OPMODE));
char *BandwidthString(int Bandwidth)
{
if (Bandwidth == BANDWIDTH_7K8) return "7.8k";
if (Bandwidth == BANDWIDTH_10K4) return "10.4k";
if (Bandwidth == BANDWIDTH_15K6) return "15.6k";
if (Bandwidth == BANDWIDTH_20K8) return "20.8k";
if (Bandwidth == BANDWIDTH_31K25) return "31.25k";
if (Bandwidth == BANDWIDTH_41K7) return "41.7k";
if (Bandwidth == BANDWIDTH_62K5) return "62.5k";
if (Bandwidth == BANDWIDTH_125K) return "125k";
if (Bandwidth == BANDWIDTH_250K) return "250k";
if (Bandwidth == BANDWIDTH_500K) return "500k";
return "??k";
}
void SetLoRaParameters(int Channel, int ImplicitOrExplicit, int ErrorCoding, int Bandwidth, int SpreadingFactor, int LowDataRateOptimize)
{
writeRegister(Channel, REG_MODEM_CONFIG, ImplicitOrExplicit | ErrorCoding | Bandwidth);
writeRegister(Channel, REG_MODEM_CONFIG2, SpreadingFactor | CRC_ON);
writeRegister(Channel, REG_MODEM_CONFIG3, 0x04 | LowDataRateOptimize); // 0x04: AGC sets LNA gain
writeRegister(Channel, REG_DETECT_OPT, (readRegister(Channel, REG_DETECT_OPT) & 0xF8) | ((SpreadingFactor == SPREADING_6) ? 0x05 : 0x03)); // 0x05 For SF6; 0x03 otherwise
writeRegister(Channel, REG_DETECTION_THRESHOLD, (SpreadingFactor == SPREADING_6) ? 0x0C : 0x0A); // 0x0C for SF6, 0x0A otherwise
Config.LoRaDevices[Channel].CurrentBandwidth = Bandwidth;
ChannelPrintf(Channel, 2, 1, "%s, %s, SF%d, EC4:%d %s",
ImplicitOrExplicit == IMPLICIT_MODE ? "Implicit" : "Explicit",
BandwidthString(Bandwidth),
SpreadingFactor >> 4,
(ErrorCoding >> 1) + 4,
LowDataRateOptimize ? "LDRO" : "");
}
void SetDefaultLoRaParameters(int Channel)
{
// LogMessage("Set Default Parameters\n");
SetLoRaParameters(Channel,
Config.LoRaDevices[Channel].ImplicitOrExplicit,
Config.LoRaDevices[Channel].ErrorCoding,
Config.LoRaDevices[Channel].Bandwidth,
Config.LoRaDevices[Channel]. SpreadingFactor,
Config.LoRaDevices[Channel].LowDataRateOptimize);
}
/////////////////////////////////////
@ -258,16 +318,15 @@ void setLoRaMode(int Channel)
//////////////////////////////////////
void startReceiving(int Channel)
{
writeRegister(Channel, REG_MODEM_CONFIG, Config.LoRaDevices[Channel].ImplicitOrExplicit | Config.LoRaDevices[Channel].ErrorCoding | Config.LoRaDevices[Channel].Bandwidth);
writeRegister(Channel, REG_MODEM_CONFIG2, Config.LoRaDevices[Channel].SpreadingFactor | CRC_ON);
writeRegister(Channel, REG_MODEM_CONFIG3, 0x04 | Config.LoRaDevices[Channel].LowDataRateOptimize); // 0x04: AGC sets LNA gain
writeRegister(Channel, REG_DETECT_OPT, (readRegister(Channel, REG_DETECT_OPT) & 0xF8) | ((Config.LoRaDevices[Channel].SpreadingFactor == SPREADING_6) ? 0x05 : 0x03)); // 0x05 For SF6; 0x03 otherwise
writeRegister(Channel, REG_DETECTION_THRESHOLD, (Config.LoRaDevices[Channel].SpreadingFactor == SPREADING_6) ? 0x0C : 0x0A); // 0x0C for SF6, 0x0A otherwise
LogMessage("Channel %d %s mode\n", Channel, Modes[Config.LoRaDevices[Channel].SpeedMode]);
// writeRegister(Channel, REG_MODEM_CONFIG, Config.LoRaDevices[Channel].ImplicitOrExplicit | Config.LoRaDevices[Channel].ErrorCoding | Config.LoRaDevices[Channel].Bandwidth);
// writeRegister(Channel, REG_MODEM_CONFIG2, Config.LoRaDevices[Channel].SpreadingFactor | CRC_ON);
// writeRegister(Channel, REG_MODEM_CONFIG3, 0x04 | Config.LoRaDevices[Channel].LowDataRateOptimize); // 0x04: AGC sets LNA gain
// writeRegister(Channel, REG_DETECT_OPT, (readRegister(Channel, REG_DETECT_OPT) & 0xF8) | ((Config.LoRaDevices[Channel].SpreadingFactor == SPREADING_6) ? 0x05 : 0x03)); // 0x05 For SF6; 0x03 otherwise
// writeRegister(Channel, REG_DETECTION_THRESHOLD, (Config.LoRaDevices[Channel].SpreadingFactor == SPREADING_6) ? 0x0C : 0x0A); // 0x0C for SF6, 0x0A otherwise
// writeRegister(Channel, REG_PAYLOAD_LENGTH, Config.LoRaDevices[Channel].PayloadLength);
// writeRegister(Channel, REG_RX_NB_BYTES, Config.LoRaDevices[Channel].PayloadLength);
writeRegister(Channel, REG_PAYLOAD_LENGTH, 255);
writeRegister(Channel, REG_RX_NB_BYTES, 255);
@ -281,6 +340,14 @@ void startReceiving(int Channel)
setMode(Channel, RF96_MODE_RX_CONTINUOUS);
}
void ReTune(int Channel, double FreqShift)
{
setMode(Channel, RF96_MODE_SLEEP);
LogMessage("Retune by %lf\n", FreqShift);
setFrequency(Channel, Config.LoRaDevices[Channel].activeFreq + FreqShift);
startReceiving(Channel);
}
void setupRFM98(int Channel)
{
if (Config.LoRaDevices[Channel].InUse)
@ -297,7 +364,9 @@ void setupRFM98(int Channel)
// LoRa mode
setLoRaMode(Channel);
SetDefaultLoRaParameters(Channel);
startReceiving(Channel);
}
}
@ -306,9 +375,26 @@ void ShowPacketCounts(int Channel)
{
if (Config.LoRaDevices[Channel].InUse)
{
ChannelPrintf(Channel, 6, 1, "Telem Packets = %d", Config.LoRaDevices[Channel].TelemetryCount);
ChannelPrintf(Channel, 7, 1, "Image Packets = %d", Config.LoRaDevices[Channel].SSDVCount);
ChannelPrintf(Channel, 8, 1, "Bad CRC = %d Bad Type = %d", Config.LoRaDevices[Channel].BadCRCCount, Config.LoRaDevices[Channel].UnknownCount);
ChannelPrintf(Channel, 7, 1, "Telem Packets = %d", Config.LoRaDevices[Channel].TelemetryCount);
ChannelPrintf(Channel, 8, 1, "Image Packets = %d", Config.LoRaDevices[Channel].SSDVCount);
ChannelPrintf(Channel, 9, 1, "Bad CRC = %d Bad Type = %d", Config.LoRaDevices[Channel].BadCRCCount, Config.LoRaDevices[Channel].UnknownCount);
}
}
double FrequencyReference(int Channel)
{
switch (Config.LoRaDevices[Channel].CurrentBandwidth)
{
case BANDWIDTH_7K8: return 7800;
case BANDWIDTH_10K4: return 10400;
case BANDWIDTH_15K6: return 15600;
case BANDWIDTH_20K8: return 20800;
case BANDWIDTH_31K25: return 31250;
case BANDWIDTH_41K7: return 41700;
case BANDWIDTH_62K5: return 62500;
case BANDWIDTH_125K: return 125000;
case BANDWIDTH_250K: return 250000;
case BANDWIDTH_500K: return 500000;
}
}
@ -327,13 +413,14 @@ double FrequencyError(int Channel)
Temp = Temp - 524288;
}
return - ((double)Temp * (1<<24) / 32000000.0) * (Config.LoRaDevices[Channel].Reference / 500000.0);
return - ((double)Temp * (1<<24) / 32000000.0) * (FrequencyReference(Channel) / 500000.0);
}
int receiveMessage(int Channel, unsigned char *message)
{
int i, Bytes, currentAddr, x;
unsigned char data[257];
double FreqError;
Bytes = 0;
@ -349,7 +436,7 @@ int receiveMessage(int Channel, unsigned char *message)
LogMessage("CRC Failure, RSSI %d\n", readRegister(Channel, REG_PACKET_RSSI) - 157);
// reset the crc flags
writeRegister(Channel, REG_IRQ_FLAGS, 0x20);
ChannelPrintf(Channel, 3, 1, "CRC Failure %02Xh!!\n", x);
ChannelPrintf(Channel, 4, 1, "CRC Failure %02Xh!!\n", x);
Config.LoRaDevices[Channel].BadCRCCount++;
ShowPacketCounts(Channel);
}
@ -361,19 +448,13 @@ int receiveMessage(int Channel, unsigned char *message)
// LogMessage("%d bytes in packet\n", Bytes);
// LogMessage("RSSI = %d\n", readRegister(Channel, REG_PACKET_RSSI) - 137);
ChannelPrintf(Channel, 9, 1, "Packet SNR = %4d ", (char)(readRegister(Channel, REG_PACKET_SNR)) / 4);
ChannelPrintf(Channel, 10, 1, "Packet RSSI = %4d ", readRegister(Channel, REG_PACKET_RSSI) - 157);
ChannelPrintf(Channel, 11, 1, "Freq. Error = %4.1lfkHz ", FrequencyError(Channel) / 1000);
ChannelPrintf(Channel, 10, 1, "Packet SNR = %d, RSSI = %d ", (char)(readRegister(Channel, REG_PACKET_SNR)) / 4, readRegister(Channel, REG_PACKET_RSSI) - 157);
FreqError = FrequencyError(Channel) / 1000;
ChannelPrintf(Channel, 11, 1, "Freq. Error = %5.1lfkHz ", FreqError);
writeRegister(Channel, REG_FIFO_ADDR_PTR, currentAddr);
/*
// now loop over the fifo getting the data
for(i = 0; i < Bytes; i++)
{
message[i] = (unsigned char)readRegister(Channel, REG_FIFO);
}
*/
data[0] = REG_FIFO;
wiringPiSPIDataRW(Channel, data, Bytes+1);
for (i=0; i<=Bytes; i++)
@ -383,9 +464,10 @@ int receiveMessage(int Channel, unsigned char *message)
message[Bytes] = '\0';
// writeRegister(Channel, REG_FIFO_ADDR_PTR, 0); // currentAddr);
// writeRegister(Channel, REG_FIFO_ADDR_PTR, 0);
// writeRegister(Channel, REG_FIFO_RX_BASE_AD, 0);
if(Config.LoRaDevices[Channel].AFC && fabs(FreqError)>0.1)
{
ReTune(Channel, FreqError/1000);
}
}
// Clear all flags
@ -436,6 +518,20 @@ size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
return size * nmemb;
}
void LogTelemetryPacket(char *Telemetry)
{
if (Config.EnableTelemetryLogging)
{
FILE *fp;
if ((fp = fopen("telemetry.txt", "at")) != NULL)
{
fprintf(fp, "%s\n", Telemetry);
fclose(fp);
}
}
}
void UploadTelemetryPacket(char *Telemetry)
{
if (Config.EnableHabitat)
@ -458,7 +554,7 @@ void UploadTelemetryPacket(char *Telemetry)
curl_easy_setopt(curl, CURLOPT_URL, "http://habitat.habhub.org/transition/payload_telemetry");
// Now specify the POST data
sprintf(PostFields, "callsign=%s&string=%s&string_type=ascii&metadata={}", Config.Tracker, Telemetry);
sprintf(PostFields, "callsign=%s&string=%s\n&string_type=ascii&metadata={}", Config.Tracker, Telemetry);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, PostFields);
// Perform the request, res will get the return code
@ -582,6 +678,7 @@ void LoadConfigFile()
Config.EnableHabitat = 1;
Config.EnableSSDV = 1;
Config.EnableTelemetryLogging = 0;
Config.ftpServer[0] = '\0';
Config.ftpUser[0] = '\0';
Config.ftpPassword[0] = '\0';
@ -598,7 +695,10 @@ void LoadConfigFile()
ReadBoolean(fp, "EnableHabitat", 0, &Config.EnableHabitat);
ReadBoolean(fp, "EnableSSDV", 0, &Config.EnableSSDV);
ReadBoolean(fp, "LogTelemetry", 0, &Config.EnableTelemetryLogging);
Config.CallingTimeout = ReadInteger(fp, "CallingTimeout", 0, 300);
ReadString(fp, "ftpserver", Config.ftpServer, sizeof(Config.ftpServer), 0);
ReadString(fp, "ftpUser", Config.ftpUser, sizeof(Config.ftpUser), 0);
ReadString(fp, "ftpPassword", Config.ftpPassword, sizeof(Config.ftpPassword), 0);
@ -618,6 +718,7 @@ void LoadConfigFile()
Config.LoRaDevices[Channel].Bandwidth = BANDWIDTH_20K8;
Config.LoRaDevices[Channel].SpreadingFactor = SPREADING_11;
Config.LoRaDevices[Channel].LowDataRateOptimize = 0x00;
Config.LoRaDevices[Channel].AFC = FALSE;
LogMessage("Channel %d frequency set to %s\n", Channel, Config.LoRaDevices[Channel].Frequency);
Config.LoRaDevices[Channel].InUse = 1;
@ -634,10 +735,17 @@ void LoadConfigFile()
Config.LoRaDevices[Channel].SpeedMode = 0;
sprintf(Keyword, "mode_%d", Channel);
Config.LoRaDevices[Channel].SpeedMode = ReadInteger(fp, Keyword, 0, 0);
// Config.LoRaDevices[Channel].PayloadLength = Config.LoRaDevices[Channel].SpeedMode == 0 ? 80 : 255;
ChannelPrintf(Channel, 1, 1, "Channel %d %sMHz %s mode", Channel, Config.LoRaDevices[Channel].Frequency, Modes[Config.LoRaDevices[Channel].SpeedMode]);
if (Config.LoRaDevices[Channel].SpeedMode == 4)
if (Config.LoRaDevices[Channel].SpeedMode == 5)
{
// Calling channel
Config.LoRaDevices[Channel].ImplicitOrExplicit = EXPLICIT_MODE;
Config.LoRaDevices[Channel].ErrorCoding = ERROR_CODING_4_8;
Config.LoRaDevices[Channel].Bandwidth = BANDWIDTH_41K7;
Config.LoRaDevices[Channel].SpreadingFactor = SPREADING_11;
Config.LoRaDevices[Channel].LowDataRateOptimize = 0;
}
else if (Config.LoRaDevices[Channel].SpeedMode == 4)
{
// Testing
Config.LoRaDevices[Channel].ImplicitOrExplicit = IMPLICIT_MODE;
@ -736,20 +844,6 @@ void LoadConfigFile()
{
Config.LoRaDevices[Channel].Bandwidth = BANDWIDTH_500K;
}
switch (Config.LoRaDevices[Channel].Bandwidth)
{
case BANDWIDTH_7K8: Config.LoRaDevices[Channel].Reference = 7800; break;
case BANDWIDTH_10K4: Config.LoRaDevices[Channel].Reference = 10400; break;
case BANDWIDTH_15K6: Config.LoRaDevices[Channel].Reference = 15600; break;
case BANDWIDTH_20K8: Config.LoRaDevices[Channel].Reference = 20800; break;
case BANDWIDTH_31K25: Config.LoRaDevices[Channel].Reference = 31250; break;
case BANDWIDTH_41K7: Config.LoRaDevices[Channel].Reference = 41700; break;
case BANDWIDTH_62K5: Config.LoRaDevices[Channel].Reference = 62500; break;
case BANDWIDTH_125K: Config.LoRaDevices[Channel].Reference = 125000; break;
case BANDWIDTH_250K: Config.LoRaDevices[Channel].Reference = 250000; break;
case BANDWIDTH_500K: Config.LoRaDevices[Channel].Reference = 500000; break;
}
sprintf(Keyword, "implicit_%d", Channel);
if (ReadBoolean(fp, Keyword, 0, &Temp))
@ -776,6 +870,16 @@ void LoadConfigFile()
Config.LoRaDevices[Channel].LowDataRateOptimize = 0x08;
}
}
sprintf(Keyword, "AFC_%d", Channel);
if (ReadBoolean(fp, Keyword, 0, &Temp))
{
if (Temp)
{
Config.LoRaDevices[Channel].AFC = TRUE;
ChannelPrintf(Channel, 11, 24, "AFC");
}
}
}
}
@ -907,7 +1011,7 @@ void DoPositionCalcs(Channel)
Config.LoRaDevices[Channel].PreviousAltitude = Config.LoRaDevices[Channel].Altitude;
Config.LoRaDevices[Channel].LastPositionAt = Now;
ChannelPrintf(Channel, 4, 1, "%8.5lf, %8.5lf, %05u ",
ChannelPrintf(Channel, 5, 1, "%8.5lf, %8.5lf, %05u ",
Config.LoRaDevices[Channel].Latitude,
Config.LoRaDevices[Channel].Longitude,
Config.LoRaDevices[Channel].Altitude);
@ -964,20 +1068,118 @@ uint16_t CRC16(unsigned char *ptr)
return CRC;
}
void ProcessKeyPress(int ch)
{
int Channel = 0;
/* shifted keys act on channel 1 */
if (ch >= 'A' && ch <= 'Z')
{
Channel = 1;
/* change from upper to lower case */
ch += ('a' - 'A');
}
if (ch == 'q')
{
run = FALSE;
return;
}
/* ignore if channel is not in use */
if (!Config.LoRaDevices[Channel].InUse)
{
return;
}
switch(ch)
{
case 'f':
Config.LoRaDevices[Channel].AFC = !Config.LoRaDevices[Channel].AFC;
ChannelPrintf(Channel, 11, 24, "%s", Config.LoRaDevices[Channel].AFC?"AFC":" ");
break;
case 'a':
ReTune(Channel, 0.1);
break;
case 'z':
ReTune(Channel, -0.1);
break;
case 's':
ReTune(Channel, 0.01);
break;
case 'x':
ReTune(Channel, -0.01);
break;
case 'd':
ReTune(Channel, 0.001);
break;
case 'c':
ReTune(Channel, -0.001);
break;
default:
//LogMessage("KeyPress %d\n", ch);
return;
}
}
void ProcessCallingMessage(int Channel, char *Message)
{
char Payload[16];
double Frequency;
int ImplicitOrExplicit, ErrorCoding, Bandwidth, SpreadingFactor, LowDataRateOptimize;
if (sscanf(Message, "%15[^,],%lf,%d,%d,%d,%d,%d,%d",
Payload,
&Frequency,
&ImplicitOrExplicit,
&ErrorCoding,
&Bandwidth,
&SpreadingFactor,
&LowDataRateOptimize) == 7)
{
if (Config.LoRaDevices[Channel].AFC)
{
double MasterFrequency;
sscanf(Config.LoRaDevices[Channel].Frequency, "%lf", &MasterFrequency);
Frequency += Config.LoRaDevices[Channel].activeFreq - MasterFrequency;
}
LogMessage("Ch %d: Calling message, new frequency %7.3lf\n", Channel, Frequency);
// Decoded OK
setMode(Channel, RF96_MODE_SLEEP);
// setFrequency(Channel, Config.LoRaDevices[Channel].activeFreq + );
setFrequency(Channel, Frequency);
SetLoRaParameters(Channel, ImplicitOrExplicit, ErrorCoding, Bandwidth, SpreadingFactor, LowDataRateOptimize);
setMode(Channel, RF96_MODE_RX_CONTINUOUS);
// ChannelPrintf(Channel, 1, 1, "Channel %d %7.3lfMHz ", Channel, Frequency);
}
}
int main(int argc, char **argv)
{
unsigned char Message[257], Command[200], Telemetry[100], filename[100], *dest, *src;
int Bytes, ImageNumber, PreviousImageNumber, PacketNumber, PreviousPacketNumber;
int Bytes, ImageNumber, PreviousImageNumber, PacketNumber, PreviousPacketNumber, ch;
uint32_t CallsignCode, PreviousCallsignCode, LoopCount[2];
pthread_t /* CurlThread, */ SSDVThread;
FILE *fp;
WINDOW * mainwin;
mainwin = InitDisplay();
// LogMessage("**** LoRa Gateway by daveake ****\n");
// Settings for character input
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
PreviousImageNumber = -1;
PreviousCallsignCode = 0;
PreviousPacketNumber = 0;
@ -1035,7 +1237,7 @@ int main(int argc, char **argv)
}
while (1)
while (run)
{
int Channel;
@ -1058,21 +1260,50 @@ int main(int argc, char **argv)
{
LogMessage("Ch %d: Uploaded message %s\n", Channel, Message+1);
}
else if (Message[1] == '^')
{
ChannelPrintf(Channel, 4, 1, "Calling message %d bytes ", strlen(Message+1));
ProcessCallingMessage(Channel, Message+3);
// Message[strlen(Message+1)] = '\0';
}
else if (Message[1] == '$')
{
ChannelPrintf(Channel, 3, 1, "Telemetry %d bytes ", strlen(Message)-1); // Bytes);
int i;
unsigned char *startmessage, *endmessage;
ChannelPrintf(Channel, 4, 1, "Telemetry %d bytes ", strlen(Message+1));
// LogMessage("Telemetry %d bytes\n", strlen(Message)-1);
UploadTelemetryPacket(Message+1);
ProcessLine(Channel, Message+1);
endmessage = Message;
for (i=0; endmessage < &(Message[Bytes-8]); i++)
{
startmessage = endmessage + 1;
endmessage = strchr(startmessage, '\n');
if (endmessage != NULL)
{
*endmessage = '\0';
LogTelemetryPacket(startmessage);
UploadTelemetryPacket(startmessage);
if (i == 0)
{
ProcessLine(Channel, startmessage);
}
LogMessage("Ch %d: %s\n", Channel, startmessage);
}
}
DoPositionCalcs(Channel);
Config.LoRaDevices[Channel].TelemetryCount++;
Message[strlen(Message+1)] = '\0';
LogMessage("Ch %d: %s\n", Channel, Message+1);
// Message[strlen(Message+1)] = '\0';
}
else if ((Message[1] & 0xC0) == 0xC0)
{
@ -1084,7 +1315,7 @@ int main(int argc, char **argv)
SourceID = Message[1] & 0x07;
SenderID = (Message[1] >> 3) & 0x07;
ChannelPrintf(Channel, 3, 1, "Binary Telemetry");
ChannelPrintf(Channel, 4, 1, "Binary Telemetry");
memcpy(&BinaryPacket, Message+1, sizeof(BinaryPacket));
@ -1126,7 +1357,7 @@ int main(int argc, char **argv)
// Binary upload packet
int SenderID, TargetID;
ChannelPrintf(Channel, 3, 1, "Uplink Message");
ChannelPrintf(Channel, 4, 1, "Uplink Message");
TargetID = Message[1] & 0x07;
SenderID = (Message[1] >> 3) & 0x07;
@ -1174,7 +1405,7 @@ int main(int argc, char **argv)
}
LogMessage("SSDV Packet, Callsign %s, Image %d, Packet %d, %d Missing\n", Callsign, Message[6], Message[7] * 256 + Message[8], Config.LoRaDevices[Channel].SSDVMissing);
ChannelPrintf(Channel, 3, 1, "SSDV Packet %d bytes ", Bytes);
ChannelPrintf(Channel, 4, 1, "SSDV Packet %d bytes ", Bytes);
PreviousImageNumber = ImageNumber;
PreviousPacketNumber = PacketNumber;
@ -1216,11 +1447,17 @@ int main(int argc, char **argv)
else
{
LogMessage("Unknown packet type is %02Xh, RSSI %d\n", Message[1], readRegister(Channel, REG_PACKET_RSSI) - 157);
ChannelPrintf(Channel, 3, 1, "Unknown Packet %d, %d bytes", Message[0], Bytes);
ChannelPrintf(Channel, 4, 1, "Unknown Packet %d, %d bytes", Message[0], Bytes);
Config.LoRaDevices[Channel].UnknownCount++;
}
Config.LoRaDevices[Channel].LastPacketAt = time(NULL);
if (Config.CallingTimeout > 0)
{
Config.LoRaDevices[Channel].ReturnToCallingModeAt = time(NULL) + Config.CallingTimeout;
}
ShowPacketCounts(Channel);
}
@ -1231,9 +1468,37 @@ int main(int argc, char **argv)
LoopCount[Channel] = 0;
ShowPacketCounts(Channel);
ChannelPrintf(Channel, 12, 1, "Current RSSI = %4d ", readRegister(Channel, REG_CURRENT_RSSI) - 157);
if (Config.LoRaDevices[Channel].LastPacketAt > 0)
{
ChannelPrintf(Channel, 5, 1, "%us since last packet ", (unsigned int)(time(NULL) - Config.LoRaDevices[Channel].LastPacketAt));
ChannelPrintf(Channel, 6, 1, "%us since last packet ", (unsigned int)(time(NULL) - Config.LoRaDevices[Channel].LastPacketAt));
}
if ((Config.CallingTimeout > 0) && (Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0) && (time(NULL) > Config.LoRaDevices[Channel].ReturnToCallingModeAt))
{
Config.LoRaDevices[Channel].ReturnToCallingModeAt = 0;
LogMessage("Return to calling mode\n");
// setMode(Channel, RF96_MODE_SLEEP);
// setFrequency(Channel, Frequency);
// SetLoRaParameters(Channel, ImplicitOrExplicit, ErrorCoding, Bandwidth, SpreadingFactor, LowDataRateOptimize);
// setMode(Channel, RF96_MODE_RX_CONTINUOUS);
setLoRaMode(Channel);
SetDefaultLoRaParameters(Channel);
setMode(Channel, RF96_MODE_RX_CONTINUOUS);
ChannelPrintf(Channel, 1, 1, "Channel %d %sMHz %s mode", Channel, Config.LoRaDevices[Channel].Frequency, Modes[Config.LoRaDevices[Channel].SpeedMode]);
}
if ((ch = getch()) != ERR)
{
ProcessKeyPress(ch);
}
}
}

Wyświetl plik

@ -1,14 +1,17 @@
tracker=M0RPI
EnableHabitat=Y
EnableHabitat=N
EnableSSDV=Y
LogTelemetry=Y
CallingTimeout=60
frequency_0=868.451
frequency_0=434.347
mode_0=1
DIO0_0=31
DIO5_0=26
AFC_0=N
frequency_1=434.4566
mode_1=1
frequency_1=434.475
mode_1=5
DIO0_1=6
DIO5_1=5
AFC_1=Y

Wyświetl plik

@ -6,14 +6,16 @@ struct TLoRaDevice
int DIO0;
int DIO5;
char Frequency[16];
double activeFreq;
bool AFC;
int SpeedMode;
int PayloadLength;
int ImplicitOrExplicit;
int ErrorCoding;
int Bandwidth;
double Reference;
int SpreadingFactor;
int LowDataRateOptimize;
int CurrentBandwidth;
WINDOW *Window;
@ -28,6 +30,7 @@ struct TLoRaDevice
unsigned long LastPositionAt;
time_t LastPacketAt;
float AscentRate;
time_t ReturnToCallingModeAt;
};
struct TConfig
@ -35,6 +38,8 @@ struct TConfig
char Tracker[16];
int EnableHabitat;
int EnableSSDV;
int EnableTelemetryLogging;
int CallingTimeout;
char ftpServer[100];
char ftpUser[32];
char ftpPassword[32];