Skip to content

Commit

Permalink
Send AMD when AME is received (#205)
Browse files Browse the repository at this point in the history
When an AME frame is received with empty payload or a payload matching the Node ID, generates and sends a response frame with an AMD for our node ID (if the alias allocation process is already completed).

===

* Send AMD when AME is received

* check AME, ensure addressing

* typo

* don't reuse argument variable
  • Loading branch information
bobjacobsen committed Sep 21, 2022
1 parent a1db161 commit 64a191e
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 121 deletions.
43 changes: 33 additions & 10 deletions src/org/openlcb/can/NIDaAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

/**
* Implementation of Node ID Alias assignment computation.
* Provides and processes frames, but other code must move them
* Provides and processes frames, but other code must move them
* to and from the actual interface.
* It also requires subclassing to provide a timer function.
*
*
* @author Bob Jacobsen Copyright 2009, 2010
*/
public class NIDaAlgorithm implements CanFrameListener {
Expand Down Expand Up @@ -44,9 +44,9 @@ public NIDaAlgorithm(NodeID n) {

public NIDaAlgorithm(NodeID n, CanFrameListener sendInterface) {
this(n);

this.sendInterface = sendInterface;

synchronized(NIDaAlgorithm.class) {
if (timer == null ) {
timer = new Timer("OpenLCB NIDaAlgorithm Timer");
Expand Down Expand Up @@ -78,16 +78,36 @@ public OpenLcbCanFrame nextFrame() {
index++;
return f;
}

public int getNIDa() {
return nida.getNIDa();
}

/**
* @return True if frame matches current NodeID
*/
boolean compareDataAndNodeID(OpenLcbCanFrame f) {
// TODO: check for empty data or matching NodeID
return new NodeID(f.getData()).equals(nid);
}

public void processFrame(OpenLcbCanFrame f) {
if (f == null) {
return; // as a convenience, ignore
}

if (f.isAliasMapEnquiry()) {
// complete == true is (mostly) Permitted state
if (complete) {
if (f.data.length == 0 || compareDataAndNodeID(f)) {
// AME for us, reply with AMD
OpenLcbCanFrame frame = new OpenLcbCanFrame(nida.getNIDa());
frame.setAMD(nida.getNIDa(), nid);
sendInterface.send(frame);
}
}
}

// System.out.println("process "+Integer.toHexString(f.getNodeIDa())
// +" vs our "+Integer.toHexString(nida.getNIDa()));

Expand All @@ -106,7 +126,7 @@ public void processFrame(OpenLcbCanFrame f) {
cancelTimer();
}
}

public boolean isComplete() {
return complete;
}
Expand All @@ -120,7 +140,7 @@ protected void cancelTimer() {
scheduleTimer(0);
}
}

protected void timerExpired() {
if (index == 0) {
while (index < 4) {
Expand All @@ -135,9 +155,12 @@ protected void timerExpired() {
}
}
}

int index = 0;

// NodeID of this node (node for which alias algorithm running)
NodeID nid;

NIDa nida;
boolean complete = false;

Expand All @@ -148,12 +171,12 @@ public void send(CanFrame frame) {

public void dispose(){
cancelTimer(); // dispose of the timer task

synchronized(NIDaAlgorithm.class) {
timer.cancel();
timer = null;
}

done = null;
complete = true;
}
Expand Down
82 changes: 48 additions & 34 deletions src/org/openlcb/can/OpenLcbCanFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ public OpenLcbCanFrame(CanFrame frame) {
int id; // 29 bit header
int length;
byte[] data = new byte[8];

int nodeAlias;

public int getHeader() { return id; }
public void setHeader(int id) { this.id = id; }
public byte[] getData() {

public byte[] getData() {
// return a copy of appropriate length
byte[] copy = new byte[length];
System.arraycopy(data,0,copy,0,length);
return copy;
return copy;
}
public void setData(byte[] b) { data = b; length = b.length;}
public long bodyAsLong() {
Expand All @@ -65,22 +65,22 @@ public long dataAsLong() {
return retval;
}
public boolean isExtended() { return true; }

public boolean isRtr() { return false; }

public int getNumDataElements() { return length; }
public int getElement(int n) { return DatagramUtils.byteToInt(data[n]); }

// bit 1
static final int MASK_FRAME_TYPE = 0x08000000;

// bit 17-28
static final int MASK_SRC_ALIAS = 0x00000FFF;

// bit 2-16
static final int MASK_VARIABLE_FIELD = 0x07FFF000;
static final int SHIFT_VARIABLE_FIELD = 12;

// bit 2-4, at the top of the variable field
static final int MASK_OPENLCB_FORMAT = 0x07000;
static final int SHIFT_OPENLCB_FORMAT = 12;
Expand All @@ -96,7 +96,7 @@ void setSourceAlias(int a) {
id &= ~MASK_SRC_ALIAS;
id = id | (a & MASK_SRC_ALIAS);
}

int getSourceAlias() {
return (int)(id & MASK_SRC_ALIAS);
}
Expand All @@ -118,17 +118,17 @@ void setContinuation(boolean first, boolean last) {
}

void setFrameTypeCAN() {
id &= ~MASK_FRAME_TYPE;
id &= ~MASK_FRAME_TYPE;
}

boolean isFrameTypeCAN() {
return (id & MASK_FRAME_TYPE) == 0x00000000L;
}

void setFrameTypeOpenLcb() {
id |= MASK_FRAME_TYPE;
id |= MASK_FRAME_TYPE;
}

boolean isFrameTypeOpenLcb() {
return (id & MASK_FRAME_TYPE) == MASK_FRAME_TYPE;
}
Expand All @@ -141,11 +141,11 @@ void setVariableField(int f) {
int getVariableField() {
return (int)(id & MASK_VARIABLE_FIELD) >> SHIFT_VARIABLE_FIELD;
}

// end of basic message structure

// start of CAN-level messages

static final int RIM_VAR_FIELD = 0x0700;
static final int AMD_VAR_FIELD = 0x0701;
static final int AME_VAR_FIELD = 0x0702;
Expand All @@ -154,7 +154,7 @@ int getVariableField() {
void setCIM(int i, int testval, int alias) {
init(alias);
setFrameTypeCAN();
int var = (( (0x7-i) & 7) << 12) | (testval & 0xFFF);
int var = (( (0x7-i) & 7) << 12) | (testval & 0xFFF);
setVariableField(var);
length=0;
}
Expand Down Expand Up @@ -198,6 +198,20 @@ void setAMR(int alias, NodeID nid) {
data[5] = val[5];
}

void setAMD(int alias, NodeID nid) {
init(alias);
setFrameTypeCAN();
setVariableField(AMD_VAR_FIELD);
length=6;
byte[] val = nid.getContents();
data[0] = val[0];
data[1] = val[1];
data[2] = val[2];
data[3] = val[3];
data[4] = val[4];
data[5] = val[5];
}

void setAME(int alias, @Nullable NodeID nid) {
init(alias);
setFrameTypeCAN();
Expand All @@ -217,9 +231,9 @@ void setAME(int alias, @Nullable NodeID nid) {
}

// end of CAN-level messages

// start of OpenLCB format support

int getOpenLcbFormat() {
return (getVariableField() & MASK_OPENLCB_FORMAT) >> SHIFT_OPENLCB_FORMAT;
}
Expand All @@ -228,29 +242,29 @@ void setOpenLcbFormat(int i) {
int now = getVariableField() & ~MASK_OPENLCB_FORMAT;
setVariableField( ((i << SHIFT_OPENLCB_FORMAT) & MASK_OPENLCB_FORMAT) | now);
}

void setOpenLcbMTI(int mti) {
setFrameTypeOpenLcb();
setVariableField(mti | (FRAME_FORMAT_MTI << 12) );
}

boolean isOpenLcbMTI(int mti) {
return isFrameTypeOpenLcb()
return isFrameTypeOpenLcb()
&& ( getOpenLcbFormat() == FRAME_FORMAT_MTI )
&& ( (getVariableField()&~MASK_OPENLCB_FORMAT) == mti );
}

// end of OpenLCB format and decode support

// start of OpenLCB messages

void setPCEventReport(EventID eid) {
init(nodeAlias);
setOpenLcbMTI(MessageTypeIdentifier.ProducerConsumerEventReport.mti());
length=8;
loadFromEid(eid);
}

boolean isPCEventReport() {
return isOpenLcbMTI(MessageTypeIdentifier.ProducerConsumerEventReport.mti());
}
Expand Down Expand Up @@ -279,19 +293,19 @@ void setInitializationComplete(int alias, NodeID nid) {
data[4] = val[4];
data[5] = val[5];
}

boolean isInitializationComplete() {
return isOpenLcbMTI(MessageTypeIdentifier.InitializationComplete.mti());
}

EventID getEventID() {
return new EventID(data);
}

NodeID getNodeID() {
return new NodeID(data);
}

boolean isVerifyNID() {
return isOpenLcbMTI(MessageTypeIdentifier.VerifyNodeIdGlobal.mti());
}
Expand Down Expand Up @@ -357,10 +371,10 @@ void loadFromEid(EventID eid) {
data[6] = val[6];
data[7] = val[7];
}

// general, but not efficient
boolean isDatagram() {
return isFrameTypeOpenLcb()
return isFrameTypeOpenLcb()
&& ( (getOpenLcbFormat() == FRAME_FORMAT_ADDRESSED_DATAGRAM_ALL)
|| (getOpenLcbFormat() == FRAME_FORMAT_ADDRESSED_DATAGRAM_FIRST)
|| (getOpenLcbFormat() == FRAME_FORMAT_ADDRESSED_DATAGRAM_MID)
Expand Down Expand Up @@ -432,7 +446,7 @@ public int hashCode(){
// hash codes must be the same when equals returns true
// but will not allow good hashing of OpenLcbCanFrames
}

public String toString() {
String retval = "[0x"+Integer.toHexString(id)+"]";
for (int i = 0; i<length; i++) {
Expand All @@ -446,7 +460,7 @@ public String toString() {
/**
* OpenLCB CAN MTI format bits
*/
static final int FRAME_FORMAT_MTI = 1;
static final int FRAME_FORMAT_MTI = 1;
//
//
static final int FRAME_FORMAT_ADDRESSED_DATAGRAM_ALL = 2;
Expand Down
Loading

0 comments on commit 64a191e

Please sign in to comment.