Merge pull request #30 from nfi/updates-from-contiki-os-mspsim-submodule

Updates from contiki os mspsim submodule
This commit is contained in:
Joakim Eriksson 2015-09-04 15:46:04 +02:00
commit 13f10ee00e
17 changed files with 3269 additions and 26 deletions

4
.gitignore vendored
View File

@ -3,8 +3,8 @@
*.class
# Package Files #
*.jar
./*.jar
*.war
*.ear
.DS_Store
.DS_Store

BIN
images/cc430.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -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))

View File

@ -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;
}
}

1039
se/sics/mspsim/chip/CC1120.java Executable file

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

272
se/sics/mspsim/chip/Enc28J60.java Executable file
View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}