Skip to content

Commit

Permalink
Big commit due lost of sync with local repo, sorry
Browse files Browse the repository at this point in the history
  • Loading branch information
stdevPavelmc committed Apr 24, 2017
1 parent f81f45d commit cde329a
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 127 deletions.
28 changes: 28 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Si5351mcu Changelog File #

## v0.2rc (April 23, 2017) ##

* Added power level support for each output independently, watch out!: setting the power level will enable the output.
* Set default power to the lowest one (2mA) from the maximun possible (8mA).
* Fixed the need for a reset after each correction, it does it now automatically
* Added a init function to pass a custom xtal
* Modified the example to show no need for a init unless you use a different xtal
* Improved the keywords.txt file to improve edition on the Arduino IDE
* Included a "features" section on the README.md

## v0.1rc (April 20, 2017) ##

* Added enable(), disable() and off() functions.
* Added support for handling all the three outputs of the Si5351A, (CLK1 & CLK2 are mutually-exclusive)
* Updated the example with the new functions.
* Improved library logic by reusing and optimizing functions.
* Improved the documentation and comments (lib code, README and example)
* The compiled code is slightly smaller now (~1% on an ATMega328p)
* Added Changelog and version files.
* Extensive tests made to validate every function.


## Initial Release, v0.0 (April 9, 2017) ##

* Basic functionality.

102 changes: 58 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
# Arduino Si5351 Library tuned for size and click free. #
# Arduino Si5351 Library tuned for size and click noise free. #

This library is tuned for size and MCU operation, it will control only CLK0 and CLK1 outputs (for now).
This library is tuned for size on the Arduino (MCU) platform, it will control CLK0, CLK1 and CLK2 outputs for the Si5351A (the version with just 3 clocks out).

It's click free, with some provisions, keep readding
But there is not such thing as free lunch: please read the *Two of three* section below; and sure it's click free with some provisions, keep reading.

## Inspiration ##

This work is based on the previous work of these people:
This work is based on the previous work of these great people:

