CVS: examples/libraries/monitor README.txt, NONE, 1.1 doxy.cfg, NONE, 1.1 main.c, NONE, 1.1 makefile, NONE, 1.1

Chris Liechti <[email protected]> Mon, 24 Mar 2008 15:07:49 -0700
Newsgroups gmane.comp.hardware.texas-instruments.msp430.gcc.cvs
Message-ID <[email protected]>
Update of /cvsroot/mspgcc/examples/libraries/monitor
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv24586/monitor

Added Files:
	README.txt doxy.cfg main.c makefile 
Log Message:
adding the monitor example including documentation. it is an example featuring a serial console and can manipulate pins, ports and flash memory and some more.


--- NEW FILE: README.txt ---
=============================
 MSPGCC example mini monitor
=============================

Overview
========

Simple monitor for the msp430.

It can be used to test and explore new eval boards or prototypes and it
serves as example for the command line library that mspgcc provides.
It can alse serve as base for a debugging command line console for your
own projects.


Usage
=====

Download
--------
Download ``monitor.elf``. For example using the BSL::

    > msp430-bsl -c /dev/ttyUSB0 -e monitor.elf

or using the JTAG::

    > msp430-jtag -e monitor.elf

The ``makefile`` contains a ``download`` target that can be configured for
BSL or JTAG usage, see the ``makefile`` itself.


Terminal
--------
Then run a terminal program at 115200 baud connecting to the target.
Use what you're used to or alternatively try miniterm.py from
http://pyserial.sf.net, see CVS/examples there. Those that used a recent 
Windows installer already haev it installed as ``msp430-miniterm``.

So invoke a terminal program like::

    > msp430-miniterm COM3 115200
    > miniterm.py /dev/ttyUSB0 115200

The target prints a message after reset::

    Type "help" for a list of commands or help about specific commands.
    The tab key does command completion.
    Expressions; read ports "Px", "Px.y"  write: "Px=z", "Px.y=b"
    where z in 0...255 and b is "0" or "1"
    $

Then commands or expressions can be entered. E.g. setting all pins on port 5
to output a high (both lines do the same)::

    $ P5=255
    $ P5=0xff

Read P1.1 then set P1.2::

    $ P1.1
    0
    $ P1.2=1

Test the interrupt capabilities of port 1 pin 3:

    $ irq 1 3 neg
    # P1.3 interrupt
    $

Flash can be read and written::

    $ erase 0x1000
    Erasing segment at 0x1000
    $ write 0x1000 68656c6c6f20776f726421
    $ hexdump 0x1000 32
    1000   68 65 6c 6c 6f 20 77 6f  72 64 21 ff ff ff ff ff   hello word!.....
    1010   ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff   ................
    $


Hardware
========
The example compiles for a F149, 4MHz crystal at XT2 and the USART1 connected
to the host using RS232 level shifters or a USB<->serial interface chip.

Other setups are supported by editing the sources. Any MSP430 with a USART
a crystal and 16kB Flash should work. Using a watch crystal, ``fll_adjust``
from libmspgcc may need to be used. F2xx devices need adaptation of USART
initialization as well as differenet SMCLK speeds need other baudrate settings.
See http://mspgcc.sourceforge.net/baudrate.html for calculating these values.

Cuting out some code, such as the "write" command or the tab completion or the
"expression" code saves enough memory to fit the application in 8kB FLash
parts.


Implementation
==============
For hints see main.c. It is also possible to build the doxygen documentation
using::

    > make doxy

.. note:: The add on library headfiles are referenced using /opt/mspgcc/...
          these paths may need to be adapted for your own system. See
          ``doxy.cfg``.


---
2008-03  chris

--- NEW FILE: doxy.cfg ---
# Doxyfile 1.3.5

