Wer könnte mir einen Sketch umschreiben?

Hallo,

ich suche jemanden der mir einen Sketch umschreibt, soweit das möglich ist. Zum Ersteller diese hab ich keinen Kontaktmöglichkeiten.

Es handelt sich um eine FastClock, die die Zeit auf einem 4 Stück 8X8 [Max7219 Matrix Display] ausgibt. Um die Anzeige nun zu vergrößern, möchte ich 8 - 8x8 oder auch 12 - 8x8 Displays.

#define MAX_DEVICES 8

reicht da leider nicht als Angabe. ich Denke da muss mehr im Code geändert werden.
Würde sich den Code mal bitte jemand anschauen, ob der Aufwand zu groß wäre?

Grüße
Mario

Wie soll das jemand ohne den Code einschätzen können?

Gruß Tommy

Hallo Tommy,

leider kann ich als neuer den Code hier noch nicht als File hochladen.
Der Code ist schon lang... soll ich hier so spammen?

Mario

Setze Deinen Sketch bitte in Codetags. Wie das geht, steht hier.
Außerdem formatiere den Code bitte ordentlich. Strg+T in der IDE hilft Dir dabei.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

siehe post #9

Dann solltest du die evtl. vorher übersetzen.

Versuchen Sie, dem Autor zu schreiben.

https://usuaris.tinet.cat/fmco/home_en.htm

Hier der Code mit Übersetzung

#include <MD_MAX72xx.h>
#include <SPI.h>

/*    FastClockLN -- F. Cañada 2024 --  https://usuaris.tinet.cat/fmco/
      This software and associated files are a DIY project that is not intended for commercial use.
      This software uses libraries with different licenses, follow all their different terms included.

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.

      Sources are only provided for building and uploading to the device.
      Commercial use is forbidden.

       v0.1     02jan24   Start writting code
       v0.2     05jan24   Slave, Poll, RTC Poll & master modes working
       v0.3     06jan24   Added configuration menu
       v0.4     09jan24   Added pause button on Master

*/

// FastClockLN program version
#define VER_H 0
#define VER_L 4



#include <MD_MAX72xx.h>  // https://github.com/MajicDesigns/MD_MAX72XX   v3.5.1
#include <Keypad.h>      // https://github.com/Chris--A/Keypad           v3.1.1
#include "uRTCLib.h"     // https://github.com/Naguissa/uRTCLib          v6.6.1  Libreria RTC DS3231
#include <LocoNet.h>     // https://github.com/mrrwa/LocoNet/            v1.1.9
#include "Wire.h"        // Libreria I2C
#include <EEPROM.h>


////////////////////////////////////////////////////////////
// ***** USER OPTIONS *****
////////////////////////////////////////////////////////////

/*                ///< DR - Digits as rows; CR - Columns Reversed; RR - Rows Reversed
    GENERIC_HW,   ///< Use 'generic' style hardware modules commonly available.
    FC16_HW,      ///< Use FC-16 style hardware module.
    PAROLA_HW,    ///< Use the Parola style hardware modules.
    ICSTATION_HW, ///< Use ICStation style hardware module.

    DR0CR0RR0_HW, ///< Structured name
    DR0CR0RR1_HW, ///< Structured name
    DR0CR1RR0_HW, ///< Structured name; equivalent to GENERIC_HW
    DR0CR1RR1_HW, ///< Structured name
    DR1CR0RR0_HW, ///< Structured name; equivalent to FC16_HW
    DR1CR0RR1_HW, ///< Structured name
    DR1CR1RR0_HW, ///< Structured name; equivalent to PAROLA_HW
    DR1CR1RR1_HW  ///< Structured name; equivalent to ICSTATION_HW
*/

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW  // Tipo modulo

//#define USE_SPI                                             // Uncomment if standard (faster) SPI pins are used instead of the PacoMouse board

////////////////////////////////////////////////////////////
// ***** END OF USER OPTIONS *****
////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////
// ***** MAX7219 *****		#define HARDWARE_TYPE MD_MAX72XX::FC16_HW  // module type
////////////////////////////////////////////////////////////


#define MAX_DEVICES 4  // Number of modules 8x8 (4 modules all on - brightness 0: 90mA, brightness 15: 300mA)
#define SLIDE_TIME 45  // Sliding time text

