Skip to content

Commit a4a6294

Browse files
authored
Add files via upload
0 parents  commit a4a6294

File tree

6 files changed

+1029
-0
lines changed

6 files changed

+1029
-0
lines changed

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

LocoNetKS.cpp

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
||
3+
|| @file LocoNetKS.cpp
4+
|| @version 1.0
5+
|| @author Michael Zimmermann
6+
|| @contact michael.zimmermann.sg@t-online.de
7+
||
8+
|| @description
9+
|| | additional functions for class 'LocoNet'
10+
|| #
11+
||
12+
|| @license
13+
|| | Copyright (c) 2021 Michael Zimmermann <http://www.kruemelsoft.privat.t-online.de>
14+
|| | All rights reserved.
15+
|| |
16+
|| | This program is free software: you can redistribute it and/or modify
17+
|| | it under the terms of the GNU General Public License as published by
18+
|| | the Free Software Foundation, either version 3 of the License, or
19+
|| | (at your option) any later version.
20+
|| |
21+
|| | This program is distributed in the hope that it will be useful,
22+
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
23+
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24+
|| | GNU General Public License for more details.
25+
|| |
26+
|| | You should have received a copy of the GNU General Public License
27+
|| | along with this program. If not, see <http://www.gnu.org/licenses/>.
28+
|| #
29+
||
30+
*/
31+
32+
#include <LocoNet.h>
33+
#include "LocoNetKS.h"
34+
35+
#if ARDUINO >= 100
36+
#include "Arduino.h"
37+
#else
38+
#include "WProgram.h"
39+
#endif
40+
41+
//=== LocoNetClassKS ===
42+
LN_STATUS LocoNetClassKS::send(uint8_t OpCode)
43+
{
44+
lnMsg SendPacket;
45+
46+
SendPacket.data[0] = OpCode;
47+
48+
return LocoNet.send(&SendPacket);
49+
}
50+
51+
LN_STATUS LocoNetClassKS::sendSwitchState(uint16_t ui16_swAdr, boolean b_swOn, boolean b_swDirection, uint8_t ui8_OPC)
52+
{
53+
if (!ui16_swAdr || (ui16_swAdr > 2048) || (ui8_OPC < OPC_SW_REQ) || (ui8_OPC > OPC_INPUT_REP))
54+
return LN_UNKNOWN_ERROR;
55+
56+
switch (ui8_OPC)
57+
{
58+
case OPC_SW_REQ: // B0
59+
return LocoNet.requestSwitch(ui16_swAdr, b_swOn, b_swDirection);
60+
case OPC_SW_REP: // B1
61+
return sendSwitchReport(ui16_swAdr, b_swOn, b_swDirection);
62+
case OPC_INPUT_REP: // B2
63+
return sendReportSensor(ui16_swAdr, b_swOn);
64+
}
65+
return LN_UNKNOWN_ERROR;
66+
}
67+
68+
LN_STATUS LocoNetClassKS::sendSwitchReport(uint16_t Address, uint8_t Output, uint8_t Direction)
69+
{ // B1
70+
uint8_t AddrH = (--Address >> 7) & 0x0F;
71+
uint8_t AddrL = Address & 0x7F;
72+
73+
if (Output)
74+
AddrH |= OPC_SW_REQ_OUT;
75+
76+
if (Direction)
77+
AddrH |= OPC_SW_REQ_DIR;
78+
79+
return LocoNet.send(OPC_SW_REP, AddrL, AddrH);
80+
}
81+
82+
LN_STATUS LocoNetClassKS::sendReportSensor(uint16_t Address, uint8_t State)
83+
{ // B2
84+
byte AddrH = ((--Address >> 8) & 0x0F);
85+
byte AddrL = (Address >> 1) & 0x7F;
86+
if (Address % 2)
87+
AddrH |= OPC_INPUT_REP_SW;
88+
89+
if (State)
90+
AddrH |= OPC_INPUT_REP_HI;
91+
92+
return LocoNet.send(OPC_INPUT_REP, AddrL, AddrH);
93+
}
94+
//=== end LocoNetClassKS ===
95+
96+
//=== LocoNetFastClockClassKS ===
97+
/* this class is copied from original LocoNetFastClockClass in file loconet.cpp (Version 1.1.13)
98+
* modification is made for new flag "FC_FLAG_NOTIFY_JMRI" (see also commenst "added")
99+
*/
100+
#define FC_FLAG_DCS100_COMPATIBLE_SPEED 0x01
101+
#define FC_FLAG_MINUTE_ROLLOVER_SYNC 0x02
102+
#define FC_FLAG_NOTIFY_FRAC_MINS_TICK 0x04
103+
#define FC_FLAG_NOTIFY_JMRI 0x08 // new for JMRI
104+
#define FC_FRAC_MIN_BASE 0x3FFF
105+
#define FC_FRAC_RESET_HIGH 0x78
106+
#define FC_FRAC_RESET_LOW 0x6D
107+
#define FC_TIMER_TICKS 65 // 65ms ticks
108+
#define FC_TIMER_TICKS_REQ 250 // 250ms waiting for Response to FC Req
109+
110+
void LocoNetFastClockClassKS::init(uint8_t DCS100CompatibleSpeed, uint8_t CorrectDCS100Clock, uint8_t NotifyFracMin)
111+
{
112+
fcState = FC_ST_IDLE;
113+
114+
fcFlags = 0;
115+
if (DCS100CompatibleSpeed)
116+
fcFlags |= FC_FLAG_DCS100_COMPATIBLE_SPEED;
117+
118+
if (CorrectDCS100Clock)
119+
fcFlags |= FC_FLAG_MINUTE_ROLLOVER_SYNC;
120+
121+
if (NotifyFracMin)
122+
fcFlags |= FC_FLAG_NOTIFY_FRAC_MINS_TICK;
123+
}
124+
125+
// new method
126+
void LocoNetFastClockClassKS::initJMRI(uint8_t IsJMRI)
127+
{
128+
fcLastfrac_minsh = 0;
129+
if (IsJMRI)
130+
fcFlags |= FC_FLAG_NOTIFY_JMRI;
131+
}
132+
133+
void LocoNetFastClockClassKS::poll(void)
134+
{
135+
LocoNet.send(OPC_RQ_SL_DATA, FC_SLOT, 0);
136+
}
137+
138+
void LocoNetFastClockClassKS::doNotify(uint8_t Sync)
139+
{
140+
if (notifyFastClock)
141+
notifyFastClock(fcSlotData.clk_rate, fcSlotData.days,
142+
(fcSlotData.hours_24 >= (128 - 24)) ? fcSlotData.hours_24 - (128 - 24) : fcSlotData.hours_24 % 24,
143+
fcSlotData.mins_60 - (127 - 60), Sync);
144+
}
145+
146+
// changed method
147+
void LocoNetFastClockClassKS::processMessage(lnMsg* LnPacket)
148+
{
149+
if ((LnPacket->fc.slot == FC_SLOT) && ((LnPacket->fc.command == OPC_WR_SL_DATA) || (LnPacket->fc.command == OPC_SL_RD_DATA)))
150+
{
151+
if ((LnPacket->fc.clk_cntrl & 0x40)
152+
// +++ added because JMRI is sending 'fc.clk_cntrl = 0x00' (Bit 6 not set)
153+
|| (fcFlags & FC_FLAG_NOTIFY_JMRI))
154+
// added end
155+
{
156+
if (fcState >= FC_ST_REQ_TIME)
157+
{
158+
memcpy(&fcSlotData, &LnPacket->fc, sizeof(fastClockMsg));
159+
// ++ added for JMRI and use in "process66msActions"
160+
fcLastfrac_minsh = fcSlotData.frac_minsh;
161+
// added end
162+
doNotify(1);
163+
164+
if (notifyFastClockFracMins && fcFlags & FC_FLAG_NOTIFY_FRAC_MINS_TICK)
165+
notifyFastClockFracMins(FC_FRAC_MIN_BASE - ((fcSlotData.frac_minsh << 7) + fcSlotData.frac_minsl));
166+
167+
fcState = FC_ST_READY;
168+
}
169+
}
170+
else
171+
fcState = FC_ST_DISABLED;
172+
}
173+
}
174+
175+
// changed method
176+
void LocoNetFastClockClassKS::process66msActions(void)
177+
{
178+
// If we are all initialised and ready then increment accumulators
179+
if (fcState == FC_ST_READY)
180+
{
181+
fcSlotData.frac_minsl += fcSlotData.clk_rate;
182+
if (fcSlotData.frac_minsl & 0x80)
183+
{
184+
fcSlotData.frac_minsl &= ~0x80;
185+
186+
fcSlotData.frac_minsh++;
187+
if ((fcSlotData.frac_minsh & 0x80)
188+
// +++ added because JMRI starts with 'fcSlotData.frac_minsh = 3' instead of FC_FRAC_RESET_HIGH (0x78)
189+
// therefore fcSlotData.frac_minsh is always less than 0x80
190+
// and fcSlotData.frac_minsh comes in maximum up to 10, independant from fcSlotdata.clk_rate
191+
|| ((fcFlags & FC_FLAG_NOTIFY_JMRI) &&
192+
(fcSlotData.frac_minsh > (fcLastfrac_minsh + 6)) &&
193+
(fcSlotData.frac_minsh < (FC_FRAC_RESET_HIGH + (fcFlags & FC_FLAG_DCS100_COMPATIBLE_SPEED)))
194+
)
195+
)
196+
// added end
197+
{
198+
// For the next cycle prime the fraction of a minute accumulators
199+
fcSlotData.frac_minsl = FC_FRAC_RESET_LOW;
200+
201+
// If we are in FC_FLAG_DCS100_COMPATIBLE_SPEED mode we need to run faster
202+
// by reducong the FRAC_MINS duration count by 128
203+
fcSlotData.frac_minsh = FC_FRAC_RESET_HIGH + (fcFlags & FC_FLAG_DCS100_COMPATIBLE_SPEED);
204+
205+
fcSlotData.mins_60++;
206+
if (fcSlotData.mins_60 >= 0x7F)
207+
{
208+
fcSlotData.mins_60 = 127 - 60;
209+
210+
fcSlotData.hours_24++;
211+
if (fcSlotData.hours_24 & 0x80)
212+
{
213+
fcSlotData.hours_24 = 128 - 24;
214+
215+
fcSlotData.days++;
216+
}
217+
}
218+
219+
// We either send a message out onto the LocoNet to change the time,
220+
// which we will also see and act on or just notify our user
221+
// function that our internal time has changed.
222+
if (fcFlags & FC_FLAG_MINUTE_ROLLOVER_SYNC)
223+
{
224+
fcSlotData.command = OPC_WR_SL_DATA;
225+
LocoNet.send((lnMsg*)&fcSlotData);
226+
}
227+
else
228+
doNotify(0);
229+
}
230+
}
231+
232+
if (notifyFastClockFracMins && (fcFlags & FC_FLAG_NOTIFY_FRAC_MINS_TICK))
233+
notifyFastClockFracMins(FC_FRAC_MIN_BASE - ((fcSlotData.frac_minsh << 7) + fcSlotData.frac_minsl));
234+
}
235+
236+
if (fcState == FC_ST_IDLE)
237+
{
238+
LocoNet.send(OPC_RQ_SL_DATA, FC_SLOT, 0);
239+
fcState = FC_ST_REQ_TIME;
240+
}
241+
}
242+
//=== end LocoNetFastClockClassKS ===

