forked from smurfix/owslave
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathds2409.c
344 lines (332 loc) · 9.74 KB
/
ds2409.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/*
* Copyright © 2010, Matthias Urlichs <matthias@urlichs.de>
* Copyright (c) 2013, Marc Dirix <marc@dirix.nu>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License (included; see the file LICENSE)
* for more details.
*/
/* This code implements (some of) the DS2409 MicroLan Coupler (obsolete).
*/
#include <avr/io.h>
#include "features.h"
#include "onewire.h"
#define C_CONTROL 0x5A
#define C_ALL_OFF 0x66
#define C_DISCHARGE 0x99
#define C_DIRECT_MAIN_ON 0xA5
#define C_SMART_MAIN_ON 0xCC
#define C_SMART_AUX_ON 0x33
#define MAIN_CONTROL (0x01<<PA0)
#define AUX_CONTROL (0x01<<PA1)
#define MAIN_IN (0x01<<PA3)
#define AUX_IN (0x01<<PA2)
#define DEBUGP (0x01<<PA5)
#define CONTROL_OUTPUT (0x01<<PA4)
#define S_MODE 0x80
#define S_CONTROL 0x40
#define S_AUX_EVENT 0x20
#define S_MAIN_EVENT 0x10
#define S_AUX_LEVL 0x08
#define S_AUX_STAT 0x04
#define S_MAIN_LEVL 0x02
#define S_MAIN_STAT 0x01
volatile u_char status_info = 0x00;
void do_command(u_char cmd)
{
switch(cmd)
{
case C_CONTROL:
{
u_char control_byte=0;
//DISCHARGE OFF
DDRA &= ~(MAIN_IN|AUX_IN);
//Update Status
recv_byte();
control_byte = recv_byte_in();
//Write Low Enabled
if( !(control_byte & 0x18) )
{
//Set Mode Auto or Manual.
if ( control_byte & 0x20 )
status_info |= S_MODE;
else
status_info &= ~S_MODE;
status_info |= (control_byte & 0x20)<<3;
//Set Control or Transistor if Mode Auto or Manual
if( status_info&S_MODE)
{
//Manual Mode
if ( control_byte & 0x80 )
{
status_info |= S_CONTROL;
PORTA |= (CONTROL_OUTPUT);
}
else
{
status_info &= ~S_CONTROL;
PORTA &= ~(CONTROL_OUTPUT);
}
}
else
{
//Auto Mode
//FIXME Set output transistor.
if ( control_byte & 0x40 )
{
status_info |= S_CONTROL;
//Set status transtor based on association
if ( ! (status_info & S_MAIN_STAT) )
PORTA |= (CONTROL_OUTPUT);
else if ( ! (status_info & S_AUX_STAT) )
PORTA &= ~(CONTROL_OUTPUT);
}
else
status_info &= ~S_CONTROL;
//Set status transtor based on inverted association
if ( ! (status_info & S_AUX_STAT) )
PORTA |= (CONTROL_OUTPUT);
else if ( ! (status_info & S_MAIN_STAT) )
PORTA &= ~(CONTROL_OUTPUT);
}
}
//Check if Main and Aux have no short circuit
if( PINA & MAIN_IN )
status_info |= S_MAIN_LEVL;
else
status_info &= ~S_MAIN_LEVL;
if( PINA & AUX_IN )
status_info |= S_AUX_LEVL;
else
status_info &= ~S_AUX_LEVL;
xmit_byte(status_info);
xmit_byte(status_info);
break;
}
case C_ALL_OFF:
{
//DISCHARGE OFF
DDRA &= ~(MAIN_IN|AUX_IN);
//DEACTIVATE MAIN and AUX
PORTA |= (MAIN_CONTROL|AUX_CONTROL);
//Clear Event Flags
status_info &= ~(S_MAIN_EVENT|S_AUX_EVENT);
//UPDATE AUTO CONTROL
if( !(status_info&S_MODE) )
status_info |= (S_MAIN_STAT|S_AUX_STAT);
//Return Acknowledge
xmit_byte(C_ALL_OFF);
break;
}
case C_DISCHARGE:
//DEACTIVATE MAIN and AUX
PORTA |= (MAIN_CONTROL|AUX_CONTROL);
//DISCHARGE ON
DDRA |= (MAIN_IN|AUX_IN);
xmit_byte(C_DISCHARGE);
break;
case C_DIRECT_MAIN_ON:
//DISCHARGE OFF
//DDRA &= ~(MAIN_IN|AUX_IN);
//AUX OFF
PORTA |= (AUX_CONTROL);
//MAIN ON
PORTA &= ~(MAIN_CONTROL);
//UPDATE AUTO CONTROL
xmit_byte(C_DIRECT_MAIN_ON);
status_info &= ~(S_MAIN_STAT);
status_info |= (S_AUX_STAT);
if( !(status_info&S_MODE) )
{
status_info &= ~(S_CONTROL);
if( status_info&S_CONTROL )
PORTA &= ~(CONTROL_OUTPUT);
else
PORTA |= (CONTROL_OUTPUT);
}
break;
case C_SMART_MAIN_ON:
{
u_char shortcircuit=0,presence=0;
u_short loop;
//DISCHARGE OFF
DDRA &= ~(MAIN_IN|AUX_IN);
//MAIN OFF
PORTA |= (MAIN_CONTROL);
//Test Short Circuit
shortcircuit = (PINA&MAIN_IN)?0:1;
//RESET ON
recv_bit();
recv_bit_in();
DDRA |= (MAIN_IN);
//recv_byte();
for(loop=7;loop>0;loop--)
{
recv_bit();
recv_bit_in();
}
//RESET OFF
DDRA &= ~(MAIN_IN);
//Sleep 50us
for( loop = 750; loop > 0; loop--)
{
presence &= (PINA&MAIN_IN)?1:0;
}
//PORTA &= ~DEBUGP;
//Copy MAIN_IN to 1-wire
for(loop=8;loop>0;loop--)
{
xmit_bit( presence );
xmit_bit_out();
}
if( shortcircuit )
{
//Return Inverted Command
xmit_byte(~C_SMART_MAIN_ON);
xmit_byte_out();
//UPDATE AUTO CONTROL
status_info &= ~S_MAIN_LEVL;
}
else
{
//Return Command
xmit_byte(C_SMART_MAIN_ON);
xmit_byte_out();
//Add some delay.
for ( loop = 300; loop > 0; loop -- )
{
presence&=(PINA&MAIN_IN);
}
//AUX OFF
PORTA |= (AUX_CONTROL);
//MAIN ON
PORTA &= ~(MAIN_CONTROL);
//set_idle();
//UPDATE AUTO CONTROL
status_info |= S_AUX_STAT;
status_info &= ~S_MAIN_STAT;
if( !(status_info&S_MODE) )
{
status_info &= ~(S_CONTROL);
if( status_info&S_CONTROL )
PORTA &= ~(CONTROL_OUTPUT);
else
PORTA |= (CONTROL_OUTPUT);
}
}
break;
}
case C_SMART_AUX_ON:
{
u_char shortcircuit=0,presence=0;
u_short loop;
//DISCHARGE OFF
DDRA &= ~(MAIN_IN|AUX_IN);
//AUX OFF
PORTA |= (AUX_CONTROL);
//Test Short Circuit
shortcircuit = (PINA&AUX_IN)?0:1;
for(loop=3;loop>0;loop--)
{
shortcircuit &= (PINA&AUX_IN)?0:1;
}
//RESET ON
recv_bit();
recv_bit_in();
DDRA |= (AUX_IN);
//recv_byte();
for(loop=7;loop>0;loop--)
{
recv_bit();
recv_bit_in();
}
//RESET OFF
DDRA &= ~(AUX_IN);
//Check for presence puls during delay.
for( loop = 750; loop > 0; loop--)
{
presence &= (PINA&AUX_IN)?1:0;
}
//PORTA &= ~DEBUGP;
//Copy AUX_IN to 1-wire
for(loop=8;loop>0;loop--)
{
xmit_bit( presence );
xmit_bit_out();
}
if( shortcircuit )
{
//Return Inverted Command
xmit_byte(~C_SMART_AUX_ON);
xmit_byte_out();
//UPDATE AUTO CONTROL
status_info &= ~S_AUX_LEVL;
}
else
{
//Return Command
xmit_byte(C_SMART_AUX_ON);
xmit_byte_out();
//Add some delay.
for ( loop = 300; loop > 0; loop -- )
{
presence&=(PINA&AUX_IN);
}
//MAIN OFF
PORTA |= (MAIN_CONTROL);
//AUX ON
PORTA &= ~(AUX_CONTROL);
//UPDATE AUTO CONTROL
status_info |= S_MAIN_STAT;
status_info &= ~S_AUX_STAT;
if( !(status_info&S_MODE) )
{
status_info |= S_CONTROL;
if( status_info&S_CONTROL )
PORTA |= (CONTROL_OUTPUT);
else
PORTA &= ~(CONTROL_OUTPUT);
}
}
break;
}
default:
set_idle();
}
}
void update_idle(u_char bits)
{
//Check for events
//FIXME maybe pinchange interrupts
//Check if Main inactive
if( status_info & S_MAIN_STAT )
//Pin Low is Event
if( ! (PINA&MAIN_IN))
status_info |= S_MAIN_EVENT;
//Check if Aux inactive
if( status_info & S_AUX_STAT )
//Pin Low is Event
if( ! (PINA&AUX_IN))
status_info |= S_AUX_EVENT;
}
void init_state(void)
{
DDRA |= (MAIN_CONTROL|AUX_CONTROL|CONTROL_OUTPUT);
//PORTA &= ~(MAIN_CONTROL);
//Set MAIN Control, AUX Control and Presence Outputs
DDRA |= (MAIN_CONTROL|AUX_CONTROL);
//DDRA |= (DEBUGP);
//Switch Off MAIN, AUX and CONTROL_OUTPUT ON
PORTA |= (MAIN_CONTROL|AUX_CONTROL|CONTROL_OUTPUT);
//PORTA &= ~(DEBUGP);
//Set MAIN In and Aux HIZ inputs, low output
DDRA &= ~(MAIN_IN|AUX_IN);
PORTA &= ~(MAIN_IN|AUX_IN);
}