#ifdef USE_SPI
#include <SPI.h>
/*
   SPI hardware interface                                   // 8MHz SPI (~1us/byte)
   SCK:  D13 - CLK
   MISO: D12 - No usado
   MOSI: D11 - DIN
   SS:   D10 - CS
*/
#define CS_PIN 10  // or SS
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
#else
// Arbitrary pins                                           // 65.8kHz (~122us/byte)
// PacoMouse board
#define CLK_PIN 2    // or SCK
#define DATA_PIN 12  // or MOSI
#define CS_PIN A2    // or SS
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#endif


byte brillo;
bool updateMX;
byte scrMX;
byte menuOpt;
byte optBrillo, optHour, optMin, optRate, optModo;

enum screen { MX_LOGO,
              MX_TIME,
              MX_GPOFF,
              MX_MENU,
              MX_OPT_MODO,
              MX_OPT_TIME,
              MX_OPT_RTC,
              MX_OPT_RATE,
              MX_OPT_BRILLO };
enum menu { OPT_MODO,
            OPT_TIME,
            OPT_RTC_TIME,
            OPT_RATE,
            OPT_BRILLO,
            OPT_MAX };

char menuTxt[][8] = {
  // Name of menu options
  "Mode",
  "Hour",
  "Uhr",
  "Ratio",
  "Glow",
};


////////////////////////////////////////////////////////////
// ***** KEYBOARD *****
////////////////////////////////////////////////////////////

const int pinFILA1 = 3;  // Keypad 3x4 or 4x4 pins
const int pinFILA2 = 4;
const int pinFILA3 = 5;
const int pinFILA4 = 6;
const int pinCOLUMNA1 = 9;

enum teclas { K_NONE,
              K_MENU,
              K_HOUR_PLUS,
              K_MIN_MINUS,
              K_ENTER };

#define FILAS 4  // Rows and Columns of the keyboard matrix
#define COLUMNAS 1

char keys[FILAS][COLUMNAS] = {  // Key layout
  { K_MENU },
  { K_HOUR_PLUS },
  { K_MIN_MINUS },
  { K_ENTER }
};

byte filaPins[FILAS] = { pinFILA1, pinFILA2, pinFILA3, pinFILA4 };  // keyboard row pins
byte colPins[COLUMNAS] = { pinCOLUMNA1 };                           // keyboard column pins

Keypad keypad = Keypad(makeKeymap(keys), filaPins, colPins, FILAS, COLUMNAS);

byte keyValue;  // key pressed value
bool keyOn;

////////////////////////////////////////////////////////////
// ***** CLOCK *****
////////////////////////////////////////////////////////////

#define I2C_ADDRESS_CLOCK 0x68  // Direccion I2C del DS3231

enum Mode {   // Clock modes:
  LN_SLAVE,   // Slave: Just listen to the Fast Clock									(no need RTC DS3231)
  LN_POLL,    // Poll: Send SYNC periodically            								(no need RTC DS3231)
  RTC_POLL,   // RTC Poll: Writes real time at startup and then sends SYNC periodically
  LN_MASTER,  // Master:      Implementa el Slot Fast Clock								(no need RTC DS3231)
  MODE_MAX,
};  // Clock mode settings

char output[80];

char modoTxt[][12] = {
  "Slave",
  "Sync",
  "RTC Sync",
  "Master",
};

enum opt { SEL_RATE,
           SEL_LN_TIME,
           SEL_RTC_TIME };

enum Settings {
  EE_BRILLO,
  EE_MODE,
};  // EEPROM settings

uRTCLib rtc(I2C_ADDRESS_CLOCK);  // The I2C address of the DS3231 clock module
unsigned long rtcTimeout, dotTimer;
byte hour;
byte minute;
byte seconds;
byte lastMinute;

byte errorDS3231;

byte modeClock;
bool showDot;

byte pauseRate;
byte pauseHour;
byte pauseMin;
byte pauseSecond;

////////////////////////////////////////////////////////////
// ***** LOCONET *****
////////////////////////////////////////////////////////////

#define ONE_DAY 86400000UL
#define SYNC_TIME 61000UL  // Time to SYNC (70..100s LPE, 50..60s LRT)

const int pinLN_RXD = 8;  // Loconet pins. DO NOT CHANGE, LN_RXD pin must be Arduino ICP pin
const int pinLN_TXD = 7;

static lnMsg *LnPacket;  // Package received by Loconet
lnMsg SendPacket;        // Package to be sent by Loconet

