Files
Maison/PacoMouseCYD/Platformio/include/lnet.h
2026-02-11 17:16:06 +01:00

299 lines
13 KiB
C

/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- 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.
You are not allowed to modify the source code or fork/publish this project.
Commercial use is forbidden.
*/
// OPCODES
#define OPC_GPOFF 0x82 // GLOBAL power OFF request
#define OPC_GPON 0x83 // GLOBAL power ON request
#define OPC_LOCO_SPD 0xA0 // SET SLOT speed
#define OPC_LOCO_DIRF 0xA1 // SET SLOT dir,F0-4 state
#define OPC_LOCO_SND 0xA2 // SET SLOT sound functions
#define OPC_LOCO_F9F12 0xA3 // Uhlenbrock
#define OPC_SW_REQ 0xB0 // REQ SWITCH function
#define OPC_SW_REP 0xB1 // Turnout SENSOR state REPORT
#define OPC_INPUT_REP 0xB2 // General SENSOR Input codes
#define OPC_LONG_ACK 0xB4 // Long acknowledge
#define OPC_SLOT_STAT1 0xB5 // WRITE slot stat1
#define OPC_MOVE_SLOTS 0xBA // MOVE slot SRC to DEST
#define OPC_RQ_SL_DATA 0xBB // Request SLOT DATA/status block
#define OPC_SW_STATE 0xBC // REQ state of SWITCH
#define OPC_LOCO_ADR_UHLI 0xBE // REQ loco ADR Uhlenbrock
#define OPC_LOCO_ADR 0xBF // REQ loco ADR
#define OPC_UHLI_FUN 0xD4 // Uhlenbrock
#define OPC_PEER_XFER 0xE5 // move 8 bytes PEER to PEER, SRC->DST
#define OPC_SL_RD_UHLI 0xE6 // SLOT DATA return, 21 bytes Uhlenbrock
#define OPC_SL_RD_DATA 0xE7 // SLOT DATA return, 10 bytes
#define OPC_IMM_PACKET 0xED // SEND n-byte packet immediate
#define OPC_WR_SL_UHLI 0xEE // WRITE SLOT DATA, 21 bytes Uhlenbrock
#define OPC_WR_SL_DATA 0xEF // WRITE SLOT DATA, 10 bytes
// BIT MASK
#define OPC_SW_REP_INPUTS 0x40 // sensor inputs, outputs otherwise
#define OPC_SW_REP_SW 0x20 // switch input, aux input otherwise
#define OPC_SW_REP_HI 0x10 // input is HI, LO otherwise
#define OPC_SW_REP_CLOSED 0x20 // 'Closed' line is ON, OFF otherwise
#define OPC_SW_REP_THROWN 0x10 // 'Thrown' line is ON, OFF otherwise
#define OPC_SW_REQ_DIR 0x20 // switch direction - closed/thrown
#define OPC_SW_REQ_OUT 0x10 // output On/Off
#define OPC_INPUT_REP_SW 0x20 // input is switch input, aux otherwise
#define OPC_INPUT_REP_HI 0x10 // input is HI, LO otherwise
#define STAT1_SL_BUSY 0x20 // BUSY/ACTIVE: bit encoding for SLOT activity
#define STAT1_SL_ACTIVE 0x10
#define GTRK_PROG_BUSY 0x08 // programming track is Busy
#define GTRK_IDLE 0x02 // 0 = Track paused, B'cast EMERG STOP, 1 = Power On
#define GTRK_POWER 0x01 // DCC packets are on and global power is up
// VALUES
#define SLOT_0 0x00 // Slot 0. Identifies command station type if implemented
#define SLOT_FC 0x7B // Fast clock slot
#define SLOT_PRG 0x7C // This slot communicates with the programming track
#define UHLI_PRG_START 0x41 // Intellibox II program task
#define UHLI_PRG_END 0x40
#define LNCV_REQID_CFGREAD 0x1F // LNCV task
#define LNCV_REQID_CFGWRITE 0x20
#define LNCV_REQID_CFGREQUEST 0x21
#define LNCV_FLAG_PRON 0x80
#define LNCV_FLAG_PROFF 0x40
// Message structure to determine the size of a message
typedef struct {
uint8_t command; /* LocoNet Op Code */
uint8_t mesg_size; /* size of the message in bytes */
} szMsg;
/* Turnout sensor state report */
typedef struct swrep_t {
uint8_t command;
uint8_t sn1; /* first byte of report */
uint8_t sn2; /* second byte of report */
uint8_t chksum; /* exclusive-or checksum for the message */
} swRepMsg;
/* Request Switch function */
typedef struct swreq_t {
uint8_t command;
uint8_t sw1; /* first byte of request */
uint8_t sw2; /* second byte of request */
uint8_t chksum; /* exclusive-or checksum for the message */
} swReqMsg;
/* Sensor input report */
typedef struct inputrep_t {
uint8_t command;
uint8_t in1; /* first byte of report */
uint8_t in2; /* second byte of report */
uint8_t chksum; /* exclusive-or checksum for the message */
} inputRepMsg;
/* Slot data request */
typedef struct slotreq_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t pad; /* should be zero */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotReqMsg;
/* Read/Write Slot data messages */
typedef struct rwslotdata_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request */
uint8_t stat; /* slot status */
uint8_t adr; /* loco address */
uint8_t spd; /* command speed */
uint8_t dirf; /* direction and F0-F4 bits */
uint8_t trk; /* track status */
uint8_t ss2; /* slot status 2 (tells how to use ID1/ID2 & ADV Consist*/
uint8_t adr2; /* loco address high */
uint8_t snd; /* Sound 1-4 / F5-F8 */
uint8_t id1; /* ls 7 bits of ID code */
uint8_t id2; /* ms 7 bits of ID code */
uint8_t chksum; /* exclusive-or checksum for the message */
} rwSlotDataMsg;
/* Fast Clock Message */
typedef struct fastclock_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request */
uint8_t clk_rate; /* 0 = Freeze clock, 1 = normal, 10 = 10:1 etc. Max is 0x7f */
uint8_t frac_minsl; /* fractional minutes. not for external use. */
uint8_t frac_minsh;
uint8_t mins_60; /* 256 - minutes */
uint8_t track_stat; /* track status */
uint8_t hours_24; /* 256 - hours */
uint8_t days; /* clock rollovers */
uint8_t clk_cntrl; /* bit 6 = 1; data is valid clock info */
/* " " 0; ignore this reply */
uint8_t id1; /* id1/id2 is device id of last device to set the clock */
uint8_t id2; /* " " = zero shows not set has happened */
uint8_t chksum; /* exclusive-or checksum for the message */
} fastClockMsg;
/* Programmer Task Message (used in Start and Final Reply, both )*/
typedef struct progtask_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request - slot 124 is programmer */
uint8_t pcmd; /* programmer command */
uint8_t pstat; /* programmer status error flags in reply message */
uint8_t hopsa; /* Ops mode - 7 high address bits of loco to program */
uint8_t lopsa; /* Ops mode - 7 low address bits of loco to program */
uint8_t trk; /* track status. Note: bit 3 shows if prog track is busy */
uint8_t cvh; /* hi 3 bits of CV# and msb of data7 */
uint8_t cvl; /* lo 7 bits of CV# */
uint8_t data7; /* 7 bits of data to program, msb is in cvh above */
uint8_t pad2;
uint8_t pad3;
uint8_t chksum; /* exclusive-or checksum for the message */
} progTaskMsg;
/* Set slot sound functions */
typedef struct locosnd_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t snd; /* sound/function request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoSndMsg;
/* Set slot direction and F0-F4 functions */
typedef struct locodirf_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t dirf; /* direction & function request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoDirfMsg;
/* Set slot speed functions */
typedef struct locospd_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t spd; /* speed request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoSpdMsg;
/* send packet immediate message */
typedef struct sendpkt_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t val7f; /* fixed value of 0x7f */
uint8_t reps; /* repeat count */
uint8_t dhi; /* high bits of data bytes */
uint8_t im1;
uint8_t im2;
uint8_t im3;
uint8_t im4;
uint8_t im5;
uint8_t chksum; /* exclusive-or checksum for the message */
} sendPktMsg;
/* Long ACK message */
typedef struct longack_t {
uint8_t command;
uint8_t opcode; /* op-code of message getting the response (msb=0) */
uint8_t ack1; /* response code */
uint8_t chksum; /* exclusive-or checksum for the message */
} longAckMsg;
/* Write slot status message */
typedef struct slotstat_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t stat; /* status to be written */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotStatusMsg;
/* Move/Link Slot Message */
typedef struct slotmove_t {
uint8_t command;
uint8_t src; /* source slot number for the move/link */
uint8_t dest; /* destination slot for the move/link */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotMoveMsg;
typedef struct
{
uint8_t command; // OPC_PEER_XFER for replies, OPC_IMM_PACKET for commands
uint8_t mesg_size; // 15 bytes
uint8_t SRC; // source
uint8_t DSTL; // destination, low byte
uint8_t DSTH; // destination, high byte
uint8_t ReqId; // Request ID, distinguishes commands
uint8_t PXCT1; // MSBs of following data
uint8_t D0; // Data Bytes
uint8_t D1;
uint8_t D2;
uint8_t D3;
uint8_t D4;
uint8_t D5;
uint8_t D6;
} UhlenbrockMsg;
typedef struct
{
uint8_t command; // OPC_SL_RD_UHLI for replies, OPC_WR_SL_UHLI for commands
uint8_t mesg_size; // 21 bytes
uint8_t unk0;
uint8_t slot; // slot number
uint8_t stat; // slot status
uint8_t adr; // loco address
uint8_t adr2; // loco address high
uint8_t trk; // track status
uint8_t spd; // command speed
uint8_t fhi; // function high bits: F12,F20,F28
uint8_t dirf; // direction and F0-F4 bits
uint8_t snd2; // F5..F11
uint8_t snd3; // F13..F19
uint8_t snd4; // F21..F27
uint8_t unk1; // steps???
uint8_t unk2;
uint8_t unk3;
uint8_t unk4;
uint8_t unk5;
uint8_t unk6;
} UhliSlotMsg;
typedef union {
szMsg sz ;
swRepMsg srp ;
swReqMsg srq ;
inputRepMsg ir ;
slotReqMsg sr ;
rwSlotDataMsg sd ;
fastClockMsg fc ;
progTaskMsg pt ;
locoSndMsg ls ;
locoDirfMsg ldf ;
locoSpdMsg lsp ;
sendPktMsg sp ;
longAckMsg lack ;
slotStatusMsg ss ;
slotMoveMsg sm ;
UhlenbrockMsg ub;
UhliSlotMsg usd;
uint8_t data[32] ;
} lnMsg ;