All pastes #2113130 Raw Edit

Mine

public text v1 · immutable
#2113130 ·published 2012-02-08 17:50 UTC
rendered paste body
/**
 * main.cpp - swserial/timerserial/usciserial Serial Asynch test driver.
 *
 * To test: use putty and connect to /dev/ttyACM0 at 9600 Baud
 *
 */

#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

//#define MCLK_FREQ 2088200UL // NON-MODULATED DCO rate that is 9600 friendly
//#define MCLK_FREQ 1055000L
//#define MCLK_FREQ  7372800UL
//#define MCLK_FREQ 8000000UL
//#define MCLK_FREQ 10000000UL
#define MCLK_FREQ 12182400UL // NON-MODULATED DCO rate that is 9600 friendly
//#define MCLK_FREQ 18432000UL
//#define MCLK_FREQ 24000000UL

/**
 *+----------------------------------------------------------------------
 * forward declarations
 *+----------------------------------------------------------------------
 */
static void initMCLK();

/**
 * typedef Serial - start of a simple serial wrapper class
 */

template<uint32_t BAUD = 9600, uint32_t MCLK = MCLK_FREQ>
struct Serial_t {
    static const uint8_t BITRATE_L = (MCLK / BAUD) & 0xff;
    static const uint8_t BITRATE_H = (MCLK / BAUD) >> 8;
    static const uint8_t rxPinMask = 1 << 1; // rxPin P1.1
    static const uint8_t txPinMask = 1 << 2; // txPin P1.2 Launchpad friendly

#if defined(__MSP430FR5739__)
#define IS_UCRXIFG_SET (UCA0IFG & UCRXIFG)
#define IS_UCTXIFG_SET (UCA0IFG & UCTXIFG)
#else
#define IS_UCRXIFG_SET (UC0IFG & UCA0RXIFG)
#define IS_UCTXIFG_SET (UC0IFG & UCA0TXIFG)
#endif

    /**
     * begin() - initialize serial port, sets registers, port direction, and
     *   alternative port features as required by implementing serial routines.
     *   Depending on the implementing method, you may not be able to use
     *   arbitrary RX/TX pins. The software only implementation is the
     *   implemenation capable of using any arbitrary pin on PORT1.
     *
     * baudRate - bits/sec  default: 9600
     * rxPin - receive pin  default: 1 (P1.1) ( g2553 defaults )
     * txPin - transmit pin default: 2 (P1.2)
     *
     * TODO: allow for any PORTX to be used, only works with PORT1
     */
    void begin(void) {
        // Use UART defaults for most things.
        // LSB
        // 8-N-1 ( 8 bit, NO parity, 1 Stop bit)

#ifdef __MSP430FR5739__
        P2SEL1 |= BIT0 + BIT1; // P2.0=RXD, P2.1=TXD
        P2SEL0 &= ~(BIT0 + BIT1);
#else
        P1SEL  |= rxPinMask | txPinMask; // P1.1=RXD, P1.2=TXD
        P1SEL2 |= rxPinMask | txPinMask; // P1.1=RXD, P1.2=TXD
#endif

        UCA0CTL1 |= UCSWRST; // software reset the USCI
        UCA0CTL1 |= UCSSEL_2; // use SMCLK as the clock
        UCA0BR0 = BITRATE_L; // low byte of bit duration is MCLK/BAUD & 0xFF
        UCA0BR1 = BITRATE_H; // high byte of bit durration (MCLK/BAUD)/256
        UCA0CTL1 &= ~UCSWRST; // initialize USCI state machine

        __delay_cycles(MCLK_FREQ / 64 > 128000 ? MCLK_FREQ / 128 : MCLK_FREQ / 64); // slight delay
    }

    /**
     * puts() - write string s to the serial output stream without a trailing
     *    newline character.
     *
     *    NOTE: This differs from the ISO standard puts() function which
     *    normally appends a newline character.
     */
    void inline puts(register const char *s) {
        while (*s) {
            putchar(*s++);
        }
    }

};

/**
 * int getchar() - blocking byte read from serial port
 */
int getchar(void) {
    // sit and spin waiting for baudot heh I make myself laugh

    while (!(IS_UCRXIFG_SET)) {
        ; // busywait until USCI_A0 RX buffer is ready
    }

    return UCA0RXBUF; // return RXed character
}

/**
 * int getchar() - xmit char to serial port
 */