* [www.etherkit.com](https://www.etherkit.com) the full featured lib, with big code as well.
* [QRP Labs demo libs](http://qrp-labs.com/synth/si5351ademo.html) the smallest and simple ones on the net.
* [DK7IH demo code](https://radiotransmitter.wordpress.com/category/si5351a/) the first click-less code on the wild.
* [Etherkit/NT7S:](https://github.com/etherkit/Si5351Arduino) The mainstream full featured lib, with big code as well.
* [QRP Labs demo code:](http://qrp-labs.com/synth/si5351ademo.html) The smallest and simple ones on the net.
* [DK7IH demo code:](https://radiotransmitter.wordpress.com/category/si5351a/) The first clickless noise code on the wild.

## Click-less ##
## Features ##

This are so far the implemented features (Any particular wish? use the Issues tab for that):

* Custom XTAL passing on init (default is 27.0MHz)
* You are able to pass a correction to the xtal while running (as for your own calibration procedure)
* You have a fast way to power off all outputs of the Chip.
* You can enable/disable any output at any time.
* You can only have 2 of the 3 outputs running at any moment, see "Two of three" below.
* It's free of click noise while you move on frequency.
* **NEW!** Power control on each output independently (see setPower(clk, level) on the lib header, initial default is to lowest level: 2mA)

## Click noise free ##

The click noise while tunning the chip came from the following actions (stated in the datasheet & app notes):

Expand All @@ -28,24 +40,38 @@ In my tests I can move across several Mhz (1 to 10, 28 to 150) without getting o

## The start sequence is important ##

Yes, in your setup() code segment you must initialize it in the following sequence:
Yes, in your setup code segment you must initialize it in the following sequence:

* Apply correction factor (if needed)
* (Optional) power off all outputs
* Set sweet spots frequencies to **both** clock outputs
* Force a reset of the PLLs.

In the example code you can see this inside the setup function:
Here you have an example code of what I mean ("Si" is the lib instance):

```
setup() {
(... my great code here ...)
//////////////////////////////////
// Si5351 functions
//////////////////////////////////
// apply my calculated correction factor
pll.correction(-1250);
Si.correction(-1250);
// Optional, power off all outputs until needed
Si.off();
// set some freqs
pll.setFreq(0, 25000000); // CLK0 output
pll.setFreq(1, 145000000); // CLK1 output
// set some sweet spot freqs
Si.setFreq(0, 25000000); // CLK0 output
Si.setFreq(1, 145000000); // CLK1 output
// force the first reset
pll.reset();
Si.reset();
(... other great code here ...)
}
```

Expand All @@ -54,51 +80,39 @@ When I write "sweet spots frequencies" I write about some middle frequencies in
For example if you use CLK0 for VFO and CLK1 for BFO for a 40m receiver with 10 Mhz IF and upper injection I will suggest this code segment in your setup:

```
// apply my calculated correction factor
pll.correction(-1250);
// set some freqs
pll.setFreq(0, 17150000); // VFO 7.150 Mhz (mid band) + 10.0 Mhz
pll.setFreq(1, 10000000); // BFO 10.0 Mhz
// set some sweet spot freqs
Si.setFreq(0, 17150000); // VFO 7.150 Mhz (mid band) + 10.0 Mhz
Si.setFreq(1, 10000000); // BFO 10.0 Mhz
// force the first reset
pll.reset();
Si.reset();
```

## Normal operation ##

After the setup process you can setup any freq to any of the two outputs (CLK0 or CLK1) via the setFreq(CLK, FREQ) procedure as usual.

If you get in trouble (freq not in the exact spot, or other weird things) after moving in steps of more than 10 Mhz or in the lower edge of the coverage (below 3 Mhz) just make a **single** reset() and all will be ok again. This just happened one time to me in the dev process so far, in the present code I don't see this effect any more, but I mentioned it "just in case".

If you found a trouble like this I would like to hear about it to try to fix that, this is beta code and is the first iteration, it may contain some bugs or typos.
If you need to apply/vary the correction factor **after** the setup process you will get a click noise on the next setFreq() to apply the changes.

If you need to apply/vary the correction factor **after** the setup process (like in a own calibration routine) you will get a click noise on the next setFreq() to apply the changes, so, if you do it repeatedly it will have click noise on it, that perfectly normal.
## Two of three ##

## Installation ##
Yes, there is a tittle catch here with CLK1 and CLK2: both share PLL_B and as we use math to produce an integer division you can only use one of them at a time.

Just go to the [Github repository page (this page)](https://github.com/pavelmc/Si5351mcu/) and click on the "Clone or Download" green button, select download and download it to your PC.
Note: _In practice you can, but the other will move from the frequency you set, which is odd, so I made them mutually exclusive._

The file name will be like this: Si5351mcu-master.zip, you must extract the files and put them in a folder called "Si5351mcu" inside your "Libraries" arduino folder.
This are the valid combinations for independent clocks output.

Restart your Arduino IDE software and that's all.
* CLK0 and CLK1
* CLK0 and CLK2

## Assumptions ##

This lib assume this facts:

* The Si5351 is set to put a 8 pF across the XTAL.
* The CLK outputs are set to full power (8 mA over 50 ohms)
* At the moment the CLK2 will not be used.
Again: You can't use CLK1 and CLK2 at the same time, as soon as you set one of them the other will shut off. That's why you get two of three and one of them must be always CLK0.

## Author & contributors ##

The only author is Pavel Milanes, CO7WT, reachable at [email protected], contributors and sponsors are welcomed.
The only author is Pavel Milanes, CO7WT, a cuban amateur radio operator; reachable at [email protected], Until now I have no contributors or sponsors.

## Where to download the latest version? ##

Always download the latest version from the [Github repository](https://github.com/pavelmc/Si5351mcu/)
Always download the latest version from the [github repository](https://github.com/pavelmc/Si5351mcu/)

See ChangeLog.md on this repository to know what are the latest changes.

## If you like to give thanks... ##

Expand All @@ -111,4 +125,4 @@ If you like to do so, please go to Ding, select Cuba, select Cubacell (for phone
* For phone topup use this number (My cell, feel free to call me if you like): +53 538-478-19
* For internet time use this user: [email protected] (that's not an email but an user account name)

Thanks before hand.
Thanks!
135 changes: 91 additions & 44 deletions examples/si5351_mcu/si5351_mcu.ino
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
* all GNU GPL licenced:
* - Linux Kernel (www.kernel.org)
* - Hans Summers libs and demo code (qrp-labs.com)
* - Etherkit Si5351 libs on github
* - DK7IH examples.
* - Etherkit (NT7S) Si5351 libs on github
* - DK7IH example.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -29,81 +29,128 @@

/***************************************************************************
* This example is meant to be monitored with an RTL-SDR receiver
* but you can change the frequency and other vars to test with your hardware
* but you can change the frequency and other vars to test with your hardware.
*
* Take into account your XTAL error, see pll.correction(###) below
* Set your SDR software to monitor from 60 to 62 Mhz.
*
* This will set 60.0 Mhz in clock 0, put and alternating frequencies
* at 60.5 and 61.0 Mhz on CLK1 and CLK2 to show they are mutually exclusive.
*
* Then make a sweep from 60 to 62 Mhz on CLK2, with an stop every 200Khz
* and then a train of one second pulses will follow with varying power levels
*
* Take into account your XTAL error, see Si.correction(###) below
*
***************************************************************************/

#include "si5351mcu.h"
#include "Wire.h"

// lib instantiation as "pll"
Si5351mcu pll;
// lib instantiation as "Si"
Si5351mcu Si;

// Stop every X Mhz for Y seconds to measure
#define EVERY 1000000 // stop every 1Mhz for...
#define SECONDS 15000 // 15 seconds
#define EVERY 200000 // stop every 200khz
#define DANCE 3 // 3 seconds

// some variables
long freqStart = 26000000; // 26.0 MHz
long freqStop = 150000000; // 150.0 MHz
long freqStart = 60000000; // 60.0 MHz
long freqStop = 62000000; // 62.0 MHz
long step = 10000; // 10.0 kHz
long freq = freqStart;
long newStop = freq + EVERY;


void setup() {
// init the wire lib
Wire.begin();

// apply my calculated correction factor
pll.correction(-1250);

// set some freq
pll.setFreq(0, 25000000); // CLK0 output
pll.setFreq(1, 145000000); // CLK1 output

// force the first reset
pll.reset();

// 30 seconds delay for calibration
delay(30000);

// serial welcome
Serial.begin(115200);
Serial.println("Test for Si5351 click-less lib optimized for MCU");
// init the Si5351 lib
// this lib doesn't need an init function unless you need to pass a
// different xtal (from the default of 27.00000 Mhz)
// Si.init(26570000);

// set & apply my calculated correction factor
Si.correction(-1250);

// pre-load some sweet spot freqs
Si.setFreq(0, freqStart);
Si.setFreq(1, freqStart);

// disable all outputs and reset the PLLs
Si.off();
Si.reset();

// put a tone in the start freq on CLK0
Si.setFreq(0, freqStart);
Si.enable(0);

// make the dance on the two outputs
Si.setFreq(1, freqStart + 500000); // CLK1 output
Si.enable(1);
delay(3000);
// Si.disable(1); // no need to disable, enabling CLK2 disable this

Si.setFreq(2, freqStart + 1000000); // CLK2 output
Si.enable(2);
delay(3000);
//Si.disable(2); // no need to disable, enabling CLK1 disable this

Si.setFreq(1, freqStart + 500000); // CLK1 output
Si.enable(1);
delay(3000);
//Si.disable(1); // no need to disable, enabling CLK2 disable this

Si.setFreq(2, freqStart + 1000000); // CLK2 output
Si.enable(2);
delay(3000);
Si.disable(2); // this is the last in the dance, disable it

// shut down CLK0
Si.disable(0);

// set CLK2 to the start freq
Si.setFreq(2, freqStart); // it's disabled by now
}


void loop() {
// check for the stop to measure
if (freq >= newStop) {
// yes it's time to measure

// alert via serial
Serial.print("Frequency: ");
Serial.print(freq);
Serial.println(" Hz");

// stop for this time to measure
delay(SECONDS);

// reset the flag
newStop = freq + EVERY;
} else {
// time to move
if ((freq % EVERY) == 0) {
// it's time to flip-flop it

for (byte i = 0; i < 4; i++) {
// power off the clk2 output
Si.disable(2);
delay(500);
// power mod, the lib define some macros for that:
// SIOUT_2mA, SIOUT_4mA, SIOUT_6mA and SIOUT_8mA
//
// But they are incidentally matching the 0 to 3 count..
// so I will use the cycle counter for that (i)
//
// moreover, setting the power on an output will enable it
// so I will explicit omit the enable here
Si.setPower(2,i);
//Si.enable(2);
delay(1000);
}

// reset the power to low
Si.setPower(2, SIOUT_2mA);

// set it for the new cycle
freq += step;
} else {
// check if we are on the limits
if (freq <= freqStop) {
// no, set and increment
pll.setFreq(0,freq); // but it can be with CLK1 instead
Si.setFreq(2,freq); // but it can be with CLK0 or CLK1 instead

// set it for the new cycle
freq += step;

// a short delay to slow things a little.
delay(10);
delay(50);
} else {
// we reached the limit, reset to start
freq = freqStart;
Expand Down
14 changes: 12 additions & 2 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
Si5351mcu KEYWORD1

init KEYWORD2
correction KEYWORD2
12cWrite KEYWORD2
i2cWrite KEYWORD2
reset KEYWORD2
setFreq KEYWORD2
enable KEYWORD2
disable KEYWORD2
setPower KEYWORD2

XTAL LITERAL1
SIXTAL LITERAL1
SIADDR LITERAL1
SIOUT_2mA LITERAL1
SIOUT_4mA LITERAL1
SIOUT_6mA LITERAL1
SIOUT_8mA LITERAL1
SICLK0_R LITERAL1
SICLK12_R LITERAL1
Loading

0 comments on commit cde329a

Please sign in to comment.