Compare commits

..

No commits in common. "passthrough-and-runtime-frequency" and "master" have entirely different histories.

2 changed files with 91 additions and 182 deletions

View file

@ -1,35 +0,0 @@
dist: trusty
language: bash
cache:
directories:
- "${HOME}/persist"
addons:
apt:
packages:
- build-essential
- curl
- xvfb
install:
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
- sleep 3
- export DISPLAY=:1.0
- test -e "${HOME}/persist/arduino.tar.xz" || curl -o "${HOME}/persist/arduino.tar.xz" https://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz
- mkdir $HOME/arduino_ide
- tar -C $HOME/arduino_ide --strip-components=1 -xaf "${HOME}/persist/arduino.tar.xz"
- export PATH="$HOME/arduino_ide:$PATH"
- arduino --install-library "NeoGPS" || arduino --install-library "NeoGPS"
- mkdir -p artifacts
script:
- arduino --pref "build.path=$(pwd)/artifacts" --pref "arduino:avr:pro:cpu=8MHzatmega328" --pref "compiler.warning_level=all" --preserve-temp-files --verbose-build --verify "$(pwd)/RFout1MHzV1_05/RFout1MHzV1_05.ino"
deploy:
provider: releases
api_key:
secure: eUTHqMZp7e4eASS4GXx/qbmO71MNp1KbaQU9kQeFgXFxbOL60bOQJu7KHJUlLsmpipNZs098XRGpEcIIR6EhQ5A+28F1k8X/QClrScV2sn4BiXoXpHCQHPmhzySaLN1U5u/nTAQvZeUX5E6Or5N9NpvPtADoKKVn00bBuStM/ItH15/10RFUmJ8MMpczTvcFb+LHpFZksGJaQPxDVqXiVnyP+v9dnASdGWtqWPMUt6IaVhH13lE0eoY6AyOYozINPzsORb8JLOC8a3m7v5o1I9hlhpr3/oWhdqy0eDu+5QAOtBmZi7udr0gutnHlq/AkQkLFZvHZotRgMMqCBXQm3OAubDoxZ1aHX8KzKvjnFLvCjX8+gLDiDkiF3RQMJ21yIl1x+C6Dy0FAb/OvkWPQW1TqZPSdoMeNv6L/M4r9OdMHxqx38DuewhLkGfnVpGffo1PmK12uJ9z3qWYW2X/d5VyLzJgdU1tCOc9VjKT5QquZS5Qcy+gbIkbuLmWISN2TWZ4wPnbsm/OX8hfnODg4MbZhXDJoXpWXXDy3jVaiWqUji4MQmxBeIeWZ/vkygXhL0ez506qxC6meZedDcuqC87JhuSqFF/ou/IybfOpoOip+ovaWFwddkkm/RvOIyAKPnjyFD17e8IGzF0cYJ6mhYH3fOVwqe83+8rpJbrbWrWw=
file_glob: true
file: "artifacts/*.ino.hex"
on:
repo: jepler/1009-GPS_Derived_RF_Generator
tags: true
skip_cleanup: true

View file

