1 /*  Copyright (C) 2012 Eduard Timotei Budulea
2     Copyright (C) 2013 Roy R. Rankin
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "config.h"
18 #include "bit1w.h"
19 
20 bool debug = false;
21 
LowLevel1W(const char * name,const char * desc)22 LowLevel1W::LowLevel1W(const char *name, const char *desc):
23     Module(name, desc), cicluReper(0), lastValue(true),
24     lastTimeout(false),
25     state(&LowLevel1W::idle), ignoreCallback(false), bit_break(0)
26 {
27     pin = new Pin1W("pin", *this);
28     addSymbol(pin);
29     create_pkg(1);
30     assign_pin(1, pin);
31     pin->putState(false);
32     pin->update_direction(IOPIN::DIR_INPUT, true);
33     change(true);
34 }
~LowLevel1W()35 LowLevel1W::~LowLevel1W()
36 {
37     removeSymbol(pin);
38 }
39 
callback()40 void LowLevel1W::callback() {
41     change(false);
42 }
43 
change(bool pinChange)44 void LowLevel1W::change(bool pinChange) {
45     if (ignoreCallback) return;
46     guint64  ciclu = get_cycles().get();
47     bool bitValue = false;
48     switch(pin->getBitChar()) {
49     case 'Z':
50     case '1':
51     case 'x':
52     case 'W':
53         bitValue = true;
54     }
55     bool isTimeout = ciclu >= cicluReper;
56 
57 
58     if ((lastValue != bitValue || lastTimeout != isTimeout) && debug) {
59         cout << name() <<" +++change state: line = " << bitValue << ", timeout = " << isTimeout << "; time = " << hex << ciclu << ", reper = " << cicluReper << endl;
60     }
61     lastValue = bitValue;
62     lastTimeout = isTimeout;
63     ignoreCallback = true;
64     (this->*state)(bitValue, isTimeout);
65     ignoreCallback = false;
66     if (cicluReper > ciclu) {
67         if (!pinChange && bit_break >= ciclu) {
68             get_cycles().clear_break(bit_break);
69         }
70 	if(cicluReper != bit_break)
71             get_cycles().set_break(cicluReper, this);
72 	if(debug)
73 	    printf("%s now %" PRINTF_GINT64_MODIFIER "x next break  %" PRINTF_GINT64_MODIFIER "x last break %" PRINTF_GINT64_MODIFIER "x delta(usec) %.1f\n", name().c_str(), ciclu, cicluReper, bit_break, (cicluReper-ciclu)*4./20.);
74 	bit_break = cicluReper;
75     }
76 }
77 
idle(bool input,bool isTimeout)78 void LowLevel1W::idle(bool input, bool isTimeout) {
79     if(debug && !isTimeout)
80       cout <<name() << " idle input="<<input <<" timout="<<isTimeout<<endl;
81     if (input) return;
82     switch(gotBitStart()) {
83     case WRITE1:
84 	if(verbose) cout << name() << " ===write1" << endl;
85         state = &LowLevel1W::inWritting1;
86         cicluReper = get_cycles().get(0.000045);
87         return;
88 
89     case WRITE0:
90         if (verbose) cout << name() << " ===write0" << endl;
91         state = &LowLevel1W::inWritting0;
92         cicluReper = get_cycles().get(0.000040);
93         pin->update_direction(IOPIN::DIR_OUTPUT, true);
94         return;
95 
96     case READ:
97         if(verbose) cout << name() << " ===read" << endl;
98         state = &LowLevel1W::inReading;
99         cicluReper = get_cycles().get(0.000030);
100         return;
101 
102     case RESET:
103         if(verbose) cout << name() <<" ===expect reset" << endl;
104         state = &LowLevel1W::inResetPulse;
105         cicluReper = get_cycles().get(0.000440);
106         return;
107 
108     case IDLE:
109         state = &LowLevel1W::idle;
110 	return;
111     }
112 }
113 
inResetPulse(bool input,bool isTimeout)114 void LowLevel1W::inResetPulse(bool input, bool isTimeout) {
115     if(debug)
116       cout <<name() << " inResetPulse input="<<input <<" timout="<<isTimeout<<endl;
117     if (input) {
118         state = &LowLevel1W::idle;
119         return;
120     }
121     if (!isTimeout) return;
122     state = &LowLevel1W::endResetPulse;
123 }
124 
endResetPulse(bool input,bool isTimeout)125 void LowLevel1W::endResetPulse(bool input, bool isTimeout) {
126     if(debug)
127       cout << name() << " "<<__FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
128     if (!input) return;
129     gotReset();
130     state = &LowLevel1W::inPresencePulse;
131     cicluReper = get_cycles().get(0.00005);
132 }
133 
inPresencePulse(bool input,bool isTimeout)134 void LowLevel1W::inPresencePulse(bool input, bool isTimeout) {
135     if(debug)
136     cout << name() << " "<< __FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
137     if (!isTimeout) return;
138     state = &LowLevel1W::endPresencePulse;
139     pin->update_direction(IOPIN::DIR_OUTPUT, true);
140     cicluReper = get_cycles().get(0.0002);
141 }
142 
endPresencePulse(bool input,bool isTimeout)143 void LowLevel1W::endPresencePulse(bool input, bool isTimeout) {
144     if(debug)
145       cout << name() << " " << __FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
146     if (!isTimeout) return;
147     pin->update_direction(IOPIN::DIR_INPUT, true);
148     state = &LowLevel1W::waitIdle;
149     cicluReper = get_cycles().get(0.00002);
150 }
151 
waitIdle(bool input,bool isTimeout)152 void LowLevel1W::waitIdle(bool input, bool isTimeout) {
153     if(debug)
154       cout << name() << "waitIdle input=" <<input <<" timeout="<<isTimeout<<endl;
155     if (!input) return;
156     state = &LowLevel1W::idle;
157 }
158 
inWritting0(bool input,bool isTimeout)159 void LowLevel1W::inWritting0(bool input, bool isTimeout) {
160     if(debug)
161       cout << name() << " " << __FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
162     if (!isTimeout) return;
163     state = &LowLevel1W::finalizeBit;
164     pin->update_direction(IOPIN::DIR_INPUT, true);
165     //cicluReper = get_cycles().get(0.00006);
166     cicluReper = get_cycles().get(0.0000050);
167 }
168 
inWritting1(bool input,bool isTimeout)169 void LowLevel1W::inWritting1(bool input, bool isTimeout) {
170     if(debug)
171       cout <<name() << " " << __FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
172     if (!isTimeout) return;
173     if(!input) // OOPS either a reset or bus collision
174     {
175         state = &LowLevel1W::inResetPulse;
176         cicluReper = get_cycles().get(0.000440);
177 	return;
178     }
179     state = &LowLevel1W::idle;
180     if (bit_remaining() == 0)  gotBitStart();
181     //state = &LowLevel1W::finalizeBit;
182 }
183 
inReading(bool input,bool isTimeout)184 void LowLevel1W::inReading(bool input, bool isTimeout) {
185     if(debug)
186       cout << name() << " " << __FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
187     if (input) {
188         readBit(true);
189         state = &LowLevel1W::idle;
190         if (bit_remaining() == 0)  gotBitStart();
191         return;
192     }
193     if (!isTimeout) return;
194     readBit(false);
195     state = &LowLevel1W::finalizeBit;
196     // assume read < 120 us (30 + 90)
197     cicluReper = get_cycles().get(0.000090);
198 }
199 
200 // Wait for a 1 then go to idle
finalizeBit(bool input,bool isTimeout)201 void LowLevel1W::finalizeBit(bool input, bool isTimeout) {
202     if(debug)
203       cout << name() << " " <<__FUNCTION__ << "  input="<<input <<" timout="<<isTimeout<<endl;
204     if (input) {
205         state = &LowLevel1W::idle;
206 	if (bit_remaining() == 0)  gotBitStart();
207         return;
208     }
209     if (!isTimeout) return;
210     state = &LowLevel1W::inResetPulse;
211     cicluReper = get_cycles().get(0.000320);
212 }
213 
214