Skip to content

Commit 7f0e8d7

Browse files
committed
Tested and working with the emulator
1 parent cc1a76f commit 7f0e8d7

File tree

10 files changed

+203
-154
lines changed

10 files changed

+203
-154
lines changed

examples/Example01_AlternateAddress/Example01_AlternateAddress.ino

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
By: Paul Clark
77
SparkFun Electronics
8-
Date: 2024/8/1
8+
Date: 2024/11/21
99
SparkFun code, firmware, and software is released under the MIT License.
1010
Please see LICENSE.md for further details.
1111
@@ -31,9 +31,9 @@ void setup()
3131
Wire.begin(); // Begin the I2C bus
3232

3333
bool begun;
34-
begun = myOCXO.begin(Wire, 0x60); // Initialize the SiT5811 - using a custom bus and address
35-
begun = myOCXO.begin(0x60); // This is also possible. It defaults to Wire
36-
begun = myOCXO.begin(); // This is also possible. It defaults to Wire and address 0x60
34+
begun = myOCXO.begin(Wire, 0x50); // Initialize the SiT5811 - using a custom bus and address
35+
begun = myOCXO.begin(0x50); // This is also possible. It defaults to Wire
36+
begun = myOCXO.begin(); // This is also possible. It defaults to Wire and address 0x50
3737

3838
if (!begun)
3939
{
@@ -42,14 +42,13 @@ void setup()
4242
}
4343

4444
// Read the frequency control word - should be zero initially
45-
int32_t fcw = myOCXO.getFrequencyControlWord();
45+
int64_t fcw = myOCXO.getFrequencyControlWord();
4646
Serial.print("The frequency control word is: ");
4747
Serial.println(fcw);
4848

49-
// Read the pull range control
50-
uint8_t prc = myOCXO.getPullRangeControl();
51-
Serial.print("Pull range control is: ");
52-
Serial.println(myOCXO.getPullRangeControlText(prc));
49+
// Read the available (clipped) pull range
50+
double pullAvailable = myOCXO.getMaxPullAvailable();
51+
Serial.printf("Maximum frequency pull is: %e\r\n", pullAvailable);
5352
}
5453

5554
void loop()

examples/Example02_setFrequencyHz/Example02_setFrequencyHz.ino

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
By: Paul Clark
55
SparkFun Electronics
6-
Date: 2024/8/1
6+
Date: 2024/11/21
77
SparkFun code, firmware, and software is released under the MIT License.
88
Please see LICENSE.md for further details.
99
@@ -40,18 +40,14 @@ void setup()
4040
Serial.print(myOCXO.getBaseFrequencyHz());
4141
Serial.println(" Hz");
4242

43-
myOCXO.setPullRangeControl(SiT5811_PULL_RANGE_200ppm); // Set the pull range control to 200ppm
44-
45-
Serial.print("Pull range control set to ");
46-
Serial.println(myOCXO.getPullRangeControlText(myOCXO.getPullRangeControl()));
47-
48-
myOCXO.setFrequencyHz(10001000.0); // Set the frequency to 10.001MHz (+100ppm)
43+
myOCXO.setFrequencyHz(10000010.0); // Set the frequency to 10.000010MHz (+1ppm)
4944

5045
Serial.print("Frequency set to ");
5146
Serial.print(myOCXO.getFrequencyHz());
5247
Serial.println(" Hz");
5348

54-
Serial.print("Frequency control word should be 16777215. It is ");
49+
// Frequency control word should be 1ppm / 800ppm * (2^38 - 1) , rounded down
50+
Serial.print("Frequency control word should be 343597383. It is ");
5551
Serial.println(myOCXO.getFrequencyControlWord());
5652
}
5753

examples/Example03_IllegalFrequency/Example03_IllegalFrequency.ino

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
By: Paul Clark
77
SparkFun Electronics
8-
Date: 2024/8/1
8+
Date: 2024/11/21
99
SparkFun code, firmware, and software is released under the MIT License.
1010
Please see LICENSE.md for further details.
1111
@@ -42,18 +42,28 @@ void setup()
4242
Serial.print(myOCXO.getBaseFrequencyHz());
4343
Serial.println(" Hz");
4444

45-
myOCXO.setPullRangeControl(SiT5811_PULL_RANGE_200ppm); // Set the pull range control to 200ppm
45+
// Read the available (clipped) pull range
46+
double pullAvailable = myOCXO.getMaxPullAvailable();
47+
Serial.printf("Maximum frequency pull is: %e\r\n", pullAvailable);
4648

47-
Serial.print("Pull range control set to ");
48-
Serial.println(myOCXO.getPullRangeControlText(myOCXO.getPullRangeControl()));
49+
double lowestFrequency = 10e6 - (10e6 * pullAvailable);
50+
Serial.print("The lowest frequency available is ");
51+
Serial.print(lowestFrequency);
52+
Serial.println(" Hz");
4953