#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME           = "MSP430 monitor example"
#~ PROJECT_NUMBER         = 
OUTPUT_DIRECTORY       = doxy
OUTPUT_LANGUAGE        = English
BRIEF_MEMBER_DESC      = YES
REPEAT_BRIEF           = YES
ABBREVIATE_BRIEF       = 
ALWAYS_DETAILED_SEC    = NO
INLINE_INHERITED_MEMB  = NO
FULL_PATH_NAMES        = NO
STRIP_FROM_PATH        = 
SHORT_NAMES            = YES
JAVADOC_AUTOBRIEF      = YES
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP         = YES
INHERIT_DOCS           = YES
DISTRIBUTE_GROUP_DOC   = NO
TAB_SIZE               = 8
ALIASES                = 
OPTIMIZE_OUTPUT_FOR_C  = YES
OPTIMIZE_OUTPUT_JAVA   = NO
SUBGROUPING            = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL            = YES
EXTRACT_PRIVATE        = YES
EXTRACT_STATIC         = YES
EXTRACT_LOCAL_CLASSES  = YES
HIDE_UNDOC_MEMBERS     = NO
HIDE_UNDOC_CLASSES     = NO
HIDE_FRIEND_COMPOUNDS  = NO
HIDE_IN_BODY_DOCS      = NO
INTERNAL_DOCS          = NO
CASE_SENSE_NAMES       = YES
HIDE_SCOPE_NAMES       = NO
SHOW_INCLUDE_FILES     = YES
INLINE_INFO            = YES
SORT_MEMBER_DOCS       = YES
GENERATE_TODOLIST      = YES
GENERATE_TESTLIST      = YES
GENERATE_BUGLIST       = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS       = 
MAX_INITIALIZER_LINES  = 30
SHOW_USED_FILES        = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET                  = YES
WARNINGS               = YES
WARN_IF_UNDOCUMENTED   = YES
WARN_IF_DOC_ERROR      = YES
WARN_FORMAT            = "$file:$line: $text"
WARN_LOGFILE           = 
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT                  = main.c \
                         /opt/mspgcc/msp430/include/commandline.h \
                         /opt/mspgcc/msp430/include/mspgcc/eventhandler.h \
                         /opt/mspgcc/msp430/include/mspgcc/ringbuffer.h \
                         /opt/mspgcc/msp430/include/mspgcc/flash.h \
                         /opt/mspgcc/msp430/include/mspgcc/util.h
FILE_PATTERNS          = *.h \
                         *.c
RECURSIVE              = NO
EXCLUDE                = 
EXCLUDE_SYMLINKS       = NO
EXCLUDE_PATTERNS       = 
EXAMPLE_PATH           = 
EXAMPLE_PATTERNS       = 
EXAMPLE_RECURSIVE      = NO
IMAGE_PATH             = 
INPUT_FILTER           = 
FILTER_SOURCE_FILES    = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER         = YES
INLINE_SOURCES         = NO
STRIP_CODE_COMMENTS    = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION    = YES
VERBATIM_HEADERS       = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX     = YES
COLS_IN_ALPHA_INDEX    = 5
IGNORE_PREFIX          = 
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML          = YES
HTML_OUTPUT            = ./html-doc
HTML_FILE_EXTENSION    =
HTML_HEADER            =
HTML_FOOTER            =
HTML_STYLESHEET        =
HTML_ALIGN_MEMBERS     = YES
GENERATE_HTMLHELP      = NO
CHM_FILE               = 
HHC_LOCATION           = 
GENERATE_CHI           = NO
BINARY_TOC             = NO
TOC_EXPAND             = NO
DISABLE_INDEX          = NO
ENUM_VALUES_PER_LINE   = 4
GENERATE_TREEVIEW      = YES
TREEVIEW_WIDTH         = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX         = NO
LATEX_OUTPUT           = latex
LATEX_CMD_NAME         = pdflatex
MAKEINDEX_CMD_NAME     = makeindex
COMPACT_LATEX          = YES
PAPER_TYPE             = a4wide
EXTRA_PACKAGES         = 
LATEX_HEADER           = 
PDF_HYPERLINKS         = YES
USE_PDFLATEX           = YES
LATEX_BATCHMODE        = NO
LATEX_HIDE_INDICES     = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF           = NO
RTF_OUTPUT             = rtf
COMPACT_RTF            = NO
RTF_HYPERLINKS         = YES
RTF_STYLESHEET_FILE    = 
RTF_EXTENSIONS_FILE    = 
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN           = NO
MAN_OUTPUT             = 
MAN_EXTENSION          = 
MAN_LINKS              = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML           = NO
XML_OUTPUT             = 
XML_SCHEMA             = 
XML_DTD                = 
XML_PROGRAMLISTING     = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF   = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD       = NO
PERLMOD_LATEX          = NO
PERLMOD_PRETTY         = YES
PERLMOD_MAKEVAR_PREFIX = 
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor   
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING   = YES
MACRO_EXPANSION        = YES
EXPAND_ONLY_PREDEF     = YES
SEARCH_INCLUDES        = YES
INCLUDE_PATH           = 
INCLUDE_FILE_PATTERNS  = 
PREDEFINED             = __STDC__ \
                         DOXYGEN \
                         "interrupt(x)=void" \
                         "__attribute__(x)=" \
                         _PACKED_STRUCT_
