Scope
FPGAIO6587.cpp
1 #include "StdAfx.h"
2 #include "FPGAIO6587.h"
3 #include "helpers/helpers.h"
4 #include "NiFpga.h"
5 
6 namespace scope {
7 
8 FPGAIO6587::FPGAIO6587(const uint32_t& _clock_ready
9  , const uint32_t& _clock_write_data
10  , const uint32_t& _clock_write
11  , const uint32_t& _xpoint_ready
12  , const uint32_t& _clock_source
13  , const uint32_t& _xpoint_write
14  , const uint32_t& _commit_control
15  , const uint32_t& _acquisition_reset_control)
16  : onboard_clock_ready_indicator(_clock_ready)
17  , onboard_clock_write_data_control(_clock_write_data)
18  , onboard_clock_write_control(_clock_write)
19  , xpoint_switch_ready_indicator(_xpoint_ready)
20  , clock_source_control(_clock_source)
21  , xpoint_switch_write_control(_xpoint_write)
22  , commit_control(_commit_control)
23  , acquisition_reset_control(_acquisition_reset_control)
24  , iostatus(NiFpga_Status_Success) {
25 }
26 
27 bool FPGAIO6587::CheckIOModule(NiFpga_Session _session) {
28  return true;
29 }
30 
31 void FPGAIO6587::ClockFrequencySetup(const double& _clock_freq) {
32  uint8_t i = 1;
33  std::vector<uint8_t> n1(65, 1);
34  std::generate(std::begin(n1)+1, std::end(n1), [&]() { return i++*2; } );
35  std::array<uint8_t, 6> hsdiv = { 11, 9, 7, 6, 5, 4 };
36  std::array<uint8_t, 9> regaddr = { 0x89, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0x89, 0x87 };
37  std::array<uint8_t, 9> writedata = { 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40 };
38 
39  const double xtalfreq = 114.285E6;
40  double rfreqnew_dec = 0.0;
41  uint64_t rfreqnew = 0;
42  double dconew = 5.67E9;
43  uint8_t hsdivnew = 0;
44  uint8_t n1new = 0;
45  std::for_each(std::begin(n1), std::end(n1), [&](const uint8_t& _n1) {
46  for ( auto h : hsdiv ) {
47  double tmp = _n1 * (h * _clock_freq);
48  if ( ((tmp >= 4.85E9) && (tmp < 5.67E9)) && (tmp < dconew) ) {
49  hsdivnew = h;
50  n1new = _n1;
51  dconew = tmp;
52  }
53  }
54  } );
55  rfreqnew_dec = dconew / xtalfreq;
56  rfreqnew = static_cast<uint64_t>(round2ui64(rfreqnew_dec * 268435456)); // 2^28
57  writedata[1] = ((hsdivnew-4) << 5) + ((n1new-1) >> 2);
58  writedata[2] = ((n1new-1) << 6) + static_cast<uint8_t>(rfreqnew >> 32); // use the upper 8 bits of rfreqnew
59  writedata[3] = HIBYTE(HIWORD(LODWORD32(rfreqnew)));
60  writedata[4] = LOBYTE(HIWORD(LODWORD32(rfreqnew)));
61  writedata[5] = HIBYTE(LOWORD(LODWORD32(rfreqnew)));
62  writedata[6] = LOBYTE(LOWORD(LODWORD32(rfreqnew)));
63  std::transform(std::begin(writedata), std::end(writedata), std::begin(regaddr), std::begin(regndata)
64  , [](const uint8_t& w, const uint8_t& r) { return MAKEWORD(w, r); } );
65 }
66 
67 void FPGAIO6587::WriteOnboardClockFrequency(NiFpga_Session _session, const double& _clock_freq) {
68  // Supported clock frequencies between 10 and 800 MHz (-> sampling frequencies 20-1600 MHz)
69  assert( (_clock_freq >= 10E6) && (_clock_freq <= 800E6) );
70 
71  std::fill(std::begin(regndata), std::end(regndata), 0);
72  ClockFrequencySetup(_clock_freq);
73 
74  // Write register data (calculated in ClockFrequencySetup to the IO module clock chip
75  std::for_each(std::begin(regndata), std::end(regndata), [&](uint16_t rd) {
76  NiFpga_Bool ready = false;
77  uint32_t waitcounter = 0;
78  do {
79  iostatus = NiFpga_ReadBool(_session, onboard_clock_ready_indicator, &ready);
80  std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Wait 50 milliseconds
81  waitcounter += 50;
82  } while ( !ready && (waitcounter < 5000) );
83  if ( waitcounter >= 5000 )
84  throw FPGAException(-1, "WriteOnboardClockFrequency timeout");
85  iostatus = NiFpga_WriteU16(_session, onboard_clock_write_data_control, rd);
86  iostatus = NiFpga_WriteBool(_session, onboard_clock_write_control, false);
87  iostatus = NiFpga_WriteBool(_session, onboard_clock_write_control, true);
88  iostatus = NiFpga_WriteBool(_session, onboard_clock_write_control, false);
89  } );
90  DBOUT(L"FPGAIO6587::WriteOnboardClockFrequency finished");
91 }
92 
93 void FPGAIO6587::SetClockSource(NiFpga_Session _session, const uint8_t& _clock_source) {
94  NiFpga_Bool ready = false;
95  uint32_t waitcounter = 0;
96 
97  // Set xpoint clock switch
98  do {
99  iostatus = NiFpga_ReadBool(_session, xpoint_switch_ready_indicator, &ready);
100  std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Wait 50 milliseconds
101  waitcounter += 50;
102  } while ( !ready && (waitcounter < 5000) );
103  if ( waitcounter >= 5000 )
104  throw FPGAException(-1, "SetClockSource timeout");
105 
106 
107  // Set clock source
108  iostatus = NiFpga_WriteU8(_session, clock_source_control, _clock_source);
109 
110  // Write xpoint switch
111  iostatus = NiFpga_WriteBool(_session, xpoint_switch_write_control, false);
112  iostatus = NiFpga_WriteBool(_session, xpoint_switch_write_control, true);
113  iostatus = NiFpga_WriteBool(_session, xpoint_switch_write_control, false);
114 }
115 
116 void FPGAIO6587::InitializeAcquisition(NiFpga_Session _session) {
117  // Commit -> configuration loop on FPGA finishes
118  iostatus = NiFpga_WriteBool(_session, commit_control, true);
119 
120  // Reset acquisition
121  iostatus = NiFpga_WriteBool(_session, acquisition_reset_control, false);
122  iostatus = NiFpga_WriteBool(_session, acquisition_reset_control, true);
123  // The IO module needs a while for the reset (contrary to what the NI examples say...)
124  std::this_thread::sleep_for(std::chrono::milliseconds(200));
125  iostatus = NiFpga_WriteBool(_session, acquisition_reset_control, false);
126 }
127 
128 }
const uint32_t onboard_clock_write_control
the clock write control on the FPGA vi
Definition: FPGAIO6587.h:21
void WriteOnboardClockFrequency(NiFpga_Session _session, const double &_clock_freq)
Writes the program for the Si570 clock chip to the device.
Definition: FPGAIO6587.cpp:67
An exception for FPGA stuff.
Definition: FPGAException.h:9
const uint32_t xpoint_switch_write_control
the xpoint switch write control on the FPGA vi
Definition: FPGAIO6587.h:30
bool CheckIOModule(NiFpga_Session _session)
Necessary calls at the moment not supported by NI FPGA API 12.0, see CheckIOModule.vi for what to do.
Definition: FPGAIO6587.cpp:27
const uint32_t xpoint_switch_ready_indicator
the xpoint switch ready indicator on the FPGA vi
Definition: FPGAIO6587.h:24
void ClockFrequencySetup(const double &_clock_freq)
Generates value for programming the Si570 clock chip.
Definition: FPGAIO6587.cpp:31
void InitializeAcquisition(NiFpga_Session _session)
Commits the clock frequency and clock source writings and resets the IO module acquisition circuit...
Definition: FPGAIO6587.cpp:116
const uint32_t acquisition_reset_control
the acquisition reset control on the FPGA vi
Definition: FPGAIO6587.h:36
This is the include file for standard system include files, or project specific include files that ar...
std::array< uint16_t, 9 > regndata
register data for writing to the clock chip
Definition: FPGAIO6587.h:39
#define LODWORD32(l)
Extracts low dword (32 bits) from an ULONG64 (64 bits)
Definition: helpers.h:19
const uint32_t clock_source_control
the clocksource control on the FPGA vi
Definition: FPGAIO6587.h:27
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
const uint32_t commit_control
the commit control on the FPGA vi
Definition: FPGAIO6587.h:33
const uint32_t onboard_clock_write_data_control
the clock write data control on the FPGA vi
Definition: FPGAIO6587.h:18
FPGAIO6587(const uint32_t &_clock_ready, const uint32_t &_clock_write_data, const uint32_t &_clock_write, const uint32_t &_xpoint_ready, const uint32_t &_clock_source, const uint32_t &_xpoint_write, const uint32_t &_commit_control, const uint32_t &_acquisition_reset_control)
Definition: FPGAIO6587.cpp:8
void SetClockSource(NiFpga_Session _session, const uint8_t &_clock_source=3)
Possible clock sources (see SetClockSource.vi from NI examples) .
Definition: FPGAIO6587.cpp:93
FPGAStatusSafe iostatus
Current status of the module.
Definition: FPGAIO6587.h:43
Various helper functions and classes for Scope.
const uint32_t onboard_clock_ready_indicator
the clock ready indicator on the FPGA vi
Definition: FPGAIO6587.h:15