From 79cbf9f00c8547bd36e6f9648f0f1b6a6e40d9a5 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Tue, 24 Mar 2015 15:17:50 +0100 Subject: [PATCH] Updated the CC1101 and the CC1120 emulation code to the latest version --- se/sics/mspsim/chip/CC1101.java | 124 ++++++++++++++++++++----- se/sics/mspsim/chip/CC1120.java | 160 ++++++++++++++++++++++++++------ 2 files changed, 231 insertions(+), 53 deletions(-) diff --git a/se/sics/mspsim/chip/CC1101.java b/se/sics/mspsim/chip/CC1101.java index fa8d85d..1905e06 100644 --- a/se/sics/mspsim/chip/CC1101.java +++ b/se/sics/mspsim/chip/CC1101.java @@ -39,7 +39,7 @@ import se.sics.mspsim.core.USARTListener; import se.sics.mspsim.core.USARTSource; public class CC1101 extends Radio802154 implements USARTListener { - protected boolean DEBUG = true; + protected boolean DEBUG = false; /* cc1101-const.h: Configuration registers */ public static final int CC1101_IOCFG1 = 0x01; @@ -133,6 +133,9 @@ public class CC1101 extends Radio802154 implements USARTListener { 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), @@ -174,15 +177,18 @@ public class CC1101 extends Radio802154 implements USARTListener { } }; - public final static double SYMBOL_PERIOD = 0.016; /* TODO XXX 16 us */ 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; @@ -207,6 +213,24 @@ public class CC1101 extends Radio802154 implements USARTListener { 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); @@ -233,7 +257,38 @@ public class CC1101 extends Radio802154 implements USARTListener { break; case CC1101_SRX: - setState(CC1101RadioState.CC1101_STATE_RX); + 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: @@ -248,6 +303,7 @@ public class CC1101 extends Radio802154 implements USARTListener { case CC1101_SIDLE: setState(CC1101RadioState.CC1101_STATE_IDLE); + currentRssiValid = false; break; case CC1101_SAFC: @@ -259,11 +315,11 @@ public class CC1101 extends Radio802154 implements USARTListener { break; case CC1101_SPWD: - log("CC1101_SPWD almost implemented"); + // 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_IDLE); + setState(CC1101RadioState.CC1101_STATE_SLEEP); break; case CC1101_SFRX: @@ -285,7 +341,7 @@ public class CC1101 extends Radio802154 implements USARTListener { break; case CC1101_SNOP: - log("CC1101_SNOP not implemented"); + // log("CC1101_SNOP not implemented"); break; default: @@ -398,6 +454,8 @@ public class CC1101 extends Radio802154 implements USARTListener { 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: @@ -407,13 +465,14 @@ public class CC1101 extends Radio802154 implements USARTListener { /*log("getReg(CC1101_TXBYTES) " + txfifo.size());*/ return txfifo.size(); case CC1101_PKTSTATUS: - int status; - final int CCA_BIT = (1<<4); - if(currentRssiReg < CCA_THRESHOLD) { - status = CCA_BIT; - } else { - status = 0; - } + 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; @@ -421,6 +480,9 @@ public class CC1101 extends Radio802154 implements USARTListener { 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"); @@ -468,7 +530,7 @@ public class CC1101 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (0xaa)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); return; } /* Send NUM_SYNCH-1 synch bytes */ @@ -477,7 +539,7 @@ public class CC1101 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (SYNCH_BYTE_LAST + 1)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); return; } /* Send last synch byte */ @@ -486,7 +548,7 @@ public class CC1101 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (SYNCH_BYTE_LAST)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); txSentSynchByte = true; return; @@ -518,7 +580,7 @@ public class CC1101 extends Radio802154 implements USARTListener { rfListener.receivedByte((byte) (0xee)); } txSentFirstCRC = true; - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); return; } @@ -528,7 +590,8 @@ public class CC1101 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) 0); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); setState(CC1101RadioState.CC1101_STATE_TXFIFO_UNDERFLOW); return; } @@ -537,7 +600,7 @@ public class CC1101 extends Radio802154 implements USARTListener { rfListener.receivedByte((byte) (txfifo.get(0).intValue())); } txfifo.remove(0); - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, getInterByteDelayMs()); /*printTXFIFO();*/ } @@ -643,11 +706,16 @@ public class CC1101 extends Radio802154 implements USARTListener { 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; - setGDO0(true); + if(triggerGDO0onSynch) { + setGDO0(true); + } } return; } @@ -663,7 +731,16 @@ public class CC1101 extends Radio802154 implements USARTListener { rxGotSynchByte = false; } - rxfifo.add(data); + 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();*/ } @@ -749,10 +826,11 @@ public class CC1101 extends Radio802154 implements USARTListener { void setStateRX() { setState(CC1101RadioState.CC1101_STATE_RX); + currentRssiValid = true; } void reset() { - setState(CC1101RadioState.CC1101_STATE_IDLE); + setState(CC1101RadioState.CC1101_STATE_SLEEP); registers[CC1101_PARTNUM] = 0; registers[CC1101_VERSION] = 6; diff --git a/se/sics/mspsim/chip/CC1120.java b/se/sics/mspsim/chip/CC1120.java index 54d2774..8a3b22e 100755 --- a/se/sics/mspsim/chip/CC1120.java +++ b/se/sics/mspsim/chip/CC1120.java @@ -252,6 +252,9 @@ public class CC1120 extends Radio802154 implements USARTListener { public final static int CCA_THRESHOLD = -95; + private boolean triggerGDO0onSynch = false; + private boolean triggerGDO0onFifoThreshold = false; + public static enum CC1120RadioState { CC1120_STATE_SLEEP(0b00000)/* 0 */, CC1120_STATE_IDLE(0b00001), @@ -297,7 +300,7 @@ public class CC1120 extends Radio802154 implements USARTListener { protected boolean DEBUG = false; - public final static double SYMBOL_PERIOD = 0.016; /* TODO XXX 16 us */ + public final static double BITRATE_BYTE_DURATION = 0.16; /* ms. Duration per byte transmitted, corresponds to 50kbit/s */ public final static double FREQUENCY_CHANNEL_0 = 902; /* MHz */ public final static double FREQUENCY_CHANNEL_WIDTH = 0.125; /* MHz */ @@ -355,7 +358,42 @@ public class CC1120 extends Radio802154 implements USARTListener { break; case CC1120_SRX: - setState(CC1120RadioState.CC1120_STATE_RX); + + if(getState() == CC1120RadioState.CC1120_STATE_IDLE || + getState() == CC1120RadioState.CC1120_STATE_SLEEP) { + TimeEvent goToRX = new TimeEvent(0, "CC1120 go to RX") { + public void execute(long t) { + if(getState() == CC1120RadioState.CC1120_STATE_RX) { + /* Radio already in RX, ignore */ + return; + } + rxfifo.clear(); + rxExpectedLen = -1; + rxGotSynchByte = false; + setGDO0(false); + setState(CC1120RadioState.CC1120_STATE_RX); + } + }; + + /* The time to activate RX depends on SETTLING_CFG's FS_AUTOCAL settings. + * Calibrated from trxeb1120 platform. */ + double stateDelay; + int settling = getRegister(CC1120_SETTLING_CFG); + settling = (settling >> 3) & 0b11; /* bit 4:3 */ + if (settling == 0) { + stateDelay = 0.20; + } else if (settling == 1) { + stateDelay = 0.50; + } else { + /* not implemented: assuming calibration */ + stateDelay = 0.50; + } + cpu.scheduleTimeEventMillis(goToRX, stateDelay); + + } else { + setStateRX(); + } + break; case CC1120_STX: @@ -381,7 +419,7 @@ public class CC1120 extends Radio802154 implements USARTListener { break; case CC1120_SPWD: - System.out.println("CC1120_SPWD almost implemented"); + /*System.out.println("CC1120_SPWD almost implemented");*/ /* TODO XXX * Wait until CS is de-asserted. (We should at least wait until radio is done * receiving or transmitting.)*/ @@ -526,6 +564,9 @@ public class CC1120 extends Radio802154 implements USARTListener { return; } int setReg(int address, int data, boolean extended) { + /*System.err.println(String.format("setReg(0x%02x, %s) 0x%02x", address, + extended ? "extended" : "normal", data));*/ + switch (address) { case CC1120_TXFIFO: txfifo.add((byte) data); @@ -540,16 +581,45 @@ public class CC1120 extends Radio802154 implements USARTListener { case CC1120_FREQ0: nextFreq0 = data; return 0; + case CC1120_IOCFG0: + if (data == 65 || data == 1) { + /* CC1120_SETTING_IOCFG0 (IOCFG_GPIO_CFG_RXFIFO_THR_PKT) + * or + * CC1120_SETTING_IOCFG0 (IOCFG_GPIO_CFG_RXFIFO_THR_PKT | IOCFG_GPIO_CFG_INVERT) */ + triggerGDO0onFifoThreshold = true; + } else { + /* Assuming: + * CC1120_SETTING_IOCFG0 (IOCFG_GPIO_CFG_PKT_SYNC_RXTX | IOCFG_GPIO_CFG_INVERT) */ + triggerGDO0onSynch = true; + } + return 0; } - System.out.println(String.format("setReg(0x%02x, %s) 0x%02x", address, - extended ? "extended" : "normal", data)); if (extended) { int oldValue = extendedRegisters[address]; extendedRegisters[address] = data; configurationChanged(address, oldValue, data); return oldValue; } + + switch (address) { + case CC1120_DRATE0: + if (data != 0x99) { + System.err.println("Warning: incompatible CC1120 data rate. Only 50kbit/s (0x99) is currently supported. CC1120_DRATE0: " + Integer.toHexString(data)); + } + return 0; + case CC1120_DRATE1: + if (data != 0x99) { + System.err.println("Warning: incompatible CC1120 data rate. Only 50kbit/s (0x99) is currently supported. CC1120_DRATE1: " + Integer.toHexString(data)); + } + return 0; + case CC1120_DRATE2: + if (data != 0x99) { + System.err.println("Warning: incompatible CC1120 data rate. Only 50kbit/s (0x99) is currently supported. CC1120_DRATE2: " + Integer.toHexString(data)); + } + return 0; + } + int oldValue = registers[address]; registers[address] = data; configurationChanged(address, oldValue, data); @@ -572,7 +642,7 @@ public class CC1120 extends Radio802154 implements USARTListener { ret += (0b1111 & currentRssiReg0); /* RSSI_3_0 */ ret = ret << 1; - if(getRSSI() < CCA_THRESHOLD) { + if(currentRssi > CCA_THRESHOLD) { ret += 1; /* Carrier detected */ } else { ret += 0; /* No carrier detected */ @@ -593,18 +663,23 @@ public class CC1120 extends Radio802154 implements USARTListener { 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"); + + /* RXFIFO underflow */ + setState(CC1120RadioState.CC1120_STATE_RX_FIFO_ERR); return -1; } if (address != CC1120.CC1120_MARCSTATE) { - System.out - .println(String.format("getReg(0x%02x, %s) 0x%02x", + /*System.out.println(String.format("getReg(0x%02x, %s) 0x%02x", address, extended ? "extended" : "normal", extended ? extendedRegisters[address] - : registers[address])); + : registers[address]));*/ } if (extended) { @@ -632,6 +707,7 @@ public class CC1120 extends Radio802154 implements USARTListener { public static final int NUM_PREAMBLE = 4; public static final int NUM_SYNCH = 4; public static final byte SYNCH_BYTE_LAST = (byte) 0xDE; + private boolean txPreambleDelay = false; private boolean txSentSynchByte = false; private int txSendSynchByteCnt = 0; private boolean txSentFirstCRC = false; @@ -641,6 +717,13 @@ public class CC1120 extends Radio802154 implements USARTListener { return; } + /* Delay */ + if (!txPreambleDelay) { + cpu.scheduleTimeEventMillis(sendEvent, 0.75); + txPreambleDelay = true; + return; + } + /* Send preamble and synch bytes */ if (!txSentSynchByte) { /* Send NUM_PREAMBLE preamble bytes */ @@ -649,7 +732,7 @@ public class CC1120 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (0xaa)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); return; } /* Send NUM_SYNCH-1 synch bytes */ @@ -658,7 +741,7 @@ public class CC1120 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (SYNCH_BYTE_LAST + 1)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); return; } /* Send last synch byte */ @@ -667,7 +750,7 @@ public class CC1120 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) (SYNCH_BYTE_LAST)); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); txSentSynchByte = true; return; @@ -685,6 +768,7 @@ public class CC1120 extends Radio802154 implements USARTListener { System.out.println("Warning: TXFIFO not empty after sending CRC bytes"); } setStateRX(); + txPreambleDelay = false; txSentSynchByte = false; txSendSynchByteCnt = 0; txSentFirstCRC = false; @@ -699,7 +783,7 @@ public class CC1120 extends Radio802154 implements USARTListener { rfListener.receivedByte((byte) (0xee)); } txSentFirstCRC = true; - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); return; } @@ -709,7 +793,7 @@ public class CC1120 extends Radio802154 implements USARTListener { if (rfListener != null) { rfListener.receivedByte((byte) 0); } - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); return; } @@ -717,7 +801,7 @@ public class CC1120 extends Radio802154 implements USARTListener { rfListener.receivedByte((byte) (txfifo.get(0).intValue())); } txfifo.remove(0); - cpu.scheduleTimeEventMillis(sendEvent, SYMBOL_PERIOD * 2); + cpu.scheduleTimeEventMillis(sendEvent, BITRATE_BYTE_DURATION); /* printTXFIFO(); */ } @@ -777,11 +861,11 @@ public class CC1120 extends Radio802154 implements USARTListener { } boolean receiverOn = false; - boolean setState(CC1120RadioState newState) { + boolean setState(final CC1120RadioState newState) { if (newState != CC1120RadioState.CC1120_STATE_IDLE && newState != CC1120RadioState.CC1120_STATE_RX && newState != CC1120RadioState.CC1120_STATE_TX) { - System.out.println("setState(" + newState + ")"); + /*System.out.println("setState(" + newState + ")");*/ } if (changeFrequencyNextState @@ -807,12 +891,13 @@ public class CC1120 extends Radio802154 implements USARTListener { /* Notify state listener */ if (stateListener != null) { - stateListener.newState(state); + stateListener.newState(state); } if (receiverListener != null && isReadyToReceive() != receiverOn) { - receiverOn = isReadyToReceive(); - receiverListener.newState(receiverOn); + receiverOn = isReadyToReceive(); + receiverListener.newState(receiverOn); } + return true; } @@ -823,7 +908,10 @@ public class CC1120 extends Radio802154 implements USARTListener { /* Await synch byte */ if (data == SYNCH_BYTE_LAST) { rxGotSynchByte = true; - setGDO0(true); + + if(triggerGDO0onSynch) { + setGDO0(true); + } } return; } @@ -834,12 +922,22 @@ public class CC1120 extends Radio802154 implements USARTListener { rxExpectedLen--; if (rxExpectedLen == 0) { - setGDO0(false); + setGDO0(false); /* triggerGDO0onFifoThreshold, triggerGDO0onSynch */ rxExpectedLen = -1; rxGotSynchByte = false; } - rxfifo.add(data); + if (rxfifo.size() < 128) { + /* printRXFIFO(); */ + rxfifo.add(data); + + if (triggerGDO0onFifoThreshold && rxfifo.size() >= 3 && rxExpectedLen > 0) { + setGDO0(true); + } + } else { + /* RXFIFO overflow */ + setState(CC1120RadioState.CC1120_STATE_RX_FIFO_ERR); + } /* printRXFIFO(); */ } @@ -855,12 +953,14 @@ public class CC1120 extends Radio802154 implements USARTListener { registers[register] = data; } - public void setRSSI(int power) { - currentRssiReg1 = 0xff&power; - } - public int getRSSI() { - return currentRssiReg1; - } + private int currentRssi = -100; + public void setRSSI(int power) { + currentRssi = power; + currentRssiReg1 = 0xff&power; + } + public int getRSSI() { + return currentRssiReg1; + } public int getActiveFrequency() { return (int) (1000 * Math.round(frequency)); /* kHz */