unsigned long syncTimer;
bool doSendSync;
byte clockHour, clockMin, clockRate;
unsigned long clockTimer, clockInterval;
bool newMinuteLN;
byte trk;

enum cs { CS_IB_I,
          CS_IB_II,
          CS_DR5K,
          CS_DAISY,
          CS_63820,
          CS_DIG,
          CS_UNKNOW };
byte typeCS;

char csTxt[][15] = {
  // Name of the power plants
  "Intellibox I",
  "Intellibox II",
  "DR5000",
  "Daisy",
  "63820",
  "Digitrax",
  "desconocido",
};

////////////////////////////////////////////////////////////
// ***** PROGRAM *****
////////////////////////////////////////////////////////////

void setup() {
  byte i;
  Wire.begin();  // I2C port initialization. SDA = A4, SCL = A5
  Wire.setClock(400000L);
  initVariables();  // Initial state
  mx.begin();       // Initialize MX7219 display
  mx.clear();
  mx.control(0, MAX_DEVICES - 1, MD_MAX72XX::INTENSITY, brillo);
  mx.control(MD_MAX72XX::UPDATE, false);  // Disable auto-update
  LocoNet.init(pinLN_TXD);                // Initializes Loconet communications
  identifyCS();
}


void loop() {
  loconetProcess();  // Loconet comunications
  if (doSendSync)
    sendSYNC();
  if (updateMX)
    showMX();
  readKeypad();  // keyboard reading
  if (keyOn)     // a key has been pressed
    controlKeypad();
}


void initVariables() {
  keypad.setDebounceTime(20);
  keyOn = false;
  brillo = EEPROM.read(EE_BRILLO) & 0x0F;  // Brightness: 0..15 (30mA..190mA average)
  scrMX = MX_LOGO;
  updateMX = true;
  typeCS = CS_UNKNOW;
  showDot = true;
  hour = 0;
  minute = 0;
  lastMinute = 99;
  clockRate = 0;  // fast clock internal
  clockHour = 0;
  clockMin = 0;
  pauseRate = 0;
  clockInterval = ONE_DAY;
  clockTimer = millis();
  rtcTimeout = millis();
  syncTimer = millis();
  Wire.beginTransmission(I2C_ADDRESS_CLOCK);  // Search DS3231
  errorDS3231 = Wire.endTransmission();
  modeClock = EEPROM.read(EE_MODE);
  startMode();
  trk = 0x07;  // GPON, not IDLE, LNv1.1
}


void startMode() {
  switch (modeClock) {
    case LN_SLAVE:
      break;
    case LN_POLL:
      doSendSync = true;
      break;
    case RTC_POLL:
      if (errorDS3231)  // If RTC is not installed, it is a slave
        modeClock = LN_SLAVE;
      break;
    case LN_MASTER:
      clockRate = (errorDS3231) ? 0 : 1;  // If RTC is installed it starts automatically.
      break;
    default:  // Configuration error, convert to slave
      modeClock = LN_SLAVE;
      break;
  }
}

////////////////////////////////////////////////////////////
// ***** KEYBOARD *****
////////////////////////////////////////////////////////////

void readKeypad() {
  byte inputButton;

  inputButton = keypad.getKey();  // read keyboard
  if (inputButton != NO_KEY) {
    keyValue = inputButton;
    keyOn = true;
  }
}


