예제 #1
0
void main(void) {
    byte evalue;
    initSquareWear();
    setModeOutput(pinC7);
    latC7 = 0;
    delayMilliseconds(250); // short delay for EEPROM to stablize
    evalue = readEEPROM(0x0);   // read EEPROM address 0
    switch(evalue) {
        case 0:
            writeEEPROM(0x0, 1);    // write next index to EEPROM address 0
            busyEEPROM();           // wait till write completes
            while(1) {
                latC7 = !latC7;
                delayMilliseconds(100);
            }
            break;
        case 1:
            writeEEPROM(0x0, 2);
            busyEEPROM();
            while(1) {
                latC7 = !latC7;
                delayMilliseconds(500);
            }
            break;
        default:
            writeEEPROM(0x0, 0);
            busyEEPROM();
            while(1) {
                latC7 = !latC7;
                delayMilliseconds(1000);
            }
            break;

    }
}
예제 #2
0
void main(void) {
    // array of pin names
    byte pins[12] = {pinC0, pinC1, pinC2, pinC3,
                     pinC4, pinC5, pinC6, pinC7,
                     pinB4, pinB5, pinB6, pinB7};
    // since pins C4-C7 are current sinks, they are active HIGH,
    // the other pins are active LOW.
    byte highs[12]= {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0};
    byte i;
    initSquareWear();
    // portC pins are set as output mode by default
    setModeOutput(pinB4);
    setModeOutput(pinB5);
    setModeOutput(pinB6);
    setModeOutput(pinB7);
    while(1) {
        for(i=0;i<12;i++) {
            setValue(pins[i], highs[i]);
        }
        delayMilliseconds(delaytime);
        for(i=0;i<12;i++) {
            setValue(pins[i], 1-highs[i]);
        }
        delayMilliseconds(delaytime);
    }
}
예제 #3
0
파일: gps.c 프로젝트: petejbell/pits
void *GPSLoop(void *some_void_ptr)
{
	unsigned char Line[100];
	int id, Length;
	struct i2c_info bb;
	struct TGPS *GPS;

	GPS = (struct TGPS *)some_void_ptr;
	
	Length = 0;

    while (1)
    {
        int i;
		unsigned char Character;

		printf ("SDA/SCL = %d/%d\n", Config.SDA, Config.SCL);
		
		if (OpenI2C(&bb, 0x42, Config.SDA, Config.SCL, 10, 100))		// struct, i2c address, SDA, SCL, us clock delay, timeout ms
		{
			printf("Failed to open I2C\n");
			exit(1);
		}
	
		SetFlightMode(&bb);

        while (!bb.Failed)
        {
            Character = I2CGetc(&bb);

			if (Character == 0xFF)
			{
				delayMilliseconds (100);
			}
            else if (Character == '$')
			{
				Line[0] = Character;
				Length = 1;
			}
            else if (Length > 90)
			{
				Length = 0;
            }
            else if ((Length > 0) && (Character != '\r'))
            {
               	Line[Length++] = Character;
               	if (Character == '\n')
               	{
               		Line[Length] = '\0';
					// puts(Line);
               		ProcessLine(&bb, GPS, Line, Length);
					delayMilliseconds (100);
               		Length = 0;
               	}
            }
		}
		
		ResetI2C(&bb);
	}
}
예제 #4
0
int main() {

    initSystem();
    initSystemClock();
    I2cMaster::start();

    setGpioPinModeOutput(pPin13);
    setGpioPinLow(pPin13);

    lcd.init();
    lcd.clear();
    lcd.home();
    lcd.autoscrollOff();
    lcd.setBacklight(0);
    delayMilliseconds(1000);
    lcd.setBacklight(I2cLcd::kBacklight_Green);
    lcd.displayTopRow("Hello, World!");
    delayMilliseconds(1000);
    lcd.setBacklight(I2cLcd::kBacklight_White);
    long counter = 0;

    for(;;) {
        for(uint8_t color = 0; color < 8 ; color++) {
            lcd.displayBottomRow(ltoa(counter, number, 10));
            writeGpioPinDigital(pPin13, color % 2);
            counter++;
        }
    }

}
예제 #5
0
void main(void) {
    float temp;
    float duty;
    initSquareWear();
    setModePWM(pinC4);
    setModePWM(pinC5);
    setModePWM(pinC6);
    setModeADC(pinADC11);

    while(1) {
        // read temperature sensor value
        temp = (float)getValue(pinADC11);
        // converts to Celcius
        temp = (temp * 4.1 / 1024 - 0.5) / 0.01;

        // blue LED brightness
        // Gaussian centered at 10 degree Celcius
        duty = 31.0 * exp(-(temp-10)*(temp-10)/100.0) * 0.25;
        setValue(pinC6, (byte)duty);

        // red LED brightness
        // Gaussian centered at 50 degree Celcius
        duty = 31.0 * exp(-(temp-50.0)*(temp-50.0)/100.0);
        setValue(pinC4, (byte)duty);

        // green LED brightness
        // Gaussian centered at 27 degree Celcius
        duty = 31.0 * exp(-(temp-27.0)*(temp-27.0)/50.0);
        setValue(pinC5, (byte)duty);
        delayMilliseconds(100);

    }
}
예제 #6
0
void Fade(int delayms) {
    byte i;
    byte v;
    for(v=0;v<32;v++) { // increase PWM values
        for(i=0;i<12;i++) {
            setValue(pinnames[i], v);
        }
        delayMilliseconds(delayms);
    }
    for(v=32;v!=0;v--) { // decrease PWM values
        for(i=0;i<12;i++) {
            setValue(pinnames[i], v-1);
        }
        delayMilliseconds(delayms);
    }
}
예제 #7
0
void main(void) {
    initSquareWear();       // must call initialization function first
    setModeOutput(pinC7);   // set pinC7 as digital OUTPUT pin
    while(1) {
        latC7 = !latC7 ;    // toggle pin C7 value
        delayMilliseconds(delaytime);
    }
}
예제 #8
0
void Blink(int delayms) {
    byte i;
    for(i=0;i<12;i++) {
        setValue(pinnames[i], 1-getValue(pinnames[i])); // toggle
        
    }
    
    delayMilliseconds(delayms);
}
예제 #9
0
void button_callback(void) {
    if (buttonPressed()) {
        delayMilliseconds(50);   // wait 50ms for debounce
        if(buttonPressed())
        {
            change=1;
        }
    }
}
예제 #10
0
void CMUcom4::end()
{
    delayMilliseconds(CMUCOM4_END_DELAY);

#if defined(__AVR_ATmega1280__) || \
    defined(__AVR_ATmega2560__) || \
    defined(__SAM3X8E__)
    switch(_port)
    {
        case CMUCOM4_SERIAL1: Serial1.end(); break;
        case CMUCOM4_SERIAL2: Serial2.end(); break;
        case CMUCOM4_SERIAL3: Serial3.end(); break;
        default: Serial.end(); break;
    }
#else
    Serial.end();
#endif

    delayMilliseconds(CMUCOM4_END_DELAY);
}
예제 #11
0
void CMUcom4::begin(unsigned long baud)
{
    delayMilliseconds(CMUCOM4_BEGIN_DELAY);

#if defined(__AVR_ATmega1280__) || \
    defined(__AVR_ATmega2560__) || \
    defined(__SAM3X8E__)
    switch(_port)
    {
        case CMUCOM4_SERIAL1: Serial1.begin(baud); break;
        case CMUCOM4_SERIAL2: Serial2.begin(baud); break;
        case CMUCOM4_SERIAL3: Serial3.begin(baud); break;
        default: Serial.begin(baud); break;
    }
#else
    Serial.begin(baud);
#endif

    delayMilliseconds(CMUCOM4_BEGIN_DELAY);
}
예제 #12
0
void main(void) {
    ulong t;
    byte i;
    initSquareWear();
    setModePWM(pinC7);      // set pinC7 as PWM output
    setModeADC(pinADC4);    // set pinADC4 as analog read
#if OUTPUT_TO_USB_SERIAL
    openUSBSerial();        // open USB serial port
#endif
    // use timer interrupt to sample pulse sensor data
    // open timer interrupt, 20ms interval (50Hz frequency)
    openTimerInterrupt(20, sample);
    t=t_prev_peak;
    while(1) {
        // inner loop blinks LED
        if(t!=t_prev_peak) {
            // if a new peak has been detected
            t=t_prev_peak;
            // quickly fade LED (pinC7)
            for(i=0;i<32;i++) {
                setValue(pinC7, i);
#if OUTPUT_TO_USB_SERIAL
                // need to call pollUSBSerial as often as we can
                pollUSBSerial();
#endif
                delayMilliseconds(1);
            }
            for(i=0;i<32;i++) {
                setValue(pinC7, 31-i);
#if OUTPUT_TO_USB_SERIAL
                // need to call pollUSBSerial as often as we can
                pollUSBSerial();
#endif   
                delayMilliseconds(1);
            }
        }
#if OUTPUT_TO_USB_SERIAL
        pollUSBSerial();
#endif
    }
}
예제 #13
0
void main(void) {
    uint value;

    initSquareWear();
    setModeADC(pinADC4);    // set ADC4 as analog read pin
    setModeOutput(pinC7);   // set C7 as PWM output pin

    while(1) {
        // read analog value
        value = getValue(pinADC4);
        latC7 = !latC7;
        delayMilliseconds(value);   // set delay time
    }
}
예제 #14
0
void main(void) {
    byte duty=0;
    initSquareWear();
    setModePWM(pinC7);

    // open button interrupt before going to sleep
    openOnBoardButtonInterrupt(callback);
    
    while(1) {
        // fade LED (pinC7)
        for(duty=0;duty<32;duty++) {
            setValue(pinC7, duty);
            delayMilliseconds(50);
        }
        for(duty=32;duty!=0;duty--) {
            setValue(pinC7, duty-1);
            delayMilliseconds(50);
        }
        // enter deep sleep: CPU clock will stop running
        // the only way to wake up CPU is through external,
        // pin-change, watchdog interrupts, or reset.
        deepSleep();
    }
}
예제 #15
0
void main(void) {
    byte duty = 0;
    char incr = 1;
    initSquareWear();
    setModePWM(pinC7);  // set pinC7 and pinC3 as PWM output pins
    setModePWM(pinC3);

    while(1) {
        setValue(pinC7, duty);  // set duty cycle
        setValue(pinC3, duty);
        duty += incr;
        if (duty == 31) incr = -1;  // maximum duty cycle is 31
        else if (duty == 0) incr = +1;
        delayMilliseconds(100);
    }
}
예제 #16
0
void main(void) {
    uint duty = 0;
    char incr = 1;
    initSquareWear();

    // open hardware pwm
    openHardwarePWM();

    while(1) {
        setHardwarePWMduty(duty);
        duty += incr;
        if (duty == 1023) incr = -1;  // hardware pwm maximum duty cycle 1023
        else if (duty == 0) incr = +1;
        delayMilliseconds(2);
    }
}
예제 #17
0
void main(void) {
    uint value;
    initSquareWear();
    
    setModeADC(pinADC4);    // set ADC4 as analog read pin
    setModePWM(pinC7);      // set C7 as PWM output pin

    while(1) {
        // read 10-bit analog value
        value = getValue(pinADC4);
        // convert the analog value to 5-bit PWM value
        // and set it for pinC7
        setValue(pinC7, value>>5);
        delayMilliseconds(5);
    }
}
예제 #18
0
void main(void) {
    byte duty = 0;
    char incr = 1;
    initSquareWear();
    setModeOutput(pinC7);   // set pinC7 as output pin
    setModePWM(pinC6);      // set pinC6 as PWM pin

    // open timer interrupt, use 'delaytime' as interval'
    // and 'toggle' as callback function
    openTimerInterrupt(delaytime, toggle);
    while(1) {
        // fade pinC6
        setValue(pinC6, duty);
        duty += incr;
        if (duty == 31) incr = -1;
        else if (duty == 0) incr = +1;
        delayMilliseconds(100);
    }
}
예제 #19
0
void sendI2C(unsigned char addr, char* data, unsigned char len) {
	unsigned char i;
	
	delayMilliseconds(250);
	SSPIF = 0; // Clear SSP flag
	SEN = 1; // Start Enable
	while(SEN); // Wait to finish
	SSPIF = 0; // Clear SSP flag
	SSPBUF = addr; // Send address
	while(!SSPIF); // Wait for SSPIF flag
	SSPIF = 0; // Clear SSP flag
	for(i = 0; i < len; i++) {
		SSPBUF = data[i]; // Send data
		while(!SSPIF); // Wait for SSPIF flag
		SSPIF = 0; // Clear SSP flag
//		delayMilliseconds(10); // Allow interpretation
	}
	PEN = 1;
	while(PEN); // Wait to finish
	SSPIF = 0; // Clear SSP flag
}
예제 #20
0
void main(void) {
    byte i;
    float c = 0;
    float b;
    initSquareWear();
    for(i=0;i<8;i++) {
        // set all portC pins for PWM output
        setModePWM(pins[i]);
    }
    while(1) {
        for(i=0; i<8; i++) {
            // compute PWM value
            b = (sin(3.14/4*i+c) + 1.0) / 2.0;
            b = sqrt(b) * 31;
            if (onvs[i] == 0)
                b = 31 - b;
            // set PWM value
            setValue(pins[i], b);
        }
        delayMilliseconds(10);
        c += 0.1;
    }
}
예제 #21
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);
			}
		}
	}
}
예제 #22
0
파일: tracker.c 프로젝트: cvansas/pits
void SetNTX2BFrequency(char *FrequencyString)
{
	int fd, Frequency;
	char Command[16];
	struct termios options;
	uint8_t setNMEAoff[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xA9           };

	// First disable transmitter
	digitalWrite (NTX2B_ENABLE, 0);
	pinMode (NTX2B_ENABLE, OUTPUT);
	delayMilliseconds (200);
	
	fd = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY);
	if (fd >= 0)
	{
		tcgetattr(fd, &options);

		cfsetispeed(&options, B4800);
		cfsetospeed(&options, B4800);

		options.c_cflag &= ~CSTOPB;
		options.c_cflag |= CS8;
		options.c_oflag &= ~ONLCR;
		options.c_oflag &= ~OPOST;
		options.c_iflag &= ~IXON;
		options.c_iflag &= ~IXOFF;
		options.c_lflag &= ~ECHO;
		options.c_cc[VMIN]  = 0;
		options.c_cc[VTIME] = 10;
		
		tcsetattr(fd, TCSANOW, &options);

		// Tel UBlox to shut up
		write(fd, setNMEAoff, sizeof(setNMEAoff));
		tcsetattr(fd, TCSAFLUSH, &options);
		close(fd);
		delayMilliseconds (1000);
		
		fd = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY);
		
		if (strlen(FrequencyString) < 3)
		{
			// Already a channel number
			Frequency = strtol(FrequencyString, NULL, 16);
		}
		else
		{
			// Convert from MHz to channel number
			Frequency = (int)((atof(FrequencyString) - 434.05) / 0.003124);
		}
		
		sprintf(Command, "%cch%02X\r", 0x80, Frequency);

		printf("NTX2B-FA transmitter now set to channel %02Xh which is %8.4lfMHz\n", Frequency, (double)(Frequency) * 0.003125 + 434.05);

		// Let enable line float (but Tx will pull it up anyway)
		delayMilliseconds (200);
		pinMode (NTX2B_ENABLE, INPUT);
		pullUpDnControl(NTX2B_ENABLE, PUD_OFF);
		delayMilliseconds (20);

		write(fd, Command, strlen(Command)); 
		tcsetattr(fd, TCSAFLUSH, &options);
		delayMilliseconds (50);

		close(fd);

		// Switch on the radio
		delayMilliseconds (100);
		digitalWrite (NTX2B_ENABLE, 1);
		pinMode (NTX2B_ENABLE, OUTPUT);
	}
}