mrfioc2  2.3.0
delayModule.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
3 * mrfioc2 is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
6 
7 #include "drvem.h"
8 #include "delayModule.h"
9 
10 #define SERIAL_DATA_BIT(idx) (1 << (0+4*idx))
11 #define SERIAL_CLOCK_BIT(idx) (1 << (1+4*idx))
12 #define TRANSFER_LATCH_CLOCK_BIT(idx) (1 << (2+4*idx))
13 #define OUTPUT_DISABLE_BIT(idx) (1 << (3+4*idx))
14 
15 
16 DelayModule::DelayModule(const std::string& n, EVRMRM* o, unsigned int idx)
17  : DelayModuleEvr(n)
18  ,N_(idx)
19  ,gpio_(o->gpio())
20 {
21 }
22 
24 {
25 }
26 
27 void DelayModule::setDelay0(double val)
28 {
29  if(val < 0) val = 0;
30  if(val > 8.686)val = 8.686;
31  setDelay(true, false, (epicsUInt16)(val * 1023.0 / 8.686), 0);
32 }
33 
34 double DelayModule::getDelay0() const
35 {
36  return (dly0_ * 8.686 / 1023.0);
37 }
38 
39 void DelayModule::setDelay1(double val)
40 {
41  if(val < 0) val = 0;
42  if(val > 8.686)val = 8.686;
43  setDelay(false, true, 0, (epicsUInt16)(val * 1023.0 / 8.686));
44 }
45 
46 double DelayModule::getDelay1() const
47 {
48  return (dly1_ * 8.686 / 1023.0);
49 }
50 
52 {
53  epicsGuard<epicsMutex> g(gpio_->lock_);
54  setGpioOutput();
55  if(enabled) enable();
56  else disable();
57 }
58 
60 {
61  epicsUInt32 data;
62 
63  data = gpio_->getOutput();
64  return !(data & OUTPUT_DISABLE_BIT(N_));
65 }
66 
67 // ---------------------- //
68 // Private methods below //
69 // ---------------------- //
70 
71 void DelayModule::setGpioOutput(){
72  epicsUInt32 direction;
73 
74  // set 4 pins affecting the module to output
75  direction = gpio_->getDirection();
77  gpio_->setDirection(direction);
78 }
79 
80 void DelayModule::enable(){
81  epicsUInt32 data;
82 
83  //clear output disable bit to enable the module
84  data = gpio_->getOutput();
85  data &= ~OUTPUT_DISABLE_BIT(N_);
86  gpio_->setOutput(data);
87 }
88 
89 void DelayModule::disable(){
90  epicsUInt32 data;
91 
92  //set output disable bit to disable the module
93  data = gpio_->getOutput();
94  data |= OUTPUT_DISABLE_BIT(N_);
95  gpio_->setOutput(data);
96 }
97 
98 void DelayModule::setDelay(bool output0, bool output1, epicsUInt16 value0, epicsUInt16 value1){
99  epicsUInt32 latch=0, delay=0;
100 
101  //printf("out0: %d, out1: %d, value0: %d, value1: %d\n", output0, output1, value0, value1);
102  if(output0 | output1){
103  //we need to lock GPIO pins, so nobody else messes with them.
104  epicsGuard<epicsMutex> g(gpio_->lock_);
105  setGpioOutput();
106 
107  // We have to shift in the bits in following order:
108  // DA7, DA6, DA5, DA4, DA3, DA2, DA1, DA0,
109  // DB3, DB2, DB1, DB0, LENA, 0, DA9, DA8,
110  // LENB, 0, DB9, DB8, DB7, DB6, DB5, DB4
111 
112  if(output0){ // output 0 selected = UNIV 0 = DB
113  delay |= ((dly1_ & 0x0ff) << 16) | (dly1_ & 0x300);
114  delay |= ((value0 & 0x00f) << 12) | (value0 >> 4);
115  latch |= 0x000080;
116  dly0_ = value0;
117  }
118  if(output1){ // output 1 selected = UNIV 1 = DA
119  delay |= ((dly0_ & 0x00f) << 12) | (dly0_ >> 4);
120  delay |= ((value1 & 0x0ff) << 16) | (value1 & 0x300);
121  latch |= 0x000800;
122  dly1_ = value1;
123  }
124 
125  // we output the data, set the latches and output the data again. This is to ensure that the delay values are stable when we latch them.
126  pushData(delay);
127  pushData(delay | latch);
128  pushData(delay);
129  }
130 }
131 
132 void DelayModule::pushData(epicsUInt32 data){
133  epicsUInt32 bit, gpio;
134  epicsUInt8 i;
135 
136  // Prepare gpio mask before sending the data. Allways use mask so we don't ruin data on other GPIO pins.
137  gpio = gpio_->getOutput() & ~(SERIAL_DATA_BIT(N_) | SERIAL_CLOCK_BIT(N_) | TRANSFER_LATCH_CLOCK_BIT(N_));
138 
139  for( i = 24; i; i-- ){
140  bit = 0;
141  if(data & 0x00800000) bit = SERIAL_DATA_BIT(N_);
142  gpio_->setOutput(gpio | bit);
143  gpio_->setOutput(gpio | bit | SERIAL_CLOCK_BIT(N_));
144  gpio_->setOutput(gpio | bit);
145  data <<= 1;
146  }
147  // finish the transmission. A rising edge on LCLK transfers the data from the shift register to the actual delay chips
148  gpio_->setOutput(gpio | TRANSFER_LATCH_CLOCK_BIT(N_));
149  gpio_->setOutput(gpio);
150 }
void setOutput(epicsUInt32)
Definition: mrmGpio.cpp:38
void setDirection(epicsUInt32)
Definition: mrmGpio.cpp:21
virtual void setState(bool enabled) OVERRIDE FINAL
setState Sets the enabled state of the delay module. If disabled, the module will output logic low on...
Definition: delayModule.cpp:51
Modular Register Map Event Receivers.
Definition: drvem.h:86
virtual void setDelay1(double val) OVERRIDE FINAL
setDelay1 Sets the delay of the output 1 in the module
Definition: delayModule.cpp:39
#define OUTPUT_DISABLE_BIT(idx)
Definition: delayModule.cpp:13
virtual ~DelayModule()
Definition: delayModule.cpp:23
epicsUInt32 getDirection()
Definition: mrmGpio.cpp:15
virtual double getDelay0() const OVERRIDE FINAL
getDelay0 Returns the last set delay for the output 0 in the module
Definition: delayModule.cpp:34
DelayModule(const std::string &, EVRMRM *, unsigned int)
Definition: delayModule.cpp:16
epicsUInt32 getOutput()
Definition: mrmGpio.cpp:32
epicsMutex lock_
Definition: mrmGpio.h:29
#define TRANSFER_LATCH_CLOCK_BIT(idx)
Definition: delayModule.cpp:12
virtual void setDelay0(double val) OVERRIDE FINAL
setDelay0 Sets the delay of the output 0 in the module
Definition: delayModule.cpp:27
virtual double getDelay1() const OVERRIDE FINAL
getDelay1R eturns the last set delay for the output 1 in the module
Definition: delayModule.cpp:46
virtual bool enabled() const OVERRIDE FINAL
enabled Checks if the module is enabled or not.
Definition: delayModule.cpp:59
#define SERIAL_CLOCK_BIT(idx)
Definition: delayModule.cpp:11
#define SERIAL_DATA_BIT(idx)
Definition: delayModule.cpp:10