void controlKeypad() {  // Action when pressing a key
  keyOn = false;
  switch (scrMX) {  // according to the current screen
    case MX_TIME:
      isKeyMenu();
      if (modeClock == LN_MASTER) {  // Only in Master mode
        switch (keyValue) {
          case K_HOUR_PLUS:  // Resume
            if (pauseRate > 0) {
              clockRate = pauseRate;
              if ((!errorDS3231) && (clockRate == 1))
                rtc.set(pauseSecond, pauseMin, pauseHour, URTCLIB_WEEKDAY_MONDAY, 1, 1, 24);
              pauseRate = 0;
              newMinuteLN = true;
            }
            break;
          case K_MIN_MINUS:  // Pause
            if (clockRate > 0) {
              pauseRate = clockRate;
              if (!errorDS3231) {
                rtc.refresh();  // Lee RTC DS3231
                pauseHour = rtc.hour();
                pauseMin = rtc.minute();
                pauseSecond = rtc.second();
              }
              clockRate = 0;
              showDot = true;
              newMinuteLN = true;
            }
            break;
        }
      }
      break;
    case MX_LOGO:
      break;
    case MX_GPOFF:
      break;
    case MX_MENU:
      switch (keyValue) {
        case K_MENU:  // exit the menu
          scrMX = (trk & 0x01) ? MX_TIME : MX_GPOFF;
          break;
        case K_ENTER:
          switch (menuOpt) {  // enter the menu option
            case OPT_BRILLO:
              scrMX = MX_OPT_BRILLO;
              optBrillo = brillo;
              break;
            case OPT_TIME:
              scrMX = MX_OPT_TIME;
              optHour = clockHour;
              optMin = clockMin;
              break;
            case OPT_RTC_TIME:
              if (errorDS3231) {
                slideText(SLIDE_TIME, "RTC not found");
              } else {
                scrMX = MX_OPT_RTC;
                rtc.refresh();  // Lee RTC DS3231
                optHour = rtc.hour();
                optMin = rtc.minute();
              }
              break;
            case OPT_RATE:
              scrMX = MX_OPT_RATE;
              optRate = clockRate;
              break;
            case OPT_MODO:
              scrMX = MX_OPT_MODO;
              optModo = modeClock;
              break;
          }
          showDot = true;
          break;
        case K_HOUR_PLUS:
          menuOpt++;
          if (menuOpt == OPT_MAX)
            menuOpt = OPT_MODO;
          updateMX = true;
          break;
        case K_MIN_MINUS:
          menuOpt = (menuOpt > 0) ? --menuOpt : OPT_BRILLO;
          break;
      }
      updateMX = true;
      break;
    case MX_OPT_BRILLO:  // change screen brightness
      isKeyMenu();
      switch (keyValue) {
        case K_HOUR_PLUS:
          if (optBrillo < 15)
            optBrillo++;
          break;
        case K_MIN_MINUS:
          if (optBrillo > 0)
            optBrillo--;
          break;
        case K_ENTER:
          scrMX = MX_MENU;
          brillo = optBrillo;
          EEPROM.update(EE_BRILLO, brillo);
          break;
      }
      updateMX = true;
      break;
    case MX_OPT_RATE:  // Change ratio 0:1 .. 127:1
      isKeyMenu();
      switch (keyValue) {
        case K_HOUR_PLUS:
          if (optRate < 127)
            optRate++;
          break;
        case K_MIN_MINUS:
          if (optRate > 0)
            optRate--;
          break;
        case K_ENTER:
          scrMX = MX_MENU;
          clockRate = optRate;
          pauseRate = 0;  // cancela pausa
          if (clockRate > 0)
            clockInterval = 60000UL / (unsigned long)clockRate;  // calculate interval for one minute
          if (modeClock == LN_MASTER)
            sendTimeLN(clockHour, clockMin, clockRate, false);
          else
            sendTimeLN(clockHour, clockMin, clockRate, true);
          break;
      }
      updateMX = true;
      break;
    case MX_OPT_TIME:  // Change the time on the Fast Clock
      isKeyMenu();
      switch (keyValue) {
        case K_HOUR_PLUS:
          if (optHour < 23)
            optHour++;
          else
            optHour = 0;
          break;
        case K_MIN_MINUS:
          if (optMin < 59)
            optMin++;
          else
            optMin = 0;
          break;
        case K_ENTER:
          scrMX = MX_MENU;
          clockHour = optHour;
          clockMin = optMin;
          clockTimer = millis();
          newMinuteLN = true;
          if (modeClock != LN_MASTER)
            sendTimeLN(clockHour, clockMin, clockRate, true);
          break;
      }
      updateMX = true;
      break;
    case MX_OPT_RTC:  // Change RTC time
      isKeyMenu();
      switch (keyValue) {
        case K_HOUR_PLUS:
          if (optHour < 23)
            optHour++;
          else
            optHour = 0;
          break;
        case K_MIN_MINUS:
          if (optMin < 59)
            optMin++;
          else
            optMin = 0;
          break;
        case K_ENTER:
          scrMX = MX_MENU;
          lastMinute = 99;
          rtc.set(0, optMin, optHour, URTCLIB_WEEKDAY_MONDAY, 1, 1, 24);
          break;
      }
      updateMX = true;
      break;
    case MX_OPT_MODO:  // Change mode
      isKeyMenu();
      switch (keyValue) {
        case K_HOUR_PLUS:
          optModo++;
          if (optModo == MODE_MAX)
            optModo = LN_SLAVE;
          break;
        case K_MIN_MINUS:
          optModo = (optModo > 0) ? --optModo : LN_MASTER;
          break;
        case K_ENTER:
          scrMX = MX_MENU;
          modeClock = optModo;
          EEPROM.update(EE_MODE, modeClock);
          startMode();  // start new mode
          break;
      }
      updateMX = true;
      break;
    default:
      isKeyMenu();
      break;
  }
}

