thamwaypulser.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "thamwaypulser.h"
15 #include "charinterface.h"
16 
17 #if defined USE_EZUSB
18  REGISTER_TYPE(XDriverList, ThamwayUSBPulser, "NMR pulser Thamway N210-1026 PG32U40(USB)");
19 #endif
20 REGISTER_TYPE(XDriverList, ThamwayCharPulser, "NMR pulser Thamway N210-1026S/T (GPIB/TCP)");
21 
22 #define MAX_PATTERN_SIZE 256*1024u
23 //[ms]
24 #define TIMER_PERIOD (1.0/(40.0e3))
25 //[ms]
26 #define MIN_PULSE_WIDTH 0.0001 //100ns, perhaps 50ns is enough?
27 
28 
29 #define ADDR_REG_ADDR_L 0x00
30 #define ADDR_REG_ADDR_H 0x02
31 #define ADDR_REG_STS 0x03
32 #define ADDR_REG_TIME_LSW 0x04
33 #define ADDR_REG_TIME_MSW 0x06
34 #define ADDR_REG_DATA_LSW 0x08
35 #define ADDR_REG_REP_N 0x0a
36 #define ADDR_REG_MODE 0x0c
37 #define ADDR_REG_CTRL 0x0d
38 #define ADDR_REG_DATA_MSW 0x0e
39 #define CMD_TRG 0xff80uL
40 #define CMD_STOP 0xff40uL
41 #define CMD_JP 0xff20uL
42 #define CMD_INT 0xff10uL
43 
44 
46  return TIMER_PERIOD;
47 }
48 
50  return MIN_PULSE_WIDTH;
51 }
52 
53 
54 XThamwayPulser::XThamwayPulser(const char *name, bool runtime,
55  Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
56  XPulser(name, runtime, ref(tr_meas), meas) {
57 
58  const int ports[] = {
59  XPulser::PORTSEL_GATE, XPulser::PORTSEL_PREGATE, XPulser::PORTSEL_TRIG1, XPulser::PORTSEL_QPSK_OLD_PSGATE,
60  XPulser::PORTSEL_QPSK_OLD_INV, XPulser::PORTSEL_GATE, XPulser::PORTSEL_TRIG2, XPulser::PORTSEL_TRIG1,
61  XPulser::PORTSEL_PULSE1, XPulser::PORTSEL_ASW, XPulser::PORTSEL_UNSEL, XPulser::PORTSEL_UNSEL,
62  XPulser::PORTSEL_UNSEL, XPulser::PORTSEL_UNSEL, XPulser::PORTSEL_UNSEL, XPulser::PORTSEL_UNSEL
63  };
64  iterate_commit([=](Transaction &tr){
65  for(unsigned int i = 0; i < sizeof(ports)/sizeof(int); i++) {
66  tr[ *XPulser::portSel(i)] = ports[i];
67  }
68  });
69 }
70 
71 
72 void
74  const Snapshot &shot(tr);
75  tr[ *this].m_patterns.clear();
76  uint16_t pat = (uint16_t)(shot[ *this].relPatList().back().pattern & XPulser::PAT_DO_MASK);
77  pulseAdd(tr, 10, pat); //leading blanks
78  pulseAdd(tr, 10, pat);
79  uint32_t startaddr = 2;
80  for(auto it = shot[ *this].relPatList().begin();
81  it != shot[ *this].relPatList().end(); it++) {
82  pulseAdd(tr, it->toappear, pat);
83  pat = (uint16_t)(it->pattern & XPulser::PAT_DO_MASK);
84  }
85 // if(tr[ *this].m_patterns.back().term_n_cmd < 2) {
86 // pulseAdd(tr, lrint(2 * minPulseWidth() / resolution()), pat);
87 // }
89  p.term_n_cmd = CMD_JP * 0x10000uL + startaddr;
90  p.data = 0;
91  tr[ *this].m_patterns.push_back(p);
92  p.term_n_cmd = CMD_STOP * 0x10000uL;
93  p.data = 0;
94  tr[ *this].m_patterns.push_back(p);
95 }
96 
97 int
98 XThamwayPulser::pulseAdd(Transaction &tr, uint64_t term, uint16_t pattern) {
99  term = std::max(term, (uint64_t)lrint(MIN_PULSE_WIDTH / TIMER_PERIOD));
100  for(; term;) {
101  uint64_t t = std::min((uint64_t)term, (uint64_t)0xfe000000uL);
102  term -= t;
103  Payload::Pulse p;
104  p.term_n_cmd = t;
105  p.data = pattern;
106  tr[ *this].m_patterns.push_back(p);
107  }
108  return 0;
109 }
110 
111 void
112 XThamwayCharPulser::changeOutput(const Snapshot &shot, bool output, unsigned int blankpattern) {
113  XScopedLock<XInterface> lock( *this->interface());
114  if( !this->interface()->isOpened())
115  return;
116 
117  this->interface()->send("STOP");
118  this->interface()->send("SAVER 0"); //not needed for TCP/IP version.
119  this->interface()->send("SETMODE 1"); //extended mode
120  this->interface()->send("MEMCLR 0");
121  if(output) {
122  if(shot[ *this].m_patterns.size() >= MAX_PATTERN_SIZE) {
123  throw XInterface::XInterfaceError(i18n("Number of patterns exceeded the size limit."), __FILE__, __LINE__);
124  }
125 
126  unsigned int addr = 0;
127  for(auto it = shot[ *this].m_patterns.begin(); it != shot[ *this].m_patterns.end(); ++it) {
128  this->interface()->sendf("POKE 0x%x,0x%x,0x%x", addr, it->term_n_cmd, it->data);
129  addr++;
130  }
131  this->interface()->send("START 0"); //infinite loops
132  }
133 }
134 
135 void
136 XThamwayCharPulser::getStatus(bool *running, bool *extclk_det) {
137  if(running) {
138  this->interface()->query("ISRUN?");
139  *running = (this->interface()->toStrSimplified() == "RUN");
140  }
141  if(extclk_det)
142  *extclk_det = true; //uncertain
143 }
144 
145 void
147  this->interface()->setEOS("\r\n");
148  this->start();
149 }
150 
151 #if defined USE_EZUSB
152 
153 void
154 XThamwayUSBPulser::changeOutput(const Snapshot &shot, bool output, unsigned int blankpattern) {
155  XScopedLock<XInterface> lock( *this->interface());
156  if( !this->interface()->isOpened())
157  return;
158 
159  this->interface()->resetBulkWrite();
160  this->interface()->writeToRegister8(ADDR_REG_CTRL, 0); //stops it
161  this->interface()->writeToRegister8(ADDR_REG_MODE, 2); //direct output on.
162  this->interface()->writeToRegister16(ADDR_REG_DATA_LSW, blankpattern % 0x10000uL);
163  this->interface()->writeToRegister16(ADDR_REG_DATA_MSW, blankpattern / 0x10000uL);
164  this->interface()->writeToRegister8(ADDR_REG_MODE, 0); //direct output off.
165  this->interface()->writeToRegister16(ADDR_REG_ADDR_L, 0);
166  this->interface()->writeToRegister8(ADDR_REG_ADDR_H, 0);
167  if(output) {
168  if(shot[ *this].m_patterns.size() >= MAX_PATTERN_SIZE) {
169  throw XInterface::XInterfaceError(i18n("Number of patterns exceeded the size limit."), __FILE__, __LINE__);
170  }
171  this->interface()->deferWritings();
172  for(auto it = shot[ *this].m_patterns.begin(); it != shot[ *this].m_patterns.end(); ++it) {
173  this->interface()->writeToRegister16(ADDR_REG_TIME_LSW, it->term_n_cmd % 0x10000uL);
174  this->interface()->writeToRegister16(ADDR_REG_TIME_MSW, it->term_n_cmd / 0x10000uL);
175  this->interface()->writeToRegister16(ADDR_REG_DATA_LSW, it->data % 0x10000uL);
176  this->interface()->writeToRegister16(ADDR_REG_DATA_MSW, it->data / 0x10000uL);
177  this->interface()->writeToRegister8(ADDR_REG_CTRL, 2); //addr++
178  }
179  this->interface()->bulkWriteStored();
180 
181  this->interface()->writeToRegister8(ADDR_REG_STS, 0); //clears STS.
182  this->interface()->writeToRegister16(ADDR_REG_REP_N, 0); //infinite loops
183  this->interface()->writeToRegister16(ADDR_REG_ADDR_L, 0);
184  this->interface()->writeToRegister8(ADDR_REG_ADDR_H, 0);
185  bool ext_clock = false;
186 // getStatus(0, &ext_clock); //PROT does not use ext. clock.
187  this->interface()->writeToRegister8(ADDR_REG_MODE, 8 | (ext_clock ? 4 : 0)); //external Trig
188  this->interface()->writeToRegister8(ADDR_REG_CTRL, 1); //starts it
189  }
190 }
191 
192 
193 void
194 XThamwayUSBPulser::getStatus(bool *running, bool *extclk_det) {
195  uint8_t sta = this->interface()->singleRead(ADDR_REG_STS);
196  if(running)
197  *running = sta & 0x2;
198  if(extclk_det)
199  *extclk_det = !(sta & 0x20);
200  this->interface()->writeToRegister8(ADDR_REG_STS, 0);
201 }
202 
203 void
205  XString idn = this->interface()->getIDN();
206  fprintf(stderr, "PG IDN=%s\n", idn.c_str());
207  this->start();
208 }
209 
210 #endif //USE_EZUSB

Generated for KAME4 by  doxygen 1.8.3