LocoNetKS.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
||
3+
|| @file LocoNetKS.h
4+
|| @version 1.0
5+
|| @author Michael Zimmermann
6+
|| @contact michael.zimmermann.sg@t-online.de
7+
||
8+
|| @description
9+
|| | additional functions for 'LocoNetClass' and 'LocoNetFastClockClass' from Loconet-Library, published by MRRwA (previously EmbeddedLocoNet)
10+
|| #
11+
||
12+
|| @license
13+
|| | Copyright (c) 2021 Michael Zimmermann <http://www.kruemelsoft.privat.t-online.de>
14+
|| | All rights reserved.
15+
|| |
16+
|| | This program is free software: you can redistribute it and/or modify
17+
|| | it under the terms of the GNU General Public License as published by
18+
|| | the Free Software Foundation, either version 3 of the License, or
19+
|| | (at your option) any later version.
20+
|| |
21+
|| | This program is distributed in the hope that it will be useful,
22+
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
23+
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24+
|| | GNU General Public License for more details.
25+
|| |
26+
|| | You should have received a copy of the GNU General Public License
27+
|| | along with this program. If not, see <http://www.gnu.org/licenses/>.
28+
|| |
29+
|| | (see also: licenseinformations in file 'loconet.h' published by MRRwA (previously EmbeddedLocoNet))
30+
|| #
31+
||
32+
*/
33+
34+
#ifndef _KS_LOCONETKS_H
35+
#define _KS_LOCONETKS_H
36+
37+
class LocoNetClassKS {
38+
public:
39+
LocoNetClassKS() {};
40+
41+
LN_STATUS send(uint8_t OpCode);
42+
43+
LN_STATUS sendSwitchState(uint16_t ui16_swAdr, boolean b_swOn, boolean b_swDirection, uint8_t ui8_OPC);
44+
45+
protected:
46+
// B1
47+
LN_STATUS sendSwitchReport(uint16_t Address, uint8_t Output, uint8_t Direction);
48+
// B2
49+
LN_STATUS sendReportSensor(uint16_t Address, uint8_t State);
50+
};
51+
52+
extern LocoNetClassKS LocoNetKS;
53+
54+
class LocoNetFastClockClassKS
55+
{
56+
private:
57+
FC_STATE fcState; // State of the Fast Clock Slave
58+
uint8_t fcFlags; // Storage of the option flags passed into initFastClock()
59+
fastClockMsg fcSlotData; // Primary storage for the Fast Clock slot data
60+
uint8_t fcLastPeriod; // Period of last tick so we can alternate between
61+
uint8_t fcLastfrac_minsh; // new
62+
63+
void doNotify(uint8_t Sync);
64+
65+
public:
66+
void init(uint8_t DCS100CompatibleSpeed, uint8_t CorrectDCS100Clock, uint8_t NotifyFracMin);
67+
void initJMRI(uint8_t IsJMRI); // new
68+
void poll(void);
69+
void processMessage(lnMsg* LnPacket); // modified
70+
void process66msActions(void); // modified
71+
72+
FC_STATE getFastClockState() { return fcState; } // new, used in debug-cases
73+
fastClockMsg getFastClockSlotData() { return fcSlotData; } // new, used in debug-cases
74+
};
75+
76+
#endif

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# LocoNetKS
2+
3+
This is a simple library with additional functions I missed in the original LocoNET-library for usage with Arduino-platform.<br>
4+
5+
In addition, I copied the original LocoNetFastClockClass and modified it.<br>
6+
This was necessary because the original class doesnot work for me during the development of the [Nebenuhr](Nebenuhr), a FastClock-Slave which has to work with [JMRI](https://www.jmri.org/)<br>
7+
8+
Needed base-library can be found on https://github.com/mrrwa/LocoNet
9+
10+
Tested on ATmega328.

keywords.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#######################################
2+
# Syntax Coloring Map For Buttons
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
LocoNetClassKS KEYWORD1
10+
LocoNetKS KEYWORD1
11+
LN_STATUS KEYWORD1
12+
13+
#######################################
14+
# Methods and Functions (KEYWORD2)
15+
#######################################
16+
17+
send KEYWORD2
18+
sendSwitchState KEYWORD2

library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=LocoNetKS
2+
version=1.0
3+
author=michael <Kruemelbahn2000@hotmail.de>
4+
maintainer=michael <Kruemelbahn2000@hotmail.de>
5+
sentence=additional functions for class LocoNet (see http://mrrwa.org/loconet-interface/)
6+
paragraph=This library allows extends the interface to the LocoNet-Library
7+
category=Communication
8+
url=http://www.kruemelsoft.privat.t-online.de
9+
architectures=avr

0 commit comments

Comments
 (0)