EXPAND_AS_DEFINED      = 
SKIP_FUNCTION_MACROS   = NO
#---------------------------------------------------------------------------
# Configuration::addtions related to external references   
#---------------------------------------------------------------------------
TAGFILES               = 
GENERATE_TAGFILE       = 
ALLEXTERNALS           = NO
EXTERNAL_GROUPS        = YES
PERL_PATH              = 
#---------------------------------------------------------------------------
# Configuration options related to the dot tool   
#---------------------------------------------------------------------------
CLASS_DIAGRAMS         = YES
HIDE_UNDOC_RELATIONS   = NO
HAVE_DOT               = YES
CLASS_GRAPH            = YES
COLLABORATION_GRAPH    = YES
UML_LOOK               = YES
TEMPLATE_RELATIONS     = YES
INCLUDE_GRAPH          = YES
INCLUDED_BY_GRAPH      = YES
CALL_GRAPH             = YES
GRAPHICAL_HIERARCHY    = YES
DOT_IMAGE_FORMAT       = png
DOT_PATH               = 
DOTFILE_DIRS           = 
MAX_DOT_GRAPH_DEPTH    = 0
GENERATE_LEGEND        = YES
DOT_CLEANUP            = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine   
#---------------------------------------------------------------------------
SEARCHENGINE           = NO

--- NEW FILE: main.c ---
/**
 * @file
 *
 * Simple monitor for the msp430.
 *
 * It can be used to test and explore new eval boards or prototypes and it
 * serves as example for the command line library that mspgcc provides.
 * It can alse serve as base for a debugging command line console for your
 * own projects.
 *
 *
 * Hardware requirements:
 * - MSP430Fxxx with hardware USART
 * - Crystal
 *
 * The example uses USART1 and a 4MHZ crystal on XT2 though that can easily
 * addaped.
 *
 *
 * Software design:
 * - the event handler is used to distribute foreground computing time to
 *   different tasks.
 * - the ringbuffer is used to transfer data from the serial port interrupt
 *   to the foreground event
 *   <pre>
 *     +--------------------+    +------------+    +---------------------+
 *     | usart_rx_interrupt |--->| ringbuffer |--->| event_keys_received |
 *     +--------------------+    +------------+    +---------------------+
 *   </pre>
 * - mspgcc's libcommandline is used to implement a simple command line
 *   interface. It also provides most of the commands
 * - mspgcc's line editor of libmspgcc is used for the command line editing
 *   features
 *
 * Command line features:
 * - some kind of "expression" is parsed, this is used to modifiy ports/pins.
 *   e.g. "P1=255" sets all P1 pins to output and high.
 *   e.g. "P1" sets all P1 pins to input and returns the value read.
 *   e.g. "P1.1=1" sets only pin P1.1 to output and high.
 * - the "irq" command can be used to test the interrupt capabilities of P1
 *   and P2.
 * - The "adc" commands excersises ADC12.
 * - a machine interface mode switches off echo and formats the exit code
 *   for better machine readability.
 *   The machine mode is active for a single command each time.
 *
 * (C) 2008,  chris <[email protected]>
 */
#include <io.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include <mspgcc/util.h>
#include <mspgcc/ringbuffer.h>
#include <mspgcc/eventhandler.h>
#include <commandline.h>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// console prompts
#define  PROMPT                 "$ "    ///< Prompt printed when command line
                                        ///< is read for user inputs.

// prompts and control bytes for the machine interface
#define MACHINE_START           '\x1f'  ///< US, switches on machine mode for current command
#define MACHINE_EXITCODE        '\x1c'  ///< FS, command output is finished, exit code follows
#define MACHINE_END             '\x04'  ///< EOT, output of exit code finsihed, command is done

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// return status of commands
#define SUCCESS                 0       ///< everthing was ok
#define ERROR_PARAMETER         1       ///< unexpected/wrong parameter

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
volatile bool interrupted = false;      ///< set when ctrl+c is received
bool machine_interface = false;         ///< machine interface is active

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/**
 * Make an ADC12 measurement.
 */
