mrfioc2  2.3.0
evgEvtClk.cpp
Go to the documentation of this file.
1 
2 #include <stdio.h>
3 #include <errlog.h>
4 #include <stdexcept>
5 #include <sstream>
6 
7 #include <mrfCommonIO.h>
8 #include <mrfCommon.h>
9 #include <mrfFracSynth.h>
10 
11 #include "evgMrm.h"
12 #include "evgRegMap.h"
13 
14 epicsFloat64
16  epicsUInt16 cur = getSource();
17  switch(cur) {
18  case ClkSrcPXIe100:
19  return 100;
20  // case ClkSrcPXIe10: ??
21  case ClkSrcRF:
22  case ClkSrcSplit:
23  return getRFFreq()/getRFDiv();
24  default:
25  return m_fracSynFreq;
26  }
27 }
28 
29 void
30 evgMrm::setRFFreq (epicsFloat64 RFref) {
31  if(RFref < 50.0f || RFref > 1600.0f) {
32  std::ostringstream strm;
33  strm<<"Cannot set RF frequency to "<<RFref<<" MHz. Valid range is 50 - 1600.";
34  throw std::runtime_error(strm.str());
35  }
36 
37  m_RFref = RFref;
38 }
39 
40 epicsFloat64
42  return m_RFref;
43 }
44 
45 void
46 evgMrm::setRFDiv(epicsUInt32 rfDiv) {
47  if(rfDiv < 1 || rfDiv == 13 || rfDiv > 32) {
48  char err[80];
49  sprintf(err, "Invalid RF Divider %d. Valid range is 1 - 12, 14 - 32", rfDiv);
50  std::string strErr(err);
51  throw std::runtime_error(strErr);
52  }
53  m_RFDiv = rfDiv;
54 
55  recalcRFDiv();
56 }
57 
58 epicsUInt32
60  return m_RFDiv;
61 }
62 
63 void
64 evgMrm::setFracSynFreq(epicsFloat64 freq) {
65  epicsFloat64 error;
66 
67  epicsUInt32 controlWord = FracSynthControlWord (freq, MRF_FRAC_SYNTH_REF, 0, &error);
68  if ((!controlWord) || (error > 100.0)) {
69  char err[80];
70  sprintf(err, "Cannot set event clock speed to %f MHz.\n", freq);
71  std::string strErr(err);
72  throw std::runtime_error(strErr);
73  }
74  epicsUInt32 uSecDivider = (epicsUInt16)freq;
75 
76  epicsUInt32 oldControlWord=READ32(m_pReg, FracSynthWord),
77  olduSecDivider=READ32(m_pReg, uSecDiv);
78 
79  /* Changing the control word disturbes the phase of the synthesiser
80  which will cause a glitch. Don't change the control word unless needed.*/
81  if(controlWord != oldControlWord || uSecDivider!=olduSecDivider){
82  WRITE32(m_pReg, FracSynthWord, controlWord);
83  epicsUInt32 uSecDivider = (epicsUInt16)freq;
84  WRITE32(m_pReg, uSecDiv, uSecDivider);
85  }
86 
87  m_fracSynFreq = FracSynthAnalyze(READ32(m_pReg, FracSynthWord), 24.0, 0);
88 }
89 
90 epicsFloat64
92  return FracSynthAnalyze(READ32(m_pReg, FracSynthWord), 24.0, 0);
93 }
94 
95 void
96 evgMrm::setSource (epicsUInt16 clkSrc) {
97  switch(clkSrc) {
98  case ClkSrcInternal:
99  case ClkSrcRF:
100  case ClkSrcPXIe100:
101  case ClkSrcRecovered:
102  case ClkSrcSplit:
103  case ClkSrcPXIe10:
104  case ClkSrcRecovered_2:
105  m_ClkSrc = (ClkSrc)clkSrc;
106 
107  recalcRFDiv();
108  return;
109  }
110 
111  throw std::invalid_argument("Invalid clock source");
112 }
113 
114 epicsUInt16 evgMrm::getSource() const {
115  epicsUInt32 cur = READ32(m_pReg, ClockControl);
116  cur &= ClockControl_Sel_MASK;
117  return cur >> ClockControl_Sel_SHIFT;
118 }
119 
120 bool evgMrm::pllLocked() const
121 {
122  epicsUInt32 cur = READ32(m_pReg, ClockControl);
123  epicsUInt32 mask = 0;
124  if(version()>=MRFVersion(2, 7, 0))
126  return (cur&mask)==mask;
127 }
128 
129 void evgMrm::recalcRFDiv()
130 {
131  epicsUInt32 cur = READ32(m_pReg, ClockControl);
132 
133  cur &= ~ClockControl_Sel_MASK;
134  cur &= ~ClockControl_Div_MASK;
135 
136  epicsUInt32 div = m_RFDiv-1; // /1 -> 0, /2 -> 1, etc.
137 
138  switch(m_ClkSrc) {
139  case ClkSrcInternal:
140  case ClkSrcRecovered:
141  case ClkSrcRecovered_2:
142  // disable RF input
143  div = 0xc; // /13 is magic for OFF
144  break;
145  default:
146  break;
147  }
148 
150  cur |= (epicsUInt32(m_ClkSrc)<<ClockControl_Sel_SHIFT)&ClockControl_Sel_MASK;
151  WRITE32(m_pReg, ClockControl, cur);
152 }
epicsShareExtern epicsUInt32 FracSynthControlWord(epicsFloat64 DesiredFreq, epicsFloat64 ReferenceFreq, epicsInt32 debugFlag, epicsFloat64 *Error)
Definition: mrfFracSynth.c:552
#define READ32(base, offset)
Definition: mrfCommonIO.h:114
epicsFloat64 getFrequency() const
Definition: evgEvtClk.cpp:15
epicsUInt32 getRFDiv() const
Definition: evgEvtClk.cpp:59
epicsFloat64 getFracSynFreq() const
Definition: evgEvtClk.cpp:91
ClkSrc
Definition: evgMrm.h:113
#define ClockControl_Div_SHIFT
Definition: evgRegMap.h:121
void setRFDiv(epicsUInt32)
Definition: evgEvtClk.cpp:46
bool pllLocked() const
Definition: evgEvtClk.cpp:120
epicsUInt16 getSource() const
Definition: evgEvtClk.cpp:114
#define ClockControl_Div_MASK
Definition: evgRegMap.h:120
#define ClockControl_Sel_SHIFT
Definition: evgRegMap.h:119
#define MRF_FRAC_SYNTH_REF
Definition: mrfCommon.h:99
void setFracSynFreq(epicsFloat64)
Definition: evgEvtClk.cpp:64
#define ClockControl_cglock
Definition: evgRegMap.h:123
void setRFFreq(epicsFloat64)
Definition: evgEvtClk.cpp:30
epicsShareExtern epicsFloat64 FracSynthAnalyze(epicsUInt32 ControlWord, epicsFloat64 ReferenceFreq, epicsInt32 PrintFlag)
Definition: mrfFracSynth.c:844
epicsFloat64 getRFFreq() const
Definition: evgEvtClk.cpp:41
#define ClockControl_plllock
Definition: evgRegMap.h:117
#define WRITE32(base, offset, value)
Definition: mrfCommonIO.h:119
#define ClockControl_Sel_MASK
Definition: evgRegMap.h:118
void setSource(epicsUInt16)
Definition: evgEvtClk.cpp:96
MRFVersion version() const
Definition: evgMrm.cpp:223