/* * 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 <inttypes.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 _baseAdr; // base address uint8_t _dataFrameCount; // frame counting uint8_t _address; // current address on the bus 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; // data from the SX-bus (1 adsress) uint8_t _sxbus[MAX_ADDRESS_NUMBER]; // to store the SX data /* SX Timing 1 Bit 50 �s 1 Addres 600 �s (= 12 Bit) 1 Telegram ca. 4,8 ms 1 All 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 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 = 111 - _baseAdr; if ((_address == _sx_write_address) && (_sx_write_busy == 1)) { _sx_writing = 1; } else { _sx_writing = 0; } break; case 0: // A3 bitWrite(_baseAdr, 3, _bit); _bitCount++; break; case 1: // A2 bitWrite(_baseAdr, 2, _bit); _bitCount++; break; case 3: // A1 bitWrite(_baseAdr, 1, _bit); _bitCount++; break; case 4: // A0 bitWrite(_baseAdr, 0, _bit); _bitCount++; 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) { case 2: // "Trenn_bits" case 5: case 8: _bitCount++; break; // ignore case 11: // Last "Trenn_bit" // save read _data _sxbus[_address] = _data; _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; } // calc sx address from baseAdr and dataFrameCount // _address = (6-_dataFrameCount) * 16 + (15 - _baseAdr) _address = ((6 - _dataFrameCount) << 4) + (15 - _baseAdr); // check if we want to write if ((_address == _sx_write_address) && (_sx_write_busy == 1)) { _sx_writing = 1; } else { _sx_writing = 0; } break; // 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; } //end switch/case _bitCount}// write the 8 databits to the 12 bit frame// When finished writing report it.void SXArduino::writeData() { switch(_bitCount) { case 11: // Last "Trenn_bit" _sx_writing = 0; // Stop writing`` _sx_write_busy = 0; // Report end case 2: case 5: case 8: // "Trenn_bits" 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 base address (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 } // 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 } //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.uint8_t SXArduino::set(uint8_t ad, uint8_t d) { if (_sx_write_busy == 0) { if (ad < MAX_ADDRESS_NUMBER) { _sx_write_address = ad; _sx_write_data = d; _sx_write_busy = 1; return 0; } return 2; // address out of range } return 1; // don't accept new data}// Check if writing is finished// (A write lasts between 600usec and 80 msec)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; }}
#include "SXArduino.h"// SX-bus interfaceSXArduino SXbus; // Get access to the SX-busvoid 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(9600); // open the serial port // SX-bus communication SXbus.init(); // CHANGE on INT1 triggers the interrupt routine sxisr (see above) attachInterrupt(1, sxisr, CHANGE); }void loop() { // put your main code here, to run repeatedly: Serial.println(SXbus._state); Serial.println(SXbus.get(111));}
De directorie structuur is:sketchSXArduino.ino [file]libraries [map]libraries\SXarduino [map]libraries\SXarduino\Sxarduino.h [file]libraries\SXarduino\Sxarduino.cpp [file]