5054
myOCXO.setFrequencyHz(9900000.0); // Try to set the frequency to 9.9MHz (-10000ppm)
5155

5256
Serial.print("Frequency set to ");
5357
Serial.print(myOCXO.getFrequencyHz());
5458
Serial.println(" Hz");
5559

56-
Serial.print("Frequency control word should be -33554432. It is ");
60+
double fractionalPull = pullAvailable / 800e-6; // Fractional pull compared to 800ppm
61+
fractionalPull *= pow(2, 38); // Convert to expected control word
62+
int64_t expectedControlWord = 0 - fractionalPull;
63+
64+
Serial.print("Frequency control word should be ");
65+
Serial.print(expectedControlWord);
66+
Serial.print(". It is ");
5767
Serial.println(myOCXO.getFrequencyControlWord());
5868
}
5969

examples/Example04_setFrequencyByBiasMillis/Example04_setFrequencyByBiasMillis.ino

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,24 @@
66
77
By: Paul Clark
88
SparkFun Electronics
9-
Date: 2024/8/1
9+
Date: 2024/11/21
1010
SparkFun code, firmware, and software is released under the MIT License.
1111
Please see LICENSE.md for further details.
1212
13-
Consider the SiT5811AI-FS033IT-10.000000 used on the SparkFun RTK mosaic-T:
13+
Consider the SiT5811AI-KYG33IV-10.000000:
1414
The operating temperature range is Industrial, -40 to 85°C (option "I").
1515
LVCMOS output (option "-").
16-
Frequency stability +/-50ppb (option "S").
17-
It is OCXO with an I2C address of 0x60 (option "0").
16+
Frequency stability +/-1ppb (option "Y").
17+
It is DCOCXO with a configurable I2C address (option "G").
1818
Supply voltage 3.3V (option "33").
1919
Pin 1 is Output Enable (option "I"). (No software OE control).
20-
The default pull range is 6.25ppm (option "T").
20+
The pull range limit is 3.125ppm (option "V").
2121
Base frequency is 10.000000MHz.
2222
2323
Consider this example:
2424
* The OCXO frequency has not yet been changed. It is running at the default 10.000000 MHz.
2525
* 10.000000 MHZ is the library default base frequency. But we could set it with setBaseFrequencyHz(10000000.0)
26-
* The pull range is read during begin. But we could set it with setPullRangeControl(SiT5811_PULL_RANGE_6ppm25)
26+
* The available pull range is read during begin.
2727
* The mosaic-T manual states that the oscillator frequency should be changed by no more than 3ppb per second.
2828
* We tell the library this using setMaxFrequencyChangePPB(3.0)
2929
* The GNSS RxClkBias reports that receiver time is ahead of system time by 200 nanoseconds (+200ns).
@@ -33,8 +33,8 @@
3333
* To remove that bias in one second, the oscillator frequency would need to be reduced to 9.999998 MHz.
3434
* That is a change of 2 parts in 10000000, or 0.2ppm, or 200ppb.
3535
* The frequency change will be limited to 3ppb.
36-
* Since the SiT5811 Pull Range is set to 6.25ppm, and the Pull Register is 26-bit signed, 3ppb corresponds to 16106 LSB.
37-
* The firmware writes the value -16106 to the Frequency Control Register, reducing the frequency to 9.99999997 MHz.
36+
* Since the SiT5811 maximum Pull Range is 800ppm, and the Pull Register is 39-bit signed, 3ppb corresponds to 1030792 LSB.
37+
* The firmware writes the value -1030792 to the Frequency Control Register, reducing the frequency to 9.99999997 MHz.
3838
* getFrequencyHz will return 9999999.97
3939
4040
*/
@@ -70,24 +70,25 @@ void setup()
7070
Serial.print(myOCXO.getBaseFrequencyHz());
7171
Serial.println(" Hz");
7272

73-
myOCXO.setPullRangeControl(SiT5811_PULL_RANGE_6ppm25); // Set the pull range control to 6.25ppm
74-
75-
Serial.print("Pull range control set to ");
76-
Serial.println(myOCXO.getPullRangeControlText(myOCXO.getPullRangeControl()));
77-
7873
myOCXO.setMaxFrequencyChangePPB(3.0); // Set the maximum frequency change in PPB
7974

8075
Serial.print("Maximum frequency change set to ");
8176
Serial.print(myOCXO.getMaxFrequencyChangePPB());
8277
Serial.println(" PPB");
8378

84-
myOCXO.setFrequencyByBiasMillis(200.0e-6); // Set the frequency by clock bias (+200ns, +200e-6ms)
79+
Serial.print("Frequency control word should be 0. It is ");
80+
Serial.println(myOCXO.getFrequencyControlWord());
81+
82+
Serial.println("Applying a clock bias of +200ns");
83+
// Set the frequency by clock bias (+200ns, +200e-6ms)
84+
// For this test, set the P term to 1.0 and the I term to 0.0
85+
myOCXO.setFrequencyByBiasMillis(200.0e-6, 1.0, 0.0);
8586

