示例#1
0
文件: tracker.c 项目: cvansas/pits
int main(void)
{
	int fd, ReturnCode, i;
	unsigned long Sentence_Counter = 0;
	int ImagePacketCount, MaxImagePackets;
	char Sentence[100], Command[100];
	struct stat st = {0};
	struct TGPS GPS;
	pthread_t PredictionThread, LoRaThread, APRSThread, GPSThread, DS18B20Thread, ADCThread, CameraThread, BMP085Thread, BME280Thread, LEDThread, LogThread;
	
	if (prog_count("tracker") > 1)
	{
		printf("\nThe tracker program is already running!\n");
		printf("It is started automatically, with the camera script, when the Pi boots.\n\n");
		printf("If you just want the tracker software to run, it already is,\n");
		printf("and its output can be viewed on a monitor attached to a Pi video socket.\n\n");
		printf("If instead you want to view the tracker output via ssh,\n");
		printf("then you should first stop it by typing the following command:\n");
		printf("	sudo killall tracker\n\n");
		printf("and then restart manually with\n");
		printf("	sudo ./tracker\n\n");
		exit(1);
	}
	
	printf("\n\nRASPBERRY PI-IN-THE-SKY FLIGHT COMPUTER\n");
	printf(    "=======================================\n\n");

	Config.BoardType = GetBoardType();

	if (Config.BoardType)
	{
		if (Config.BoardType == 3)
		{
			printf("RPi Zero\n");
			printf("PITS Zero Board\n");
		}
		else
		{
			if (Config.BoardType == 2)
			{
				printf("RPi 2 B\n");
			}
			else
			{
				printf("RPi Model A+ or B+\n");
			}
			printf("PITS+ Board\n");
		}
				
		Config.LED_OK = 25;
		Config.LED_Warn = 24;
		
		Config.SDA = 2;
		Config.SCL = 3;
	}
	else
	{
		printf("RPi Model A or B\n");
		printf("PITS Board\n");

		Config.LED_OK = 11;
		Config.LED_Warn = 4;
		
		Config.SDA = 5;
		Config.SCL = 6;
	}
	
	printf("Device Tree is %s\n\n", devicetree() ? "enabled" : "disabled");

	LoadConfigFile(&Config);

	if (Config.DisableMonitor)
	{
		system("/opt/vc/bin/tvservice -off");
	}
	
	if (FileExists("/boot/clear.txt"))
	{
		// remove SSDV and other camera images, plus log files

		printf("Removing existing photo files\n");
		remove("gps.txt");
		remove("telemetry.txt");
		remove("/boot/clear.txt");
		system("rm -rf /home/pi/pits/tracker/images/*");
	}
		
	// Remove any old SSDV files
	system("rm -f ssdv*.bin");

	GPS.SecondsInDay = 0;
	GPS.Hours = 0;
	GPS.Minutes = 0;
	GPS.Seconds = 0;
	GPS.Longitude = 0.0;
	GPS.Latitude = 0.0;
	GPS.Altitude = 0;
	GPS.Satellites = 0;
	GPS.Speed = 0.0;
	GPS.Direction = 0.0;
	GPS.DS18B20Temperature[0] = 0.0;
	GPS.DS18B20Temperature[1] = 0.0;
	GPS.BatteryVoltage = 0.0;
	GPS.BMP180Temperature = 0.0;
	GPS.Pressure = 0.0;
	GPS.MaximumAltitude = 0.0;
	GPS.DS18B20Count = 0;

	
	// Set up I/O
	if (wiringPiSetup() == -1)
	{
		exit (1);
	}

	// Switch off the radio till it's configured
	pinMode (NTX2B_ENABLE, OUTPUT);
	digitalWrite (NTX2B_ENABLE, 0);
		
	// Switch on the GPS
	if (Config.BoardType == 0)
	{
		// Only PITS board had this, not PITS+
		pinMode (UBLOX_ENABLE, OUTPUT);
		digitalWrite (UBLOX_ENABLE, 0);
	}

	if (!Config.DisableRTTY)
	{
		if (*Config.Frequency)
		{
			SetFrequency(Config.Frequency);
		}
	
		fd = OpenSerialPort();

		digitalWrite (NTX2B_ENABLE, 1);
	}
	
	// Set up DS18B20
	system("sudo modprobe w1-gpio");
	system("sudo modprobe w1-therm");
	
	if (!devicetree())
	{
		// SPI for ADC (older boards), LoRa add-on board
		system("gpio load spi");
	}

	// SSDV Folders
	sprintf(Config.Channels[0].SSDVFolder, "%s/RTTY", SSDVFolder);
	*Config.Channels[1].SSDVFolder = '\0';										// No folder for APRS images
	sprintf(Config.Channels[2].SSDVFolder, "%s/LORA0", SSDVFolder);
	sprintf(Config.Channels[3].SSDVFolder, "%s/LORA1", SSDVFolder);
	sprintf(Config.Channels[4].SSDVFolder, "%s/FULL", SSDVFolder);
		
	if (Config.Camera)
	{
		// Create SSDV Folders
		if (stat(SSDVFolder, &st) == -1)
		{
			mkdir(SSDVFolder, 0777);
		}	
	
		for (i=0; i<5; i++)
		{
			if (*Config.Channels[i].SSDVFolder)
			{
				if (stat(Config.Channels[i].SSDVFolder, &st) == -1)
				{
					mkdir(Config.Channels[i].SSDVFolder, 0777);
				}
			}
		}

		// Filenames for SSDV
		for (i=0; i<5; i++)
		{
			sprintf(Config.Channels[i].take_pic, "take_pic_%d", i);
			// sprintf(Config.Channels[i].current_ssdv, "ssdv_%d.bin", i);
			// sprintf(Config.Channels[i].next_ssdv, "ssdv_%d.nxt", i);
			sprintf(Config.Channels[i].convert_file, "convert_%d", i);
			sprintf(Config.Channels[i].ssdv_done, "ssdv_done_%d", i);
			
			Config.Channels[i].SSDVImageNumber = -1;
			Config.Channels[i].SSDVPacketNumber = -1;
			
			Config.Channels[i].ImageFP = NULL;
		}
	}
	
	if (pthread_create(&GPSThread, NULL, GPSLoop, &GPS))
	{
		fprintf(stderr, "Error creating GPS thread\n");
		return 1;
	}

	if (*(Config.APRS_Callsign) && Config.APRS_ID && Config.APRS_Period)
	{
		if (pthread_create(&APRSThread, NULL, APRSLoop, &GPS))
		{
			fprintf(stderr, "Error creating APRS thread\n");
			return 1;
		}
	}
	
	if (Config.LoRaDevices[0].InUse || Config.LoRaDevices[1].InUse)
	{
		if (pthread_create(&LoRaThread, NULL, LoRaLoop, &GPS))
		{
			fprintf(stderr, "Error creating LoRa thread\n");
		}
	}
	
	if (pthread_create(&DS18B20Thread, NULL, DS18B20Loop, &GPS))
	{
		fprintf(stderr, "Error creating DS18B20s thread\n");
		return 1;
	}

	if (Config.BoardType != 3)
	{
		// Not a zero, so should have ADC on it
		if (I2CADCExists())
		{
			printf ("V2.4 or later board with I2C ADC\n");
			
			if (pthread_create(&ADCThread, NULL, I2CADCLoop, &GPS))
			{
				fprintf(stderr, "Error creating ADC thread\n");
				return 1;
			}
		}
		else
		{
			printf ("Older board with SPI ADC\n");
			
			if (pthread_create(&ADCThread, NULL, ADCLoop, &GPS))
			{
				fprintf(stderr, "Error creating ADC thread\n");
				return 1;
			}
		}
	}

	if (Config.Camera)
	{
		if (pthread_create(&CameraThread, NULL, CameraLoop, &GPS))
		{
			fprintf(stderr, "Error creating camera thread\n");
			return 1;
		}
	}

	if (pthread_create(&LEDThread, NULL, LEDLoop, &GPS))
	{
		fprintf(stderr, "Error creating LED thread\n");
		return 1;
	}

	if (Config.TelemetryFileUpdate > 0)
	{
		if (pthread_create(&LogThread, NULL, LogLoop, &GPS))
		{
			fprintf(stderr, "Error creating Log thread\n");
			return 1;
		}
	}
	
	if (Config.EnableBMP085)
	{
		if (pthread_create(&BMP085Thread, NULL, BMP085Loop, &GPS))
		{
			fprintf(stderr, "Error creating BMP085 thread\n");
			return 1;
		}
	}

	if (Config.EnableBME280)
	{
		if (pthread_create(&BME280Thread, NULL, BME280Loop, &GPS))
		{
			fprintf(stderr, "Error creating BME280 thread\n");
			return 1;
		}
	}

	if (Config.EnableLandingPrediction)
	{
		if (pthread_create(&PredictionThread, NULL, PredictionLoop, &GPS))
		{
			fprintf(stderr, "Error creating prediction thread\n");
		}
	}	
	
	if (!Config.DisableRTTY)
	{
		if (Config.InfoMessageCount < 0)
		{
			// Default number depends on baud rate
			Config.InfoMessageCount = (Config.TxSpeed < B300) ? 2 : 4;
		}
	
		for (i=0; i<Config.InfoMessageCount; i++)
		{
			SendIPAddress(fd);
			SendFreeSpace(fd);
		}
	}

	ImagePacketCount = 0;
	
	while (1)
	{
		static int CarrierOn=1;
		
		if (Config.DisableRTTY)
		{
			delayMilliseconds (200);
		}
		else if (LoRaUploadNow(&GPS, 10))
		{
			if (CarrierOn)
			{
				digitalWrite (NTX2B_ENABLE, 0);
				CarrierOn = 0;
				printf("Switching RTTY carrier off\n");
			}
			delayMilliseconds (200);
		}
		else
		{
			if (!CarrierOn)
			{
				digitalWrite (NTX2B_ENABLE, 1);
				printf("Switching RTTY carrier on\n");
				CarrierOn = 1;
			}
			
			MaxImagePackets = (GPS.Altitude > Config.SSDVHigh) ? Config.Channels[RTTY_CHANNEL].ImagePackets : 1;
			
			if (ImagePacketCount++ < MaxImagePackets)
			{
				SendRTTYImage(fd);
			}
			else
			{
				ImagePacketCount = 0;
				
				BuildSentence(Sentence, ++Sentence_Counter, &GPS);
			
				SendSentence(fd, Sentence);
			}
		}
	}
}
示例#2
0
int main(int argc, char **argv)
{
	unsigned char Message[257];
	int Bytes, ch;
	uint32_t LoopCount[2];
	pthread_t SSDVThread, FTPThread, NetworkThread, HabitatThread, ServerThread;
	WINDOW * mainwin;
	int LEDCounts[2];
	
	if (prog_count("gateway") > 1)
	{
		printf("\nThe gateway program is already running!\n\n");
		exit(1);
	}

	mainwin = InitDisplay();
	
	// Settings for character input
	noecho();
	cbreak();
	nodelay(stdscr, TRUE);
	keypad(stdscr, TRUE);
		
	Config.LoRaDevices[0].InUse = 0;
	Config.LoRaDevices[1].InUse = 0;
	
	LEDCounts[0] = 0;
	LEDCounts[1] = 0;	
	
	// Remove any old SSDV files
	// system("rm -f /tmp/*.bin");	
	
	// Default pin allocations

	Config.LoRaDevices[0].DIO0 = 6;
	Config.LoRaDevices[0].DIO5 = 5;
	
	Config.LoRaDevices[1].DIO0 = 27;
	Config.LoRaDevices[1].DIO5 = 26;
	
	LoadConfigFile();
	LoadPayloadFiles();
	
	if (wiringPiSetup() < 0)
	{
		fprintf(stderr, "Failed to open wiringPi\n");
		exit(1);
	}
	
	if (Config.LoRaDevices[0].ActivityLED >= 0) pinMode(Config.LoRaDevices[0].ActivityLED, OUTPUT);
	if (Config.LoRaDevices[1].ActivityLED >= 0) pinMode(Config.LoRaDevices[1].ActivityLED, OUTPUT);
	if (Config.InternetLED >= 0) pinMode(Config.InternetLED, OUTPUT);
	if (Config.NetworkLED >= 0) pinMode(Config.NetworkLED, OUTPUT);
	
	setupRFM98(0);
	setupRFM98(1);
	
	ShowPacketCounts(0);
	ShowPacketCounts(1);

	LoopCount[0] = 0;
	LoopCount[1] = 0;
	
	if (pthread_create(&SSDVThread, NULL, SSDVLoop, NULL))
	{
		fprintf(stderr, "Error creating SSDV thread\n");
		return 1;
	}

	if (pthread_create(&FTPThread, NULL, FTPLoop, NULL))
	{
		fprintf(stderr, "Error creating FTP thread\n");
		return 1;
	}

	if (pthread_create(&HabitatThread, NULL, HabitatLoop, NULL))
	{
		fprintf(stderr, "Error creating Habitat thread\n");
		return 1;
	}
	
	if (Config.ServerPort > 0)
	{
		if (pthread_create(&ServerThread, NULL, ServerLoop, NULL))
		{
			fprintf(stderr, "Error creating server thread\n");
			return 1;
		}
	}

	if ((Config.NetworkLED >= 0) && (Config.InternetLED >= 0))
	{
		if (pthread_create(&NetworkThread, NULL, NetworkLoop, NULL))
		{
			fprintf(stderr, "Error creating Network thread\n");
			return 1;
		}
	}

	while (run)
	{
		int Channel;
		
		for (Channel=0; Channel<=1; Channel++)
		{
			if (Config.LoRaDevices[Channel].InUse)
			{
				if (digitalRead(Config.LoRaDevices[Channel].DIO0))
				{
					Bytes = receiveMessage(Channel, Message+1);
					
					if (Bytes > 0)
					{
						if (Config.LoRaDevices[Channel].ActivityLED >= 0)
						{
							digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 1);
							LEDCounts[Channel] = 5;
						}
						// LogMessage("Channel %d data available - %d bytes\n", Channel, Bytes);
						// LogMessage("Line = '%s'\n", Message);

						if (Message[1] == '!')
						{
							ProcessUploadMessage(Channel, (char *) Message+1);
						}
						else if (Message[1] == '^')
						{
							ProcessCallingMessage(Channel, (char *) Message+1);
						}
						else if (Message[1] == '$')
						{
							ProcessTelemetryMessage(Channel, (char *) Message+1);
						}
						else if (Message[1] == 0x66)
						{
							ProcessSSDVMessage(Channel, Message);
						}
						else
						{
							LogMessage("Unknown packet type is %02Xh, RSSI %d\n", Message[1], readRegister(Channel, REG_PACKET_RSSI) - 157);
							ChannelPrintf(Channel, 4, 1, "Unknown Packet %d, %d bytes", Message[0], Bytes);
							Config.LoRaDevices[Channel].UnknownCount++;
						}
						
						Config.LoRaDevices[Channel].LastPacketAt = time(NULL);
						
						if (Config.LoRaDevices[Channel].InCallingMode && (Config.CallingTimeout > 0))
						{
							Config.LoRaDevices[Channel].ReturnToCallingModeAt = time(NULL) + Config.CallingTimeout;
						}
						

						ShowPacketCounts(Channel);
					}
				}
				
				if (++LoopCount[Channel] > 1000000)
				{
					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, 6, 1, "%us since last packet   ", (unsigned int)(time(NULL) - Config.LoRaDevices[Channel].LastPacketAt));
					}
					
					if (Config.LoRaDevices[Channel].InCallingMode && (Config.CallingTimeout > 0) && (Config.LoRaDevices[Channel].ReturnToCallingModeAt > 0) && (time(NULL) > Config.LoRaDevices[Channel].ReturnToCallingModeAt))
					{
						Config.LoRaDevices[Channel].InCallingMode = 0;
						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);
					}
					
					if (LEDCounts[Channel] && (Config.LoRaDevices[Channel].ActivityLED >= 0))
					{
						if (--LEDCounts[Channel] == 0)
						{
							digitalWrite(Config.LoRaDevices[Channel].ActivityLED, 0);
						}
					}
				}
			}
		}
		// delay(5);
 	}

	CloseDisplay(mainwin);
	
	if (Config.NetworkLED >= 0) digitalWrite(Config.NetworkLED, 0);
	if (Config.InternetLED >= 0) digitalWrite(Config.InternetLED, 0);
	if (Config.LoRaDevices[0].ActivityLED >= 0) digitalWrite(Config.LoRaDevices[0].ActivityLED, 0);
	if (Config.LoRaDevices[1].ActivityLED >= 0) digitalWrite(Config.LoRaDevices[1].ActivityLED, 0);	
	
	return 0;
}