void isKeyMenu() {  // Pressing menu returns to the main menu
  if (keyValue == K_MENU) {
    scrMX = MX_MENU;
    menuOpt = OPT_MODO;
    updateMX = true;
    mx.control(0, MAX_DEVICES - 1, MD_MAX72XX::INTENSITY, brillo);
  }
}

////////////////////////////////////////////////////////////
// ***** MAX7219 *****
////////////////////////////////////////////////////////////

// 3         2         1
//10987654321098765432109876543210
// xxxxx  xxxxx  xx  xxxxx  xxxxx
//--------        --------
void printTime(byte hora, byte minuto) {  // Print time on MX7219 display
  byte decena, unidad;
  mx.clear();
  decena = hora / 10;
  unidad = hora % 10;
  if (decena)
    printDigit(30, decena);
  printDigit(23, unidad);
  if (showDot)
    mx.setChar(16, ':');
  decena = minuto / 10;
  unidad = minuto % 10;
  printDigit(12, decena);
  printDigit(5, unidad);
  mx.update();
}


void printDigit(byte pos, byte number) {  // print a digit
  if (number == 1)
    pos--;
  mx.setChar(pos, number + 0x30);
}


int printText(int pos, char *text) {  // Print a text
  int w, i;
  for (i = 0; text[i]; i++) {
    w = mx.setChar(pos, text[i]);
    pos = pos - w;
    mx.setColumn(pos--, 0x00);
    if (pos < 0)
      break;
  }
  mx.update();
  return pos;
}


void slideText(int ms_delay, char *mensaje) {  // Print a mobile message
  int col = 0;
  int last_pos, ms_count;
  bool completo = false;
  mx.clear();
  while ((!completo) && (!updateMX)) {  // until it completes or the screen is updated
    last_pos = printText(col, mensaje);
    ms_count = ms_delay;
    while (ms_count--) {
      delay(1);
      loconetProcess();  // Loconet comunications
    }
    col++;
    if (last_pos > (int)mx.getColumnCount())
      completo = true;
  }
}


void showMX() {  // display screen on MX7219 display
  updateMX = false;
  switch (scrMX) {
    case MX_LOGO:
      slideText(SLIDE_TIME, "FastClockLN");
      showCS();
      showMode();
      scrMX = (trk & 0x01) ? MX_TIME : MX_GPOFF;
      updateMX = true;
      break;
    case MX_TIME:
      printTime(clockHour, clockMin);
      break;
    case MX_GPOFF:
      slideText(SLIDE_TIME, "Power OFF");
      updateMX = true;
      break;
    case MX_MENU:
      mx.clear();
      printText(31, menuTxt[menuOpt]);
      break;
    case MX_OPT_BRILLO:
      mx.clear();
      snprintf(output, 80, "%d", optBrillo);
      if (optBrillo > 9)
        printText(19, output);
      else
        printText(15, output);
      mx.control(0, MAX_DEVICES - 1, MD_MAX72XX::INTENSITY, optBrillo);
      mx.update();
      break;
    case MX_OPT_RTC:
    case MX_OPT_TIME:
      printTime(optHour, optMin);
      break;
    case MX_OPT_RATE:
      mx.clear();
      if (optRate > 0) {
        snprintf(output, 80, "%d:1", optRate);
        if (optRate > 99) {
          printText(26, output);
        } else {
          if (optRate > 9)
            printText(24, output);
          else
            printText(21, output);
        }
      } else {
        printText(28, "Pausa");
      }
      break;
    case MX_OPT_MODO:
      mx.clear();
      printText(31, modoTxt[optModo]);
      break;
  }
}

// 3         2         1
//1098765432109876 5432109876543210
//--------         --------


void showMode() {
  snprintf(output, 80, "Mode: %s", modoTxt[modeClock]);
  slideText(SLIDE_TIME, output);
}


