From f1e8246a1d623ae342791d42e88c4fde219890f2 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Thu, 29 Aug 2013 19:50:24 +0200 Subject: [PATCH] Emulation support for the TI CC430 sub-GHz SoC --- images/cc430.jpg | Bin 0 -> 41071 bytes se/sics/mspsim/config/CC430f5137Config.java | 166 +++++++++++++ se/sics/mspsim/core/PMMDummy.java | 56 +++++ se/sics/mspsim/core/RF1A.java | 248 ++++++++++++++++++++ se/sics/mspsim/platform/ti/CC430Node.java | 84 +++++++ 5 files changed, 554 insertions(+) create mode 100755 images/cc430.jpg create mode 100644 se/sics/mspsim/config/CC430f5137Config.java create mode 100755 se/sics/mspsim/core/PMMDummy.java create mode 100644 se/sics/mspsim/core/RF1A.java create mode 100644 se/sics/mspsim/platform/ti/CC430Node.java diff --git a/images/cc430.jpg b/images/cc430.jpg new file mode 100755 index 0000000000000000000000000000000000000000..19d84c9b2f21591f35245523478c609d7e3445d1 GIT binary patch literal 41071 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 literal 0 HcmV?d00001 diff --git a/se/sics/mspsim/config/CC430f5137Config.java b/se/sics/mspsim/config/CC430f5137Config.java new file mode 100644 index 0000000..979c905 --- /dev/null +++ b/se/sics/mspsim/config/CC430f5137Config.java @@ -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 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); + } + +} diff --git a/se/sics/mspsim/core/PMMDummy.java b/se/sics/mspsim/core/PMMDummy.java new file mode 100755 index 0000000..e69bc92 --- /dev/null +++ b/se/sics/mspsim/core/PMMDummy.java @@ -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); + } + } +} diff --git a/se/sics/mspsim/core/RF1A.java b/se/sics/mspsim/core/RF1A.java new file mode 100644 index 0000000..840810d --- /dev/null +++ b/se/sics/mspsim/core/RF1A.java @@ -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); + } + } +} diff --git a/se/sics/mspsim/platform/ti/CC430Node.java b/se/sics/mspsim/platform/ti/CC430Node.java new file mode 100644 index 0000000..05f5266 --- /dev/null +++ b/se/sics/mspsim/platform/ti/CC430Node.java @@ -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); + } +} \ No newline at end of file