Files
openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp
T
kaltenbe 051a4e2aa5 added Si5351C directory
changes in lmslib.cpp
2016-02-11 10:04:36 +01:00

873 lines
22 KiB
C++

/**
@file Si5351C.cpp
@author Lime Microsystems
@brief Configuring of Si5351C
*/
#include "Si5351C.h"
#include "lmsComms.h"
#include <math.h>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <set>
#include <string.h>
#include <assert.h>
#include <iostream>
using namespace std;
#define Log(msg, type) cout << (msg) << endl;
/// Splits float into fraction integers A + B/C
void realToFrac(const float real, int &A, int &B, int &C)
{
A = (int)real;
B = (int)((real - A) * 1048576 + 0.5);
C = 1048576;
int a = B;
int b = C;
int temp;
while( b!= 0) // greatest common divider
{
temp = a % b;
a = b;
b = temp;
}
B = B/a;
C = C/a;
}
/// Default configuration
const unsigned char Si5351C::m_defaultConfiguration[] =
{ 0,0x00,
1,0x00,
2,0x08,
3,0x00,
4,0x00,
5,0x00,
6,0x00,
7,0x00,
8,0x00,
9,0x00,
10,0x00,
11,0x00,
12,0x00,
13,0x00,
14,0x00,
15,0x04,
16,0x4F,
17,0x4F,
18,0x4F,
19,0x4F,
20,0x4F,
21,0x4F,
22,0x0F,
23,0x0F,
24,0x00,
25,0x00,
26,0x00,
27,0x80,
28,0x00,
29,0x0B,
30,0x2F,
31,0x00,
32,0x00,
33,0x00,
34,0x00,
35,0x00,
36,0x00,
37,0x00,
38,0x00,
39,0x00,
40,0x00,
41,0x00,
42,0x00,
43,0x01,
44,0x00,
45,0x0D,
46,0x00,
47,0x00,
48,0x00,
49,0x00,
50,0x00,
51,0x01,
52,0x00,
53,0x0D,
54,0x00,
55,0x00,
56,0x00,
57,0x00,
58,0x00,
59,0x01,
60,0x00,
61,0x0D,
62,0x00,
63,0x00,
64,0x00,
65,0x00,
66,0x00,
67,0x01,
68,0x00,
69,0x0D,
70,0x00,
71,0x00,
72,0x00,
73,0x00,
74,0x00,
75,0x01,
76,0x00,
77,0x0D,
78,0x00,
79,0x00,
80,0x00,
81,0x00,
82,0x00,
83,0x01,
84,0x00,
85,0x0D,
86,0x00,
87,0x00,
88,0x00,
89,0x00,
90,0x1E,
91,0x1E,
92,0x00,
93,0x00,
94,0x00,
95,0x00,
96,0x00,
97,0x00,
98,0x00,
99,0x00,
100,0x00,
101,0x00,
102,0x00,
103,0x00,
104,0x00,
105,0x00,
106,0x00,
107,0x00,
108,0x00,
109,0x00,
110,0x00,
111,0x00,
112,0x00,
113,0x00,
114,0x00,
115,0x00,
116,0x00,
117,0x00,
118,0x00,
119,0x00,
120,0x00,
121,0x00,
122,0x00,
123,0x00,
124,0x00,
125,0x00,
126,0x00,
127,0x00,
128,0x00,
129,0x00,
130,0x00,
131,0x00,
132,0x00,
133,0x00,
134,0x00,
135,0x00,
136,0x00,
137,0x00,
138,0x00,
139,0x00,
140,0x00,
141,0x00,
142,0x00,
143,0x00,
144,0x00,
145,0x00,
146,0x00,
147,0x00,
148,0x00,
149,0x00,
150,0x00,
151,0x00,
152,0x00,
153,0x00,
154,0x00,
155,0x00,
156,0x00,
157,0x00,
158,0x00,
159,0x00,
160,0x00,
161,0x00,
162,0x00,
163,0x00,
164,0x00,
165,0x00,
166,0x00,
167,0x00,
168,0x00,
169,0x00,
170,0x00,
171,0x00,
172,0x00,
173,0x00,
174,0x00,
175,0x00,
176,0x00,
177,0x00,
178,0x00,
179,0x00,
180,0x00,
181,0x30,
182,0x00,
183,0xD2,
184,0x60,
185,0x60,
186,0x00,
187,0xC0,
188,0x00,
189,0x00,
190,0x00,
191,0x00,
192,0x00,
193,0x00,
194,0x00,
195,0x00,
196,0x00,
197,0x00,
198,0x00,
199,0x00,
200,0x00,
201,0x00,
202,0x00,
203,0x00,
204,0x00,
205,0x00,
206,0x00,
207,0x00,
208,0x00,
209,0x00,
210,0x00,
211,0x00,
212,0x00,
213,0x00,
214,0x00,
215,0x00,
216,0x00,
217,0x00,
218,0x00,
219,0x00,
220,0x00,
221,0x0D,
222,0x00,
223,0x00,
224,0x00,
225,0x00,
226,0x00,
227,0x00,
228,0x00,
229,0x00,
230,0x00,
231,0x00,
232,0x00};
// ---------------------------------------------------------------------------
Si5351C::Si5351C()
{
memset(m_newConfiguration, 0, 255);
for(unsigned int i=0; i<sizeof(m_defaultConfiguration); i+=2)
{
m_newConfiguration[m_defaultConfiguration[i]] = m_defaultConfiguration[i+1];
}
device = NULL;
}
// ---------------------------------------------------------------------------
Si5351C::~Si5351C()
{
}
/** @brief Sends Configuration to Si5351C
*/
Si5351C::Status Si5351C::UploadConfiguration()
{
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_SI5351_WR;
if (!device)
return FAILED;
//Disable outputs
pkt.outBuffer.push_back(3);
pkt.outBuffer.push_back(0xFF);
//Power down all output drivers
for(int i=0; i<8; ++i)
{
pkt.outBuffer.push_back(16 + i);
pkt.outBuffer.push_back(0x84);
}
//write new configuration
for (int i = 15; i <= 92; ++i)
{
pkt.outBuffer.push_back(i);
pkt.outBuffer.push_back(m_newConfiguration[i]);
}
for (int i = 149; i <= 170; ++i)
{
pkt.outBuffer.push_back(i);
pkt.outBuffer.push_back(m_newConfiguration[i]);
}
//apply soft reset
pkt.outBuffer.push_back(177);
pkt.outBuffer.push_back(0xAC);
//Enabe desired outputs
pkt.outBuffer.push_back(3);
pkt.outBuffer.push_back(m_newConfiguration[3]);
if( !device->IsOpen() )
{
return FAILED;
}
LMScomms::TransferStatus status;
status = device->TransferPacket(pkt);
if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD)
{
return FAILED;
}
return SUCCESS;
}
// ---------------------------------------------------------------------------
/**
@brief Sets connection manager to use for data transferring Si5351C
@param mng connection manager for data transferring
*/
void Si5351C::Initialize(LMScomms *mng)
{
assert(mng != nullptr);
device = mng;
}
/**
@brief Loads register values for Si5356A from file
@param FName input filename
*/
bool Si5351C::LoadRegValuesFromFile(string FName)
{
fstream fin;
fin.open(FName.c_str(), ios::in);
const int len = 1024;
char line[len];
int addr;
int value;
while(!fin.eof())
{
fin.getline(line, len);
if( line[0] == '#')
continue;
if( strcmp(line, "#END_PROFILE") == 0)
break;
sscanf(line, "%i,%x",&addr,&value);
m_newConfiguration[addr] = value;
}
fin.close();
return false;
};
/** @brief Calculates multisynth dividers and VCO frequencies
@param clocks output clocks configuration
@param plls plls configurations
@param Fmin lowest VCO frequency
@param Fmax highest VCO frequency
*/
void Si5351C::FindVCO(Si5351_Channel *clocks, Si5351_PLL *plls, const unsigned long Fmin, const unsigned long Fmax)
{
int clockCount = 8;
//reset output parameters
for(int i=0; i<clockCount; i++)
{
clocks[i].pllSource = 0;
clocks[i].int_mode = 0;
clocks[i].multisynthDivider = 8;
}
bool clk6satisfied = !clocks[6].powered;
bool clk7satisfied = !clocks[7].powered;
bool pllAused = false;
bool pllBused = false;
map< unsigned long, int> availableFrequenciesPLLA; //all available frequencies for VCO
map< unsigned long, int> availableFrequenciesPLLB; //all available frequencies for VCO
//if clk6 or clk7 is used make available frequencies according to them
if(clocks[6].powered || clocks[7].powered)
{
set<unsigned long> clk6freqs;
set<unsigned long> clk7freqs;
set<unsigned long> sharedFreqs;
unsigned int mult = 6;
if(!clk6satisfied)
{
unsigned long freq = clocks[6].outputFreqHz;
while(freq <= Fmax && mult <= 254)
{
freq = clocks[6].outputFreqHz*mult;
if(freq >= Fmin && freq <= Fmax)
{
clk6freqs.insert(freq);
}
mult += 2;
}
}
mult = 6;
if(!clk7satisfied)
{
unsigned long freq = clocks[7].outputFreqHz;
while(freq <= Fmax && mult <= 254)
{
freq = clocks[7].outputFreqHz*mult;
if(freq >= Fmin && freq <= Fmax)
{
clk7freqs.insert(freq);
}
mult += 2;
}
}
bool canShare = false;
//find if clk6 and clk7 can share the same pll
for (set<unsigned long>::iterator it6=clk6freqs.begin(); it6!=clk6freqs.end(); ++it6)
{
for (set<unsigned long>::iterator it7=clk7freqs.begin(); it7!=clk7freqs.end(); ++it7)
{
if(*it6 == *it7)
{
canShare = true;
sharedFreqs.insert(*it6);
}
}
}
if(canShare) //assign PLLA for both clocks
{
clocks[6].pllSource = 0;
clocks[7].pllSource = 0;
pllAused = true;
for (set<unsigned long>::iterator it=sharedFreqs.begin(); it!=sharedFreqs.end(); ++it)
{
availableFrequenciesPLLA.insert( pair<unsigned long, int> (*it, 0) );
}
clk6satisfied = true;
clk7satisfied = true;
}
else //if clocks 6 and 7 can't share pll, assign pllA to clk6 and pllB to clk7
{
if(!clk6satisfied)
{
clocks[6].pllSource = 0;
clk6satisfied = true;
pllAused = true;
for (set<unsigned long>::iterator it6=clk6freqs.begin(); it6!=clk6freqs.end(); ++it6)
{
availableFrequenciesPLLA.insert( pair<unsigned long, int>(*it6, 0) );
}
}
if(!clk7satisfied)
{
clocks[7].pllSource = 1;
clk7satisfied = true;
pllBused = true;
for (set<unsigned long>::iterator it7=clk7freqs.begin(); it7!=clk7freqs.end(); ++it7)
{
availableFrequenciesPLLB.insert( pair<unsigned long, int> (*it7, 0) );
}
}
}
}
//PLLA stage, find all clocks that have integer coefficients with PLLA
//if pllA is not used by clk6 or clk7, fill available frequencies according to clk1-clk5 clocks
if( availableFrequenciesPLLA.size() == 0 && !pllAused)
{
for(int i=0; i<6; ++i)
{
unsigned long freq = clocks[i].outputFreqHz > Fmin ? clocks[i].outputFreqHz : (clocks[i].outputFreqHz*((Fmin/clocks[i].outputFreqHz) + ((Fmin%clocks[i].outputFreqHz)!=0)));
while(freq >= Fmin && freq <= Fmax)
{
//add all output frequency multiples that are in VCO interval
availableFrequenciesPLLA.insert( pair<unsigned long, int> (freq, 0));
freq += clocks[i].outputFreqHz;
}
}
}
unsigned int bestScore = 0; //score shows how many outputs have integer dividers
//calculate scores for all available frequencies
unsigned long bestVCOA = 0;
for (map<unsigned long, int>::iterator it=availableFrequenciesPLLA.begin(); it!=availableFrequenciesPLLA.end(); ++it)
{
for(int i=0; i<8; ++i)
{
if(clocks[i].outputFreqHz == 0 || !clocks[i].powered)
continue;
if( (it->first % clocks[i].outputFreqHz) == 0)
{
it->second = it->second+1;
}
}
if(it->second >= bestScore)
{
bestScore = it->second;
bestVCOA = it->first;
}
}
//scores calculated
//cout << "PLLA stage: " << endl;
//cout << "best score: " << bestScore << " best VCO: " << bestVCOA << endl;
plls[0].VCO_Hz = bestVCOA;
plls[0].feedbackDivider = (double)bestVCOA/plls[0].inputFreqHz;
for(int i=0; i<clockCount; ++i)
{
if(clocks[i].outputFreqHz == 0 || !clocks[i].powered)
continue;
clocks[i].multisynthDivider = bestVCOA/clocks[i].outputFreqHz;
if(bestVCOA%clocks[i].outputFreqHz == 0)
{
clocks[i].int_mode = true;
clocks[i].multisynthDivider = bestVCOA/clocks[i].outputFreqHz;
}
else
{
clocks[i].int_mode = false;
clocks[i].multisynthDivider = (double)bestVCOA/clocks[i].outputFreqHz;
}
clocks[i].pllSource = 0;
}
//PLLB stage, find all clocks that have integer coefficients with PLLB
//if pllB is not used by clk6 or clk7, fill available frequencies according to clk1-clk5 clocks, that don't have integer dividers
if( availableFrequenciesPLLB.size() == 0 && !pllBused)
{
for(int i=0; i<6; ++i)
{
if(clocks[i].outputFreqHz == 0 || !clocks[i].powered)
continue;
if(clocks[i].int_mode) //skip clocks with integer dividers
continue;
unsigned long freq = clocks[i].outputFreqHz > Fmin ? clocks[i].outputFreqHz : (clocks[i].outputFreqHz*((Fmin/clocks[i].outputFreqHz) + ((Fmin%clocks[i].outputFreqHz)!=0)));
while(freq >= Fmin && freq <= Fmax)
{
availableFrequenciesPLLB.insert( pair<unsigned long, int> (freq, 0));
freq += clocks[i].outputFreqHz;
}
}
}
bestScore = 0;
//calculate scores for all available frequencies
unsigned long bestVCOB = 0;
for (map<unsigned long, int>::iterator it=availableFrequenciesPLLB.begin(); it!=availableFrequenciesPLLB.end(); ++it)
{
for(int i=0; i<8; ++i)
{
if(clocks[i].outputFreqHz == 0 || !clocks[i].powered)
continue;
if( (it->first % clocks[i].outputFreqHz) == 0)
{
it->second = it->second+1;
}
}
if(it->second >= bestScore)
{
bestScore = it->second;
bestVCOB = it->first;
}
}
//scores calculated
// cout << "PLLB stage: " << endl;
// cout << "best score: " << bestScore << " best VCO: " << bestVCOB << endl;
if(bestVCOB == 0) //just in case if pllb is not used make it the same frequency as plla
bestVCOB = bestVCOA;
plls[1].VCO_Hz = bestVCOB;
plls[1].feedbackDivider = (double)bestVCOB/plls[0].inputFreqHz;
for(int i=0; i<clockCount; ++i)
{
if(clocks[i].outputFreqHz == 0 || !clocks[i].powered)
continue;
if(clocks[i].int_mode)
continue;
clocks[i].multisynthDivider = bestVCOB/clocks[i].outputFreqHz;
if(bestVCOB%clocks[i].outputFreqHz == 0)
{
clocks[i].int_mode = true;
clocks[i].multisynthDivider = bestVCOB/clocks[i].outputFreqHz;
}
else
{
clocks[i].int_mode = false;
clocks[i].multisynthDivider = (double)bestVCOB/clocks[i].outputFreqHz;
}
clocks[i].pllSource = 1;
}
}
/** @brief Modifies register map with clock settings
@return true if success
*/
Si5351C::Status Si5351C::ConfigureClocks()
{
FindVCO(CLK, PLL, 600000000, 900000000);
stringstream ss;
int addr;
m_newConfiguration[3] = 0;
for(int i=0; i<8; ++i)
{
m_newConfiguration[3] |= (!CLK[i].powered) << i; //enabled
m_newConfiguration[16+i] = 0;
m_newConfiguration[16+i] |= !CLK[i].powered << 7; // powered
if(CLK[i].int_mode)
{
m_newConfiguration[16+i] |= 1 << 6; //integer mode
}
else
m_newConfiguration[16+i] |= 0 << 6;
m_newConfiguration[16+i] |= CLK[i].pllSource << 5; //PLL source
m_newConfiguration[16+i] |= CLK[i].inverted << 4; // invert
m_newConfiguration[16+i] |= 3 << 2;
m_newConfiguration[16+i] |= 3;
addr = 42+i*8;
ss.clear();
ss.str( string() );
ss << "CLK" << i << " fOut = " << CLK[i].outputFreqHz/1000000.0 << " MHz";
int DivA;
int DivB;
int DivC;
realToFrac(CLK[i].multisynthDivider, DivA, DivB, DivC);
ss << " Multisynth Divider " << DivA << " " << DivB << "/" << DivC;
ss << " R divider = " << CLK[i].outputDivider << " source = " << (CLK[i].pllSource == 0 ? "PLLA" : "PLLB") << endl;
Log(ss.str(), LOG_INFO);
if( CLK[i].multisynthDivider < 8 || 900 < CLK[i].multisynthDivider)
{
Log("Si5351C - Output multisynth divider is outside [8;900] interval.\n", LOG_ERROR);
return FAILED;
}
if(i<6)
{
if(CLK[i].outputFreqHz <= 150000000)
{
unsigned MSX_P1 = 128 * DivA + floor(128 * ( (float)DivB/DivC)) - 512;
unsigned MSX_P2 = 128 * DivB - DivC * floor( 128 * DivB/DivC );
unsigned MSX_P3 = DivC;
m_newConfiguration[addr] = MSX_P3 >> 8;
m_newConfiguration[addr+1] = MSX_P3;
m_newConfiguration[addr+2] = 0;
m_newConfiguration[addr+2] |= (MSX_P1 >> 16 ) & 0x03;
m_newConfiguration[addr+3] = MSX_P1 >> 8;
m_newConfiguration[addr+4] = MSX_P1;
m_newConfiguration[addr+5] = 0;
m_newConfiguration[addr+5] = (MSX_P2 >> 16) & 0x0F;
m_newConfiguration[addr+5] |= (MSX_P3 >> 16) << 4;
m_newConfiguration[addr+6] = MSX_P2;
m_newConfiguration[addr+7] = MSX_P2 >> 8;
}
else if( CLK[i].outputFreqHz <= 160000000) // AVAILABLE ONLY ON 0-5 MULTISYNTHS
{
Log("Si5351C - clock configuring for more than 150 MHz not implemented\n", LOG_ERROR);
return FAILED;
}
}
else // CLK6 and CLK7 only integer mode
{
if(CLK[i].outputFreqHz <= 150000000)
{
if(i==6)
{
m_newConfiguration[90] = DivA;
if(DivA%2 != 0)
{
Log("Si5351C - CLK6 multisynth divider is not even integer\n", LOG_ERROR);
return FAILED;
}
}
else
{
m_newConfiguration[91] = DivA;
if(DivA%2 != 0)
{
Log("Si5351C - CLK7 multisynth divider is not even integer\n", LOG_ERROR);
return FAILED;
}
}
}
else if( CLK[i].outputFreqHz <= 160000000) // AVAILABLE ONLY ON 0-5 MULTISYNTHS
{
Log("Si5351C - clock configuring for more than 150 MHz not implemented\n", LOG_ERROR);
return FAILED;
}
}
}
//configure pll
//set input clk source
m_newConfiguration[15] = m_newConfiguration[15] & 0xF3;
m_newConfiguration[15] |= (PLL[0].CLK_SRC & 1) << 2;
m_newConfiguration[15] |= (PLL[1].CLK_SRC & 1) << 3;
for(int i=0; i<2; ++i)
{
addr = 26+i*8;
if(PLL[i].feedbackDivider < 15 || PLL[i].feedbackDivider > 90)
{
Log("Si5351C - VCO frequency divider out of range [15:90].\n", LOG_ERROR);
return FAILED;
}
if( PLL[i].VCO_Hz < 600000000 || PLL[i].VCO_Hz > 900000000)
{
Log("Si5351C - Can't calculate valid VCO frequency.\n", LOG_ERROR);
return FAILED;
}
ss.clear();
ss.str(string());
ss << "Si5351C : VCO" << (i==0 ? "A" : "B") << " = " << PLL[i].VCO_Hz/1000000.0 << " MHz";
//calculate MSNx_P1, MSNx_P2, MSNx_P3
int MSNx_P1;
int MSNx_P2;
int MSNx_P3;
int DivA;
int DivB;
int DivC;
realToFrac(PLL[i].feedbackDivider, DivA, DivB, DivC);
ss << " Feedback Divider " << DivA << " " << DivB << "/" << DivC << endl;
Log(ss.str(), LOG_INFO);
MSNx_P1 = 128 * DivA + floor(128 * ( (float)DivB/DivC)) - 512;
MSNx_P2 = 128 * DivB - DivC * floor( 128 * DivB/DivC );
MSNx_P3 = DivC;
m_newConfiguration[addr+4] = MSNx_P1;
m_newConfiguration[addr+3] = MSNx_P1 >> 8;
m_newConfiguration[addr+2] = MSNx_P1 >> 16;
m_newConfiguration[addr+7] = MSNx_P2;
m_newConfiguration[addr+6] = MSNx_P2 >> 8;
m_newConfiguration[addr+5] = 0;
m_newConfiguration[addr+5] = (MSNx_P2 >> 16) & 0x0F;
m_newConfiguration[addr+5] |= (MSNx_P3 >> 16) << 4;
m_newConfiguration[addr+1] |= MSNx_P3;
m_newConfiguration[addr] |= MSNx_P3 >> 8;
}
return SUCCESS;
}
/** @brief Sets output clock parameters
@param id clock id 0-CLK0 1-CLK1 ...
@param fOut_Hz output frequency in Hz
@param enabled is this output powered
@param inverted invert clock
*/
void Si5351C::SetClock(unsigned char id, unsigned long fOut_Hz, bool enabled, bool inverted)
{
if( id < 8)
{
if(fOut_Hz < 8000 || fOut_Hz > 160000000)
{
stringstream ss;
ss << "Si5351C - CLK" << (int)id << " output frequency must be between 8kHz and 160MHz. fOut_MHz = " << fOut_Hz/1000000.0 << endl;
Log(ss.str(), LOG_ERROR);
return;
}
CLK[id].powered = enabled;
CLK[id].inverted = inverted;
CLK[id].outputFreqHz = fOut_Hz;
}
}
/** @brief Sets PLL input frequency
@param id PLL id 0-PLLA 1-PLLB
@param CLKIN_Hz clock input in Hz
*/
void Si5351C::SetPLL(unsigned char id, unsigned long CLKIN_Hz, int CLK_SRC)
{
if (id < 2)
{
PLL[id].inputFreqHz = CLKIN_Hz;
PLL[id].CLK_SRC = CLK_SRC;
}
}
/** @brief Resets configuration registers to default values
*/
void Si5351C::Reset()
{
memset(m_newConfiguration, 0, 255);
for(unsigned int i=0; i<sizeof(m_defaultConfiguration); i+=2)
{
m_newConfiguration[m_defaultConfiguration[i]] = m_defaultConfiguration[i+1];
}
}
Si5351C::StatusBits Si5351C::GetStatusBits()
{
StatusBits stat;
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_SI5351_RD;
pkt.outBuffer.push_back(0);
pkt.outBuffer.push_back(1);
LMScomms::TransferStatus status;
status = device->TransferPacket(pkt);
if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD)
{
return stat;
}
stat.sys_init = (pkt.inBuffer[0] >> 7);
stat.lol_b = (pkt.inBuffer[0] >> 6) & 0x1;
stat.lol_a = (pkt.inBuffer[0] >> 5) & 0x1;
stat.los = (pkt.inBuffer[0] >> 4) & 0x1;
stat.sys_init_stky = (pkt.inBuffer[1] >> 7);
stat.lol_b_stky = (pkt.inBuffer[1] >> 6) & 0x1;
stat.lol_a_stky = (pkt.inBuffer[1] >> 5) & 0x1;
stat.los_stky = (pkt.inBuffer[1] >> 4) & 0x1;
return stat;
}
Si5351C::Status Si5351C::ClearStatus()
{
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_SI5351_WR;
pkt.outBuffer.push_back(1);
pkt.outBuffer.push_back(0x0);
LMScomms::TransferStatus status;
status = device->TransferPacket(pkt);
if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD)
return FAILED;
return SUCCESS;
}