Vincent Molenaar 2 years ago
parent
commit
3726e5d8bb
5 changed files with 512 additions and 0 deletions
  1. BIN
      74HC595-Pinouts.png
  2. BIN
      dcc sein 74hc595 V2.fzz
  3. BIN
      dcc sein 74hc595.fzz
  4. 512 0
      nano_seindecoder_inc_DCC_simple.ino
  5. BIN
      schematic1.png

BIN
74HC595-Pinouts.png


BIN
dcc sein 74hc595 V2.fzz


BIN
dcc sein 74hc595.fzz


+ 512 - 0
nano_seindecoder_inc_DCC_simple.ino

@@ -0,0 +1,512 @@
+///////////////////////////////////////////////////////
+//
+// DCC packet analyze: Ruud Boer, October 2015
+// DCC packet capture: Robin McKay, March 2014
+//
+// The DCC signal is detected on Arduino digital pin 2
+//
+// Set theSerial Monitor Baud Rate to 38400 !!
+//
+// Keyboard commands that can be sent viaSerial Monitor:
+// 1 = 1s refresh time
+// 2 = 2s
+// 3 = 4s (default)
+// 4 = 8s
+// 5 = 16s
+// 6 = 4 DCC packet buffer
+// 7 = 8
+// 8 = 16
+// 9 = 32 (default)
+// 0 = 64
+// a = show accessory packets toggle
+// l = show locomotive packets toggle
+//
+////////////////////////////////////////////////////////
+
+byte refreshTime = 4; // Time between DCC packets buffer refreshes in s
+byte packetBufferSize = 2; // DCC packets buffer size
+
+#define TIMER_PRESCALER 64
+#define DccBitTimerCount (F_CPU * 80L / TIMER_PRESCALER / 1000000L)
+// 16000000 * 80 / 64 / 1000000 = 20; 20 x 4usecs = 80us
+
+boolean packetEnd;
+boolean preambleFound;
+
+const byte bitBufSize = 50; // number of slots for bits
+volatile byte bitBuffer[bitBufSize];
+volatile byte bitBuffHead = 1;
+volatile byte bitBuffTail = 0;
+
+byte pktByteCount = 0;
+byte packetBytesCount;
+byte preambleOneCount;
+byte dccPacket[6]; // buffer to hold a packet
+byte instrByte1;
+byte decoderType; //0=Loc, 1=Acc
+byte bufferCounter = 0;
+byte isDifferentPacket = 0;
+byte showLoc = 1;
+byte showAcc = 1;
+
+
+unsigned int decoderAddress;
+unsigned int packetBuffer[64];
+unsigned int packetNew = 0;
+
+unsigned long timeToRefresh = millis() + refreshTime * 1000;
+
+//========================
+
+//custom vars
+#include<SPI.h>
+
+const int boards = 3 ;
+const int registers = boards*3;
+const int outputCount = registers*8;
+
+const int signalValsLength = outputCount; //2signalvals = 1 sein
+int signalVals[signalValsLength];
+
+byte data[registers]; //data array die naar de registers wordt gestuurd, index register , value = byte (00000000)
+int bitCounter = 0; //bits in byte 0 tot 7
+int byteCounter = 0; //byte gelijk aan register
+int val = 0; //tijdelijk var om de value voor de bit te bepalen
+
+bool testMode = true;
+int testOffset = 0;
+int testInterval = 1000;
+unsigned long updateTestAt = millis()+testInterval;
+//end custom vars
+
+//custom functions
+
+void setTestValues(bool val){
+  if(val == testMode)
+    return;
+  testMode = val;
+  Serial.print("setting testVal ");
+  Serial.println(val);
+  if(!val){
+    processData();
+    updateRegisters();
+  }else{
+    updateTestData();
+    updateRegisters();
+  }
+}
+
+void updateTestData(){
+  bitCounter = 0;
+  byteCounter = 0;
+  if(testOffset == 3)
+    testOffset = 0;
+  for (int i = 0; i < signalValsLength; i++){
+    if(bitCounter > 7){
+      byteCounter++;
+      bitCounter = 0;
+    }
+
+    //stap door 
+    if((i+testOffset) % 3 != 0)
+      bitSet(data[byteCounter],7-bitCounter);
+    else
+      bitClear(data[byteCounter],7-bitCounter);
+    bitCounter++;
+
+    //random*/
+    /*
+    if(random(0,2) == 1)
+      bitSet(data[byteCounter],7-bitCounter);
+    else
+      bitClear(data[byteCounter],7-bitCounter);
+    bitCounter++;
+    //*/   
+  }
+ 
+  testOffset++;
+}
+
+void processData(){
+  Serial.println("1");
+  bitCounter = 0;
+  byteCounter = 0;
+  for (int i = 0; i < signalValsLength; i++){
+    if(bitCounter > 7){
+      byteCounter++;
+      bitCounter = 0;
+    }
+  
+    if(signalVals[i] == 1)
+      bitSet(data[byteCounter],7-bitCounter);
+    else
+      bitClear(data[byteCounter],7-bitCounter);
+    bitCounter++;
+    
+  }
+}
+
+void printStatus(int value){
+ switch(value){
+    case 0:
+     Serial.print("groen");
+    break;
+    case 1:
+     Serial.print("rood");
+    break;
+    case 3:
+     Serial.print("oranje");
+    break;
+    default:
+     Serial.print("invalid signal");
+    break;
+    
+  }
+ Serial.print(" ");
+ Serial.println(value);
+}
+
+void setupSpi(){
+  SPI.begin();
+  pinMode(SS, OUTPUT);
+  digitalWrite(SS, HIGH);
+  SPI.setDataMode(3);
+  SPI.setClockDivider(4);  
+  SPI.setBitOrder(LSBFIRST);
+
+}
+
+void updateRegisters(){
+  //Serial.println("2");
+  digitalWrite(SS, LOW);
+  //digitalWrite(13, LOW);
+  for(int r = registers-1; r >= 0 ; r--){
+     SPI.transfer(data[r]); // high byte
+  }
+  digitalWrite(SS, HIGH);
+   digitalWrite(13, HIGH);
+}
+
+void resetData(){
+  return;
+    bitCounter = 0;
+    byteCounter = 0;
+    for(int r = registers-1; r >= 0 ; r--){
+     data[r] = 0; // reset Byte
+  }
+}
+
+void handleData(int addr , bool val){
+  if(addr == 799){
+    setTestValues(val);
+  }
+  
+  if(addr <= 899)
+    return;
+  addr = addr-900;
+  if(val)
+    signalVals[addr] = 0;
+  else
+    signalVals[addr] = 1;
+  
+  processData();
+  updateRegisters();
+}
+
+//end custom functions
+
+void getPacket() {
+  preambleFound = false;
+  packetEnd = false;
+  packetBytesCount = 0;
+  preambleOneCount = 0;
+  while (! packetEnd) {
+    if (preambleFound) getNextByte();
+    else checkForPreamble();
+  }
+}
+
+//========================
+
+void checkForPreamble() {
+  byte nextBit = getBit();
+  if (nextBit == 1) preambleOneCount++;
+  if (preambleOneCount < 10 && nextBit == 0) preambleOneCount = 0;
+  if (preambleOneCount >= 10 && nextBit == 0) preambleFound = true;
+}
+
+//========================
+
+void getNextByte() {
+  byte newByte = 0;
+  for (byte n = 0; n < 8; n++) newByte = (newByte << 1) + getBit();
+  packetBytesCount ++;
+  dccPacket[packetBytesCount] = newByte;
+  dccPacket[0] = packetBytesCount;
+  if (getBit() == 1) packetEnd = true;
+}
+
+//========================
+
+byte getBit() {
+  // gets the next bit from the bitBuffer
+  // if the buffer is empty it will wait indefinitely for bits to arrive
+  byte nbs = bitBuffHead;
+  while (nbs == bitBuffHead) byte nbs = nextBitSlot(bitBuffTail); //Buffer empty
+  bitBuffTail = nbs;
+  return (bitBuffer[bitBuffTail]);
+}
+
+//========================
+
+void beginBitDetection() {
+  TCCR0A &= B11111100;
+  attachInterrupt(0, startTimer, RISING);
+}
+
+//========================
+
+void startTimer() {
+  OCR0B = TCNT0 + DccBitTimerCount;
+  TIMSK0 |= B00000100;
+  TIFR0  |= B00000100;
+}
+
+//========================
+
+ISR(TIMER0_COMPB_vect) {
+  byte bitFound = ! ((PIND & B00000100) >> 2);
+  TIMSK0 &= B11111011;
+  byte nbs = nextBitSlot(bitBuffHead);
+  if (nbs == bitBuffTail) return;
+  else {
+    bitBuffHead = nbs;
+    bitBuffer[bitBuffHead] = bitFound;
+  }
+}
+
+//========================
+
+byte nextBitSlot(byte slot) {
+  slot ++;
+  if (slot >= bitBufSize) slot = 0;
+  return (slot);
+}
+
+//========================
+
+void printPacket() {
+ Serial.print(" ");
+  for (byte n = 1; n < pktByteCount; n++) {
+   Serial.print(" ");
+   Serial.print(dccPacket[n], BIN);
+  }
+  Serial.println(" ");
+}
+
+//========================
+
+void refreshBuffer() {
+  timeToRefresh = millis() + refreshTime * 500;
+  for (byte n = 0; n < packetBufferSize; n++) packetBuffer[n] = 0;
+  bufferCounter = 0;
+  Serial.println("-");
+  /*
+    Serial.print("Loc ");
+    Serial.print(showLoc);
+    Serial.print(" / Acc ");
+    Serial.print(showAcc);
+    Serial.print(" / Time ");
+    Serial.print(refreshTime);
+    Serial.print(" / Buff ");
+    Serial.println(packetBufferSize);
+    Serial.println(" ");
+  */
+
+}
+
+//========================
+
+void setup() {
+  Serial.begin(38400); // 38400 when on DCC, 9600 when testing on 123Circuits !!!!!!!!!!!!!!!!!!!!!!!
+  Serial.println("---");
+  Serial.println("DCC Packet Analyze started");
+  Serial.print("Updates every ");
+  Serial.print(refreshTime);
+  Serial.println(" seconds");
+  Serial.println("---");
+
+  setupSpi();
+
+  processData();
+  updateRegisters();
+  
+  beginBitDetection(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+}
+
+//====================
+
+void loop() {
+  updateRegisters();
+  getPacket(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+  byte speed;
+  byte checksum = 0;
+
+  if (millis() > timeToRefresh){ 
+    refreshBuffer();
+    //processData();
+    //updateRegisters();
+  }
+
+  if(millis() > updateTestAt && testMode )
+  {
+    Serial.println("running test");
+    updateTestAt = millis()+testInterval;
+    updateTestData();
+    updateRegisters();
+  }
+
+  pktByteCount = dccPacket[0];
+  if (!pktByteCount){
+    Serial.println("nodata");
+    return; // No new packet available
+  }
+
+  for (byte n = 1; n <= pktByteCount; n++) checksum ^= dccPacket[n];
+  //checksum=0; //Comment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+  if (checksum) {
+    Serial.println("invalid checkSum");
+    return; // Invalid Checksum
+  }
+
+  else { // There is a new packet with a correct checksum
+    isDifferentPacket = 1;
+    for (byte n = 0; n < packetBufferSize ; n++) { // Check if packet is not already in the buffer.
+      // The checksum byte is used for the test, not ideal, some new packets may not show (only 256 different checksums)
+      if (dccPacket[pktByteCount] == packetBuffer[n]) isDifferentPacket = 0;
+    }
+
+    if (isDifferentPacket) {  // packet does not yet exist in the packet buffer
+      packetBuffer[bufferCounter] = dccPacket[pktByteCount]; // add new packet to the buffer
+      bufferCounter = (++bufferCounter) & (packetBufferSize - 1);
+
+      if (dccPacket[1] == B11111111) { //Idle packet
+        Serial.println("Idle ");
+        return;
+      }
+
+      if (!bitRead(dccPacket[1], 7)) { //bit7=0 -> Loc Decoder Short Address
+        decoderAddress = dccPacket[1];
+        instrByte1 = dccPacket[2];
+        decoderType = 0;
+      }
+      else {
+        if (bitRead(dccPacket[1], 6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
+          decoderAddress = 256 * (dccPacket[1] & B00000111) + dccPacket[2];
+          instrByte1 = dccPacket[3];
+          decoderType = 0;
+        }
+        else { //bit7=1 AND bit6=0 -> Accessory Decoder
+          decoderAddress = dccPacket[1] & B00111111;
+          instrByte1 = dccPacket[2];
+          decoderType = 1;
+        }
+      }
+      if (decoderType) { // Accessory Basic
+        if (showAcc) {
+          if (instrByte1 & B10000000) { // Basic Accessory
+            decoderAddress = (((~instrByte1)&B01110000) << 2) + decoderAddress;
+            byte port = (instrByte1 & B00000110) >> 1;
+            int decAddr = (decoderAddress) * 4 + port + 1;
+            Serial.print("Acc ");
+            Serial.print(decAddr);
+            Serial.print(" ");
+            Serial.print(decoderAddress);
+            Serial.print(":");
+            Serial.print(port);
+            Serial.print(" ");
+            Serial.print(bitRead(instrByte1, 3));
+            if (bitRead(instrByte1, 0)){ 
+              Serial.print(" On");
+            }else
+            {
+              Serial.print(" Off");
+            }
+            //custom code
+            handleData(decAddr ,bitRead(instrByte1, 0));
+            //end custom code
+          }
+          else { // Accessory Extended NMRA spec is not clear about address and instruction format !!!
+            Serial.print("Acc Ext ");
+            decoderAddress = (decoderAddress << 5) + ((instrByte1 & B01110000) >> 2) + ((instrByte1 & B00000110) >> 1);
+            Serial.print(decoderAddress);
+            Serial.print(" Asp ");
+            Serial.print(dccPacket[3], BIN);
+          }
+          printPacket();
+        }
+      }
+      else { // Loc / Multi Function Decoder
+        
+      }
+    }
+  }
+  if (Serial.available()) {
+    Serial.println(" ");
+    switch (Serial.read()) {
+      case 49:
+        Serial.println("Refresh Time = 1s");
+        refreshTime = 1;
+        break;
+      case 50:
+        Serial.println("Refresh Time = 2s");
+        refreshTime = 2;
+        break;
+      case 51:
+        Serial.println("Refresh Time = 4s");
+        refreshTime = 4;
+        break;
+      case 52:
+        Serial.println("Refresh Time = 8s");
+        refreshTime = 8;
+        break;
+      case 53:
+        Serial.println("Refresh Time = 16s");
+        refreshTime = 16;
+        break;
+      case 54:
+        Serial.println("Buffer Size = 4");
+        packetBufferSize = 2;
+        break;
+      case 55:
+        Serial.println("Buffer Size = 8");
+        packetBufferSize = 8;
+        break;
+      case 56:
+        Serial.println("Buffer Size = 16");
+        packetBufferSize = 16;
+        break;
+      case 57:
+        Serial.println("Buffer Size = 32");
+        packetBufferSize = 32;
+        break;
+      case 48:
+        Serial.println("Buffer Size = 64");
+        packetBufferSize = 64;
+        break;
+      case 97:
+        if (showAcc) showAcc = 0; else showAcc = 1;
+        Serial.print("show acc packets = ");
+        Serial.println(showAcc);
+        break;
+      case 108:
+        if (showLoc) showLoc = 0; else showLoc = 1;
+        Serial.print("show loc packets = ");
+        Serial.println(showLoc);
+        break;
+    }
+    Serial.println(" ");
+  }
+}
+
+//=====================

BIN
schematic1.png