//***************************************************************************** // // qs-rgb.c - Quickstart for the EK-LM4F120XL Stellaris LaunchPad // // Copyright (c) 2012 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 9453 of the EK-LM4F120XL Firmware Package. // //***************************************************************************** #include #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_hibernate.h" #include "driverlib/fpu.h" #include "driverlib/sysctl.h" #include "driverlib/rom.h" #include "driverlib/pin_map.h" #include "driverlib/gpio.h" #include "driverlib/systick.h" #include "driverlib/interrupt.h" #include "driverlib/hibernate.h" #include "utils/uartstdio.h" #include "utils/cmdline.h" #include "drivers/rgb.h" #include "drivers/buttons.h" #include "rgb_commands.h" #include "qs-rgb.h" //***************************************************************************** // //! \addtogroup example_list //!

EK-LM4F120XL Quickstart Application (qs-rgb)

//! //! A demonstration of the Stellaris LaunchPad (EK-LM4F120XL) capabilities. //! //! Press and/or hold the left button traverse toward the red end of the //! ROYGBIV color spectrum. Press and/or hold the right button to traverse //! toward the violet end of the ROYGBIV color spectrum. //! //! Leave idle for 5 seconds to see a automatically changing color display //! //! Press and hold both left and right buttons for 3 seconds to enter //! hibernation. During hibernation last color on screen will blink on the //! LED for 0.5 seconds every 3 seconds. //! //! Command line UART protocol can also control the system. //! //! Command 'help' to generate list of commands and helpful information. //! Command 'hib' will place the device into hibernation mode. //! Command 'rand' will initiate the pseudo-random sequence. //! Command 'intensity' followed by a number between 0.0 and 1.0 will scale //! the brightness of the LED by that factor. //! Command 'rgb' followed by a six character hex value will set the color. For //! example 'rgb FF0000' will produce a red color. // //***************************************************************************** //***************************************************************************** // // Entry counter to track how long to stay in certain staging states before // making transition into hibernate. // //***************************************************************************** static volatile unsigned long ulHibModeEntryCount; //***************************************************************************** // // Array of pre-defined colors for use when buttons cause manual color steps. // //***************************************************************************** static float fManualColors[7] = {0.0f, .214f, .428f, .642f, .856f, 1.07f, 1.284f}; //***************************************************************************** // // Input buffer for the command line interpreter. // //***************************************************************************** static char g_cInput[APP_INPUT_BUF_SIZE]; //***************************************************************************** // // Application state structure. Gets stored to hibernate memory for // preservation across hibernate events. // //***************************************************************************** volatile sAppState_t g_sAppState; //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, unsigned long ulLine) { } #endif //***************************************************************************** // // Handler to manage the button press events and state machine transitions // that result from those button events. // // This function is called by the SysTickIntHandler if a button event is // detected. Function will determine which button was pressed and tweak various // elements of the global state structure accordingly. // //***************************************************************************** void AppButtonHandler(void) { static unsigned long ulTickCounter; ulTickCounter++; // // Switch statement to adjust the color wheel position based on buttons // switch(g_sAppState.ulButtons & ALL_BUTTONS) { case LEFT_BUTTON: // // Check if the button has been held long enough to peform another // color wheel increment. // if((ulTickCounter % APP_BUTTON_POLL_DIVIDER) == 0) { // // Perform the increment and index wrap around. // g_sAppState.ulManualIndex++; if(g_sAppState.ulManualIndex >= APP_NUM_MANUAL_COLORS) { g_sAppState.ulManualIndex = 0; } g_sAppState.fColorWheelPos = APP_PI * fManualColors[g_sAppState.ulManualIndex]; } // // Reset some state counts and system mode so that we know the user // is present and actively engaging with the application. // ulHibModeEntryCount = 0; g_sAppState.ulModeTimer = 0; g_sAppState.ulMode = APP_MODE_NORMAL; break; case RIGHT_BUTTON: // // Check if the button has been held long enough to perform another // color wheel decrement. // if((ulTickCounter % APP_BUTTON_POLL_DIVIDER) == 0) { // // Perform the decrement and index wrap around. // if(g_sAppState.ulManualIndex == 0) { // // set to one greater than the last color so that we decrement // back into range with next instruction. // g_sAppState.ulManualIndex = APP_NUM_MANUAL_COLORS; } g_sAppState.ulManualIndex--; g_sAppState.fColorWheelPos = APP_PI * fManualColors[g_sAppState.ulManualIndex]; } // // Reset some state counts and system mode so that we know the user // is present and actively engaging with the application. // ulHibModeEntryCount = 0; g_sAppState.ulModeTimer = 0; g_sAppState.ulMode = APP_MODE_NORMAL; break; case ALL_BUTTONS: // // Both buttons for longer than debounce time will cause hibernation // if(ulHibModeEntryCount < APP_HIB_BUTTON_DEBOUNCE) { ulHibModeEntryCount++; g_sAppState.ulMode = APP_MODE_NORMAL; } else { g_sAppState.ulMode = APP_MODE_HIB; } g_sAppState.ulModeTimer = 0; break; default: if(g_sAppState.ulMode == APP_MODE_HIB_FLASH) { // // Waking from hibernate RTC just do a quick flash then back to // hibernation. // if(ulHibModeEntryCount < APP_HIB_FLASH_DURATION) { ulHibModeEntryCount++; } else { g_sAppState.ulMode = APP_MODE_HIB; } } else { // // Normal or remote mode and no user action will cause transition // to automatic scrolling mode. // ulHibModeEntryCount = 0; if(g_sAppState.ulModeTimer < APP_AUTO_MODE_TIMEOUT) { g_sAppState.ulModeTimer++; } else { g_sAppState.ulMode = APP_MODE_AUTO; } // // reset the tick counter when no buttons are pressed // this makes the first button reaction speed quicker // ulTickCounter = APP_BUTTON_POLL_DIVIDER - 1; } break; } } //***************************************************************************** // // Uses the fColorWheelPos variable to update the color mix shown on the RGB // // ulForceUpdate when set forces a color update even if a color change // has not been detected. Used primarily at startup to init the color after // a hibernate. // // This function is called by the SysTickIntHandler to update the colors on // the RGB LED whenever a button or timeout event has changed the color wheel // position. Color is determined by a series of sine functions and conditions // //***************************************************************************** void AppRainbow(unsigned long ulForceUpdate) { static float fPrevPos; float fCurPos; float fTemp; volatile unsigned long * pulColors; pulColors = g_sAppState.ulColors; fCurPos = g_sAppState.fColorWheelPos; if((fCurPos != fPrevPos) || ulForceUpdate) { // // Preserve the new color wheel position // fPrevPos = fCurPos; // // Adjust the BLUE value based on the control state // fTemp = 65535.0f * sinf(fCurPos); if(fTemp < 0) { pulColors[GREEN] = 0; } else { pulColors[GREEN] = (unsigned long) fTemp; } // // Adjust the RED value based on the control state // fTemp = 65535.0f * sinf(fCurPos - APP_PI / 2.0f); if(fTemp < 0) { pulColors[BLUE] = 0; } else { pulColors[BLUE] = (unsigned long) fTemp; } // // Adjust the GREEN value based on the control state // if(fCurPos < APP_PI) { fTemp = 65535.0f * sinf(fCurPos + APP_PI * 0.5f); } else { fTemp = 65535.0f * sinf(fCurPos + APP_PI); } if(fTemp < 0) { pulColors[RED] = 0; } else { pulColors[RED] = (unsigned long) fTemp; } // // Update the actual LED state // RGBColorSet(pulColors); } } //***************************************************************************** // // Called by the NVIC as a result of SysTick Timer rollover interrupt flag // // Checks buttons and calls AppButtonHandler to manage button events. // Tracks time and auto mode color stepping. Calls AppRainbow to implement // RGB color changes. // //***************************************************************************** void SysTickIntHandler(void) { static float x; g_sAppState.ulButtons = ButtonsPoll(0,0); AppButtonHandler(); // // Auto increment the color wheel if in the AUTO mode. AUTO mode is when // device is active but user interaction has timed out. // if(g_sAppState.ulMode == APP_MODE_AUTO) { g_sAppState.fColorWheelPos += APP_AUTO_COLOR_STEP; } // // Provide wrap around of the control variable from 0 to 1.5 times PI // if(g_sAppState.fColorWheelPos > (APP_PI * 1.5f)) { g_sAppState.fColorWheelPos = 0.0f; } if(x < 0.0f) { g_sAppState.fColorWheelPos = APP_PI * 1.5f; } // // Set the RGB Color based on current control variable value. // AppRainbow(0); } //***************************************************************************** // // Uses the fColorWheelPos variable to update the color mix shown on the RGB // // This function is called when system has decided it is time to enter // Hibernate. This will prepare the hibernate peripheral, save the system // state and then enter hibernate mode. // //***************************************************************************** void AppHibernateEnter(void) { // // Alert UART command line users that we are going to hibernate // UARTprintf("Entering Hibernate...\n"); // // Prepare Hibernation Module // HibernateGPIORetentionEnable(); HibernateRTCSet(0); HibernateRTCEnable(); HibernateRTCMatch0Set(5); HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC); // // Store state information to battery backed memory // since sizeof returns number of bytes we convert to words and force // a rounding up to next whole word. // HibernateDataSet((unsigned long*)&g_sAppState, sizeof(sAppState_t)/4+1); // // Disable the LED for 100 milliseconds to let user know we are // ready for hibernate and will hibernate on relase of buttons // RGBDisable(); SysCtlDelay(SysCtlClockGet()/3/10); RGBEnable(); // // Wait for wake button to be released prior to going into hibernate // while(g_sAppState.ulButtons & RIGHT_BUTTON) { // //Delay for about 300 clock ticks to allow time for interrupts to //sense that button is released // SysCtlDelay(100); } // // Disable the LED for power savings and go to hibernate mode // RGBDisable(); HibernateRequest(); } //***************************************************************************** // // Main function performs init and manages system. // // Called automatically after the system and compiler pre-init sequences. // Performs system init calls, restores state from hibernate if needed and // then manages the application context duties of the system. // //***************************************************************************** int main(void) { unsigned long ulStatus; unsigned long ulResetCause; long lCommandStatus; // // Enable stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. // ROM_FPUEnable(); ROM_FPUStackingEnable(); // // Set the system clock to run at 40Mhz off PLL with external crystal as // reference. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); // // Enable the hibernate module // SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); // // Enable and Initialize the UART. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTStdioInit(0); UARTprintf("Welcome to the Stellaris LM4F120 LaunchPad!\n"); UARTprintf("Type 'help' for a list of commands\n"); UARTprintf("> "); // // Determine why system reset occurred and respond accordingly. // ulResetCause = SysCtlResetCauseGet(); SysCtlResetCauseClear(ulResetCause); if(ulResetCause == SYSCTL_CAUSE_POR) { if(HibernateIsActive()) { // // Read the status bits to see what caused the wake. // ulStatus = HibernateIntStatus(0); HibernateIntClear(ulStatus); // // Wake was due to the push button. // if(ulStatus & HIBERNATE_INT_PIN_WAKE) { UARTprintf("Hibernate Wake Pin Wake Event\n"); UARTprintf("> "); // // Recover the application state variables from battery backed // hibernate memory. Set ulMode to normal. // HibernateDataGet((unsigned long*) &g_sAppState, sizeof(sAppState_t) / 4 + 1); g_sAppState.ulMode = APP_MODE_NORMAL; } // // Wake was due to RTC match // else if(ulStatus & HIBERNATE_INT_RTC_MATCH_0) { UARTprintf("Hibernate RTC Wake Event\n"); UARTprintf("> "); // // Recover the application state variables from battery backed // hibernate memory. Set ulMode to briefly flash the RGB. // HibernateDataGet((unsigned long*) &g_sAppState, sizeof(sAppState_t) / 4 + 1); g_sAppState.ulMode = APP_MODE_HIB_FLASH; } } else { // // Reset was do to a cold first time power up. // UARTprintf("Power on reset. Hibernate not active.\n"); UARTprintf("> "); g_sAppState.ulMode = APP_MODE_NORMAL; g_sAppState.fColorWheelPos = 0; g_sAppState.fIntensity = APP_INTENSITY_DEFAULT; g_sAppState.ulButtons = 0; } } else { // // External Pin reset or other reset event occured. // UARTprintf("External or other reset\n"); UARTprintf("> "); // // Treat this as a cold power up reset without restore from hibernate. // g_sAppState.ulMode = APP_MODE_NORMAL; g_sAppState.fColorWheelPos = APP_PI; g_sAppState.fIntensity = APP_INTENSITY_DEFAULT; g_sAppState.ulButtons = 0; // // colors get a default initialization later when we call AppRainbow. // } // // Initialize clocking for the Hibernate module // HibernateEnableExpClk(SysCtlClockGet()); // // Initialize the RGB LED. AppRainbow typically only called from interrupt // context. Safe to call here to force initial color update because // interrupts are not yet enabled. // RGBInit(0); RGBIntensitySet(g_sAppState.fIntensity); AppRainbow(1); RGBEnable(); // // Initialize the buttons // ButtonsInit(); // // Initialize the SysTick interrupt to process colors and buttons. // SysTickPeriodSet(SysCtlClockGet() / APP_SYSTICKS_PER_SEC); SysTickEnable(); SysTickIntEnable(); IntMasterEnable(); // // spin forever and wait for carriage returns or state changes. // while(1) { UARTprintf("\n>"); // // Peek to see if a full command is ready for processing // while(UARTPeek('\r') == -1) { // // millisecond delay. A SysCtlSleep() here would also be OK. // SysCtlDelay(SysCtlClockGet() / (1000 / 3)); // // Check for change of mode and enter hibernate if requested. // all other mode changes handled in interrupt context. // if(g_sAppState.ulMode == APP_MODE_HIB) { AppHibernateEnter(); } } // // a '\r' was detected get the line of text from the user. // UARTgets(g_cInput,sizeof(g_cInput)); // // Pass the line from the user to the command processor. // It will be parsed and valid commands executed. // lCommandStatus = CmdLineProcess(g_cInput); // // Handle the case of bad command. // if(lCommandStatus == CMDLINE_BAD_CMD) { UARTprintf("Bad command!\n"); } // // Handle the case of too many arguments. // else if(lCommandStatus == CMDLINE_TOO_MANY_ARGS) { UARTprintf("Too many arguments for command processor!\n"); } } }