Part Number: MSP430G2553
Tool/software: Code Composer Studio
Hello,
I am trying to find a starting point and code to help finish my project. My project is for the Zigbee to send multiple JSSON strings to the MSP430 microcontroller. These strings are sequences for the LEDs that need to be recorded on a table or struct in the microcontroller. I have TI demo code for the light show, but runs a uart buffer.
#include <msp430.h>
#include <stdint.h>
/*
* main.c
*/
//#define DEMO_MODE
#define LEDDIR P2DIR
#define LEDOUT P2OUT
#define RED BIT0
#define GREEN BIT1
#define BLUE BIT2
#define ALL_LEDS (RED | GREEN | BLUE)
#define P1UNUSED (BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
#define P2UNUSED (BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
#define MAXLEVEL 256 // For color muxing
#define MAXINTENSITY 100 // For overall brightness
#define MAX_COMMAND_LENGTH 15
// 100Hz LED Refresh Rate at 8MHz, = 80000 clocks per Complete LED Cycle
// 50 brightness levels for each LED cycle = 1600 clocks for each intensity step
// 200 clocks between steps = 8 levels of color for each, R, G, B = 3 bits color for each = 9 bit color resolution
// 25us timer interrupt
// Function Prototypes
void ledOff();
void ledSet(uint8_t r, uint8_t g, uint8_t b, uint8_t bright);
void ledFade(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness1,
uint8_t brightness2, uint16_t delay_step);
void ledPulse(uint8_t r, uint8_t g, uint8_t b, uint8_t min_brightness,
uint8_t max_brightness, uint16_t delay_step);
void initUART();
// Global Variables
int8_t ledStatus;
uint8_t red_level;
uint8_t green_level;
uint8_t blue_level;
uint8_t brightness;
uint8_t brightness_count;
uint8_t level_count;
uint16_t ticks; // counter for number of 125us intervals has passed
uint16_t tickWakeupCount = 0; // How many ticks should pass before exiting Active (0 = skip)
uint8_t exitRoutine = 0; // Flag to signal exiting a routine to do the next
uint8_t uartRxBuffer[MAX_COMMAND_LENGTH];
uint8_t uartRxPtr = 0;
uint8_t uartFlag = 0;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
// Set up the Clock System
BCSCTL1 = CALBC1_8MHZ; // Set range to 8MHz
DCOCTL = CALDCO_8MHZ; // Set DCO to 8MHz
BCSCTL2 = SELM_0 | DIVM_0 | DIVS_0; // Set MCLK to 8MHz, set SMCLK to 8MHz
initUART();
// Disable all LEDs at powerup (drive output high)
LEDOUT |= ALL_LEDS;
LEDDIR |= ALL_LEDS;
// Initialize unused GPIOs
P1OUT &= ~P1UNUSED;
P1DIR |= P1UNUSED;
P2OUT &= ~P2UNUSED;
P2DIR |= P2UNUSED;
// Set initial settings for RGB LED control
red_level = 0;
green_level = 0;
blue_level = 0;
brightness = 0;
brightness_count = 0;
level_count = 0;
ticks = 0;
// Configure Timer0 to interrupt every 200 clock cycles (at 8MHz = 25us)
TA0CCR0 = 199; // 200 - 1
TA0CTL = TASSEL_2 | ID_0 | MC_1 | TACLR; // SMCLK/1, clear count, UP Mode
TA0CCTL0 |= CCIE;
_enable_interrupts();
#ifdef DEMO_MODE
// Demo
brightness = 0;
uint8_t index = 0;
// White, Red, Orange, Yellow, Blue
uint8_t r_array[5] = {8, 8, 8, 8, 0};
uint8_t g_array[5] = {8, 0, 3, 8, 0};
uint8_t b_array[5] = {8, 0, 0, 0, 8};
while(1)
{
red_level = r_array[index];
green_level = g_array[index];
blue_level = b_array[index];
ledFade(r_array[index], g_array[index], b_array[index],
50, 0, 2000);
index++;
if (index >= 5)
{
index = 0;
}
}
#else
// Main Loop
while (1)
{
// Check for uart complete flag (for command received)
if (uartFlag)
{
// Check to see which command received
switch (uartRxBuffer[1])
{
// Turn on a specific color and brightness
case 0x01:
ledSet(uartRxBuffer[2], uartRxBuffer[3], uartRxBuffer[4],
uartRxBuffer[5]);
break;
// Set to fade a specific color from one brightness level to another
case 0x02:
ledFade(uartRxBuffer[2], uartRxBuffer[3], uartRxBuffer[4],
uartRxBuffer[5], uartRxBuffer[6],
((uartRxBuffer[7] << 8) + uartRxBuffer[8]));
break;
// Set to pulse a constant color from low brightness to high brightness back to low, repeatedly
case 0x03:
ledPulse(uartRxBuffer[2], uartRxBuffer[3], uartRxBuffer[4],
uartRxBuffer[5], uartRxBuffer[6],
((uartRxBuffer[7] << 8) + uartRxBuffer[8]));
break;
/*************************************************************
* Add additional commands here as new case statements
*************************************************************/
}
}
// Go to LPM0 to wait for more serial commands
__bis_SR_register(LPM0_bits + GIE);
}
#endif
return 0;
}
void ledOff()
{
TA0CTL &= ~MC_3; // Halt timer
TA0CTL |= TACLR; // Reset timer count
TA0CCTL0 &= ~CCIFG; // Clear flag, if set
// Disable all LEDs (drive output high)
LEDOUT |= ALL_LEDS;
// Reset all values/counters
level_count = 0;
brightness = 0;
brightness_count = 0;
ticks = 0;
tickWakeupCount = 0;
}
void ledSet(uint8_t r, uint8_t g, uint8_t b, uint8_t bright)
{
// Clear UART flags
uartRxPtr = 0;
uartFlag = 0;
// Turn off LEDs
ledOff();
// Assign specific color
red_level = r;
green_level = g;
blue_level = b;
brightness = bright;
// Start timer to generate color
TA0CTL |= MC_1;
}
void ledFade(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness1,
uint8_t brightness2, uint16_t delay_step)
{
uint8_t change_amount;
// Clear UART flags
uartRxPtr = 0;
uartFlag = 0;
// Check to see which direction to fade the LED (brighter or dimmer)
if (brightness1 > brightness2) {
change_amount = 0xFF;
} else {
change_amount = 1;
}
// Turn off LEDs
ledOff();
// Assign specific color
red_level = r;
green_level = g;
blue_level = b;
brightness = brightness1;
// Start timer to generate color
TA0CTL |= MC_1;
exitRoutine = 0;
while (brightness != brightness2)
{
if (exitRoutine)
{
// Received Stop Command, exit the routine
return;
}
// Set wakeup count
ticks = 0;
tickWakeupCount = delay_step;
// Go to LPM0 until wakeup count is reached
LPM0;
// Update the brightness level
brightness += change_amount;
}
}
void ledPulse(uint8_t r, uint8_t g, uint8_t b, uint8_t min_brightness,
uint8_t max_brightness, uint16_t delay_step)
{
uint8_t i;
// Clear UART Flags
uartRxPtr = 0;
uartFlag = 0;
// Turn off LEDs
ledOff();
// Assign specific color
red_level = r;
green_level = g;
blue_level = b;
brightness = min_brightness;
// Start timer to generate color
TA0CTL |= MC_1;
exitRoutine = 0;
while (1)
{
// Slowly increase the LED Brightness up to max
for (i = min_brightness; i < max_brightness; i++)
{
if (exitRoutine)
{
// Received Stop Command, exit the routine
return;
}
// Adjust the brightness
brightness = i;
// Set the wake up count
ticks = 0;
tickWakeupCount = delay_step;
// Go to LPM0 until wakeup count is reached
LPM0;
}
// Slowly decrease the LED brightness down to min
for (i = max_brightness; i > min_brightness; i--)
{
if (exitRoutine)
{
// Received Stop Command, exit the routine
return;
}
// Adjust the brightness
brightness = i;
// Set the wake up count
ticks = 0;
tickWakeupCount = delay_step;
// Go to LPM0 until wakeup count is reached
LPM0;
}
}
}
void initUART()
{
// Configure USCI_A0 as UART
UCA0CTL1 = UCSWRST; // put in software reset to configure
UCA0CTL0 = UCMODE_0; // 8-n-1 UART Mode
UCA0CTL1 |= UCSSEL_2; // Use SMCLK as clock source for BRCLK
// From Table 15-4 in x2xx User's Guide, SLAU144j.pdf:
// UCBRx = 833 = 0x341
// UCBRSx = 2
// UCBRFx = 0
UCA0BR1 = 0x03; // set baud rate control register
UCA0BR0 = 0x41;
UCA0MCTL = UCBRF_0 | UCBRS_2; // Set modulation Stage values to get correct baud rate
// Clear any pending interrupt flags
IFG2 &= ~(UCA0TXIFG | UCA0RXIFG);
// Pull module out of SW reset to enable
UCA0CTL1 &= ~UCSWRST;
// Enable RX interrupts
IE2 |= UCA0RXIE;
// Configure P1.1 and P1.2 as UCA0RXD and UCA0TXD
P1SEL |= BIT1 | BIT2;
P1SEL2 |= BIT1 | BIT2;
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
// Manage Counts
level_count++;
if (level_count >= MAXLEVEL)
{
level_count = 0;
brightness_count++;
if (brightness_count >= MAXINTENSITY)
{
brightness_count = 0;
}
}
if (brightness > brightness_count)
{
// update blue first
ledStatus = (blue_level > level_count);
// Add green, shifting blue to the next bit up
ledStatus = (ledStatus << 1) + (green_level > level_count);
// Add red, shifting blue and green to the appropriate places as well
ledStatus = (ledStatus << 1) + (red_level > level_count);
LEDOUT = (ledStatus ^ 0x07);
}
else
{
LEDOUT |= ALL_LEDS;
}
ticks++;
if (tickWakeupCount)
{
if (ticks >= tickWakeupCount)
{
_bic_SR_register_on_exit(LPM4_bits); // guaranteed to wake up fully from LPM
}
}
}
// UART Interrupt Service Routine
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
// Check if TX is enabled and TXIFG set
if ((IE2 & UCA0TXIE) && (IFG2 & UCA0TXIFG))
{
// TX ISR - unused
}
// Check if RX is enabled and RXIFG set
else if ((IE2 & UCA0RXIE) && (IFG2 & UCA0RXIFG))
{
// Check to make sure we are not still waiting to process the last command
if (!uartFlag)
{
// RX ISR
// Check to make sure we haven't gone too far
if (uartRxPtr > MAX_COMMAND_LENGTH)
{
// Reset the pointer to start writing a new command to the buffer
uartRxPtr = 0;
}
// Save byte to array
uartRxBuffer[uartRxPtr++] = UCA0RXBUF;
// check to see if we have the entire command
if (uartRxPtr >= uartRxBuffer[0])
{
// Check for stop command
if ((uartRxBuffer[0] == 2) && (uartRxBuffer[1] == 0))
{
// Turn of the LEDs and stop any active wakeup counter
ledOff();
// Reset all color levels
red_level = 0;
green_level = 0;
blue_level = 0;
// Set flag for exiting any in progress commands
exitRoutine = 1;
// Clear UART command flags
uartRxPtr = 0;
uartFlag = 0;
// Exit ISR to active mode (to exit any active effects)
_bic_SR_register_on_exit(LPM4_bits);
}
else
{
// Set flag to signify a command is ready to be parsed
uartFlag = 1;
// Exit ISR to active mode to parse the command
_bic_SR_register_on_exit(LPM4_bits);
}
}
}
}
}
I want the sequences to be loaded onto a table and then read to fill in the values for the LEDs for the demo code above. I have found the code below, but I am not sure it is viable for what I want to do.
init_RAM_table( ) {
char * table_ptr = &RAMtable[0]; // point to the first pointer in the table
for (y = 0; y < 26; y++){ // y is the number of the segment of memory
init_segment_pointers(* EEPROMy, *table_ptr);
table_ptr // table_ptr + 5 every iteration and is initialized to
}
}
init_segment_pointers( * segment_ptr, * table_ptr) {
for (n = 0 ; n < 5 ; n++) {
Search the mirrored bytes for 0xFF @ EEPROMy[n][k] to identify the offset k;
// Set the RAMtable ptr to the last valid location in the circular buffer
*table_ptr = &segment_ptr[n][k+50];
table_ptr++; // Increment the RAMtable ptr being written to
}
}
This is mainly what i want to accomplish, but I am also concerned with:
-A global variable to identify the specific microcontroller
-Creating a stop and next sequence ISR to be sent from the zigbee at any time
Thank you. I know this is a bit of work that needs to be done but any and all help would be appreciated.