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 "rom1w.h"
19
20
21 class ROMCodeAttribute : public Integer {
22
23 public:
24
ROMCodeAttribute()25 ROMCodeAttribute()
26 : Integer("ROMCode",0x06050403020110LL,"Device ROM code")
27 {
28 // Add CRC
29 gint64 v = getVal();
30 set(v);
31 }
32
33
set(gint64 i)34 void set(gint64 i)
35 {
36 gint64 id = (i & 0xffffffffffff00LL) | 0x10;
37 gint64 crc;
38 crc = Rom1W::calculateCRC8((const unsigned char *)&id, 7);
39 id |= crc << 56;
40 Integer::set(id);
41 }
42
get(char * buffer,int buf_size)43 virtual void get(char *buffer, int buf_size)
44 {
45 if(buffer)
46 {
47 gint64 i;
48 i = getVal();;
49 snprintf(buffer,buf_size,"0x%" PRINTF_GINT64_MODIFIER "x",i);
50 }
51
52 }
53
54
toString()55 virtual string toString()
56 {
57 return Integer::toString("0x%" PRINTF_INT64_MODIFIER "x");
58 }
59
60 };
gotReset()61 void Rom1W::gotReset() {
62
63 if(verbose) cout << name() << " got rom reset" << endl;
64 romState = &Rom1W::readRomCommand;
65 bitRemaining = 8;
66 isReading = true;
67 }
68
getBit(int bitIndex,unsigned char * buffer)69 static bool getBit(int bitIndex, unsigned char * buffer) {
70 return 0 != (buffer[bitIndex / 8] & (1 << (7 - bitIndex % 8)));
71 }
72
gotBitStart()73 Rom1W::NextAction Rom1W::gotBitStart() {
74 if(verbose)cout << name() << " gotBitStart" << endl;
75 if (--bitRemaining < 0) return (this->*romState)();
76 if (isReading) return READ;
77 bool write1 = getBit(bitRemaining, octetBuffer);
78 if(verbose)
79 cout << name() << " writing bit = " << write1 << " remaining " << bitRemaining <<endl;
80 return write1 ? WRITE1 : WRITE0;
81 }
82
readBit(bool value)83 void Rom1W::readBit(bool value) {
84 if(verbose)
85 cout << name() << " " << __FUNCTION__ << " got readbit = " << value << endl;
86 if (value)
87 octetBuffer[bitRemaining / 8] |= 1 << (7 - bitRemaining % 8);
88 else
89 octetBuffer[bitRemaining / 8] &= ~(1 << (7 - bitRemaining % 8));
90
91 if (verbose && (bitRemaining % 8) == 0)
92 {
93 printf("%s read byte %0x index %d\n", name().c_str(), octetBuffer[bitRemaining / 8], (bitRemaining / 8));
94 }
95 }
96
int64ToBuff(long long unsigned int num,unsigned char * buff)97 static void int64ToBuff(long long unsigned int num, unsigned char * buff) {
98 for (int i = 0; i < 8; ++i)
99 buff[i] = num >> ((7 - i) * 8);
100 }
101
readRomCommand()102 Rom1W::NextAction Rom1W::readRomCommand() {
103 if(verbose)
104 cout << name() << " "<<__FUNCTION__ << " got " << hex << (int)octetBuffer[0] << endl;
105 gint64 intaddr;
106 switch (octetBuffer[0]) {
107 case 0x33: // Skip ROM
108 isSelected = false;
109 romState = &Rom1W::readRom;
110 intaddr = attr_ROMCode->getVal();
111 int64ToBuff(intaddr, octetBuffer);
112 bitRemaining = 64;
113 isReading = false;
114 return IDLE;
115
116 case 0x55: // Match ROM
117 isSelected = false;
118 romState = &Rom1W::matchRom;
119 bitRemaining = 64;
120 isReading = true;
121 return READ;
122
123 case 0xEC: // Alarm Search
124 // Fall through to Search ROM
125
126 case 0xF0: // Search ROM
127 isSelected = (octetBuffer[0]==0xF0 || isAlarm())?true:false;
128 romState = &Rom1W::searchRom;
129 intaddr = attr_ROMCode->getVal();
130 int64ToBuff(intaddr, octetBuffer + 1);
131 if (octetBuffer[8] & 1)
132 octetBuffer[0] = 0x40;
133 else
134 octetBuffer[0] = 0x80;
135 octetBuffer[9] = 63;
136 bitRemaining = 2;
137 isReading = false;
138 return IDLE;
139
140 case 0xCC: // Skip ROM
141 isSelected = false;
142 if(verbose)
143 cout << name() << " Skip rom function command\n";
144 break;
145
146 case 0xA5:
147 if (isSelected) break;
148 default:
149 return RESET;
150 }
151 return readRom();
152 }
153
readRom()154 Rom1W::NextAction Rom1W::readRom() {
155 if(verbose) cout << name() << " called " << __FUNCTION__ << endl;
156 resetEngine();
157 romState = &Rom1W::deviceData;
158 return IDLE;
159 }
160
matchRom()161 Rom1W::NextAction Rom1W::matchRom() {
162 if(verbose) cout << name() << " called " << __FUNCTION__ << endl;
163 unsigned char myaddr[8];
164 gint64 intaddr;
165 intaddr = attr_ROMCode->getVal();
166 int64ToBuff(intaddr, myaddr);
167 if (memcmp(myaddr, octetBuffer, 8))
168 {
169 if(verbose)
170 {
171 cout << name() << " " << hex << intaddr << " no match\n got ";
172 for(int i=0; i < 8; i++)
173 printf("%x", octetBuffer[i]);
174 cout <<endl;
175 }
176 return ignoreData();
177 }
178 if(verbose) cout << name() << " " << hex << intaddr << " match\n";
179 isSelected = true;
180 return readRom();
181 }
182
searchRom()183 Rom1W::NextAction Rom1W::searchRom() {
184 if(verbose)
185 cout << name() << " called " << __FUNCTION__ << " isReading " << isReading <<endl;
186 if (isReading) {
187 bool myBit = getBit(octetBuffer[9], octetBuffer + 1);
188 if (myBit != (0 != (0x80 & octetBuffer[0])))
189 {
190 isSelected = false;
191 }
192 if (!octetBuffer[9]) // read all bits
193 {
194 if(isSelected)
195 {
196 if(verbose)
197 printf("%s searchRom selected\n", name().c_str());
198 return RESET;
199 }
200 else
201 {
202 if (verbose)
203 printf("%s searchRom not selected\n", name().c_str());
204 return RESET;
205 }
206 }
207 if (getBit(--octetBuffer[9], octetBuffer + 1))
208 octetBuffer[0] = 0x40;
209 else
210 octetBuffer[0] = 0x80;
211 if (!isSelected)
212 octetBuffer[0] = 0xC0; // do not pull down the bus
213 bitRemaining = 2;
214 isReading = false;
215 return IDLE;
216 }
217 isReading = true;
218 bitRemaining = 1;
219 return IDLE;
220 }
221
deviceData()222 Rom1W::NextAction Rom1W::deviceData() {
223 if(verbose)
224 cout << name() << " called " << __FUNCTION__ << endl;
225 doneBits();
226 return RESET;
227 }
228 //
229 // Just read data until a reset pulse happens
ignoreData()230 Rom1W::NextAction Rom1W::ignoreData() {
231 if (verbose)
232 cout << name() << " called " << __FUNCTION__ << endl;
233 romState = &Rom1W::ignoreData;
234 bitRemaining = 64;
235 isReading = true;
236 return READ;
237 }
238 //
239 // Allow reading of device status
240 //
statusPoll()241 Rom1W::NextAction Rom1W::statusPoll() {
242 if(verbose)
243 cout << name() << " called " << __FUNCTION__ << endl;
244 bitRemaining = 8;
245 octetBuffer[0] = isReady?0xff:0x00;
246 isReading = false;
247 return IDLE;
248 }
249
250 // This is called to setup polling of device status.
251 // delay is the cycle counter after which the poll will return 1's
set_status_poll(guint64 delay)252 void Rom1W::set_status_poll(guint64 delay)
253 {
254 isReady = false;
255 bitRemaining = 8;
256 isReading = false;
257 octetBuffer[0] = 0x00;
258 romState = &Rom1W::statusPoll;
259 if (delay > get_cycles().get())
260 {
261 if (poll_break)
262 get_cycles().clear_break(poll_break);
263 get_cycles().set_break(delay, this);
264 if(verbose)
265 printf("%s to poll busy for %.3f mS\n",
266 name().c_str(), (delay - get_cycles().get())*4./(20. * 1000.));
267 poll_break = delay;
268 }
269 }
270
271 // Rom1W::callback catches breaks from both Bit1W and Rom1W
272 // and uses last break setting (bit_break-Bit1W and poll_break-Rom1W)
273 // to determine what action to take
callback()274 void Rom1W::callback()
275 {
276 guint64 now = get_cycles().get();
277 if (now == poll_break)
278 {
279 isReady = true;
280 octetBuffer[0] = 0xff;
281 poll_break = 0;
282 }
283 if(now == bit_break)
284 LowLevel1W::callback();
285 }
286
Rom1W(const char * _name,const char * desc)287 Rom1W::Rom1W(const char *_name, const char *desc):
288 LowLevel1W(_name, desc), isSelected(false), bitRemaining(0),
289 isReading(false), romState(&Rom1W::deviceData)
290 {
291 poll_break = 0;
292 attr_ROMCode = new ROMCodeAttribute();
293 addSymbol(attr_ROMCode);
294 }
295
~Rom1W()296 Rom1W::~Rom1W() {
297 removeSymbol(attr_ROMCode);
298 delete attr_ROMCode;
299 }
300
301 static const guint8 crc8Table[256] = {0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
302 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
303 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
304 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
305 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
306 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
307 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
308 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
309 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
310 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
311 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
312 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
313 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
314 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
315 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
316 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
317
calculateCRC8(const unsigned char * buffer,int bufferLen)318 guint8 Rom1W::calculateCRC8(const unsigned char *buffer, int bufferLen) {
319 guint8 crc = 0;
320 for (int i = 0; i < bufferLen; ++i)
321 crc = crc8Table[crc ^ buffer[i]];
322 return crc;
323 }
324