279 lines
8.0 KiB
C++
279 lines
8.0 KiB
C++
#include "arduinocompat.h"
|
|
|
|
#include <chrono>
|
|
|
|
#include <QUdpSocket>
|
|
#include <QDebug>
|
|
|
|
using ms = std::chrono::duration<double, std::milli>;
|
|
|
|
static std::chrono::system_clock::time_point last_sync;
|
|
|
|
uint64_t millis()
|
|
{
|
|
ms elapsed = std::chrono::system_clock::now() - last_sync;
|
|
return uint64_t(elapsed.count());
|
|
}
|
|
|
|
void init_millis()
|
|
{
|
|
last_sync = std::chrono::system_clock::now();
|
|
}
|
|
|
|
/*
|
|
Z21mobile for Arduino
|
|
|
|
Showing the funktion of the Z21 Library
|
|
connected to a W5100 Ethernet
|
|
|
|
*/
|
|
|
|
#define DEBUG //To see information from Z21 LAN Protokoll on Serial
|
|
|
|
#include <z21.h>
|
|
z21Class z21;
|
|
|
|
//----------------------------------------------------------------------------
|
|
//#include <SPI.h> // needed for Arduino versions later than 0018
|
|
//#include <Ethernet.h>
|
|
//#include <EthernetUdp.h> // UDP library
|
|
|
|
// An EthernetUDP instance to let us send and receive packets over UDP
|
|
//EthernetUDP Udp;
|
|
|
|
//---------------------------------------------------------------
|
|
byte mac[] = { 0xFE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
|
// The IP address will be dependent on your local network:
|
|
//IPAddress ip(192, 168, 188, 111);
|
|
|
|
#define Z21_UDP_TX_MAX_SIZE 15 //--> POM DATA has 12 Byte!
|
|
unsigned char packetBuffer[Z21_UDP_TX_MAX_SIZE]; //buffer to hold incoming packet,
|
|
|
|
#define maxIP 20 //Größe des IP-Speicher
|
|
typedef struct //Rückmeldung des Status der Programmierung
|
|
{
|
|
byte IP0;
|
|
byte IP1;
|
|
byte IP2;
|
|
byte IP3;
|
|
uint16_t port;
|
|
} listofIP;
|
|
listofIP mem[maxIP];
|
|
byte storedIP = 0; //speicher für IPs
|
|
|
|
QUdpSocket Udp;
|
|
|
|
/*********************************************************************************************/
|
|
// the setup routine runs once when you press reset:
|
|
void arduino_setup()
|
|
{
|
|
// initialize the digital pin as an output.
|
|
//Serial.begin(115200);
|
|
//Serial.println("Z21mobile");
|
|
qDebug() << "BEGIN Z21 Mobile";
|
|
|
|
// start the Ethernet and UDP:
|
|
//Ethernet.begin(mac,ip); //IP and MAC Festlegung
|
|
//Udp.begin(z21Port); //UDP Z21 Port
|
|
Udp.bind(z21Port);
|
|
|
|
z21.setPower(csNormal);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
byte addIP (byte ip0, byte ip1, byte ip2, byte ip3, uint16_t port)
|
|
{
|
|
//suche ob IP schon vorhanden?
|
|
for (byte i = 0; i < storedIP; i++) {
|
|
if (mem[i].IP0 == ip0 && mem[i].IP1 == ip1 && mem[i].IP2 == ip2 && mem[i].IP3 == ip3)
|
|
return i+1;
|
|
}
|
|
if (storedIP >= maxIP)
|
|
return 0;
|
|
|
|
qDebug().nospace() << "NEW CLIENT: " << ip0 << "." << ip1 << "." << ip2 << "." << ip3 << " port: " << port;
|
|
|
|
mem[storedIP].IP0 = ip0;
|
|
mem[storedIP].IP1 = ip1;
|
|
mem[storedIP].IP2 = ip2;
|
|
mem[storedIP].IP3 = ip3;
|
|
mem[storedIP].port = port;
|
|
storedIP++;
|
|
return storedIP;
|
|
}
|
|
|
|
byte addIP (const QHostAddress& addr, uint16_t port)
|
|
{
|
|
struct IPv4
|
|
{
|
|
byte ip0;
|
|
byte ip1;
|
|
byte ip2;
|
|
byte ip3;
|
|
};
|
|
IPv4 ip = {};
|
|
|
|
bool ok = false;
|
|
*reinterpret_cast<quint32 *>(&ip) = addr.toIPv4Address(&ok);
|
|
if(!ok)
|
|
return 0;
|
|
|
|
return addIP(ip.ip0, ip.ip1, ip.ip2, ip.ip3, port);
|
|
}
|
|
|
|
void makeHostAddress(QHostAddress *addr, quint16 *port, const listofIP *ip)
|
|
{
|
|
addr->setAddress(*reinterpret_cast<const quint32 *>(ip));
|
|
*port = ip->port;
|
|
}
|
|
|
|
/*********************************************************************************************/
|
|
// the loop routine runs over and over again forever:
|
|
void arduino_loop()
|
|
{
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
// if(Udp.parsePacket() > 0) { //packetSize
|
|
// Udp.read(packetBuffer,Z21_UDP_TX_MAX_SIZE); // read the packet into packetBufffer
|
|
// IPAddress remote = Udp.remoteIP();
|
|
// z21.receive(addIP(remote[0], remote[1], remote[2], remote[3]), packetBuffer);
|
|
// }
|
|
|
|
if(Udp.hasPendingDatagrams())
|
|
{
|
|
QHostAddress remote;
|
|
quint16 port;
|
|
Udp.readDatagram(reinterpret_cast<char *>(packetBuffer), Z21_UDP_TX_MAX_SIZE, &remote, &port);
|
|
|
|
byte client = addIP(remote, port);
|
|
z21.receive(client, packetBuffer);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
//unsigned long getz21BcFlag (byte flag);
|
|
//byte getPower(); //Zusand Gleisspannung ausgeben
|
|
//void setS88Data(byte *data); //return state of S88 sensors
|
|
//void setLNDetector(byte *data); //return state from LN detector
|
|
//void setLNMessage(byte *data, byte DataLen, byte bcType, bool TX); //return LN Message
|
|
//void setTrntInfo(uint16_t Adr, bool State); //Return the state of accessory
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21RailPower(uint8_t State)
|
|
{
|
|
qDebug() << "Power:" << QString::number(State, 16);
|
|
|
|
//Serial.print("Power: ");
|
|
//Serial.println(State, HEX);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21EthSend(uint8_t client, uint8_t *data)
|
|
{
|
|
// if (client == 0) { //all stored
|
|
// for (byte i = 0; i < storedIP; i++) {
|
|
// IPAddress ip(mem[i].IP0, mem[i].IP1, mem[i].IP2, mem[i].IP3);
|
|
// Udp.beginPacket(ip, Udp.remotePort()); //Broadcast
|
|
// Udp.write(data, data[0]);
|
|
// Udp.endPacket();
|
|
// }
|
|
// }
|
|
// else {
|
|
// IPAddress ip(mem[client-1].IP0, mem[client-1].IP1, mem[client-1].IP2, mem[client-1].IP3);
|
|
// Udp.beginPacket(ip, Udp.remotePort()); //no Broadcast
|
|
// Udp.write(data, data[0]);
|
|
// Udp.endPacket();
|
|
// }
|
|
|
|
if (client == 0)
|
|
{
|
|
//all stored
|
|
for (byte i = 0; i < storedIP; i++)
|
|
{
|
|
QHostAddress remote;
|
|
quint16 port;
|
|
makeHostAddress(&remote, &port, mem + i);
|
|
|
|
Udp.writeDatagram(reinterpret_cast<char *>(data), data[0], remote, port);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QHostAddress remote;
|
|
quint16 port;
|
|
makeHostAddress(&remote, &port, mem + client - 1);
|
|
|
|
Udp.writeDatagram(reinterpret_cast<char *>(data), data[0], remote, port);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21S88Data()
|
|
{
|
|
//z21.setS88Data (datasend); //Send back state of S88 Feedback
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21getLocoState(uint16_t Adr, bool bc)
|
|
{
|
|
//void setLocoStateFull (int Adr, byte steps, byte speed, byte F0, byte F1, byte F2, byte F3, bool bc);
|
|
}
|
|
|
|
void notifyz21LocoFkt(uint16_t Adr, uint8_t type, uint8_t fkt)
|
|
{
|
|
qDebug() << "Loco:" << Adr << "Type:" << type << "FK:" << fkt;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21LocoSpeed(uint16_t Adr, uint8_t speed, uint8_t steps)
|
|
{
|
|
qDebug() << "Loco:" << Adr << "Speed:" << speed << "Steps:" << steps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21Accessory(uint16_t Adr, bool state, bool active)
|
|
{
|
|
qDebug() << "Accessory:" << Adr << "State:" << state << "Active:" << active;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
uint8_t notifyz21AccessoryInfo(uint16_t Adr)
|
|
//return state of the Address (left/right = true/false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
uint8_t notifyz21LNdispatch(uint8_t Adr2, uint8_t Adr)
|
|
//return the Slot that was dispatched, 0xFF at error!
|
|
{
|
|
return 0xFF;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21LNSendPacket(uint8_t *data, uint8_t length)
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21CVREAD(uint8_t cvAdrMSB, uint8_t cvAdrLSB)
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21CVWRITE(uint8_t cvAdrMSB, uint8_t cvAdrLSB, uint8_t value)
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
void notifyz21CVPOMWRITEBYTE(uint16_t Adr, uint16_t cvAdr, uint8_t value)
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
|