simulavr  1.1.0
spisink.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include "spisink.h"
3 
4 using namespace std;
5 
6 enum {
7  SSBIT = 0,
8  SCLKBIT = 1,
9  MISOBIT = 2
10  };
11 
13  Net& sclkNet,
14  Net& misoNet,
15  bool clockIsIdleHigh,
16  bool clockSampleOnLeadingEdge
17  ) throw():
18  _port(0),
19  _ss( &_port, (unsigned char)(1<<SSBIT) ),
20  _sclk( &_port, (unsigned char)(1<<SCLKBIT) ),
21  _miso( &_port, (unsigned char)(1<<MISOBIT) ),
22  _ssState(false),
23  _sclkState(false),
24  _misoState(false),
25  _state(0),
26  _sr(0),
27  _clockIsIdleHigh(clockIsIdleHigh),
28  _clockSampleOnLeadingEdge(clockSampleOnLeadingEdge),
29  _prevClkState(clockIsIdleHigh),
30  _prevSS(true)
31  {
32  _ss.outState = Pin::PULLUP;
33  ssNet.Add(&_ss);
34 
35  _sclk.outState = Pin::PULLUP;
36  sclkNet.Add(&_sclk);
37 
38  _miso.outState = Pin::PULLUP;
39  misoNet.Add(&_miso);
40  }
41 
42 int SpiSink::Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns){
43  *timeToNextStepIn_ns = 1000; // Once every microsecond
44  bool sample = false;
45 
46  _ssState = (_port & (1<<SSBIT))?true:false;
47  _sclkState = (_port & (1<<SCLKBIT))?true:false;
48  _misoState = (_port & (1<<MISOBIT))?true:false;
49 
50  if(!_ssState){
51  if(_prevClkState != _sclkState){
52  _prevClkState = _sclkState;
53  if(_clockIsIdleHigh){
54  // Clock is HIGH when idle
55  if(_clockSampleOnLeadingEdge){
56  // Sample on leading edge
57  sample = (_sclkState)?false:true;
58  }
59  else {
60  // Sample on trailing edge
61  sample = (_sclkState)?true:false;
62  }
63  }
64  else {
65  // Clock is LOW when idle
66  if(_clockSampleOnLeadingEdge){
67  // Sample on leading edge
68  sample = (_sclkState)?true:false;
69  }
70  else {
71  // Sample on trailing edge
72  sample = (_sclkState)?false:true;
73  }
74  }
75  }
76  }
77  else {
78  _sr = 0;
79  _state = 0;
80  }
81 
82  for(;;){
83  switch(_state){
84  case 0: // Waiting for /SS
85  if(!_ssState){
86  _state = 1;
87  continue;
88  }
89  break;
90  case 1: // First sample
91  case 2: // Second sample
92  case 3: // Third sample
93  case 4: // Fourth sample
94  case 5: // Fifth sample
95  case 6: // Sixth sample
96  case 7: // Seventh sample
97  if(sample){
98  _sr <<= 1;
99  if(_misoState){
100  _sr |= 0x01;
101  }
102  ++_state;
103  }
104  break;
105  case 8: // First sample
106  if(sample){
107  _sr <<= 1;
108  if(_misoState){
109  _sr |= 0x01;
110  }
111  _state = 1;
112 
113  streamsize streamWidth = cout.width();
114  ios_base::fmtflags saved = cout.flags();
115  cout.setf(ios_base::hex,ios_base::basefield);
116  cout.setf(ios_base::uppercase);
117  cout.setf(ios_base::right);
118  cout << "spisink: 0x";
119  cout.width(2);
120  cout.fill('0');
121  cout << (unsigned long)_sr;
122  cout << endl;
123  cout.width(streamWidth);
124  cout.flags(saved);
125  }
126  break;
127  }
128  break;
129  }
130 
131  if(_ssState != _prevSS){
132  if(_ssState){
133  cout << "spisink: /SS negated" << endl;
134  }
135  else {
136  cout << "spisink: /SS asserted" << endl;
137  }
138  _prevSS = _ssState;
139  }
140 
141  return 0;
142  }
143 
int Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns=0)
Return nonzero if a breakpoint was hit.
Definition: spisink.cpp:42
STL namespace.
Definition: spisink.cpp:7
long long SystemClockOffset
SpiSink(Net &ssNet, Net &sclkNet, Net &misoNet, bool clockIsIdleHigh=true, bool clockSampleOnLeadingEdge=true)
Definition: spisink.cpp:12
Connect Pins to each other and transfers a output change from a pin to input values for all pins...
Definition: net.h:34