/* * SXArduino.h * * Created on: 10.07.2015 * Version: 0.1 * Copyright: Gerard van der Sel * * Changed on: * Version: * * interface hardware needed ! see Read SX Signal - SX Clock must be connected to Pin2=INT0 and SX Data must be connected to Pin4. For triggering a scope, a signal can be generated at Pin3 at a defined base address. Pin6 can be connected via a 150 ohm resistor to the write line of the SX bus 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 SXArduino_H_#define SXArduino_H_#include <Arduino.h>// define arduino pins, ports and bits#define SX_T0 3 // must be INT1 !!#define SX_T0_DDR DDRD#define SX_T0_PORT PORTD#define SX_T0_PORTPIN PORTD3#define SX_T0_PINREG PIND#define SX_T1 5#define SX_T1_DDR DDRD#define SX_T1_PORT PORTD#define SX_T1_PORTPIN PORTD5#define SX_T1_PINREG PIND#define SX_D 6#define SX_D_DDR DDRD#define SX_D_PORT PORTD#define SX_D_PORTPIN PORTD6#define SX_D_PINREG PIND// defines for state machine#define SYNC 0#define PWR 1#define ADDR 2#define DATA 3#define MAX_DATACOUNT 7 // 7 dataframes in 1 SYNC Channel#define MAX_DATABITCOUNT 12 // 12 bits in 1 frame#define MAX_ADDRESS_NUMBER 112 // SX channelsclass SXArduino {public: SXArduino(); void init(void); uint8_t get(uint8_t); uint8_t set(uint8_t, uint8_t); uint8_t writing(); uint8_t getPWRBit(); void setPWRBit(uint8_t); void isr(void);private: void readPower(void); void writePower(void); void readAdr(void); void readData(void); void writeData(void); uint8_t _numFrame; // number frame uint8_t _dataFrameCount; // frame counting uint8_t _address; // current address on the bus volatile uint8_t _state; uint8_t _bitCount; // bit counting uint8_t _PWRBit; // Current state of POWER on track uint8_t _newPWRBit; // Command POWER on track uint8_t _sx_write_address; // stores address to write to uint8_t _sx_write_data; // data to write uint8_t _sx_writing; // active during the actual writing volatile uint8_t _sx_write_busy; // wait to send data, cannot accept new data uint8_t _clk; uint8_t _bit; uint8_t _data; // 1 data uint8_t uint8_t _sxbus[MAX_ADDRESS_NUMBER]; // to store the SX data /* SX Timing 1 Bit 50 �s 1 Kanal 600 �s (= 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 */};#endif /* SXArduino_H_ */
/* * SXAduino.cpp * * Created on: 16.07.2015 * Version: 0.1 * Copyright: Gerard van der Sel * * Changed on: * Version: * * interface hardware needed ! Interface SX-bus - SX T0 (Clock) must be connected to Pin 3 (IOL, INT1); - SX T1 must be connected to Pin 5 (IOL, T1); - SX D must be connected to Pin 6 (IOL, AIN0). 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 "SXArduino.h"SXArduino::SXArduino() { pinMode(SX_T0, INPUT); // SX-T0 is an input, no pull up to simulate tri-state pinMode(SX_T1, INPUT); // SX-T1 is also an input pinMode(SX_D, INPUT); // SX-D is also an input when not writing to allow other devices to write}void SXArduino::init() { // initialize function // initialize pins and variables pinMode(SX_T0, INPUT); // SX-T0 is an input, no pull up to simulate tri-state pinMode(SX_T1, INPUT); // SX-T1 is also an input pinMode(SX_D, INPUT); // SX-D is also an input when not writing to allow other devices to write for (int i = 0; i < MAX_ADDRESS_NUMBER; i++) { // reset sx variable to zero _sxbus[i] = 0; } // start always with search for SYNC _state = SYNC; _dataFrameCount = 0; _bitCount = 0; _sx_writing = 0; _sx_write_busy = 0; _newPWRBit = 2; _PWRBit = 0; // At start no power}// Read the bit that indicates if there is power on the track and store it.// After reading the bit start processing the address.void SXArduino::readPower() { if(_bitCount == 0) { _PWRBit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0; _bitCount++; } else { _bitCount = 0; _state = ADDR; } // end if _bitCount}// Write the bit that controls the power on the track if the user want to change it.// After writing the bit the pin is changed from output to input void SXArduino::writePower() { if(_bitCount == 0) { if (_newPWRBit != 2) { bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, _newPWRBit); // and write the newPWRBit } else { _newPWRBit = 2; bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input } // end if _newPWRBit } // end if _bitCount}// Read the address bits.// If base-address is read calculate the real address and// check if we must write // Proceed to the next stage DATAvoid SXArduino::readAdr() { _bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0; switch(_bitCount) { case 0: // A3 bitWrite(_numFrame, 3, _bit); _bitCount++; break; case 1: // A2 bitWrite(_numFrame, 2, _bit); _bitCount++; break; case 3: // A1 bitWrite(_numFrame, 1, _bit); _bitCount++; break; case 4: // A0 bitWrite(_numFrame, 0, _bit); _bitCount++; break; case 2: // "Trenbit" _bitCount++; break; case 5: // last "Trenbit" // advance to next state // we are processing the 7 data bytes (i.e. 7 SX addresses) _state = DATA; _bitCount = 0; // _dataFrameCount is 0. _address = (MAX_ADDRESS_NUMBER - 1) - _numFrame; if ((_address == _sx_write_address) && (_sx_write_busy == 1)) { _sx_writing = 1; } else { _sx_writing = 0; } break; } //end switch/case _bitCount}// read 12 bits and convert it to a databyte.// Read 7 databytes to read all data// After reading 7 data bytes start searching for SYNCvoid SXArduino::readData() { _bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0; // continue read _data // a total of 7 DATA blocks will be received // for a certain base-address switch(_bitCount) { // Read the data bits case 0: // D0 bitWrite(_data, 0, _bit); _bitCount++; break; case 1: // D1 bitWrite(_data, 1, _bit); _bitCount++; break; case 3: // D2 bitWrite(_data, 2, _bit); _bitCount++; break; case 4: // D3 bitWrite(_data, 3, _bit); _bitCount++; break; case 6: // D4 bitWrite(_data, 4, _bit); _bitCount++; break; case 7: // D5 bitWrite(_data, 5, _bit); _bitCount++; break; case 9: // D6 bitWrite(_data, 6, _bit); _bitCount++; break; case 10: // D7 bitWrite(_data, 7, _bit); _bitCount++; break; case 2: // "Trenn_bits" case 5: case 8: _bitCount++; break; // ignore case 11: // Last "Trenn_bit" // save read _data _sxbus[_address] = _data; // setup for next read _bitCount = 0; _data = 0; // increment dataFrameCount to move on the next DATA byte // check, if we already reached the last DATA block - in this // case move on to the next SX-Datenpaket, i.e. look for SYNC _dataFrameCount++; if (_dataFrameCount == MAX_DATACOUNT) { // and move on to SYNC _state _dataFrameCount = 0; _state = SYNC; } else { // calc sx address from numFrame and dataFrameCount // _address = (6-_dataFrameCount) * 16 + (15 - _numFrame) _address = ((6 - _dataFrameCount) << 4) + (15 - _numFrame); // check if we want to write if ((_address == _sx_write_address) && (_sx_write_busy == 1)) { _sx_writing = 1; } else { _sx_writing = 0; } } break; } //end switch/case _bitCount}// write the 8 databits to the 12 bit frame// When finished writing report it.void SXArduino::writeData() { switch(_bitCount) { default: // Last "Trenn_bit" _sx_writing = 0; // Stop writing`` _sx_write_busy = 0; // Report end case 2: // "Trenn_bits" case 5: case 8: bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to input break; // Write the data bits case 0: // D0 bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 0)); break; case 1: // D1 bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 1)); break; case 3: // D2 bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 2)); break; case 4: // D3 bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 3)); break; case 6: // D4 bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 4)); break; case 7: // D5 bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 5)); break; case 9: // D6 bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 6)); break; case 10: // D7 bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 7)); break; } //end switch/case _bitCount}// interrupt service routine (AVR INT1)// driven by LEVEL CHANGES of the clock signal T0 (SX pin 1)// LOW: writing// HIGH: reading and controlvoid SXArduino::isr() { // 4 different states are distinguished // 1. SNYC = looking for a SYNC signal // 2. PWR = look for PWR bit // 3. ADDR = look for number frame (0..15) // 4. DATA = decode the data-bytes _clk = (SX_T0_PINREG & _BV(SX_T0_PORTPIN)) > 0; switch(_state) { case SYNC: // Search for 0 0 0 1 if (_clk != LOW) { _bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0; // read pin if (_bit == LOW) { _bitCount++; } else { if (_bitCount == 3) { // sync bits 0 0 0 1 found _state = PWR; // advance to next state } // endif _bitCount _bitCount = 0; // reset _bitCounter and start over } // endif _bit==LOW } // endif _clk!=LOW break; case PWR: if (_clk == LOW) { writePower(); } else { readPower(); } // endif _clk==LOW break; case ADDR: if (_clk != LOW) { readAdr(); } // endif _clk!=LOW break; case DATA: if (_clk == LOW) { if (_sx_writing == 1) { writeData(); } } else { readData(); } // endif _clk==LOW break; default: _state = SYNC; // Error restart _dataFrameCount = 0; _bitCount = 0; _sx_writing = 0; _sx_write_busy = 0; _newPWRBit = 2; _PWRBit = 0; break; } //end switch/case _state}// functions 'accessing' the SX-bus// Read data from the array, filled by the isr.uint8_t SXArduino::get(uint8_t ad) { // returns the value of a SX address if (ad < MAX_ADDRESS_NUMBER) { return _sxbus[ad]; } else { return 0; }}// Start writing data to the SX-bus.// Check if writing or invalid address.// (A write lasts between 600 us and 80 ms)uint8_t SXArduino::set(uint8_t adr, uint8_t dt) { if (_sx_write_busy == 0) { if (adr < MAX_ADDRESS_NUMBER) { _sx_write_address = adr; _sx_write_data = dt; _sx_write_busy = 1; return 0; // success } return 2; // address out of range } return 1; // writing busy}// Check if writing is finished// (A write lasts between 600 us and 80 ms)uint8_t SXArduino::writing() { return _sx_write_busy;}// Read POWER status from the SX-busuint8_t SXArduino::getPWRBit() { return _PWRBit;}// Write POWER status to the SX-bus and control a connected central.void SXArduino::setPWRBit(uint8_t val) { if (val == 0 || val == 1) { _newPWRBit = val; }}
/* * SXArduino.h * * Version: 3.0 * Copyright: Gerard van der Sel * * Changed on: 19-12.2015 * Version: 3.0 * Changes: Added some comment. Given its version number. * * Changed on: 30.11.2015 * Version: 0.5 * Changes: Reading and writing to multiple addresses in one cycle, resolved timing issues. * * Changed on: 14.11.2015 * Version: 0.4 * Changes: Reading and writing to multiple addresses in one cycle. * * Changed on: 27.10.2015 * Version: 0.3 * Changes: onWait() added to synchronise with the SXbus. * * Changed on: 27.09.2015 * Version: 0.2 * Changes: Minor changes * * Changed on: 10.07.2015 * Version: 0.1 * Changes: Initial version * * interface hardware needed ! see Read SX Signal - SX Clock must be connected to Pin3 = INT1 and SX Data must be connected to Pin 5. Both are connected through a resistor off 22 kilo ohm. Pin 6 can be connected via a 100 ohm resistor to the write line of the SX bus 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 SXArduino_H_#define SXArduino_H_#include <Arduino.h>// define arduino pins, ports and bits// depends on the hardware used.#define SX_T0 3 // Clock#define SX_T0_DDR DDRD#define SX_T0_PORT PORTD#define SX_T0_PORTPIN PORTD3#define SX_T0_PINREG PIND#define SX_T1 5 // Data read#define SX_T1_DDR DDRD#define SX_T1_PORT PORTD#define SX_T1_PORTPIN PORTD5#define SX_T1_PINREG PIND#define SX_D 6 // Data write#define SX_D_DDR DDRD#define SX_D_PORT PORTD#define SX_D_PORTPIN PORTD6#define SX_D_PINREG PIND// defines for state machine#define DATA 0 // For performance DATA first#define SYNC 1 // (Gives fastest code)#define PWR 2#define ADDR 3// defines for Selectrix constants#define SX_STOP 3 // 3 "0" bits achter elkaar#define SX_DATACOUNT 7 // 7 dataframes in 1 SYNC Channel#define SX_SEPLEN 3 // 3 bit in a separated part#define SX_BYTELEN 12 // 12 bits for one byte#define SX_ADDRESS_NUMBER 112 // SX channels#define NO_WRITE 256 // No data to writeclass SXArduino {public: SXArduino(); void init(void); int get(uint8_t); uint8_t set(uint8_t, uint8_t); uint8_t isSet(uint8_t); uint8_t getPWR(void); void setPWR(uint8_t); void isr(void); uint8_t inSync(void); private: void initVar(); uint8_t calcIndex(uint8_t adr); uint8_t _sx_numFrame; // number frame uint8_t _sx_dataFrameCount; // frame counting uint8_t _sx_state; uint8_t _sx_sepCount; // bit counting (seperator) uint8_t _sx_byteCount; // bit counting (byte) uint8_t _sx_PWR; // current state of POWER on track uint8_t _sx_newPWR; // command POWER on track uint8_t _sx_read_data; // read data uint8_t _sx_write_data; // data to write uint8_t _sx_index; // current index in the array uint8_t _sx_writing; // active during the actual writing uint8_t _sx_bit; // value data bit (T1) uint8_t _sx_sync; // set if Frame 0 is processed uint8_t _sxbusrcev[SX_ADDRESS_NUMBER]; // to store the received SX data uint16_t _sxbussnd[SX_ADDRESS_NUMBER]; // to store the SX data to send /* 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 */};#endif /* SXArduino_H_ */
/* * SXAduino.cpp * * Version: 3.0 * Copyright: Gerard van der Sel * * Changed on: 19-12.2015 * Version: 3.0 * Changes: Added some comment. Given its version number. * * Changed on: 30.11.2015 * Version: 0.5 * Changes: Reading and writing to multiple addresses in one cycle, resolved timing issues. * * Changed on: 14.11.2015 * Version: 0.4 * Changes: Reading and writing to multiple addresses in one cycle. * * Changed on: 27.10.2015 * Version: 0.3 * Changes: onWait() added to synchronise with the SXbus. * * Changed on: 27.09.2015 * Version: 0.2 * Changes: Minor changes * * Changed on: 10.07.2015 * Version: 0.1 * Changes: Initial version * * interface hardware needed ! Interface SX-bus - SX T0 (Clock) must be connected to Pin 3 (IOL, INT1); - SX T1 must be connected to Pin 5 (IOL, T1); - SX D must be connected to Pin 6 (IOL, AIN0). SX-bus interface (NEM 682)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 -- ------------------- ------------------- ------------------- --------- ^ ^ ^ ^ P P P POpbouw 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, 0This 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 "SXArduino.h"SXArduino::SXArduino() { pinMode(SX_T0, INPUT); // SX-T0 is an input, no pull up to simulate tri-state pinMode(SX_T1, INPUT); // SX-T1 is also an input pinMode(SX_D, INPUT); // SX-D is also an input when not writing to allow other devices to write}void SXArduino::init() { // initialize function // initialize pins and variables pinMode(SX_T0, INPUT); // SX-T0 is an input, no pull up to simulate tri-state pinMode(SX_T1, INPUT); // SX-T1 is also an input pinMode(SX_D, INPUT); // SX-D is also an input when not writing to allow other devices to write for (int i = 0; i < SX_ADDRESS_NUMBER; i++) { _sxbusrcev[i] = 0; // reset sx received data to zero _sxbussnd[i] = NO_WRITE; // set sx data to send to NO_WRITE } initVar(); // Start looking for SYNC}void SXArduino:: initVar() { // start always with search for header _sx_state = SYNC; // First look for SYNC pattern _sx_dataFrameCount = SX_DATACOUNT; // Read all dataframes _sx_sepCount = SX_SEPLEN; // Distanse between two separators _sx_byteCount = SX_STOP; // Check for SX_STOP bits of "0" _sx_numFrame = 0; // Set frame 0 _sx_index = 0; // Set index 0 // no writing to the SX bus _sx_writing = 0; // Set no write // Powerbit send and receive _sx_newPWR = 2; // Don't write power bit _sx_PWR = 0; // At start no power // reset sync bit _sx_sync = 0; // Clear sync-flag}// interrupt service routine (AVR INT1)// driven by RISING EDGES of the SX clock signal T0 (SX pin 1)void SXArduino::isr() { _sx_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0; // read pin switch (_sx_state) { // Find sync pattern "0001" to start reading and writing case SYNC: if (_sx_bit == LOW) { // Sync bits "0" if (_sx_byteCount > 0) { // If more then 3 _sx_byteCount--; } } else { if (_sx_byteCount == 0) { // High, read 3 bits? _sx_state = PWR; // Setup for POWER bit _sx_sepCount = SX_SEPLEN - 1; // Set _sx_sepCount and continue } _sx_byteCount = SX_STOP; // Error, setup for restart } break; // Read (and write) the power bit. case PWR: _sx_sepCount--; if (_sx_sepCount == 0) { // Skip the separator bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input _sx_state = ADDR; // Setup for next state ADDR _sx_byteCount = SX_BYTELEN / 2; _sx_sepCount = SX_SEPLEN; _sx_numFrame = 0; } else { if (_sx_newPWR < 2) { // Set power from me bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, _sx_newPWR); // and write newPWR } // end if _sx_newPWR _sx_newPWR = 2; // Power set _sx_PWR = _sx_bit; // Get power status from central } break; // Read the address bits. case ADDR: _sx_sepCount--; if (_sx_sepCount == 0) { // Skip the separator _sx_sepCount = SX_SEPLEN; } else { _sx_numFrame = (_sx_numFrame * 2) + _sx_bit; // Read bit into framenumber } _sx_byteCount--; if (_sx_byteCount == 0) { // Addres part is processed // Advance to the next state _sx_state = DATA; // Setup for DATA read _sx_byteCount = SX_BYTELEN; _sx_index = _sx_numFrame * 7; // Calculate index // Check if we want to write and prepare it if (_sxbussnd[_sx_index] < NO_WRITE) { _sx_write_data = _sxbussnd[_sx_index]; // Get data to write _sx_writing = 1; // Write _sxbussnd[_sx_index] |= NO_WRITE; // Report bye written to SX-bus } else { _sx_writing = 0; // No write } if (_sx_numFrame == 0) { _sx_sync = 1; // Signal frame 0 for sync purposes } } break; // Read (and write) the data bits case DATA: _sx_sepCount--; if (_sx_sepCount == 0) { // Skip the separator bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input _sx_sepCount = SX_SEPLEN; } else { if (_sx_writing == 1) { // If we want to write bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 0)); _sx_write_data = _sx_write_data / 2; // Prepare for next write } _sx_read_data = (_sx_read_data / 2); // Prepare for reading data bitWrite(_sx_read_data, 7, _sx_bit); // Insert the bit } _sx_byteCount--; if (_sx_byteCount == 0) { // All bits done // save read _data _sxbusrcev[_sx_index] = _sx_read_data; // Save read data in array // Setup for next read/write _sx_byteCount = SX_BYTELEN; _sx_index++; // Decrement dataFrameCount // check, if we already reached the last DATA block - in this // case move on to the next SX-Datenpaket, i.e. look for SYNC _sx_dataFrameCount--; if (_sx_dataFrameCount == 0) { // Move on to find SYNC pattern _sx_dataFrameCount = SX_DATACOUNT; _sx_state = SYNC; _sx_byteCount = SX_STOP; _sx_writing = 0; } else { // Check if we want to write if (_sxbussnd[_sx_index] < NO_WRITE) { _sx_write_data = _sxbussnd[_sx_index]; // Get data to write _sx_writing = 1; // Write _sxbussnd[_sx_index] |= NO_WRITE; // Report bye written to SX-bus } else { _sx_writing = 0; // No write } } } break; default: bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input initVar(); // Start looking for SYNC break; } //end switch/case _sx_state}// Convert from SX-bus addresses to index in array.uint8_t SXArduino::calcIndex(uint8_t SXadr) { uint8_t frame = 15 - (SXadr & 15); // Get the frame number uint8_t offset = 6 - (SXadr >> 4); // Get the offset in the frame return frame * 7 + offset; // Calculate the index in the array}// functions 'accessing' the SX-bus// Read data from the array, filled by the isr.int SXArduino::get(uint8_t adr) { // returns the value of a SX address if (adr < SX_ADDRESS_NUMBER) { return _sxbusrcev[calcIndex(adr)]; } else { return -1; // Save value }}// Write data to the array, writing to the SX-bus is done by the isr.// Check if invalid address.uint8_t SXArduino::set(uint8_t adr, uint8_t dt) { if (adr < SX_ADDRESS_NUMBER) { _sxbussnd[calcIndex(adr)] = dt; return 0; // success } return 1; // address out of range}// Checks if the isr has written the data to the SX-busuint8_t SXArduino::isSet(uint8_t adr) { if (adr < SX_ADDRESS_NUMBER) { if (_sxbussnd[calcIndex(adr)] < NO_WRITE) { return 2; // not written } else { return 0; // written } } return 1; // address out of range}// Read POWER status from the SX-busuint8_t SXArduino::getPWR() { return _sx_PWR;}// Write POWER status to the SX-bus and control a connected central.void SXArduino::setPWR(uint8_t val) { if (val == 0 || val == 1) { _sx_newPWR = val; }}// Every time frame 0 is passed sync bit is set by isr.uint8_t SXArduino::inSync() { if (_sx_sync == 1) { _sx_sync = 0; // reset sync bit to check for next pass return 1; // report frame 0 found } return 0;}
/* * Test sketch for SX-bus interface for the ARduino * All addresses are written with a value. * In the background an ISR is running to send those values to the SX-bus. * While sending the bus is read and put in a buffer * * Watch out: Adresses 104 to 111 are used. To avoid this set noCC2000 to false */#include "SXArduino.h"#include "Arduino.h"// SX-bus interfaceSXArduino SXbus; // Get access to the SX-busuint8_t valrcv;uint8_t valsnd;int waitSX;int waitLussen;int waitloop;int burst; // pauzeint adr;bool noCC2000;void sxisr(void) { // if you want to understand this, see: // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239522239 SXbus.isr();} void setup() { // put your setup code here, to run once: // Serial communication Serial.begin(230400); // open the serial port // SX-bus communication SXbus.init(); // CHANGE on INT1 triggers the interrupt routine sxisr (see above) attachInterrupt(1, sxisr, CHANGE); // Init prog waitSX = 0; waitLussen = 0; valsnd = 0; waitloop = 0; noCC2000 = true; // false 0 ... 103, true 0 ... 111 burst = 5; // 5 slagen pauze (= 5 * 77 = 385 msec)}uint8_t getSXbusval(int adr) { return SXbus.get(adr);}uint8_t getSXbuspower() { return SXbus.getPWR();}void setSXbusval(uint8_t adr, uint8_t val) { SXbus.set(adr, val);}void setSXbuspower(uint8_t onoff) { SXbus.setPWR(onoff);}void loop() { // put your main code here, to run repeatedly: if (SXbus.inSync() == 1) { // Iedere 76,8 msec true // fill bytes conform SX messages for (int j = 0; j < 16; j++) { // 16 frames Serial.print("Data: "); for (int i = 0; i < 7; i++) { // 7 databytes per frame adr = ((6 - i) << 4) + (15 - j); if ((adr < 104) || (noCC2000)) { // Exclude the addresses used by CC2000 if (waitLussen == 0) { Serial.print(valsnd); Serial.print("="); setSXbusval(adr, valsnd); valsnd++; } valrcv = getSXbusval(adr); Serial.print(valrcv); if (i < 6) { Serial.print(", "); } } } Serial.println(); } if (burst < waitLussen) { waitLussen = 0; } else { waitLussen++; } Serial.print("Power: "); if (getSXbuspower() == 1) { Serial.println("On"); } else { Serial.println("Off"); } waitSX++; if (waitSX > 5) { // 5 x 80 ms = 400 ms wachttijd waitSX = 0; Serial.print("Switch power "); if (getSXbuspower() == 1) { setSXbuspower(0); Serial.println("off"); } else { setSXbuspower(1); Serial.println("on"); } } waitloop = 0; } else { if (waitloop == 0) { Serial.println("Waiting.... "); // 15 tekens (incl CR+LF) } waitloop++; // max 63 tekens totaal => 32 msec bij 19200 baud }}
/* SX interface (66824 or 66842) Creator: Gerard van der Sel Version: 1.1 Date: 27-12-2015 This software emulates a SX interface on the Arduino. Extra hardware needed is de SX-Arduino board which contains the hardware to communicate with the SX-bus. Protocol used by the SX-Interface (66824 or 66842) 2 byte message: First byte contains command and address: Command is located in bit 7 of first byte: 0: Read address 1: Write address Address: 0 to 111 (valid adresses on the SX-bus) 127 controls track power Second byte contains data in case of a write command in case of a valid address: 0 to 255 in case of address 127: 0 trackpower off 128 trackpower on in case of a read: byte is discarded Note: For this sketch to run, don't solder switch and LED on de SXArduino board*/#include "Arduino.h"#include "SXArduino.h"SXArduino SXbus; // Interface to the SX-busboolean cmdAdr; // Received byte is a commandboolean cmdWrite; // Write commanduint8_t address; // Address for reading or writinguint8_t rcvdData;void sxisr(void) { // if you want to understand this, see: // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239522239 SXbus.isr();} void setup() { // put your setup code here, to run once: // initialize serial: Serial.begin(19200); // initialize SX-bus SXbus.init(); // Changes on INT1 triggers the interrupt routine sxisr (see above) attachInterrupt(1, sxisr, CHANGE); // initialize application cmdAdr = true; cmdWrite = false;}void serialEvent() { // Read all the data while (Serial.available()) { rcvdData = (uint8_t)Serial.read(); // First byte is a command, decode it if (cmdAdr) { // If byte value > 127 a write command, data in second byte if (rcvdData > 127) { cmdWrite = true; address = rcvdData - 128; // address is received data - 128 } else { // Read command, perform it if (rcvdData < 112) { // Get address data Serial.print((char)SXbus.get(rcvdData)); } else { // Illegal address, power? if (rcvdData == 127) { Serial.print((char)(SXbus.getPWR() * 128)); } } } cmdAdr = false; } else { // Second byte data if (cmdWrite) { if (address < 112) { SXbus.set(address, rcvdData); } else { if (address == 127) { if ((rcvdData & 128) == 0) { SXbus.setPWR(0); } else { SXbus.setPWR(1); } } } cmdWrite = false; } cmdAdr = true; } }}void loop() { // put your main code here, to run repeatedly: // Nothing to do.}