Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki
This commit is contained in:
commit
d716ee55e7
|
@ -723,7 +723,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
|||
watchdog_periodic();
|
||||
t0 = RTIMER_NOW();
|
||||
seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
|
||||
|
||||
previous_txtime = RTIMER_NOW();
|
||||
for(strobes = 0, collisions = 0;
|
||||
got_strobe_ack == 0 && collisions == 0 &&
|
||||
RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
|
||||
|
@ -737,7 +737,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
|||
|
||||
len = 0;
|
||||
|
||||
previous_txtime = RTIMER_NOW();
|
||||
|
||||
{
|
||||
rtimer_clock_t wt;
|
||||
rtimer_clock_t txtime;
|
||||
|
|
|
@ -781,6 +781,7 @@ input_packet(void)
|
|||
{
|
||||
struct lpp_hdr hdr;
|
||||
clock_time_t reception_time;
|
||||
int ret;
|
||||
|
||||
reception_time = clock_time();
|
||||
|
||||
|
@ -845,7 +846,7 @@ input_packet(void)
|
|||
if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
|
||||
i->broadcast_flag == BROADCAST_FLAG_SEND) {
|
||||
i->num_transmissions = 1;
|
||||
NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
|
||||
ret = NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
|
||||
queuebuf_datalen(i->packet));
|
||||
sent = 1;
|
||||
PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
|
||||
|
@ -860,7 +861,7 @@ input_packet(void)
|
|||
}
|
||||
#else /* WITH_PENDING_BROADCAST */
|
||||
i->num_transmissions = 1;
|
||||
NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
|
||||
ret = NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
|
||||
queuebuf_datalen(i->packet));
|
||||
PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
|
||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||
|
@ -879,12 +880,23 @@ input_packet(void)
|
|||
neighbors, and are dequeued by the dutycycling function
|
||||
instead, after the appropriate time. */
|
||||
if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
|
||||
#if RDC_CONF_HARDWARE_ACK
|
||||
|
||||
if(ret == RADIO_TX_OK) {
|
||||
remove_queued_packet(i, 1);
|
||||
} else {
|
||||
remove_queued_packet(i, 0);
|
||||
}
|
||||
#else
|
||||
if(detect_ack()) {
|
||||
remove_queued_packet(i, 1);
|
||||
} else {
|
||||
remove_queued_packet(i, 0);
|
||||
}
|
||||
|
||||
#endif /* RDC_CONF_HARDWARE_ACK */
|
||||
|
||||
|
||||
#if WITH_PROBE_AFTER_TRANSMISSION
|
||||
/* Send a probe packet to catch any reply from the other node. */
|
||||
restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
|
||||
|
|
|
@ -454,6 +454,7 @@ send_packet(void)
|
|||
rtimer_clock_t t;
|
||||
rtimer_clock_t encounter_time = 0;
|
||||
int strobes;
|
||||
int ret;
|
||||
#if 0
|
||||
struct xmac_hdr *hdr;
|
||||
#endif
|
||||
|
@ -640,11 +641,11 @@ send_packet(void)
|
|||
|
||||
if(is_broadcast) {
|
||||
#if WITH_STROBE_BROADCAST
|
||||
NETSTACK_RADIO.send(strobe, strobe_len);
|
||||
ret = NETSTACK_RADIO.send(strobe, strobe_len);
|
||||
#else
|
||||
/* restore the packet to send */
|
||||
queuebuf_to_packetbuf(packet);
|
||||
NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||
ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||
#endif
|
||||
off();
|
||||
} else {
|
||||
|
@ -652,7 +653,7 @@ send_packet(void)
|
|||
rtimer_clock_t wt;
|
||||
#endif
|
||||
on();
|
||||
NETSTACK_RADIO.send(strobe, strobe_len);
|
||||
ret = NETSTACK_RADIO.send(strobe, strobe_len);
|
||||
#if 0
|
||||
/* Turn off the radio for a while to let the other side
|
||||
respond. We don't need to keep our radio on when we know
|
||||
|
@ -661,12 +662,20 @@ send_packet(void)
|
|||
wt = RTIMER_NOW();
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
|
||||
#endif /* 0 */
|
||||
|
||||
#if RDC_CONF_HARDWARE_ACK
|
||||
if(ret == RADIO_TX_OK) {
|
||||
got_strobe_ack = 1;
|
||||
} else {
|
||||
off();
|
||||
}
|
||||
#else
|
||||
if(detect_ack()) {
|
||||
got_strobe_ack = 1;
|
||||
} else {
|
||||
off();
|
||||
}
|
||||
#endif /* RDC_CONF_HARDWARE_ACK */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,12 +702,18 @@ send_packet(void)
|
|||
|
||||
/* Send the data packet. */
|
||||
if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
|
||||
NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||
ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||
|
||||
if(!is_broadcast) {
|
||||
#if RDC_CONF_HARDWARE_ACK
|
||||
if(ret == RADIO_TX_OK) {
|
||||
got_ack = 1;
|
||||
}
|
||||
#else
|
||||
if(detect_ack()) {
|
||||
got_ack = 1;
|
||||
}
|
||||
#endif /* RDC_CONF_HARDWARE_ACK */
|
||||
}
|
||||
}
|
||||
off();
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
* Machine dependent STM32W radio code.
|
||||
* \author
|
||||
* Salvatore Pitrulli
|
||||
* Chi-Anh La la@imag.fr
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -53,13 +55,26 @@
|
|||
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/rime/rimestats.h"
|
||||
|
||||
|
||||
#include "sys/rtimer.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#include "dev/leds.h"
|
||||
#define LED_ACTIVITY 0
|
||||
|
||||
#ifdef ST_CONF_RADIO_AUTOACK
|
||||
#define ST_RADIO_AUTOACK ST_CONF_RADIO_AUTOACK
|
||||
#else
|
||||
#define ST_RADIO_AUTOACK 0
|
||||
#endif /* ST_CONF_RADIO_AUTOACK */
|
||||
|
||||
#if RDC_CONF_DEBUG_LED
|
||||
#define LED_RDC RDC_CONF_DEBUG_LED
|
||||
#define LED_ACTIVITY 1
|
||||
#else
|
||||
#define LED_RDC 0
|
||||
#endif
|
||||
|
||||
|
||||
#if DEBUG > 0
|
||||
#include <stdio.h>
|
||||
|
@ -71,13 +86,37 @@
|
|||
#if LED_ACTIVITY
|
||||
#define LED_TX_ON() leds_on(LEDS_GREEN)
|
||||
#define LED_TX_OFF() leds_off(LEDS_GREEN)
|
||||
#define LED_RX_ON() leds_on(LEDS_RED)
|
||||
#define LED_RX_OFF() leds_off(LEDS_RED)
|
||||
#define LED_RX_ON() { \
|
||||
if(LED_RDC == 0){ \
|
||||
leds_on(LEDS_RED); \
|
||||
} \
|
||||
}
|
||||
#define LED_RX_OFF() { \
|
||||
if(LED_RDC == 0){ \
|
||||
leds_off(LEDS_RED); \
|
||||
} \
|
||||
}
|
||||
#define LED_RDC_ON() { \
|
||||
if(LED_RDC == 1){ \
|
||||
leds_on(LEDS_RED); \
|
||||
} \
|
||||
}
|
||||
#define LED_RDC_OFF() { \
|
||||
if(LED_RDC == 1){ \
|
||||
leds_off(LEDS_RED); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LED_TX_ON()
|
||||
#define LED_TX_OFF()
|
||||
#define LED_RX_ON()
|
||||
#define LED_RX_OFF()
|
||||
#define LED_RDC_ON()
|
||||
#define LED_RDC_OFF()
|
||||
#endif
|
||||
|
||||
#if RDC_CONF_HARDWARE_CSMA
|
||||
#define MAC_RETRIES 0
|
||||
#endif
|
||||
|
||||
#ifndef MAC_RETRIES
|
||||
|
@ -113,16 +152,28 @@
|
|||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
|
||||
} \
|
||||
}
|
||||
|
||||
#if RDC_CONF_HARDWARE_CSMA
|
||||
#define ST_RADIO_CHECK_CCA FALSE
|
||||
#define ST_RADIO_CCA_ATTEMPT_MAX 0
|
||||
#define ST_BACKOFF_EXP_MIN 0
|
||||
#define ST_BACKOFF_EXP_MAX 0
|
||||
#else
|
||||
#define ST_RADIO_CHECK_CCA TRUE
|
||||
#define ST_RADIO_CCA_ATTEMPT_MAX 4
|
||||
#define ST_BACKOFF_EXP_MIN 2
|
||||
#define ST_BACKOFF_EXP_MAX 6
|
||||
#endif
|
||||
const RadioTransmitConfig radioTransmitConfig = {
|
||||
TRUE, // waitForAck;
|
||||
TRUE, // checkCca; // Set to FALSE with low-power MACs.
|
||||
4, // ccaAttemptMax;
|
||||
2, // backoffExponentMin;
|
||||
6, // backoffExponentMax;
|
||||
ST_RADIO_CHECK_CCA, // checkCca; // Set to FALSE with low-power MACs.
|
||||
ST_RADIO_CCA_ATTEMPT_MAX, // ccaAttemptMax;
|
||||
ST_BACKOFF_EXP_MIN, // backoffExponentMin;
|
||||
ST_BACKOFF_EXP_MAX, // backoffExponentMax;
|
||||
TRUE // appendCrc;
|
||||
};
|
||||
|
||||
#define MAC_RETRIES 0
|
||||
|
||||
/*
|
||||
* The buffers which hold incoming data.
|
||||
*/
|
||||
|
@ -173,6 +224,20 @@ static uint8_t receiving_packet = 0;
|
|||
static s8 last_rssi;
|
||||
static volatile StStatus last_tx_status;
|
||||
|
||||
#define BUSYWAIT_UNTIL(cond, max_time) \
|
||||
do { \
|
||||
rtimer_clock_t t0; \
|
||||
t0 = RTIMER_NOW(); \
|
||||
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
|
||||
} while(0)
|
||||
|
||||
static uint8_t locked;
|
||||
#define GET_LOCK() locked++
|
||||
static void RELEASE_LOCK(void) {
|
||||
if(locked>0)
|
||||
locked--;
|
||||
}
|
||||
static volatile uint8_t is_transmit_ack;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(stm32w_radio_process, "STM32W radio driver");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -208,20 +273,26 @@ const struct radio_driver stm32w_radio_driver =
|
|||
/*---------------------------------------------------------------------------*/
|
||||
static int stm32w_radio_init(void)
|
||||
{
|
||||
|
||||
// A channel needs also to be setted.
|
||||
ST_RadioSetChannel(RF_CHANNEL);
|
||||
|
||||
// Initialize radio (analog section, digital baseband and MAC).
|
||||
// Leave radio powered up in non-promiscuous rx mode.
|
||||
ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
|
||||
|
||||
onoroff = OFF;
|
||||
ST_RadioSetNodeId(STM32W_NODE_ID); // To be deleted.
|
||||
ST_RadioSetPanId(IEEE802154_PANID);
|
||||
|
||||
CLEAN_RXBUFS();
|
||||
CLEAN_TXBUF();
|
||||
|
||||
#if ST_RADIO_AUTOACK && !(UIP_CONF_LL_802154 && RIMEADDR_CONF_SIZE==8)
|
||||
#error "Autoack and address filtering can only be used with EUI 64"
|
||||
#endif
|
||||
ST_RadioEnableAutoAck(ST_RADIO_AUTOACK);
|
||||
ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
|
||||
|
||||
locked = 0;
|
||||
process_start(&stm32w_radio_process, NULL);
|
||||
|
||||
return 0;
|
||||
|
@ -291,6 +362,10 @@ static int stm32w_radio_transmit(unsigned short payload_len)
|
|||
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||
}
|
||||
|
||||
#if RADIO_WAIT_FOR_PACKET_SENT
|
||||
GET_LOCK();
|
||||
#endif /* RADIO_WAIT_FOR_PACKET_SENT */
|
||||
last_tx_status = -1;
|
||||
LED_TX_ON();
|
||||
if(ST_RadioTransmit(stm32w_txbuf)==ST_SUCCESS){
|
||||
|
||||
|
@ -312,14 +387,21 @@ static int stm32w_radio_transmit(unsigned short payload_len)
|
|||
PRINTF("stm32w: unknown tx error.\r\n");
|
||||
TO_PREV_STATE();
|
||||
LED_TX_OFF();
|
||||
RELEASE_LOCK();
|
||||
return RADIO_TX_ERR;
|
||||
}
|
||||
|
||||
TO_PREV_STATE();
|
||||
if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED){
|
||||
return RADIO_TX_OK;
|
||||
if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED || last_tx_status == ST_MAC_NO_ACK_RECEIVED){
|
||||
RELEASE_LOCK();
|
||||
if(last_tx_status == ST_PHY_ACK_RECEIVED){
|
||||
return RADIO_TX_OK; /* ACK status */
|
||||
}
|
||||
else if (last_tx_status == ST_MAC_NO_ACK_RECEIVED || last_tx_status == ST_SUCCESS){
|
||||
return RADIO_TX_NOACK;
|
||||
}
|
||||
}
|
||||
LED_TX_OFF();
|
||||
RELEASE_LOCK();
|
||||
return RADIO_TX_ERR;
|
||||
|
||||
#else /* RADIO_WAIT_FOR_PACKET_SENT */
|
||||
|
@ -332,6 +414,9 @@ static int stm32w_radio_transmit(unsigned short payload_len)
|
|||
|
||||
}
|
||||
|
||||
#if RADIO_WAIT_FOR_PACKET_SENT
|
||||
RELEASE_LOCK();
|
||||
#endif /* RADIO_WAIT_FOR_PACKET_SENT */
|
||||
TO_PREV_STATE();
|
||||
|
||||
PRINTF("stm32w: transmission never started.\r\n");
|
||||
|
@ -372,7 +457,14 @@ static int stm32w_radio_off(void)
|
|||
/* Any transmit or receive packets in progress are aborted.
|
||||
* Waiting for end of transmission or reception have to be done.
|
||||
*/
|
||||
if(onoroff == ON){
|
||||
if(locked)
|
||||
{
|
||||
PRINTF("stm32w: try to off while sending/receiving (lock=%u).\r\n", locked);
|
||||
return 0;
|
||||
}
|
||||
/* off only if there is no transmission or reception of packet. */
|
||||
if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet){
|
||||
LED_RDC_OFF();
|
||||
ST_RadioSleep();
|
||||
onoroff = OFF;
|
||||
CLEAN_TXBUF();
|
||||
|
@ -386,7 +478,9 @@ static int stm32w_radio_off(void)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
static int stm32w_radio_on(void)
|
||||
{
|
||||
PRINTF("stm32w: turn radio on\n");
|
||||
if(onoroff == OFF){
|
||||
LED_RDC_ON();
|
||||
ST_RadioWake();
|
||||
onoroff = ON;
|
||||
|
||||
|
@ -410,6 +504,7 @@ void ST_RadioReceiveIsrCallback(u8 *packet,
|
|||
s8 rssi)
|
||||
{
|
||||
LED_RX_ON();
|
||||
PRINTF("stm32w: incomming packet received\n");
|
||||
receiving_packet = 0;
|
||||
/* Copy packet into the buffer. It is better to do this here. */
|
||||
if(add_to_rxbuf(packet)){
|
||||
|
@ -417,6 +512,21 @@ void ST_RadioReceiveIsrCallback(u8 *packet,
|
|||
last_rssi = rssi;
|
||||
}
|
||||
LED_RX_OFF();
|
||||
GET_LOCK();
|
||||
is_transmit_ack = 1;
|
||||
/* Wait for sending ACK */
|
||||
BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
|
||||
RELEASE_LOCK();
|
||||
|
||||
}
|
||||
|
||||
void ST_RadioTxAckIsrCallback (void)
|
||||
{
|
||||
/* This callback is for simplemac 1.1.0.
|
||||
Till now we block (RTIMER_SECOND / 1500)
|
||||
to prevent radio off during ACK transmission */
|
||||
is_transmit_ack = 0;
|
||||
//RELEASE_LOCK();
|
||||
}
|
||||
|
||||
|
||||
|
@ -461,19 +571,19 @@ void ST_RadioTransmitCompleteIsrCallback(StStatus status,
|
|||
|
||||
/* Debug outputs. */
|
||||
if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED){
|
||||
PRINTF("TX_END");
|
||||
PRINTF("stm32w: return status TX_END\r\n");
|
||||
}
|
||||
else if (status == ST_MAC_NO_ACK_RECEIVED){
|
||||
PRINTF("TX_END_NOACK!!!");
|
||||
PRINTF("stm32w: return status TX_END_NOACK\r\n");
|
||||
}
|
||||
else if (status == ST_PHY_TX_CCA_FAIL){
|
||||
PRINTF("TX_END_CCA!!!");
|
||||
PRINTF("stm32w: return status TX_END_CCA_FAIL\r\n");
|
||||
}
|
||||
else if(status == ST_PHY_TX_UNDERFLOW){
|
||||
PRINTF("TX_END_UFL!!!");
|
||||
PRINTF("stm32w: return status TX_END_UNDERFLOW\r\n");
|
||||
}
|
||||
else {
|
||||
PRINTF("TX_END_INCOMPL!!!");
|
||||
PRINTF("stm32w: return status TX_END_INCOMPLETE\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +643,7 @@ static int stm32w_radio_read(void *buf, unsigned short bufsize)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
void ST_RadioOverflowIsrCallback(void)
|
||||
{
|
||||
PRINTF("OVERFLOW\r\n");
|
||||
PRINTF("stm32w: radio overflow\r\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void ST_RadioSfdSentIsrCallback(u32 sfdSentTime)
|
||||
|
|
|
@ -46,8 +46,12 @@
|
|||
#include "sys/clock.h"
|
||||
|
||||
|
||||
//#define RT_RESOLUTION RES_85US
|
||||
#ifdef RT_CONF_RESOLUTION
|
||||
#define RT_RESOLUTION RT_CONF_RESOLUTION
|
||||
#else
|
||||
#define RT_RESOLUTION RES_171US
|
||||
|
||||
#endif
|
||||
|
||||
#define RES_341US 0
|
||||
#define RES_171US 1
|
||||
|
|
|
@ -37,75 +37,87 @@
|
|||
* contiki-conf.h for MB851.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __CONTIKI_CONF_H__
|
||||
#define __CONTIKI_CONF_H__
|
||||
|
||||
#include PLATFORM_HEADER
|
||||
#ifdef PLATFORM_CONF_H
|
||||
#include PLATFORM_CONF_H
|
||||
#else
|
||||
#include "platform-conf.h"
|
||||
#endif /* PLATFORM_CONF_H */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h> // For memcpm().
|
||||
|
||||
#define CC_CONF_REGISTER_ARGS 0
|
||||
#define CC_CONF_FUNCTION_POINTER_ARGS 1
|
||||
#define CC_CONF_FASTCALL
|
||||
#define CC_CONF_VA_ARGS 1
|
||||
#define CC_CONF_INLINE inline
|
||||
|
||||
#define CCIF
|
||||
#define CLIF
|
||||
|
||||
/* These names are deprecated, use C99 names. */
|
||||
typedef uint8_t u8_t;
|
||||
typedef uint16_t u16_t;
|
||||
typedef uint32_t u32_t;
|
||||
typedef int32_t s32_t;
|
||||
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
|
||||
//#define FIXED_NET_ADDRESS 1
|
||||
//#define NET_ADDR_A 0x2001
|
||||
//#define NET_ADDR_B 0xdb8
|
||||
//#define NET_ADDR_C 0xbbbb
|
||||
//#define NET_ADDR_D 0xabcd
|
||||
|
||||
#define UART1_CONF_TX_WITH_INTERRUPT 0
|
||||
#define WITH_SERIAL_LINE_INPUT 1
|
||||
#define ENERGEST_CONF_ON 0
|
||||
#define TELNETD_CONF_NUMLINES 6
|
||||
|
||||
#define QUEUEBUF_CONF_NUM 2
|
||||
/* Radio and 802.15.4 params */
|
||||
/* 802.15.4 radio channel */
|
||||
#define RF_CHANNEL 16
|
||||
/* 802.15.4 PAN ID */
|
||||
#define IEEE802154_CONF_PANID 0x1234
|
||||
/* Use EID 64, enable hardware autoack and address filtering */
|
||||
#define RIMEADDR_CONF_SIZE 8
|
||||
#define UIP_CONF_LL_802154 1
|
||||
#define ST_CONF_RADIO_AUTOACK 1
|
||||
/* Number of buffers for incoming frames */
|
||||
#define RADIO_RXBUFS 2
|
||||
/* Set to 0 for non ethernet links */
|
||||
#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
/* RDC params */
|
||||
/* TX routine passes the cca/ack result in the return parameter */
|
||||
#define RDC_CONF_HARDWARE_ACK 1
|
||||
/* TX routine does automatic cca and optional backoff */
|
||||
#define RDC_CONF_HARDWARE_CSMA 0
|
||||
/* RDC debug with LED */
|
||||
#define RDC_CONF_DEBUG_LED 1
|
||||
/* Channel check rate (per second) */
|
||||
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
||||
/* Use ACK for optimization (LPP, XMAC) */
|
||||
#define WITH_ACK_OPTIMIZATION 0
|
||||
|
||||
/* Netstack config */
|
||||
#define NETSTACK_CONF_MAC csma_driver
|
||||
#define NETSTACK_CONF_RDC contikimac_driver
|
||||
#define NETSTACK_CONF_FRAMER framer_802154
|
||||
#define NETSTACK_CONF_RADIO stm32w_radio_driver
|
||||
|
||||
/* ContikiMAC config */
|
||||
#define CONTIKIMAC_CONF_COMPOWER 1
|
||||
#define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0
|
||||
#define CONTIKIMAC_CONF_ANNOUNCEMENTS 0
|
||||
|
||||
/* CXMAC config */
|
||||
#define CXMAC_CONF_ANNOUNCEMENTS 0
|
||||
#define CXMAC_CONF_COMPOWER 1
|
||||
|
||||
/* XMAC config */
|
||||
#define XMAC_CONF_ANNOUNCEMENTS 0
|
||||
#define XMAC_CONF_COMPOWER 1
|
||||
|
||||
/* Other */
|
||||
#define ENERGEST_CONF_ON 0
|
||||
#define QUEUEBUF_CONF_NUM 2
|
||||
|
||||
#if WITH_UIP6
|
||||
|
||||
/* No radio cycling */
|
||||
/* Network setup for IPv6 */
|
||||
#define NETSTACK_CONF_NETWORK sicslowpan_driver
|
||||
#define NETSTACK_CONF_MAC nullmac_driver
|
||||
#define NETSTACK_CONF_RDC sicslowmac_driver
|
||||
#define NETSTACK_CONF_FRAMER framer_802154
|
||||
|
||||
#define RIMEADDR_CONF_SIZE 8
|
||||
#define UIP_CONF_LL_802154 1
|
||||
/* Specify a minimum packet size for 6lowpan compression to be
|
||||
enabled. This is needed for ContikiMAC, which needs packets to be
|
||||
larger than a specified size, if no ContikiMAC header should be
|
||||
used. */
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63
|
||||
#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0
|
||||
|
||||
#define UIP_CONF_ROUTER 1
|
||||
#define UIP_CONF_IPV6_RPL 1
|
||||
#define UIP_CONF_ND6_SEND_RA 0
|
||||
//#define RPL_BORDER_ROUTER 0
|
||||
|
||||
/* A trick to resolve a compilation error with IAR. */
|
||||
#ifdef __ICCARM__
|
||||
#define UIP_CONF_DS6_AADDR_NBU 1
|
||||
#endif
|
||||
|
||||
#define UIP_CONF_IPV6 1
|
||||
#define UIP_CONF_IPV6_QUEUE_PKT 0 // This is a very costly feature as it increases the RAM usage by approximately UIP_ND6_MAX_NEIGHBORS * UIP_LINK_MTU bytes.
|
||||
#define UIP_CONF_IPV6_QUEUE_PKT 0
|
||||
#define UIP_CONF_IPV6_CHECKS 1
|
||||
#define UIP_CONF_IPV6_REASSEMBLY 0
|
||||
#define UIP_CONF_ND6_MAX_PREFIXES 2
|
||||
|
@ -113,54 +125,25 @@ typedef unsigned short uip_stats_t;
|
|||
#define UIP_CONF_ND6_MAX_DEFROUTERS 1
|
||||
#define UIP_CONF_IP_FORWARD 0
|
||||
#define UIP_CONF_BUFFER_SIZE 140
|
||||
#define UIP_CONF_MAX_CONNECTIONS 6
|
||||
#define UIP_CONF_MAX_LISTENPORTS 6
|
||||
#define UIP_CONF_UDP_CONNS 3
|
||||
#define UIP_CONF_MAX_CONNECTIONS 4
|
||||
#define UIP_CONF_MAX_LISTENPORTS 8
|
||||
#define UIP_CONF_UDP_CONNS 4
|
||||
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_HC1 1
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_HC06 2
|
||||
#include "net/sicslowpan.h"
|
||||
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC06
|
||||
#define SICSLOWPAN_CONF_FRAG 1
|
||||
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2
|
||||
#define SICSLOWPAN_CONF_MAXAGE 2
|
||||
|
||||
#define UIP_CONF_ICMP6 0
|
||||
#else /* WITH_UIP6 */
|
||||
|
||||
/* Network setup for non-IPv6 (rime). */
|
||||
#define NETSTACK_CONF_NETWORK rime_driver
|
||||
|
||||
#endif /* WITH_UIP6 */
|
||||
|
||||
#define UIP_CONF_UDP 1
|
||||
#define UIP_CONF_TCP 1
|
||||
|
||||
#define IEEE802154_CONF_PANID 0x1234
|
||||
#define STM32W_NODE_ID 0x5678 // to be deleted
|
||||
#define RF_CHANNEL 16
|
||||
#define RADIO_RXBUFS 2 // Set to a number greater than 1 to decrease packet loss probability at high rates (e.g, with fragmented packets)
|
||||
#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
typedef unsigned long clock_time_t;
|
||||
|
||||
#define CLOCK_CONF_SECOND 1000
|
||||
|
||||
typedef unsigned long long rtimer_clock_t;
|
||||
#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0)
|
||||
|
||||
/* LEDs ports MB851 */
|
||||
#define LEDS_CONF_RED_PIN 5
|
||||
#define LEDS_CONF_GREEN_PIN 6
|
||||
#define LEDS_CONF_PORT PORTB
|
||||
#define LEDS_CONF_RED (1<<LEDS_CONF_RED_PIN)
|
||||
#define LEDS_CONF_GREEN (1<<LEDS_CONF_GREEN_PIN)
|
||||
|
||||
|
||||
#define UIP_ARCH_ADD32 1
|
||||
#define UIP_ARCH_CHKSUM 0
|
||||
|
||||
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
|
||||
|
||||
#ifdef PROJECT_CONF_H
|
||||
#include PROJECT_CONF_H
|
||||
#endif /* PROJECT_CONF_H */
|
||||
|
||||
|
||||
#endif /* __CONTIKI_CONF_H__ */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* Contiki main file.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -82,9 +83,9 @@
|
|||
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
PROCINIT(&etimer_process, &tcpip_process, &sensors_process);
|
||||
PROCINIT(&tcpip_process, &sensors_process);
|
||||
#else
|
||||
PROCINIT(&etimer_process, &sensors_process);
|
||||
PROCINIT(&sensors_process);
|
||||
#warning "No TCP/IP process!"
|
||||
#endif
|
||||
|
||||
|
@ -108,9 +109,6 @@ set_rime_addr(void)
|
|||
eui64.u8[c] = stm32w_eui64[7 - c];
|
||||
}
|
||||
}
|
||||
PRINTF("\n\rRadio EUI-64:");
|
||||
PRINTLLADDR(eui64);
|
||||
PRINTF("\n\r");
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
memcpy(&uip_lladdr.addr, &eui64, sizeof(uip_lladdr.addr));
|
||||
|
@ -161,17 +159,25 @@ main(void)
|
|||
uart1_set_input(serial_line_input_byte);
|
||||
serial_line_init();
|
||||
#endif
|
||||
/* rtimer and ctimer should be initialized before radio duty cycling layers*/
|
||||
rtimer_init();
|
||||
/* etimer_process should be initialized before ctimer */
|
||||
process_start(&etimer_process, NULL);
|
||||
ctimer_init();
|
||||
|
||||
|
||||
netstack_init();
|
||||
#if !UIP_CONF_IPV6
|
||||
ST_RadioEnableAutoAck(FALSE); // Because frames are not 802.15.4 compatible.
|
||||
ST_RadioEnableAddressFiltering(FALSE);
|
||||
#endif
|
||||
|
||||
set_rime_addr();
|
||||
|
||||
ctimer_init();
|
||||
rtimer_init();
|
||||
printf("%s %s, channel check rate %lu Hz\n",
|
||||
NETSTACK_MAC.name, NETSTACK_RDC.name,
|
||||
CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
|
||||
NETSTACK_RDC.channel_check_interval()));
|
||||
printf("802.15.4 PAN ID 0x%x, EUI-%d:",
|
||||
IEEE802154_CONF_PANID, UIP_CONF_LL_802154?64:16);
|
||||
uip_debug_lladdr_print(&rimeaddr_node_addr);
|
||||
printf(", radio channel %u\n", RF_CHANNEL);
|
||||
|
||||
procinit_init();
|
||||
|
||||
|
|
94
platform/mb851/platform-conf.h
Normal file
94
platform/mb851/platform-conf.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2010, STMicroelectronics.
|
||||
* 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. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 the Contiki OS
|
||||
*
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \file
|
||||
* platform-conf.h for MB851.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __PLATFORM_CONF_H__
|
||||
#define __PLATFORM_CONF_H__
|
||||
|
||||
#include PLATFORM_HEADER
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h> // For memcpm().
|
||||
|
||||
/* Platform-dependent definitions */
|
||||
#define CC_CONF_REGISTER_ARGS 0
|
||||
#define CC_CONF_FUNCTION_POINTER_ARGS 1
|
||||
#define CC_CONF_FASTCALL
|
||||
#define CC_CONF_VA_ARGS 1
|
||||
#define CC_CONF_INLINE inline
|
||||
|
||||
#define CCIF
|
||||
#define CLIF
|
||||
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
#define UART1_CONF_TX_WITH_INTERRUPT 0
|
||||
#define WITH_SERIAL_LINE_INPUT 1
|
||||
|
||||
/* rtimer_second = 11719 */
|
||||
#define RT_CONF_RESOLUTION 2
|
||||
|
||||
/* A trick to resolve a compilation error with IAR. */
|
||||
#ifdef __ICCARM__
|
||||
#define UIP_CONF_DS6_AADDR_NBU 1
|
||||
#endif
|
||||
|
||||
typedef unsigned long clock_time_t;
|
||||
|
||||
#define CLOCK_CONF_SECOND 1000
|
||||
|
||||
typedef unsigned long rtimer_clock_t;
|
||||
#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0)
|
||||
|
||||
/* LEDs ports MB851 */
|
||||
#define LEDS_CONF_RED_PIN 5
|
||||
#define LEDS_CONF_GREEN_PIN 6
|
||||
#define LEDS_CONF_PORT PORTB
|
||||
#define LEDS_CONF_RED (1<<LEDS_CONF_RED_PIN)
|
||||
#define LEDS_CONF_GREEN (1<<LEDS_CONF_GREEN_PIN)
|
||||
|
||||
#define UIP_ARCH_ADD32 1
|
||||
#define UIP_ARCH_CHKSUM 0
|
||||
|
||||
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
|
||||
#endif /* __PLATFORM_CONF_H__ */
|
|
@ -29,6 +29,7 @@
|
|||
*
|
||||
* This file is part of the Contiki OS
|
||||
*
|
||||
* $Id: contiki-conf.h,v 1.2 2010/10/27 14:05:24 salvopitru Exp $
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
@ -36,74 +37,87 @@
|
|||
* contiki-conf.h for MBXXX.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __CONTIKI_CONF_H__
|
||||
#define __CONTIKI_CONF_H__
|
||||
|
||||
#include PLATFORM_HEADER
|
||||
#ifdef PLATFORM_CONF_H
|
||||
#include PLATFORM_CONF_H
|
||||
#else
|
||||
#include "platform-conf.h"
|
||||
#endif /* PLATFORM_CONF_H */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h> // For memcpm().
|
||||
|
||||
#define CC_CONF_REGISTER_ARGS 0
|
||||
#define CC_CONF_FUNCTION_POINTER_ARGS 1
|
||||
#define CC_CONF_FASTCALL
|
||||
#define CC_CONF_VA_ARGS 1
|
||||
#define CC_CONF_INLINE inline
|
||||
|
||||
#define CCIF
|
||||
#define CLIF
|
||||
|
||||
/* These names are deprecated, use C99 names. */
|
||||
typedef uint8_t u8_t;
|
||||
typedef uint16_t u16_t;
|
||||
typedef uint32_t u32_t;
|
||||
typedef int32_t s32_t;
|
||||
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
//#define FIXED_NET_ADDRESS 1
|
||||
//#define NET_ADDR_A 0x2001
|
||||
//#define NET_ADDR_B 0xdb8
|
||||
//#define NET_ADDR_C 0xbbbb
|
||||
//#define NET_ADDR_D 0xabcd
|
||||
|
||||
#define UART1_CONF_TX_WITH_INTERRUPT 0
|
||||
#define WITH_SERIAL_LINE_INPUT 1
|
||||
#define ENERGEST_CONF_ON 0
|
||||
#define TELNETD_CONF_NUMLINES 6
|
||||
|
||||
#define QUEUEBUF_CONF_NUM 2
|
||||
/* Radio and 802.15.4 params */
|
||||
/* 802.15.4 radio channel */
|
||||
#define RF_CHANNEL 16
|
||||
/* 802.15.4 PAN ID */
|
||||
#define IEEE802154_CONF_PANID 0x1234
|
||||
/* Use EID 64, enable hardware autoack and address filtering */
|
||||
#define RIMEADDR_CONF_SIZE 8
|
||||
#define UIP_CONF_LL_802154 1
|
||||
#define ST_CONF_RADIO_AUTOACK 1
|
||||
/* Number of buffers for incoming frames */
|
||||
#define RADIO_RXBUFS 2
|
||||
/* Set to 0 for non ethernet links */
|
||||
#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
/* RDC params */
|
||||
/* TX routine passes the cca/ack result in the return parameter */
|
||||
#define RDC_CONF_HARDWARE_ACK 1
|
||||
/* TX routine does automatic cca and optional backoff */
|
||||
#define RDC_CONF_HARDWARE_CSMA 0
|
||||
/* RDC debug with LED */
|
||||
#define RDC_CONF_DEBUG_LED 1
|
||||
/* Channel check rate (per second) */
|
||||
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
||||
/* Use ACK for optimization (LPP, XMAC) */
|
||||
#define WITH_ACK_OPTIMIZATION 0
|
||||
|
||||
/* Netstack config */
|
||||
#define NETSTACK_CONF_MAC csma_driver
|
||||
#define NETSTACK_CONF_RDC contikimac_driver
|
||||
#define NETSTACK_CONF_FRAMER framer_802154
|
||||
#define NETSTACK_CONF_RADIO stm32w_radio_driver
|
||||
|
||||
/* ContikiMAC config */
|
||||
#define CONTIKIMAC_CONF_COMPOWER 1
|
||||
#define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0
|
||||
#define CONTIKIMAC_CONF_ANNOUNCEMENTS 0
|
||||
|
||||
/* CXMAC config */
|
||||
#define CXMAC_CONF_ANNOUNCEMENTS 0
|
||||
#define CXMAC_CONF_COMPOWER 1
|
||||
|
||||
/* XMAC config */
|
||||
#define XMAC_CONF_ANNOUNCEMENTS 0
|
||||
#define XMAC_CONF_COMPOWER 1
|
||||
|
||||
/* Other */
|
||||
#define ENERGEST_CONF_ON 0
|
||||
#define QUEUEBUF_CONF_NUM 2
|
||||
|
||||
#if WITH_UIP6
|
||||
|
||||
/* No radio cycling */
|
||||
/* Network setup for IPv6 */
|
||||
#define NETSTACK_CONF_NETWORK sicslowpan_driver
|
||||
#define NETSTACK_CONF_MAC nullmac_driver
|
||||
#define NETSTACK_CONF_RDC sicslowmac_driver
|
||||
#define NETSTACK_CONF_FRAMER framer_802154
|
||||
|
||||
#define RIMEADDR_CONF_SIZE 8
|
||||
#define UIP_CONF_LL_802154 1
|
||||
/* Specify a minimum packet size for 6lowpan compression to be
|
||||
enabled. This is needed for ContikiMAC, which needs packets to be
|
||||
larger than a specified size, if no ContikiMAC header should be
|
||||
used. */
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63
|
||||
#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0
|
||||
|
||||
#define UIP_CONF_ROUTER 1
|
||||
#define UIP_CONF_IPV6_RPL 1
|
||||
#define UIP_CONF_ND6_SEND_RA 0
|
||||
//#define RPL_BORDER_ROUTER 0
|
||||
|
||||
/* A trick to resolve a compilation error with IAR. */
|
||||
#ifdef __ICCARM__
|
||||
#define UIP_CONF_DS6_AADDR_NBU 1
|
||||
#endif
|
||||
|
||||
#define UIP_CONF_IPV6 1
|
||||
#define UIP_CONF_IPV6_QUEUE_PKT 0 // This is a very costly feature as it increases the RAM usage by approximately UIP_ND6_MAX_NEIGHBORS * UIP_LINK_MTU bytes.
|
||||
#define UIP_CONF_IPV6_QUEUE_PKT 0
|
||||
#define UIP_CONF_IPV6_CHECKS 1
|
||||
#define UIP_CONF_IPV6_REASSEMBLY 0
|
||||
#define UIP_CONF_ND6_MAX_PREFIXES 2
|
||||
|
@ -111,53 +125,25 @@ typedef unsigned short uip_stats_t;
|
|||
#define UIP_CONF_ND6_MAX_DEFROUTERS 1
|
||||
#define UIP_CONF_IP_FORWARD 0
|
||||
#define UIP_CONF_BUFFER_SIZE 140
|
||||
#define UIP_CONF_MAX_CONNECTIONS 6
|
||||
#define UIP_CONF_MAX_LISTENPORTS 6
|
||||
#define UIP_CONF_UDP_CONNS 3
|
||||
#define UIP_CONF_MAX_CONNECTIONS 4
|
||||
#define UIP_CONF_MAX_LISTENPORTS 8
|
||||
#define UIP_CONF_UDP_CONNS 4
|
||||
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_HC1 1
|
||||
#define SICSLOWPAN_CONF_COMPRESSION_HC06 2
|
||||
#include "net/sicslowpan.h"
|
||||
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC06
|
||||
#define SICSLOWPAN_CONF_FRAG 1
|
||||
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2
|
||||
#define SICSLOWPAN_CONF_MAXAGE 2
|
||||
|
||||
#define UIP_CONF_ICMP6 0
|
||||
#else /* WITH_UIP6 */
|
||||
|
||||
/* Network setup for non-IPv6 (rime). */
|
||||
#define NETSTACK_CONF_NETWORK rime_driver
|
||||
|
||||
#endif /* WITH_UIP6 */
|
||||
|
||||
#define UIP_CONF_UDP 1
|
||||
#define UIP_CONF_TCP 1
|
||||
|
||||
#define IEEE802154_CONF_PANID 0x1234
|
||||
#define STM32W_NODE_ID 0x5678 // to be deleted
|
||||
#define RF_CHANNEL 16
|
||||
#define RADIO_RXBUFS 2 // Set to a number greater than 1 to decrease packet loss probability at high rates (e.g, with fragmented packets)
|
||||
#define UIP_CONF_LLH_LEN 0
|
||||
|
||||
typedef unsigned long clock_time_t;
|
||||
|
||||
#define CLOCK_CONF_SECOND 1000
|
||||
|
||||
typedef unsigned long long rtimer_clock_t;
|
||||
#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0)
|
||||
|
||||
/* LEDs ports MB8xxx */
|
||||
|
||||
#define LEDS_CONF_GREEN LED_D1
|
||||
#define LEDS_CONF_YELLOW LED_D3
|
||||
#define LEDS_CONF_RED LED_D3
|
||||
|
||||
|
||||
#define UIP_ARCH_ADD32 1
|
||||
#define UIP_ARCH_CHKSUM 0
|
||||
|
||||
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
|
||||
|
||||
#ifdef PROJECT_CONF_H
|
||||
#include PROJECT_CONF_H
|
||||
#endif /* PROJECT_CONF_H */
|
||||
|
||||
|
||||
#endif /* __CONTIKI_CONF_H__ */
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
* Contiki main file.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -65,8 +66,6 @@
|
|||
#include "net/rime.h"
|
||||
#include "net/rime/rime-udp.h"
|
||||
#include "net/uip.h"
|
||||
|
||||
|
||||
#define DEBUG 1
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
|
@ -81,9 +80,9 @@
|
|||
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
PROCINIT(&etimer_process, &tcpip_process, &sensors_process);
|
||||
PROCINIT(&tcpip_process, &sensors_process);
|
||||
#else
|
||||
PROCINIT(&etimer_process, &sensors_process);
|
||||
PROCINIT(&sensors_process);
|
||||
#warning "No TCP/IP process!"
|
||||
#endif
|
||||
|
||||
|
@ -107,9 +106,6 @@ set_rime_addr(void)
|
|||
eui64.u8[c] = stm32w_eui64[7 - c];
|
||||
}
|
||||
}
|
||||
PRINTF("\n\rRadio EUI-64:");
|
||||
PRINTLLADDR(eui64);
|
||||
PRINTF("\n\r");
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
memcpy(&uip_lladdr.addr, &eui64, sizeof(uip_lladdr.addr));
|
||||
|
@ -160,17 +156,24 @@ main(void)
|
|||
uart1_set_input(serial_line_input_byte);
|
||||
serial_line_init();
|
||||
#endif
|
||||
/* rtimer and ctimer should be initialized before radio duty cycling layers*/
|
||||
rtimer_init();
|
||||
/* etimer_process should be initialized before ctimer */
|
||||
process_start(&etimer_process, NULL);
|
||||
ctimer_init();
|
||||
|
||||
rtimer_init();
|
||||
netstack_init();
|
||||
#if !UIP_CONF_IPV6
|
||||
ST_RadioEnableAutoAck(FALSE); // Because frames are not 802.15.4 compatible.
|
||||
ST_RadioEnableAddressFiltering(FALSE);
|
||||
#endif
|
||||
|
||||
set_rime_addr();
|
||||
|
||||
ctimer_init();
|
||||
rtimer_init();
|
||||
printf("%s %s, channel check rate %lu Hz\n",
|
||||
NETSTACK_MAC.name, NETSTACK_RDC.name,
|
||||
CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
|
||||
NETSTACK_RDC.channel_check_interval()));
|
||||
printf("802.15.4 PAN ID 0x%x, EUI-%d:",
|
||||
IEEE802154_CONF_PANID, UIP_CONF_LL_802154?64:16);
|
||||
uip_debug_lladdr_print(&rimeaddr_node_addr);
|
||||
printf(", radio channel %u\n", RF_CHANNEL);
|
||||
|
||||
procinit_init();
|
||||
|
||||
|
@ -179,7 +182,6 @@ main(void)
|
|||
|
||||
autostart_start(autostart_processes);
|
||||
|
||||
|
||||
watchdog_start();
|
||||
|
||||
while(1){
|
||||
|
|
92
platform/mbxxx/platform-conf.h
Normal file
92
platform/mbxxx/platform-conf.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2010, STMicroelectronics.
|
||||
* 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. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 the Contiki OS
|
||||
*
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \file
|
||||
* platform-conf.h for MBXXX.
|
||||
* \author
|
||||
* Salvatore Pitrulli <salvopitru@users.sourceforge.net>
|
||||
* Chi-Anh La <la@imag.fr>
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __PLATFORM_CONF_H__
|
||||
#define __PLATFORM_CONF_H__
|
||||
|
||||
#include PLATFORM_HEADER
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h> // For memcpm().
|
||||
|
||||
/* Platform-dependent definitions */
|
||||
#define CC_CONF_REGISTER_ARGS 0
|
||||
#define CC_CONF_FUNCTION_POINTER_ARGS 1
|
||||
#define CC_CONF_FASTCALL
|
||||
#define CC_CONF_VA_ARGS 1
|
||||
#define CC_CONF_INLINE inline
|
||||
|
||||
#define CCIF
|
||||
#define CLIF
|
||||
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
#define UART1_CONF_TX_WITH_INTERRUPT 0
|
||||
#define WITH_SERIAL_LINE_INPUT 1
|
||||
|
||||
/* rtimer_second = 11719 */
|
||||
#define RT_CONF_RESOLUTION 2
|
||||
|
||||
/* A trick to resolve a compilation error with IAR. */
|
||||
#ifdef __ICCARM__
|
||||
#define UIP_CONF_DS6_AADDR_NBU 1
|
||||
#endif
|
||||
|
||||
typedef unsigned long clock_time_t;
|
||||
|
||||
#define CLOCK_CONF_SECOND 1000
|
||||
|
||||
typedef unsigned long rtimer_clock_t;
|
||||
#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0)
|
||||
|
||||
/* LEDs ports MB8xxx */
|
||||
#define LEDS_CONF_GREEN LED_D1
|
||||
#define LEDS_CONF_YELLOW LED_D3
|
||||
#define LEDS_CONF_RED LED_D3
|
||||
|
||||
#define UIP_ARCH_ADD32 1
|
||||
#define UIP_ARCH_CHKSUM 0
|
||||
|
||||
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
|
||||
#endif /* __PLATFORM_CONF_H__ */
|
|
@ -32,10 +32,10 @@
|
|||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import se.sics.cooja.MoteInterfaceHandler;
|
||||
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.interfaces.*;
|
||||
import se.sics.mspsim.platform.esb.ESBNode;
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
|
||||
package se.sics.cooja.mspmote;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Observable;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
@ -56,14 +57,12 @@ import se.sics.cooja.interfaces.IPAddress;
|
|||
import se.sics.cooja.motes.AbstractEmulatedMote;
|
||||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||
import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin;
|
||||
import se.sics.cooja.mspmote.plugins.MspBreakpointContainer;
|
||||
import se.sics.cooja.plugins.BufferListener.BufferAccess;
|
||||
import se.sics.cooja.mspmote.plugins.MspBreakpoint;
|
||||
import se.sics.cooja.plugins.Visualizer;
|
||||
import se.sics.mspsim.cli.CommandContext;
|
||||
import se.sics.mspsim.cli.CommandHandler;
|
||||
import se.sics.mspsim.cli.LineListener;
|
||||
import se.sics.mspsim.cli.LineOutputStream;
|
||||
import se.sics.mspsim.core.CPUMonitor;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.core.MSP430Constants;
|
||||
|
@ -103,15 +102,11 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
private int heapStartAddress;
|
||||
private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable();
|
||||
|
||||
private MspBreakpointContainer breakpointsContainer;
|
||||
|
||||
public MspMote() {
|
||||
myMoteType = null;
|
||||
myCpu = null;
|
||||
myMemory = null;
|
||||
myMoteInterfaceHandler = null;
|
||||
|
||||
/* Scheduled from setConfigXML */
|
||||
}
|
||||
|
||||
public MspMote(MspMoteType moteType, Simulation simulation) {
|
||||
|
@ -130,9 +125,8 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
/* TODO Setup COOJA-specific window manager */
|
||||
registry.registerComponent("windowManager", new JFrameWindowManager());
|
||||
|
||||
/* Create watchpoint container */
|
||||
try {
|
||||
breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo());
|
||||
debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo();
|
||||
} catch (IOException e) {
|
||||
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
||||
}
|
||||
|
@ -300,7 +294,6 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
|
||||
if (stopNextInstruction) {
|
||||
stopNextInstruction = false;
|
||||
/*sendCLICommandAndPrint("trace 1000");*/ /* TODO Enable */
|
||||
scheduleNextWakeup(t);
|
||||
throw new RuntimeException("MSPSim requested simulation stop");
|
||||
}
|
||||
|
@ -333,6 +326,10 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
/*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/
|
||||
scheduleNextWakeup(nextExecute);
|
||||
|
||||
if (stopNextInstruction) {
|
||||
stopNextInstruction = false;
|
||||
throw new RuntimeException("MSPSim requested simulation stop");
|
||||
}
|
||||
|
||||
/* XXX TODO Reimplement stack monitoring using MSPSim internals */
|
||||
/*if (monitorStackUsage) {
|
||||
|
@ -391,9 +388,8 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
myMoteInterfaceHandler = createMoteInterfaceHandler();
|
||||
}
|
||||
|
||||
/* Create watchpoint container */
|
||||
try {
|
||||
breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo());
|
||||
debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo();
|
||||
} catch (IOException e) {
|
||||
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
||||
}
|
||||
|
@ -404,7 +400,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
if (name.equals("motetype_identifier")) {
|
||||
/* Ignored: handled by simulation */
|
||||
} else if ("breakpoints".equals(element.getName())) {
|
||||
breakpointsContainer.setConfigXML(element.getChildren(), visAvailable);
|
||||
setWatchpointConfigXML(element.getChildren(), visAvailable);
|
||||
} else if (name.equals("interface_config")) {
|
||||
String intfClass = element.getText().trim();
|
||||
if (intfClass.equals("se.sics.cooja.mspmote.interfaces.MspIPAddress")) {
|
||||
|
@ -440,7 +436,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
|
||||
/* Breakpoints */
|
||||
element = new Element("breakpoints");
|
||||
element.addContent(breakpointsContainer.getConfigXML());
|
||||
element.addContent(getWatchpointConfigXML());
|
||||
config.add(element);
|
||||
|
||||
// Mote interfaces
|
||||
|
@ -458,39 +454,13 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
return config;
|
||||
}
|
||||
|
||||
|
||||
/* Watchpoints: Forward to breakpoint container */
|
||||
public void addWatchpointListener(ActionListener listener) {
|
||||
breakpointsContainer.addWatchpointListener(listener);
|
||||
}
|
||||
|
||||
public Watchpoint getLastWatchpoint() {
|
||||
return breakpointsContainer.getLastWatchpoint();
|
||||
}
|
||||
|
||||
public Mote getMote() {
|
||||
return breakpointsContainer.getMote();
|
||||
}
|
||||
|
||||
public ActionListener[] getWatchpointListeners() {
|
||||
return breakpointsContainer.getWatchpointListeners();
|
||||
}
|
||||
|
||||
public void removeWatchpointListener(ActionListener listener) {
|
||||
breakpointsContainer.removeWatchpointListener(listener);
|
||||
}
|
||||
|
||||
public MspBreakpointContainer getBreakpointsContainer() {
|
||||
return breakpointsContainer;
|
||||
}
|
||||
|
||||
public String getExecutionDetails() {
|
||||
return executeCLICommand("stacktrace");
|
||||
}
|
||||
|
||||
public String getPCString() {
|
||||
int pc = myCpu.getPC();
|
||||
ELF elf = (ELF)myCpu.getRegistry().getComponent(ELF.class);
|
||||
ELF elf = myCpu.getRegistry().getComponent(ELF.class);
|
||||
DebugInfo di = elf.getDebugInfo(pc);
|
||||
|
||||
/* Following code examples from MSPsim, DebugCommands.java */
|
||||
|
@ -539,4 +509,144 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
|||
|
||||
/*return executeCLICommand("line " + myCpu.getPC());*/
|
||||
}
|
||||
|
||||
|
||||
/* WatchpointMote */
|
||||
private ArrayList<WatchpointListener> watchpointListeners = new ArrayList<WatchpointListener>();
|
||||
private ArrayList<MspBreakpoint> watchpoints = new ArrayList<MspBreakpoint>();
|
||||
private Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = null;
|
||||
|
||||
public void addWatchpointListener(WatchpointListener listener) {
|
||||
watchpointListeners.add(listener);
|
||||
}
|
||||
public void removeWatchpointListener(WatchpointListener listener) {
|
||||
watchpointListeners.remove(listener);
|
||||
}
|
||||
public WatchpointListener[] getWatchpointListeners() {
|
||||
return watchpointListeners.toArray(new WatchpointListener[0]);
|
||||
}
|
||||
|
||||
public Watchpoint addBreakpoint(File codeFile, int lineNr, int address) {
|
||||
MspBreakpoint bp = new MspBreakpoint(this, address, codeFile, new Integer(lineNr));
|
||||
watchpoints.add(bp);
|
||||
|
||||
for (WatchpointListener listener: watchpointListeners) {
|
||||
listener.watchpointsChanged();
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
public void removeBreakpoint(Watchpoint watchpoint) {
|
||||
((MspBreakpoint)watchpoint).unregisterBreakpoint();
|
||||
watchpoints.remove(watchpoint);
|
||||
|
||||
for (WatchpointListener listener: watchpointListeners) {
|
||||
listener.watchpointsChanged();
|
||||
}
|
||||
}
|
||||
public Watchpoint[] getBreakpoints() {
|
||||
return watchpoints.toArray(new Watchpoint[0]);
|
||||
}
|
||||
|
||||
public boolean breakpointExists(int address) {
|
||||
if (address < 0) {
|
||||
return false;
|
||||
}
|
||||
for (Watchpoint watchpoint: watchpoints) {
|
||||
if (watchpoint.getExecutableAddress() == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean breakpointExists(File file, int lineNr) {
|
||||
for (Watchpoint watchpoint: watchpoints) {
|
||||
if (watchpoint.getCodeFile() == null) {
|
||||
continue;
|
||||
}
|
||||
if (watchpoint.getCodeFile().compareTo(file) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (watchpoint.getLineNumber() != lineNr) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Integer getExecutableAddressOf(File file, int lineNr) {
|
||||
if (file == null || lineNr < 0 || debuggingInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Match file */
|
||||
Hashtable<Integer, Integer> lineTable = debuggingInfo.get(file);
|
||||
if (lineTable == null) {
|
||||
Enumeration<File> fileEnum = debuggingInfo.keys();
|
||||
while (fileEnum.hasMoreElements()) {
|
||||
File f = fileEnum.nextElement();
|
||||
if (f != null && f.getName().equals(file.getName())) {
|
||||
lineTable = debuggingInfo.get(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineTable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Match line number */
|
||||
Integer address = lineTable.get(lineNr);
|
||||
if (address != null) {
|
||||
Enumeration<Integer> lineEnum = lineTable.keys();
|
||||
while (lineEnum.hasMoreElements()) {
|
||||
Integer l = lineEnum.nextElement();
|
||||
if (l != null && l.intValue() == lineNr) {
|
||||
/* Found line address */
|
||||
return lineTable.get(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void signalBreakpointTrigger(MspBreakpoint b) {
|
||||
if (b.stopsSimulation() && getSimulation().isRunning()) {
|
||||
/* Stop simulation immediately */
|
||||
stopNextInstruction();
|
||||
}
|
||||
|
||||
/* Notify listeners */
|
||||
WatchpointListener[] listeners = getWatchpointListeners();
|
||||
for (WatchpointListener listener: listeners) {
|
||||
listener.watchpointTriggered(b);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Element> getWatchpointConfigXML() {
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
||||
for (MspBreakpoint breakpoint: watchpoints) {
|
||||
element = new Element("breakpoint");
|
||||
element.addContent(breakpoint.getConfigXML());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
public boolean setWatchpointConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
if (element.getName().equals("breakpoint")) {
|
||||
MspBreakpoint breakpoint = new MspBreakpoint(this);
|
||||
if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) {
|
||||
logger.warn("Could not restore breakpoint: " + breakpoint);
|
||||
} else {
|
||||
watchpoints.add(breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,26 +31,32 @@
|
|||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JColorChooser;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.GUI;
|
||||
import se.sics.cooja.Mote;
|
||||
import se.sics.cooja.MoteType;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
|
||||
/**
|
||||
* Displays a set of breakpoints.
|
||||
|
@ -60,27 +66,27 @@ import se.sics.cooja.mspmote.MspMote;
|
|||
public class BreakpointsUI extends JPanel {
|
||||
private static Logger logger = Logger.getLogger(BreakpointsUI.class);
|
||||
|
||||
private static final int COLUMN_INFO = 0;
|
||||
private static final int COLUMN_ADDRESS = 1;
|
||||
private static final int COLUMN_FILELINE = 2;
|
||||
private static final int COLUMN_ADDRESS = 0;
|
||||
private static final int COLUMN_FILELINE = 1;
|
||||
private static final int COLUMN_INFO = 2;
|
||||
private static final int COLUMN_STOP = 3;
|
||||
private static final int COLUMN_REMOVE = 4;
|
||||
|
||||
private static final String[] COLUMN_NAMES = {
|
||||
"Info",
|
||||
"Address",
|
||||
"File",
|
||||
"Stop",
|
||||
"Remove"
|
||||
"Source",
|
||||
"Info",
|
||||
"Stops simulation"
|
||||
};
|
||||
|
||||
private MspBreakpointContainer breakpoints = null;
|
||||
private WatchpointMote mote;
|
||||
private MspCodeWatcher codeWatcher;
|
||||
private JTable table = null;
|
||||
|
||||
private MspBreakpoint popupBreakpoint = null;
|
||||
private Watchpoint selectedWatchpoint = null;
|
||||
|
||||
public BreakpointsUI(MspBreakpointContainer breakpoints, final MspCodeWatcher codeWatcher) {
|
||||
this.breakpoints = breakpoints;
|
||||
public BreakpointsUI(WatchpointMote mote, final MspCodeWatcher codeWatcher) {
|
||||
this.mote = mote;
|
||||
this.codeWatcher = codeWatcher;
|
||||
|
||||
/* Breakpoints table */
|
||||
table = new JTable(tableModel) {
|
||||
|
@ -93,15 +99,20 @@ public class BreakpointsUI extends JPanel {
|
|||
int realColumnIndex = table.convertColumnIndexToModel(colIndex);
|
||||
|
||||
if (realColumnIndex == COLUMN_FILELINE) {
|
||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
||||
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
||||
return null;
|
||||
}
|
||||
File file = allBreakpoints[rowIndex].getCodeFile();
|
||||
Watchpoint watchpoint = allBreakpoints[rowIndex];
|
||||
File file = watchpoint.getCodeFile();
|
||||
if (file == null) {
|
||||
return null;
|
||||
return String.format("[unknown @ 0x%04x]", watchpoint.getExecutableAddress());
|
||||
}
|
||||
return file.getPath() + ":" + allBreakpoints[rowIndex].getLineNumber();
|
||||
Integer line = watchpoint.getLineNumber();
|
||||
if (line == null) {
|
||||
return file.getPath() + ":?";
|
||||
}
|
||||
return file.getPath() + ":" + line;
|
||||
}
|
||||
|
||||
if (realColumnIndex == COLUMN_INFO) {
|
||||
|
@ -111,20 +122,10 @@ public class BreakpointsUI extends JPanel {
|
|||
if (realColumnIndex == COLUMN_STOP) {
|
||||
return "Indicates whether the watchpoint will stop the simulation when triggered";
|
||||
}
|
||||
|
||||
if (realColumnIndex == COLUMN_REMOVE) {
|
||||
return "Remove breakpoint from this mote only. (Right-click for more options)";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
table.getColumnModel().getColumn(COLUMN_ADDRESS).setPreferredWidth(60); /* XXX */
|
||||
table.getColumnModel().getColumn(COLUMN_ADDRESS).setMaxWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_INFO).setPreferredWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_INFO).setMaxWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer(
|
||||
new DefaultTableCellRenderer() {
|
||||
table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer(new DefaultTableCellRenderer() {
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component c = super.getTableCellRendererComponent(
|
||||
|
@ -133,31 +134,29 @@ public class BreakpointsUI extends JPanel {
|
|||
return c;
|
||||
}
|
||||
|
||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
||||
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||
if (row < 0 || row >= allBreakpoints.length) {
|
||||
return c;
|
||||
}
|
||||
MspBreakpoint breakpoint = allBreakpoints[row];
|
||||
Watchpoint breakpoint = allBreakpoints[row];
|
||||
if (breakpoint.getColor() == null) {
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Use watchpoint color */
|
||||
c.setBackground(Color.WHITE);
|
||||
c.setForeground(breakpoint.getColor());
|
||||
return c;
|
||||
}
|
||||
});
|
||||
table.getColumnModel().getColumn(COLUMN_STOP).setPreferredWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_STOP).setMaxWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_REMOVE).setPreferredWidth(60);
|
||||
table.getColumnModel().getColumn(COLUMN_REMOVE).setMaxWidth(60);
|
||||
|
||||
/* Popup menu: register on all motes */
|
||||
final JPopupMenu popupMenu = new JPopupMenu();
|
||||
popupMenu.add(new JMenuItem(addToMoteTypeAction));
|
||||
popupMenu.add(new JMenuItem(delFromMoteTypeAction));
|
||||
popupMenu.add(new JMenuItem(gotoCodeAction));
|
||||
popupMenu.add(new JSeparator());
|
||||
popupMenu.add(new JMenuItem(removeWatchpointAction));
|
||||
popupMenu.add(new JMenuItem(configureWatchpointAction));
|
||||
|
||||
/* Show source file on breakpoint mouse click */
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
java.awt.Point p = e.getPoint();
|
||||
|
@ -167,63 +166,32 @@ public class BreakpointsUI extends JPanel {
|
|||
|
||||
if (realColumnIndex != COLUMN_ADDRESS
|
||||
&& realColumnIndex != COLUMN_FILELINE
|
||||
&& realColumnIndex != COLUMN_REMOVE
|
||||
&& realColumnIndex != COLUMN_INFO) {
|
||||
return;
|
||||
}
|
||||
|
||||
MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
||||
Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints();
|
||||
if (rowIndex < 0 || rowIndex >= allBreakpoints.length) {
|
||||
return;
|
||||
}
|
||||
MspBreakpoint breakpoint = allBreakpoints[rowIndex];
|
||||
Watchpoint breakpoint = allBreakpoints[rowIndex];
|
||||
|
||||
if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e)) {
|
||||
popupBreakpoint = breakpoint;
|
||||
selectedWatchpoint = breakpoint;
|
||||
popupMenu.show(table, e.getX(), e.getY());
|
||||
return;
|
||||
}
|
||||
|
||||
if (realColumnIndex == COLUMN_INFO) {
|
||||
String msg = JOptionPane.showInputDialog(
|
||||
GUI.getTopParentContainer(),
|
||||
"Enter description",
|
||||
"Watchpoint Description",
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
if (msg != null) {
|
||||
breakpoint.setUserMessage(msg);
|
||||
}
|
||||
Color newColor = JColorChooser.showDialog(
|
||||
GUI.getTopParentContainer(),
|
||||
"Watchpoint Color",
|
||||
breakpoint.getColor());
|
||||
if (newColor != null) {
|
||||
breakpoint.setColor(newColor);
|
||||
}
|
||||
configureWatchpointInfo(breakpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
File file = allBreakpoints[rowIndex].getCodeFile();
|
||||
/*File file = allBreakpoints[rowIndex].getCodeFile();
|
||||
int line = allBreakpoints[rowIndex].getLineNumber();
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display source code */
|
||||
codeWatcher.displaySourceFile(file, line);
|
||||
}
|
||||
});
|
||||
|
||||
/* Update when breakpoints are triggered/added/removed */
|
||||
breakpoints.addWatchpointListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MspBreakpoint triggered = BreakpointsUI.this.breakpoints.getLastWatchpoint();
|
||||
if (triggered == null) {
|
||||
table.repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
flashBreakpoint(triggered);
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -232,24 +200,41 @@ public class BreakpointsUI extends JPanel {
|
|||
add(BorderLayout.CENTER, table);
|
||||
}
|
||||
|
||||
private void flashBreakpoint(MspBreakpoint breakpoint) {
|
||||
/* Locate breakpoints table index */
|
||||
int index = -1;
|
||||
MspBreakpoint[] all = breakpoints.getBreakpoints();
|
||||
for (int i=0; i < breakpoints.getBreakpointsCount(); i++) {
|
||||
if (breakpoint == all[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
private void configureWatchpointInfo(Watchpoint breakpoint) {
|
||||
String msg = (String) JOptionPane.showInputDialog(
|
||||
GUI.getTopParentContainer(),
|
||||
"Enter description;",
|
||||
"Watchpoint description",
|
||||
JOptionPane.QUESTION_MESSAGE, null, null, breakpoint.getUserMessage());
|
||||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
breakpoint.setUserMessage(msg);
|
||||
Color newColor = JColorChooser.showDialog(
|
||||
GUI.getTopParentContainer(),
|
||||
"Watchpoint color",
|
||||
breakpoint.getColor());
|
||||
if (newColor == null) {
|
||||
return;
|
||||
}
|
||||
breakpoint.setColor(newColor);
|
||||
}
|
||||
|
||||
final int breakpointIndex = index;
|
||||
public void selectBreakpoint(final Watchpoint breakpoint) {
|
||||
if (breakpoint == null) {
|
||||
return;
|
||||
}
|
||||
/* Locate breakpoints table index */
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
table.setRowSelectionInterval(breakpointIndex, breakpointIndex);
|
||||
Watchpoint[] watchpoints = mote.getBreakpoints();
|
||||
for (int i=0; i < watchpoints.length; i++) {
|
||||
if (breakpoint == watchpoints[i]) {
|
||||
/* Select */
|
||||
table.setRowSelectionInterval(i, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -259,18 +244,18 @@ public class BreakpointsUI extends JPanel {
|
|||
return COLUMN_NAMES[col].toString();
|
||||
}
|
||||
public int getRowCount() {
|
||||
return breakpoints.getBreakpointsCount();
|
||||
return mote.getBreakpoints().length;
|
||||
}
|
||||
public int getColumnCount() {
|
||||
return COLUMN_NAMES.length;
|
||||
}
|
||||
public Object getValueAt(int row, int col) {
|
||||
MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row];
|
||||
Watchpoint breakpoint = mote.getBreakpoints()[row];
|
||||
|
||||
/* Executable address in hexadecimal */
|
||||
if (col == COLUMN_ADDRESS) {
|
||||
Integer address = breakpoint.getExecutableAddress();
|
||||
return "0x" + Integer.toHexString(address.intValue());
|
||||
return String.format("0x%04x", address.intValue());
|
||||
}
|
||||
|
||||
/* Source file + line number */
|
||||
|
@ -300,7 +285,7 @@ public class BreakpointsUI extends JPanel {
|
|||
return getColumnClass(col) == Boolean.class;
|
||||
}
|
||||
public void setValueAt(Object value, int row, int col) {
|
||||
MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row];
|
||||
Watchpoint breakpoint = mote.getBreakpoints()[row];
|
||||
|
||||
if (col == COLUMN_STOP) {
|
||||
/* Toggle stop state */
|
||||
|
@ -308,109 +293,36 @@ public class BreakpointsUI extends JPanel {
|
|||
fireTableCellUpdated(row, col);
|
||||
return;
|
||||
}
|
||||
|
||||
if (col == COLUMN_REMOVE) {
|
||||
/* Remove breakpoint */
|
||||
Integer address = breakpoint.getExecutableAddress();
|
||||
breakpoints.removeBreakpoint(address);
|
||||
fireTableCellUpdated(row, col);
|
||||
return;
|
||||
}
|
||||
}
|
||||
public Class<?> getColumnClass(int c) {
|
||||
return getValueAt(0, c).getClass();
|
||||
}
|
||||
};
|
||||
|
||||
private Action addToMoteTypeAction = new AbstractAction("Register on all motes (mote type)") {
|
||||
private Action gotoCodeAction = new AbstractAction("Show in source code") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (popupBreakpoint == null) {
|
||||
logger.fatal("No breakpoint to add");
|
||||
}
|
||||
|
||||
/* Extract all motes of the same mote type */
|
||||
Simulation sim = popupBreakpoint.getMote().getSimulation();
|
||||
MoteType type = popupBreakpoint.getMote().getType();
|
||||
ArrayList<MspMote> motes = new ArrayList<MspMote>();
|
||||
for (Mote m: sim.getMotes()) {
|
||||
if (m.getType() == type) {
|
||||
if (!(m instanceof MspMote)) {
|
||||
logger.fatal("At least one mote was not a MSP mote: " + m);
|
||||
if (selectedWatchpoint == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
motes.add((MspMote)m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register breakpoints */
|
||||
int reregistered = 0;
|
||||
for (MspMote m: motes) {
|
||||
/* Avoid duplicates (match executable addresses) */
|
||||
MspBreakpointContainer container = m.getBreakpointsContainer();
|
||||
MspBreakpoint[] breakpoints = container.getBreakpoints();
|
||||
for (MspBreakpoint w: breakpoints) {
|
||||
if (popupBreakpoint.getExecutableAddress().intValue() ==
|
||||
w.getExecutableAddress().intValue()) {
|
||||
logger.info("Reregistering breakpoint at mote: " + m);
|
||||
container.removeBreakpoint(w.getExecutableAddress());
|
||||
reregistered++;
|
||||
}
|
||||
}
|
||||
|
||||
MspBreakpoint newBreakpoint = container.addBreakpoint(
|
||||
popupBreakpoint.getCodeFile(),
|
||||
popupBreakpoint.getLineNumber(),
|
||||
popupBreakpoint.getExecutableAddress());
|
||||
newBreakpoint.setUserMessage(popupBreakpoint.getUserMessage());
|
||||
newBreakpoint.setColor(popupBreakpoint.getColor());
|
||||
newBreakpoint.setStopsSimulation(popupBreakpoint.stopsSimulation());
|
||||
}
|
||||
|
||||
JOptionPane.showMessageDialog(GUI.getTopParentContainer(),
|
||||
"Registered " + motes.size() + " breakpoints (" + reregistered + " re-registered)",
|
||||
"Breakpoints added", JOptionPane.INFORMATION_MESSAGE);
|
||||
codeWatcher.displaySourceFile(selectedWatchpoint.getCodeFile(), selectedWatchpoint.getLineNumber(), false);
|
||||
}
|
||||
};
|
||||
private Action delFromMoteTypeAction = new AbstractAction("Delete from all motes (mote type)") {
|
||||
private Action removeWatchpointAction = new AbstractAction("Remove watchpoint") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (popupBreakpoint == null) {
|
||||
logger.fatal("No breakpoint to delete");
|
||||
}
|
||||
|
||||
/* Extract all motes of the same mote type */
|
||||
Simulation sim = popupBreakpoint.getMote().getSimulation();
|
||||
MoteType type = popupBreakpoint.getMote().getType();
|
||||
ArrayList<MspMote> motes = new ArrayList<MspMote>();
|
||||
for (Mote m: sim.getMotes()) {
|
||||
if (m.getType() == type) {
|
||||
if (!(m instanceof MspMote)) {
|
||||
logger.fatal("At least one mote was not a MSP mote: " + m);
|
||||
if (selectedWatchpoint == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
motes.add((MspMote)m);
|
||||
mote.removeBreakpoint(selectedWatchpoint);
|
||||
table.invalidate();
|
||||
table.repaint();
|
||||
}
|
||||
};
|
||||
private Action configureWatchpointAction = new AbstractAction("Configure watchpoint information") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedWatchpoint == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Delete breakpoints */
|
||||
int deleted = 0;
|
||||
for (MspMote m: motes) {
|
||||
/* Avoid duplicates (match executable addresses) */
|
||||
MspBreakpointContainer container = m.getBreakpointsContainer();
|
||||
MspBreakpoint[] breakpoints = container.getBreakpoints();
|
||||
for (MspBreakpoint w: breakpoints) {
|
||||
if (popupBreakpoint.getExecutableAddress().intValue() ==
|
||||
w.getExecutableAddress().intValue()) {
|
||||
container.removeBreakpoint(w.getExecutableAddress());
|
||||
deleted++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JOptionPane.showMessageDialog(GUI.getTopParentContainer(),
|
||||
"Deleted " + deleted + " breakpoints",
|
||||
"Breakpoints deleted", JOptionPane.INFORMATION_MESSAGE);
|
||||
configureWatchpointInfo(selectedWatchpoint);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,32 +34,33 @@ package se.sics.cooja.mspmote.plugins;
|
|||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Highlighter;
|
||||
import javax.swing.text.Highlighter.HighlightPainter;
|
||||
|
||||
import jsyntaxpane.DefaultSyntaxKit;
|
||||
import jsyntaxpane.components.Markers.SimpleMarker;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.mspsim.extutil.highlight.CScanner;
|
||||
import se.sics.mspsim.extutil.highlight.Token;
|
||||
import se.sics.mspsim.extutil.highlight.TokenTypes;
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
import se.sics.cooja.util.JSyntaxAddBreakpoint;
|
||||
import se.sics.cooja.util.JSyntaxRemoveBreakpoint;
|
||||
import se.sics.cooja.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Displays source code and allows a user to add and remove breakpoints.
|
||||
|
@ -69,184 +70,231 @@ import se.sics.mspsim.extutil.highlight.TokenTypes;
|
|||
public class CodeUI extends JPanel {
|
||||
private static Logger logger = Logger.getLogger(CodeUI.class);
|
||||
|
||||
private JPanel panel = null;
|
||||
private JList codeList = null;
|
||||
{
|
||||
DefaultSyntaxKit.initKit();
|
||||
}
|
||||
|
||||
private MspBreakpointContainer breakpoints = null;
|
||||
private JEditorPane codeEditor = null;
|
||||
private HashMap<Integer, Integer> codeEditorLines = null;
|
||||
protected File displayedFile = null;
|
||||
|
||||
private Token tokensArray[][] = null;
|
||||
private int tokensStartPos[] = null;
|
||||
private static final HighlightPainter CURRENT_LINE_MARKER = new SimpleMarker(Color.ORANGE);
|
||||
private static final HighlightPainter SELECTED_LINE_MARKER = new SimpleMarker(Color.GREEN);
|
||||
private static final HighlightPainter BREAKPOINTS_MARKER = new SimpleMarker(Color.LIGHT_GRAY);
|
||||
private final Object currentLineTag;
|
||||
private final Object selectedLineTag;
|
||||
private final ArrayList<Object> breakpointsLineTags = new ArrayList<Object>();
|
||||
|
||||
/**
|
||||
* @param breakpoints Breakpoints
|
||||
*/
|
||||
public CodeUI(MspBreakpointContainer breakpoints) {
|
||||
this.breakpoints = breakpoints;
|
||||
private JSyntaxAddBreakpoint actionAddBreakpoint = null;
|
||||
private JSyntaxRemoveBreakpoint actionRemoveBreakpoint = null;
|
||||
|
||||
private WatchpointMote mote;
|
||||
|
||||
public CodeUI(WatchpointMote mote) {
|
||||
this.mote = mote;
|
||||
|
||||
{
|
||||
/* Workaround to configure jsyntaxpane */
|
||||
JEditorPane e = new JEditorPane();
|
||||
new JScrollPane(e);
|
||||
e.setContentType("text/c");
|
||||
DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit();
|
||||
kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName());
|
||||
kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName());
|
||||
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint");
|
||||
}
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
codeEditor = new JEditorPane();
|
||||
add(new JScrollPane(codeEditor), BorderLayout.CENTER);
|
||||
doLayout();
|
||||
|
||||
panel = new JPanel(new BorderLayout());
|
||||
add(panel, BorderLayout.CENTER);
|
||||
displayNoCode();
|
||||
codeEditorLines = new HashMap<Integer, Integer>();
|
||||
codeEditor.setContentType("text/c");
|
||||
DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit();
|
||||
kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName());
|
||||
kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName());
|
||||
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint");
|
||||
|
||||
breakpoints.addWatchpointListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
/* Only update code list if simulation is not running */
|
||||
if (CodeUI.this.breakpoints.getMote().getSimulation().isRunning() ||
|
||||
CodeUI.this.breakpoints.getLastWatchpoint() != null) {
|
||||
JPopupMenu p = codeEditor.getComponentPopupMenu();
|
||||
for (Component c: p.getComponents()) {
|
||||
if (c instanceof JMenuItem) {
|
||||
if (((JMenuItem) c).getAction() != null &&
|
||||
((JMenuItem) c).getAction() instanceof JSyntaxAddBreakpoint) {
|
||||
actionAddBreakpoint = (JSyntaxAddBreakpoint)(((JMenuItem) c).getAction());
|
||||
actionAddBreakpoint.setMenuText("Add breakpoint");
|
||||
}
|
||||
if (((JMenuItem) c).getAction() != null &&
|
||||
((JMenuItem) c).getAction() instanceof JSyntaxRemoveBreakpoint) {
|
||||
actionRemoveBreakpoint = (JSyntaxRemoveBreakpoint)(((JMenuItem) c).getAction());
|
||||
actionRemoveBreakpoint.setMenuText("Remove breakpoint");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeEditor.setText("");
|
||||
codeEditorLines.clear();
|
||||
codeEditor.setEditable(false);
|
||||
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
Object o = null;
|
||||
try {
|
||||
o = hl.addHighlight(0, 0, CURRENT_LINE_MARKER);
|
||||
} catch (BadLocationException e1) {
|
||||
}
|
||||
currentLineTag = o;
|
||||
|
||||
o = null;
|
||||
try {
|
||||
o = hl.addHighlight(0, 0, SELECTED_LINE_MARKER);
|
||||
} catch (BadLocationException e1) {
|
||||
}
|
||||
selectedLineTag = o;
|
||||
|
||||
codeEditor.getComponentPopupMenu().addPopupMenuListener(new PopupMenuListener() {
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
||||
/* Disable breakpoint actions */
|
||||
actionAddBreakpoint.setEnabled(false);
|
||||
actionRemoveBreakpoint.setEnabled(false);
|
||||
|
||||
int line = getCodeEditorMouseLine();
|
||||
if (line < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (codeList != null) {
|
||||
codeList.updateUI();
|
||||
/* Configure breakpoint menu options */
|
||||
Integer address =
|
||||
CodeUI.this.mote.getExecutableAddressOf(displayedFile, line);
|
||||
if (address == null) {
|
||||
return;
|
||||
}
|
||||
final int start = codeEditorLines.get(line);
|
||||
int end = codeEditorLines.get(line+1);
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
try {
|
||||
hl.changeHighlight(selectedLineTag, start, end);
|
||||
} catch (BadLocationException e1) {
|
||||
}
|
||||
boolean hasBreakpoint =
|
||||
CodeUI.this.mote.breakpointExists(address);
|
||||
if (!hasBreakpoint) {
|
||||
actionAddBreakpoint.setEnabled(true);
|
||||
actionAddBreakpoint.putValue("WatchpointMote", CodeUI.this.mote);
|
||||
actionAddBreakpoint.putValue("WatchpointFile", displayedFile);
|
||||
actionAddBreakpoint.putValue("WatchpointLine", new Integer(line));
|
||||
actionAddBreakpoint.putValue("WatchpointAddress", new Integer(address));
|
||||
} else {
|
||||
actionRemoveBreakpoint.setEnabled(true);
|
||||
actionRemoveBreakpoint.putValue("WatchpointMote", CodeUI.this.mote);
|
||||
actionRemoveBreakpoint.putValue("WatchpointFile", displayedFile);
|
||||
actionRemoveBreakpoint.putValue("WatchpointLine", new Integer(line));
|
||||
actionRemoveBreakpoint.putValue("WatchpointAddress", new Integer(address));
|
||||
}
|
||||
}
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
try {
|
||||
hl.changeHighlight(selectedLineTag, 0, 0);
|
||||
} catch (BadLocationException e1) {
|
||||
}
|
||||
}
|
||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
displayNoCode(true);
|
||||
}
|
||||
});
|
||||
|
||||
public void updateBreakpoints() {
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
|
||||
for (Object breakpointsLineTag: breakpointsLineTags) {
|
||||
hl.removeHighlight(breakpointsLineTag);
|
||||
}
|
||||
breakpointsLineTags.clear();
|
||||
|
||||
for (Watchpoint w: mote.getBreakpoints()) {
|
||||
if (!w.getCodeFile().equals(displayedFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int start = codeEditorLines.get(w.getLineNumber());
|
||||
int end = codeEditorLines.get(w.getLineNumber()+1);
|
||||
try {
|
||||
breakpointsLineTags.add(hl.addHighlight(start, end, BREAKPOINTS_MARKER));
|
||||
} catch (BadLocationException e1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getCodeEditorMouseLine() {
|
||||
if (codeEditorLines == null) {
|
||||
return -1;
|
||||
}
|
||||
Point mousePos = codeEditor.getMousePosition();
|
||||
if (mousePos == null) {
|
||||
return -1;
|
||||
}
|
||||
int modelPos = codeEditor.viewToModel(mousePos);
|
||||
int line = 1;
|
||||
while (codeEditorLines.containsKey(line+1)) {
|
||||
int next = codeEditorLines.get(line+1);
|
||||
if (modelPos < next) {
|
||||
return line;
|
||||
}
|
||||
line++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any shown source code.
|
||||
*/
|
||||
public void displayNoCode() {
|
||||
// Display "no code" message
|
||||
public void displayNoCode(final boolean markCurrent) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
panel.removeAll();
|
||||
panel.repaint();
|
||||
displayedFile = null;
|
||||
codeEditor.setText(null);
|
||||
codeEditorLines.clear();
|
||||
displayLine(-1, markCurrent);
|
||||
}
|
||||
});
|
||||
displayedFile = null;
|
||||
return;
|
||||
}
|
||||
|
||||
private void createTokens(String[] codeData) {
|
||||
|
||||
/* Merge code lines */
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String line: codeData) {
|
||||
sb.append(line);
|
||||
sb.append('\n');
|
||||
}
|
||||
String code = sb.toString();
|
||||
|
||||
/* Scan code */
|
||||
CScanner cScanner = new CScanner();
|
||||
cScanner.change(0, 0, code.length());
|
||||
int nrTokens;
|
||||
nrTokens = cScanner.scan(code.toCharArray(), 0, code.length());
|
||||
|
||||
/* Extract tokens */
|
||||
ArrayList<Token> codeTokensVector = new ArrayList<Token>();
|
||||
for (int i=0; i < nrTokens; i++) {
|
||||
Token token = cScanner.getToken(i);
|
||||
codeTokensVector.add(token);
|
||||
}
|
||||
|
||||
/* Create new line token array */
|
||||
Token newTokensArray[][] = new Token[codeData.length][];
|
||||
int[] newTokensStartPos = new int[codeData.length];
|
||||
int lineStart=0, lineEnd=-1;
|
||||
Iterator<Token> tokens = codeTokensVector.iterator();
|
||||
Token currentToken = tokens.next();
|
||||
for (int i=0; i < newTokensArray.length; i++) {
|
||||
lineStart = lineEnd + 1;
|
||||
lineEnd = lineStart + codeData[i].length();
|
||||
|
||||
newTokensStartPos[i] = lineStart;;
|
||||
|
||||
/* Advance tokens until correct line */
|
||||
while (currentToken.position + currentToken.symbol.name.length() < lineStart) {
|
||||
if (!tokens.hasNext()) {
|
||||
break;
|
||||
}
|
||||
currentToken = tokens.next();
|
||||
}
|
||||
|
||||
/* Advance tokens until last token on line */
|
||||
Vector<Token> lineTokens = new Vector<Token>();
|
||||
while (currentToken.position < lineEnd) {
|
||||
lineTokens.add(currentToken);
|
||||
|
||||
if (!tokens.hasNext()) {
|
||||
break;
|
||||
}
|
||||
currentToken = tokens.next();
|
||||
}
|
||||
|
||||
if (currentToken == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store line tokens */
|
||||
Token[] lineTokensArray = new Token[lineTokens.size()];
|
||||
for (int j=0; j < lineTokens.size(); j++) {
|
||||
lineTokensArray[j] = lineTokens.get(j);
|
||||
}
|
||||
newTokensArray[i] = lineTokensArray;
|
||||
}
|
||||
|
||||
/* Start using tokens array */
|
||||
tokensArray = newTokensArray;
|
||||
tokensStartPos = newTokensStartPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display given source code and mark given line.
|
||||
*
|
||||
* @param codeFile Source code file
|
||||
* @param codeData Source code
|
||||
* @param lineNr Line numer
|
||||
*/
|
||||
public void displayNewCode(File codeFile, String[] codeData, final int lineNr) {
|
||||
displayedFile = codeFile;
|
||||
|
||||
if (codeData == null || codeData.length == 0) {
|
||||
displayNoCode();
|
||||
public void displayNewCode(final File codeFile, final int lineNr, final boolean markCurrent) {
|
||||
if (!codeFile.equals(displayedFile)) {
|
||||
/* Read from disk */
|
||||
final String data = StringUtils.loadFromFile(codeFile);
|
||||
if (data == null || data.length() == 0) {
|
||||
displayNoCode(markCurrent);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Opening " + codeFile + " (" + codeData.length + " lines)");
|
||||
|
||||
/* Create new list */
|
||||
final JList newList = new JList(new CodeListModel(codeData));
|
||||
newList.setBackground(Color.WHITE);
|
||||
newList.setFont(new Font("courier", 0, 12));
|
||||
newList.setCellRenderer(new CodeCellRenderer(lineNr));
|
||||
((CodeCellRenderer)newList.getCellRenderer()).setNice(false);
|
||||
newList.setFixedCellHeight(12);
|
||||
newList.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
String[] lines = data.split("\n");
|
||||
logger.info("Opening " + codeFile + " (" + lines.length + " lines)");
|
||||
int length = 0;
|
||||
codeEditorLines.clear();
|
||||
for (int line=1; line-1 < lines.length; line++) {
|
||||
codeEditorLines.put(line, length);
|
||||
length += lines[line-1].length()+1;
|
||||
}
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
codeEditor.setText(data.toString());
|
||||
displayedFile = codeFile;
|
||||
updateBreakpoints();
|
||||
}
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseExited(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
});
|
||||
createTokens(codeData);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
panel.removeAll();
|
||||
codeList = newList;
|
||||
panel.add(codeList);
|
||||
panel.validate();
|
||||
displayLine(lineNr);
|
||||
displayLine(lineNr, markCurrent);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,290 +303,35 @@ public class CodeUI extends JPanel {
|
|||
*
|
||||
* @param lineNumber Line number
|
||||
*/
|
||||
public void displayLine(int lineNumber) {
|
||||
if (codeList == null) {
|
||||
return;
|
||||
private void displayLine(int lineNumber, boolean markCurrent) {
|
||||
try {
|
||||
if (markCurrent) {
|
||||
/* remove previous highlight */
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
hl.changeHighlight(currentLineTag, 0, 0);
|
||||
}
|
||||
|
||||
((CodeCellRenderer) codeList.getCellRenderer()).setNice(false);
|
||||
((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber);
|
||||
((CodeCellRenderer) codeList.getCellRenderer()).validate();
|
||||
|
||||
if (lineNumber > 0) {
|
||||
int index = lineNumber - 1;
|
||||
codeList.setSelectedIndex(index);
|
||||
codeList.ensureIndexIsVisible(Math.max(0, index-3));
|
||||
codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize()));
|
||||
codeList.ensureIndexIsVisible(index);
|
||||
if (lineNumber >= 0) {
|
||||
final int start = codeEditorLines.get(lineNumber);
|
||||
int end = codeEditorLines.get(lineNumber+1);
|
||||
if (markCurrent) {
|
||||
/* highlight code */
|
||||
Highlighter hl = codeEditor.getHighlighter();
|
||||
hl.changeHighlight(currentLineTag, start, end);
|
||||
}
|
||||
|
||||
codeList.updateUI();
|
||||
/* ensure visible */
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
((CodeCellRenderer) codeList.getCellRenderer()).setNice(true);
|
||||
codeList.repaint();
|
||||
try {
|
||||
codeEditor.scrollRectToVisible(codeEditor.modelToView(start));
|
||||
} catch (BadLocationException e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleMouseEvent(MouseEvent event) {
|
||||
if (event.isPopupTrigger()) {
|
||||
Point menuLocation = codeList.getPopupLocation(event);
|
||||
if (menuLocation == null) {
|
||||
menuLocation = new Point(
|
||||
codeList.getLocationOnScreen().x + event.getX(),
|
||||
codeList.getLocationOnScreen().y + event.getY());
|
||||
}
|
||||
|
||||
final int currentLine = codeList.locationToIndex(new Point(event.getX(), event.getY())) + 1;
|
||||
codeList.setSelectedIndex(currentLine - 1);
|
||||
JPopupMenu popupMenu = createPopupMenu(displayedFile, currentLine);
|
||||
|
||||
popupMenu.setLocation(menuLocation);
|
||||
popupMenu.setInvoker(codeList);
|
||||
popupMenu.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Error when highlighting current line: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private JPopupMenu createPopupMenu(final File codeFile, final int lineNr) {
|
||||
final Integer executableAddress = breakpoints.getExecutableAddressOf(codeFile, lineNr);
|
||||
boolean breakpointExists = breakpoints.breakpointExists(codeFile, lineNr);
|
||||
|
||||
JPopupMenu menuMotePlugins = new JPopupMenu();
|
||||
JMenuItem headerMenuItem = new JMenuItem("Breakpoints:");
|
||||
headerMenuItem.setEnabled(false);
|
||||
menuMotePlugins.add(headerMenuItem);
|
||||
menuMotePlugins.add(new JSeparator());
|
||||
|
||||
JMenuItem addBreakpointMenuItem = new JMenuItem("Add breakpoint on line " + lineNr);
|
||||
if (executableAddress == null || breakpointExists) {
|
||||
addBreakpointMenuItem.setEnabled(false);
|
||||
} else {
|
||||
addBreakpointMenuItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
breakpoints.addBreakpoint(codeFile, lineNr, executableAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
menuMotePlugins.add(addBreakpointMenuItem);
|
||||
|
||||
JMenuItem delBreakpointMenuItem = new JMenuItem("Delete breakpoint on line " + lineNr);
|
||||
if (executableAddress == null || !breakpointExists) {
|
||||
delBreakpointMenuItem.setEnabled(false);
|
||||
} else {
|
||||
delBreakpointMenuItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
breakpoints.removeBreakpoint(executableAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
menuMotePlugins.add(delBreakpointMenuItem);
|
||||
|
||||
return menuMotePlugins;
|
||||
}
|
||||
|
||||
private class CodeListModel extends AbstractListModel {
|
||||
private String[] codeData;
|
||||
|
||||
public CodeListModel(String[] codeData) {
|
||||
super();
|
||||
this.codeData = codeData;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
if (codeData == null || codeData.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return codeData.length;
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
if (codeData == null || codeData.length == 0) {
|
||||
return "No code to display";
|
||||
}
|
||||
|
||||
return codeData[index];
|
||||
}
|
||||
}
|
||||
|
||||
/* FROM: http://www.rgagnon.com/javadetails/java-0306.html, 03/19/2008 */
|
||||
private static String stringToHTMLString(String string) {
|
||||
StringBuffer sb = new StringBuffer(string.length());
|
||||
boolean lastWasBlankChar = false;
|
||||
int len = string.length();
|
||||
char c;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
c = string.charAt(i);
|
||||
if (c == ' ') {
|
||||
if (lastWasBlankChar) {
|
||||
lastWasBlankChar = false;
|
||||
sb.append(" ");
|
||||
}
|
||||
else {
|
||||
lastWasBlankChar = true;
|
||||
sb.append(' ');
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastWasBlankChar = false;
|
||||
//
|
||||
// HTML Special Chars
|
||||
if (c == '"') {
|
||||
sb.append(""");
|
||||
} else if (c == '&') {
|
||||
sb.append("&");
|
||||
} else if (c == '<') {
|
||||
sb.append("<");
|
||||
} else if (c == '>') {
|
||||
sb.append(">");
|
||||
} else if (c == '\n') {
|
||||
// Handle Newline
|
||||
sb.append("<br/>");
|
||||
} else {
|
||||
int ci = 0xffff & c;
|
||||
if (ci < 160 ) {
|
||||
// nothing special only 7 Bit
|
||||
sb.append(c);
|
||||
} else {
|
||||
// Not 7 Bit use the unicode system
|
||||
sb.append("&#");
|
||||
sb.append(new Integer(ci).toString());
|
||||
sb.append(';');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private class CodeCellRenderer extends JLabel implements ListCellRenderer {
|
||||
private int currentIndex;
|
||||
private boolean nice = true;
|
||||
|
||||
public CodeCellRenderer(int currentLineNr) {
|
||||
this.currentIndex = currentLineNr - 1;
|
||||
}
|
||||
|
||||
public void setNice(boolean b) {
|
||||
nice = b;
|
||||
}
|
||||
|
||||
public void changeCurrentLine(int currentLineNr) {
|
||||
this.currentIndex = currentLineNr - 1;
|
||||
}
|
||||
|
||||
private String getColoredLabelText(int lineNr, int lineStartPos, Token[] tokens, String code) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<html>");
|
||||
|
||||
/* Add line number */
|
||||
String lineString = "0000" + Integer.toString(lineNr);
|
||||
lineString = lineString.substring(lineString.length() - 4);
|
||||
sb.append("<font color=\"333333\">");
|
||||
sb.append(lineString);
|
||||
sb.append(": </font>");
|
||||
|
||||
/* Add code */
|
||||
if (tokens == null || tokens.length == 0 || lineStartPos < 0) {
|
||||
sb.append("<font color=\"000000\">");
|
||||
sb.append(code);
|
||||
sb.append("</font>");
|
||||
} else {
|
||||
for (int i=tokens.length-1; i >= 0; i--) {
|
||||
Token subToken = tokens[i];
|
||||
|
||||
String colorString = "000000";
|
||||
|
||||
/* Determine code color */
|
||||
final int type = subToken.symbol.type;
|
||||
switch (type) {
|
||||
case TokenTypes.COMMENT:
|
||||
case TokenTypes.START_COMMENT:
|
||||
case TokenTypes.MID_COMMENT:
|
||||
case TokenTypes.END_COMMENT:
|
||||
colorString = "00AA00";
|
||||
break;
|
||||
case TokenTypes.STRING:
|
||||
colorString = "0000AA";
|
||||
break;
|
||||
case TokenTypes.KEYWORD:
|
||||
case TokenTypes.KEYWORD2:
|
||||
colorString = "AA0000";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract part of token residing in current line */
|
||||
int tokenLinePos;
|
||||
String subCode;
|
||||
if (subToken.position < lineStartPos) {
|
||||
subCode = subToken.symbol.name.substring(lineStartPos - subToken.position);
|
||||
tokenLinePos = 0;
|
||||
} else if (subToken.position + subToken.symbol.name.length() > lineStartPos + code.length()) {
|
||||
subCode = subToken.symbol.name.substring(0, code.length() + lineStartPos - subToken.position);
|
||||
tokenLinePos = subToken.position - lineStartPos;
|
||||
} else {
|
||||
subCode = subToken.symbol.name;
|
||||
tokenLinePos = subToken.position - lineStartPos;
|
||||
}
|
||||
|
||||
subCode = stringToHTMLString(subCode);
|
||||
String firstPart = code.substring(0, tokenLinePos);
|
||||
String coloredSubCode = "<font color=\"" + colorString + "\">" + subCode + "</font>";
|
||||
String lastPart =
|
||||
tokenLinePos + subToken.symbol.name.length() >= code.length()?
|
||||
"":code.substring(tokenLinePos + subToken.symbol.name.length());
|
||||
|
||||
code = firstPart + coloredSubCode + lastPart;
|
||||
}
|
||||
|
||||
code = code.replace(" ", " ");
|
||||
sb.append(code);
|
||||
}
|
||||
|
||||
sb.append("</html>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Component getListCellRendererComponent(
|
||||
JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus)
|
||||
{
|
||||
int lineNr = index + 1;
|
||||
if (!nice) {
|
||||
setText((String) value);
|
||||
} else if (tokensArray != null && index < tokensArray.length && tokensArray[index] != null) {
|
||||
setText(getColoredLabelText(lineNr, tokensStartPos[index], tokensArray[index], (String) value));
|
||||
} else {
|
||||
setText(getColoredLabelText(lineNr, 0, null, (String) value));
|
||||
}
|
||||
|
||||
if (index == currentIndex) {
|
||||
setBackground(Color.green);
|
||||
} else if (isSelected) {
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
} else {
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
setEnabled(list.isEnabled());
|
||||
|
||||
if (breakpoints.breakpointExists(displayedFile, lineNr)) {
|
||||
setFont(list.getFont().deriveFont(Font.BOLD));
|
||||
} else {
|
||||
setFont(list.getFont());
|
||||
}
|
||||
|
||||
setOpaque(true);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,101 +34,125 @@ package se.sics.cooja.mspmote.plugins;
|
|||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.cooja.util.StringUtils;
|
||||
import se.sics.mspsim.core.CPUMonitor;
|
||||
|
||||
/**
|
||||
* Breakpoint.
|
||||
* Contains meta data such source code file and line number.
|
||||
* Mspsim watchpoint.
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class MspBreakpoint implements Watchpoint {
|
||||
private static Logger logger = Logger.getLogger(MspBreakpoint.class);
|
||||
|
||||
private MspBreakpointContainer breakpoints;
|
||||
private MspMote mspMote;
|
||||
|
||||
private int address = -1; /* Binary address */
|
||||
private File codeFile = null; /* Source code, may be null*/
|
||||
private int lineNr = -1; /* Source code line number, may be null */
|
||||
|
||||
private CPUMonitor cpuMonitor = null;
|
||||
|
||||
private boolean stopsSimulation = true;
|
||||
|
||||
private Integer address = null; /* Binary address */
|
||||
|
||||
private File codeFile = null; /* Source code, may be null*/
|
||||
private Integer lineNr = null; /* Source code line number, may be null */
|
||||
|
||||
private String msg = null;
|
||||
private Color color = Color.BLACK;
|
||||
|
||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote) {
|
||||
this.breakpoints = breakpoints;
|
||||
private String contikiCode = null;
|
||||
|
||||
public MspBreakpoint(MspMote mote) {
|
||||
this.mspMote = mote;
|
||||
/* expects setConfigXML(..) */
|
||||
}
|
||||
|
||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address) {
|
||||
this(breakpoints, mote);
|
||||
public MspBreakpoint(MspMote mote, Integer address, File codeFile, Integer lineNr) {
|
||||
this(mote);
|
||||
this.address = address;
|
||||
this.codeFile = codeFile;
|
||||
this.lineNr = lineNr;
|
||||
|
||||
createMonitor();
|
||||
}
|
||||
|
||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address, File codeFile, Integer lineNr) {
|
||||
this(breakpoints, mote, address);
|
||||
this.codeFile = codeFile;
|
||||
this.lineNr = lineNr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MSP mote
|
||||
*/
|
||||
public MspMote getMote() {
|
||||
return mspMote;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Executable address
|
||||
*/
|
||||
public Integer getExecutableAddress() {
|
||||
return address;
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc = "";
|
||||
if (codeFile != null) {
|
||||
desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address) + ")";
|
||||
} else if (address >= 0) {
|
||||
desc += "0x" + Integer.toHexString(address);
|
||||
}
|
||||
if (msg != null) {
|
||||
desc += "\n\n" + msg;
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
public void setUserMessage(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
public String getUserMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source code file
|
||||
*/
|
||||
public File getCodeFile() {
|
||||
return codeFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source code file line number
|
||||
*/
|
||||
public Integer getLineNumber() {
|
||||
public int getLineNumber() {
|
||||
return lineNr;
|
||||
}
|
||||
|
||||
public boolean stopsSimulation() {
|
||||
return stopsSimulation;
|
||||
public int getExecutableAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setStopsSimulation(boolean stops) {
|
||||
stopsSimulation = stops;
|
||||
}
|
||||
public boolean stopsSimulation() {
|
||||
return stopsSimulation;
|
||||
}
|
||||
|
||||
private void createMonitor() {
|
||||
cpuMonitor = new CPUMonitor() {
|
||||
public void cpuAction(int type, int adr, int data) {
|
||||
breakpoints.signalBreakpointTrigger(MspBreakpoint.this);
|
||||
if (type != CPUMonitor.EXECUTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
mspMote.signalBreakpointTrigger(MspBreakpoint.this);
|
||||
}
|
||||
};
|
||||
mspMote.getCPU().addWatchPoint(address, cpuMonitor);
|
||||
|
||||
|
||||
/* Remember Contiki code, to verify it when reloaded */
|
||||
if (contikiCode == null) {
|
||||
final String code = StringUtils.loadFromFile(codeFile);
|
||||
if (code != null) {
|
||||
String[] lines = code.split("\n");
|
||||
if (lineNr-1 < lines.length) {
|
||||
contikiCode = lines[lineNr-1].trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void unregisterBreakpoint() {
|
||||
|
@ -136,27 +160,25 @@ public class MspBreakpoint implements Watchpoint {
|
|||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
||||
element = new Element("address");
|
||||
element.setText(address.toString());
|
||||
config.add(element);
|
||||
|
||||
element = new Element("stops");
|
||||
element.setText("" + stopsSimulation);
|
||||
config.add(element);
|
||||
|
||||
if (codeFile != null) {
|
||||
element = new Element("codefile");
|
||||
File file = mspMote.getSimulation().getGUI().createPortablePath(codeFile);
|
||||
element.setText(file.getPath().replaceAll("\\\\", "/"));
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
if (lineNr != null) {
|
||||
element = new Element("line");
|
||||
element.setText(lineNr.toString());
|
||||
element.setText("" + lineNr);
|
||||
config.add(element);
|
||||
|
||||
if (contikiCode != null) {
|
||||
element = new Element("contikicode");
|
||||
element.setText(contikiCode);
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
|
@ -193,8 +215,23 @@ public class MspBreakpoint implements Watchpoint {
|
|||
}
|
||||
} else if (element.getName().equals("line")) {
|
||||
lineNr = Integer.parseInt(element.getText());
|
||||
} else if (element.getName().equals("address")) {
|
||||
address = Integer.parseInt(element.getText());
|
||||
} else if (element.getName().equals("contikicode")) {
|
||||
String lastContikiCode = element.getText().trim();
|
||||
|
||||
/* Verify that Contiki code did not change */
|
||||
final String code = StringUtils.loadFromFile(codeFile);
|
||||
if (code != null) {
|
||||
String[] lines = code.split("\n");
|
||||
if (lineNr-1 < lines.length) {
|
||||
contikiCode = lines[lineNr-1].trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (!lastContikiCode.equals(contikiCode)) {
|
||||
logger.warn("Detected modified Contiki code at breakpoint: " + codeFile.getPath() + ":" + lineNr + ".");
|
||||
logger.warn("From: '" + lastContikiCode + "'");
|
||||
logger.warn(" To: '" + contikiCode + "'");
|
||||
}
|
||||
} else if (element.getName().equals("msg")) {
|
||||
msg = element.getText();
|
||||
} else if (element.getName().equals("color")) {
|
||||
|
@ -204,51 +241,18 @@ public class MspBreakpoint implements Watchpoint {
|
|||
}
|
||||
}
|
||||
|
||||
if (address == null) {
|
||||
/* Update executable address */
|
||||
address = mspMote.getExecutableAddressOf(codeFile, lineNr);
|
||||
if (address < 0) {
|
||||
logger.fatal("Could not restore breakpoint, did source code change?");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Save source code line */
|
||||
|
||||
if (codeFile != null && lineNr != null) {
|
||||
/* Update executable address */
|
||||
address = mspMote.getBreakpointsContainer().getExecutableAddressOf(codeFile, lineNr);
|
||||
if (address == null) {
|
||||
logger.fatal("Could not restore breakpoint, did source code change?");
|
||||
address = 0;
|
||||
}
|
||||
}
|
||||
|
||||
createMonitor();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setUserMessage(String msg) {
|
||||
this.msg = msg;
|
||||
public String toString() {
|
||||
return getMote() + ": " + getDescription();
|
||||
}
|
||||
public String getUserMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc = "";
|
||||
if (codeFile != null) {
|
||||
desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address.intValue()) + ")";
|
||||
} else if (address != null) {
|
||||
desc += "0x" + Integer.toHexString(address.intValue());
|
||||
}
|
||||
if (msg != null) {
|
||||
desc += "\n\n" + msg;
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,280 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*
|
||||
* $Id: MspBreakpointContainer.java,v 1.3 2010/01/21 22:32:32 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
|
||||
/**
|
||||
* Breakpoint collection
|
||||
*
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public class MspBreakpointContainer implements WatchpointMote {
|
||||
private static Logger logger = Logger.getLogger(MspBreakpointContainer.class);
|
||||
|
||||
private Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = null;
|
||||
private MspMote mspMote;
|
||||
|
||||
private ArrayList<MspBreakpoint> breakpoints = new ArrayList<MspBreakpoint>();
|
||||
private ArrayList<ActionListener> listeners = new ArrayList<ActionListener>();
|
||||
private MspBreakpoint lastTriggeredBreakpoint = null;
|
||||
|
||||
/**
|
||||
* @param debuggingInfo Debugging information read from firmware file
|
||||
* @param mote Mote
|
||||
*/
|
||||
public MspBreakpointContainer(MspMote mote, Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo) {
|
||||
this.mspMote = mote;
|
||||
this.debuggingInfo = debuggingInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add breakpoint at given address.
|
||||
*
|
||||
* @param address Executable address
|
||||
*/
|
||||
public void addBreakpoint(Integer address) {
|
||||
addBreakpoint((File) null, (Integer) null, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add breakpoint at given address with given meta data.
|
||||
*
|
||||
* @param codeFile Source code file
|
||||
* @param lineNr Source code file line number
|
||||
* @param address Executable address
|
||||
* @return Added breakpoint
|
||||
*/
|
||||
public MspBreakpoint addBreakpoint(File codeFile, int lineNr, Integer address) {
|
||||
MspBreakpoint bp = new MspBreakpoint(this, mspMote, address, codeFile, new Integer(lineNr));
|
||||
breakpoints.add(bp);
|
||||
|
||||
/* Notify listeners */
|
||||
lastTriggeredBreakpoint = null;
|
||||
for (ActionListener listener: listeners) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove breakpoint at given address.
|
||||
*
|
||||
* @param address Executable address
|
||||
*/
|
||||
public MspBreakpoint removeBreakpoint(Integer address) {
|
||||
MspBreakpoint breakpointToRemove = null;
|
||||
for (MspBreakpoint breakpoint: breakpoints) {
|
||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
||||
breakpointToRemove = breakpoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (breakpointToRemove == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
breakpointToRemove.unregisterBreakpoint();
|
||||
breakpoints.remove(breakpointToRemove);
|
||||
|
||||
/* Notify listeners */
|
||||
lastTriggeredBreakpoint = null;
|
||||
for (ActionListener listener: listeners) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
return breakpointToRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a breakpoint exists at given address.
|
||||
*
|
||||
* @param address Executable address
|
||||
* @return True if breakpoint exists, false otherwise
|
||||
*/
|
||||
public boolean breakpointExists(Integer address) {
|
||||
if (address == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (MspBreakpoint breakpoint: breakpoints) {
|
||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean breakpointExists(File file, int lineNr) {
|
||||
for (MspBreakpoint breakpoint: breakpoints) {
|
||||
if (breakpoint.getCodeFile() == null) {
|
||||
continue;
|
||||
}
|
||||
if (breakpoint.getCodeFile().compareTo(file) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (breakpoint.getLineNumber().intValue() != lineNr) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All breakpoints
|
||||
*/
|
||||
public MspBreakpoint[] getBreakpoints() {
|
||||
return breakpoints.toArray(new MspBreakpoint[0]);
|
||||
}
|
||||
|
||||
public int getBreakpointsCount() {
|
||||
return breakpoints.size();
|
||||
}
|
||||
|
||||
public void addWatchpointListener(ActionListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeWatchpointListener(ActionListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public ActionListener[] getWatchpointListeners() {
|
||||
return listeners.toArray(new ActionListener[0]);
|
||||
}
|
||||
|
||||
protected void signalBreakpointTrigger(MspBreakpoint b) {
|
||||
if (b.stopsSimulation() && mspMote.getSimulation().isRunning()) {
|
||||
/* Stop simulation immediately */
|
||||
mspMote.stopNextInstruction();
|
||||
}
|
||||
|
||||
/* Notify listeners */
|
||||
lastTriggeredBreakpoint = b;
|
||||
ActionListener[] arr = getWatchpointListeners();
|
||||
for (ActionListener listener: arr) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
}
|
||||
|
||||
public MspMote getMote() {
|
||||
return mspMote;
|
||||
}
|
||||
|
||||
public MspBreakpoint getLastWatchpoint() {
|
||||
return lastTriggeredBreakpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to calculate the executable address of given file.
|
||||
* Using debugging information from firmware file,
|
||||
*
|
||||
* @param file Source code file
|
||||
* @param lineNr Source code file line number
|
||||
* @return Executable address or null if not found
|
||||
*/
|
||||
public Integer getExecutableAddressOf(File file, int lineNr) {
|
||||
if (file == null || lineNr < 0 || debuggingInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Match file */
|
||||
Hashtable<Integer, Integer> lineTable = debuggingInfo.get(file);
|
||||
if (lineTable == null) {
|
||||
Enumeration<File> fileEnum = debuggingInfo.keys();
|
||||
while (fileEnum.hasMoreElements()) {
|
||||
File f = fileEnum.nextElement();
|
||||
if (f != null && f.getName().equals(file.getName())) {
|
||||
lineTable = debuggingInfo.get(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineTable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Match line number */
|
||||
Integer address = lineTable.get(lineNr);
|
||||
if (address != null) {
|
||||
Enumeration<Integer> lineEnum = lineTable.keys();
|
||||
while (lineEnum.hasMoreElements()) {
|
||||
Integer l = lineEnum.nextElement();
|
||||
if (l != null && l.intValue() == lineNr) {
|
||||
/* Found line address */
|
||||
return lineTable.get(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
Element element;
|
||||
|
||||
for (MspBreakpoint breakpoint: breakpoints) {
|
||||
element = new Element("breakpoint");
|
||||
element.addContent(breakpoint.getConfigXML());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
if (element.getName().equals("breakpoint")) {
|
||||
MspBreakpoint breakpoint = new MspBreakpoint(this, mspMote);
|
||||
if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) {
|
||||
logger.warn("Could not restore breakpoint: " + breakpoint);
|
||||
} else {
|
||||
breakpoints.add(breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -30,18 +30,16 @@
|
|||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
|
@ -54,8 +52,7 @@ import javax.swing.JLabel;
|
|||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
@ -72,11 +69,12 @@ import se.sics.cooja.MotePlugin;
|
|||
import se.sics.cooja.PluginType;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.VisPlugin;
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
import se.sics.cooja.WatchpointMote.WatchpointListener;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.cooja.mspmote.MspMoteType;
|
||||
import se.sics.cooja.util.StringUtils;
|
||||
import se.sics.mspsim.core.EmulationException;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.ui.DebugUI;
|
||||
import se.sics.mspsim.util.DebugInfo;
|
||||
import se.sics.mspsim.util.ELFDebug;
|
||||
|
@ -85,25 +83,31 @@ import se.sics.mspsim.util.ELFDebug;
|
|||
@PluginType(PluginType.MOTE_PLUGIN)
|
||||
public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
||||
private static final long serialVersionUID = -8463196456352243367L;
|
||||
|
||||
private static final int SOURCECODE = 0;
|
||||
private static final int BREAKPOINTS = 2;
|
||||
|
||||
private static Logger logger = Logger.getLogger(MspCodeWatcher.class);
|
||||
private Simulation simulation;
|
||||
private Observer simObserver;
|
||||
private MspMote mspMote;
|
||||
|
||||
private File currentCodeFile = null;
|
||||
private int currentLineNumber = -1;
|
||||
|
||||
private JSplitPane leftSplitPane, rightSplitPane;
|
||||
private DebugUI assCodeUI;
|
||||
private CodeUI sourceCodeUI;
|
||||
private BreakpointsUI breakpointsUI;
|
||||
|
||||
private MspBreakpointContainer breakpoints = null;
|
||||
private MspMote mspMote; /* currently the only supported mote */
|
||||
private WatchpointMote watchpointMote;
|
||||
private WatchpointListener watchpointListener;
|
||||
|
||||
private JComboBox fileComboBox;
|
||||
private String[] debugInfoMap = null;
|
||||
private File[] sourceFiles;
|
||||
|
||||
private JTabbedPane mainPane;
|
||||
|
||||
/**
|
||||
* Mini-debugger for MSP Motes.
|
||||
* Visualizes instructions, source code and allows a user to manipulate breakpoints.
|
||||
|
@ -113,15 +117,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
* @param gui Simulator
|
||||
*/
|
||||
public MspCodeWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
||||
super("Msp Code Watcher", gui);
|
||||
this.mspMote = (MspMote) mote;
|
||||
super("Msp Code Watcher - " + mote, gui);
|
||||
simulation = simulationToVisualize;
|
||||
this.mspMote = (MspMote) mote;
|
||||
this.watchpointMote = (WatchpointMote) mote;
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
|
||||
/* Breakpoints */
|
||||
breakpoints = mspMote.getBreakpointsContainer();
|
||||
|
||||
/* Create source file list */
|
||||
fileComboBox = new JComboBox();
|
||||
fileComboBox.addActionListener(new ActionListener() {
|
||||
|
@ -151,56 +153,66 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
updateFileComboBox();
|
||||
|
||||
/* Browse code control (north) */
|
||||
JButton currentFileButton = new JButton(currentFileAction);
|
||||
JButton mapButton = new JButton(mapAction);
|
||||
Box sourceCodeControl = Box.createHorizontalBox();
|
||||
sourceCodeControl.add(new JButton(stepAction));
|
||||
sourceCodeControl.add(Box.createHorizontalStrut(10));
|
||||
sourceCodeControl.add(new JLabel("Current location: "));
|
||||
sourceCodeControl.add(new JButton(currentFileAction));
|
||||
sourceCodeControl.add(Box.createHorizontalGlue());
|
||||
sourceCodeControl.add(new JLabel("Source files: "));
|
||||
sourceCodeControl.add(fileComboBox);
|
||||
sourceCodeControl.add(Box.createHorizontalStrut(5));
|
||||
sourceCodeControl.add(new JButton(mapAction));
|
||||
sourceCodeControl.add(Box.createHorizontalStrut(10));
|
||||
|
||||
Box browseBox = Box.createHorizontalBox();
|
||||
browseBox.add(Box.createHorizontalStrut(10));
|
||||
browseBox.add(new JLabel("Program counter: "));
|
||||
browseBox.add(currentFileButton);
|
||||
browseBox.add(Box.createHorizontalGlue());
|
||||
browseBox.add(new JLabel("Browse: "));
|
||||
browseBox.add(fileComboBox);
|
||||
browseBox.add(Box.createHorizontalStrut(10));
|
||||
browseBox.add(mapButton);
|
||||
browseBox.add(Box.createHorizontalStrut(10));
|
||||
/* Execution control panel (south of source code panel) */
|
||||
|
||||
/* Execution control panel (south) */
|
||||
JPanel controlPanel = new JPanel();
|
||||
JButton button = new JButton(stepAction);
|
||||
controlPanel.add(button);
|
||||
/* Layout */
|
||||
mainPane = new JTabbedPane();
|
||||
|
||||
sourceCodeUI = new CodeUI(watchpointMote);
|
||||
JPanel sourceCodePanel = new JPanel(new BorderLayout());
|
||||
sourceCodePanel.add(BorderLayout.CENTER, sourceCodeUI);
|
||||
sourceCodePanel.add(BorderLayout.SOUTH, sourceCodeControl);
|
||||
mainPane.addTab("Source code", null, sourceCodePanel, null); /* SOURCECODE */
|
||||
|
||||
/* Main components: assembler and C code + breakpoints (center) */
|
||||
assCodeUI = new DebugUI(this.mspMote.getCPU(), true);
|
||||
breakpointsUI = new BreakpointsUI(breakpoints, this);
|
||||
sourceCodeUI = new CodeUI(breakpoints);
|
||||
leftSplitPane = new JSplitPane(
|
||||
JSplitPane.HORIZONTAL_SPLIT,
|
||||
new JScrollPane(assCodeUI),
|
||||
new JScrollPane(breakpointsUI)
|
||||
);
|
||||
leftSplitPane.setOneTouchExpandable(true);
|
||||
leftSplitPane.setDividerLocation(0.0);
|
||||
rightSplitPane = new JSplitPane(
|
||||
JSplitPane.HORIZONTAL_SPLIT,
|
||||
leftSplitPane,
|
||||
new JScrollPane(sourceCodeUI)
|
||||
);
|
||||
rightSplitPane.setOneTouchExpandable(true);
|
||||
rightSplitPane.setDividerLocation(0.0);
|
||||
for (Component c: assCodeUI.getComponents()) {
|
||||
c.setBackground(Color.WHITE);
|
||||
}
|
||||
mainPane.addTab("Instructions", null, assCodeUI, null);
|
||||
|
||||
add(BorderLayout.NORTH, browseBox);
|
||||
add(BorderLayout.CENTER, rightSplitPane);
|
||||
add(BorderLayout.SOUTH, controlPanel);
|
||||
breakpointsUI = new BreakpointsUI(mspMote, this);
|
||||
mainPane.addTab("Breakpoints", null, breakpointsUI, "Right-click source code to add"); /* BREAKPOINTS */
|
||||
|
||||
add(BorderLayout.CENTER, mainPane);
|
||||
|
||||
/* Listen for breakpoint changes */
|
||||
watchpointMote.addWatchpointListener(watchpointListener = new WatchpointListener() {
|
||||
public void watchpointTriggered(final Watchpoint watchpoint) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
logger.info("Watchpoint triggered: " + watchpoint);
|
||||
if (simulation.isRunning()) {
|
||||
return;
|
||||
}
|
||||
breakpointsUI.selectBreakpoint(watchpoint);
|
||||
sourceCodeUI.updateBreakpoints();
|
||||
showCurrentPC();
|
||||
}
|
||||
});
|
||||
}
|
||||
public void watchpointsChanged() {
|
||||
sourceCodeUI.updateBreakpoints();
|
||||
}
|
||||
});
|
||||
|
||||
/* Observe when simulation starts/stops */
|
||||
simulation.addObserver(simObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
if (!simulation.isRunning()) {
|
||||
stepAction.setEnabled(true);
|
||||
updateInfo();
|
||||
showCurrentPC();
|
||||
} else {
|
||||
stepAction.setEnabled(false);
|
||||
}
|
||||
|
@ -208,7 +220,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
});
|
||||
|
||||
setSize(750, 500);
|
||||
updateInfo();
|
||||
showCurrentPC();
|
||||
}
|
||||
|
||||
private void updateFileComboBox() {
|
||||
|
@ -221,25 +233,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
fileComboBox.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
public void displaySourceFile(File file, final int line) {
|
||||
if (file != null &&
|
||||
sourceCodeUI.displayedFile != null &&
|
||||
file.compareTo(sourceCodeUI.displayedFile) == 0) {
|
||||
/* No need to reload source file */
|
||||
public void displaySourceFile(final File file, final int line, final boolean markCurrent) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
sourceCodeUI.displayLine(line);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load source file from disk */
|
||||
String[] codeData = readTextFile(file);
|
||||
if (codeData == null) {
|
||||
return;
|
||||
}
|
||||
sourceCodeUI.displayNewCode(file, codeData, line);
|
||||
mainPane.setSelectedIndex(SOURCECODE); /* code */
|
||||
sourceCodeUI.displayNewCode(file, line, markCurrent);
|
||||
}});
|
||||
}
|
||||
|
||||
private void sourceFileSelectionChanged() {
|
||||
|
@ -249,32 +248,40 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
}
|
||||
|
||||
File selectedFile = sourceFiles[index-1];
|
||||
displaySourceFile(selectedFile, -1);
|
||||
displaySourceFile(selectedFile, -1, false);
|
||||
}
|
||||
|
||||
private void updateInfo() {
|
||||
private void showCurrentPC() {
|
||||
/* Instructions */
|
||||
assCodeUI.updateRegs();
|
||||
assCodeUI.repaint();
|
||||
|
||||
/* Source */
|
||||
updateCurrentSourceCodeFile();
|
||||
if (currentCodeFile == null) {
|
||||
File file = currentCodeFile;
|
||||
Integer line = currentLineNumber;
|
||||
if (file == null || line == null) {
|
||||
currentFileAction.setEnabled(false);
|
||||
currentFileAction.putValue(Action.NAME, "[unknown]");
|
||||
currentFileAction.putValue(Action.SHORT_DESCRIPTION, null);
|
||||
return;
|
||||
}
|
||||
currentFileAction.setEnabled(true);
|
||||
currentFileAction.putValue(Action.NAME, currentCodeFile.getName() + ":" + currentLineNumber);
|
||||
currentFileAction.putValue(Action.SHORT_DESCRIPTION, currentCodeFile.getAbsolutePath() + ":" + currentLineNumber);
|
||||
fileComboBox.setSelectedItem(currentCodeFile.getName());
|
||||
currentFileAction.putValue(Action.NAME, file.getName() + ":" + line);
|
||||
currentFileAction.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath() + ":" + line);
|
||||
fileComboBox.setSelectedItem(file.getName());
|
||||
|
||||
displaySourceFile(currentCodeFile, currentLineNumber);
|
||||
displaySourceFile(file, line, true);
|
||||
}
|
||||
|
||||
public void closePlugin() {
|
||||
watchpointMote.removeWatchpointListener(watchpointListener);
|
||||
watchpointListener = null;
|
||||
|
||||
simulation.deleteObserver(simObserver);
|
||||
simObserver = null;
|
||||
|
||||
/* TODO XXX Unregister breakpoints? */
|
||||
}
|
||||
|
||||
private void updateCurrentSourceCodeFile() {
|
||||
|
@ -285,8 +292,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
if (debug == null) {
|
||||
return;
|
||||
}
|
||||
DebugInfo debugInfo = debug.getDebugInfo(mspMote.getCPU().reg[MSP430.PC]);
|
||||
int pc = mspMote.getCPU().getPC();
|
||||
DebugInfo debugInfo = debug.getDebugInfo(pc);
|
||||
if (debugInfo == null) {
|
||||
if (pc != 0) {
|
||||
logger.warn("No sourcecode info at " + String.format("0x%04x", mspMote.getCPU().getPC()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -321,6 +332,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
private void tryMapDebugInfo() {
|
||||
final String[] debugFiles;
|
||||
try {
|
||||
|
||||
ELFDebug debug = ((MspMoteType)mspMote.getType()).getELF().getDebug();
|
||||
debugFiles = debug != null ? debug.getSourceFiles() : null;
|
||||
if (debugFiles == null) {
|
||||
|
@ -539,52 +551,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
return sorted.toArray(new File[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to open and read given text file.
|
||||
*
|
||||
* @param file File
|
||||
* @return Line-by-line text in file
|
||||
*/
|
||||
public static String[] readTextFile(File file) {
|
||||
if (GUI.isVisualizedInApplet()) {
|
||||
/* Download from web server instead */
|
||||
String path = file.getPath();
|
||||
|
||||
/* Extract Contiki build path */
|
||||
String contikiBuildPath = GUI.getExternalToolsSetting("PATH_CONTIKI_BUILD");
|
||||
String contikiWebPath = GUI.getExternalToolsSetting("PATH_CONTIKI_WEB");
|
||||
|
||||
if (!path.startsWith(contikiBuildPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
/* Replace Contiki parent path with web server code base */
|
||||
path = contikiWebPath + '/' + path.substring(contikiBuildPath.length());
|
||||
path = path.replace('\\', '/');
|
||||
URL url = new URL(GUI.getAppletCodeBase(), path);
|
||||
String data = StringUtils.loadFromURL(url);
|
||||
return data!=null?data.split("\n"):null;
|
||||
} catch (MalformedURLException e) {
|
||||
logger.warn("Failure to read source code: " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String data = StringUtils.loadFromFile(file);
|
||||
return data!=null?data.split("\n"):null;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
||||
element = new Element("split_1");
|
||||
element.addContent("" + leftSplitPane.getDividerLocation());
|
||||
config.add(element);
|
||||
|
||||
element = new Element("split_2");
|
||||
element.addContent("" + rightSplitPane.getDividerLocation());
|
||||
element = new Element("tab");
|
||||
element.addContent("" + mainPane.getSelectedIndex());
|
||||
config.add(element);
|
||||
|
||||
return config;
|
||||
|
@ -592,10 +564,8 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
if (element.getName().equals("split_1")) {
|
||||
leftSplitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
||||
} else if (element.getName().equals("split_2")) {
|
||||
rightSplitPane.setDividerLocation(Integer.parseInt(element.getText()));
|
||||
if (element.getName().equals("tab")) {
|
||||
mainPane.setSelectedIndex(Integer.parseInt(element.getText()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -608,11 +578,11 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
if (currentCodeFile == null) {
|
||||
return;
|
||||
}
|
||||
displaySourceFile(currentCodeFile, currentLineNumber);
|
||||
displaySourceFile(currentCodeFile, currentLineNumber, true);
|
||||
}
|
||||
};
|
||||
|
||||
private AbstractAction mapAction = new AbstractAction("Map") {
|
||||
private AbstractAction mapAction = new AbstractAction("Locate sources") {
|
||||
private static final long serialVersionUID = -3929432830596292495L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
@ -622,14 +592,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin {
|
|||
|
||||
private AbstractAction stepAction = new AbstractAction("Step instruction") {
|
||||
private static final long serialVersionUID = 3520750710757816575L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
mspMote.getCPU().stepInstructions(1);
|
||||
} catch (EmulationException ex) {
|
||||
logger.fatal("Error: ", ex);
|
||||
}
|
||||
updateInfo();
|
||||
showCurrentPC();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -62,6 +63,7 @@ The COOJA Simulator
|
|||
<classpath>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
@ -74,6 +76,7 @@ The COOJA Simulator
|
|||
<pathelement path="."/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
@ -104,6 +107,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -118,6 +122,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -131,6 +136,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -144,6 +150,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -156,6 +163,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
<pathelement location="../mspsim/lib/jfreechart-1.0.11.jar"/>
|
||||
<pathelement location="../mspsim/lib/jcommon-1.0.14.jar"/>
|
||||
</classpath>
|
||||
|
@ -170,6 +178,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -190,6 +199,7 @@ The COOJA Simulator
|
|||
<pathelement path="${build}"/>
|
||||
<pathelement location="lib/jdom.jar"/>
|
||||
<pathelement location="lib/log4j.jar"/>
|
||||
<pathelement location="lib/jsyntaxpane.jar"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
@ -214,7 +224,7 @@ The COOJA Simulator
|
|||
<jar destfile="${dist}/cooja.jar" basedir="${build}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="se.sics.cooja.GUI"/>
|
||||
<attribute name="Class-Path" value=". lib/log4j.jar lib/jdom.jar"/>
|
||||
<attribute name="Class-Path" value=". lib/log4j.jar lib/jdom.jar lib/jsyntaxpane.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
<mkdir dir="${dist}/lib"/>
|
||||
|
|
|
@ -32,24 +32,26 @@
|
|||
package se.sics.cooja;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public interface Watchpoint {
|
||||
|
||||
/**
|
||||
* @return Short watchpoint description
|
||||
*/
|
||||
public String getDescription();
|
||||
public WatchpointMote getMote();
|
||||
|
||||
/**
|
||||
* @return Mote
|
||||
*/
|
||||
public Mote getMote();
|
||||
|
||||
/**
|
||||
* @return Color
|
||||
*/
|
||||
public Color getColor();
|
||||
public void setColor(Color newColor);
|
||||
|
||||
public String getDescription();
|
||||
public void setUserMessage(String msg);
|
||||
public String getUserMessage();
|
||||
|
||||
public File getCodeFile();
|
||||
public int getLineNumber();
|
||||
public int getExecutableAddress();
|
||||
|
||||
public void setStopsSimulation(boolean b);
|
||||
public boolean stopsSimulation();
|
||||
}
|
||||
|
|
|
@ -31,12 +31,17 @@
|
|||
|
||||
package se.sics.cooja;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public interface WatchpointMote {
|
||||
public interface WatchpointMote extends Mote {
|
||||
|
||||
public interface WatchpointListener {
|
||||
public void watchpointTriggered(Watchpoint watchpoint);
|
||||
public void watchpointsChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a breakpoint listener.
|
||||
|
@ -44,28 +49,27 @@ public interface WatchpointMote {
|
|||
*
|
||||
* @param listener Action listener
|
||||
*/
|
||||
public void addWatchpointListener(ActionListener listener);
|
||||
public void addWatchpointListener(WatchpointListener listener);
|
||||
|
||||
/**
|
||||
* Removes previously registered listener.
|
||||
*
|
||||
* @param listener Listeners
|
||||
*/
|
||||
public void removeWatchpointListener(ActionListener listener);
|
||||
public void removeWatchpointListener(WatchpointListener listener);
|
||||
|
||||
/**
|
||||
* @return All registered listeners
|
||||
*/
|
||||
public ActionListener[] getWatchpointListeners();
|
||||
public WatchpointListener[] getWatchpointListeners();
|
||||
|
||||
/**
|
||||
* @return Last triggered watchpoint
|
||||
*/
|
||||
public Watchpoint getLastWatchpoint();
|
||||
public Watchpoint addBreakpoint(File codeFile, int lineNr, int address);
|
||||
public void removeBreakpoint(Watchpoint watchpoint);
|
||||
public Watchpoint[] getBreakpoints();
|
||||
|
||||
/**
|
||||
* @return Mote
|
||||
*/
|
||||
public Mote getMote();
|
||||
public boolean breakpointExists(int address);
|
||||
public boolean breakpointExists(File file, int lineNr);
|
||||
|
||||
public Integer getExecutableAddressOf(File file, int lineNr);
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
package se.sics.cooja.plugins;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
|
@ -53,9 +54,12 @@ import java.util.Observer;
|
|||
|
||||
import javax.script.ScriptException;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
|
@ -63,8 +67,10 @@ import javax.swing.JPopupMenu;
|
|||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import jsyntaxpane.DefaultSyntaxKit;
|
||||
import jsyntaxpane.actions.DefaultSyntaxAction;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
@ -83,6 +89,10 @@ public class ScriptRunner extends VisPlugin {
|
|||
private static final long serialVersionUID = 7614358340336799109L;
|
||||
private static Logger logger = Logger.getLogger(ScriptRunner.class);
|
||||
|
||||
{
|
||||
DefaultSyntaxKit.initKit();
|
||||
}
|
||||
|
||||
final String[] EXAMPLE_SCRIPTS = new String[] {
|
||||
"basic.js", "Various commands",
|
||||
"helloworld.js", "Wait for 'Hello, world'",
|
||||
|
@ -97,24 +107,19 @@ public class ScriptRunner extends VisPlugin {
|
|||
|
||||
private static BufferedWriter logWriter = null; /* For non-GUI tests */
|
||||
|
||||
private JTextArea scriptTextArea = null;
|
||||
private JEditorPane codeEditor = null;
|
||||
|
||||
private JTextArea logTextArea = null;
|
||||
private JButton toggleButton = null;
|
||||
private JButton examplesButton = null;
|
||||
|
||||
private int scriptFirstLinesNumber;
|
||||
private JSyntaxLinkFile actionLinkFile = null;
|
||||
private File linkedFile = null;
|
||||
|
||||
public ScriptRunner(Simulation simulation, GUI gui) {
|
||||
super("Contiki Test Editor", gui, false);
|
||||
this.simulation = simulation;
|
||||
|
||||
final JTextArea lineTextArea = new JTextArea();
|
||||
lineTextArea.setEnabled(false);
|
||||
lineTextArea.setMargin(new Insets(5,0,5,0));
|
||||
|
||||
scriptFirstLinesNumber = 1;
|
||||
|
||||
/* Examples popup menu */
|
||||
final JPopupMenu popupMenu = new JPopupMenu();
|
||||
JMenuItem moteItem;
|
||||
|
@ -148,65 +153,19 @@ public class ScriptRunner extends VisPlugin {
|
|||
}
|
||||
});
|
||||
|
||||
{
|
||||
/* Workaround to configure jsyntaxpane */
|
||||
JEditorPane e = new JEditorPane();
|
||||
new JScrollPane(e);
|
||||
e.setContentType("text/javascript");
|
||||
DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit();
|
||||
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
|
||||
kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName());
|
||||
}
|
||||
|
||||
/* Script area */
|
||||
scriptTextArea = new JTextArea(12,50);
|
||||
scriptTextArea.getDocument().addDocumentListener(new DocumentListener() {
|
||||
private int lastLines = -1;
|
||||
|
||||
private void update() {
|
||||
int lines = scriptTextArea.getLineCount() + scriptFirstLinesNumber;
|
||||
if (lines == lastLines) {
|
||||
return;
|
||||
}
|
||||
lastLines = lines;
|
||||
|
||||
String txt = "";
|
||||
for (int i=scriptFirstLinesNumber; i < 10; i++) {
|
||||
if (i > lines) {
|
||||
break;
|
||||
}
|
||||
txt += "00" + i + "\n";
|
||||
}
|
||||
for (int i=10; i < 100; i++) {
|
||||
if (i > lines) {
|
||||
break;
|
||||
}
|
||||
txt += "0" + i + "\n";
|
||||
}
|
||||
for (int i=100; i < 1000; i++) {
|
||||
if (i > lines) {
|
||||
break;
|
||||
}
|
||||
txt += i + "\n";
|
||||
}
|
||||
lineTextArea.setText(txt);
|
||||
|
||||
/*ScriptParser parser;
|
||||
try {
|
||||
parser = new ScriptParser(scriptTextArea.getText());
|
||||
String tooltip = parser.getJSCode();
|
||||
tooltip = tooltip.replaceAll("\n", "<br>");
|
||||
tooltip = "<html><b>Generated code:</b><p>" + tooltip + "</html>";
|
||||
lineTextArea.setToolTipText(tooltip);
|
||||
} catch (ScriptSyntaxErrorException e) {
|
||||
lineTextArea.setToolTipText("Unable to generate code: " + e.getMessage());
|
||||
}*/
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
});
|
||||
scriptTextArea.setMargin(new Insets(5,0,5,5));
|
||||
scriptTextArea.setEditable(true);
|
||||
scriptTextArea.setCursor(null);
|
||||
scriptTextArea.setTabSize(1);
|
||||
setLayout(new BorderLayout());
|
||||
codeEditor = new JEditorPane();
|
||||
|
||||
logTextArea = new JTextArea(12,50);
|
||||
logTextArea.setMargin(new Insets(5,5,5,5));
|
||||
|
@ -231,16 +190,30 @@ public class ScriptRunner extends VisPlugin {
|
|||
}
|
||||
});
|
||||
|
||||
JPanel scriptArea = new JPanel(new BorderLayout());
|
||||
scriptArea.setEnabled(false);
|
||||
scriptArea.add(BorderLayout.WEST, lineTextArea);
|
||||
scriptArea.add(BorderLayout.CENTER, scriptTextArea);
|
||||
|
||||
doLayout();
|
||||
JSplitPane centerPanel = new JSplitPane(
|
||||
JSplitPane.VERTICAL_SPLIT,
|
||||
new JScrollPane(scriptArea),
|
||||
new JScrollPane(codeEditor),
|
||||
new JScrollPane(logTextArea)
|
||||
);
|
||||
|
||||
codeEditor.setContentType("text/javascript");
|
||||
DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit();
|
||||
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
|
||||
kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName());
|
||||
|
||||
JPopupMenu p = codeEditor.getComponentPopupMenu();
|
||||
for (Component c: p.getComponents()) {
|
||||
if (c instanceof JMenuItem) {
|
||||
if (((JMenuItem) c).getAction() != null &&
|
||||
((JMenuItem) c).getAction() instanceof JSyntaxLinkFile) {
|
||||
actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction());
|
||||
actionLinkFile.setMenuText("Link script to disk file");
|
||||
actionLinkFile.putValue("ScriptRunner", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
centerPanel.setOneTouchExpandable(true);
|
||||
centerPanel.setResizeWeight(0.5);
|
||||
|
||||
|
@ -271,21 +244,43 @@ public class ScriptRunner extends VisPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
public void setLinkFile(File source) {
|
||||
linkedFile = source;
|
||||
if (source == null) {
|
||||
updateScript("");
|
||||
|
||||
actionLinkFile.setMenuText("Link script to disk file");
|
||||
actionLinkFile.putValue("JavascriptSource", null);
|
||||
|
||||
codeEditor.setEditable(true);
|
||||
} else {
|
||||
updateScript(linkedFile);
|
||||
|
||||
actionLinkFile.setMenuText("Unlink script: " + source.getName());
|
||||
actionLinkFile.putValue("JavascriptSource", source);
|
||||
|
||||
codeEditor.setEditable(false);
|
||||
}
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
public void setScriptActive(boolean active) {
|
||||
if (active) {
|
||||
/* setScriptActive(true) */
|
||||
|
||||
/* Free any resources */
|
||||
setScriptActive(false);
|
||||
|
||||
/* Reload script from file */
|
||||
if (scriptFile != null) {
|
||||
String script = StringUtils.loadFromFile(scriptFile);
|
||||
if (linkedFile != null) {
|
||||
String script = StringUtils.loadFromFile(linkedFile);
|
||||
if (script == null) {
|
||||
logger.fatal("Failed to load script from: " + scriptFile.getAbsolutePath());
|
||||
logger.fatal("Failed to load script from: " + linkedFile.getAbsolutePath());
|
||||
} else {
|
||||
updateScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
if (active) {
|
||||
/* Free any resources */
|
||||
setScriptActive(false);
|
||||
|
||||
/* Create new engine */
|
||||
engine = new LogScriptEngine(simulation);
|
||||
if (GUI.isVisualized()) {
|
||||
|
@ -331,14 +326,14 @@ public class ScriptRunner extends VisPlugin {
|
|||
|
||||
/* Activate engine */
|
||||
try {
|
||||
engine.activateScript(scriptTextArea.getText());
|
||||
engine.activateScript(codeEditor.getText());
|
||||
|
||||
actionLinkFile.setEnabled(false);
|
||||
toggleButton.setText("Deactivate");
|
||||
examplesButton.setEnabled(false);
|
||||
logTextArea.setText("");
|
||||
scriptTextArea.setEnabled(false);
|
||||
setTitle("Contiki Test Editor (ACTIVE) "
|
||||
+ (scriptFile==null?"":" (" + scriptFile.getName() + ")"));
|
||||
codeEditor.setEnabled(false);
|
||||
updateTitle();
|
||||
|
||||
logger.info("Test script activated");
|
||||
|
||||
|
@ -355,14 +350,14 @@ public class ScriptRunner extends VisPlugin {
|
|||
}
|
||||
|
||||
} else {
|
||||
if (engine == null) {
|
||||
return;
|
||||
}
|
||||
/* setScriptActive(false) */
|
||||
|
||||
if (engine != null) {
|
||||
/* Deactivate script */
|
||||
engine.deactivateScript();
|
||||
engine.setScriptLogObserver(null);
|
||||
engine = null;
|
||||
}
|
||||
|
||||
if (logWriter != null) {
|
||||
try {
|
||||
|
@ -376,15 +371,26 @@ public class ScriptRunner extends VisPlugin {
|
|||
logWriter = null;
|
||||
}
|
||||
|
||||
actionLinkFile.setEnabled(true);
|
||||
toggleButton.setText("Activate");
|
||||
examplesButton.setEnabled(true);
|
||||
scriptTextArea.setEnabled(scriptFile==null?true:false);
|
||||
examplesButton.setEnabled(linkedFile==null?true:false);
|
||||
codeEditor.setEnabled(true);
|
||||
logger.info("Test script deactivated");
|
||||
setTitle("Contiki Test Editor"
|
||||
+ (scriptFile==null?"":" (" + scriptFile.getName() + ")"));
|
||||
updateTitle();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTitle() {
|
||||
String title = "Contiki Test Editor ";
|
||||
if (linkedFile != null) {
|
||||
title += ": " + linkedFile.getName() + " ";
|
||||
}
|
||||
if (isActive()) {
|
||||
title += "(ACTIVE) ";
|
||||
}
|
||||
setTitle(title);
|
||||
}
|
||||
|
||||
private void exportAndRun() {
|
||||
/* Save simulation config */
|
||||
File configFile = simulation.getGUI().doSaveConfig(true);
|
||||
|
@ -558,7 +564,7 @@ public class ScriptRunner extends VisPlugin {
|
|||
return;
|
||||
}
|
||||
|
||||
scriptTextArea.setText(script);
|
||||
codeEditor.setText(script);
|
||||
logTextArea.setText("");
|
||||
}
|
||||
|
||||
|
@ -566,29 +572,32 @@ public class ScriptRunner extends VisPlugin {
|
|||
ArrayList<Element> config = new ArrayList<Element>();
|
||||
Element element;
|
||||
|
||||
if (scriptFile != null) {
|
||||
if (linkedFile != null) {
|
||||
element = new Element("scriptfile");
|
||||
element.setText(simulation.getGUI().createPortablePath(scriptFile).getPath().replace('\\', '/'));
|
||||
element.setText(simulation.getGUI().createPortablePath(linkedFile).getPath().replace('\\', '/'));
|
||||
config.add(element);
|
||||
/*StringUtils.saveToFile(scriptFile, scriptTextArea.getText());*/
|
||||
} else {
|
||||
element = new Element("script");
|
||||
element.setText(scriptTextArea.getText());
|
||||
element.setText(codeEditor.getText());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
element = new Element("active");
|
||||
element.setText("" + (engine != null));
|
||||
element.setText("" + isActive());
|
||||
config.add(element);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return engine != null;
|
||||
|
||||
}
|
||||
public void closePlugin() {
|
||||
setScriptActive(false);
|
||||
}
|
||||
|
||||
private File scriptFile = null;
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
String name = element.getName();
|
||||
|
@ -598,14 +607,7 @@ public class ScriptRunner extends VisPlugin {
|
|||
}
|
||||
} else if ("scriptfile".equals(name)) {
|
||||
File file = simulation.getGUI().restorePortablePath(new File(element.getText().trim()));
|
||||
String script = StringUtils.loadFromFile(file);
|
||||
if (script == null) {
|
||||
logger.fatal("Failed to load script from: " + file.getAbsolutePath());
|
||||
} else {
|
||||
updateScript(script);
|
||||
}
|
||||
scriptFile = file;
|
||||
scriptTextArea.setEnabled(false);
|
||||
setLinkFile(file);
|
||||
} else if ("active".equals(name)) {
|
||||
boolean active = Boolean.parseBoolean(element.getText());
|
||||
if (GUI.isVisualized()) {
|
||||
|
@ -627,4 +629,45 @@ public class ScriptRunner extends VisPlugin {
|
|||
return StringUtils.loadFromURL(ScriptRunner.class.getResource("/scripts/" + file));
|
||||
}
|
||||
|
||||
public static class JSyntaxLinkFile extends DefaultSyntaxAction {
|
||||
private static Logger logger = Logger.getLogger(JSyntaxLinkFile.class);
|
||||
|
||||
public JSyntaxLinkFile() {
|
||||
super("linkfile");
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuItem menuItem = (JMenuItem) e.getSource();
|
||||
Action action = menuItem.getAction();
|
||||
ScriptRunner scriptRunner = (ScriptRunner) action.getValue("ScriptRunner");
|
||||
File currentSource = (File) action.getValue("JavascriptSource");
|
||||
|
||||
if (currentSource != null) {
|
||||
scriptRunner.setLinkFile(null);
|
||||
return;
|
||||
}
|
||||
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setCurrentDirectory(new java.io.File("."));
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fileChooser.setDialogTitle("Select script file");
|
||||
fileChooser.setFileFilter(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
if (file.isDirectory()) { return true; }
|
||||
if (file.getName().endsWith(".js")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public String getDescription() {
|
||||
return "Javascript";
|
||||
}
|
||||
});
|
||||
if (fileChooser.showOpenDialog(scriptRunner) != JFileChooser.APPROVE_OPTION) {
|
||||
logger.debug("cancel");
|
||||
return;
|
||||
}
|
||||
scriptRunner.setLinkFile(fileChooser.getSelectedFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,11 +88,12 @@ import se.sics.cooja.GUI;
|
|||
import se.sics.cooja.Mote;
|
||||
import se.sics.cooja.Plugin;
|
||||
import se.sics.cooja.PluginType;
|
||||
import se.sics.cooja.SimEventCentral.MoteCountListener;
|
||||
import se.sics.cooja.Simulation;
|
||||
import se.sics.cooja.VisPlugin;
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
import se.sics.cooja.SimEventCentral.MoteCountListener;
|
||||
import se.sics.cooja.WatchpointMote.WatchpointListener;
|
||||
import se.sics.cooja.interfaces.LED;
|
||||
import se.sics.cooja.interfaces.Radio;
|
||||
import se.sics.cooja.interfaces.Radio.RadioEvent;
|
||||
|
@ -850,7 +851,7 @@ public class TimeLine extends VisPlugin {
|
|||
if (popupLocation == null) {
|
||||
return;
|
||||
}
|
||||
long time = (long) ((double)popupLocation.x*currentPixelDivisor);
|
||||
long time = (long) (popupLocation.x*currentPixelDivisor);
|
||||
|
||||
Plugin[] plugins = simulation.getGUI().getStartedPlugins();
|
||||
for (Plugin p: plugins) {
|
||||
|
@ -870,7 +871,7 @@ public class TimeLine extends VisPlugin {
|
|||
if (popupLocation == null) {
|
||||
return;
|
||||
}
|
||||
long time = (long) ((double)popupLocation.x*currentPixelDivisor);
|
||||
long time = (long) (popupLocation.x*currentPixelDivisor);
|
||||
|
||||
Plugin[] plugins = simulation.getGUI().getStartedPlugins();
|
||||
for (Plugin p: plugins) {
|
||||
|
@ -929,7 +930,7 @@ public class TimeLine extends VisPlugin {
|
|||
private Mote mote;
|
||||
|
||||
private WatchpointMote watchpointMote; /* XXX */
|
||||
private ActionListener watchpointListener; /* XXX */
|
||||
private WatchpointListener watchpointListener; /* XXX */
|
||||
|
||||
public MoteObservation(Mote mote, Observable observable, Observer observer) {
|
||||
this.mote = mote;
|
||||
|
@ -938,7 +939,7 @@ public class TimeLine extends VisPlugin {
|
|||
}
|
||||
|
||||
/* XXX Special case, should be generalized */
|
||||
public MoteObservation(Mote mote, WatchpointMote watchpointMote, ActionListener listener) {
|
||||
public MoteObservation(Mote mote, WatchpointMote watchpointMote, WatchpointListener listener) {
|
||||
this.mote = mote;
|
||||
this.watchpointMote = watchpointMote;
|
||||
this.watchpointListener = listener;
|
||||
|
@ -1110,18 +1111,22 @@ public class TimeLine extends VisPlugin {
|
|||
/* XXX Experimental: Watchpoints */
|
||||
if (mote instanceof WatchpointMote) {
|
||||
final WatchpointMote watchpointMote = ((WatchpointMote)mote);
|
||||
ActionListener listener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (watchpointMote.getLastWatchpoint() == null) {
|
||||
return;
|
||||
WatchpointListener listener = new WatchpointListener() {
|
||||
public void watchpointTriggered(Watchpoint watchpoint) {
|
||||
WatchpointEvent ev = new WatchpointEvent(simulation.getSimulationTime(), watchpoint);
|
||||
|
||||
if (executionDetails && mote instanceof AbstractEmulatedMote) {
|
||||
String details = ((AbstractEmulatedMote) mote).getExecutionDetails();
|
||||
if (details != null) {
|
||||
details = "<br>" + details.replace("\n", "<br>");
|
||||
ev.details = details;
|
||||
}
|
||||
}
|
||||
WatchpointEvent ev = new WatchpointEvent(
|
||||
simulation.getSimulationTime(),
|
||||
watchpointMote.getLastWatchpoint()
|
||||
);
|
||||
|
||||
moteEvents.addWatchpoint(ev);
|
||||
}
|
||||
public void watchpointsChanged() {
|
||||
}
|
||||
};
|
||||
|
||||
watchpointMote.addWatchpointListener(listener);
|
||||
|
@ -1417,7 +1422,7 @@ public class TimeLine extends VisPlugin {
|
|||
popupLocation = e.getPoint();
|
||||
showInAllAction.actionPerformed(null);
|
||||
|
||||
long time = (long) ((double)popupLocation.x*currentPixelDivisor);
|
||||
long time = (long) (popupLocation.x*currentPixelDivisor);
|
||||
Plugin[] plugins = simulation.getGUI().getStartedPlugins();
|
||||
for (Plugin p: plugins) {
|
||||
if (!(p instanceof TimeLine)) {
|
||||
|
@ -1524,7 +1529,34 @@ public class TimeLine extends VisPlugin {
|
|||
if (t.getTipText() == null || t.getTipText().equals("")) {
|
||||
return;
|
||||
}
|
||||
popUpToolTip = PopupFactory.getSharedInstance().getPopup(timeline, t, e.getXOnScreen(), e.getYOnScreen());
|
||||
t.validate();
|
||||
|
||||
/* Check tooltip width */
|
||||
Rectangle screenBounds = timeline.getGraphicsConfiguration().getBounds();
|
||||
int x;
|
||||
{
|
||||
int tooltip = e.getLocationOnScreen().x + t.getPreferredSize().width;
|
||||
int screen = screenBounds.x + screenBounds.width;
|
||||
if (tooltip > screen) {
|
||||
x = e.getLocationOnScreen().x - (tooltip-screen);
|
||||
} else {
|
||||
x = e.getLocationOnScreen().x;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check tooltip height */
|
||||
int y;
|
||||
{
|
||||
int tooltip = e.getLocationOnScreen().y + t.getPreferredSize().height;
|
||||
int screen = screenBounds.y + screenBounds.height;
|
||||
if (tooltip > screen) {
|
||||
y = e.getLocationOnScreen().y - (tooltip-screen);
|
||||
} else {
|
||||
y = e.getLocationOnScreen().y;
|
||||
}
|
||||
}
|
||||
|
||||
popUpToolTip = PopupFactory.getSharedInstance().getPopup(null, t, x, y);
|
||||
popUpToolTip.show();
|
||||
}
|
||||
}
|
||||
|
@ -1680,12 +1712,12 @@ public class TimeLine extends VisPlugin {
|
|||
while (time <= end) {
|
||||
if (time % (100*Simulation.MILLISECOND) == 0) {
|
||||
g.drawLine(
|
||||
(int) (time/currentPixelDivisor), (int)0,
|
||||
(int) (time/currentPixelDivisor), (int)TIME_MARKER_PIXEL_HEIGHT);
|
||||
(int) (time/currentPixelDivisor), 0,
|
||||
(int) (time/currentPixelDivisor), TIME_MARKER_PIXEL_HEIGHT);
|
||||
} else {
|
||||
g.drawLine(
|
||||
(int) (time/currentPixelDivisor), (int)0,
|
||||
(int) (time/currentPixelDivisor), (int)TIME_MARKER_PIXEL_HEIGHT/2);
|
||||
(int) (time/currentPixelDivisor), 0,
|
||||
(int) (time/currentPixelDivisor), TIME_MARKER_PIXEL_HEIGHT/2);
|
||||
}
|
||||
time += (10*Simulation.MILLISECOND);
|
||||
}
|
||||
|
@ -1693,8 +1725,8 @@ public class TimeLine extends VisPlugin {
|
|||
|
||||
private void drawMouseTime(Graphics g, long start, long end) {
|
||||
if (mousePixelPositionX >= 0) {
|
||||
long time = (long) ((double)mousePixelPositionX*currentPixelDivisor);
|
||||
long diff = (long) ((double)Math.abs(mouseDownPixelPositionX-mousePixelPositionX)*currentPixelDivisor);
|
||||
long time = (long) (mousePixelPositionX*currentPixelDivisor);
|
||||
long diff = (long) (Math.abs(mouseDownPixelPositionX-mousePixelPositionX)*currentPixelDivisor);
|
||||
String str =
|
||||
"Time (ms): " + (double)time/Simulation.MILLISECOND +
|
||||
" (" + (double)diff/Simulation.MILLISECOND + ")";
|
||||
|
@ -2333,7 +2365,7 @@ public class TimeLine extends VisPlugin {
|
|||
Rectangle visibleRectangle = timeline.getVisibleRect();
|
||||
boolean isTracking = visibleRectangle.x + visibleRectangle.width >= timeline.getWidth();
|
||||
|
||||
int newHeight = (int) (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size());
|
||||
int newHeight = (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size());
|
||||
timeline.setPreferredSize(new Dimension(
|
||||
newWidth,
|
||||
newHeight
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
* $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.util;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
import jsyntaxpane.SyntaxDocument;
|
||||
import jsyntaxpane.actions.DefaultSyntaxAction;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
|
||||
public class JSyntaxAddBreakpoint extends DefaultSyntaxAction {
|
||||
private static Logger logger = Logger.getLogger(JSyntaxAddBreakpoint.class);
|
||||
|
||||
public JSyntaxAddBreakpoint() {
|
||||
super("addbreakpoint");
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuItem menuItem = (JMenuItem) e.getSource();
|
||||
Action action = menuItem.getAction();
|
||||
WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote");
|
||||
if (watchpointMote == null) {
|
||||
logger.warn("Error: No source, cannot configure breakpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = (File) action.getValue("WatchpointFile");
|
||||
Integer line = (Integer) action.getValue("WatchpointLine");
|
||||
Integer address = (Integer) action.getValue("WatchpointAddress");
|
||||
if (file == null || line == null || address == null) {
|
||||
logger.warn("Error: Bad breakpoint info, cannot add breakpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
watchpointMote.addBreakpoint(file, line, address);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
* $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.util;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import jsyntaxpane.actions.DefaultSyntaxAction;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.Watchpoint;
|
||||
import se.sics.cooja.WatchpointMote;
|
||||
|
||||
public class JSyntaxRemoveBreakpoint extends DefaultSyntaxAction {
|
||||
private static Logger logger = Logger.getLogger(JSyntaxRemoveBreakpoint.class);
|
||||
|
||||
public JSyntaxRemoveBreakpoint() {
|
||||
super("removebreakpoint");
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuItem menuItem = (JMenuItem) e.getSource();
|
||||
Action action = menuItem.getAction();
|
||||
WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote");
|
||||
if (watchpointMote == null) {
|
||||
logger.warn("Error: No source, cannot configure breakpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = (File) action.getValue("WatchpointFile");
|
||||
Integer line = (Integer) action.getValue("WatchpointLine");
|
||||
Integer address = (Integer) action.getValue("WatchpointAddress");
|
||||
if (file == null || line == null || address == null) {
|
||||
logger.warn("Error: Bad breakpoint info, cannot remove breakpoint");
|
||||
return;
|
||||
}
|
||||
for (Watchpoint w: watchpointMote.getBreakpoints()) {
|
||||
if (file.equals(w.getCodeFile()) && line.equals(w.getLineNumber()) && address.equals(w.getExecutableAddress())) {
|
||||
watchpointMote.removeBreakpoint(w);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
4
tools/cooja/lib/JSYNTAXPANE_LICENSE
Normal file
4
tools/cooja/lib/JSYNTAXPANE_LICENSE
Normal file
|
@ -0,0 +1,4 @@
|
|||
Downloaded from http://code.google.com/p/jsyntaxpane/.
|
||||
|
||||
Apache License 2.0:
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
BIN
tools/cooja/lib/jsyntaxpane.jar
Normal file
BIN
tools/cooja/lib/jsyntaxpane.jar
Normal file
Binary file not shown.
Loading…
Reference in a new issue