void showCS() {
  snprintf(output, 80, "Connected to %s", csTxt[typeCS]);
  slideText(SLIDE_TIME, output);
}

////////////////////////////////////////////////////////////
// ***** LOCONET DECODE *****
////////////////////////////////////////////////////////////

void loconetProcess() {          // Decoding Loconet packets
  LnPacket = LocoNet.receive();  // receives Loconet packets
  if (LnPacket) {
    if (!LocoNet.processSwitchSensorMessage(LnPacket)) {  // Packages diverted and sensors
      switch (LnPacket->sz.command) {
        case OPC_SL_RD_DATA:  // slot information
          trk = LnPacket->sd.trk;
          if (LnPacket->sd.slot == FC_SLOT) {  // FAST Clock
            if (modeClock != LN_MASTER) {
              if (LnPacket->fc.clk_cntrl & 0x40) {  // bit 6 = 1; data is valid clock info
                setFastClock();
              }
            }
          }
          if (LnPacket->sd.slot == 0x00) {  // Slot 0. ID from the central
            getCS();
          }
          break;
        case OPC_RQ_SL_DATA:
          if (LnPacket->sr.slot == FC_SLOT) {  // FAST Clock SYNC
            if (modeClock == LN_MASTER) {
              sendTimeLN(clockHour, clockMin, clockRate, false);
            }
          }
          break;
        case OPC_WR_SL_DATA:
          trk = LnPacket->sd.trk;
          if (LnPacket->sd.slot == FC_SLOT) {  // FAST Clock
            setFastClock();                    // update. JMRI sends only EF 0E 7B ... (OPC_WR_SL_DATA) with clk_cntrl == 0
            if ((modeClock == LN_MASTER) && (!errorDS3231)) {
              if (clockRate == 1)  // save new time in RTC if 1:1
                rtc.set(0, clockMin, clockHour, URTCLIB_WEEKDAY_MONDAY, 1, 1, 24);
            }
          }
          break;
      }
    }
  }
  if (clockRate > 0) {  // Update internal fast clock
    if (millis() - clockTimer > clockInterval) {
      clockTimer = millis();
      clockMin++;
      if (clockMin > 59) {
        clockMin = 0;
        clockHour++;
      }
      if (clockHour > 23)
        clockHour = 0;
      newMinuteLN = true;
    }
    if (scrMX == MX_TIME) {  // blinking clock dots every second
      if (millis() - dotTimer > 1000UL) {
        dotTimer = millis();
        if (showDot)
          mx.setChar(16, ':');
        else {
          mx.setColumn(16, 0x00);
          mx.setColumn(15, 0x00);
        }
        mx.update();
        showDot = !showDot;
      }
    }
  }

  switch (modeClock) {
    case LN_POLL:                              // mode 'Sync'
      if (millis() - syncTimer > SYNC_TIME) {  // timer for SYNC
        syncTimer = millis();
        doSendSync = true;
      }
    case LN_SLAVE:                              // 'Slave and Sync' mode
      if ((scrMX == MX_TIME) && newMinuteLN) {  // update clock
        updateMX = true;
        newMinuteLN = false;
      }
      break;
    case RTC_POLL:  // Mode 'RTC Sync'
      if (millis() - syncTimer > 22000UL) {
        rtc.refresh();  // Lee RTC DS3231
        hour = rtc.hour();
        minute = rtc.minute();
        seconds = rtc.second();
        sendTimeLN(hour, minute, 1, true);                         // Send time via LN when connecting
        syncTimer = millis() - (unsigned long)(seconds * 1000UL);  // fix for sync time in hh:mm:00
        modeClock = LN_POLL;                                       // switch to Sync mode
      }
      break;
    case LN_MASTER:                              // mode 'Master'
      if ((clockRate == 1) && (!errorDS3231)) {  // Read RTC every half second if installed and Ratio 1:1
        if (millis() - rtcTimeout > 500) {
          rtcTimeout = millis();
          clockTimer = millis();             // reset internal timeout
          rtc.refresh();                     // Lee RTC DS3231
          if (rtc.minute() != lastMinute) {  // check if the minute changes
            clockHour = rtc.hour();
            clockMin = rtc.minute();
            lastMinute = clockMin;
            newMinuteLN = true;
          }
        }
      }
      if (newMinuteLN) {  // Every new minute sends by LN automatically
        sendTimeLN(clockHour, clockMin, clockRate, false);
        if (scrMX == MX_TIME)
          updateMX = true;
        newMinuteLN = false;
      }
      break;
  }
}


