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++); }
}