8687
Serial.print("Frequency should be 9999999.97 Hz. It is ");
8788
Serial.print(myOCXO.getFrequencyHz());
8889
Serial.println(" Hz");
8990

90-
Serial.print("Frequency control word should be -16106. It is ");
91+
Serial.print("Frequency control word should be -1030792. It is ");
9192
Serial.println(myOCXO.getFrequencyControlWord());
9293
}
9394

examples/SiT5358_Emulator/SiT5358_Emulator.ino

Lines changed: 0 additions & 97 deletions
This file was deleted.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Emulate the SiT5811 OCXO.
3+
4+
By: Paul Clark
5+
SparkFun Electronics
6+
Date: 2024/11/21
7+
SparkFun code, firmware, and software is released under the MIT License.
8+
Please see LICENSE.md for further details.
9+
10+
Note: This code doesn't update the registerAddress correctly - on ESP32 (3.0.1).
11+
registerAddress is only updated _after_ the registers have been read...
12+
SfeSiT5811Driver::begin() calls readClipRegister() and readRegisters()
13+
twice, to ensure registerAddress points at 0x00 and 0x0C correctly.
14+
15+
*/
16+
17+
#include <Wire.h>
18+
19+
#define I2C_DEV_ADDR 0x50
20+
21+
// Emulate registers 0x00 (DCXO Clip) to 0x0E (DCXO LSW) (16-bit, MSB first)
22+
#define CLIP 0x00 // Change to (e.g.) 0x08 to emulate 200ppm clip range.
23+
#define NUM_REG_BYTES (15*2)
24+
volatile uint8_t registerBytes[NUM_REG_BYTES];
25+
volatile uint8_t registerAddress = 0;
26+
27+
// On Request:
28+
// Write bytes from registerBytes, starting at registerAddress * 2
29+
void requestHandler()
30+
{
31+
int i = registerAddress * 2;
32+
for (; i < NUM_REG_BYTES; i++)
33+
Wire.write(registerBytes[i]);
34+
}
35+
36+
// On Receive:
37+
// Copy the first incoming byte into registerAddress (see notes above)
38+
// Copy the remaining bytes into registerBytes, starting at registerAddress * 2
39+
void receiveHandler(int len)
40+
{
41+
int count = -1;
42+
while (Wire.available())
43+
{
44+
uint8_t b = Wire.read();
45+
switch (count)
46+
{
47+
case -1:
48+
registerAddress = b;
49+
break;
50+
default:
51+
if (((registerAddress * 2) + count) < NUM_REG_BYTES)
52+
registerBytes[((registerAddress * 2) + count)] = b;
53+
break;
54+
}
55+
count++;
56+
}
57+
}
58+
59+
void setup()
60+
{
61+
// Initialize the register bytes
62+
for (int i = 0; i < NUM_REG_BYTES; i++)
63+
registerBytes[i] = 0;
64+
registerBytes[0] = CLIP; // Store in OCXO Clip MSB
65+
66+
delay(1000); // Allow time for the microcontroller to start up
67+
68+
Serial.begin(115200); // Begin the Serial console
69+
while (!Serial)
70+
{
71+
delay(100); // Wait for the user to open the Serial Monitor
72+
}
73+
Serial.println("SparkFun SiT5811 Emulator");
74+
75+
Wire.onReceive(receiveHandler);
76+
Wire.onRequest(requestHandler);
77+
Wire.begin((uint8_t)I2C_DEV_ADDR);
78+
}
79+
80+
void loop()
81+
{
82+
static unsigned long lastPrint = 0;
83+
84+
if (millis() > (lastPrint + 1000))
85+
{
86+
lastPrint = millis();
87+
88+
// Extract the 39-bit Frequency Control Word
89+
uint64_t freqControl = ((uint64_t)registerBytes[28]) >> 1;
90+
freqControl |= ((uint64_t)registerBytes[27]) << 7;
91+
freqControl |= ((uint64_t)registerBytes[26]) << 15;
92+
freqControl |= ((uint64_t)registerBytes[25]) << 23;
93+
freqControl |= ((uint64_t)registerBytes[24]) << 31;
94+
if (freqControl & 0x0000004000000000) // Correct two's complement
95+
freqControl |= 0xFFFFFFC000000000;
96+
97+
union // Avoid any ambiguity when converting uint64_t to int64_t
98+
{
99+
uint64_t unsigned64;
100+
int64_t signed64;
101+
} unsignedSigned64;
102+
unsignedSigned64.unsigned64 = freqControl;
103+
104+
Serial.print("Frequency control is ");
105+
Serial.println(unsignedSigned64.signed64);
106+
}
107+
}

0 commit comments

Comments
 (0)