void setFastClock() {
  if (LnPacket->fc.clk_rate != clockRate) {  // 0 = Freeze clock, 1 = normal, 10 = 10:1 etc. Max is 0x7f
    clockRate = LnPacket->fc.clk_rate;       // calculate new internal interval
    if (clockRate > 0)
      clockInterval = 60000UL / (unsigned long)clockRate;  // calculate interval for one minute
    showDot = true;
  }                                          // [EF 0E 7B 01 7F 79 43 07 68 1B 40 00 00 15] JMRI: 00:00 DAY 27
  clockMin = LnPacket->fc.mins_60 - 0x43;    // 256 - minutes   ???
  clockHour = LnPacket->fc.hours_24 - 0x68;  // 256 - hours     ???
  clockTimer = millis();                     // reset local sub-minute phase counter
  if (modeClock != LN_MASTER)
    newMinuteLN = true;
  if (scrMX == MX_TIME)
    updateMX = true;
}


void sendTimeLN(byte hh, byte mm, byte rate, bool writeTime) {
  if ((hh > 23) || (mm > 59)) {  // Avoid sending wrong time
    hh = 11;
    mm = 33;
  }
  if (writeTime)
    SendPacket.data[0] = OPC_WR_SL_DATA;  // Set new time
  else
    SendPacket.data[0] = OPC_SL_RD_DATA;  // write not accepted by TwinCenter (LACK: B4 6F 00 24)
  SendPacket.data[1] = 0x0E;
  SendPacket.data[2] = FC_SLOT;
  SendPacket.data[3] = rate;  // clock rate: 1 for RTC
  SendPacket.data[4] = 0x7F;
  SendPacket.data[5] = 0x79;
  SendPacket.data[6] = mm + 0x43;
  SendPacket.data[7] = trk;  // trk
  SendPacket.data[8] = hh + 0x68;
  SendPacket.data[9] = 0x00;   // day
  SendPacket.data[10] = 0x40;  // control
  SendPacket.data[11] = 0x00;  // ID
  SendPacket.data[12] = 0x00;
  LocoNet.send(&SendPacket);
}

void sendSYNC() {  // Envia SYNC
  SendPacket.data[0] = OPC_RQ_SL_DATA;
  SendPacket.data[1] = FC_SLOT;
  SendPacket.data[2] = 0x00;
  LocoNet.send(&SendPacket);
  doSendSync = false;
}

void notifyPower(uint8_t State) {  // Callback Power ON/OFF
  if (State == 1) {                // OPC_GPON
    bitSet(trk, 0);
    scrMX = MX_TIME;
  } else {  // OPC_GPOFF
    bitClear(trk, 0);
    scrMX = MX_GPOFF;
  }
  updateMX = true;
}


void identifyCS() {  // Read slot 0 to identify central
  SendPacket.data[0] = OPC_RQ_SL_DATA;
  SendPacket.data[1] = 0x00;
  SendPacket.data[2] = 0x00;
  LocoNet.send(&SendPacket);
}

