In den 80-ern und 90-ern war das Selectrix Digitalsystem revolutionär in Technik und Anwendung. Heute zu Tage ist die Rolle leider nicht mehr so groß, und mehr und mehr von DCC übernommen. So fehlt im Moment z.B eine Selectrix Zentrale mit Netzwerkanschluss. Da bei mir der Computer nicht direkt an der Anlage steht ist das entscheidend für die Weiterverwendung von Selectrix Decoder.
Dann habe ich eine große Menge Weichenmotoren mit den dazu passenden Sx Decodern bekommen, die ich auf der Anlage sehr gut gebrauchen kann. Und so habe ich nachgedacht wie ich die Decoder weiterverwenden kann, ohne Selectrix Zentrale. Ich brauche so zu sagen eine DCC nach Selectrix Bridge.
Die heutige Microcontroller bieten hierfür eine Möglichkeit. Schon lange gibt es für die Arduino (Nano) Module Software, die DCC Signale verarbeiten können, als NMRA DCC Bibliothek. Dann habe ich im Netz auch tolle Software von Gerard van der Sel gefunden. Er hat einen Bibliothek programmiert für das dekodieren von Selectrix Signale mit einem Arduino. Und nebenbei auch eine kleine Selectrix Zentrale für den Arduino programmiert. Ich habe beide Softwares genommen, die Zentrale leicht modifiziert und zusammengebaut. Leider geht das nicht auf nur einer Arduino, sie ist dafür zu langsam, so dass ich sie auf 2 Arduino Nanos verteilen muss, eine für das dekodieren des DCC Signales, und eine für das generieren des Selectrix Signals.
Ich kann jetzt die Selectrix Weichendecoder weiter verwenden, und von meiner DCC Zentrale (Ecos) und Software steuern.
Ich stelle hier die Software gerne zur Verfügung. Sie wird also 2 mal verwendet, einmal für die DCC Arduino, und einmal für die Selectrix Arduino. Hierzu wird in SelectrixCentrlae.ino entweder #define DCCSIDE oder #define SXSIDE aktiviert. Da es nicht möglich ist, die Selectrix Arduino zu programmieren wenn die DCC Arduino aktiv ist und Daten sendet, habe ich in der Hardware einen Jumper eingebaut, die beim Programmieren entfernt wird.
Code für die Arduinos hier unten, Schaltplan in der Beilage.
Hier die Arduino SelectrixCentrale.ino Datei
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
/*
SX1 centrale
Creator: Gerard van der Sel / R. Helder
Version: 2.0
Date: 05-02-2025
This software forms a bridge between a DCC signal and the Selectrix SX bus on an Arduino.
I originally tried to run the complete code on one Arduino Nano, but the frequent interrupts from the DCC signal
made this impossible, probably also because there are in my case other protocols on the track
This means that the code runs on 2 Arduino Nano board that are connected to each other by Tx/Rx pin.
One board receives the DCC signals. This code is complete based on the NMRA DCC library. When a valid DCC accesory
command is received, the function notifyDccAccTurnoutOutput() is called and a message with format S<adress> or
R<adress> is sent from the Tx pin to the other board. Adress is in the DCC range 0 < a < 800
The second board generates the Sx Signal. It has a buffer of 112 adresses, pre formatted for the bus signal.
When the S or R command is received, the function serialEvent() interprets the message and alters this buffer
with the new data, which is one bit in this buffer for a specific adress.
To compile for the DCC board, uncomment DCCSIDE below
To compile for the SX board, uncomment SXSIDE below
Remeber to disconnect the Tx-Rx line before uploading new code !
Extra hardware needed is de DCC-Arduino board which contains the hardware to read from the DCC-bus: the DCC signal
is read through an opto-coupler on pin D2
Extra hardware needed is de SX-Arduino board which contains the hardware to communicate with the SX-bus:
Connect Arduino pin D3 to pin 1 and 3 of a SN74HCT04. Pin 2 and 4 are connected through a 220 Ohm resistor each to
the Sx T0 line. Connect Arduino pin D4 to pin 5 of a SN74HCT04. Pin 6 is connected through a 220 Ohm resistor to
the Sx T1 line. Gnd must also be connected.
*/
#include <Arduino.h>
#include "SXcentrale.h"
#include <NmraDcc.h>
NmraDcc Dcc; // Interface to the DCC track for reading
SXcentrale SXcntrl; // Interface to the SX-bus and track
//#define DCCSIDE // uncomment to compile for the DCC board
#define SXSIDE // uncomment to compile for the SX board
//------------------------------------------------------------------------------
ISR(TIMER1_OVF_vect)
// interrupt service routine
//------------------------------------------------------------------------------
{
SXcntrl.isr();
}
//------------------------------------------------------------------------------
void setup()
// put your setup code here, to run once:
//------------------------------------------------------------------------------
{
#ifdef DCCSIDE
// initialize Nmra DCC communication
// for info: github.com/mrrwa/NmraDcc/blob/master/NmraDcc.h
Dcc.pin(0, 2, 1);
Dcc.init(MAN_ID_DIY, 10, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0);
#endif
// initialize serial:
Serial.begin(115200);
//Serial.println("Start SxBridge");
//delay(1000);
#ifdef SXSIDE
// initialize SX-bus
SXcntrl.init();
#endif
// initialize application
pinMode(LED_BUILTIN, OUTPUT);
}
//------------------------------------------------------------------------------
void serialEvent()
{
uint8_t dccAdres[2];
uint8_t cmd;
static bool on = false;
#ifdef SXSIDE
// Read all the data. Data is sent in a frame that starts with 'S' or 'R' for synchronisation
// Format: S001 for setting adres 1
// R001 for resetting adres 1
while (Serial.available())
{
cmd = (uint8_t)Serial.read();
// Serial.print('.');
if (cmd == 'S' || cmd == 'R')
{
uint8_t nr = Serial.readBytes(dccAdres, 3);
if (nr == 3)
{
uint16_t adres = 100*(dccAdres[0]-'0') + 10*(dccAdres[1]-'0') + dccAdres[2]-'0';
if (adres < 8*SX_ADDRESS_NUMBER)
{
if (cmd == 'S')
{
SXcntrl.setbit(0, adres, 1);
Serial.print("S");Serial.println(adres);
}
else
{
SXcntrl.setbit(0, adres, 0);
Serial.print("R");Serial.println(adres);
}
}
}
}
}
#endif
}
//------------------------------------------------------------------------------
void loop()
// put your main code here, to run repeatedly:
//------------------------------------------------------------------------------
{
#ifdef DCCSIDE
// DCC-Kommandos empfangen
Dcc.process();
#endif
/*
// DEBUG: Blink 2 outputs on Sx decoder
// SXcntrl.set(0, 1, 2);
SXcntrl.setbit(0, 1, 1);
SXcntrl.setbit(0, 2, 0);
delay(1000); // wait for a second
// SXcntrl.set(0, 1, 4);
SXcntrl.setbit(0, 1, 0);
SXcntrl.setbit(0, 2, 1);
Serial.println();
delay(1000); // wait for a second
*/
}
//------------------------------------------------------------------------------
void notifyDccAccTurnoutOutput (uint16_t Addr, uint8_t Direction, uint8_t OutputPower)
/* notifyDccAccTurnoutOutput() Output oriented callback for a turnout accessory decoder.
* Most useful when CV29_OUTPUT_ADDRESS_MODE IS set.
* OutputPower is 1 if the power is on, and 0 otherwise.
*
* Inputs:
* Addr - Per output address. There will be 4 Addr addresses
* per board for a standard accessory decoder with 4 output pairs.
* Direction - Turnout direction. It has a value of 0 or 1.
* Equivalent to bit 0 of the 3 DDD bits in the accessory packet.
* OutputPower - Output On/Off. Equivalent to packet C bit. It has these values:
* 0 - Output is off.
* 1 - Output is on.
*
* Returns:
* None
*/
//------------------------------------------------------------------------------
{
uint8_t SxAddress; // calculated Selectrix address
uint8_t SxData[4];
static uint8_t prevAddr = -1;
static uint8_t prevDirection = -1;
if (!OutputPower)
return;
if (prevAddr != Addr || prevDirection != Direction)
{
// Centrale zend meerdere pakketten achter elkaar, filter deze
prevAddr = Addr;
prevDirection = Direction;
if (Direction)
SxData[0] = 'S';
else
SxData[0] = 'R';
SxData[1] = (Addr / 100) + '0';
SxData[2] = (Addr % 100) / 10 + '0';
SxData[3] = (Addr % 10) + '0';
Serial.write(SxData, 4);
}
}
Und die SXmaster.cpp
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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/*
* SXmaster.cpp
*
* Version: 0.2
* Copyright: Gerard van der Sel / Ronald Helder
*
* Changed on: 27-01-2025
* Version: 0.2
* Changes: Complete rewritten for efficiency, but only for Sx0
*
*
* interface hardware needed !
Interface SX-bus voor de centrale:
- SX T0 (Clock) must be connected to D3 ;
- SX T1 must be connected to Pin D4 ;
- SX D must be connected to Pin D5 .
SX-bus interface (NEM 681)
De clock lijn (T0) is verbonden met een interruptingang, zodat op
de flanken van dit signaal een interrupt gegenereerd kan worden.
Hierna kan data gelezen worden van T1 of data geschreven worden naar D.
Klok:
-- ---------------- ---------------- ---------------- ------
| | | | | | | |
-- -- -- --
Data:
-- ------------------- ------------------- ------------------- ---------
X X X X
-- ------------------- ------------------- ------------------- ---------
^ ^ ^ ^ ^ ^ ^ ^
W R W R W R W R
Opbouw telegram (96 bits):
0 0 0 1 S 1 A3 A2 1 A1 A0 1 synchronisatie 'byte'
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1 7 data 'bytes'
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1 ieder 'byte' is de inhoud
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1 van een adres
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
0 = Logische 0
1 = Logische 1
S = Spanning rails (0 = uit, 1= aan)
Ax = Gezamelijk het nummer van het telegram
Dx = D0 t/m D7 vormen de data op een Selectrix adres.
Verdeling adressen over de verschillende telegrammen:
telegram '0' : 111, 95, 79, 63, 47, 31, 15
telegram '1' : 110, 94, 78, 62, 46, 30, 14
telegram '2' : 109, 93, 77, 61, 45, 29, 13
telegram '3' : 108, 92, 76, 60, 44, 28, 12
telegram '4' : 107, 91, 75, 59, 43, 27, 11
telegram '5' : 106, 90, 74, 58, 42, 26, 10
telegram '6' : 105, 89, 73, 57, 41, 25, 9
telegram '7' : 104, 88, 72, 56, 40, 24, 8
telegram '8' : 103, 87, 71, 55, 39, 23, 7
telegram '9' : 102, 86, 70, 54, 38, 22, 6
telegram '10' : 101, 85, 69, 53, 37, 21, 5
telegram '11' : 100, 84, 68, 52, 36, 20, 4
telegram '12' : 99, 83, 67, 51, 35, 19, 3
telegram '13' : 98, 82, 66, 50, 34, 18, 2
telegram '14' : 97, 81, 65, 49, 33, 17, 1
telegram '15' : 96, 80, 64, 48, 32, 16, 0
In deze versie worden alle 16 telegrammen volgens bovenstaand
patroon bij initialisatie al opgebouwd, zodat in de isr geen
test of rekenwerk hoeft plaats te vinden, en de isr dus erg
efficient wordt. Bij het schrijven naar de database set()
wordt gelijk al in dit patroon geschreven.
** SX Timing **
1 Bit 50 us
1 Kanal 600 us (= 12 Bit)
1 Grundrahmen ca. 4,8 ms
1 Gesamtrahmen ca. 80 ms (= 16 Grundrahmen)
0 0 0 1 S 1 A3 A2 1 A1 A0 1 == sync frame of 12 bits
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include "SXcentrale.h"
SXcentrale::SXcentrale()
{
}
//------------------------------------------------------------------------------
void SXcentrale::init()
// initialize function
//------------------------------------------------------------------------------
{
// Initialize pins and variables
pinMode(SX_T0, OUTPUT); // SX-T0 is an output
pinMode(SX0_T1, OUTPUT); // SX0_T1 is also an output
pinMode(SX0_D, INPUT_PULLUP); // SX0_D is an input
digitalWrite(SX_T0, LOW);
digitalWrite(SX0_T1, LOW);
// Create the datastructure that will be send 1:1 to the bus, bit by bit
for (uint8_t sx_frame = 0; sx_frame < SX_TELCOUNT; sx_frame++)
{
// Fill first row with (LSB->MSB): 0 0 0 1 S 1 A3 A2 1 A1 A0 1 synchronisatie 'byte'
int idx = sx_frame*SX_DATACOUNT;
uint16_t adres = (sx_frame);
sxbusSX0[idx] = 0x0928; // 1's: B0000100100101000
sxbusSX0[idx] |= 0x0010; // PWR: B0000000000010000
sxbusSX0[idx] |= (adres & 0x0008) << 3; // A3
sxbusSX0[idx] |= (adres & 0x0004) << 5; // A2
sxbusSX0[idx] |= (adres & 0x0002) << 8; // A1
sxbusSX0[idx] |= (adres & 0x0001) << 10; // A0
for (uint8_t sx_telgram = 1; sx_telgram < SX_DATACOUNT; sx_telgram++)
{
// Fill each datarow with D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1, with every D = 0 (for now)
sxbusSX0[idx + sx_telgram] = 0x0924;
}
}
/* DEBUG
for (int i=0; i<48; i++)
{
Serial.println(sxbusSX0[i], BIN);
delay(100);
}
Serial.println("---------------------------------------");
delay(2000);
*/
// initialize timer1
uint8_t oldSREG = SREG;
noInterrupts(); // disable all interrupts
// Set timer1 to the correct value for our interrupt interval
TCCR1A = 0;
TCCR1B = (1 << CS10);
TCNT1 = Timer1_40; // preload timer with 40usec delay
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
SREG = oldSREG; // restore interrupts
}
void SXcentrale::initVar(void)
{
}
// Local functions
//------------------------------------------------------------------------------
void SXcentrale::writeT0(void)
// Write clock line high (inverted because hardware (TTL 7404) inverts again)
//------------------------------------------------------------------------------
{
uint8_t port = (SX_T0_PORT & B11110111);
SX_T0_PORT = port;
}
//------------------------------------------------------------------------------
void SXcentrale::writeT0T1(void)
// Write clock low and transmit line according to data
// (inverted because hardware (TTL 7404) inverts again)
//------------------------------------------------------------------------------
{
static uint16_t *pData = sxbusSX0; // pointer to data to be sent (for efficiency)
static uint16_t sx_sendmask = 0x0001; // Start with sending LSB
/* DEBUG
x = 0; //(pData == &sxbusSX0[119]);
if (x) Serial.print("Data:");
if (x) Serial.print(*pData, BIN);
if (x) Serial.print(" SM:");
if (x) Serial.print(sx_sendmask, BIN);
if (x) Serial.print(":");
if (x) Serial.println((*pData & sx_sendmask) ? 1:0);
*/
uint8_t port = (SX_T0_PORT & B11100111);
if (*pData & sx_sendmask)
port |= B00001000;
else
port |= B00011000;
SX_T0_PORT = port;
sx_sendmask = sx_sendmask << 1;
if (sx_sendmask & 0x1000)
{
// End of group (line / adres)
sx_sendmask = 0x0001;
pData++; // point to next channel
if (pData >= (&sxbusSX0[SX_TELCOUNT * SX_DATACOUNT]))
{
pData = sxbusSX0; // been round all channels/adresses, start again
// Serial.println("****** ROUND *******");
}
}
}
//------------------------------------------------------------------------------
void SXcentrale::readD(void)
// Read data line
// Data reading is not done in this version [because I don't need it ;-) ]
//------------------------------------------------------------------------------
{
}
//------------------------------------------------------------------------------
void SXcentrale::isr(void)
// Interrupt service routine (AVR OVERFLOW T1)
//------------------------------------------------------------------------------
{
static bool _writeFase = true;
if (_writeFase)
{
// 10 usec fase (make clock low and write data)
writeT0T1(); // Clock low and write 1 databit
_writeFase = false;
TCNT1 += Timer1_10; // reload timer
}
else
{
// 40 usec fase (make clock high and read data)
writeT0(); // Clock high
readD();
_writeFase = true;
TCNT1 += Timer1_40; // reload timer
}
}
//------------------------------------------------------------------------------
uint8_t SXcentrale::calcIndex(uint8_t SXadr)
// Convert from SX-bus addresses to index in array.
//------------------------------------------------------------------------------
{
uint8_t frame = 15 - (SXadr & 0x0F); // Get the frame number
uint8_t offset = 7 - (SXadr >> 4); // Get the offset in the frame
// Serial.print(SXadr);
// Serial.print("=");
// Serial.print(frame);
// Serial.print(".");
// Serial.println(offset);
return frame * 8 + offset; // Calculate the index in the array
}
// functions 'accessing' the SX-bus
//------------------------------------------------------------------------------
int SXcentrale::get(uint8_t bus, uint8_t adr)
// Read data from the array, filled by the isr.
// In:
// bus: 0 - 3, bus to read from.
// adr: 0 - 111, address value read from.
// Return value:
// -1: Address out of range
// -3: SX-bus out of range
// 0 - 255: Value from SX-bus
//------------------------------------------------------------------------------
{
// returns the value of a SX address
if (adr < SX_ADDRESS_NUMBER)
{
switch (bus)
{
case 0:
return sxbusSX0[calcIndex(adr)] & 0xff; // Return value
default:
return -3; // Report bus out of range
}
}
return -1; // Report address out of range
}
//------------------------------------------------------------------------------
int SXcentrale::set(uint8_t bus, uint8_t adr, uint8_t data)
// Write data to the array, writing to the SX-bus is done by the isr.
// In:
// bus: 0 - 3, bus to send value to, only 0 is a valid number in this version.
// adr: 0 - 111, address value send to.
// data: 0 - 255, value send
// Return value:
// 0: Success
// -1: Address out of range
// -3: SX-bus out of range
//------------------------------------------------------------------------------
{
if (adr < SX_ADDRESS_NUMBER && bus == 0)
{
// store in pattern D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1 (D0 = LSB)
uint8_t idx = calcIndex(adr);
sxbusSX0[idx] = 0x0924;
sxbusSX0[idx] |= data & 0x03;
sxbusSX0[idx] |= (data & 0x0C) << 1;
sxbusSX0[idx] |= (data & 0x30) << 2;
sxbusSX0[idx] |= (data & 0xC0) << 3;
return 0; // success
}
return -1; // address out of range
}
//------------------------------------------------------------------------------
int SXcentrale::setbit(uint8_t bus, uint16_t dccAdr, uint8_t data)
// Write one bit to the array, writing to the SX-bus is done by the isr.
// In:
// bus: 0 - 3, bus to send value to, only 0 is a valid number in this version.
// dccAdr: 0 - 895, DCC bit-address value send to (adres * 8 + bitnummer).
// data: 0 - 1, reset or set
// Return value:
// 0: Success
// -1: Address out of range
// -3: SX-bus out of range
//------------------------------------------------------------------------------
{
if (dccAdr < 8*SX_ADDRESS_NUMBER && bus == 0)
{
// store in pattern D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1 (D0 = LSB)
uint16_t adres = dccAdr / 8;
uint16_t bit = dccAdr % 8;
uint8_t idx = calcIndex(adres);
if (data)
{
// Set bit
data = (0x01 << bit);
sxbusSX0[idx] |= data & 0x03;
sxbusSX0[idx] |= (data & 0x0C) << 1;
sxbusSX0[idx] |= (data & 0x30) << 2;
sxbusSX0[idx] |= (data & 0xC0) << 3;
Serial.print(" a:");Serial.print(adres);Serial.print(" b:");Serial.print(data);
}
else
{
// Reset bit
uint16_t mask = 0;
data = (0x01 << bit);
mask |= data & 0x03;
mask |= (data & 0x0C) << 1;
mask |= (data & 0x30) << 2;
mask |= (data & 0xC0) << 3;
sxbusSX0[idx] &= ~mask;
Serial.print(" a:");Serial.print(adres);Serial.print(" m:");Serial.print(mask);
}
return 0; // success
}
return -1; // address out of range
}
//------------------------------------------------------------------------------
uint8_t SXcentrale::getPWR()
// Read POWER status from the SX-bus
// Return value:
// 0: Power off
// 1: Power on
//------------------------------------------------------------------------------
{
return (sxbusSX0[0] & SX_BIT_PWR);
}
//------------------------------------------------------------------------------
int SXcentrale::setPWR(uint8_t val)
// Write POWER status to the SX-bus and control a connected central.
// Return value:
// 0: Success
// -2: Illegal power value
//------------------------------------------------------------------------------
{
for (uint8_t sx_frame = 0; sx_frame < SX_TELCOUNT; sx_frame++)
{
int idx = sx_frame*SX_DATACOUNT;
if (val == 1)
sxbusSX0[idx] |= SX_BIT_PWR;
else
sxbusSX0[idx] &= (~SX_BIT_PWR);
}
}
und dann noch SXcentrale.h
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
/*
* SXcentrale.cpp
*
* Version: 0.2
* Copyright: Gerard van der Sel / Ronald Helder
*
* Changed on: 27-01-2025
* Version: 0.2
* Changes: Complete rewritten for efficiency, but only for Sx0
*
*
* interface hardware needed !
Hardware:
Connect T0 (Timing Signal) to D3
Connect T1 (Write Data) to D4
Connect D (Read Data) to D5
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SXcentrale_H_
#define SXcentrale_H_
#include <Arduino.h>
// Define arduino pins and ports
// The io pins for the busses
#if (1)
#define SX_T0 3 // Clock (for all)
#define SX_T0_PORT PORTD
#define SX_T0_PORTPIN PORTD3
#define SX0_T1 4 // Data write
#define SX0_T1_PORT PORTD
#define SX0_T1_PORTPIN PORTD4
#define SX0_D 5 // Data read
#define SX0_D_INPORT PIND
#define SX0_D_INPORTPIN PIND5
#else
#define SX_T0 8 // Clock (for all)
#define SX_T0_PORT PORTB
#define SX_T0_PORTPIN PORTB0
#define SX0_T1 9 // Data write
#define SX0_T1_PORT PORTB
#define SX0_T1_PORTPIN PORTB1
#define SX0_D 10 // Data read
#define SX0_D_INPORT PINC
#define SX0_D_INPORTPIN PINB2
#endif
// defines for Selectrix constants
#define SX_DATACOUNT 8 // 7 dataframes in 1 SYNC Channel
#define SX_TELCOUNT 16 // 16 SYNC Channels to transmit all data
#define SX_BIT_PWR 0x0010
#define SX_ADDRESS_NUMBER 112 // number SX channels
#define Timer1_10 -160 // 10 usec delay
#define Timer1_40 -640 // 40 usec delay
//#define Timer1_10 -160 // 20 usec delay
//#define Timer1_40 -960 // 60 usec delay
//#define Timer1_10 60000 // 10 usec delay (debug, also set CS12)
//#define Timer1_40 60000 // 40 usec delay (debug, also set CS12)
class SXcentrale
{
public:
SXcentrale();
void init(void);
int get(uint8_t, uint8_t);
int set(uint8_t, uint8_t, uint8_t);
int setbit(uint8_t, uint16_t, uint8_t);
uint8_t getPWR(void);
int setPWR(uint8_t);
void isr(void);
private:
void writeT0(void);
void writeT0T1(void);
void readD(void);
void initVar(void);
uint8_t calcIndex(uint8_t adr);
uint16_t sxbusSX0[SX_TELCOUNT * SX_DATACOUNT]; // to store the SX-bus data in signal format (see .cpp file), with D0 LSB in _sxbus (same as normal var)
uint16_t sx_sendmask; // specifies bit to be sent
};
#endif /* SXcentrale_H_ */