int putchar(int c) {

    // make sure previous character has been sent
    // before trying to send another character
    while (!(IS_UCTXIFG_SET)) {
        ; // busywait until USCIA0TX buffer is ready
    }

    UCA0TXBUF = (uint8_t) c; // TX character

    return 0;
}

static Serial_t<9600> Serial;

/**
 * itoa() - simple integer to ascii converter
 *
 */
static const char* itoa(uint16_t val, uint8_t base=10) {
    static char buf[32] = { 0 };
    int i = sizeof(buf)-2;

    for (; val && i; --i, val /= base) {
        buf[i] = "0123456789abcdef"[val % base];
    }

    return &buf[i + 1];
}

int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // Disable watchdog

    initMCLK(); // setup MCLK based on MCLK_FREQ

    Serial.begin(); // configure serial device

    if (0) {
        uint8_t *l = (uint8_t *) 0x0056;
        uint8_t *h = (uint8_t *) 0x0057;

        Serial.puts("\r\n");
        Serial.puts("BCSCTL1=0x"); Serial.puts(itoa(*h,16));
        Serial.puts(" DCOCTL=0x"); Serial.puts(itoa(*l,16));
        Serial.puts("\r\nWelcome to msp430 serial toolbox\r\nlogin: ");
    }

    register int c;
    register int nCharCnt = 0;

    for (;;) {
        c = getchar();

        // do some minimum line control to handle backspace
        if (c != 127) {
            putchar(c);
            nCharCnt++;
        } else {
            if (nCharCnt > 0) {
                putchar(c);
                --nCharCnt;
            }
        }

        // append newline on CR
        if (c == '\r') {
            Serial.puts("\n# ");
            nCharCnt = 0;
        }

        // restart processor if user presses CTR12182400L-D
        if (c == 0x04 /*CTRL-D*/) {
            // setting the WDTCTL without a password resets the 430
            WDTCTL = WDTHOLD;
        }
    }

    return 0;
}

/**
 * initMCLK() - initialize system MCLK_FREQ
 */
static void initMCLK() {
#ifdef __MSP430_HAS_BC2__

    P1SEL |= BIT4;
    P1DIR |= BIT4;
    { volatile uint16_t n; for(n=0; n < 0xffff; n++); }

#if MCLK_FREQ == 18432000UL
    // Use 16MHz DCO factory calibration and bump it up
    DCOCTL = 0;
    BCSCTL1 = CALBC1_16MHZ;
    DCOCTL = CALDCO_16MHZ;
    DCOCTL += 56;
#elif MCLK_FREQ == 16000000UL
    // Use 16MHz DCO factory calibration
    DCOCTL = 0;
    BCSCTL1 = CALBC1_16MHZ;
    DCOCTL = CALDCO_16MHZ;
    DCOCTL += 8;
#elif MCLK_FREQ == 12000000UL
    // Use 12MHz DCO factory calibration
    DCOCTL = 0;
    BCSCTL1 = CALBC1_12MHZ;
    DCOCTL = CALDCO_12MHZ;
#elif MCLK_FREQ == 12182400UL
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 1 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#elif MCLK_FREQ == 10000000UL
    // Use 1MHz DCO factory calibration

#if 0
    // 10.6180 MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 12.298 MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 0 << 6 | 1 << 5);
#endif
#if 0
    // 11.4100 MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 8.73200 MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 8.73200 MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 615.340kHz
    DCOCTL = 0;12182400
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 654.800kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 1 << 5);
#endif
#if 0
    // 699.580kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 1 << 6 | 0 << 5);
#endif
#if 0
    // 750.500Hz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 164.00kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 0 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 286.700kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 0 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 313.116kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 545.125kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 1 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 1.2245MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 0 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 1.301MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 0 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 1 << 5);
#endif
#if 0
    // 1.3875MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 0 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 1 << 6 | 0 << 5);
#endif
#if 0
    // 2.088MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 0 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 8.73MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // 9.295MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 1 << 5);
#endif
#if 1
    // ~12.1824MHz12182400
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1  | 0 << 1) ;
    DCOCTL = (0 << 7 | 1 << 6 | 0 << 5);
#endif
#if 0
    // 10.61MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 11.4MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // ~4.45MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // ~5.0MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (0 << 7 | 1 << 6 | 0 << 5);