/*
  Reading Slot #0 can be used to identify the Intellibox. In fact, it can be
  used to identify all of our 'LocoNet master' devices: one can tell that it is
  an Intellibox, a DAISY or a Power 2 in analog mode by looking at the answer
  of a Slot #0 read request. One would find that ID1 and ID2 have these values:
  ID1 = 'I', ID2 = 'B'.
  Furthermore, the value of the Speed byte tells the "level" of the LocoNet
  driver of the Command Station. The current firmware of the Intellibox (IB),
  of the DAISY and of the Power2 (in analog mode) report the Speed byte as
  having value 2 (this basically means: the LocoNet driver supports our FRED
  - used in the "intelligent, 4 locos" mode).
  Now, if one needs to find out exactly to which of our Command Stations one
  is connected to (Intellibox, DAISY, Power2 in analog mode - or Digitrax),
  then a Slot write of Slot #0 has to be performed (e.g. using the very values
  one just read from that Slot):
  - a Power 2 in analog mode does not reply at all
  - an IB/TC replies with LACK, error = 0Eh (OPC_WR_SL_DATA length)
  - a DAISY replies with LACK, error = 1
  - a Digitrax Chief replies with LACK 'Ok' (7Fh)
  One can tell a Digitrax CS also by looking at ID1 and ID2 of the Slot #0 read.

  Detect Hardware type (Read Slot 0)
  0xE7, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x49, 0x42, 0x18  "Intellibox / TwinCenter"               ADR: 0    ID: 'IB'  SPD: 2
  0xE7, 0x0E, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x08, 0x00, 0x00, 0x49, 0x42, 0x13  "DR5000"                                ADR: 0    ID: 'IB'  SPD: 3
  0xE7, 0x0E, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x08, 0x00, 0x00, 0x49, 0x42, 0x12  "YD7001"                                ADR: 0    ID: 'IB'  SPD: 3
  0xE7, 0x0E, 0x00, 0x02, 0x42, 0x03, 0x00, 0x07, 0x00, 0x00, 0x15, 0x49, 0x42, 0x4C  "Intellibox II / IB-Basic / IB-Com"     ADR: 'B'  ID: 'IB'  SPD: 3
  0xE7, 0x0E, 0x00, 0x02, 0x42, 0x03, 0x00, 0x06, 0x00, 0x00, 0x15, 0x49, 0x42, 0x4D  "System Control 7"                      ADR: 'B'  ID: 'IB'  SPD: 3
  0xE7, 0x0E, 0x00, 0x02, 0x42, 0x03, 0x00, 0x07, 0x00, 0x00, 0x15, 0x49, 0x42, 0x4C  "Daisy II Tillig"                       ADR: 'B'  ID: 'IB'  SPD: 3
  0xE7, 0x0E, 0x00, 0x00, 0x44, 0x02, 0x00, 0x07, 0x00, 0x59, 0x01, 0x49, 0x42, 0x04  "Daisy"                                 ADR: 'DY' ID: 'IB'  SPD: 2
  0xE7, 0x0E, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x07, 0x00, 0x49, 0x02, 0x49, 0x42, 0x1C  "Adapter 63820"                         ADR: 'LI' ID: 'IB'  SPD: 1
  0xE7, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11  "Digitrax Chief"                        ADR: 0    ID: 0     SPD: 0
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11  DCS100
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12  DCS200
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12  DCS50
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52  DCS52
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x25, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30  DT200
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51  DCS210
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x11, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40  DCS240
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x20, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71  DCS240+
  0xe7, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16  DB150                                   ADR: 0    ID: 0     SPD: 4
  0xe7, 0x0e, 0x00, 0x33, 0x0e, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2d  DCS51                                   ADR: 0    ID: 1     SPD: 0

              SLOT  STAT1 ADRL   SPD  DIRF  TRK   STAT2  ADH   SND   ID1   ID2   CHK

*/


void getCS() {  // Identify central
  typeCS = CS_UNKNOW;
  trk = LnPacket->sd.trk;
  if ((LnPacket->sd.id1 == 'I') && (LnPacket->sd.id2 == 'B')) {
    switch (LnPacket->sd.adr) {
      case 0:
        switch (LnPacket->sd.spd) {
          case 2:  // "Intellibox / TwinCenter"
            typeCS = CS_IB_I;
            break;
          case 3:  // "DR5000"
            typeCS = CS_DR5K;
            break;
        }
        break;
      case 'B':  // "Intellibox II / IB-Basic / IB-Com"
        typeCS = CS_IB_II;
        break;
      case 'D':
        if (LnPacket->sd.adr2 == 'Y') {  // "Daisy"
          typeCS = CS_DAISY;
        }
        break;
      case 'L':
        if (LnPacket->sd.adr2 == 'I') {  // "Adapter 63820"
          typeCS = CS_63820;
        }
        break;
    }
  }
  if ((LnPacket->sd.id1 == 0) && (LnPacket->sd.id2 == 0)) {  // "Digitrax Chief"
    typeCS = CS_DIG;
  }
}

Sie meinen NICHT , auf die Idee wäre ich nicht alleine gekommen?
Wenn SIE mir eine Email des Autors geben , ziehe ich das gern in Erwägung.

Ein "vielen Dank" hätte durchaus gereicht.

Hier ganz nach unten scrollen.

Du sagst mir nicht, was ich tun soll. Wenn ich faul wäre, hätte ich keinen Ort gefunden, um dem Autor zu schreiben.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.