mirror of https://github.com/contiki-ng/mspsim
Merge pull request #30 from nfi/updates-from-contiki-os-mspsim-submodule
Updates from contiki os mspsim submodule
This commit is contained in:
commit
13f10ee00e
|
|
@ -3,8 +3,8 @@
|
|||
*.class
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
./*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
|
|
@ -75,6 +75,15 @@ public class Main {
|
|||
if ("exp5438".equals(platform)) {
|
||||
return "se.sics.mspsim.platform.ti.Exp5438Node";
|
||||
}
|
||||
if ("exp1101".equals(platform)) {
|
||||
return "se.sics.mspsim.platform.ti.Exp1101Node";
|
||||
}
|
||||
if ("exp1120".equals(platform)) {
|
||||
return "se.sics.mspsim.platform.ti.Exp1120Node";
|
||||
}
|
||||
if ("cc430".equals(platform)) {
|
||||
return "se.sics.mspsim.platform.ti.CC430Node";
|
||||
}
|
||||
// Try to guess the node type.
|
||||
return "se.sics.mspsim.platform." + platform + '.'
|
||||
+ Character.toUpperCase(platform.charAt(0))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,905 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package se.sics.mspsim.chip;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOPort.PinState;
|
||||
import se.sics.mspsim.core.MSP430Core;
|
||||
import se.sics.mspsim.core.TimeEvent;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
|
||||
public class CC1101 extends Radio802154 implements USARTListener {
|
||||
protected boolean DEBUG = false;
|
||||
|
||||
/* cc1101-const.h: Configuration registers */
|
||||
public static final int CC1101_IOCFG1 = 0x01;
|
||||
public static final int CC1101_IOCFG0 = 0x02;
|
||||
public static final int CC1101_FIFOTHR = 0x03;
|
||||
public static final int CC1101_SYNC1 = 0x04;
|
||||
public static final int CC1101_SYNC0 = 0x05;
|
||||
public static final int CC1101_PKTLEN = 0x06;
|
||||
public static final int CC1101_PKTCTRL1 = 0x07;
|
||||
public static final int CC1101_PKTCTRL0 = 0x08;
|
||||
public static final int CC1101_ADDR = 0x09;
|
||||
public static final int CC1101_CHANNR = 0x0A;
|
||||
public static final int CC1101_FSCTRL1 = 0x0B;
|
||||
public static final int CC1101_FSCTRL0 = 0x0C;
|
||||
public static final int CC1101_FREQ2 = 0x0D;
|
||||
public static final int CC1101_FREQ1 = 0x0E;
|
||||
public static final int CC1101_FREQ0 = 0x0F;
|
||||
public static final int CC1101_MDMCFG4 = 0x10;
|
||||
public static final int CC1101_MDMCFG3 = 0x11;
|
||||
public static final int CC1101_MDMCFG2 = 0x12;
|
||||
public static final int CC1101_MDMCFG1 = 0x13;
|
||||
public static final int CC1101_MDMCFG0 = 0x14;
|
||||
public static final int CC1101_DEVIATN = 0x15;
|
||||
public static final int CC1101_MCSM2 = 0x16;
|
||||
public static final int CC1101_MCSM1 = 0x17;
|
||||
public static final int CC1101_MCSM0 = 0x18;
|
||||
public static final int CC1101_FOCCFG = 0x19;
|
||||
public static final int CC1101_BSCFG = 0x1A;
|
||||
public static final int CC1101_AGCCTRL2 = 0x1B;
|
||||
public static final int CC1101_AGCCTRL1 = 0x1C;
|
||||
public static final int CC1101_AGCCTRL0 = 0x1D;
|
||||
public static final int CC1101_WOREVT1 = 0x1E;
|
||||
public static final int CC1101_WOREVT0 = 0x1F;
|
||||
public static final int CC1101_WORCTRL = 0x20;
|
||||
public static final int CC1101_FREND1 = 0x21;
|
||||
public static final int CC1101_FREND0 = 0x22;
|
||||
public static final int CC1101_FSCAL3 = 0x23;
|
||||
public static final int CC1101_FSCAL2 = 0x24;
|
||||
public static final int CC1101_FSCAL1 = 0x25;
|
||||
public static final int CC1101_FSCAL0 = 0x26;
|
||||
public static final int CC1101_RCCTRL1 = 0x27;
|
||||
public static final int CC1101_RCCTRL0 = 0x28;
|
||||
public static final int CC1101_FSTEST = 0x29;
|
||||
public static final int CC1101_PTEST = 0x2A;
|
||||
public static final int CC1101_AGCTEST = 0x2B;
|
||||
public static final int CC1101_TEST2 = 0x2C;
|
||||
public static final int CC1101_TEST1 = 0x2D;
|
||||
public static final int CC1101_TEST0 = 0x2E;
|
||||
public static final int CC1101_PARTNUM = 0x30;
|
||||
public static final int CC1101_VERSION = 0x31;
|
||||
public static final int CC1101_FREQEST = 0x32;
|
||||
public static final int CC1101_LQI = 0x33;
|
||||
public static final int CC1101_RSSI = 0x34;
|
||||
public static final int CC1101_MARCSTATE = 0x35;
|
||||
public static final int CC1101_WORTIME1 = 0x36;
|
||||
public static final int CC1101_WORTIME0 = 0x37;
|
||||
public static final int CC1101_PKTSTATUS = 0x38;
|
||||
public static final int CC1101_VCO_VC_DAC = 0x39;
|
||||
public static final int CC1101_TXBYTES = 0x3A;
|
||||
public static final int CC1101_RXBYTES = 0x3B;
|
||||
public static final int CC1101_RCCTRL1_STATUS = 0x3C;
|
||||
public static final int CC1101_RCCTRL0_STATUS = 0x3D;
|
||||
public static final int CC1101_PATABLE = 0x3E;
|
||||
public static final int CC1101_PA_M30 = 0x03;
|
||||
public static final int CC1101_PA_M20 = 0x0E;
|
||||
public static final int CC1101_PA_M15 = 0x1E;
|
||||
public static final int CC1101_PA_M10 = 0x27;
|
||||
public static final int CC1101_PA_M6 = 0x38;
|
||||
public static final int CC1101_PA_0 = 0x8E;
|
||||
public static final int CC1101_PA_5 = 0x84;
|
||||
public static final int CC1101_PA_7 = 0xCC;
|
||||
public static final int CC1101_PA_10 = 0xC3;
|
||||
public static final int CC1101_PA_11 = 0xC0;
|
||||
|
||||
public final static int CC1101_TXFIFO = 0x3F;
|
||||
public final static int CC1101_RXFIFO = 0x3F;
|
||||
|
||||
/* Strobe commands */
|
||||
public static final int CC1101_SRES = 0x30;
|
||||
public static final int CC1101_SFSTXON = 0x31;
|
||||
public static final int CC1101_SXOFF = 0x32;
|
||||
public static final int CC1101_SCAL = 0x33;
|
||||
public static final int CC1101_SRX = 0x34;
|
||||
public static final int CC1101_STX = 0x35;
|
||||
public static final int CC1101_SIDLE = 0x36;
|
||||
public static final int CC1101_SAFC = 0x37;
|
||||
public static final int CC1101_SWOR = 0x38;
|
||||
public static final int CC1101_SPWD = 0x39;
|
||||
public static final int CC1101_SFRX = 0x3A;
|
||||
public static final int CC1101_SFTX = 0x3B;
|
||||
public static final int CC1101_SWORRST = 0x3C;
|
||||
public static final int CC1101_SNOP = 0x3D;
|
||||
|
||||
public static final int CC1101_PKTSTATUS_CS_BIT = (1 << 6);
|
||||
public static final int CC1101_PKTSTATUS_CCA_BIT = (1 << 4);
|
||||
|
||||
public static enum CC1101RadioState {
|
||||
CC1101_STATE_SLEEP(0x00)/* 0 */,
|
||||
CC1101_STATE_IDLE(0x01),
|
||||
CC1101_STATE_XOFF(0x02),
|
||||
CC1101_STATE_VCOON_MC(0x03),
|
||||
CC1101_STATE_REGON_MC(0x04),
|
||||
CC1101_STATE_MANCAL(0x05),
|
||||
CC1101_STATE_VCOON(0x06),
|
||||
CC1101_STATE_REGON(0x07),
|
||||
CC1101_STATE_STARTCAL(0x08),
|
||||
CC1101_STATE_BWBOOST(0x09),
|
||||
CC1101_STATE_FS_LOCK(0x0A),
|
||||
CC1101_STATE_IFADCON(0x0B),
|
||||
CC1101_STATE_ENDCAL(0x0C),
|
||||
CC1101_STATE_RX(0x0D) /* 13 */,
|
||||
CC1101_STATE_RX_END(0x0E),
|
||||
CC1101_STATE_RX_RST(0x0F),
|
||||
CC1101_STATE_TXRX_SWITCH(0x10),
|
||||
CC1101_STATE_RXFIFO_OVERFLOW(0x11),
|
||||
CC1101_STATE_FSTXON(0x12),
|
||||
CC1101_STATE_TX(0x13),
|
||||
CC1101_STATE_TX_END(0x14),
|
||||
CC1101_STATE_RXTX_SWITCH(0x15),
|
||||
CC1101_STATE_TXFIFO_UNDERFLOW(0x16);
|
||||
|
||||
private final int state;
|
||||
|
||||
CC1101RadioState(int stateNo) {
|
||||
state = stateNo;
|
||||
}
|
||||
|
||||
public int getStateAsInt() {
|
||||
return state | (0b10 << 5); /* TODO 2 pin state not implemented */
|
||||
}
|
||||
};
|
||||
private TimeEvent sendEvent = new TimeEvent(0, "CC1101 Send") {
|
||||
public void execute(long t) {
|
||||
txNext();
|
||||
}
|
||||
};
|
||||
|
||||
public final static double FREQUENCY_CHANNEL_0 = 902; /* MHz */
|
||||
public final static double FREQUENCY_CHANNEL_WIDTH = 0.125; /* MHz */
|
||||
|
||||
public final static int CCA_THRESHOLD = -95;
|
||||
|
||||
private boolean triggerGDO0onSynch = false;
|
||||
private boolean triggerGDO0onFifoThreshold = true;
|
||||
|
||||
private StateListener stateListener = null;
|
||||
private ReceiverListener receiverListener = null;
|
||||
|
||||
private boolean currentRssiValid;
|
||||
private int currentRssiReg = 0;
|
||||
|
||||
private CC1101RadioState state = null;
|
||||
|
||||
protected List<Byte> txfifo = new ArrayList<Byte>();
|
||||
protected List<Byte> rxfifo = new ArrayList<Byte>();
|
||||
|
||||
protected int[] registers = new int[64];
|
||||
protected int[] memory = new int[512];
|
||||
|
||||
private boolean chipSelect;
|
||||
|
||||
private IOPort gdo0Port = null;
|
||||
private int gdo0Pin = -1;
|
||||
private IOPort gdo2Port = null;
|
||||
private int gdo2Pin = -1;
|
||||
|
||||
private int channel = 0;
|
||||
|
||||
public CC1101(MSP430Core cpu) {
|
||||
super("CC1101", "Radio", cpu);
|
||||
reset();
|
||||
}
|
||||
|
||||
public long getBitRate() {
|
||||
/* This function returns the current bit rate of the radio. It
|
||||
should use the CC1101 configuration registers to figure out
|
||||
the actual bit rate, but this code simply checks for two
|
||||
specific configurations that correspond to known bit
|
||||
rates. */
|
||||
if(registers[CC1101_MDMCFG3] == 0xf8) {
|
||||
return 50000;
|
||||
} else if(registers[CC1101_MDMCFG3] == 0x3b) {
|
||||
return 250000;
|
||||
}
|
||||
return 250000;
|
||||
}
|
||||
|
||||
public double getInterByteDelayMs() {
|
||||
return 1000.0 / (getBitRate() / 8.0);
|
||||
}
|
||||
|
||||
public void log(String str) {
|
||||
if (DEBUG) {
|
||||
System.out.println(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void strobe(int cmd) {
|
||||
switch (cmd) {
|
||||
case CC1101_SRES:
|
||||
log("CC1101_SRES not implemented");
|
||||
reset();
|
||||
break;
|
||||
|
||||
case CC1101_SFSTXON:
|
||||
log("CC1101_SFSTXON not implemented");
|
||||
break;
|
||||
|
||||
case CC1101_SXOFF:
|
||||
log("CC1101_SXOFF not implemented");
|
||||
break;
|
||||
|
||||
case CC1101_SCAL:
|
||||
setState(CC1101RadioState.CC1101_STATE_IDLE);
|
||||
break;
|
||||
|
||||
case CC1101_SRX:
|
||||
if(getState() == CC1101RadioState.CC1101_STATE_IDLE ||
|
||||
getState() == CC1101RadioState.CC1101_STATE_SLEEP) {
|
||||
log("CC1101 from idle to rx, should wait");
|
||||
TimeEvent goToRX = new TimeEvent(0, "CC1101 go to RX") {
|
||||
public void execute(long t) {
|
||||
if(getState() == CC1101RadioState.CC1101_STATE_RX) {
|
||||
/* Radio already in RX, ignore */
|
||||
return;
|
||||
}
|
||||
rxfifo.clear();
|
||||
rxExpectedLen = -1;
|
||||
rxGotSynchByte = false;
|
||||
setGDO0(false);
|
||||
setState(CC1101RadioState.CC1101_STATE_RX);
|
||||
}
|
||||
};
|
||||
int RXTIME = 190;
|
||||
cpu.scheduleTimeEventMillis(goToRX, RXTIME / 1000.0);
|
||||
|
||||
TimeEvent rssiValid = new TimeEvent(0, "CC1101 set RSSI valid") {
|
||||
public void execute(long t) {
|
||||
log("RSSI is now valid");
|
||||
currentRssiValid = true;
|
||||
}
|
||||
};
|
||||
log("RSSI is not valid");
|
||||
int RSSITIME = 380;
|
||||
cpu.scheduleTimeEventMillis(rssiValid, RSSITIME / 1000.0);
|
||||
// setState(CC1101RadioState.CC1101_STATE_RX);
|
||||
} else {
|
||||
setStateRX();
|
||||
}
|
||||
break;
|
||||
|
||||
case CC1101_STX:
|
||||
int len = (int) (0xff&txfifo.get(0));
|
||||
txFooterCountdown = 1 + len + 1/*len*/;
|
||||
if (DEBUG) {
|
||||
System.out.println("TX started: len = " + len + ", txFooterCountdown = " + txFooterCountdown);
|
||||
}
|
||||
txNext();
|
||||
setState(CC1101RadioState.CC1101_STATE_TX);
|
||||
break;
|
||||
|
||||
case CC1101_SIDLE:
|
||||
setState(CC1101RadioState.CC1101_STATE_IDLE);
|
||||
currentRssiValid = false;
|
||||
break;
|
||||
|
||||
case CC1101_SAFC:
|
||||
log("CC1101_SAFC not implemented");
|
||||
break;
|
||||
|
||||
case CC1101_SWOR:
|
||||
log("CC1101_SWOR not implemented");
|
||||
break;
|
||||
|
||||
case CC1101_SPWD:
|
||||
// log("CC1101_SPWD almost implemented");
|
||||
/* TODO XXX
|
||||
* Wait until CS is de-asserted. (We should at least wait
|
||||
* receiving or transmitting.)*/
|
||||
setState(CC1101RadioState.CC1101_STATE_SLEEP);
|
||||
break;
|
||||
|
||||
case CC1101_SFRX:
|
||||
rxfifo.clear();
|
||||
rxExpectedLen = -1;
|
||||
rxGotSynchByte = false;
|
||||
setGDO0(false);
|
||||
/*printRXFIFO();*/
|
||||
break;
|
||||
|
||||
case CC1101_SFTX:
|
||||
txfifo.clear();
|
||||
txFooterCountdown = -1;
|
||||
/*printTXFIFO();*/
|
||||
break;
|
||||
|
||||
case CC1101_SWORRST:
|
||||
log("CC1101_SWORRST not implemented");
|
||||
break;
|
||||
|
||||
case CC1101_SNOP:
|
||||
// log("CC1101_SNOP not implemented");
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.printf("strobe(0x%02x)\n", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int getLQI() {
|
||||
return 0; /* TODO */
|
||||
};
|
||||
|
||||
public void setLQI(int lqi) {
|
||||
}
|
||||
|
||||
/* SPI */
|
||||
public final static int SPI_READ_BIT = 0x80;
|
||||
public final static int SPI_BURST_BIT = 0x40;
|
||||
|
||||
private boolean spiBurstMode = false;
|
||||
private boolean spiReadMode = false;
|
||||
private boolean spiGotAddress = false;
|
||||
private int spiAddress;
|
||||
|
||||
public static boolean spiIsBurst(int data) {
|
||||
return (data & SPI_BURST_BIT) == SPI_BURST_BIT;
|
||||
}
|
||||
|
||||
public static boolean spiIsRead(int data) {
|
||||
return (data & SPI_READ_BIT) == SPI_READ_BIT;
|
||||
}
|
||||
|
||||
public static boolean spiIsStrobe(int data) {
|
||||
data = data & 0x3f;
|
||||
return data >= 0x30 && data <= 0x3d;
|
||||
}
|
||||
|
||||
private void spiResetState() {
|
||||
spiBurstMode = false;
|
||||
spiReadMode = false;
|
||||
spiGotAddress = false;
|
||||
spiAddress = 0xFF;
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
if (spiGotAddress) {
|
||||
if (!spiBurstMode) {
|
||||
/* Single access mode */
|
||||
if (spiReadMode) {
|
||||
source.byteReceived(getReg(spiAddress));
|
||||
} else {
|
||||
source.byteReceived(setReg(spiAddress, data));
|
||||
}
|
||||
spiResetState();
|
||||
} else {
|
||||
/* Burst mode */
|
||||
if (spiReadMode) {
|
||||
source.byteReceived(getReg(spiAddress));
|
||||
} else {
|
||||
source.byteReceived(setReg(spiAddress, data));
|
||||
}
|
||||
|
||||
if (spiAddress != CC1101_TXFIFO && spiAddress != CC1101_PATABLE) {
|
||||
spiAddress++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read/write. Burst/single. */
|
||||
spiBurstMode = spiIsBurst(data);
|
||||
spiReadMode = spiIsRead(data);
|
||||
|
||||
/* Is this a strobe command? */
|
||||
if (!spiBurstMode && spiIsStrobe(data)) {
|
||||
/* Strobe command */
|
||||
strobe(data);
|
||||
source.byteReceived(0);
|
||||
spiResetState();
|
||||
return;
|
||||
}
|
||||
|
||||
spiAddress = data & 0x3f;
|
||||
spiGotAddress = true;
|
||||
|
||||
/* Return MARCSTATE */
|
||||
source.byteReceived(getMarcstate());
|
||||
return;
|
||||
}
|
||||
public int setReg(int address, int data) {
|
||||
switch (address) {
|
||||
case CC1101_TXFIFO:
|
||||
txfifo.add((byte) data);
|
||||
/*printTXFIFO();*/
|
||||
return txfifo.size();
|
||||
case CC1101_CHANNR:
|
||||
channel = data;
|
||||
if (channelListener != null) {
|
||||
channelListener.channelChanged(channel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
log(String.format("setReg(0x%02x) 0x%02x", address, data));
|
||||
int oldValue = registers[address];
|
||||
registers[address] = data;
|
||||
configurationChanged(address, oldValue, data);
|
||||
return oldValue;
|
||||
}
|
||||
public int getReg(int address) {
|
||||
/* MSP430Core.profiler.printStackTrace(System.out); */
|
||||
switch (address) {
|
||||
case CC1101_CHANNR:
|
||||
return channel;
|
||||
case CC1101_MARCSTATE:
|
||||
return getMarcstate();
|
||||
case CC1101_RXBYTES:
|
||||
/*log("getReg(CC1101_RXBYTES) " + rxfifo.size());*/
|
||||
return rxfifo.size();
|
||||
case CC1101_TXBYTES:
|
||||
/*log("getReg(CC1101_TXBYTES) " + txfifo.size());*/
|
||||
return txfifo.size();
|
||||
case CC1101_PKTSTATUS:
|
||||
int status = 0;
|
||||
if(currentRssiValid) {
|
||||
if(currentRssiReg < CCA_THRESHOLD) {
|
||||
status |= CC1101_PKTSTATUS_CCA_BIT;
|
||||
} else {
|
||||
status |= CC1101_PKTSTATUS_CS_BIT;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
case CC1101_RSSI:
|
||||
return currentRssiReg;
|
||||
case CC1101_RXFIFO:
|
||||
if (rxfifo.size() > 0) {
|
||||
int ret = (int) rxfifo.remove(0);
|
||||
/*printRXFIFO();*/
|
||||
if (triggerGDO0onFifoThreshold && rxfifo.size() == 0) {
|
||||
setGDO0(false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
System.err.println("Warning: reading from empty RXFIFO");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log(String.format("getReg(0x%02x) 0x%02x", address, registers[address]));
|
||||
return registers[address];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isReadyToReceive() {
|
||||
/* TODO Implement me */
|
||||
if (getState() == CC1101RadioState.CC1101_STATE_IDLE) {
|
||||
return false;
|
||||
}
|
||||
if (getState() == CC1101RadioState.CC1101_STATE_SLEEP) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* txFooterCountdown: send CRC footer in these many bytes */
|
||||
protected int txFooterCountdown = -1;
|
||||
|
||||
/* TX/RX states */
|
||||
public static final int NUM_PREAMBLE = 4;
|
||||
public static final int NUM_SYNCH = 4;
|
||||
public static final byte SYNCH_BYTE_LAST = (byte) 0x91;
|
||||
private boolean txSentSynchByte = false;
|
||||
private int txSendSynchByteCnt = 0;
|
||||
private boolean txSentFirstCRC = false;
|
||||
void txNext() {
|
||||
if (txFooterCountdown < 0) {
|
||||
System.out.println("Warning: Aborting transmit since txFooterCountdown=" + txFooterCountdown);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send preamble and synch bytes */
|
||||
if (!txSentSynchByte) {
|
||||
/* Send NUM_PREAMBLE preamble bytes */
|
||||
if (txSendSynchByteCnt < NUM_PREAMBLE) {
|
||||
txSendSynchByteCnt++;
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (0xaa));
|
||||
}
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
return;
|
||||
}
|
||||
/* Send NUM_SYNCH-1 synch bytes */
|
||||
if (txSendSynchByteCnt < NUM_PREAMBLE + NUM_SYNCH - 1) {
|
||||
txSendSynchByteCnt++;
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (SYNCH_BYTE_LAST + 1));
|
||||
}
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
return;
|
||||
}
|
||||
/* Send last synch byte */
|
||||
if (txSendSynchByteCnt < NUM_PREAMBLE + NUM_SYNCH) {
|
||||
txSendSynchByteCnt++;
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (SYNCH_BYTE_LAST));
|
||||
}
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
|
||||
txSentSynchByte = true;
|
||||
return;
|
||||
}
|
||||
|
||||
txSentFirstCRC = false;
|
||||
}
|
||||
|
||||
if (txSentFirstCRC) {
|
||||
/* send second CRC byte */
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (0xef));
|
||||
}
|
||||
if (!txfifo.isEmpty()) {
|
||||
System.out.println("Warning: TXFIFO not empty after sending CRC bytes");
|
||||
}
|
||||
setStateRX();
|
||||
txSentSynchByte = false;
|
||||
txSendSynchByteCnt = 0;
|
||||
txSentFirstCRC = false;
|
||||
return;
|
||||
}
|
||||
|
||||
txFooterCountdown--;
|
||||
|
||||
if (txFooterCountdown == 0) {
|
||||
/* countdown is zero, send first CRC byte */
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (0xee));
|
||||
}
|
||||
txSentFirstCRC = true;
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send payload byte (including first FIFO length byte) */
|
||||
if (txfifo.isEmpty()) {
|
||||
System.out.println("Warning: TXFIFO is empty, sending zero-byte, txFooterCountdown=" + txFooterCountdown);
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) 0);
|
||||
}
|
||||
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
setState(CC1101RadioState.CC1101_STATE_TXFIFO_UNDERFLOW);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rfListener != null) {
|
||||
rfListener.receivedByte((byte) (txfifo.get(0).intValue()));
|
||||
}
|
||||
txfifo.remove(0);
|
||||
cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs());
|
||||
|
||||
/*printTXFIFO();*/
|
||||
}
|
||||
|
||||
public void setGDO0(IOPort port, int pin) {
|
||||
gdo0Port = port;
|
||||
gdo0Pin = pin;
|
||||
}
|
||||
public void setGDO0(boolean active) {
|
||||
/* TODO Read active low/high configuration */
|
||||
|
||||
if (active) {
|
||||
if (gdo0Port != null) {
|
||||
gdo0Port.setPinState(gdo0Pin, IOPort.PinState.HI);
|
||||
}
|
||||
if (gdo0Listener != null) {
|
||||
gdo0Listener.event(IOPort.PinState.HI);
|
||||
}
|
||||
} else {
|
||||
if (gdo0Port != null) {
|
||||
gdo0Port.setPinState(gdo0Pin, IOPort.PinState.LOW);
|
||||
}
|
||||
if (gdo0Listener != null) {
|
||||
gdo0Listener.event(IOPort.PinState.LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface GDOListener {
|
||||
public void event(PinState state);
|
||||
}
|
||||
private GDOListener gdo0Listener = null;
|
||||
public void setGDO0Listener(GDOListener l) {
|
||||
gdo0Listener = l;
|
||||
}
|
||||
|
||||
public void setGDO2(IOPort port, int pin) {
|
||||
gdo2Port = port;
|
||||
gdo2Pin = pin;
|
||||
}
|
||||
public void setGDO2(boolean active) {
|
||||
if (gdo2Port == null) {
|
||||
return;
|
||||
}
|
||||
gdo2Port.setPinState(gdo2Pin, active ? IOPort.PinState.LOW
|
||||
: IOPort.PinState.HI);
|
||||
}
|
||||
|
||||
private void printRXFIFO() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("RXFIFO[%03d]: ", rxfifo.size()));
|
||||
for (int i = 0; i < rxfifo.size(); i++) {
|
||||
sb.append(String.format("%02x", rxfifo.get(i)));
|
||||
}
|
||||
log(sb.toString() + "\n");
|
||||
}
|
||||
private void printTXFIFO() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("TXFIFO[%03d]: ", txfifo.size()));
|
||||
for (int i = 0; i < txfifo.size(); i++) {
|
||||
sb.append(String.format("%02x", txfifo.get(i)));
|
||||
}
|
||||
log(sb.toString() + "\n");
|
||||
}
|
||||
|
||||
public CC1101RadioState getState() {
|
||||
return state;
|
||||
}
|
||||
public interface StateListener {
|
||||
public void newState(CC1101RadioState state);
|
||||
}
|
||||
public void setStateListener(StateListener listener) {
|
||||
stateListener = listener;
|
||||
}
|
||||
public interface ReceiverListener {
|
||||
public void newState(boolean on);
|
||||
}
|
||||
public void setReceiverListener(ReceiverListener listener) {
|
||||
receiverListener = listener;
|
||||
}
|
||||
|
||||
boolean receiverOn = false;
|
||||
boolean setState(CC1101RadioState newState) {
|
||||
if (newState != CC1101RadioState.CC1101_STATE_IDLE
|
||||
&& newState != CC1101RadioState.CC1101_STATE_RX
|
||||
&& newState != CC1101RadioState.CC1101_STATE_TX) {
|
||||
log("setState(" + newState + ")");
|
||||
}
|
||||
|
||||
state = newState;
|
||||
|
||||
/* Notify state listener */
|
||||
if (stateListener != null) {
|
||||
stateListener.newState(state);
|
||||
}
|
||||
if (receiverListener != null && isReadyToReceive() != receiverOn) {
|
||||
receiverOn = isReadyToReceive();
|
||||
receiverListener.newState(receiverOn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean rxGotSynchByte = false;
|
||||
private int rxExpectedLen = -1;
|
||||
public void receivedByte(byte data) {
|
||||
if(state != CC1101RadioState.CC1101_STATE_RX) {
|
||||
return;
|
||||
}
|
||||
if (!rxGotSynchByte) {
|
||||
/* Await synch byte */
|
||||
if (data == SYNCH_BYTE_LAST) {
|
||||
rxGotSynchByte = true;
|
||||
if(triggerGDO0onSynch) {
|
||||
setGDO0(true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rxExpectedLen < 0) {
|
||||
rxExpectedLen = 1/*len*/ + (int) data/*payload*/ + 2/*CRC*/;
|
||||
}
|
||||
|
||||
rxExpectedLen--;
|
||||
if (rxExpectedLen == 0) {
|
||||
setGDO0(false);
|
||||
rxExpectedLen = -1;
|
||||
rxGotSynchByte = false;
|
||||
}
|
||||
|
||||
if (rxfifo.size() < 64) {
|
||||
rxfifo.add(data);
|
||||
|
||||
if (triggerGDO0onFifoThreshold && rxfifo.size() >= 3 && rxExpectedLen > 0) {
|
||||
setGDO0(true);
|
||||
}
|
||||
} else {
|
||||
log("rxfifo overflow " + rxfifo.size());
|
||||
setState(CC1101RadioState.CC1101_STATE_RXFIFO_OVERFLOW);
|
||||
}
|
||||
/*printRXFIFO();*/
|
||||
}
|
||||
|
||||
public String info() {
|
||||
return "CC1101 info: [not implemented]";
|
||||
}
|
||||
|
||||
public int getRegister(int register) {
|
||||
return registers[register];
|
||||
}
|
||||
|
||||
public void setRegister(int register, int data) {
|
||||
registers[register] = data;
|
||||
}
|
||||
|
||||
public void setRSSI(int power) {
|
||||
currentRssiReg = power;
|
||||
}
|
||||
public int getRSSI() {
|
||||
return currentRssiReg;
|
||||
}
|
||||
|
||||
public int getActiveFrequency() {
|
||||
return (int) 0; /* Not implemented */
|
||||
}
|
||||
|
||||
public int getActiveChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public int getOutputPowerIndicator() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public double getFrequency() {
|
||||
return 0; /* Not implemented */
|
||||
}
|
||||
|
||||
public void notifyReset() {
|
||||
super.notifyReset();
|
||||
setChipSelect(false);
|
||||
}
|
||||
|
||||
public int getOutputPower() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getOutputPowerMax() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getOutputPowerIndicatorMax() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Chip APIs
|
||||
*****************************************************************************/
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return data in register at the correct position */
|
||||
public int getConfiguration(int parameter) {
|
||||
return registers[parameter];
|
||||
}
|
||||
|
||||
public boolean getChipSelect() {
|
||||
return chipSelect;
|
||||
}
|
||||
|
||||
public void setChipSelect(boolean select) {
|
||||
chipSelect = select;
|
||||
if (!chipSelect) {
|
||||
spiResetState();
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
/*log("Chip select: " + chipSelect);*/
|
||||
}
|
||||
}
|
||||
|
||||
void setStateRX() {
|
||||
setState(CC1101RadioState.CC1101_STATE_RX);
|
||||
currentRssiValid = true;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
setState(CC1101RadioState.CC1101_STATE_SLEEP);
|
||||
|
||||
registers[CC1101_PARTNUM] = 0;
|
||||
registers[CC1101_VERSION] = 6;
|
||||
}
|
||||
|
||||
public int getMarcstate() {
|
||||
return getState().getStateAsInt();
|
||||
}
|
||||
|
||||
private boolean lastWasRead = false;
|
||||
public void setLastInstructionWasRead(boolean wasRead) {
|
||||
lastWasRead = wasRead;
|
||||
}
|
||||
|
||||
public int getStatusByte() {
|
||||
int status = 0;
|
||||
|
||||
/* Bit 7: RF ready */
|
||||
if (true) {
|
||||
status += 0; /* XXX Always ready! */
|
||||
}
|
||||
|
||||
/* Bit 4-6: simplified state */
|
||||
status = status << 3;
|
||||
if (state == CC1101RadioState.CC1101_STATE_IDLE) {
|
||||
status += 0;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_RX ||
|
||||
state == CC1101RadioState.CC1101_STATE_RX_END ||
|
||||
state == CC1101RadioState.CC1101_STATE_RX_RST) {
|
||||
status += 1;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_TX ||
|
||||
state == CC1101RadioState.CC1101_STATE_TX_END) {
|
||||
status += 2;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_FSTXON) {
|
||||
status += 3;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_ENDCAL ||
|
||||
state == CC1101RadioState.CC1101_STATE_MANCAL ||
|
||||
state == CC1101RadioState.CC1101_STATE_STARTCAL) {
|
||||
status += 4;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_RXTX_SWITCH ||
|
||||
state == CC1101RadioState.CC1101_STATE_TXRX_SWITCH) {
|
||||
status += 5;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_RXFIFO_OVERFLOW) {
|
||||
status += 6;
|
||||
} else if (state == CC1101RadioState.CC1101_STATE_TXFIFO_UNDERFLOW) {
|
||||
status += 7;
|
||||
}
|
||||
|
||||
/* Bit 0-3 */
|
||||
status = status << 4;
|
||||
if (lastWasRead) {
|
||||
/* Return available bytes in RXFIFO */
|
||||
int available = rxfifo.size();
|
||||
if (available > 15) {
|
||||
status += 15;
|
||||
} else {
|
||||
status += available;
|
||||
}
|
||||
} else {
|
||||
/* Return available bytes in TXFIFO */
|
||||
int available = 64 - txfifo.size();
|
||||
if (available > 15) {
|
||||
status += 15;
|
||||
} else {
|
||||
status += available;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -521,6 +521,13 @@ public class CC2520 extends Radio802154 implements USARTListener, SPIData {
|
|||
}
|
||||
}
|
||||
|
||||
public int getFooterLength() {
|
||||
if (autoCRC) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
// FCF max fram version = 3 and frame filtering enabled
|
||||
memory[REG_FRMFILT0] = 0x0d;
|
||||
|
|
@ -837,20 +844,24 @@ public class CC2520 extends Radio802154 implements USARTListener, SPIData {
|
|||
|
||||
// Here we check the CRC of the packet!
|
||||
//System.out.println("Reading from " + ((rxfifoWritePos + 128 - 2) & 127));
|
||||
int crc = rxFIFO.get(-2) << 8;
|
||||
crc += rxFIFO.get(-1); //memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 1) & 127)];
|
||||
if (autoCRC) {
|
||||
int crc = rxFIFO.get(-2) << 8;
|
||||
crc += rxFIFO.get(-1); //memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 1) & 127)];
|
||||
|
||||
crcOk = crc == rxCrc.getCRCBitrev();
|
||||
if (DEBUG && !crcOk) {
|
||||
log("CRC not OK: recv:" + Utils.hex16(crc) + " calc: " + Utils.hex16(rxCrc.getCRCBitrev()));
|
||||
crcOk = crc == rxCrc.getCRCBitrev();
|
||||
if (DEBUG && !crcOk) {
|
||||
log("CRC not OK: recv:" + Utils.hex16(crc) + " calc: " + Utils.hex16(rxCrc.getCRCBitrev()));
|
||||
}
|
||||
// Should take a RSSI value as input or use a set-RSSI value...
|
||||
rxFIFO.set(-2, memory[REG_RSSI] & 0xff);
|
||||
rxFIFO.set(-1, (corrval & 0x7F) | (crcOk ? 0x80 : 0));
|
||||
// memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 2) & 127)] = ;
|
||||
// // Set CRC ok and add a correlation - TODO: fix better correlation value!!!
|
||||
// memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 1) & 127)] = 37 |
|
||||
// (crcOk ? 0x80 : 0);
|
||||
} else {
|
||||
crcOk = true;
|
||||
}
|
||||
// Should take a RSSI value as input or use a set-RSSI value...
|
||||
rxFIFO.set(-2, memory[REG_RSSI] & 0xff);
|
||||
rxFIFO.set(-1, (corrval & 0x7F) | (crcOk ? 0x80 : 0));
|
||||
// memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 2) & 127)] = ;
|
||||
// // Set CRC ok and add a correlation - TODO: fix better correlation value!!!
|
||||
// memory[RAM_RXFIFO + ((rxfifoWritePos + 128 - 1) & 127)] = 37 |
|
||||
// (crcOk ? 0x80 : 0);
|
||||
|
||||
/* set FIFOP only if this is the first received packet - e.g. if rxfifoLen is at most rxlen + 1
|
||||
* TODO: check what happens when rxfifoLen < rxlen - e.g we have been reading before FIFOP */
|
||||
|
|
@ -910,6 +921,15 @@ public class CC2520 extends Radio802154 implements USARTListener, SPIData {
|
|||
// + " CCAMUX: " + (memory[address] & CCAMUX));
|
||||
// updateCCA();
|
||||
// break;
|
||||
case REG_GPIOCTRL0:
|
||||
/*
|
||||
* XXX TODO Implement support for GPIO control. Below example code
|
||||
* demonstrates how GPIO0 is set to fifop functionality (0x28).
|
||||
*/
|
||||
if (data == 0x28) {
|
||||
fifopGPIO = gpio[0];
|
||||
}
|
||||
break;
|
||||
case REG_FSCTRL: {
|
||||
ChannelListener listener = this.channelListener;
|
||||
if (listener != null) {
|
||||
|
|
@ -926,6 +946,10 @@ public class CC2520 extends Radio802154 implements USARTListener, SPIData {
|
|||
}
|
||||
|
||||
int readMemory(int address) {
|
||||
switch(address) {
|
||||
case REG_RXFIFOCNT:
|
||||
return rxFIFO.length();
|
||||
}
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
|
|
@ -1084,14 +1108,18 @@ public class CC2520 extends Radio802154 implements USARTListener, SPIData {
|
|||
private void txNext() {
|
||||
if(txfifoPos <= memory[RAM_TXFIFO]) {
|
||||
int len = memory[RAM_TXFIFO] & 0xff;
|
||||
if (txfifoPos == len - 1) {
|
||||
txCrc.setCRC(0);
|
||||
for (int i = 1; i < len - 1; i++) {
|
||||
txCrc.addBitrev(memory[RAM_TXFIFO + i] & 0xff);
|
||||
|
||||
if (autoCRC) {
|
||||
if (txfifoPos == len - 1) {
|
||||
txCrc.setCRC(0);
|
||||
for (int i = 1; i < len - 1; i++) {
|
||||
txCrc.addBitrev(memory[RAM_TXFIFO + i] & 0xff);
|
||||
}
|
||||
memory[RAM_TXFIFO + len - 1] = txCrc.getCRCHi();
|
||||
memory[RAM_TXFIFO + len] = txCrc.getCRCLow();
|
||||
}
|
||||
memory[RAM_TXFIFO + len - 1] = txCrc.getCRCHi();
|
||||
memory[RAM_TXFIFO + len] = txCrc.getCRCLow();
|
||||
}
|
||||
|
||||
if (txfifoPos > 0x7f) {
|
||||
logw(WarningType.EXECUTION, "**** Warning - packet size too large - repeating packet bytes txfifoPos: " + txfifoPos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Thingsquare.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is a stub implementation for the Enc28j60 Ethernet chip. This ignores
|
||||
* the majority of configuration and setup, and only provides the very minimum
|
||||
* functionality to support a simple bit-banged Thingsquare Mist driver. */
|
||||
|
||||
package se.sics.mspsim.chip;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import se.sics.mspsim.core.Chip;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOPort.PinState;
|
||||
import se.sics.mspsim.core.MSP430Core;
|
||||
|
||||
public class Enc28J60 extends Chip {
|
||||
protected boolean DEBUG = false;
|
||||
|
||||
public static final int EIE = 0x1b;
|
||||
public static final int EIR = 0x1c;
|
||||
public static final int ESTAT = 0x1d;
|
||||
public static final int ECON2 = 0x1e;
|
||||
public static final int ECON1 = 0x1f;
|
||||
|
||||
public static final int ESTAT_CLKRDY = 0x01;
|
||||
public static final int ESTAT_TXABRT = 0x02;
|
||||
|
||||
public static final int ECON1_RXEN = 0x04;
|
||||
public static final int ECON1_TXRTS = 0x08;
|
||||
|
||||
public static final int ECON2_AUTOINC = 0x80;
|
||||
public static final int ECON2_PKTDEC = 0x40;
|
||||
|
||||
public static final int EPKTCNT = 0x19;
|
||||
|
||||
private static final int WBM_COMMAND = 0x3a; /* Note: 0x7a with write bit set */
|
||||
private static final int RBM_COMMAND = 0x3a; /* Note: 0x7a with write bit set */
|
||||
|
||||
private IOPort myPort;
|
||||
|
||||
private int myClk;
|
||||
private int myMosi;
|
||||
private int myChipSelect;
|
||||
private int myMisoBit;
|
||||
|
||||
public Enc28J60(MSP430Core cpu, IOPort port, int clk, int mosi,
|
||||
int miso, int chipSelect) {
|
||||
super("Enc28J60", "Ethernet", cpu);
|
||||
|
||||
myPort = port;
|
||||
myClk = (1 << clk);
|
||||
myMosi = (1 << mosi);
|
||||
myChipSelect = (1 << chipSelect);
|
||||
|
||||
myMisoBit = miso;
|
||||
}
|
||||
|
||||
public void log(String msg) {
|
||||
if (DEBUG) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean writingToWBM = false;
|
||||
private boolean readingFromRBM = false;
|
||||
private boolean nextEcon1 = false;
|
||||
private boolean nextEcon2 = false;
|
||||
|
||||
private ArrayList<Byte> wbmData = new ArrayList<Byte>();
|
||||
|
||||
private ArrayList<RbmPacket> rbmPackets = new ArrayList<RbmPacket>();
|
||||
private static class RbmPacket {
|
||||
ArrayList<Byte> data = new ArrayList<Byte>();
|
||||
boolean wasRead = false;
|
||||
}
|
||||
|
||||
public void writePacket(byte[] data) {
|
||||
RbmPacket p = new RbmPacket();
|
||||
int len = data.length;
|
||||
|
||||
p.data.add(new Byte((byte) 0x00)); /* ignored: next packet pointer */
|
||||
p.data.add(new Byte((byte) 0x00)); /* ignored: next packet pointer */
|
||||
|
||||
p.data.add(new Byte((byte) (len & 0xff))); /* length */
|
||||
p.data.add(new Byte((byte) ((len >> 8) & 0xff))); /* length */
|
||||
|
||||
p.data.add(new Byte((byte) 0x00)); /* ignored: status */
|
||||
p.data.add(new Byte((byte) 0x00)); /* ignored: status */
|
||||
|
||||
for (byte b : data) {
|
||||
p.data.add(new Byte(b)); /* data */
|
||||
}
|
||||
|
||||
rbmPackets.add(p);
|
||||
log("Enc28j60: nr pending packets increased to: " + rbmPackets.size());
|
||||
}
|
||||
|
||||
private PacketListener listener = null;
|
||||
public static interface PacketListener {
|
||||
public void packetSent(Byte[] packetData);
|
||||
}
|
||||
public void setPacketListener(PacketListener l) {
|
||||
listener = l;
|
||||
}
|
||||
|
||||
private int inputByte(int data) {
|
||||
int val = 0x00;
|
||||
|
||||
if (writingToWBM) {
|
||||
wbmData.add(new Byte((byte) data));
|
||||
val = 0x00;
|
||||
return val;
|
||||
} else if (readingFromRBM) {
|
||||
if (rbmPackets.size() > 0) {
|
||||
if (rbmPackets.get(0).data.isEmpty()) {
|
||||
log("Enc28j60: warning, packet data is already consumed, returning 0");
|
||||
} else {
|
||||
val = rbmPackets.get(0).data.remove(0);
|
||||
rbmPackets.get(0).wasRead = true;
|
||||
}
|
||||
} else {
|
||||
log("Enc28j60: warning, no packet in rbm, returning 0");
|
||||
val = 0x00;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* Strip optional write flag */
|
||||
boolean writing = (data & 0x40) != 0;
|
||||
data = (data & ~0x40);
|
||||
|
||||
if (nextEcon1) {
|
||||
if ((data & ECON1_TXRTS) != 0) {
|
||||
log("Transmitting enc28j60 packet, size: " + wbmData.size());
|
||||
if (listener != null) {
|
||||
wbmData.remove(0);
|
||||
listener.packetSent(wbmData.toArray(new Byte[0]));
|
||||
}
|
||||
wbmData.clear();
|
||||
}
|
||||
nextEcon1 = false;
|
||||
} else if (nextEcon2) {
|
||||
if (!rbmPackets.isEmpty() && rbmPackets.get(0).wasRead) {
|
||||
rbmPackets.remove(0);
|
||||
log("Enc28j60: nr pending packets decreased to: " + rbmPackets.size());
|
||||
}
|
||||
nextEcon2 = false;
|
||||
} else if (data == ECON1) {
|
||||
/* we are awaiting a ECON1 command */
|
||||
nextEcon1 = true;
|
||||
} else if (data == ECON2) {
|
||||
/* we are awaiting a ECON2 command */
|
||||
nextEcon2 = true;
|
||||
} else if (data == EPKTCNT) {
|
||||
return rbmPackets.size();
|
||||
} else if (data == ESTAT) {
|
||||
/* chip is always ready */
|
||||
val = ESTAT_CLKRDY;
|
||||
} else if (writing && data == WBM_COMMAND) {
|
||||
writingToWBM = true;
|
||||
} else if (data == RBM_COMMAND) {
|
||||
if (rbmPackets.size() > 0) {
|
||||
if (rbmPackets.get(0).data.isEmpty()) {
|
||||
log("Enc28j60: warning, packet data is already consumed, returning 0");
|
||||
} else {
|
||||
val = rbmPackets.get(0).data.remove(0);
|
||||
rbmPackets.get(0).wasRead = true;
|
||||
}
|
||||
} else {
|
||||
log("Enc28j60: warning, no packet in rbm, returning 0");
|
||||
val = 0x00;
|
||||
}
|
||||
readingFromRBM = true;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
private int spiOut = 0; /* byte being sent over SPI */
|
||||
private int spiOutCount = 0;
|
||||
private int spiIn = 0; /* byte being received over SPI */
|
||||
private int spiInCount = 0;
|
||||
public void write(IOPort port, int data) {
|
||||
if (port != myPort) {
|
||||
/* ignore */
|
||||
return;
|
||||
}
|
||||
|
||||
boolean chipSelect = (data & myChipSelect) == 0;
|
||||
boolean clk = (data & myClk) != 0;
|
||||
boolean mosi = (data & myMosi) != 0;
|
||||
|
||||
if (!chipSelect) {
|
||||
if (readingFromRBM && spiOutCount == 0 && !rbmPackets.isEmpty()) {
|
||||
/* XXX Hack: pushing back last byte to rbm */
|
||||
rbmPackets.get(0).data.add(0, (byte)spiOut);
|
||||
}
|
||||
writingToWBM = false;
|
||||
readingFromRBM = false;
|
||||
}
|
||||
|
||||
if (!chipSelect || !clk) {
|
||||
/* ignore */
|
||||
//log("write ignored: chipSelect " + chipSelect + ", clk " + clk);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare next outgoing bit on miso */
|
||||
if (spiOutCount < 8) {
|
||||
spiOutCount++;
|
||||
|
||||
if ((spiOut & 0x80) != 0) {
|
||||
port.setPinState(myMisoBit, PinState.HI);
|
||||
} else {
|
||||
port.setPinState(myMisoBit, PinState.LOW);
|
||||
}
|
||||
|
||||
spiOut = (spiOut << 1);
|
||||
}
|
||||
|
||||
/* Read next incoming bit on mosi */
|
||||
spiIn = (spiIn << 1);
|
||||
if (mosi) {
|
||||
spiIn |= 0x01;
|
||||
}
|
||||
spiInCount++;
|
||||
|
||||
if (spiInCount >= 8) {
|
||||
/* We've now read all 8 bits on mosi */
|
||||
spiOut = inputByte(spiIn);
|
||||
spiOutCount = 0;
|
||||
spiIn = 0;
|
||||
spiInCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getConfiguration(int parameter) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* Copyright (c) 2011, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of MSPSim.
|
||||
*
|
||||
*
|
||||
* -----------------------------------------------------------------
|
||||
*
|
||||
* Author : Joakim Eriksson
|
||||
*/
|
||||
|
||||
package se.sics.mspsim.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import se.sics.mspsim.core.ClockSystem;
|
||||
import se.sics.mspsim.core.GenericUSCI;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.MSP430Config;
|
||||
import se.sics.mspsim.core.MSP430Core;
|
||||
import se.sics.mspsim.core.Multiplier32;
|
||||
import se.sics.mspsim.core.PMM;
|
||||
import se.sics.mspsim.core.PMMDummy;
|
||||
import se.sics.mspsim.core.SysReg;
|
||||
import se.sics.mspsim.core.Timer;
|
||||
import se.sics.mspsim.core.UnifiedClockSystem;
|
||||
import se.sics.mspsim.util.Utils;
|
||||
import se.sics.mspsim.core.RF1A;
|
||||
|
||||
public class CC430f5137Config extends MSP430Config {
|
||||
|
||||
// NOTE: this MCU also needs to configure
|
||||
// - positions of all timers (A0, A1, B)
|
||||
// - memory configuration
|
||||
// -
|
||||
private static final String portConfig[] = {
|
||||
"P1=200,IN 00,OUT 02,DIR 04,REN 06,DS 08,SEL 0A,IV_L 0E,IV_H 0F,IES 18,IE 1A,IFG 1C",
|
||||
"P2=200,IN 01,OUT 03,DIR 05,REN 07,DS 09,SEL 0B,IV_L 1E,IV_H 1F,IES 19,IE 1B,IFG 1D",
|
||||
"P3=220,IN 00,OUT 02,DIR 04,REN 06,DS 08,SEL 0A",
|
||||
"P4=220,IN 01,OUT 03,DIR 05,REN 07,DS 09,SEL 0B",
|
||||
"P5=240,IN 00,OUT 02,DIR 04,REN 06,DS 08,SEL 0A",
|
||||
"P6=240,IN 01,OUT 03,DIR 05,REN 07,DS 09,SEL 0B",
|
||||
"P7=260,IN 00,OUT 02,DIR 04,REN 06,DS 08,SEL 0A",
|
||||
"P8=260,IN 01,OUT 03,DIR 05,REN 07,DS 09,SEL 0B",
|
||||
"P9=280,IN 00,OUT 02,DIR 04,REN 06,DS 08,SEL 0A",
|
||||
"P:=280,IN 01,OUT 03,DIR 05,REN 07,DS 09,SEL 0B",
|
||||
};
|
||||
|
||||
public CC430f5137Config() {
|
||||
/* 64 vectors for the MSP430f54xx series */
|
||||
maxInterruptVector = 63;
|
||||
MSP430XArch = true;
|
||||
flashControllerOffset = 0x140;
|
||||
sfrOffset = 0x100;
|
||||
|
||||
/* configuration for the timers - need to set-up new source maps!!! */
|
||||
|
||||
/* XXX Adam: the ints after TimerConfig(X, Y) seem to be the interrupt vectors, i.e. i = (vector_addresss - 0xff80)/2 */
|
||||
|
||||
//#define TIMER1_A1_VECTOR (0x0064) /* 0xFFE4 Timer1_A3 CC1-2, TA1 */
|
||||
//#define TIMER1_A0_VECTOR (0x0066) /* 0xFFE6 Timer1_A3 CC0 */
|
||||
//#define DMA_VECTOR (0x0068) /* 0xFFE8 DMA */
|
||||
//#define CC1101_VECTOR (0x006A) /* 0xFFEA CC1101 Radio Interface */
|
||||
//#define TIMER0_A1_VECTOR (0x006C) /* 0xFFEC Timer0_A5 CC1-4, TA */
|
||||
//#define TIMER0_A0_VECTOR (0x006E) /* 0xFFEE Timer0_A5 CC0 */
|
||||
|
||||
|
||||
TimerConfig timerA0 = new TimerConfig(0x6e / 2, 0x6c / 2, 5, 0x340, Timer.TIMER_Bx149, "TimerA0", 0x340 + 0x2e);
|
||||
TimerConfig timerA1 = new TimerConfig(0x66 / 2, 0x64 / 2, 3, 0x380, Timer.TIMER_Ax149, "TimerA1", 0x380 + 0x2e);
|
||||
|
||||
timerConfig = new TimerConfig[] {timerA0, timerA1};
|
||||
|
||||
uartConfig = new UARTConfig[] {
|
||||
new UARTConfig("USCI A0", 57, 0x5c0),
|
||||
new UARTConfig("USCI B0", 56, 0x5e0),
|
||||
new UARTConfig("USCI A1", 46, 0x600),
|
||||
new UARTConfig("USCI B1", 45, 0x620),
|
||||
};
|
||||
|
||||
/* configure memory */
|
||||
infoMemConfig(0x1800, 128 * 4);
|
||||
ramConfig(0x1c00, 4 * 1024);
|
||||
mainFlashConfig(0x8000, 32 * 1024);
|
||||
|
||||
ioMemSize(0x1000); /* 4 KB of IO Memory */
|
||||
|
||||
watchdogOffset = 0x15c;
|
||||
// bsl, IO, etc at a later stage...
|
||||
}
|
||||
|
||||
public int setup(MSP430Core cpu, ArrayList<IOUnit> ioUnits) {
|
||||
|
||||
Multiplier32 mp = new Multiplier32(cpu, cpu.memory, 0x4c0);
|
||||
cpu.setIORange(0x4c0, 0x2e, mp);
|
||||
|
||||
/* this code should be slightly more generic... and be somewhere else... */
|
||||
for (int i = 0, n = uartConfig.length; i < n; i++) {
|
||||
GenericUSCI usci = new GenericUSCI(cpu, i, cpu.memory, this);
|
||||
/* setup 0 - 1f as IO addresses */
|
||||
cpu.setIORange(uartConfig[i].offset, 0x20, usci);
|
||||
// System.out.println("Adding IOUnit USCI: " + usci.getName());
|
||||
ioUnits.add(usci);
|
||||
}
|
||||
IOPort last = null;
|
||||
ioUnits.add(last = IOPort.parseIOPort(cpu, 47, portConfig[0], last));
|
||||
ioUnits.add(last = IOPort.parseIOPort(cpu, 42, portConfig[1], last));
|
||||
|
||||
for (int i = 2; i < portConfig.length; i++) {
|
||||
ioUnits.add(last = IOPort.parseIOPort(cpu, 0, portConfig[i], last));
|
||||
}
|
||||
|
||||
/* XXX: Stub IO units: Sysreg and PMM */
|
||||
SysReg sysreg = new SysReg(cpu, cpu.memory);
|
||||
cpu.setIORange(SysReg.ADDRESS, SysReg.SIZE, sysreg);
|
||||
ioUnits.add(sysreg);
|
||||
|
||||
PMMDummy pmmDummy = new PMMDummy(cpu, cpu.memory, 0x110);
|
||||
cpu.setIORange(0x110, PMMDummy.SIZE, pmmDummy);
|
||||
ioUnits.add(pmmDummy);
|
||||
|
||||
PMM pmm = new PMM(cpu, cpu.memory, 0x120);
|
||||
cpu.setIORange(0x120, PMM.SIZE, pmm);
|
||||
ioUnits.add(pmm);
|
||||
|
||||
RF1A rf1a = new RF1A(cpu, cpu.memory);
|
||||
cpu.setIORange(RF1A.ADDRESS, RF1A.SIZE, rf1a);
|
||||
ioUnits.add(rf1a);
|
||||
|
||||
|
||||
return portConfig.length + uartConfig.length;
|
||||
}
|
||||
|
||||
public String getAddressAsString(int addr) {
|
||||
return Utils.hex20(addr);
|
||||
}
|
||||
|
||||
public ClockSystem createClockSystem(MSP430Core cpu, int[] memory, Timer[] timers) {
|
||||
return new UnifiedClockSystem(cpu, memory, 0, timers);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -373,7 +373,7 @@ public class GenericUSCI extends IOUnit implements DMATrigger, USARTSource {
|
|||
|
||||
/* For timing issues we have to send the ACK after reading the
|
||||
* register */
|
||||
if (!i2cTransmitter) {
|
||||
if (i2cEnabled && !i2cTransmitter) {
|
||||
txBuffer.add(I2CData.ACK);
|
||||
stat |= USCI_BUSY;
|
||||
if (!transmitting) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package se.sics.mspsim.core;
|
||||
|
||||
public class PMMDummy extends IOUnit {
|
||||
public static int SIZE = 0x10;
|
||||
|
||||
public PMMDummy(MSP430Core cpu, int[] memory, int address) {
|
||||
super("PMMDummy", "PMMDummy", cpu, memory, address);
|
||||
reset(0);
|
||||
}
|
||||
|
||||
public void reset(int type) {
|
||||
}
|
||||
|
||||
public void write(int address, int value, boolean word, long cycles) {
|
||||
memory[address] = value;
|
||||
}
|
||||
|
||||
public int read(int address, boolean word, long cycles) {
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
public void interruptServiced(int vector) {
|
||||
if (DEBUG) {
|
||||
log(this.getName() + ": Interrupt services vector: " + vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package se.sics.mspsim.core;
|
||||
|
||||
import se.sics.mspsim.chip.CC1101;
|
||||
import se.sics.mspsim.chip.CC1101.GDOListener;
|
||||
import se.sics.mspsim.core.IOPort.PinState;
|
||||
|
||||
public class RF1A extends IOUnit implements InterruptHandler {
|
||||
private boolean DEBUG = true;
|
||||
|
||||
public static int ADDRESS = 0xf00;
|
||||
public static int SIZE = 64;
|
||||
|
||||
private static final int RF1AIFCTL0 = 0x00;
|
||||
private static final int RF1AIFCTL1 = 0x02;
|
||||
private static final int RF1AIFCTL2 = 0x04;
|
||||
private static final int RF1AIFERR = 0x06;
|
||||
private static final int RF1AIFERRV = 0x0c;
|
||||
private static final int RF1AIFIV = 0x0e;
|
||||
private static final int RF1AINSTRW = 0x10;
|
||||
private static final int RF1AINSTR1W = 0x12;
|
||||
private static final int RF1AINSTR2B = 0x14;
|
||||
private static final int RF1ADINW = 0x16;
|
||||
private static final int RF1ADOUTB = 0x20;
|
||||
private static final int RF1ASTATB = 0x21;
|
||||
private static final int RF1ASTAT1W = 0x22;
|
||||
private static final int RF1ASTAT2W = 0x24;
|
||||
private static final int RF1ADOUT0W = 0x28;
|
||||
private static final int RF1ADOUT1W = 0x2a;
|
||||
private static final int RF1ADOUT2W = 0x2c;
|
||||
private static final int RF1AIN = 0x30;
|
||||
private static final int RF1AIFG = 0x32;
|
||||
private static final int RF1AIES = 0x34;
|
||||
private static final int RF1AIE = 0x36;
|
||||
private static final int RF1AIV = 0x38;
|
||||
private static final int RF1ARXFIFO = 0x3c;
|
||||
private static final int RF1ATXFIFO = 0x3e;
|
||||
|
||||
private CC1101 cc1101;
|
||||
|
||||
private boolean interruptOnCC1101GDO0 = false;
|
||||
private boolean gdo0IsHigh = false;
|
||||
|
||||
public RF1A(final MSP430Core cpu, int[] memory) {
|
||||
super("RF1A", "RF1A", cpu, memory, ADDRESS);
|
||||
cc1101 = new CC1101(cpu);
|
||||
cc1101.setGDO0Listener(new GDOListener() {
|
||||
public void event(PinState state) {
|
||||
/* cc430f5137 datasheet p. 17 */
|
||||
gdo0IsHigh = (state == PinState.HI);
|
||||
cpu.flagInterrupt(53, RF1A.this, gdo0IsHigh);
|
||||
}
|
||||
});
|
||||
|
||||
reset(0);
|
||||
}
|
||||
|
||||
public void reset(int type) {
|
||||
/* Initial values */
|
||||
memory[ADDRESS + 0x00] = 0x0000; /* RF1AIFCTL0 */
|
||||
memory[ADDRESS + 0x02] = 0x0000; /* RF1AIFCTL1 */
|
||||
memory[ADDRESS + 0x04] = 0x0000; /* RF1AIFCTL2 */
|
||||
memory[ADDRESS + 0x06] = 0x0000; /* RF1AIFERR */
|
||||
memory[ADDRESS + 0x0c] = 0x0000; /* RF1AIFERRV */
|
||||
memory[ADDRESS + 0x0e] = 0x0000; /* RF1AIFIV */
|
||||
memory[ADDRESS + 0x10] = 0x0000; /* RF1AINSTRW */
|
||||
|
||||
memory[ADDRESS + 0x12] = 0x0000; /* RF1AINSTR1W */
|
||||
memory[ADDRESS + 0x14] = 0x0000; /* RF1AINSTR2B */
|
||||
memory[ADDRESS + 0x16] = 0x0000; /* RF1ADINW */
|
||||
|
||||
memory[ADDRESS + 0x20] = 0x0000; /* RF1ASTAT0W */
|
||||
memory[ADDRESS + 0x22] = 0x0000; /* RF1ASTAT1W */
|
||||
memory[ADDRESS + 0x24] = 0x0000; /* RF1ASTAT2W */
|
||||
memory[ADDRESS + 0x28] = 0x0000; /* RF1ADOUT0W */
|
||||
|
||||
memory[ADDRESS + 0x2a] = 0x0000; /* RF1ADOUT1W */
|
||||
memory[ADDRESS + 0x2c] = 0x0000; /* RF1ADOUT2W */
|
||||
|
||||
memory[ADDRESS + 0x30] = 0x0000; /* RF1AIN */
|
||||
memory[ADDRESS + 0x32] = 0x0000; /* RF1AIFG */
|
||||
memory[ADDRESS + 0x34] = 0x0000; /* RF1AIES */
|
||||
memory[ADDRESS + 0x36] = 0x0000; /* RF1AIE */
|
||||
memory[ADDRESS + 0x38] = 0x0000; /* RF1AIV */
|
||||
|
||||
memory[ADDRESS + 0x3c] = 0x0000; /* RF1ARXFIFO */
|
||||
memory[ADDRESS + 0x3e] = 0x0000; /* RF1ATXFIFO */
|
||||
|
||||
interruptOnCC1101GDO0 = false;
|
||||
|
||||
ioAddress = -1;
|
||||
ioBurst = false;
|
||||
ioRead = false;
|
||||
ioWrite = false;
|
||||
expectingDummyWrite = false;
|
||||
}
|
||||
|
||||
private int ioAddress = -1;
|
||||
private boolean ioBurst = false;
|
||||
private boolean ioRead = false;
|
||||
private boolean ioWrite = false;
|
||||
private boolean expectingDummyWrite = false;
|
||||
public void write(int address, int value, boolean word, long cycles) {
|
||||
/*if (DEBUG) {
|
||||
System.out.printf(this.getName() + ": Write to 0x%04x: 0x%04x\n", address, value);
|
||||
}*/
|
||||
|
||||
if (address == ADDRESS + RF1AIE) {
|
||||
/* Configure interrupts */
|
||||
interruptOnCC1101GDO0 = (value & 1) != 0;
|
||||
} else if (address == ADDRESS + RF1AINSTRW + 1) {
|
||||
/* Store address. Read/write? Burst/single? */
|
||||
expectingDummyWrite = false;
|
||||
ioBurst = CC1101.spiIsBurst(value);
|
||||
if (!ioBurst && CC1101.spiIsStrobe(value)) {
|
||||
/* Execute strobe command */
|
||||
cc1101.setLastInstructionWasRead(false); /* This is probably wrong! */
|
||||
ioBurst = false;
|
||||
ioRead = false;
|
||||
ioWrite = false;
|
||||
expectingDummyWrite = true;
|
||||
cc1101.strobe(value & (~CC1101.SPI_READ_BIT) & (~CC1101.SPI_BURST_BIT));
|
||||
} else {
|
||||
/* Store address */
|
||||
ioRead = CC1101.spiIsRead(value);
|
||||
ioWrite = !ioRead;
|
||||
cc1101.setLastInstructionWasRead(ioRead);
|
||||
ioAddress = value & (~CC1101.SPI_READ_BIT) & (~CC1101.SPI_BURST_BIT);
|
||||
if (DEBUG) {
|
||||
if (ioAddress == CC1101.CC1101_RXFIFO) {
|
||||
} else if (ioAddress == CC1101.CC1101_MARCSTATE) {
|
||||
} else if (ioAddress == CC1101.CC1101_RXBYTES) {
|
||||
} else if (ioAddress == CC1101.CC1101_TXBYTES) {
|
||||
} else {
|
||||
System.out.printf("IO address 0x%04x (" + (ioRead?"read":"write") + ", " + (ioBurst?"burst":"single") + ")\n", ioAddress);
|
||||
}
|
||||
}
|
||||
if (ioRead) {
|
||||
expectingDummyWrite = true;
|
||||
}
|
||||
}
|
||||
} else if (address == ADDRESS + RF1AINSTRW) {
|
||||
if (expectingDummyWrite) {
|
||||
/* Ignore dummy write */
|
||||
expectingDummyWrite = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ioRead && !ioWrite) {
|
||||
System.out.printf("Error: Unknown data mode for write 0x%04x\n", address);
|
||||
return;
|
||||
} else if (ioRead) {
|
||||
System.out.printf("Error: writing in read mode: 0x%04x\n", address);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write CC1101 register */
|
||||
cc1101.setReg(ioAddress, value);
|
||||
if (ioBurst) {
|
||||
if (ioAddress != CC1101.CC1101_TXFIFO && ioAddress != CC1101.CC1101_PATABLE) {
|
||||
ioAddress++;
|
||||
}
|
||||
} else {
|
||||
ioWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int read(int address, boolean word, long cycles) {
|
||||
/*if (DEBUG) {
|
||||
System.out.printf(this.getName() + ": Read from 0x%04x\n", address);
|
||||
}*/
|
||||
|
||||
if (address == ADDRESS + RF1AIV) {
|
||||
if (interruptOnCC1101GDO0 && gdo0IsHigh) {
|
||||
return 2; /* RF1AIV_RFIFG0 */
|
||||
}
|
||||
return 0;
|
||||
} else if (address == ADDRESS + RF1AIFCTL1) {
|
||||
/* XXX TODO: CTL1 always return 0xFF */
|
||||
return 0xff;
|
||||
} else if (address == ADDRESS + RF1ASTAT1W + 1) {
|
||||
/* Marcstate */
|
||||
return cc1101.getMarcstate();
|
||||
} else if (!word && address == ADDRESS + RF1ASTATB) {
|
||||
/* Status byte */
|
||||
return cc1101.getStatusByte();
|
||||
} else if (address == ADDRESS + RF1ADOUTB) {
|
||||
/* Return last received byte from emulated SPI interface */
|
||||
|
||||
if (!ioRead && !ioWrite) {
|
||||
System.out.printf("Error: Unknown data mode for read 0x%04x\n", address);
|
||||
return -1;
|
||||
} else if (ioWrite) {
|
||||
System.out.printf("Error: reading in write mode: 0x%04x\n", address);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read CC1101 register */
|
||||
int val = cc1101.getReg(ioAddress);
|
||||
|
||||
if (ioBurst) {
|
||||
if (ioAddress != CC1101.CC1101_TXFIFO && ioAddress != CC1101.CC1101_PATABLE) {
|
||||
ioAddress++;
|
||||
}
|
||||
} else {
|
||||
ioRead = false;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void interruptServiced(int vector) {
|
||||
if (DEBUG) {
|
||||
System.out.println(this.getName() + ": Interrupt services vector: " + vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package se.sics.mspsim.platform.ti;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import se.sics.mspsim.config.CC430f5137Config;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.PortListener;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
import se.sics.mspsim.platform.GenericNode;
|
||||
import se.sics.mspsim.ui.SerialMon;
|
||||
import se.sics.mspsim.util.ArgumentManager;
|
||||
|
||||
public class CC430Node extends GenericNode implements PortListener, USARTListener {
|
||||
|
||||
IOPort port1;
|
||||
IOPort port3;
|
||||
IOPort port4;
|
||||
IOPort port5;
|
||||
IOPort port7;
|
||||
IOPort port8;
|
||||
|
||||
public CC430Node() {
|
||||
/* TODO XXX MSP430F5438 */
|
||||
super("CC430", new CC430f5137Config());
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
}
|
||||
|
||||
public void portWrite(IOPort source, int data) {
|
||||
|
||||
}
|
||||
|
||||
private void setupNodePorts() {
|
||||
port1 = cpu.getIOUnit(IOPort.class, "P1");
|
||||
port1.addPortListener(this);
|
||||
port3 = cpu.getIOUnit(IOPort.class, "P3");
|
||||
port3.addPortListener(this);
|
||||
port4 = cpu.getIOUnit(IOPort.class, "P4");
|
||||
port4.addPortListener(this);
|
||||
port5 = cpu.getIOUnit(IOPort.class, "P5");
|
||||
port5.addPortListener(this);
|
||||
port7 = cpu.getIOUnit(IOPort.class, "P7");
|
||||
port7.addPortListener(this);
|
||||
port8 = cpu.getIOUnit(IOPort.class, "P8");
|
||||
port8.addPortListener(this);
|
||||
|
||||
IOUnit usart0 = cpu.getIOUnit("USCI B0");
|
||||
if (usart0 instanceof USARTSource) {
|
||||
registry.registerComponent("serialio0", usart0);
|
||||
}
|
||||
|
||||
IOUnit usart = cpu.getIOUnit("USCI A0");
|
||||
if (usart instanceof USARTSource) {
|
||||
registry.registerComponent("serialio", usart);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupNode() {
|
||||
setupNodePorts();
|
||||
|
||||
if (!config.getPropertyAsBoolean("nogui", true)) {
|
||||
// Add some windows for listening to serial output
|
||||
IOUnit usart = cpu.getIOUnit("USCI A0");
|
||||
if (usart instanceof USARTSource) {
|
||||
SerialMon serial = new SerialMon((USARTSource)usart, "USCI A0 Port Output");
|
||||
registry.registerComponent("serialgui", serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
CC430Node node = new CC430Node();
|
||||
ArgumentManager config = new ArgumentManager();
|
||||
config.handleArguments(args);
|
||||
node.setupArgs(config);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package se.sics.mspsim.platform.ti;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import se.sics.mspsim.chip.CC1101;
|
||||
import se.sics.mspsim.config.MSP430f5437Config;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.PortListener;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
import se.sics.mspsim.platform.GenericNode;
|
||||
import se.sics.mspsim.ui.SerialMon;
|
||||
import se.sics.mspsim.util.ArgumentManager;
|
||||
|
||||
public class Exp1101Node extends GenericNode implements PortListener, USARTListener {
|
||||
|
||||
public static final int CC1101_GDO0 = 7; /* 1.7 */
|
||||
public static final int CC1101_GDO2 = 3; /* 1.3 */
|
||||
|
||||
public static final int CC1101_CHIP_SELECT = (1 << 0); // 3.0
|
||||
|
||||
IOPort port1;
|
||||
IOPort port3;
|
||||
IOPort port4;
|
||||
IOPort port5;
|
||||
IOPort port7;
|
||||
IOPort port8;
|
||||
|
||||
public static final int LEDS_CONF_RED = (1 << 0); // 1.0
|
||||
public static final int LEDS_CONF_YELLOW = (1 << 1); // 1.1
|
||||
|
||||
public CC1101 radio;
|
||||
|
||||
public Exp1101Node() {
|
||||
super("Exp1101", new MSP430f5437Config());
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
radio.dataReceived(source, data);
|
||||
|
||||
/* if nothing selected, just write back a random byte to these devs */
|
||||
if (!radio.getChipSelect()) {
|
||||
source.byteReceived(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void portWrite(IOPort source, int data) {
|
||||
if (source == port3) {
|
||||
// Chip select = active low...
|
||||
radio.setChipSelect((data & CC1101_CHIP_SELECT) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupNodePorts() {
|
||||
port1 = cpu.getIOUnit(IOPort.class, "P1");
|
||||
port1.addPortListener(this);
|
||||
port3 = cpu.getIOUnit(IOPort.class, "P3");
|
||||
port3.addPortListener(this);
|
||||
port4 = cpu.getIOUnit(IOPort.class, "P4");
|
||||
port4.addPortListener(this);
|
||||
port5 = cpu.getIOUnit(IOPort.class, "P5");
|
||||
port5.addPortListener(this);
|
||||
port7 = cpu.getIOUnit(IOPort.class, "P7");
|
||||
port7.addPortListener(this);
|
||||
port8 = cpu.getIOUnit(IOPort.class, "P8");
|
||||
port8.addPortListener(this);
|
||||
|
||||
IOUnit usart0 = cpu.getIOUnit("USCI B0");
|
||||
if (usart0 instanceof USARTSource) {
|
||||
radio = new CC1101(cpu);
|
||||
radio.setGDO0(port1, CC1101_GDO0);
|
||||
radio.setGDO2(port1, CC1101_GDO2);
|
||||
((USARTSource) usart0).addUSARTListener(this);
|
||||
} else {
|
||||
throw new EmulationException("Could not setup exp1101 mote - missing USCI B0");
|
||||
}
|
||||
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
registry.registerComponent("serialio", usart);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupNode() {
|
||||
setupNodePorts();
|
||||
|
||||
if (!config.getPropertyAsBoolean("nogui", true)) {
|
||||
// Add some windows for listening to serial output
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
SerialMon serial = new SerialMon((USARTSource)usart, "USCI A1 Port Output");
|
||||
registry.registerComponent("serialgui", serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Exp1101Node node = new Exp1101Node();
|
||||
ArgumentManager config = new ArgumentManager();
|
||||
config.handleArguments(args);
|
||||
node.setupArgs(config);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package se.sics.mspsim.platform.ti;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import se.sics.mspsim.chip.CC1120;
|
||||
import se.sics.mspsim.config.MSP430f5437Config;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.PortListener;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
import se.sics.mspsim.platform.GenericNode;
|
||||
import se.sics.mspsim.ui.SerialMon;
|
||||
import se.sics.mspsim.util.ArgumentManager;
|
||||
|
||||
public class Exp1120Node extends GenericNode implements PortListener, USARTListener {
|
||||
|
||||
public static final int CC1120_GDO0 = 7; /* 1.7 */
|
||||
public static final int CC1120_GDO2 = 3; /* 1.3 */
|
||||
|
||||
public static final int CC1120_CHIP_SELECT = (1 << 0); // 3.0
|
||||
|
||||
IOPort port1;
|
||||
IOPort port3;
|
||||
IOPort port4;
|
||||
IOPort port5;
|
||||
IOPort port7;
|
||||
IOPort port8;
|
||||
|
||||
public static final int LEDS_CONF_RED = (1 << 0); // 1.0
|
||||
public static final int LEDS_CONF_YELLOW = (1 << 1); // 1.1
|
||||
|
||||
public CC1120 radio;
|
||||
|
||||
public Exp1120Node() {
|
||||
super("Exp1120", new MSP430f5437Config());
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
radio.dataReceived(source, data);
|
||||
|
||||
/* if nothing selected, just write back a random byte to these devs */
|
||||
if (!radio.getChipSelect()) {
|
||||
source.byteReceived(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void portWrite(IOPort source, int data) {
|
||||
if (source == port3) {
|
||||
// Chip select = active low...
|
||||
radio.setChipSelect((data & CC1120_CHIP_SELECT) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupNodePorts() {
|
||||
port1 = cpu.getIOUnit(IOPort.class, "P1");
|
||||
port1.addPortListener(this);
|
||||
port3 = cpu.getIOUnit(IOPort.class, "P3");
|
||||
port3.addPortListener(this);
|
||||
port4 = cpu.getIOUnit(IOPort.class, "P4");
|
||||
port4.addPortListener(this);
|
||||
port5 = cpu.getIOUnit(IOPort.class, "P5");
|
||||
port5.addPortListener(this);
|
||||
port7 = cpu.getIOUnit(IOPort.class, "P7");
|
||||
port7.addPortListener(this);
|
||||
port8 = cpu.getIOUnit(IOPort.class, "P8");
|
||||
port8.addPortListener(this);
|
||||
|
||||
IOUnit usart0 = cpu.getIOUnit("USCI B0");
|
||||
if (usart0 instanceof USARTSource) {
|
||||
radio = new CC1120(cpu);
|
||||
radio.setGDO0(port1, CC1120_GDO0);
|
||||
radio.setGDO2(port1, CC1120_GDO2);
|
||||
((USARTSource) usart0).addUSARTListener(this);
|
||||
} else {
|
||||
throw new EmulationException("Error creating Exp1120Node: no USCI B0");
|
||||
}
|
||||
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
registry.registerComponent("serialio", usart);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupNode() {
|
||||
setupNodePorts();
|
||||
|
||||
if (!config.getPropertyAsBoolean("nogui", true)) {
|
||||
// Add some windows for listening to serial output
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
SerialMon serial = new SerialMon((USARTSource)usart, "USCI A1 Port Output");
|
||||
registry.registerComponent("serialgui", serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Exp1120Node node = new Exp1120Node();
|
||||
ArgumentManager config = new ArgumentManager();
|
||||
config.handleArguments(args);
|
||||
node.setupArgs(config);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package se.sics.mspsim.platform.ti;
|
||||
|
||||
import se.sics.mspsim.chip.CC1120;
|
||||
import se.sics.mspsim.chip.Enc28J60;
|
||||
import se.sics.mspsim.config.MSP430f5437Config;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.PortListener;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
import se.sics.mspsim.platform.GenericNode;
|
||||
|
||||
public class Trxeb1120Node extends GenericNode implements PortListener, USARTListener {
|
||||
|
||||
public static final int CC1120_GDO0 = 7; /* 1.7 */
|
||||
public static final int CC1120_GDO2 = 3; /* 1.3 */
|
||||
public static final int CC1120_CHIP_SELECT = (1 << 0); // 3.0
|
||||
|
||||
public static final int ENC28J60_CLK = 2; /* 10.2 */
|
||||
public static final int ENC28J60_MOSI = 1; /* 10.1 */
|
||||
public static final int ENC28J60_MISO = 0; /* 10.0 */
|
||||
public static final int ENC28J60_CHIP_SELECT = 3; /* 10.3 */
|
||||
|
||||
IOPort port1;
|
||||
IOPort port3;
|
||||
IOPort port4;
|
||||
IOPort port5;
|
||||
IOPort port7;
|
||||
IOPort port8;
|
||||
IOPort port10;
|
||||
|
||||
public CC1120 radio;
|
||||
public Enc28J60 enc = null;
|
||||
|
||||
private boolean withEnc;
|
||||
|
||||
public Trxeb1120Node(boolean withEnc) {
|
||||
super("Trxeb1120", new MSP430f5437Config());
|
||||
|
||||
this.withEnc = withEnc;
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
radio.dataReceived(source, data);
|
||||
|
||||
/* if nothing selected, just write back a random byte to these devs */
|
||||
if (!radio.getChipSelect()) {
|
||||
source.byteReceived(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void portWrite(IOPort source, int data) {
|
||||
if (source == port3) {
|
||||
// Chip select = active low...
|
||||
radio.setChipSelect((data & CC1120_CHIP_SELECT) == 0);
|
||||
} else if (withEnc && source == port10) {
|
||||
enc.write(port10, data);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupNodePorts() {
|
||||
port1 = cpu.getIOUnit(IOPort.class, "P1");
|
||||
port1.addPortListener(this);
|
||||
port3 = cpu.getIOUnit(IOPort.class, "P3");
|
||||
port3.addPortListener(this);
|
||||
port4 = cpu.getIOUnit(IOPort.class, "P4");
|
||||
port4.addPortListener(this);
|
||||
port5 = cpu.getIOUnit(IOPort.class, "P5");
|
||||
port5.addPortListener(this);
|
||||
port7 = cpu.getIOUnit(IOPort.class, "P7");
|
||||
port7.addPortListener(this);
|
||||
port8 = cpu.getIOUnit(IOPort.class, "P8");
|
||||
port8.addPortListener(this);
|
||||
|
||||
IOUnit usart0 = cpu.getIOUnit("USCI B0");
|
||||
if (usart0 instanceof USARTSource) {
|
||||
radio = new CC1120(cpu);
|
||||
radio.setGDO0(port1, CC1120_GDO0);
|
||||
radio.setGDO2(port1, CC1120_GDO2);
|
||||
((USARTSource) usart0).addUSARTListener(this);
|
||||
} else {
|
||||
throw new EmulationException("Error creating Trxeb1120Node: no USCI B0");
|
||||
}
|
||||
|
||||
if (withEnc) {
|
||||
port10 = cpu.getIOUnit(IOPort.class, "P10");
|
||||
port10.addPortListener(this);
|
||||
enc = new Enc28J60(cpu, port10, ENC28J60_CLK, ENC28J60_MOSI, ENC28J60_MISO, ENC28J60_CHIP_SELECT);
|
||||
}
|
||||
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
registry.registerComponent("serialio", usart);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupNode() {
|
||||
setupNodePorts();
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package se.sics.mspsim.platform.ti;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import se.sics.mspsim.chip.CC2520;
|
||||
import se.sics.mspsim.config.MSP430f5437Config;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.IOPort;
|
||||
import se.sics.mspsim.core.IOUnit;
|
||||
import se.sics.mspsim.core.PortListener;
|
||||
import se.sics.mspsim.core.USARTListener;
|
||||
import se.sics.mspsim.core.USARTSource;
|
||||
import se.sics.mspsim.platform.GenericNode;
|
||||
import se.sics.mspsim.util.ArgumentManager;
|
||||
|
||||
public class Trxeb2520Node extends GenericNode implements PortListener, USARTListener {
|
||||
|
||||
/* TrxEB + CC2520EM 2.1.
|
||||
* Assuming non-default GPIO configuration (see trxeb2520 platform) */
|
||||
public static final int CC2520_FIFOP = 4; /* GPIO0 - 1.4 */
|
||||
public static final int CC2520_FIFO = 4; /* GPIO1 - 3.4 */
|
||||
public static final int CC2520_CCA = 3; /* GPIO3 - 1.3 */
|
||||
public static final int CC2520_SFD = 2; /* GPIO4 - 1.2 */
|
||||
|
||||
/* Output: VREG_EN to CC2520 */
|
||||
public static final int CC2520_VREG = (1 << 7); /* 1.7 */
|
||||
/* Output: SPI Chip Select (CS_N) */
|
||||
public static final int CC2520_CHIP_SELECT = (1 << 0); /* 3.0 */
|
||||
public static final int CC2520_RESET = (1 << 0); /* 8.0 */
|
||||
|
||||
IOPort port1;
|
||||
IOPort port3;
|
||||
IOPort port4;
|
||||
IOPort port5;
|
||||
IOPort port7;
|
||||
IOPort port8;
|
||||
|
||||
public CC2520 radio;
|
||||
|
||||
public Trxeb2520Node() {
|
||||
super("Trxeb2520", new MSP430f5437Config());
|
||||
}
|
||||
|
||||
public void dataReceived(USARTSource source, int data) {
|
||||
radio.dataReceived(source, data);
|
||||
|
||||
/* if nothing selected, just write back a random byte to these devs */
|
||||
if (!radio.getChipSelect()) {
|
||||
source.byteReceived(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void portWrite(IOPort source, int data) {
|
||||
if (source == port1) {
|
||||
radio.setVRegOn((data & CC2520_VREG) != 0);
|
||||
} else if (source == port3) {
|
||||
radio.setChipSelect((data & CC2520_CHIP_SELECT) == 0);
|
||||
} else if (source == port8) {
|
||||
// if ((data & CC2520_RESET) != 0) {
|
||||
// radio.notifyReset();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private void setupNodePorts() {
|
||||
port1 = cpu.getIOUnit(IOPort.class, "P1");
|
||||
port1.addPortListener(this);
|
||||
port3 = cpu.getIOUnit(IOPort.class, "P3");
|
||||
port3.addPortListener(this);
|
||||
port4 = cpu.getIOUnit(IOPort.class, "P4");
|
||||
port4.addPortListener(this);
|
||||
port5 = cpu.getIOUnit(IOPort.class, "P5");
|
||||
port5.addPortListener(this);
|
||||
port7 = cpu.getIOUnit(IOPort.class, "P7");
|
||||
port7.addPortListener(this);
|
||||
port8 = cpu.getIOUnit(IOPort.class, "P8");
|
||||
port8.addPortListener(this);
|
||||
|
||||
IOUnit usart0 = cpu.getIOUnit("USCI B0");
|
||||
if (usart0 instanceof USARTSource) {
|
||||
radio = new CC2520(cpu);
|
||||
radio.setGPIO(0, port1, CC2520_FIFOP);
|
||||
radio.setGPIO(1, port3, CC2520_FIFO);
|
||||
radio.setGPIO(3, port1, CC2520_CCA);
|
||||
radio.setGPIO(4, port1, CC2520_SFD);
|
||||
((USARTSource) usart0).addUSARTListener(this);
|
||||
} else {
|
||||
throw new EmulationException("Error creating Trxeb2520Node: no USCI B0");
|
||||
}
|
||||
|
||||
IOUnit usart = cpu.getIOUnit("USCI A1");
|
||||
if (usart instanceof USARTSource) {
|
||||
registry.registerComponent("serialio", usart);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupNode() {
|
||||
setupNodePorts();
|
||||
}
|
||||
|
||||
public int getModeMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Trxeb2520Node node = new Trxeb2520Node();
|
||||
ArgumentManager config = new ArgumentManager();
|
||||
config.handleArguments(args);
|
||||
node.setupArgs(config);
|
||||
}
|
||||
}
|
||||
|
|
@ -374,6 +374,7 @@ public class ELF {
|
|||
public MapTable getMap() {
|
||||
MapTable map = new MapTable();
|
||||
int sAddrHighest = -1;
|
||||
boolean foundEnd = false;
|
||||
|
||||
ELFSection name = sections[symTable.link];
|
||||
int len = symTable.size;
|
||||
|
|
@ -418,13 +419,14 @@ public class ELF {
|
|||
if (sAddr > 0 && sAddr < 0x100000) {
|
||||
String symbolName = sn;
|
||||
|
||||
if (sAddr < 0x5c00 && sAddr > sAddrHighest) {
|
||||
if (sAddr < 0x5c00 && sAddr > sAddrHighest && !sn.equals("__stack")) {
|
||||
sAddrHighest = sAddr;
|
||||
}
|
||||
// if (bind == ELFSection.SYMBIND_LOCAL) {
|
||||
// symbolName += " (" + currentFile + ')';
|
||||
// }
|
||||
if ("_end".equals(symbolName)) {
|
||||
foundEnd = true;
|
||||
map.setHeapStart(sAddr);
|
||||
} else if ("__stack".equals(symbolName)){
|
||||
map.setStackStart(sAddr);
|
||||
|
|
@ -455,10 +457,10 @@ public class ELF {
|
|||
addr += symTable.getEntrySize();
|
||||
}
|
||||
|
||||
if (map.getHeapStart() <= 0 && sAddrHighest > 0) {
|
||||
System.err.printf("Warning: Unable to parse _end symbol. I'm guessing that heap starts at 0x%05x\n", sAddrHighest);
|
||||
map.setHeapStart(sAddrHighest);
|
||||
}
|
||||
if (!foundEnd && sAddrHighest > 0) {
|
||||
System.out.printf("Warning: Unable to parse _end symbol. I'm guessing that heap starts at 0x%05x\n", sAddrHighest);
|
||||
map.setHeapStart(sAddrHighest);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue