package de.uniluebeck.itm.wsn.drivers.jennic; import com.google.common.util.concurrent.TimeLimiter; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import de.uniluebeck.itm.util.StringUtils; import de.uniluebeck.itm.wsn.drivers.core.ChipType; import de.uniluebeck.itm.wsn.drivers.core.exception.RamReadFailedException; import de.uniluebeck.itm.wsn.drivers.core.exception.UnexpectedResponseException; import de.uniluebeck.itm.wsn.drivers.core.operation.GetChipTypeOperation; import de.uniluebeck.itm.wsn.drivers.core.operation.OperationListener; import de.uniluebeck.itm.wsn.drivers.core.operation.TimeLimitedOperation; import de.uniluebeck.itm.wsn.drivers.core.serialport.SerialPortProgrammingMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import static de.uniluebeck.itm.util.StringUtils.toHexString; public class JennicGetChipTypeOperation extends TimeLimitedOperation<ChipType> implements GetChipTypeOperation { private static final Logger log = LoggerFactory.getLogger(JennicGetChipTypeOperation.class); private final JennicHelper helper; @Inject public JennicGetChipTypeOperation(final TimeLimiter timeLimiter, final JennicHelper helper, @Assisted final long timeoutMillis, @Assisted @Nullable final OperationListener<ChipType> operationCallback) { super(timeLimiter, timeoutMillis, operationCallback); this.helper = helper; } private ChipType determineChipType(byte s, byte t) { if (s == 0x00 && t == 0x20) { return ChipType.JN513X; } else if (s == 0x10 && t == 0x00) { return ChipType.JN513XR1; } else if (s == 0x20 && t == 0x00) { return ChipType.JN5121; } else { log.warn("Defaulted to chip type JN5121. Identification may be wrong."); return ChipType.UNKNOWN; } } @Override @SerialPortProgrammingMode protected ChipType callInternal() throws Exception { log.trace("Getting ChipType..."); ChipType chipType = ChipType.UNKNOWN; helper.sendBootloaderMessage(Messages.chipIdMessage()); try { // read chip type read response byte[] res = helper.receiveBootloaderReply(Messages.CHIP_ID_RESPONSE); if (log.isTraceEnabled()) { String S = "received: (len=" + res.length + ") "; for (int i = 0; i < res.length; i++) { S = S + "res[" + i + "]=" + StringUtils.toHexString(res[i]) + " "; } log.trace(S); } if (res.length == 6) { if (((res[1] == 0) && (res[2] == 0x10) && (res[3] == 0x40) && (res[4] == 0x46) && (res[5] == (byte) 0x86)) || ((res[1] == 0) && (res[2] == 0x10) && (res[3] == (byte) 0x80) && (res[4] == 0x46) && (res[5] == (byte) 0x86))) { chipType = ChipType.JN5148; log.debug("Chip identified as " + chipType + "."); } else { log.error("BYTES incorrect res[1]=" + res[1] + " != " + 0 + "res[2]=" + res[2] + " != " + 0x10 + "res[3]=" + res[3] + " != " + 0x40 + "res[4]=" + res[4] + " != " + 0x46 + "res[5]=" + res[5] + " != " + (byte) 0x86 ); } } else { log.error("length incorrect"); } } catch (UnexpectedResponseException e) { // send chip type read request helper.sendBootloaderMessage(Messages.ramReadRequestMessage(0x100000FC, 0x0004)); // read chip type read response final byte[] response = helper.receiveBootloaderReply(Messages.RAM_READ_RESPONSE); // Throw error if reading failed if (response[1] != 0x00) { if (log.isErrorEnabled()) { log.error("Failed to read chip type: should be 0x00, yet it is: ", toHexString(response[1])); } throw new RamReadFailedException(); } chipType = determineChipType(response[2], response[3]); log.trace("Chip identified as {} (received {} {})", new Object[]{chipType, toHexString(response[2]), toHexString(response[3])} ); } return chipType; } }