MSP430 USB Stick Development Tool Program #2

(If you find this page, you can use this Software. I'd appreciate it if you let me know.)

Back to MSP430 USB Stick Development Tool Page

Morse Code Thermometer is a program that builds on the Blinking Thermometer. Instead of blipping the light to represent the temperature it blinks the light in Morse Code to represent the temperature. More interesting, when the light looks to be on it is actually switched on-off at about 500 Hz. So, with a modification to the Development Stick that brings a wire out from the first discrete output pin, you can actually have audio. In my setup I used two resistors (1k & 330) to voltage divide the discrete output and feed the resultant signal into my computers AUX audio input. A filter cap might help, but the tone sounds pretty good to me.

I've also used this signal into a VOX controlled radio transmitter. It turns out to be a slick way to transmit temperature to a remote location. An FRS radio can be used but I don't think the FCC allows anything but voice in the U.S. Ham Radio usage requires a license.

Since I haven't looked into using the PWM output, I am generating the tone by switching the output under software control using a timer interrupt of about 1 msec. The dot and dash timing is further divided down using a software counter in the HS interrupt service routine.


There are a few constants that might be interesting to play with.

The ADCSlope is 34 meaning that the ADC puts out a count that changes by 34 when the temperature changes by 1 Degree F. I determined this constant based on the value from the TI authors. The TI authors said 31 was approximately 0.5 degrees C. I'm sure if you looked at how the ADC is setup you could derive this value.

The ADCOffset was determined by knowing the temp, setting a breakpoint, and seeing what the value that was returned in LastADCVal. Your device might have a different offset.

RestartDelay determines how many LS interrupt service calls are performed before starting the whole thing over. The speed of the LS interrupt service is determined by CodeSpeed.

Text specifies the text sent. '??' is used to indicate the location within the text stream to insert the temperature.

//******************************************************************************
//  MSP430F20x3 Demo - SD16, Using the Integrated Temperature Sensor
//
//  Description: Use SD16 and it's integrated temperature sensor to detect
//  temperature.  Blink LED to represent temp.
//
// By B. L. Wiscons May 2007 based on example by
//  M. Buccini / L. Westlund
//  Texas Instruments Inc.
//  October 2005
//  Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include  <msp430x20x3.h>
#include  <string.h>
//#include 

#define ADCDeltaOn 31                       // ~0.5 Deg C delta
#define DigitLength 3                       // LED on/off time
#define CodeSpeed 600                       // number of HS interrupt service's
                                            // before a LS service. A LS service
                                            // corresponds to one 'dit' time.
                                            // 400 ends up with a code speed
                                            // of about 10 WPM
#define RestartDelay 100                    // number of LS interrupt service's
                                            //   before restarting the whole 
                                            //   thing over
static unsigned int LastADCVal;             // holds ADC temperature result
static unsigned int tempcp;                 // cp to inset temperature result
static unsigned int intcnt,nextcase;        // interupt counter
static unsigned int HSintcnt;               // interupt counter
static char P1OUTi,cp;
static unsigned int code;
char text[20]="TEMP IS ?? DEG F";


//Place the Morse codes into constant memory
//  A Morse code consists of one word allowing up to 8 dots and/or dashes
//  a dot/dash occupies two bits 11 indicates a dash 01 is a dot
//  00 indicates no-more-dot/dash
/*
0	-----	1111,1111,1100,0000	FFC0
1	.----	0111,1111,1100,0000	7FC0
2	..---	0101,1111,1100,0000	5FC0
3	...--	0101,0111,1100,0000	57C0
4	....-	0101,0101,1100,0000	55C0
5	.....	0101,0101,0100,0000	5540
6	-....	1101,0101,0100,0000	D540
7	--...	1111,0101,0100,0000	F540
8	---..	1111,1101,0100,0000	FD40
9	----.	1111,1111,0100,0000	FF40
*/
const unsigned int MorseDigit[10] = {0xFFC0,0x7FC0,0x5FC0,0x57C0,0x55C0,
                                0x5540,0xD540,0xF540,0xFD40,0xFF40};
/*
A	.-	0111,0000,0000,0000	7000
B	-...	1101,0101,0000,0000	D500
C	-.-.	1101,1101,0000,0000	DD00
D	-..	1101,0100,0000,0000	D400
E	.	0100,0000,0000,0000	4000
F	..-.	0101,1101,0000,0000	5D00
G	--.	1111,0100,0000,0000	F400
H	....	0101,0101,0000,0000	5500
I	..	0101,0000,0000,0000	5000
J	.---	0111,1111,0000,0000	7F00
K	-.-	1101,1100,0000,0000	DC00
L	..-.	0101,1101,0000,0000	5D00
M	--	1111,0000,0000,0000	F000
N	-.	1101,0000,0000,0000	D000
O	---	1111,1100,0000,0000	FC00
P	.--.	0111,1101,0000,0000	7D00
Q	--.-	1111,0111,0000,0000	F700
R	.-.	0111,0100,0000,0000	7400
S	...	0101,0100,0000,0000	5400
T	-	1100,0000,0000,0000	C000
U	..-	0101,1100,0000,0000	5C00
V	...-	0101,0111,0000,0000	5700
W	.--	0111,1100,0000,0000	7C00
X	-..-	1101,0111,0000,0000	D700
Y	-.--	1101,1111,0000,0000	DF00
Z	--..	1111,0101,0000,0000	F500
*/
const unsigned int MorseLetter[26] = {0x7000,0XD500,0XDD00,0XD400,0X4000,
                                0X5D00,0XF400,0X5500,0X5000,0X7F00,
                                0XDC00,0X5D00,0XF000,0XD000,0XFC00,
                                0X7D00,0XF700,0X7400,0X5400,0XC000,
                                0X5C00,0X5700,0X7C00,0XD700,0XDF00,
                                0XF500};
const unsigned int MorseUnkown = 0x7770;
void main(void)
{
//strcpy(text,"TEMP IS ?? DEG F");
tempcp=strcspn(text,"?");
if (tempcp > (strlen(text)-2))
  return;
BCSCTL2 |= DIVS_2;                        // SMCLK/4
WDTCTL = WDTPW | WDTTMSEL| 3; // Puts in interval time mode
IE1 |= WDTIE;                             // Enable WDT interrupt
P1DIR |= 0x03;                            // P1.0 to output direction
SD16CTL = SD16REFON +SD16SSEL_1;          // 1.2V ref, SMCLK
SD16INCTL0 = SD16INCH_6;                  // A6+/-
SD16CCTL0 = SD16SNGL + SD16IE ;           // Single conv, interrupt
//printf("Ready\n"); 
_BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 with interrupt
}

#pragma vector=SD16_VECTOR
__interrupt void SD16ISR(void)
{
LastADCVal = SD16MEM0;                    // Store value
}

// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
int t,t1;          
if (P1OUTi)
  P1OUT ^= 0x01;                        // toggle LED
else P1OUT &= ~0x01;                    // LED off
P1OUT ^= 0x02;                          // toggle 2nd LED
HSintcnt++;
if (HSintcnt>=CodeSpeed)
  {
  if (nextcase)
    {
    intcnt=nextcase;
    nextcase=0;
    }
  else 
    intcnt++;
  HSintcnt=0;
  }
else return;
switch (intcnt)
  {
  case 1:
    {
    P1OUTi |= 0x01;                          // LED on  
    SD16CCTL0 |= SD16SC;                      // Start SD16 conversion
    break;
    }
  case 2:
  case 3:
  case 4:
  case 5:
  case 6:
    {
    P1OUTi ^= 0x01;                          // LED toggle  
    break;
    }

  case 7:
    {
    t=(LastADCVal-51636)/34;
    t1=t/10;
    text[tempcp]='0'+t1;
    t1=t-t1*10;
    text[tempcp+1]='0'+t1;
    cp=0;
    code=0;
    break;
    }
  case 16:
    {
    if (text[cp]==0)
      {
      nextcase=40;
      break;
      }
    else 
      if (text[cp]==' ')
      {
//        nextcase=17;
        code=0;
      }
      else 
        if (text[cp]>='0' & text[cp]<='9')
          code = MorseDigit[text[cp]-'0'];
        else if (text[cp]>='A' & text[cp]<='Z')
          code = MorseLetter[text[cp]-'A'];
        else code= MorseUnkown; 
    cp++;
    break;
    }
  case 17:
    {
    if (code&0xC000)
      {
      P1OUTi=1;
      code=(code&0x3FFF)| ((code-0x4000)&0xC000);
      if (code&0xC000)
        nextcase=17;
      };
    
    break;
    }
  case 18:  
    {
    P1OUTi &= ~0x01;                         // LED off
    code=code<<2;
    if (code&0xC000)
      nextcase=17;
    break;
    }
  case 22:
    {
    nextcase=16;
    break;
    }
  case 25:  
    {
    P1OUTi &= ~0x01;                         // LED off
    nextcase=22;
    break;
    }
  case 40+RestartDelay:
    {
    SD16CCTL0 |= SD16SC;                      // Start SD16 conversion
    break;
    }
  case 50+RestartDelay:
    {
    nextcase=7;                            // back to beginning
    break;
    }

  };     //end of switch  
}       //end of interupt routine