unsigned short singleADC(unsigned short settings) {
    ADC12CTL0 = ADC12ON|SHT1_10;
    ADC12IE   = 0;
    ADC12CTL1 = CSTARTADD_15|CONSEQ_0|SHS_0|SHP;
    ADC12MCTL15 = settings;
    ADC12CTL0 |= ENC;

    ADC12CTL0 |= ADC12SC;               //start conversion
    while (ADC12CTL1 & ADC12BUSY) {}
    ADC12CTL0 &= ~ENC;

    return ADC12MEM15;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void event_keys_received(void); // fwd.

// Ring buffer for the received characters in the interrupt serRX and getchar
RINGBUFFER_NEW(ringbuffer, 40);

/**
 * Receive characters from the serial port, store then in ringbuffer and
 * start event for the processing in the foreground.
 */
wakeup interrupt (UART1RX_VECTOR) usart_rx_interrupt(void) {
    char character = U1RXBUF;
    if (character == 0x03) {                    // ETX ctrl+c
        interrupted = true;
    } else {
        // put new character in buffer (overflows ignored, these characters
        // are just dropped)
        ringbuffer_put(&ringbuffer, character);
        EVENTHANDLER_LAUNCH(eventhandler_find(event_keys_received));
    }
}

/**
 * Write character to the serial port. printf and other functions use this to
 * do the actual output.
 */
int putchar(int character) {
    while (!(UTCTL1 & TXEPT)) {}                // wait util tx buffer is free
    TXBUF1 = character;                         // send character
    return 1;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// allocate a buffer for the line editor
static char line_buffer[160];
// initialize line editor
static LINEEDITOR_STATE lineeditor = {
    line: line_buffer,
    line_size: sizeof(line_buffer),
    flags: {echo:1},
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// read the given ADC channel
#define HELP_adc \
"ADC measurement\n\n" \
"USAGE: %s channel\n\n" \
"Make an analog measurement on the given 'channel'."
static int command_adc(int argc, char *argv[]) {
    if (argc != 2) {
        puts(HELP_adc);
        return ERROR_PARAMETER;
    }
    unsigned char channel = commandline_number(argv[1]);
    unsigned short value;
    
    value = singleADC(channel);
    
    if (!machine_interface) {
        printf("Channel %d: %u mV (%u counts)\n", channel, (unsigned int)((3300UL*value)/4096), value);
    } else {
        printf("%u", value);
    }
    return SUCCESS;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

volatile unsigned char *PORT_IES[] = {0, &P1IES, &P2IES};
volatile unsigned char *PORT_IE[] = {0, &P1IE, &P2IE};

volatile unsigned char ifg[2];

/**
 * Get flags from the ifg global array, clear the value afterwards.
 * This function disables interupts to ensure that no interrupt sets
 * a bit while it is processed.
 */
critical unsigned get_ifg(unsigned port) {
    // must mask with enabled interrupts to get expected result
    unsigned result = ifg[port] & *PORT_IE[port+1];
    ifg[port] = 0;
    return result;
}

/**
 * Event handler that prints messages about occoured port interrupts.
 */
void event_port_interrupt(void) {
    for (unsigned port=0; port<2; port++) {
        unsigned value = get_ifg(port);
        for (unsigned bit=0; bit<8; bit++) {
            if (value & (1 << bit)) {
                printf("\n# P%d.%d interrupt", port+1, bit);
            }
        }
    }
    if (!machine_interface) {
        printf("\n%s%s", PROMPT, lineeditor.line);
    }
}

/**
 * Port 1 interrupt handler that copies interrupt flags to a global variable
 * and starts the ::event_port_interrupt.
 */
wakeup interrupt(PORT1_VECTOR) port1_interrupt(void) {
    ifg[0] |= P1IFG;
    EVENTHANDLER_LAUNCH(eventhandler_find(event_port_interrupt));
    P1IFG = 0;
}

/**
 * Port 2 interrupt handler that copies interrupt flags to a global variable
 * and starts the ::event_port_interrupt.
 */
wakeup interrupt(PORT2_VECTOR) port2_interrupt(void) {
    ifg[1] |= P2IFG;
    EVENTHANDLER_LAUNCH(eventhandler_find(event_port_interrupt));
    P2IFG = 0;
}

#define HELP_irq \
"enable pin interrupts\n\n" \
"USAGE: irq port pin pos|neg|off\n\n" \
"Enable port interrupt on pin, off disables interrupt."
static int command_irq(int argc, char *argv[]) {
    if (argc != 4) {
        puts(HELP_irq);
        return ERROR_PARAMETER;
    }
    unsigned port = commandline_number(argv[1]);
    unsigned pin = commandline_number(argv[2]);
    
    if (port < 1 || port > 2) {
        printf("ERROR: port number invalid\n");
        return ERROR_PARAMETER;
    }
    if (pin < 0 || pin > 7) {
        printf("ERROR: pin number invalid\n");
        return ERROR_PARAMETER;
    }
    
    int mask = 1 << pin;
    if (strcasecmp(argv[3], "pos") == 0) {
        *PORT_IES[port] &= ~mask;
        *PORT_IE[port] |= mask;
    } else if (strcasecmp(argv[3], "neg") == 0) {
        *PORT_IES[port] |= mask;
        *PORT_IE[port] |= mask;
    } else if (strcasecmp(argv[3], "off") == 0) {
        *PORT_IE[port] &= ~mask;
    } else {
        printf("ERROR: invalid operation\n");
        return ERROR_PARAMETER;
    }
    return SUCCESS;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

volatile unsigned char *PORT_DIR[] = {0, &P1DIR, &P2DIR, &P3DIR, &P4DIR, &P5DIR, &P6DIR};
volatile unsigned char *PORT_IN[] = {0, &P1IN, &P2IN, &P3IN, &P4IN, &P5IN, &P6IN};
volatile unsigned char *PORT_OUT[] = {0, &P1OUT, &P2OUT, &P3OUT, &P4OUT, &P5OUT, &P6OUT};

/**
 * Modify ports/pins by a string specification.
 * what we want to parse:
 * - "P1.2=0"         clear pin
 * - "P1.2=1"         set pin
 * - "P1.2"           read pin
 * - "P1=0x12"        set port
 * - "P1=255"         set port
 * - "P1"             read port
 */
static int expr_pin(const char *input) {
    
    if (input[0] == 'P' && input[1] != '\0') {
        // read the port
        unsigned port = input[1] - '0';
        if (port < 1 || port > 6) {
            printf("ERROR: port number invalid\n");
        }
        // pin access
        if (input[2] == '.' && input[3] != '\0') {
            unsigned pin = input[3] - '0';
            unsigned mask = 1 << pin;
            if (pin < 0 || pin > 7) {
                printf("ERROR: pin number invalid\n");
            }
            // read or write
            if (input[4] == '\0') {
                // read
                *PORT_DIR[port] &= ~mask;
                printf("%s=%c\n", input, (*PORT_IN[port] & mask) ? '1' : '0');
                return SUCCESS;
            } else if (input[4] == '=') {
                //write
                if (input[5] == '1') {
                    *PORT_DIR[port] |= mask;
                    *PORT_OUT[port] |= mask;
                } else if (input[5] == '0') {
                    *PORT_DIR[port] |= mask;
                    *PORT_OUT[port] &= ~mask;
                } else {
                    printf("ERROR: invalid assignment\n");
                }
                return SUCCESS;
            } else {
                printf("ERROR: invalid port spec\n");
            }
            return SUCCESS;
        } else if (input[2] == '\0') {
            *PORT_DIR[port] = 0;
            printf("0x%02x\n", *PORT_IN[port]);
            return SUCCESS;
        } else if (input[2] == '=') {
            // port assignment
            unsigned char value = commandline_number(&input[3]);
            *PORT_DIR[port] = 0xff;
            *PORT_OUT[port] = value;
            return SUCCESS;
        } else {
            printf("ERROR: unknown operation\n");
            return ERROR_PARAMETER;
        }
    } else {
        //~ printf("ERROR: port spec not matching");
        return ERROR_PARAMETER;
    }
}

/**
 * Parse and eval expressions.
 */
int expression_eval(char *commandline) {
    // currently only one type of expression
    return expr_pin(commandline);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/**
 * Register the commands. The table name must be the one it is, so that
 * "help" works.
 */
const COMMANDLINE_TABLE commandline_table[] = {
    COMMANDLINE_ENTRY(adc,              HELP_adc),
    COMMANDLINE_ENTRY(checksum,         HELP_checksum), //privided by library
    COMMANDLINE_ENTRY(erase,            HELP_erase),    //privided by library
    COMMANDLINE_ENTRY(help,             HELP_help),     //privided by library
    COMMANDLINE_ENTRY(irq,              HELP_irq),
    COMMANDLINE_ENTRY(hexdump,          HELP_hexdump),  //privided by library
    COMMANDLINE_ENTRY(reset,            HELP_reset),    //privided by library
    COMMANDLINE_ENTRY(write,            HELP_write),    //privided by library
    {0} // sentinel, marks the end of the table
};


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/**
 * This event is run when one or more characters are in the receive buffer.
 * The line editor is used to process the caracters (unless it is a tab
 * character, then ::commandline_tabcomplete is called) and when a line is
 * complete, run the ::commandline_eval function. Finally prin the exit code
 * of the command and the prompt again.
 */
static void event_keys_received(void) {
    // process characters from the receive buffer
    while (ringbuffer_len(&ringbuffer)) {
        // proccess them in the line editor
        int character = ringbuffer_get(&ringbuffer);
        if (character == MACHINE_START) {
            machine_interface = true;
            lineeditor.flags.echo = false;
            continue;
        }
        // use the tab character to to command completition and show a list
        // of available commands
        if (character == '\t') {
            commandline_tabcomplete(
                commandline_table,
                &lineeditor,
                PROMPT
            );
        } else if (lineeditor_simple_process_key(&lineeditor, character)) {
            interrupted = false;
            int retval;
            // found a newline -> process the line
            // 1st try to evaluate it as expression
            retval = expression_eval(line_buffer);
            // then fall back to our command line interpreter
            if (retval != 0) retval = commandline_eval(line_buffer, commandline_table);
            if (machine_interface) {
                machine_interface = false;
                // reset line buffer, start with a fresh line
                LINEEDITOR_RESET(&lineeditor);
                lineeditor.flags.echo = true;
                // show prompt
                printf("%c%d%c", MACHINE_EXITCODE, retval, MACHINE_END);
            } else {
                if (retval == COMMANDLINE_NO_SUCH_COMMNAD) {
                    printf("Unknown command \"%s\". Try \"help\".\n", line_buffer);
                } else if (retval) { //if command failed
                    printf("-- errorcode: %d\n", retval);
                } // no output for successful commands
                // reset line buffer, start with a fresh line
                LINEEDITOR_RESET(&lineeditor);
                // show prompt
                printf(PROMPT);
            }
        }
    }
}

/**
 * Table with the event handlers
 */
const EVENTHANDLER_TABLE eventhandler_table[] = {
    event_port_interrupt,
    event_keys_received,
    0 // sentinel, marks end of list
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/** table of baudrates */
static const struct {
    unsigned char UBR0;
    unsigned char UBR1;
    unsigned char UMCTL;
} baudrates[] = {
    //~ { UBR0:0x04, UBR1:0x00, UMCTL:0x92 }, /* UART 2000000Hz 454545bps */
    { UBR0:0x08, UBR1:0x00, UMCTL:0x5B }, /* UART 2000000Hz 229885bps */
    { UBR0:0x11, UBR1:0x00, UMCTL:0x52 }, /* UART 2000000Hz 114942bps */
    { UBR0:0x68, UBR1:0x00, UMCTL:0x04 }, /* UART 2000000Hz 19212bps */
    { UBR0:0xD0, UBR1:0x00, UMCTL:0x11 }, /* UART 2000000Hz 9601bps */
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


/**
 * Main program that initializes hardware and runs the event handler loop.
 */
int main(void) {
    WDTCTL = WDTPW|WDTHOLD;             // Init watchdog timer (WDTPW|WDTTMSEL|WDTCNTCL|WDTSSEL|WDTIS_2)
    
    IE1 = 0;    //WDTIE
    IE2 = 0;
    ME1 = 0;
    ME2 = 0;
    
    // Clock system initialization
    BCSCTL1 = 0;                        // select LF oszi, Enable XT2
    // Wait for crystal
    do {
        IFG1 &= ~OFIFG;
        delay(255);                     // Time for flag to set
    } while (IFG1 & OFIFG);
    BCSCTL2 = SELM_XT2CLK|SELS|DIVS_DIV4;  // Select XT2CLK for MCLK & SMCLK/4
    BCSCTL1 |= DIVA_DIV4;                  // ACLK/4
    
    // Init of USART1 Module x, 8, N, 1
    P3SEL |= BIT6|BIT7;                 // select pin function for USART
    U1CTL = CHAR|SWRST;                 // init & reset
    U1CTL &= ~SWRST;                    // release reset
    U1TCTL = SSEL_SMCLK | TXEPT;
    U1RCTL = 0;
    
    unsigned char baudselect = 1;
    UBR01 = baudrates[baudselect].UBR0;
    UBR11 = baudrates[baudselect].UBR1;
    UMCTL1 = baudrates[baudselect].UMCTL;
    
    IE2 |= URXIE1;                      // Enable USART1 receive interrupts (UART mode)
    ME2 |= UTXE1 | URXE1;               // Enable USART1 transmitter and receiver (UART mode)

    delay(10000);
    // show prompt for a first time
    printf("\n"
           "MSPGCC example mini monitor\n"
           "\n"
           "Type \"help\" for a list of commands or help about specific commands.\n"
           "The tab key does command completion.\n"
           "Expressions; read ports \"Px\", \"Px.y\"  write: \"Px=z\", \"Px.y=b\"\n"
           "where z in 0...255 and b is \"0\" or \"1\"\n"
           "\n"
           PROMPT
    );
    // enable interrupts and run the event handler, which will not return
    eint();
    eventhandler(0);
}

--- NEW FILE: makefile ---
# makfile configuration
NAME            = monitor
CSOURCES        = main.c
ASOURCES        = 
CPU             = msp430x149
#~ CPU             = msp430x169
#~ CPU             = msp430x135
#~ CPU             = msp430x123


ASFLAGS         = -mmcu=${CPU} -D_GNU_ASSEMBLER_ -I .
CFLAGS          = -mmcu=${CPU} -O2 -Wall -g --std=gnu99 -I .
LDFLAGS         = -L . -lcommandline -lmspgcc -lspi

ifdef WINDIR
BSLOPT = -c COM3
else
BSLOPT = -c /dev/ttyUSB0
endif

# switch the compiler (for the internal make rules)
CC              = msp430-gcc
AS              = msp430-gcc

OBJECTS         = ${CSOURCES:.c=.o} ${ASOURCES:.S=.o}

.PHONY: all FORCE clean download download-jtag download-bsl dist

# all should be the first target. it's built when make is run without args
all: ${NAME}.elf ${NAME}.a43 ${NAME}.lst dependencies.d

# confgigure the next line for the download method you want to use
#~ download: download-jtag
download: download-bsl

#additional rules for files
${NAME}.elf: ${OBJECTS}
	${CC} -mmcu=${CPU} -o $@ ${OBJECTS} $(LDFLAGS)

${NAME}.a43: ${NAME}.elf
	msp430-objcopy -O ihex $^ $@

${NAME}.lst: ${NAME}.elf
	msp430-objdump -dSt $^ >$@
	@echo "----- RAM/Flash Usage -----"
	msp430-size $^

download-jtag: all
	msp430-jtag -e ${NAME}.elf

download-bsl: all
	msp430-bsl $(BSLOPT) -e ${NAME}.elf

clean:
	rm -f ${NAME}.elf ${NAME}.a43 ${NAME}.lst ${OBJECTS} dependencies.d

# doxygen documentation
doxy: FORCE doxy.cfg
	doxygen -d Preprocessor doxy.cfg >doxy.log

# backup archive
dist:
	tar czf dist.tgz *.c *.h *.txt makefile

# dummy target as dependecy if something has to be build everytime
FORCE:

# project dependencies
dependencies.d:
	$(CC) -MM ${CFLAGS} ${CSOURCES} > dependencies.d
ifdef ASOURCES
	$(CC) -MM ${ASFLAGS} ${ASOURCES} >> dependencies.d
endif

-include dependencies.d

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/