diff --git a/se/sics/mspsim/chip/CC2420.java b/se/sics/mspsim/chip/CC2420.java index d51b624..cf234b3 100644 --- a/se/sics/mspsim/chip/CC2420.java +++ b/se/sics/mspsim/chip/CC2420.java @@ -222,6 +222,7 @@ public class CC2420 extends Radio802154 implements USARTListener { public static final int TYPE_BEACON_FRAME = 0x00; public static final int TYPE_DATA_FRAME = 0x01; public static final int TYPE_ACK_FRAME = 0x02; + public static final int TYPE_CMD_FRAME = 0x03; // FCF Low public static final int DESTINATION_ADDRESS_MODE = 0x30; @@ -614,7 +615,7 @@ public class CC2420 extends Radio802154 implements USARTListener { frameType = fcf0 & FRAME_TYPE; } else if (rxread == 2) { fcf1 = data & 0xff; - if (frameType == TYPE_DATA_FRAME) { + if (frameType == TYPE_DATA_FRAME || frameType == TYPE_CMD_FRAME) { ackRequest = (fcf0 & ACK_REQUEST) > 0; destinationAddressMode = (fcf1 >> 2) & 3; /* check this !!! */ diff --git a/se/sics/mspsim/core/ADC12Plus.java b/se/sics/mspsim/core/ADC12Plus.java index c2e6695..4b43a5c 100644 --- a/se/sics/mspsim/core/ADC12Plus.java +++ b/se/sics/mspsim/core/ADC12Plus.java @@ -78,6 +78,8 @@ package se.sics.mspsim.core; import java.util.Arrays; +import se.sics.mspsim.core.EmulationLogger.WarningType; + /** * ADC12 Plus IO peripheral diff --git a/se/sics/mspsim/core/AES128.java b/se/sics/mspsim/core/AES128.java index e11918a..68c0348 100644 --- a/se/sics/mspsim/core/AES128.java +++ b/se/sics/mspsim/core/AES128.java @@ -32,11 +32,11 @@ */ package se.sics.mspsim.core; -import java.nio.ByteBuffer; - import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; +import se.sics.mspsim.core.EmulationLogger.WarningType; + /** * AES128 msp430 peripheral emulation @@ -149,9 +149,64 @@ public class AES128 extends IOUnit { /** * Variable holders for the different registers needed by this peripheral */ - private ByteBuffer key = ByteBuffer.allocate(16); - private ByteBuffer inData = ByteBuffer.allocate(16); - private ByteBuffer outData = ByteBuffer.allocate(16); + + /* avoid using NIO resources */ + private static class ByteBuffer { + byte[] buffer; + int pos; + + ByteBuffer(int size) { + buffer = new byte[size]; + pos = 0; + } + + public int position() { + return pos; + } + + public void position(int p) { + pos = p; + } + + public boolean hasRemaining() { + return pos < buffer.length; + } + + public void clear() { + pos = 0; + } + + public void resetPos() { + pos = 0; + } + + public byte[] array() { + return buffer; + } + + public void put(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + put(bytes[i]); + } + } + + public void put(byte data) { + buffer[pos++] = data; + } + + /* assume that calling code is ok... */ + public byte get() { + return buffer[pos++]; + } + + public int limit() { + return buffer.length; + } + } + + private ByteBuffer key = new ByteBuffer(16); + private ByteBuffer inData = new ByteBuffer(16); + private ByteBuffer outData = new ByteBuffer(16); /** * Syntax sugar @@ -247,7 +302,7 @@ public class AES128 extends IOUnit { byte[] bytes = cipher.doFinal(inData.array()); outData.clear(); outData.put(bytes); - outData.rewind(); + outData.resetPos(); } catch (Exception e) { log(e.getStackTrace().toString()); } @@ -269,7 +324,7 @@ public class AES128 extends IOUnit { byte[] bytes = cipher.doFinal(inData.array()); outData.clear(); outData.put(bytes); - outData.rewind(); + outData.resetPos(); } catch (Exception e) { log(e.getStackTrace().toString()); } @@ -353,7 +408,7 @@ public class AES128 extends IOUnit { if (!advancedCipherMode) { value |= AESKEYWR; } else { - key.rewind(); + key.resetPos(); } } else { isBusy = true; @@ -380,7 +435,7 @@ public class AES128 extends IOUnit { if (!advancedCipherMode) { value |= AESKEYWR; } else { - inData.rewind(); + inData.resetPos(); } } else { inData.position(inData.limit()); diff --git a/se/sics/mspsim/core/GenericUSCI.java b/se/sics/mspsim/core/GenericUSCI.java index 7ac5c84..50f4ec1 100644 --- a/se/sics/mspsim/core/GenericUSCI.java +++ b/se/sics/mspsim/core/GenericUSCI.java @@ -1,7 +1,8 @@ package se.sics.mspsim.core; +import java.util.ArrayDeque; + import se.sics.mspsim.chip.I2CUnit.I2CData; -import se.sics.mspsim.util.RingBuffer; /** @@ -85,7 +86,7 @@ public class GenericUSCI extends IOUnit implements DMATrigger, USARTSource { private boolean readyForNextTransmit; private boolean stopConditionPending; - private RingBuffer txBuffer = new RingBuffer<>(100); + private ArrayDeque txBuffer = new ArrayDeque(100); public GenericUSCI(MSP430Core cpu, int uartIndex, int[] memory, MSP430Config config) { super(config.uartConfig[uartIndex].name, cpu, memory, config.uartConfig[uartIndex].offset); diff --git a/se/sics/mspsim/core/RTC.java b/se/sics/mspsim/core/RTC.java index 1eb208a..28234d0 100644 --- a/se/sics/mspsim/core/RTC.java +++ b/se/sics/mspsim/core/RTC.java @@ -35,6 +35,8 @@ package se.sics.mspsim.core; import java.util.Calendar; import java.util.GregorianCalendar; +import se.sics.mspsim.core.EmulationLogger.WarningType; + /** * RTC module for the MSP430 diff --git a/se/sics/mspsim/util/RingBuffer.java b/se/sics/mspsim/util/RingBuffer.java deleted file mode 100644 index 104a947..0000000 --- a/se/sics/mspsim/util/RingBuffer.java +++ /dev/null @@ -1,190 +0,0 @@ -package se.sics.mspsim.util; - -/****************************************************************************** - * File: RingBuffer.java - * - * Author: Keith Schwarz (htiek@cs.stanford.edu) - * - * An implementation of a synchronized queue backed by a ring buffer. This - * functionality and implementation is similar to the ArrayBlockingQueue class, - * but I thought that I'd implement my own version to get a better feel for how - * it works. - * - * A ring buffer is a space-efficient, locality-friendly implementation of a - * FIFO queue. It is implemented as a fixed-sized array that is treated as - * though it wraps around like a ring; it has no well-defined start or end - * point. This array stores two pointers, a read pointer and a write pointer, - * delineating where the next insert should take place and from where the next - * element should be dequeued. For example: - * - * [2] [3] [ ] [ ] [ ] [ ] [0] [1] - * ^ ^ - * | | - * write read - * - * When using a ring buffer, one must be careful not to let the read and write - * pointers cross one another. If this happens, future write operations will - * start overwriting old elements that have not yet been consumed. For this - * reason, most ring buffers adopt one of two strategies. First, the ring buffer - * can increase its size whenever it runs out of room. This approach allows the - * buffer to grow arbitrarily large if need be. The second option, and the one - * used in this implementation, is simply to block on a read or write when data - * is not available. This allows the ring buffer to implement the - * producer/consumer pattern fairly easily; any number of threads can begin - * creating data while some number of threads consume it, and at no time are too - * many elements kept in memory waiting to be read. - */ - -public final class RingBuffer { - /* The actual ring buffer. */ - private final T[] elements; - - /* The write pointer, represented as an offset into the array. */ - private int offset = 0; - - /* - * The read pointer is encoded implicitly by keeping track of the number of - * unconsumed elements. We can then determine its position by backing up that - * many positions before the read position. - */ - private int unconsumedElements = 0; - - /** - * Constructs a new RingBuffer with the specified capacity, which must be - * positive. - * - * @param size - * The capacity of the new ring buffer. - * @throws IllegalArgumentException - * If the capacity is negative. - */ - @SuppressWarnings("unchecked") - public RingBuffer(int size) { - /* Validate the size. */ - if (size <= 0) - throw new IllegalArgumentException( - "RingBuffer capacity must be positive."); - - /* Construct the array to be that size. */ - elements = (T[]) new Object[size]; - } - - /** - * Clear the buffer - */ - @SuppressWarnings("unchecked") - public synchronized void clear() { - offset = 0; - unconsumedElements = 0; - for (int i = 0; i < elements.length; i++) { - elements[i] = null; - } - } - - /** - * Appends an element to the ring buffer, blocking until space becomes - * available. - * - * @param elem - * The element to add to the ring buffer. - */ - public synchronized boolean add(T elem) { - /* - * Block until the capacity is nonzero. Otherwise we don't have any space - * to write. - */ - if (unconsumedElements == elements.length) - return false; - - /* - * Write the element into the next open spot, then advance the write - * pointer forward a step. - */ - elements[offset] = elem; - offset = (offset + 1) % elements.length; - - /* - * Increase the number of unconsumed elements by one, then notify any - * threads that are waiting that more data is now available. - */ - ++unconsumedElements; - return true; - } - - /** - * Returns the maximum capacity of the ring buffer. - * - * @return The maximum capacity of the ring buffer. - */ - public int capacity() { - return elements.length; - } - - /** - * Observes, but does not dequeue, the next available element, blocking until - * data becomes available. - * - * @return The next available element. - */ - public synchronized T peek() { - /* Wait for data to become available. */ - if (unconsumedElements == 0) - return null; - - /* - * Hand back the next value. The index of this next value is a bit tricky - * to compute. We know that there are unconsumedElements elements waiting - * to be read, and they're contiguously before the write position. - * However, the buffer wraps around itself, and so we can't just do a - * naive subtraction; that might end up giving us a negative index. To - * avoid this, we'll use a clever trick in which we'll add to the index - * the capacity minus the distance. This value must be positive, since the - * distance is never greater than the capacity, and if we then wrap this - * value around using the modulus operator we'll end up with a valid - * index. All of this machinery works because - * - * (x + (n - k)) mod n == (x - k) mod n - * - * And Java's modulus operator works best on positive values. - */ - return elements[(offset + (capacity() - unconsumedElements)) % capacity()]; - } - - /** - * Removes and returns the next available element, blocking until data - * becomes available. - * - * @return The next available element - */ - public synchronized T remove() { - /* Use peek() to get the element to return. */ - T result = peek(); - - /* Mark that one fewer elements are now available to read. */ - --unconsumedElements; - - /* Because there is more space left, wake up any waiting threads. */ - notifyAll(); - - return result; - } - - /** - * Returns the number of elements that are currently being stored in the ring - * buffer. - * - * @return The number of elements currently stored in the ring buffer. - */ - public synchronized int size() { - return unconsumedElements; - } - - /** - * Returns whether the ring buffer is empty. - * - * @return Whether the ring buffer is empty. - */ - public synchronized boolean isEmpty() { - return size() == 0; - } -} \ No newline at end of file