#endif
#if 0
    // ~7.375MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 0 << 1 | 0 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // ~98.4kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | ( 0 << 3 | 0 << 2 | 0 << 1) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // ~172.4kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | ( 0 << 3 | 0 << 2 | 0 << 1) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // ~164.0kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | ( 0 << 3 | 0 << 2 | 1 << 1) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
#if 0
    // ~286.722kHz - ~286.874kHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | ( 0 << 3 | 0 << 2 | 1 << 1) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // 14.36MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
#endif
#if 0
    // ~12.1824MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1  | 1 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
#endif
    { volatile uint16_t n; for(n=0; n < 0xffff; n++); }
#elif MCLK_FREQ == 8000000UL
    // Use 8MHz DCO factory calibration
    DCOCTL = 0;
    BCSCTL1 = CALBC1_8MHZ;
    DCOCTL = CALDCO_8MHZ;
    DCOCTL += 6;
#elif MCLK_FREQ == 7372800UL
    // Use 8MHz DCO factory calibration
#if 0
    DCOCTL = 0;
    BCSCTL1 = CALBC1_8MHZ;
    DCOCTL = CALDCO_8MHZ;
    DCOCTL -= 29;    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1  | 1 << 0) ;
    DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);

#else
    DCOCTL = 0;
    BCSCTL1 = CALBC1_8MHZ;
    BCSCTL1--;
    DCOCTL = CALDCO_8MHZ;
    DCOCTL += 95;
#endif
#elif MCLK_FREQ == 1000000UL
    // Use 1MHz DCO factory calibration
    DCOCTL = 0;
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;
    DCOCTL -= 2;
#else
    // Use 1.024MHz DCO default frequency
    // Do nothing! Use the default ...
#endif
#elif defined(__MSP430_HAS_UCS__) || defined(__MSP430_HAS_CS__)
    PJSEL0 |= BIT0;
    PJSEL1 &= ~BIT0;
    PJDIR |= BIT0;
#if MCLK_FREQ == 8000000UL
    // Use 8MHz DCO factory calibration
    CSCTL0_H = 0xA5;// CS_KEY
    CSCTL1 |= DCOFSEL0 | DCOFSEL1;// Set max. DCO setting
    CSCTL2 = SELA_3 | SELS_3 | SELM_3;// set ACLK = MCLK = DCO
    CSCTL3 = DIVA_0 | DIVS_0 | DIVM_0;// set all dividers
    CSCTL0_H = 0x01;// Lock Register
#elif MCLK_FREQ == 24000000UL
    CSCTL0_H = 0xA5; // CS_KEY
    CSCTL1 |= DCORSEL | DCOFSEL0 | DCOFSEL1;// Set max. DCO setting
    CSCTL2 = SELA_3 + SELS_3 + SELM_3;// set ACLK = MCLK = DCO
    CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0;// set all dividers
    CSCTL0_H = 0x01;// Lock Register
#else
#warning "Warning: you probably want to initialize the MCLK!"
#endif
#else
#warning "Warning: you probably want to initialize the MCLK!"
#endif

#if 0
    // ~19.72MHz
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (1 << 3 | 1 << 2 | 1 << 1  | 1 << 0) ;
    DCOCTL = (1 << 7 | 1 << 6 | 1 << 5);
    // ~1.224, 1.30, 1.387, 1.487,   - 2.088
    DCOCTL = 0;
    BCSCTL1 = XT2OFF | (0 << 3 | 0 << 2 | 0 << 1  | 0 << 0) ;
    DCOCTL = 0x000;
    //BCSCTL1 = XT2OFF | (1 << 3 | 0 << 2 | 0 << 1  | 0 << 0) ;
    //DCOCTL = (0 << 7 | 0 << 6 | 0 << 5);
    //DCOCTL=0x000; // b = 0b00000000 ~1.224MHz
    //DCOCTL=0x020; // b = 0b00100000 ~1.301MHz
    //DCOCTL=0x040; // b = 0b01000000 ~1.387MHz
    //DCOCTL=0x060; // b = 0b01100000 ~1.487MHz
    //DCOCTL=0x080; // b = 0b10000000 ~1.602MHz
    //DCOCTL=0x0a0; // b = 0b10100000 ~1.735MHz
    //DCOCTL=0x0c0; // b = 0b11000000 ~1.894MHz
    //DCOCTL=0x0e0; // b = 0b11100000 ~2.088MHz
#endif

    { volatile uint16_t n; for(n=0; n < 0xffff; n++); }

}