@ -14,25 +14,12 @@ SoftwareSerial gpsPort(2, 3); // RX, TX
#define LEDIndicator1 5 //LED indicator for GPS Lock on pin A3
#define FIXOut 4 //Pin Out at IDC. Indicator for GPS Lock on pin 4
#define LDO_Enable A3 //GPS Voltage regulator Enable on pin A3
boolean GPSOK, passthrough;
int state; // serial command state machine
uint32_t freq; // Frequency in Hz commanded via serial
#define softwareversion "1.05" //Version of this program, sent to serialport at startup
boolean GPSOK;
const char softwareversion[] = "1.05" ; //Version of this program, sent to serialport at startup
NMEAGPS gps; // This parses the GPS characters
gps_fix fix; // This holds on to the latest values
constexpr auto MHz = 1000000lu;
constexpr auto KHz = 1000lu;
constexpr auto Hz = 1lu;
// This is a little bit arcane but it just lets you keep the user string
// and the actual value in synch automatically
#define SPEED 1
#define UNITS MHz
#define STRINGIFY1(x) #x
#define STRINGIFY(x) STRINGIFY1(x)
#define SPEED_STR STRINGIFY(SPEED) STRINGIFY(UNITS)
#define SPEED_ARG (UINT32_C(SPEED) * UNITS)
//-------------------------- SETUP -----------------------
@ -40,18 +27,9 @@ void setup()
{
Serial.begin(9600);
while (!Serial);
Serial.println(F(""));
Serial.println(F("Zachtek GPS referenced RF, Software version: " softwareversion));
if(strapped_for_passthrough()) {
pinMode(LDO_Enable, OUTPUT); // Set Voltage Regulator Enable pin as output.
digitalWrite(LDO_Enable, HIGH); //Turn on 3.1V Power supply for the Ublox GPS module
gpsPort.begin(9600);
passthrough = 1;
Serial.println(F("Strapped for passthrough. Disconnect jumper between SDA/SCL for normal operation"));
return;
}
Serial.println("");
Serial.print(F("Zachtek GPS referenced RF, Software version: "));
Serial.println(softwareversion);
pinMode(LDO_Enable, OUTPUT); // Set Voltage Regulator Enable pin as output.
@ -80,15 +58,15 @@ void setup()
delay(500);//Wait for GPSmodule to complete it's power on.
//Program GPS to output RF
if (setGPS_OutputFreq(SPEED_ARG)) {
Serial.println ("GPS Initialized to output RF at " SPEED_STR);
if (setGPS_OutputFreq1MHz()) {
Serial.println ("GPS Initialized to output RF at 1MHz");
Serial.println ("Initialization is complete.");
Serial.println ("");
GPSOK = true;
}
else
{
Serial.println (F("Error! Could not program GPS!"));
Serial.println ("Error! Could not program GPS!");
GPSOK = false;
}
}
@ -96,59 +74,11 @@ void setup()
//--------------------------
// Handle serial commands
void handle_serial() {
int c = Serial.read();
if(c == 'P') {
Serial.println(F("Entering passthrough mode -- reset microcontroller to return to normal mode\n"));
passthrough = true;
}
else if(c == 'F' || c == 'f') {
Serial.print(F("Frequency?"));
state = 1; freq = 0;
}
else if(state == 1) {
if(c >= '0' && c <= '9') {
Serial.write(c);
freq = freq * 10 + c - '0';
} else if (c == 'M' || c == 'm') {
Serial.write(c);
freq *= 1000000lu;
} else if (c == 'K' || c == 'k') {
Serial.write(c);
freq *= 1000lu;
} else if (c == '\n' || c == '\r') {
Serial.println(F(""));
if (setGPS_OutputFreq(freq)) {
Serial.print ("GPS Initialized to output RF at " );
Serial.println (freq);
Serial.println ("Initialization is complete.");
Serial.println ("");
GPSOK = true;
}
else
{
Serial.println (F("Error! Could not program GPS!"));
GPSOK = false;
}
state = 0;
}
}
}
//-------------------------- Main loop -----------------------
void loop()
{
if(passthrough) {
if(gpsPort.available()) Serial.write(gpsPort.read());
if(Serial.available()) gpsPort.write(Serial.read());
return;
}
if(Serial.available()) {
handle_serial();
}
if(state != 0) return;
while (gps.available( gpsPort )) {
fix = gps.read();
if (fix.valid.location && fix.valid.date && fix.valid.time)
@ -178,68 +108,81 @@ void loop()
//--------------------------
// For details of the UBX protocol, see
// https://www.u-blox.com/sites/default/files/products/documents/u-blox7-V14_ReceiverDescriptionProtocolSpec_%28GPS.G7-SW-12001%29_Public.pdf
// Documentation of this packet is under the heading CFG-TP5 (35.19.2) in the current documentation.
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x20, 0x1B
};
#define OFFSET_FREQUENCY_LOCKED (18)
#define OFFSET_CKSUM (38)
// Note: Normally payload_start is 2 bytes past the start of buf, because the first two bytes
// are the message type and are not checksummed.
void ubx_compute_checksum(uint8_t *payload_start, uint8_t *payload_end, uint8_t *cksum) {
uint8_t ck_a=0, ck_b=0;
for(const uint8_t *p = payload_start; p != payload_end; p++)
{
ck_a += *p;
ck_b += ck_a;
}
cksum[0] = ck_a;
cksum[1] = ck_b;
}
bool setGPS_OutputFreq(uint32_t freq) {
for(int i=0; i<4; i++) {
setOutputFreq[OFFSET_FREQUENCY_LOCKED+i] = freq & 0xff;
freq >>= 8;
}
ubx_compute_checksum(setOutputFreq+2, setOutputFreq+38, setOutputFreq+38);
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
bool gps_set_sucess = getUBX_ACK(setOutputFreq);
// Serial.println(F("Set output Freq Done"));
return gps_set_sucess;
}
bool setGPS_OutputFreq1Kz()
bool setGPS_OutputFreq100kHz()
{
return setGPS_OutputFreq(1*KHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x20, 0x1B
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
bool setGPS_OutputFreq1MHz()
{
return setGPS_OutputFreq(1*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x8A, 0x8B
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
bool setGPS_OutputFreq2MHz()
{
return setGPS_OutputFreq(2*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x80, 0x84, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x1B, 0x7F
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
bool setGPS_OutputFreq4MHz()
{
return setGPS_OutputFreq(4*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x3F, 0x8C
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
//8MHz is the highest low-jitter frequency possible
bool setGPS_OutputFreq8MHz()
{
return setGPS_OutputFreq(8*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xD4, 0x28
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
//10 MHz is very jittery. Numbers that can be done with an integer division from 48MHz will produce
@ -247,14 +190,34 @@ bool setGPS_OutputFreq8MHz()
//If 10MHz low jitter is needed then one option is to output 2MHz and then filter out the 5th overtone arriving at 10MHz in that way.
bool setGPS_OutputFreq10MHz()
{
return setGPS_OutputFreq(10*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xF6, 0x10
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
//16MHz is above the specs for lUblox Neo-6, only included for experiments.
//This will not produce as clean Square wave.
bool setGPS_OutputFreq16MHz()
{
return setGPS_OutputFreq(16*MHz);
int gps_set_sucess = 0;
uint8_t setOutputFreq[] = {
0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x24, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x60, 0x12
};
sendUBX(setOutputFreq, sizeof(setOutputFreq) / sizeof(uint8_t));
gps_set_sucess = getUBX_ACK(setOutputFreq);
//Serial.println("Set output Freq Done");
return gps_set_sucess;
}
@ -286,7 +249,10 @@ boolean getUBX_ACK(uint8_t *MSG) {
ackPacket[9] = 0; // CK_B
// Calculate the checksums
ubx_compute_checksum(ackPacket+2, ackPacket+8, ackPacket+8);
for (uint8_t ubxi = 2; ubxi < 8; ubxi++) {
ackPacket[8] = ackPacket[8] + ackPacket[ubxi];
ackPacket[9] = ackPacket[9] + ackPacket[8];
}
while (1) { // Test for success
if (ackByteID > 9) {
@ -311,26 +277,4 @@ boolean getUBX_ACK(uint8_t *MSG) {
}//else
}//If
}//While
}//getUBX_ACK
// If pins 7/8 on the 10-pin header are bridged, this is "strapped for passthrough"
// Detect this by driving one pin high and checking the other pin, then driving low and repeating
// set pins back to inputs before returning
bool strapped_for_passthrough() {
bool result = true;
pinMode(A4, OUTPUT);
digitalWrite(A4, HIGH);
delay(1);
if(!digitalRead(A5)) result = false;
digitalWrite(A4, LOW);
pinMode(A5, INPUT_PULLUP);
delay(1);
if(digitalRead(A5)) result = false;
pinMode(A4, INPUT);
pinMode(A5, INPUT);
return result;
}
}//getUBX_ACK