summaryrefslogtreecommitdiff
path: root/boards/ek-lm4f232/drivers
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-06-29 12:34:32 +0300
committerYuval Adam <yuv.adm@gmail.com>2014-06-29 12:34:32 +0300
commitc3e4c9a25c2910d2d66d52215b3406b13d5b23d5 (patch)
treeadded370d1e356901f8579f076e3263fb0464db7 /boards/ek-lm4f232/drivers
parent990090a4cc9070837d31e66b58d40f0c3d038741 (diff)
Add more board models
Diffstat (limited to 'boards/ek-lm4f232/drivers')
-rw-r--r--boards/ek-lm4f232/drivers/buttons.c186
-rw-r--r--boards/ek-lm4f232/drivers/buttons.h103
-rw-r--r--boards/ek-lm4f232/drivers/cfal96x64x16.c816
-rw-r--r--boards/ek-lm4f232/drivers/cfal96x64x16.h37
-rw-r--r--boards/ek-lm4f232/drivers/slidemenuwidget.c1424
-rw-r--r--boards/ek-lm4f232/drivers/slidemenuwidget.h457
-rw-r--r--boards/ek-lm4f232/drivers/stripchartwidget.c672
-rw-r--r--boards/ek-lm4f232/drivers/stripchartwidget.h392
-rw-r--r--boards/ek-lm4f232/drivers/usb_sound.c804
-rw-r--r--boards/ek-lm4f232/drivers/usb_sound.h81
10 files changed, 4972 insertions, 0 deletions
diff --git a/boards/ek-lm4f232/drivers/buttons.c b/boards/ek-lm4f232/drivers/buttons.c
new file mode 100644
index 0000000..9dc9ce9
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/buttons.c
@@ -0,0 +1,186 @@
+//*****************************************************************************
+//
+// buttons.c - Evaluation board driver for push buttons.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "driverlib/gpio.h"
+#include "driverlib/pin_map.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "inc/hw_types.h"
+#include "inc/hw_memmap.h"
+#include "buttons.h"
+
+//*****************************************************************************
+//
+//! \addtogroup buttons_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Holds the current, debounced state of each button. A 0 in a bit indicates
+// that that button is currently pressed, otherwise it is released.
+// We assume that we start with all the buttons released (though if one is
+// pressed when the application starts, this will be detected).
+//
+//*****************************************************************************
+static uint8_t g_ui8ButtonStates = ALL_BUTTONS;
+
+//*****************************************************************************
+//
+//! Polls the current state of the buttons and determines which have changed.
+//!
+//! \param pui8Delta points to a character that will be written to indicate
+//! which button states changed since the last time this function was called.
+//! This value is derived from the debounced state of the buttons.
+//! \param pui8RawState points to a location where the raw button state will
+//! be stored.
+//!
+//! This function should be called periodically by the application to poll the
+//! pushbuttons. It determines both the current debounced state of the buttons
+//! and also which buttons have changed state since the last time the function
+//! was called.
+//!
+//! In order for button debouncing to work properly, this function should be
+//! caled at a regular interval, even if the state of the buttons is not needed
+//! that often.
+//!
+//! If button debouncing is not required, the the caller can pass a pointer
+//! for the \e pui8RawState parameter in order to get the raw state of the
+//! buttons. The value returned in \e pui8RawState will be a bit mask where
+//! a 1 indicates the buttons is pressed.
+//!
+//! \return Returns the current debounced state of the buttons where a 1 in the
+//! button ID's position indicates that the button is pressed and a 0
+//! indicates that it is released.
+//
+//*****************************************************************************
+uint8_t
+ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8RawState)
+{
+ uint32_t ui32Delta;
+ uint32_t ui32Data;
+ static uint8_t ui8SwitchClockA = 0;
+ static uint8_t ui8SwitchClockB = 0;
+
+ //
+ // Read the raw state of the push buttons. Save the raw state
+ // (inverting the bit sense) if the caller supplied storage for the
+ // raw value.
+ //
+ ui32Data = (MAP_GPIOPinRead(BUTTONS_GPIO_BASE, ALL_BUTTONS));
+ if(pui8RawState)
+ {
+ *pui8RawState = (uint8_t)~ui32Data;
+ }
+
+ //
+ // Determine the switches that are at a different state than the debounced
+ // state.
+ //
+ ui32Delta = ui32Data ^ g_ui8ButtonStates;
+
+ //
+ // Increment the clocks by one.
+ //
+ ui8SwitchClockA ^= ui8SwitchClockB;
+ ui8SwitchClockB = ~ui8SwitchClockB;
+
+ //
+ // Reset the clocks corresponding to switches that have not changed state.
+ //
+ ui8SwitchClockA &= ui32Delta;
+ ui8SwitchClockB &= ui32Delta;
+
+ //
+ // Get the new debounced switch state.
+ //
+ g_ui8ButtonStates &= ui8SwitchClockA | ui8SwitchClockB;
+ g_ui8ButtonStates |= (~(ui8SwitchClockA | ui8SwitchClockB)) & ui32Data;
+
+ //
+ // Determine the switches that just changed debounced state.
+ //
+ ui32Delta ^= (ui8SwitchClockA | ui8SwitchClockB);
+
+ //
+ // Store the bit mask for the buttons that have changed for return to
+ // caller.
+ //
+ if(pui8Delta)
+ {
+ *pui8Delta = (uint8_t)ui32Delta;
+ }
+
+ //
+ // Return the debounced buttons states to the caller. Invert the bit
+ // sense so that a '1' indicates the button is pressed, which is a
+ // sensible way to interpret the return value.
+ //
+ return(~g_ui8ButtonStates);
+}
+
+//*****************************************************************************
+//
+//! Initializes the GPIO pins used by the board pushbuttons.
+//!
+//! This function must be called during application initialization to
+//! configure the GPIO pins to which the pushbuttons are attached. It enables
+//! the port used by the buttons and configures each button GPIO as an input
+//! with a weak pull-up.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ButtonsInit(void)
+{
+ //
+ // Enable the GPIO port to which the pushbuttons are connected.
+ //
+ MAP_SysCtlPeripheralEnable(BUTTONS_GPIO_PERIPH);
+
+ //
+ // Set each of the button GPIO pins as an input with a pull-up.
+ //
+ MAP_GPIODirModeSet(BUTTONS_GPIO_BASE, ALL_BUTTONS, GPIO_DIR_MODE_IN);
+ MAP_GPIOPadConfigSet(BUTTONS_GPIO_BASE, ALL_BUTTONS,
+ GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
+
+ //
+ // Initialize the debounced button state with the current state read from
+ // the GPIO bank.
+ //
+ g_ui8ButtonStates = MAP_GPIOPinRead(BUTTONS_GPIO_BASE, ALL_BUTTONS);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/boards/ek-lm4f232/drivers/buttons.h b/boards/ek-lm4f232/drivers/buttons.h
new file mode 100644
index 0000000..fa52fa4
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/buttons.h
@@ -0,0 +1,103 @@
+//*****************************************************************************
+//
+// buttons.h - Prototypes for the evaluation board buttons driver.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#ifndef __BUTTONS_H__
+#define __BUTTONS_H__
+
+//*****************************************************************************
+//
+// Defines for the hardware resources used by the pushbuttons.
+//
+// The switches are on the following ports/pins:
+//
+// PM0 - Up
+// PM1 - Down
+// PM2 - Left
+// PM3 - Right
+// PM4 - Select/Wake
+//
+// The switches tie the GPIO to ground, so the GPIOs need to be configured
+// with pull-ups, and a value of 0 means the switch is pressed.
+//
+//*****************************************************************************
+#define BUTTONS_GPIO_PERIPH SYSCTL_PERIPH_GPIOM
+#define BUTTONS_GPIO_BASE GPIO_PORTM_BASE
+
+#define NUM_BUTTONS 5
+#define UP_BUTTON GPIO_PIN_0
+#define DOWN_BUTTON GPIO_PIN_1
+#define LEFT_BUTTON GPIO_PIN_2
+#define RIGHT_BUTTON GPIO_PIN_3
+#define SELECT_BUTTON GPIO_PIN_4
+
+#define ALL_BUTTONS (LEFT_BUTTON | RIGHT_BUTTON | UP_BUTTON | \
+ DOWN_BUTTON | SELECT_BUTTON)
+
+//*****************************************************************************
+//
+// Useful macros for detecting button events.
+//
+//*****************************************************************************
+#define BUTTON_PRESSED(button, buttons, changed) \
+ (((button) & (changed)) && ((button) & (buttons)))
+
+#define BUTTON_RELEASED(button, buttons, changed) \
+ (((button) & (changed)) && !((button) & (buttons)))
+
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Functions exported from buttons.c
+//
+//*****************************************************************************
+extern void ButtonsInit(void);
+extern uint8_t ButtonsPoll(uint8_t *pui8Delta,
+ uint8_t *pui8Raw);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+//*****************************************************************************
+//
+// Prototypes for the globals exported by this driver.
+//
+//*****************************************************************************
+
+#endif // __BUTTONS_H__
diff --git a/boards/ek-lm4f232/drivers/cfal96x64x16.c b/boards/ek-lm4f232/drivers/cfal96x64x16.c
new file mode 100644
index 0000000..1036643
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/cfal96x64x16.c
@@ -0,0 +1,816 @@
+//*****************************************************************************
+//
+// cfal96x64x16.c - Display driver for the Crystalfontz CFAL9664-F-B1 OLED
+// display with an SSD1332. This version uses an SSI
+// interface to the display controller.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! \addtogroup display_api
+//! @{
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_memmap.h"
+#include "driverlib/gpio.h"
+#include "driverlib/ssi.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/rom.h"
+#include "driverlib/pin_map.h"
+#include "grlib/grlib.h"
+#include "drivers/cfal96x64x16.h"
+
+//*****************************************************************************
+//
+// Defines the SSI and GPIO peripherals that are used for this display.
+//
+//*****************************************************************************
+#define DISPLAY_SSI_PERIPH SYSCTL_PERIPH_SSI2
+#define DISPLAY_SSI_GPIO_PERIPH SYSCTL_PERIPH_GPIOH
+#define DISPLAY_RST_GPIO_PERIPH SYSCTL_PERIPH_GPIOG
+
+//*****************************************************************************
+//
+// Defines the GPIO pin configuration macros for the pins that are used for
+// the SSI function.
+//
+//*****************************************************************************
+#define DISPLAY_PINCFG_SSICLK GPIO_PH4_SSI2CLK
+#define DISPLAY_PINCFG_SSIFSS GPIO_PH5_SSI2FSS
+#define DISPLAY_PINCFG_SSITX GPIO_PH7_SSI2TX
+
+//*****************************************************************************
+//
+// Defines the port and pins for the SSI peripheral.
+//
+//*****************************************************************************
+#define DISPLAY_SSI_PORT GPIO_PORTH_BASE
+#define DISPLAY_SSI_PINS (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7)
+
+//*****************************************************************************
+//
+// Defines the port and pins for the display voltage enable signal.
+//
+//*****************************************************************************
+#define DISPLAY_ENV_PORT GPIO_PORTG_BASE
+#define DISPLAY_ENV_PIN GPIO_PIN_0
+
+//*****************************************************************************
+//
+// Defines the port and pins for the display reset signal.
+//
+//*****************************************************************************
+#define DISPLAY_RST_PORT GPIO_PORTG_BASE
+#define DISPLAY_RST_PIN GPIO_PIN_1
+
+//*****************************************************************************
+//
+// Defines the port and pins for the display Data/Command (D/C) signal.
+//
+//*****************************************************************************
+#define DISPLAY_D_C_PORT GPIO_PORTH_BASE
+#define DISPLAY_D_C_PIN GPIO_PIN_6
+
+//*****************************************************************************
+//
+// Defines the SSI peripheral used and the data speed.
+//
+//*****************************************************************************
+#define DISPLAY_SSI_BASE SSI2_BASE // SSI2
+#define DISPLAY_SSI_CLOCK 4000000
+
+//*****************************************************************************
+//
+// An array that holds a set of commands that are sent to the display when
+// it is initialized.
+//
+//*****************************************************************************
+static
+uint8_t g_ui8DisplayInitCommands[] =
+{
+// 0xAE, // display off
+ 0x87, 0x07, // master control current 7/16
+ 0x81, 0xA0, // contrast A control
+ 0x82, 0x60, // contrast B control
+ 0x83, 0xB0, // contrast C control
+ 0xA0, 0x20,//00 // remap and data format - use 8-bit color mode
+ 0xBB, 0x1F, // Vpa
+ 0xBC, 0x1F, // Vpb
+ 0xBD, 0x1F, // Vpc
+// 0xAD, 0x8E, // internal Vp, external supply
+ 0x26, 0x01, // rectangle fill enabled
+ 0xAF // display on
+};
+#define NUM_INIT_BYTES sizeof(g_ui8DisplayInitCommands)
+
+//*****************************************************************************
+//
+// Translates a 24-bit RGB color to a display driver-specific color.
+//
+// \param c is the 24-bit RGB color. The least-significant byte is the blue
+// channel, the next byte is the green channel, and the third byte is the red
+// channel.
+//
+// This macro translates a 24-bit RGB color into a value that can be written
+// into the display's frame buffer in order to reproduce that color, or the
+// closest possible approximation of that color.
+//
+// \return Returns the display-driver specific color.
+//
+// 24-bit format: XXXX XXXX RRRR RRRR GGGG GGGG BBBB BBBB
+// 16-bit format: ---- ---- ---- ---- RRRR RGGG GGGB BBBB
+// 8-bit format: ---- ---- ---- ---- ---- ---- RRRG GGBB
+//
+//
+//*****************************************************************************
+#define DPYCOLORTRANSLATE16(c) ((((c) & 0x00f80000) >> 8) | \
+ (((c) & 0x0000fc00) >> 5) | \
+ (((c) & 0x000000f8) >> 3))
+#define DPYCOLORTRANSLATE8(c) ((((c) & 0x00e00000) >> 16) | \
+ (((c) & 0x0000e000) >> 11) | \
+ (((c) & 0x000000c0) >> 6))
+#define DPYCOLORTRANSLATE DPYCOLORTRANSLATE8
+
+//*****************************************************************************
+//
+//! Write a set of command bytes to the display controller.
+//
+//! \param pi8Cmd is a pointer to a set of command bytes.
+//! \param ui32Count is the count of command bytes.
+//!
+//! This function provides a way to send multiple command bytes to the display
+//! controller. It can be used for single commands, or multiple commands
+//! chained together in a buffer. It will wait for any previous operation to
+//! finish, and then copy all the command bytes to the controller. It will
+//! not return until the last command byte has been written to the SSI FIFO,
+//! but data could still be shifting out to the display controller when this
+//! function returns.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16WriteCommand(const uint8_t *pi8Cmd, uint32_t ui32Count)
+{
+ //
+ // Wait for any previous SSI operation to finish.
+ //
+ while(ROM_SSIBusy(DISPLAY_SSI_BASE))
+ {
+ }
+
+ //
+ // Set the D/C pin low to indicate command
+ //
+ ROM_GPIOPinWrite(DISPLAY_D_C_PORT, DISPLAY_D_C_PIN, 0);
+
+ //
+ // Send all the command bytes to the display
+ //
+ while(ui32Count--)
+ {
+ ROM_SSIDataPut(DISPLAY_SSI_BASE, *pi8Cmd);
+ pi8Cmd++;
+ }
+}
+
+//*****************************************************************************
+//
+//! Write a set of data bytes to the display controller.
+//
+//! \param pi8Data is a pointer to a set of data bytes, containing pixel data.
+//! \param ui32Count is the count of command bytes.
+//!
+//! This function provides a way to send a set of pixel data to the display.
+//! The data will draw pixels according to whatever the most recent col, row
+//! settings are for the display. It will wait for any previous operation to
+//! finish, and then copy all the data bytes to the controller. It will
+//! not return until the last data byte has been written to the SSI FIFO,
+//! but data could still be shifting out to the display controller when this
+//! function returns.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16WriteData(const uint8_t *pi8Data, uint32_t ui32Count)
+{
+ //
+ // Wait for any previous SSI operation to finish.
+ //
+ while(ROM_SSIBusy(DISPLAY_SSI_BASE))
+ {
+ }
+
+ //
+ // Set the D/C pin high to indicate data
+ //
+ ROM_GPIOPinWrite(DISPLAY_D_C_PORT, DISPLAY_D_C_PIN, DISPLAY_D_C_PIN);
+
+ //
+ // Send all the data bytes to the display
+ //
+ while(ui32Count--)
+ {
+ ROM_SSIDataPut(DISPLAY_SSI_BASE, *pi8Data);
+ pi8Data++;
+ }
+}
+
+//*****************************************************************************
+//
+//! Draws a pixel on the screen.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param i32X is the X coordinate of the pixel.
+//! \param i32Y is the Y coordinate of the pixel.
+//! \param ui32Value is the color of the pixel.
+//!
+//! This function sets the given pixel to a particular color. The coordinates
+//! of the pixel are assumed to be within the extents of the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16PixelDraw(void *pvDisplayData, int32_t i32X, int32_t i32Y,
+ uint32_t ui32Value)
+{
+ uint8_t ui8Cmd[8];
+
+ //
+ // Load column command, start and end column
+ //
+ ui8Cmd[0] = 0x15;
+ ui8Cmd[1] = (uint8_t)i32X;
+ ui8Cmd[2] = (uint8_t)i32X;
+
+ //
+ // Load row command, start and end row
+ //
+ ui8Cmd[3] = 0x75;
+ ui8Cmd[4] = (uint8_t)i32Y;
+ ui8Cmd[5] = (uint8_t)i32Y;
+
+ //
+ // Send the column, row commands to the display
+ //
+ CFAL96x64x16WriteCommand(ui8Cmd, 6);
+
+ //
+ // Send the data value representing the pixel to the display
+ //
+ CFAL96x64x16WriteData((uint8_t *)&ui32Value, 1);
+}
+
+//*****************************************************************************
+//
+//! Draws a horizontal sequence of pixels on the screen.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param i32X is the X coordinate of the first pixel.
+//! \param i32Y is the Y coordinate of the first pixel.
+//! \param i32X0 is sub-pixel offset within the pixel data, which is valid for 1
+//! or 4 bit per pixel formats.
+//! \param i32Count is the number of pixels to draw.
+//! \param i32BPP is the number of bits per pixel; must be 1, 4, or 8 optionally
+//! ORed with various flags unused by this driver.
+//! \param pui8Data is a pointer to the pixel data. For 1 and 4 bit per pixel
+//! formats, the most significant bit(s) represent the left-most pixel.
+//! \param pui8Palette is a pointer to the palette used to draw the pixels.
+//!
+//! This function draws a horizontal sequence of pixels on the screen, using
+//! the supplied palette. For 1 bit per pixel format, the palette contains
+//! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
+//! contains 24-bit RGB values that must be translated before being written to
+//! the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16PixelDrawMultiple(void *pvDisplayData, int32_t i32X, int32_t i32Y, int32_t i32X0,
+ int32_t i32Count, int32_t i32BPP,
+ const uint8_t *pui8Data,
+ const uint8_t *pui8Palette)
+{
+ uint32_t ui32Byte;
+ uint8_t ui8Cmd[8];
+
+ //
+ // Load column command. Use the specified X for the start and just set
+ // the end to the rightmost column since we dont know where the data ends.
+ //
+ ui8Cmd[0] = 0x15;
+ ui8Cmd[1] = (uint8_t)i32X;
+ ui8Cmd[2] = 95;
+
+ //
+ // Load row command. Use the specified Y for the start row and just set
+ // the end row to the bottom row since we dont know where the data ends.
+ //
+ ui8Cmd[3] = 0x75;
+ ui8Cmd[4] = (uint8_t)i32Y;
+ ui8Cmd[5] = 63;
+
+ //
+ // Send the column, row commands to the display
+ //
+ CFAL96x64x16WriteCommand(ui8Cmd, 6);
+
+ //
+ // Determine how to interpret the pixel data based on the number of bits
+ // per pixel.
+ //
+ switch(i32BPP & 0xFF)
+ {
+ //
+ // The pixel data is in 1 bit per pixel format.
+ //
+ case 1:
+ {
+ //
+ // Loop while there are more pixels to draw.
+ //
+ while(i32Count)
+ {
+ //
+ // Get the next byte of image data.
+ //
+ ui32Byte = *pui8Data++;
+
+ //
+ // Loop through the pixels in this byte of image data.
+ //
+ for(; (i32X0 < 8) && i32Count; i32X0++, i32Count--)
+ {
+ //
+ // Draw this pixel in the appropriate color.
+ //
+ uint8_t ui8BPP = ((uint32_t *)pui8Palette)
+ [(ui32Byte >> (7 - i32X0)) & 1];
+ CFAL96x64x16WriteData(&ui8BPP, 1);
+ }
+
+ //
+ // Start at the beginning of the next byte of image data.
+ //
+ i32X0 = 0;
+ }
+
+ //
+ // The image data has been drawn.
+ //
+ break;
+ }
+
+ //
+ // The pixel data is in 4 bit per pixel format.
+ //
+ case 4:
+ {
+ //
+ // Loop while there are more pixels to draw. "Duff's device" is
+ // used to jump into the middle of the loop if the first nibble of
+ // the pixel data should not be used. Duff's device makes use of
+ // the fact that a case statement is legal anywhere within a
+ // sub-block of a switch statement. See
+ // http://en.wikipedia.org/wiki/Duff's_device for detailed
+ // information about Duff's device.
+ //
+ switch(i32X0 & 1)
+ {
+ case 0:
+ while(i32Count)
+ {
+ uint8_t ui8Color;
+
+ //
+ // Get the upper nibble of the next byte of pixel data
+ // and extract the corresponding entry from the
+ // palette.
+ //
+ ui32Byte = (*pui8Data >> 4) * 3;
+ ui32Byte = (*(uint32_t *)(pui8Palette + ui32Byte) &
+ 0x00ffffff);
+
+ //
+ // Translate this palette entry and write it to the
+ // screen.
+ //
+ ui8Color = DPYCOLORTRANSLATE(ui32Byte);
+ CFAL96x64x16WriteData(&ui8Color, 1);
+
+ //
+ // Decrement the count of pixels to draw.
+ //
+ i32Count--;
+
+ //
+ // See if there is another pixel to draw.
+ //
+ if(i32Count)
+ {
+ case 1:
+ //
+ // Get the lower nibble of the next byte of pixel
+ // data and extract the corresponding entry from
+ // the palette.
+ //
+ ui32Byte = (*pui8Data++ & 15) * 3;
+ ui32Byte = (*(uint32_t *)(pui8Palette + ui32Byte) &
+ 0x00ffffff);
+
+ //
+ // Translate this palette entry and write it to the
+ // screen.
+ //
+ ui8Color = DPYCOLORTRANSLATE(ui32Byte);
+ CFAL96x64x16WriteData(&ui8Color, 1);
+
+ //
+ // Decrement the count of pixels to draw.
+ //
+ i32Count--;
+ }
+ }
+ }
+
+ //
+ // The image data has been drawn.
+ //
+ break;
+ }
+
+ //
+ // The pixel data is in 8 bit per pixel format.
+ //
+ case 8:
+ {
+ //
+ // Loop while there are more pixels to draw.
+ //
+ while(i32Count--)
+ {
+ uint8_t ui8Color;
+
+ //
+ // Get the next byte of pixel data and extract the
+ // corresponding entry from the palette.
+ //
+ ui32Byte = *pui8Data++ * 3;
+ ui32Byte = *(uint32_t *)(pui8Palette + ui32Byte) & 0x00ffffff;
+
+ //
+ // Translate this palette entry and write it to the screen.
+ //
+ ui8Color = DPYCOLORTRANSLATE(ui32Byte);
+ CFAL96x64x16WriteData(&ui8Color, 1);
+ }
+
+ //
+ // The image data has been drawn.
+ //
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Draws a horizontal line.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param i32X1 is the X coordinate of the start of the line.
+//! \param i32X2 is the X coordinate of the end of the line.
+//! \param i32Y is the Y coordinate of the line.
+//! \param ui32Value is the color of the line.
+//!
+//! This function draws a horizontal line on the display. The coordinates of
+//! the line are assumed to be within the extents of the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16LineDrawH(void *pvDisplayData, int32_t i32X1, int32_t i32X2, int32_t i32Y,
+ uint32_t ui32Value)
+{
+ uint8_t ui8LineBuf[16];
+ unsigned int uIdx;
+
+ //
+ // Send command for starting row and column
+ //
+ ui8LineBuf[0] = 0x15;
+ ui8LineBuf[1] = i32X1 < i32X2 ? i32X1 : i32X2;
+ ui8LineBuf[2] = 95;
+ ui8LineBuf[3] = 0x75;
+ ui8LineBuf[4] = i32Y;
+ ui8LineBuf[5] = 63;
+ CFAL96x64x16WriteCommand(ui8LineBuf, 6);
+
+ //
+ // Use buffer of pixels to draw line, so multiple bytes can be sent at
+ // one time. Fill the buffer with the line color.
+ //
+ for(uIdx = 0; uIdx < sizeof(ui8LineBuf); uIdx++)
+ {
+ ui8LineBuf[uIdx] = ui32Value;
+ }
+
+ uIdx = (i32X1 < i32X2) ? (i32X2 - i32X1) : (i32X1 - i32X2);
+ uIdx += 1;
+ while(uIdx)
+ {
+ CFAL96x64x16WriteData(ui8LineBuf, (uIdx < 16) ? uIdx : 16);
+ uIdx -= (uIdx < 16) ? uIdx : 16;
+ }
+}
+
+//*****************************************************************************
+//
+//! Draws a vertical line.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param i32X is the X coordinate of the line.
+//! \param i32Y1 is the Y coordinate of the start of the line.
+//! \param i32Y2 is the Y coordinate of the end of the line.
+//! \param ui32Value is the color of the line.
+//!
+//! This function draws a vertical line on the display. The coordinates of the
+//! line are assumed to be within the extents of the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16LineDrawV(void *pvDisplayData, int32_t i32X, int32_t i32Y1, int32_t i32Y2,
+ uint32_t ui32Value)
+{
+ uint8_t ui8LineBuf[16];
+ unsigned int uIdx;
+
+ //
+ // Send command for starting row and column. Also, set vertical
+ // address increment.
+ //
+ ui8LineBuf[0] = 0x15;
+ ui8LineBuf[1] = i32X;
+ ui8LineBuf[2] = 95;
+ ui8LineBuf[3] = 0x75;
+ ui8LineBuf[4] = i32Y1 < i32Y2 ? i32Y1 : i32Y2;
+ ui8LineBuf[5] = 63;
+ ui8LineBuf[6] = 0xA0;
+ ui8LineBuf[7] = 0x21;
+ CFAL96x64x16WriteCommand(ui8LineBuf, 8);
+
+ //
+ // Use buffer of pixels to draw line, so multiple bytes can be sent at
+ // one time. Fill the buffer with the line color.
+ //
+ for(uIdx = 0; uIdx < sizeof(ui8LineBuf); uIdx++)
+ {
+ ui8LineBuf[uIdx] = ui32Value;
+ }
+
+ uIdx = (i32Y1 < i32Y2) ? (i32Y2 - i32Y1) : (i32Y1 - i32Y2);
+ uIdx += 1;
+ while(uIdx)
+ {
+ CFAL96x64x16WriteData(ui8LineBuf, (uIdx < 16) ? uIdx : 16);
+ uIdx -= (uIdx < 16) ? uIdx : 16;
+ }
+
+ //
+ // Restore horizontal address increment
+ //
+ ui8LineBuf[0] = 0xA0;
+ ui8LineBuf[1] = 0x20;
+ CFAL96x64x16WriteCommand(ui8LineBuf, 2);
+}
+
+//*****************************************************************************
+//
+//! Fills a rectangle.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param pRect is a pointer to the structure describing the rectangle.
+//! \param ui32Value is the color of the rectangle.
+//!
+//! This function fills a rectangle on the display. The coordinates of the
+//! rectangle are assumed to be within the extents of the display, and the
+//! rectangle specification is fully inclusive (in other words, both i16XMin and
+//! i16XMax are drawn, aint32_t with i16YMin and i16YMax).
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16RectFill(void *pvDisplayData, const tRectangle *pRect,
+ uint32_t ui32Value)
+{
+ unsigned int uY;
+
+ for(uY = pRect->i16YMin; uY <= pRect->i16YMax; uY++)
+ {
+ CFAL96x64x16LineDrawH(0, pRect->i16XMin, pRect->i16XMax, uY, ui32Value);
+ }
+}
+
+//*****************************************************************************
+//
+//! Translates a 24-bit RGB color to a display driver-specific color.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//! \param ui32Value is the 24-bit RGB color. The least-significant byte is the
+//! blue channel, the next byte is the green channel, and the third byte is the
+//! red channel.
+//!
+//! This function translates a 24-bit RGB color into a value that can be
+//! written into the display's frame buffer in order to reproduce that color,
+//! or the closest possible approximation of that color.
+//!
+//! \return Returns the display-driver specific color.
+//
+//*****************************************************************************
+static uint32_t
+CFAL96x64x16ColorTranslate(void *pvDisplayData, uint32_t ui32Value)
+{
+ //
+ // Translate from a 24-bit RGB color to a 3-3-2 RGB color.
+ //
+ return(DPYCOLORTRANSLATE(ui32Value));
+}
+
+//*****************************************************************************
+//
+//! Flushes any cached drawing operations.
+//!
+//! \param pvDisplayData is a pointer to the driver-specific data for this
+//! display driver.
+//!
+//! This functions flushes any cached drawing operations to the display. This
+//! is useful when a local frame buffer is used for drawing operations, and the
+//! flush would copy the local frame buffer to the display. Since no memory
+//! based frame buffer is used for this driver, the flush is a no operation.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CFAL96x64x16Flush(void *pvDisplayData)
+{
+ //
+ // There is nothing to be done.
+ //
+}
+
+//*****************************************************************************
+//
+//! The display structure that describes the driver for the Crystalfontz
+//! CFAL9664-F-B1 OLED panel with SSD 1332 controller.
+//
+//*****************************************************************************
+const tDisplay g_sCFAL96x64x16 =
+{
+ sizeof(tDisplay),
+ 0,
+ 96,
+ 64,
+ CFAL96x64x16PixelDraw,
+ CFAL96x64x16PixelDrawMultiple,
+ CFAL96x64x16LineDrawH,
+ CFAL96x64x16LineDrawV,
+ CFAL96x64x16RectFill,
+ CFAL96x64x16ColorTranslate,
+ CFAL96x64x16Flush
+};
+
+//*****************************************************************************
+//
+//! Initializes the display driver.
+//!
+//! This function initializes the SSD1332 display controller on the panel,
+//! preparing it to display data.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+CFAL96x64x16Init(void)
+{
+ tRectangle sRect;
+
+ //
+ // Enable the peripherals used by this driver
+ //
+ ROM_SysCtlPeripheralEnable(DISPLAY_SSI_PERIPH);
+ ROM_SysCtlPeripheralEnable(DISPLAY_SSI_GPIO_PERIPH);
+ ROM_SysCtlPeripheralEnable(DISPLAY_RST_GPIO_PERIPH);
+
+ //
+ // Select the SSI function for the appropriate pins
+ //
+ ROM_GPIOPinConfigure(DISPLAY_PINCFG_SSICLK);
+ ROM_GPIOPinConfigure(DISPLAY_PINCFG_SSIFSS);
+ ROM_GPIOPinConfigure(DISPLAY_PINCFG_SSITX);
+
+
+ //
+ // Configure the pins for the SSI function
+ //
+ ROM_GPIOPinTypeSSI(DISPLAY_SSI_PORT, DISPLAY_SSI_PINS);
+
+ //
+ // Configure display control pins as GPIO output
+ //
+ ROM_GPIOPinTypeGPIOOutput(DISPLAY_RST_PORT, DISPLAY_RST_PIN);
+ ROM_GPIOPinTypeGPIOOutput(DISPLAY_ENV_PORT, DISPLAY_ENV_PIN);
+ ROM_GPIOPinTypeGPIOOutput(DISPLAY_D_C_PORT, DISPLAY_D_C_PIN);
+
+ //
+ // Reset pin high, power off
+ //
+ ROM_GPIOPinWrite(DISPLAY_RST_PORT, DISPLAY_RST_PIN, DISPLAY_RST_PIN);
+ ROM_GPIOPinWrite(DISPLAY_ENV_PORT, DISPLAY_ENV_PIN, 0);
+ ROM_SysCtlDelay(1000);
+
+ //
+ // Drive the reset pin low while we do other stuff
+ //
+ ROM_GPIOPinWrite(DISPLAY_RST_PORT, DISPLAY_RST_PIN, 0);
+
+ //
+ // Configure the SSI port
+ //
+ ROM_SSIDisable(DISPLAY_SSI_BASE);
+ ROM_SSIConfigSetExpClk(DISPLAY_SSI_BASE, ROM_SysCtlClockGet(),
+ SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER,
+ DISPLAY_SSI_CLOCK, 8);
+ ROM_SSIEnable(DISPLAY_SSI_BASE);
+
+ //
+ // Take the display out of reset
+ //
+ ROM_SysCtlDelay(1000);
+ ROM_GPIOPinWrite(DISPLAY_RST_PORT, DISPLAY_RST_PIN, DISPLAY_RST_PIN);
+ ROM_SysCtlDelay(1000);
+
+ //
+ // Enable display power supply
+ //
+ ROM_GPIOPinWrite(DISPLAY_ENV_PORT, DISPLAY_ENV_PIN, DISPLAY_ENV_PIN);
+ ROM_SysCtlDelay(1000);
+
+ //
+ // Send the initial configuration command bytes to the display
+ //
+ CFAL96x64x16WriteCommand(g_ui8DisplayInitCommands,
+ sizeof(g_ui8DisplayInitCommands));
+ ROM_SysCtlDelay(1000);
+
+ //
+ // Fill the entire display with a black rectangle, to clear it.
+ //
+ sRect.i16XMin = 0;
+ sRect.i16XMax = 95;
+ sRect.i16YMin = 0;
+ sRect.i16YMax = 63;
+ CFAL96x64x16RectFill(0, &sRect, 0);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/boards/ek-lm4f232/drivers/cfal96x64x16.h b/boards/ek-lm4f232/drivers/cfal96x64x16.h
new file mode 100644
index 0000000..880be00
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/cfal96x64x16.h
@@ -0,0 +1,37 @@
+//*****************************************************************************
+//
+// cfal96x64x16.h - Prototypes for the Crystalfontz CFAL9664-F-B1 OLED display
+// with an SSD1332 controller.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#ifndef __CFAL96X64X16_H__
+#define __CFAL96X64X16_H__
+
+//*****************************************************************************
+//
+// Prototypes for the globals exported by this driver.
+//
+//*****************************************************************************
+extern void CFAL96x64x16Init(void);
+extern const tDisplay g_sCFAL96x64x16;
+
+#endif // __CFAL96X64X16_H__
diff --git a/boards/ek-lm4f232/drivers/slidemenuwidget.c b/boards/ek-lm4f232/drivers/slidemenuwidget.c
new file mode 100644
index 0000000..805b77b
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/slidemenuwidget.c
@@ -0,0 +1,1424 @@
+//*****************************************************************************
+//
+// slidemenuwidget.c - A sliding menu drawing widget.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "inc/hw_types.h"
+#include "driverlib/debug.h"
+#include "utils/uartstdio.h"
+#include "grlib/grlib.h"
+#include "grlib/widget.h"
+#include "slidemenuwidget.h"
+
+//*****************************************************************************
+//
+//! \addtogroup slidemenuwidget_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// This is a custom widget for drawing a menu system on the display. The
+// widget presents the menus using a "sliding" animation. The menu items
+// are shown in a vertical list, and as the user scrolls through the list
+// of menu items, the menu slides up and down the display. When a menu item
+// is selected to descend in the menu tree, the widget slides the old menu
+// off the to left while the new menu slides in from the right. Likewise,
+// going up in the menu tree, the higher level menu slides back onto the
+// screen from the left.
+//
+// Additional structures are provided to implement a menu, and menu items.
+// Each menu contains menu items, and each menu item can have a child menu.
+// These structures can be used to build a menu tree. The menu widget will
+// show one menu at any given time, the menu that is displayed on the screen.
+//
+// In addition to child menus, any menu item can have instead a child widget.
+// If this is used, then when the user selects a menu item, a new widget can
+// be activated to perform some function. When the function of the child
+// widget completes, then the widget slides back off the screen (to the right)
+// and the parent menu is displayed again.
+//
+// A given menu can have menu items that are individually selectable or
+// multiple-selectable. For individually selectable menu items, the item
+// is selected by leaving the menu with the focus on the selected item. For
+// example navigating down to a submenu with choices A, B and C, and then
+// navigating until the focus is on item B will cause item B to be selected.
+// The menu will remember that item B was selected even when navigating away
+// from that menu.
+//
+// If a menu is configured to be multiple-selectable, then each menu item has
+// a check box that is checked by pressing the select button. When the item
+// is selected the box will show an X. Any or all or none can be selected in
+// this way. When a menu is configured to be multi-selectable, the menu items
+// cannot have any child menus or widgets.
+//
+// The menu widget provides some visual clues to the user about how to
+// navigate the menu tree. Whenever a menu item has a child menu or child
+// widget, then a small right arrow is shown on the right side of the menu
+// item that has the focus. This tells the user to press the "right" button
+// to descend to the next menu or widget. When it is possible to go up a
+// level in the menu tree (when showing a child menu), a small left arrow
+// will be shown on the menu item with the focus. This is an indication to the
+// user that they should press the "left" button.
+//
+// This widget is meant to work with key/button presses. It expects there
+// to be up/down/left/right and select buttons. The widget will need to be
+// modified in order to work with a pointer input.
+//
+// In order to perform the sliding animation, the menu widget requires that
+// it be provided with two off-screen displays. The menu widget renders the
+// two menus (the old and the new) into the two buffers, and then repeatedly
+// paints both to the physical display while adjusting the coordinates as
+// appropriate. This will cause the menus to appear animated and move across
+// the display. When the menus are being animated, the menu widget is taking
+// all the non-interrupt processor time in order to draw the buffers to the
+// display. This operation occurs in response to the widget processing of the
+// key/button events and will occur in the thread that calls
+// WidgetMessageQueueProcess(). The programmer should be aware of this
+// processing burden when designing an application that uses the sliding
+// menu widget.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// A graphics image of a small right arrow icon.
+//
+//*****************************************************************************
+const uint8_t g_ui8RtArrow[] =
+{
+ IMAGE_FMT_1BPP_UNCOMP,
+ 4, 0,
+ 8, 0,
+
+ 0x80,
+ 0xC0,
+ 0xE0,
+ 0xF0,
+ 0xE0,
+ 0xC0,
+ 0x80,
+ 0
+};
+
+//*****************************************************************************
+//
+// A graphics image of a small left arrow icon.
+//
+//*****************************************************************************
+const uint8_t g_ui8LtArrow[] =
+{
+ IMAGE_FMT_1BPP_UNCOMP,
+ 4, 0,
+ 8, 0,
+
+ 0x10,
+ 0x30,
+ 0x70,
+ 0xF0,
+ 0x70,
+ 0x30,
+ 0x10,
+ 0
+};
+
+//*****************************************************************************
+//
+// A graphics image of a small unchecked box icon.
+//
+//*****************************************************************************
+const uint8_t g_ui8Unchecked[] =
+{
+ IMAGE_FMT_1BPP_UNCOMP,
+ 7, 0,
+ 8, 0,
+
+ 0xFE,
+ 0x82,
+ 0x82,
+ 0x82,
+ 0x82,
+ 0x82,
+ 0xFE,
+ 0
+};
+
+//*****************************************************************************
+//
+// A graphics image of a small checked box icon.
+//
+//*****************************************************************************
+const uint8_t g_ui8Checked[] =
+{
+ IMAGE_FMT_1BPP_UNCOMP,
+ 7, 0,
+ 8, 0,
+
+ 0xFE,
+ 0xC6,
+ 0xAA,
+ 0x92,
+ 0xAA,
+ 0xC6,
+ 0xFE,
+ 0
+};
+
+//*****************************************************************************
+//
+//! Draws the current menu into a drawing context, off-screen buffer.
+//!
+//! \param psMenuWidget points at the SlideMenuWidget being processed.
+//! \param psContext points to the context where all drawing should be done.
+//! \param i32OffsetY is the Y offset for drawing the menu.
+//!
+//! This function renders a menu (set of menu items), into a drawing context.
+//! It assumes that the drawing context is an off-screen buffer, and that
+//! the entire buffer belongs to this widget. The vertical position of the
+//! menu can be adjusted by using the parameter i32OffsetY. This value can be
+//! positive or negative and can cause the menu to be rendered above or below
+//! the normal position in the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SlideMenuDraw(tSlideMenuWidget *psMenuWidget, tContext *psContext,
+ int32_t i32OffsetY)
+{
+ tSlideMenu *psMenu;
+ uint32_t ui32Idx;
+ tRectangle sRect;
+
+ //
+ // Check the arguments
+ //
+ ASSERT(psMenuWidget);
+ ASSERT(psContext);
+
+ //
+ // Set the foreground color for the rectangle fill to match what we want
+ // as the menu background.
+ //
+ GrContextForegroundSet(psContext, psMenuWidget->ui32ColorBackground);
+ GrRectFill(psContext, &psContext->sClipRegion);
+
+ //
+ // Get the current menu that is being displayed
+ //
+ psMenu = psMenuWidget->psSlideMenu;
+
+ //
+ // Set the foreground to the color we want for the menu item boundaries
+ // and text color, text font.
+ //
+ GrContextForegroundSet(psContext, psMenuWidget->ui32ColorForeground);
+ GrContextFontSet(psContext, psMenuWidget->psFont);
+
+ //
+ // Set the rectangle bounds for the first menu item.
+ // The starting Y value is calculated based on which menu item is currently
+ // centered. Y coordinates are subtracted to find the Y start location
+ // of the first menu item, which could even be off the display.
+ //
+ // Set the X coords of the menu item to the extents of the display
+ //
+ sRect.i16XMin = 0;
+ sRect.i16XMax = psContext->sClipRegion.i16XMax;
+
+ //
+ // Find the Y coordinate of the centered menu item
+ //
+ sRect.i16YMin = (psContext->psDisplay->ui16Height / 2) -
+ (psMenuWidget->ui32MenuItemHeight / 2);
+
+ //
+ // Adjust to find Y coordinate of first menu item
+ //
+ sRect.i16YMin -= psMenu->ui32CenterIndex * psMenuWidget->ui32MenuItemHeight;
+
+ //
+ // Now adjust for the offset that was passed in by caller. This allows
+ // for drawing menu items above or below the main display.
+ //
+ sRect.i16YMin += i32OffsetY;
+
+ //
+ // Find the ending Y coordinate of first menu item
+ //
+ sRect.i16YMax = sRect.i16YMin + psMenuWidget->ui32MenuItemHeight - 1;
+
+ //
+ // Start the index at the first menu item. It is possible that this
+ // menu item is off the display.
+ //
+ ui32Idx = 0;
+
+ //
+ // Loop through all menu items, drawing on the display. Note that some
+ // may not be on the screen, but they will be clipped.
+ //
+ while(ui32Idx < psMenu->ui32Items)
+ {
+ //
+ // If this index is the one that is highlighted, then change the
+ // background
+ //
+ if(ui32Idx == psMenu->ui32FocusIndex)
+ {
+ //
+ // Set the foreground to the highlight color, and fill the
+ // rectangle of the background of this menu item.
+ //
+ GrContextForegroundSet(psContext, psMenuWidget->ui32ColorHighlight);
+ GrRectFill(psContext, &sRect);
+
+ //
+ // Set the new foreground to the normal foreground color, and
+ // set the background to the highlight color. This is so
+ // remaining drawing operations will have the correct background
+ // and foreground colors for this highlighted menu item cell.
+ //
+ GrContextForegroundSet(psContext, psMenuWidget->ui32ColorForeground);
+ GrContextBackgroundSet(psContext, psMenuWidget->ui32ColorHighlight);
+
+ //
+ // If this menu has a parent, then draw a left arrow icon on the
+ // focused menu item.
+ //
+ if(psMenu->psParent)
+ {
+ GrImageDraw(psContext, g_ui8LtArrow, sRect.i16XMin + 4,
+ sRect.i16YMin +
+ (psMenuWidget->ui32MenuItemHeight / 2) - 4);
+ }
+
+ //
+ // If this menu has a child menu or child widget, then draw a
+ // right arrow icon on the focused menu item.
+ //
+ if(psMenu->psSlideMenuItems[ui32Idx].psChildMenu ||
+ psMenu->psSlideMenuItems[ui32Idx].psChildWidget)
+ {
+ GrImageDraw(psContext, g_ui8RtArrow, sRect.i16XMax - 8,
+ sRect.i16YMin +
+ (psMenuWidget->ui32MenuItemHeight / 2) - 4);
+ }
+ }
+
+ //
+ // Otherwise this is a normal, non-highlighted menu item cell,
+ // so set the normal background color.
+ //
+ else
+ {
+ GrContextBackgroundSet(psContext, psMenuWidget->ui32ColorBackground);
+ }
+
+ //
+ // If the current menu is multi-selectable, then draw a checkbox on
+ // the menu item. Draw a checked or unchecked box depending on whether
+ // the item has been selected.
+ //
+ if(psMenu->bMultiSelectable)
+ {
+ if(psMenu->ui32SelectedFlags & (1 << ui32Idx))
+ {
+ GrImageDraw(psContext, g_ui8Checked, sRect.i16XMax - 12,
+ sRect.i16YMin +
+ (psMenuWidget->ui32MenuItemHeight / 2) - 4);
+ }
+ else
+ {
+ GrImageDraw(psContext, g_ui8Unchecked, sRect.i16XMax - 12,
+ sRect.i16YMin +
+ (psMenuWidget->ui32MenuItemHeight / 2) - 4);
+ }
+
+ }
+
+ //
+ // Draw the rectangle representing the menu item
+ //
+ GrRectDraw(psContext, &sRect);
+
+ //
+ // Draw the text for this menu item in the middle of the menu item
+ // rectangle (cell).
+ //
+ GrStringDrawCentered(psContext,
+ psMenu->psSlideMenuItems[ui32Idx].pcText,
+ -1,
+ psMenuWidget->sBase.psDisplay->ui16Width / 2,
+ sRect.i16YMin + \
+ (psMenuWidget->ui32MenuItemHeight / 2) - 1, 0);
+
+ //
+ // Advance to the next menu item, and update the menu item rectangle
+ // bounds to the next position
+ //
+ ui32Idx++;
+ sRect.i16YMin += psMenuWidget->ui32MenuItemHeight;
+ sRect.i16YMax += psMenuWidget->ui32MenuItemHeight;
+
+ //
+ // Note that this may attempt to render menu items that run off the
+ // bottom of the drawing area, but these will just be clipped and a
+ // little bit of processing time is wasted.
+ //
+ }
+}
+
+//*****************************************************************************
+//
+//! Paints a menu, menu items on a display.
+//!
+//! \param psWidget is a pointer to the slide menu widget to be drawn.
+//!
+//! This function draws the contents of a slide menu on the display. This is
+//! called in response to a \b WIDGET_MSG_PAINT message.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+SlideMenuPaint(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tContext sContext;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+
+ //
+ // If this widget has a child widget, that means that the menu has
+ // slid off the screen and the child widget is in control. Therefore
+ // there is nothing to paint here. Just exit and the child widget will
+ // be painted.
+ //
+ if(psWidget->psChild)
+ {
+ return;
+ }
+
+ //
+ // Convert the generic widget pointer into a slide menu widget pointer,
+ // and get a pointer to its context.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Render the menu into the off-screen buffer, using normal vertical
+ // position.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Now copy the rendered menu into the physical display. This will show
+ // the menu on the display.
+ //
+ GrImageDraw(&sContext, psMenuWidget->psDisplayA->pvDisplayData,
+ psWidget->sPosition.i16XMin, psWidget->sPosition.i16YMin);
+}
+
+//*****************************************************************************
+//
+//! Performs the sliding menu operation, in response to the "down" button.
+//!
+//! \param psWidget is a pointer to the slide menu widget to move down.
+//!
+//! This function will respond to the "down" key/button event. The down
+//! button is used to select the next menu item down the list, and the effect
+//! is that the menu itself slides up, leaving the highlighted menu item
+//! in the middle of the screen.
+//!
+//! This function repeatedly draws the menu onto the display until the sliding
+//! animation is finished and will not return to the caller until then. This
+//! function is usually called from the thread context of
+//! WidgetMessageQueueProcess().
+//!
+//! \return Returns a non-zero value if the menu was moved or was not moved
+//! because it is already at the last position. If a child widget is active
+//! then this function does nothing and returns a 0.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuDown(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tSlideMenu *psMenu;
+ tContext sContext;
+ uint32_t ui32MenuHeight;
+ uint32_t ui32Y;
+
+ //
+ // If this menu widget has a child widget, that means the child widget
+ // is in control of the display, and there is nothing to do here.
+ //
+ if(psWidget->psChild)
+ {
+ return(0);
+ }
+
+ //
+ // Get handy pointers to the menu widget, and the menu that is currently
+ // displayed.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+ psMenu = psMenuWidget->psSlideMenu;
+
+ //
+ // If we are already at the end of the list of menu items, then there
+ // is nothing else to do.
+ //
+ if(psMenu->ui32FocusIndex >= (psMenu->ui32Items - 1))
+ {
+ return(1);
+ }
+
+ //
+ // Increment focus menu item. This has the effect of selecting the next
+ // menu item in the list.
+ //
+ psMenu->ui32FocusIndex++;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Render the menu into the off-screen buffer. This will be the same
+ // menu appearance as before, except the highlighted item has changed
+ // to the next menu item down.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Draw a continuation of this menu in the second offscreen buffer.
+ // This is the part of the menu that would be drawn if the display were
+ // twice as tall. We are effectively creating a virtual display that is
+ // twice as tall as the physical display.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayB);
+ SlideMenuDraw(psMenuWidget, &sContext, -1 *
+ (psMenuWidget->sBase.sPosition.i16YMax -
+ psMenuWidget->sBase.sPosition.i16YMin));
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Get the height of the displayed part of the menu.
+ //
+ ui32MenuHeight = psMenuWidget->psDisplayA->ui16Height;
+
+ //
+ // Now copy the rendered menu into the physical display
+ //
+ // Iterate over the Y displacement of one menu item cell. This loop
+ // will repeatedly draw both off screen buffers to the physical display,
+ // adjusting the position of each by one pixel each time it is drawn. Each
+ // time the offset is changed so that both buffers are drawn one higher
+ // than the previous time. This will have the effect of "sliding" the
+ // entire menu up by the height of one menu item cell.
+ // The speed of the animation is controlled entirely by the speed of the
+ // processor and the speed of the interface to the physical display.
+ //
+ for(ui32Y = 0; ui32Y <= psMenuWidget->ui32MenuItemHeight; ui32Y++)
+ {
+ GrImageDraw(&sContext, psMenuWidget->psDisplayA->pvDisplayData,
+ psWidget->sPosition.i16XMin,
+ psWidget->sPosition.i16YMin - ui32Y);
+ GrImageDraw(&sContext, psMenuWidget->psDisplayB->pvDisplayData,
+ psWidget->sPosition.i16XMin,
+ psWidget->sPosition.i16YMin + ui32MenuHeight - ui32Y);
+ }
+
+ //
+ // Increment centered menu item. This will now match the menu item with
+ // the focus. When the menu is repainted again, the newly selected
+ // menu item will be centered and highlighted.
+ //
+ psMenu->ui32CenterIndex = psMenu->ui32FocusIndex;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Render the menu into the off-screen buffer. This will be the same
+ // menu appearance as before, except the highlighted item has changed
+ // to the next menu item down. Now when a repaint occurs the menu
+ // will be redrawn with the newly highlighted menu item.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Return indication that we handled the key event.
+ //
+ return(1);
+}
+
+//*****************************************************************************
+//
+//! Performs the sliding menu operation, in response to the "up" button.
+//!
+//! \param psWidget is a pointer to the slide menu widget to move up.
+//!
+//! This function will respond to the "up" key/button event. The up
+//! button is used to select the previous menu item down the list, and the
+//! effect is that the menu itself slides down, leaving the highlighted menu
+//! item in the middle of the screen.
+//!
+//! This function repeatedly draws the menu onto the display until the sliding
+//! animation is finished and will not return to the caller until then. This
+//! function is usually called from the thread context of
+//! WidgetMessageQueueProcess().
+//!
+//! \return Returns a non-zero value if the menu was moved or was not moved
+//! because it is already at the first position. If a child widget is active
+//! then this function does nothing and returns a 0.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuUp(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tSlideMenu *psMenu;
+ tContext sContext;
+ uint32_t ui32MenuHeight;
+ uint32_t ui32Y;
+
+ //
+ // If this menu widget has a child widget, that means the child widget
+ // is in control of the display, and there is nothing to do here.
+ //
+ if(psWidget->psChild)
+ {
+ return(0);
+ }
+
+ //
+ // Get handy pointers to the menu widget, and the menu that is currently
+ // displayed.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+ psMenu = psMenuWidget->psSlideMenu;
+
+ //
+ // If we are already at the start of the list of menu items, then there
+ // is nothing else to do.
+ //
+ if(psMenu->ui32FocusIndex == 0)
+ {
+ return(1);
+ }
+
+ //
+ // Decrement the focus menu item. This has the effect of selecting the
+ // previous menu item in the list.
+ //
+ psMenu->ui32FocusIndex--;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Render the menu into the off-screen buffer. This will be the same
+ // menu appearance as before, except the highlighted item has changed
+ // to the previous menu item up.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Draw a continuation of this menu in the second offscreen buffer.
+ // This is the part of the menu that would be drawn above this menu if the
+ // display were twice as tall. We are effectively creating a virtual
+ // display that is twice as tall as the physical display.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayB);
+ SlideMenuDraw(psMenuWidget, &sContext,
+ (psMenuWidget->sBase.sPosition.i16YMax -
+ psMenuWidget->sBase.sPosition.i16YMin));
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Get the height of the displayed part of the menu.
+ //
+ ui32MenuHeight = psMenuWidget->psDisplayA->ui16Height;
+
+ //
+ // Now copy the rendered menu into the physical display
+ //
+ // Iterate over the Y displacement of one menu item cell. This loop
+ // will repeatedly draw both off screen buffers to the physical display,
+ // adjusting the position of each by one pixel each time it is drawn. Each
+ // time the offset is changed so that both buffers are drawn one lower
+ // than the previous time. This will have the effect of "sliding" the
+ // entire menu down by the height of one menu item cell.
+ // The speed of the animation is controlled entirely by the speed of the
+ // processor and the speed of the interface to the physical display.
+ //
+ for(ui32Y = 0; ui32Y <= psMenuWidget->ui32MenuItemHeight; ui32Y++)
+ {
+ GrImageDraw(&sContext, psMenuWidget->psDisplayB->pvDisplayData,
+ psWidget->sPosition.i16XMin,
+ psWidget->sPosition.i16YMin + ui32Y - ui32MenuHeight);
+ GrImageDraw(&sContext, psMenuWidget->psDisplayA->pvDisplayData,
+ psWidget->sPosition.i16XMin,
+ psWidget->sPosition.i16YMin + ui32Y);
+ }
+
+ //
+ // Decrement the centered menu item. This will now match the menu item
+ // with the focus. When the menu is repainted again, the newly selected
+ // menu item will be centered and highlighted.
+ //
+ psMenu->ui32CenterIndex = psMenu->ui32FocusIndex;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Render the menu into the off-screen buffer. This will be the same
+ // menu appearance as before, except the highlighted item has changed
+ // to the next menu item up. Now when a repaint occurs the menu
+ // will be redrawn with the newly highlighted menu item.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Return indication that we handled the key event.
+ //
+ return(1);
+}
+
+//*****************************************************************************
+//
+//! Performs the sliding menu operation, in response to the "right" button.
+//!
+//! \param psWidget is a pointer to the slide menu widget to move to the right.
+//!
+//! This function will respond to the "right" key/button event. The right
+//! button is used to select the next menu level below the current menu item,
+//! or a widget that is activated by the menu item. The effect is that the
+//! menu itself slides off to the left, and the new menu or widget slides in
+//! from the right.
+//!
+//! This function repeatedly draws the menu onto the display until the sliding
+//! animation is finished and will not return to the caller until then. This
+//! function is usually called from the thread context of
+//! WidgetMessageQueueProcess().
+//!
+//! \return Returns a non-zero value if the menu was moved or was not moved
+//! because it is already at the last position. If a child widget is active
+//! then this function does nothing and returns a 0.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuRight(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tSlideMenu *psMenu;
+ tSlideMenu *psChildMenu;
+ tContext sContext;
+ tWidget *psChildWidget;
+ uint32_t ui32X;
+ uint32_t ui32MenuWidth;
+
+ //
+ // If this menu widget has a child widget, that means the child widget
+ // is in control of the display, and there is nothing to do here.
+ //
+ if(psWidget->psChild)
+ {
+ return(0);
+ }
+
+ //
+ // Get handy pointers to the menu widget, and the current menu, and the
+ // child menu and widget if they exist.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+ psMenu = psMenuWidget->psSlideMenu;
+ psChildMenu = psMenu->psSlideMenuItems[psMenu->ui32FocusIndex].psChildMenu;
+ psChildWidget = psMenu->psSlideMenuItems[psMenu->ui32FocusIndex].psChildWidget;
+
+ //
+ // Initialize a context for the secondary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayB);
+
+ //
+ // Render the current menu into off-screen buffer B. This
+ // will be the same menu appearance as is already being shown.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Now set up context for drawing into off-screen buffer A
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+
+ //
+ // Process child menu of this menu item
+ //
+ if(psChildMenu)
+ {
+ //
+ // Switch the active menu for this SlideMenuWidget to be the child
+ // menu
+ //
+ psMenuWidget->psSlideMenu = psChildMenu;
+
+ //
+ // Draw the new (child) menu into off-screen buffer A
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+ }
+
+ //
+ // Process child widget of this menu item. This only happens if there
+ // is no child menu.
+ //
+ else if(psChildWidget)
+ {
+ //
+ // Call the widget activated callback function. This will notify
+ // the application that a child widget has been activated by the
+ // menu system.
+ //
+ if(psMenuWidget->pfnActive)
+ {
+ psMenuWidget->pfnActive(psChildWidget,
+ &psMenu->psSlideMenuItems[psMenu->ui32FocusIndex],
+ 1);
+ }
+
+ //
+ // Link the new child widget into this SlideMenuWidget so
+ // it appears as a child to this widget. Normally the menu widget
+ // has no child widget.
+ //
+ psWidget->psChild = psChildWidget;
+ psChildWidget->psParent = psWidget;
+
+ //
+ // Fill a rectangle with the new child widget background color.
+ // This is done in off-screen buffer A. When the menu slides off,
+ // it will be replaced by a blank background that will then be
+ // controlled by the new child widget.
+ //
+ GrContextForegroundSet(
+ &sContext,
+ psMenu->psSlideMenuItems[psMenu->ui32FocusIndex].ui32ChildWidgetColor);
+ GrRectFill(&sContext, &sContext.sClipRegion);
+
+ //
+ // Request a repaint for the child widget so it can draw itself once
+ // the menu slide is done.
+ //
+ WidgetPaint(psChildWidget);
+ }
+
+ //
+ // There is no child menu or child widget, so there is nothing to change
+ // on the display.
+ //
+ else
+ {
+ return(1);
+ }
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Get the width of the menu widget which is used in calculations below
+ //
+ ui32MenuWidth = psMenuWidget->psDisplayA->ui16Width;
+
+ //
+ // The following loop draws the two off-screen buffers onto the physical
+ // display using a right-to-left-wipe. This will provide an appearance
+ // of sliding to the left. The new child menu, or child widget background
+ // will slide in from the right. The "old" menu is being held in
+ // off-screen buffer B and the new one is in buffer A. So when we are
+ // done, the correct image will be in buffer A.
+ //
+ for(ui32X = 0; ui32X <= ui32MenuWidth; ui32X += 8)
+ {
+ GrImageDraw(&sContext, psMenuWidget->psDisplayB->pvDisplayData,
+ psWidget->sPosition.i16XMin - ui32X,
+ psWidget->sPosition.i16YMin);
+ GrImageDraw(&sContext, psMenuWidget->psDisplayA->pvDisplayData,
+ psWidget->sPosition.i16XMin + ui32MenuWidth - ui32X,
+ psWidget->sPosition.i16YMin);
+ }
+
+ //
+ // Return indication that we handled the key event.
+ //
+ return(1);
+}
+
+//*****************************************************************************
+//
+//! Performs the sliding menu operation, in response to the "left" button.
+//!
+//! \param psWidget is a pointer to the slide menu widget to move to the left.
+//!
+//! This function will respond to the "left" key/button event. The left
+//! button is used to ascend to the next menu up in the menu tree. The effect
+//! is that the current menu, or active widget, slides off to the right, while
+//! the parent menu slides in from the left.
+//!
+//! This function repeatedly draws the menu onto the display until the sliding
+//! animation is finished and will not return to the caller until then. This
+//! function is usually called from the thread context of
+//! WidgetMessageQueueProcess().
+//!
+//! \return Returns a non-zero value if the menu was moved or was not moved
+//! because it is already at the last position. If a child widget is active
+//! then this function does nothing and returns a 0.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuLeft(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tSlideMenu *psMenu;
+ tSlideMenu *psParentMenu;
+ tContext sContext;
+ uint32_t ui32X;
+ uint32_t ui32MenuWidth;
+
+ //
+ // Get handy pointers to the menu widget and active menu, and the parent
+ // menu if there is one.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+ psMenu = psMenuWidget->psSlideMenu;
+ psParentMenu = psMenu->psParent;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayB);
+
+ //
+ // If this widget has a child, that means that the child widget is in
+ // control, and we are requested to go back to the previous menu item.
+ // Process the child widget.
+ //
+ if(psWidget->psChild)
+ {
+ //
+ // Call the widget de-activated callback function. This notifies the
+ // application that the widget is being deactivated.
+ //
+ if(psMenuWidget->pfnActive)
+ {
+ psMenuWidget->pfnActive(psWidget->psChild,
+ &psMenu->psSlideMenuItems[psMenu->ui32FocusIndex],
+ 0);
+ }
+
+ //
+ // Unlink the child widget from the slide menu widget. The menu
+ // widget will now no longer have a child widget.
+ //
+ psWidget->psChild->psParent = 0;
+ psWidget->psChild = 0;
+
+ //
+ // Fill a rectangle with the child widget background color. This will
+ // erase everything else that is shown on the widget but leave the
+ // background, which will make the change visually less jarring.
+ // This is done in off-screen buffer B, which is the buffer that is
+ // going to be slid off the screen.
+ //
+ GrContextForegroundSet(
+ &sContext,
+ psMenu->psSlideMenuItems[psMenu->ui32FocusIndex].ui32ChildWidgetColor);
+ GrRectFill(&sContext, &sContext.sClipRegion);
+ }
+
+ //
+ // Otherwise there is not a child widget in control, so process the parent
+ // menu, if there is one.
+ //
+ else if(psParentMenu)
+ {
+ //
+ // Render the current menu into the off-screen buffer B. This will be
+ // the same menu appearance that is currently on the display.
+ //
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Now switch the widget to the parent menu
+ //
+ psMenuWidget->psSlideMenu = psParentMenu;
+ }
+
+ //
+ // Otherwise, we are already at the top level menu and there is nothing
+ // else to do.
+ //
+ else
+ {
+ return(1);
+ }
+
+ //
+ // Draw the new menu in the second offscreen buffer. This is the menu
+ // that will be on the display when the animation is over.
+ //
+ GrContextInit(&sContext, psMenuWidget->psDisplayA);
+ SlideMenuDraw(psMenuWidget, &sContext, 0);
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Get the width of the menu widget.
+ //
+ ui32MenuWidth = psMenuWidget->psDisplayA->ui16Width;
+
+ //
+ // The following loop draws the two off-screen buffers onto the physical
+ // display using a left-to-right. This will provide an appearance
+ // of sliding to the right. The parent menu will slide in from the left.
+ // The "old" child menu is being held in off-screen buffer B and the new
+ // one is in buffer A. So when we are done, the correct image will be in
+ // buffer A.
+ //
+ for(ui32X = 0; ui32X <= ui32MenuWidth; ui32X += 8)
+ {
+ GrImageDraw(&sContext, psMenuWidget->psDisplayB->pvDisplayData,
+ psWidget->sPosition.i16XMin + ui32X,
+ psWidget->sPosition.i16YMin);
+ GrImageDraw(&sContext, psMenuWidget->psDisplayA->pvDisplayData,
+ psWidget->sPosition.i16XMin + ui32X - ui32MenuWidth,
+ psWidget->sPosition.i16YMin);
+ }
+
+ //
+ // Return indication that we handled the key event.
+ //
+ return(1);
+}
+
+//*****************************************************************************
+//
+//! Handles menu selection, in response to the "select" button.
+//!
+//! \param psWidget is a pointer to the slide menu widget to use for a
+//! select operation.
+//!
+//! This function will allow for checking or unchecking multi-selectable
+//! menu items. If the menu does not allow multiple selection, then it
+//! treats it as a "right" button press.
+//!
+//! \return Returns a non-zero value if the key was handled. Returns 0 if the
+//! key was not handled.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuClick(tWidget *psWidget)
+{
+ tSlideMenuWidget *psMenuWidget;
+ tSlideMenu *psMenu;
+
+ //
+ // If a child widget is in control then there is nothing to do.
+ //
+ if(psWidget->psChild)
+ {
+ return(0);
+ }
+
+ //
+ // Get handy pointers to the menu widget and current menu.
+ //
+ psMenuWidget = (tSlideMenuWidget *)psWidget;
+ psMenu = psMenuWidget->psSlideMenu;
+
+ //
+ // Check to see if this menu allows multiple selection.
+ //
+ if(psMenu->bMultiSelectable)
+ {
+ //
+ // Toggle the selection status of the currently highlighted menu
+ // item, and then repaint it.
+ //
+ psMenu->ui32SelectedFlags ^= 1 << psMenu->ui32FocusIndex;
+ SlideMenuPaint(psWidget);
+
+ //
+ // We are done so return indication that we handled the key event.
+ //
+ return(1);
+ }
+
+ //
+ // Otherwise, treat the select button the same as a right button.
+ //
+ return(SlideMenuRight(psWidget));
+}
+
+//*****************************************************************************
+//
+//! Process key/button event to decide how to move the sliding menu.
+//!
+//! \param psWidget is a pointer to the slide menu widget to process.
+//! \param ui32Msg is the message containing the key event.
+//!
+//! This function is used to specifically handle key events destined for the
+//! slide menu widget. It decides which menu movement function should be
+//! called for each key event.
+//!
+//! \return Returns an indication if the key was handled. Non-zero if the
+//! key event was handled or else 0.
+//
+//*****************************************************************************
+static int32_t
+SlideMenuMove(tWidget *psWidget, uint32_t ui32Msg)
+{
+ //
+ // Process the key event.
+ //
+ switch(ui32Msg)
+ {
+ //
+ // User presses select button.
+ //
+ case WIDGET_MSG_KEY_SELECT:
+ {
+ return(SlideMenuClick(psWidget));
+ }
+
+ //
+ // User presses up button.
+ //
+ case WIDGET_MSG_KEY_UP:
+ {
+ return(SlideMenuUp(psWidget));
+ }
+
+ //
+ // User presses down button.
+ //
+ case WIDGET_MSG_KEY_DOWN:
+ {
+ return(SlideMenuDown(psWidget));
+ }
+
+ //
+ // User presses left button.
+ //
+ case WIDGET_MSG_KEY_LEFT:
+ {
+ return(SlideMenuLeft(psWidget));
+ }
+
+ //
+ // User presses right button.
+ //
+ case WIDGET_MSG_KEY_RIGHT:
+ {
+ return(SlideMenuRight(psWidget));
+ }
+
+ //
+ // This is an unexpected event. Return an indication that the event
+ // was not handled.
+ //
+ default:
+ {
+ return(0);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Handles messages for a slide menu widget.
+//!
+//! \param psWidget is a pointer to the slide menu widget.
+//! \param ui32Msg is the message.
+//! \param ui32Param1 is the first parameter to the message.
+//! \param ui32Param2 is the second parameter to the message.
+//!
+//! This function receives messages intended for this slide menu widget and
+//! processes them accordingly. The processing of the message varies based on
+//! the message in question.
+//!
+//! Unrecognized messages are handled by calling WidgetDefaultMsgProc().
+//!
+//! \return Returns a value appropriate to the supplied message.
+//
+//*****************************************************************************
+int32_t
+SlideMenuMsgProc(tWidget *psWidget, uint32_t ui32Msg, uint32_t ui32Param1,
+ uint32_t ui32Param2)
+{
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+
+ //
+ // Determine which message is being sent.
+ //
+ switch(ui32Msg)
+ {
+ //
+ // The widget paint request has been sent.
+ //
+ case WIDGET_MSG_PAINT:
+ {
+ //
+ // Handle the widget paint request.
+ //
+ SlideMenuPaint(psWidget);
+
+ //
+ // Return one to indicate that the message was successfully
+ // processed.
+ //
+ return(1);
+ }
+
+ //
+ // A key event has been received. By convention, this widget will
+ // process the key events if ui32Param1 is set to this widget.
+ // Otherwise a different widget has the "focus" for key events.
+ //
+ case WIDGET_MSG_KEY_SELECT:
+ case WIDGET_MSG_KEY_UP:
+ case WIDGET_MSG_KEY_DOWN:
+ case WIDGET_MSG_KEY_LEFT:
+ case WIDGET_MSG_KEY_RIGHT:
+ {
+ //
+ // If this key event is for us, then process the event.
+ //
+ if((tWidget *)ui32Param1 == psWidget)
+ {
+ return(SlideMenuMove(psWidget, ui32Msg));
+ }
+ }
+
+ //
+ // An unknown request has been sent. This widget does not handle
+ // pointer events, so they get dumped here if they occur.
+ //
+ default:
+ {
+ //
+ // Let the default message handler process this message.
+ //
+ return(WidgetDefaultMsgProc(psWidget, ui32Msg, ui32Param1,
+ ui32Param2));
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Initializes a slide menu widget.
+//!
+//! \param psWidget is a pointer to the slide menu widget to initialize.
+//! \param psDisplay is a pointer to the display on which to draw the menu.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param psDisplayOffA is one of two off-screen displays used for rendering.
+//! \param psDisplayOffB is one of two off-screen displays used for rendering.
+//! \param ui32ItemHeight is the height of a menu item
+//! \param ui32Foreground is the foreground color used for menu item boundaries
+//! and text.
+//! \param ui32Background is the background color of a menu item.
+//! \param ui32Highlight is the color of a highlighted menu item.
+//! \param psFont is a pointer to the font that should be used for text.
+//! \param psMenu is the initial menu to display
+//!
+//! This function initializes the caller provided slide menu widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SlideMenuInit(tSlideMenuWidget *psWidget, const tDisplay *psDisplay,
+ int32_t i32X, int32_t i32Y, int32_t i32Width, int32_t i32Height,
+ tDisplay *psDisplayOffA, tDisplay *psDisplayOffB,
+ uint32_t ui32ItemHeight, uint32_t ui32Foreground,
+ uint32_t ui32Background, uint32_t ui32Highlight,
+ tFont *psFont, tSlideMenu *psMenu)
+{
+ uint32_t ui32Idx;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+ ASSERT(psDisplay);
+ ASSERT(psDisplayOffA);
+ ASSERT(psDisplayOffB);
+ ASSERT(psFont);
+ ASSERT(psMenu);
+
+ //
+ // Clear out the widget structure.
+ //
+ for(ui32Idx = 0; ui32Idx < sizeof(tSlideMenuWidget); ui32Idx += 4)
+ {
+ ((uint32_t *)psWidget)[ui32Idx / 4] = 0;
+ }
+
+ //
+ // Set the size of the widget structure.
+ //
+ psWidget->sBase.i32Size = sizeof(tSlideMenuWidget);
+
+ //
+ // Mark this widget as fully disconnected.
+ //
+ psWidget->sBase.psParent = 0;
+ psWidget->sBase.psNext = 0;
+ psWidget->sBase.psChild = 0;
+
+ //
+ // Save the display pointer.
+ //
+ psWidget->sBase.psDisplay = psDisplay;
+
+ //
+ // Set the extents of the display area.
+ //
+ psWidget->sBase.sPosition.i16XMin = i32X;
+ psWidget->sBase.sPosition.i16YMin = i32Y;
+ psWidget->sBase.sPosition.i16XMax = i32X + i32Width - 1;
+ psWidget->sBase.sPosition.i16YMax = i32Y + i32Height - 1;
+
+ //
+ // Initialize the widget fields
+ //
+ psWidget->psDisplayA = psDisplayOffA;
+ psWidget->psDisplayB = psDisplayOffB;
+ psWidget->ui32MenuItemHeight = ui32ItemHeight;
+ psWidget->ui32ColorForeground = ui32Foreground;
+ psWidget->ui32ColorBackground = ui32Background;
+ psWidget->ui32ColorHighlight = ui32Highlight;
+ psWidget->psFont = psFont;
+ psWidget->psSlideMenu = psMenu;
+
+ //
+ // Use the slide menu message handler to process messages to this widget.
+ //
+ psWidget->sBase.pfnMsgProc = SlideMenuMsgProc;
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/boards/ek-lm4f232/drivers/slidemenuwidget.h b/boards/ek-lm4f232/drivers/slidemenuwidget.h
new file mode 100644
index 0000000..c7a1647
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/slidemenuwidget.h
@@ -0,0 +1,457 @@
+//*****************************************************************************
+//
+// slidemenuwidget.h - Prototypes for a sliding menu widget.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#ifndef __SLIDEMENUWIDGET_H__
+#define __SLIDEMENUWIDGET_H__
+
+//*****************************************************************************
+//
+//! \addtogroup slidemenuwidget_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! The structure that describes a menu item in the menu tree.
+//
+//*****************************************************************************
+typedef struct _SlideMenuItem
+{
+ //
+ //! A pointer to text to be rendered within the node.
+ //
+ char *pcText;
+
+ //
+ //! A child menu that is activated by this menu item, if any. Can be NULL.
+ //
+ struct _SlideMenu *psChildMenu;
+
+ //
+ //! A child widget that is activated by this menu item, if any. Can be
+ //! NULL. If both child menu and child widget are specified, the child
+ //! menu will be used.
+ //
+ tWidget *psChildWidget;
+
+ //
+ //! A color that is used when a child widget is activated. This is the
+ //! color that is used as a background when the menu slides off to make
+ //! the screen available for the child widget. By choosing this color to
+ //! match the background that is used in the child widget, the sliding
+ //! animation and widget painting appears smoother.
+ //
+ uint32_t ui32ChildWidgetColor;
+}
+tSlideMenuItem;
+
+//*****************************************************************************
+//
+//! The structure that describes a menu.
+//
+//*****************************************************************************
+typedef struct _SlideMenu
+{
+ //
+ //! The parent menu of this menu.
+ //
+ struct _SlideMenu *psParent;
+
+ //
+ //! The total number of items in this menu.
+ //
+ uint32_t ui32Items;
+
+ //
+ //! A pointer to the array of menu item structures.
+ //
+ tSlideMenuItem *psSlideMenuItems;
+
+ //
+ //! The menu item index of the item shown on the center of the screen.
+ //! Normally this is the same as the menu item that has the focus, but
+ //! can be different during the time when the menu is "sliding". When this
+ //! is 0, the first menu item is shown in the center of the screen and the
+ //! successive items are shown below it. When non-zero, then this menu
+ //! item is shown in the center, with preceding menu items shown above
+ //! and successive items shown below.
+ //
+ uint32_t ui32CenterIndex;
+
+ //
+ //! The menu item index that has the focus.
+ //
+ uint32_t ui32FocusIndex;
+
+ //
+ //! A flag to indicate if more than one menu item is selectable.
+ //
+ bool bMultiSelectable;
+
+ //
+ //! A set of bit flags to indicate which menu items are selected.
+ //
+ uint32_t ui32SelectedFlags;
+} tSlideMenu;
+
+//*****************************************************************************
+//
+//! The structure that describes a slide menu widget.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The generic widget information.
+ //
+ tWidget sBase;
+
+ //
+ //! A pointer to an off-screen display that is used for rendering the
+ //! menus prior to showing on the widget's area of the screen. There
+ //! are two off-screen displays. Each should be the size of the widget
+ //! area. The palette should include any colors that are used by this
+ //! widget.
+ //
+ tDisplay *psDisplayA;
+
+ //
+ //! A pointer to a second off-screen display.
+ //
+ tDisplay *psDisplayB;
+
+ //
+ //! The height, in pixels, of a single menu item (a cell).
+ //
+ uint32_t ui32MenuItemHeight;
+
+ //
+ //! The color used for drawing menu item cell boundaries and text.
+ //
+ uint32_t ui32ColorForeground;
+
+ //
+ //! The background color of menu item cells.
+ //
+ uint32_t ui32ColorBackground;
+
+ //
+ //! The color of a highlighted menu item.
+ //
+ uint32_t ui32ColorHighlight;
+
+ //
+ //! The font to use for menu text.
+ //
+ const tFont *psFont;
+
+ //
+ //! The current menu to display.
+ //
+ tSlideMenu *psSlideMenu;
+
+ //
+ // A function to call when a child widget becomes active or inactive
+ //
+ void (*pfnActive)(tWidget *psWidget, tSlideMenuItem *psMenuItem,
+ bool bActivated);
+}
+tSlideMenuWidget;
+
+//*****************************************************************************
+//
+//! Declares an initialized slide menu widget data structure.
+//!
+//! \param pParent is a pointer to the parent widget.
+//! \param pNext is a pointer to the sibling widget.
+//! \param pChild is a pointer to the first child widget.
+//! \param pDisplay is a pointer to the off-screen display on which to draw.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param psDisplayA is one of two off-screen displays for rendering menus.
+//! \param psDisplayB is one of two off-screen displays for rendering menus.
+//! \param ui32MenuItemHeight is the height of a menu item.
+//! \param ui32Foreground is the foreground color for menu item boundaries and
+//! text.
+//! \param ui32Background is the background color of the menu items.
+//! \param ui32Highlight is the color of a highlighted menu item.
+//! \param psFont is the font to use for the menu text.
+//! \param psMenu is the initial menu to display.
+//! \param pfnWidgetActive is a pointer to a function that will be called when
+//! a child widget is activated or deactivated.
+//!
+//! This macro provides an initialized slide menu widget data structure, which
+//! can be used to construct the widget tree at compile time in global variables
+//! (as opposed to run-time via function calls). This must be assigned to a
+//! variable, such as:
+//!
+//! \verbatim
+//! tSlideMenuWidget g_i16SlideMenu = SlideMenuStruct(...);
+//! \endverbatim
+//!
+//! Or, in an array of variables:
+//!
+//! \verbatim
+//! tSlideMenuWidget g_pi16SlideMenu[] =
+//! {
+//! SlideMenuStruct(...),
+//! SlideMenuStruct(...)
+//! };
+//! \endverbatim
+//!
+//! \return Nothing; this is not a function.
+//
+//*****************************************************************************
+#define SlideMenuStruct(pParent, pNext, pChild, pDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ psDisplayA, psDisplayB, \
+ ui32MenuItemHeight, ui32Foreground, ui32Background, \
+ ui32Highlight, psFont, psMenu, pfnWidgetActive) \
+ { \
+ { \
+ sizeof(tSlideMenuWidget), \
+ (tWidget *)(pParent), \
+ (tWidget *)(pNext), \
+ (tWidget *)(pChild), \
+ pDisplay, \
+ { \
+ i32X, \
+ i32Y, \
+ (i32X) + (i32Width) - 1, \
+ (i32Y) + (i32Height) - 1 \
+ }, \
+ SlideMenuMsgProc \
+ }, \
+ psDisplayA, \
+ psDisplayB, \
+ ui32MenuItemHeight, \
+ ui32Foreground, \
+ ui32Background, \
+ ui32Highlight, \
+ psFont, \
+ psMenu, \
+ pfnWidgetActive \
+ }
+
+//*****************************************************************************
+//
+//! Declares an initialized variable containing a slide menu widget data
+//! structure.
+//!
+//! \param i16Name is the name of the variable to be declared.
+//! \param pParent is a pointer to the parent widget.
+//! \param pNext is a pointer to the sibling widget.
+//! \param pChild is a pointer to the first child widget.
+//! \param pDisplay is a pointer to the off-screen display on which to draw.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param psDisplayA is one of two off-screen displays for rendering menus.
+//! \param psDisplayB is one of two off-screen displays for rendering menus.
+//! \param ui32MenuItemHeight is the height of a menu item.
+//! \param ui32Foreground is the foreground color for menu item boundaries and
+//! text.
+//! \param ui32Background is the background color of the menu items.
+//! \param ui32Highlight is the color of a highlighted menu item.
+//! \param psFont is the font to use for the menu text.
+//! \param psMenu is the initial menu to display.
+//! \param pfnWidgetActive is a pointer to a function that will be called when
+//! a child widget is activated or deactivated.
+//!
+//! This macro declares a variable containing an initialized slide menu widget
+//! data structure, which can be used to construct the widget tree at compile
+//! time in global variables (as opposed to run-time via function calls).
+//!
+//! \return Nothing; this is not a function.
+//
+//*****************************************************************************
+#define SlideMenu(i16Name, pParent, pNext, pChild, pDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ psDisplayA, psDisplayB, \
+ ui32MenuItemHeight, ui32Foreground, ui32Background, \
+ ui32Highlight, psFont, psMenu, pfnWidgetActive) \
+ tSlideMenuWidget i16Name = \
+ SlideMenuStruct(pParent, pNext, pChild, pDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ psDisplayA, psDisplayB, \
+ ui32MenuItemHeight, ui32Foreground, ui32Background,\
+ ui32Highlight, psFont, psMenu, pfnWidgetActive)
+
+//*****************************************************************************
+//
+//! Sets the active menu of the slide menu widget.
+//!
+//! \param psSlideMenuWidget is a pointer to the slide menu widget to modify.
+//! \param psMenu is the new slide menu to make active.
+//!
+//! This function sets the active menu for the widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define SlideMenuMenuSet(psSlideMenuWidget, psMenu) \
+ do \
+ { \
+ (psSlideMenuWidget)->psSlideMenu = (psMenu); \
+ } while(0)
+
+//*****************************************************************************
+//
+//! Sets the active callback function for a slide menu widget.
+//!
+//! \param psSlideMenuWidget is a pointer to the slide menu widget to modify.
+//! \param pfnActivated is a function pointer to the function that should
+//! be called when the menu system activates or deactivates a child widget.
+//!
+//! This function sets the child widget active callback function.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define SlideMenuActiveCallbackSet(psSlideMenuWidget, pfnActivated) \
+ do \
+ { \
+ (psSlideMenuWidget)->pfnActive = (pfnActivated); \
+ } while(0)
+
+//*****************************************************************************
+//
+//! Gets the index of the menu item that has the focus.
+//!
+//! \param psSlideMenu is a pointer to the menu to query for item index.
+//!
+//! This function returns the index of the menu item that has the focus for
+//! the specified menu.
+//!
+//! \return Index of the menu item that has the focus.
+//
+//*****************************************************************************
+#define SlideMenuFocusItemGet(psSlideMenu) \
+ ((psSlideMenu)->ui32FocusIndex)
+
+//*****************************************************************************
+//
+//! Gets the selected items mask for a menu.
+//!
+//! \param psSlideMenu is a pointer to the menu to query for selected items.
+//!
+//! This function returns a value that is a bit mask of any menu items that
+//! are selected in the current menu. This is meant to work when a menu is
+//! configured to be selectable. Then multiple menu items can be selected and
+//! the selection mask indicates which are selected.
+//!
+//! \return Selection bit mask of selected menu items.
+//
+//*****************************************************************************
+#define SlideMenuSelectedGet(psSlideMenu) \
+ ((psSlideMenu)->ui32SelectedFlags)
+
+//*****************************************************************************
+//
+//! Sets the focus item index for a menu.
+//!
+//! \param psSlideMenu is a pointer to the menu to set the focus item.
+//! \param ui32Focus is the index of the menu item that should have the focus.
+//!
+//! This function is used to specify which menu item should have the focus.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define SlideMenuFocusItemSet(psSlideMenu, ui32Focus) \
+ do \
+ { \
+ (psSlideMenu)->ui32FocusIndex = (ui32Focus); \
+ (psSlideMenu)->ui32CenterIndex = (ui32Focus); \
+ } while(0)
+
+//*****************************************************************************
+//
+//! Sets the selected items bit mask for a menu.
+//!
+//! \param psSlideMenu is a pointer to the menu to set the selection mask.
+//! \param ui32Selected is a bit mask indicating which menu items should be
+//! marked as selected.
+//!
+//! This function is used to specify which menu items are pre-selected.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define SlideMenuSelectedSet(psSlideMenu, ui32Selected) \
+ do \
+ { \
+ (psSlideMenu)->ui32SelectedFlags = (ui32Selected); \
+ } while(0)
+
+//*****************************************************************************
+//
+// Prototypes for the slide menu widget APIs.
+//
+//*****************************************************************************
+extern int32_t SlideMenuMsgProc(tWidget *psWidget, uint32_t ui32Msg,
+ uint32_t ui32Param1, uint32_t ui32Param2);
+void SlideMenuDraw(tSlideMenuWidget *psMenuWidget, tContext *pContext,
+ int32_t i32OffsetY);
+extern void SlideMenuInit(tSlideMenuWidget *psWidget, const tDisplay *pDisplay,
+ int32_t i32X, int32_t i32Y, int32_t i32Width, int32_t i32Height,
+ tDisplay *pDisplayOffA, tDisplay *pDisplayOffB,
+ uint32_t ui32ItemHeight,
+ uint32_t ui32Foreground,
+ uint32_t ui32Background,
+ uint32_t ui32Highlight,
+ tFont *psFont, tSlideMenu *psMenu);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
+#endif // __SLIDEMENUWIDGET_H__
diff --git a/boards/ek-lm4f232/drivers/stripchartwidget.c b/boards/ek-lm4f232/drivers/stripchartwidget.c
new file mode 100644
index 0000000..60d9d37
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/stripchartwidget.c
@@ -0,0 +1,672 @@
+//*****************************************************************************
+//
+// stripchartwidget.c - A simple strip chart widget.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "driverlib/debug.h"
+#include "grlib/grlib.h"
+#include "grlib/widget.h"
+#include "stripchartwidget.h"
+
+//*****************************************************************************
+//
+//! \addtogroup stripchartwidget_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// This is a custom widget for drawing a simple strip chart. The strip
+// chart can be configured with an X/Y grid, and data series can be added
+// to and displayed on the strip chart. The strip chart can be "advanced"
+// so that the grid lines will move on the display. Before advancing
+// the chart, the application must update the series data in the buffers.
+// The strip chart will only display whatever is in the series buffers, the
+// application must scroll the data in the series data buffers. By adjusting
+// the data in the series data buffers, advancing the strip chart, and
+// repainting, the strip chart can be made to scroll the data across the
+// display.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! Draws the strip chart into a drawing context, off-screen buffer.
+//!
+//! \param psChartWidget points at the StripsChartWidget being processed.
+//! \param psContext points to the context where all drawing should be done.
+//!
+//! This function renders a strip chart into a drawing context.
+//! It assumes that the drawing context is an off-screen buffer, and that
+//! the entire buffer belongs to this widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+StripChartDraw(tStripChartWidget *psChartWidget, tContext *psContext)
+{
+ tStripChartAxis *psAxisY;
+ int32_t i32Y;
+ int32_t i32Ygrid;
+ int32_t i32X;
+ int32_t i32GridRange;
+ int32_t i32DispRange;
+ int32_t i32GridMin;
+ int32_t i32DispMax;
+ tStripChartSeries *psSeries;
+
+ //
+ // Check the parameters
+ //
+ ASSERT(psChartWidget);
+ ASSERT(psContext);
+ ASSERT(psChartWidget->psAxisY);
+
+ //
+ // Get handy pointer to Y axis
+ //
+ psAxisY = psChartWidget->psAxisY;
+
+ //
+ // Find the range of Y axis in Y axis units
+ //
+ i32GridRange = psAxisY->i32Max - psAxisY->i32Min;
+
+ //
+ // Find the range of the Y axis in display units (pixels)
+ //
+ i32DispRange = (psContext->sClipRegion.i16YMax -
+ psContext->sClipRegion.i16YMin);
+
+ //
+ // Find the minimum Y units value to be shown, and the maximum of the
+ // clipping region.
+ //
+ i32GridMin = psAxisY->i32Min;
+ i32DispMax = psContext->sClipRegion.i16YMax;
+
+ //
+ // Set the fg color for the rectangle fill to match what we want as the
+ // chart background.
+ //
+ GrContextForegroundSet(psContext, psChartWidget->ui32BackgroundColor);
+ GrRectFill(psContext, &psContext->sClipRegion);
+
+ //
+ // Draw vertical grid lines
+ //
+ GrContextForegroundSet(psContext, psChartWidget->ui32GridColor);
+ for(i32X = psChartWidget->i32GridX; i32X < psContext->sClipRegion.i16XMax;
+ i32X += psChartWidget->psAxisX->i32GridInterval)
+ {
+ GrLineDrawV(psContext, psContext->sClipRegion.i16XMax - i32X,
+ psContext->sClipRegion.i16YMin,
+ psContext->sClipRegion.i16YMax);
+ }
+
+ //
+ // Draw horizontal grid lines
+ //
+ for(i32Ygrid = psAxisY->i32Min; i32Ygrid < psAxisY->i32Max;
+ i32Ygrid += psAxisY->i32GridInterval)
+ {
+ i32Y = ((i32Ygrid - i32GridMin) * i32DispRange) / i32GridRange;
+ i32Y = i32DispMax - i32Y;
+ GrLineDrawH(psContext, psContext->sClipRegion.i16XMin,
+ psContext->sClipRegion.i16XMax, i32Y);
+ }
+
+ //
+ // Compute location of Y=0 line, and draw it
+ //
+ i32Y = ((-i32GridMin) * i32DispRange) / i32GridRange;
+ i32Y = i32DispMax - i32Y;
+ GrLineDrawH(psContext, psContext->sClipRegion.i16XMin,
+ psContext->sClipRegion.i16XMax, i32Y);
+
+ //
+ // Iterate through each series to draw it
+ //
+ psSeries = psChartWidget->psSeries;
+ while(psSeries)
+ {
+ int idx = 0;
+
+ //
+ // Find the starting X position on the display for this series.
+ // If the series has less data points than can fit on the display
+ // then starting X can be somewhere in the middle of the screen.
+ //
+ i32X = 1 + psContext->sClipRegion.i16XMax - psSeries->ui16NumItems;
+
+ //
+ // If the starting X is off the left side of the screen, then the
+ // staring index (idx) for reading data needs to be adjusted to the
+ // first value in the series that will be visible on the screen
+ //
+ if(i32X < psContext->sClipRegion.i16XMin)
+ {
+ idx = psContext->sClipRegion.i16XMin - i32X;
+ i32X = psContext->sClipRegion.i16XMin;
+ }
+
+ //
+ // Set the drawing color for this series
+ //
+ GrContextForegroundSet(psContext, psSeries->ui32Color);
+
+ //
+ // Scan through all possible X values, find the Y value, and draw the
+ // pixel.
+ //
+ for(; i32X <= psContext->sClipRegion.i16XMax; i32X++)
+ {
+ //
+ // Find the Y value at each position in the data series. Take into
+ // account the data size and the stride
+ //
+ if(psSeries->ui8DataTypeSize == 1)
+ {
+ i32Y =
+ ((int8_t *)psSeries->pvData)[idx * psSeries->ui8Stride];
+ }
+ else if(psSeries->ui8DataTypeSize == 2)
+ {
+ i32Y =
+ ((int16_t *)psSeries->pvData)[idx * psSeries->ui8Stride];
+ }
+ else if(psSeries->ui8DataTypeSize == 4)
+ {
+ i32Y =
+ ((int32_t *)psSeries->pvData)[idx * psSeries->ui8Stride];
+ }
+ else
+ {
+ //
+ // If there is an invalid data size, then just force Y value
+ // to be off the display
+ //
+ i32Y = i32DispMax + 1;
+ break;
+ }
+
+ //
+ // Advance to the next position in the data series.
+ //
+ idx++;
+
+ //
+ // Now scale the Y value according to the axis scaling
+ //
+ i32Y = ((i32Y - i32GridMin) * i32DispRange) / i32GridRange;
+ i32Y = i32DispMax - i32Y;
+
+ //
+ // Draw the pixel on the display
+ //
+ GrPixelDraw(psContext, i32X, i32Y);
+ }
+
+ //
+ // Advance to the next series until there are no more.
+ //
+ psSeries = psSeries->psNextSeries;
+ }
+
+ //
+ // Draw a frame around the entire chart.
+ //
+ GrContextForegroundSet(psContext, psChartWidget->ui32Y0Color);
+ GrRectDraw(psContext, &psContext->sClipRegion);
+
+ //
+ // Draw titles
+ //
+ GrContextForegroundSet(psContext, psChartWidget->ui32TextColor);
+ GrContextFontSet(psContext, psChartWidget->psFont);
+
+ //
+ // Draw the chart title, if there is one
+ //
+ if(psChartWidget->pcTitle)
+ {
+ GrStringDrawCentered(psContext, psChartWidget->pcTitle, -1,
+ psContext->sClipRegion.i16XMax / 2,
+ GrFontHeightGet(psChartWidget->psFont), 0);
+ }
+
+ //
+ // Draw the Y axis max label, if there is one
+ //
+ if(psChartWidget->psAxisY->pcMaxLabel)
+ {
+ GrStringDraw(psContext, psChartWidget->psAxisY->pcMaxLabel, -1,
+ psContext->sClipRegion.i16XMin +
+ GrFontMaxWidthGet(psChartWidget->psFont) / 2,
+ GrFontHeightGet(psChartWidget->psFont) / 2, 0);
+ }
+
+ //
+ // Draw the Y axis min label, if there is one
+ //
+ if(psChartWidget->psAxisY->pcMinLabel)
+ {
+ GrStringDraw(psContext, psChartWidget->psAxisY->pcMinLabel, -1,
+ psContext->sClipRegion.i16XMin +
+ GrFontMaxWidthGet(psChartWidget->psFont) / 2,
+ psContext->sClipRegion.i16YMax -
+ (GrFontHeightGet(psChartWidget->psFont) +
+ (GrFontHeightGet(psChartWidget->psFont) / 2)),
+ 0);
+ }
+
+ //
+ // Draw a label for the name of the Y axis, if there is one
+ //
+ if(psChartWidget->psAxisY->pcName)
+ {
+ GrStringDraw(psContext, psChartWidget->psAxisY->pcName, -1,
+ psContext->sClipRegion.i16XMin + 1,
+ (psContext->sClipRegion.i16YMax / 2) -
+ (GrFontHeightGet(psChartWidget->psFont) / 2),
+ 1);
+ }
+}
+
+//*****************************************************************************
+//
+//! Paints the strip chart on the display.
+//!
+//! \param psWidget is a pointer to the strip chart widget to be drawn.
+//!
+//! This function draws the contents of a strip chart on the display. This is
+//! called in response to a \b WIDGET_MSG_PAINT message.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+StripChartPaint(tWidget *psWidget)
+{
+ tStripChartWidget *psChartWidget;
+ tContext sContext;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+ ASSERT(psWidget->psDisplay);
+
+ //
+ // Convert the generic widget pointer into a strip chart widget pointer.
+ //
+ psChartWidget = (tStripChartWidget *)psWidget;
+
+ //
+ // Initialize a context for the primary off-screen drawing buffer.
+ // Clip region is set to entire display by default, which is what we want.
+ //
+ ASSERT(psChartWidget->psOffscreenDisplay);
+ GrContextInit(&sContext, psChartWidget->psOffscreenDisplay);
+
+ //
+ // Render the strip chart into the off-screen buffer
+ //
+ StripChartDraw(psChartWidget, &sContext);
+
+ //
+ // Initialize a drawing context for the display where the widget is to be
+ // drawn. This is the physical display, not an off-screen buffer.
+ //
+ GrContextInit(&sContext, psWidget->psDisplay);
+
+ //
+ // Initialize the clipping region on the physical display, based on the
+ // extents of this widget.
+ //
+ GrContextClipRegionSet(&sContext, &(psWidget->sPosition));
+
+ //
+ // Now copy the rendered strip chart into the physical display
+ //
+ GrImageDraw(&sContext, psChartWidget->psOffscreenDisplay->pvDisplayData,
+ psWidget->sPosition.i16XMin, psWidget->sPosition.i16YMin);
+}
+
+//*****************************************************************************
+//
+//! Advances the strip chart X grid by a certain number of pixels.
+//!
+//! \param psChartWidget is a pointer to the strip chart widget to be advanced.
+//! \param i32Count is the number of positions to advance the grid.
+//!
+//! This function advances the X grid of the strip chart by the specified
+//! number of positions. By using this function to advance the grid in
+//! combination with updating the data in the series data buffers, the strip
+//! chart can be made to appear to scroll across the display.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+StripChartAdvance(tStripChartWidget *psChartWidget, int32_t i32Count)
+{
+ //
+ // Adjust the starting point of the X-grid
+ //
+ psChartWidget->i32GridX += i32Count;
+ psChartWidget->i32GridX %= psChartWidget->psAxisX->i32GridInterval;
+}
+
+//*****************************************************************************
+//
+//! Adds a data series to the strip chart.
+//!
+//! \param psWidget is a pointer to the strip chart widget to be modified.
+//! \param psNewSeries is a strip chart data series to be added to the strip
+//! chart.
+//!
+//! This function will add a data series to the strip chart. This function
+//! just links the series into the strip chart. It is up to the application
+//! to make sure that the data series is initialized correctly.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+StripChartSeriesAdd(tStripChartWidget *psWidget,
+ tStripChartSeries *psNewSeries)
+{
+ //
+ // If there is already at least one series in this chart, then link
+ // in to the existing chain.
+ //
+ if(psWidget->psSeries)
+ {
+ tStripChartSeries *psSeries = psWidget->psSeries;
+ while(psSeries->psNextSeries)
+ {
+ psSeries = psSeries->psNextSeries;
+ }
+ psSeries->psNextSeries = psNewSeries;
+ }
+
+ //
+ // Otherwise, there is not already a series in this chart, so set this
+ // new series as the first series for the chart.
+ //
+ else
+ {
+ psWidget->psSeries = psNewSeries;
+ }
+ psNewSeries->psNextSeries = 0;
+}
+
+//*****************************************************************************
+//
+//! Removes a data series from the strip chart.
+//!
+//! \param psWidget is a pointer to the strip chart widget to be modified.
+//! \param psOldSeries is a strip chart data series that is to be removed
+//! from the strip chart.
+//!
+//! This function will remove an existing data series from a strip chart. It
+//! will search the list of data series for the specified series, and if
+//! found it will be unlinked from the chain of data series for this strip
+//! chart.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+StripChartSeriesRemove(tStripChartWidget *psWidget,
+ tStripChartSeries *psOldSeries)
+{
+ //
+ // If the series to be removed is the first one, then find the next
+ // series in the chain and set it to be first.
+ //
+ if(psWidget->psSeries == psOldSeries)
+ {
+ psWidget->psSeries = psOldSeries->psNextSeries;
+ }
+
+ //
+ // Otherwise, scan through the chain to find the old series
+ //
+ else
+ {
+ tStripChartSeries *psSeries = psWidget->psSeries;
+ while(psSeries->psNextSeries)
+ {
+ //
+ // If the old series is found, unlink it from the chain
+ //
+ if(psSeries->psNextSeries == psOldSeries)
+ {
+ psSeries->psNextSeries = psOldSeries->psNextSeries;
+ break;
+ }
+ else
+ {
+ psSeries = psSeries->psNextSeries;
+ }
+ }
+ }
+
+ //
+ // Finally, set the "next" pointer of the old series to null so that
+ // there will not be any confusing chain fragments if this series is
+ // reused.
+ //
+ psOldSeries->psNextSeries = 0;
+}
+
+//*****************************************************************************
+//
+//! Handles messages for a strip chart widget.
+//!
+//! \param psWidget is a pointer to the strip chart widget.
+//! \param ui32Msg is the message.
+//! \param ui32Param1 is the first parameter to the message.
+//! \param ui32Param2 is the second parameter to the message.
+//!
+//! This function receives messages intended for this strip chart widget and
+//! processes them accordingly. The processing of the message varies based on
+//! the message in question.
+//!
+//! Unrecognized messages are handled by calling WidgetDefaultMsgProc().
+//!
+//! \return Returns a value appropriate to the supplied message.
+//
+//*****************************************************************************
+int32_t
+StripChartMsgProc(tWidget *psWidget, uint32_t ui32Msg, uint32_t ui32Param1,
+ uint32_t ui32Param2)
+{
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+
+ //
+ // Determine which message is being sent.
+ //
+ switch(ui32Msg)
+ {
+ //
+ // The widget paint request has been sent.
+ //
+ case WIDGET_MSG_PAINT:
+ {
+ //
+ // Handle the widget paint request.
+ //
+ StripChartPaint(psWidget);
+
+ //
+ // Return one to indicate that the message was successfully
+ // processed.
+ //
+ return(1);
+ }
+
+ //
+ // Deliberately ignore all button press messages. They may be handled
+ // by another widget.
+ //
+ case WIDGET_MSG_KEY_SELECT:
+ case WIDGET_MSG_KEY_UP:
+ case WIDGET_MSG_KEY_DOWN:
+ case WIDGET_MSG_KEY_LEFT:
+ case WIDGET_MSG_KEY_RIGHT:
+ {
+ return(0);
+ }
+
+ //
+ // An unknown request has been sent.
+ //
+ default:
+ {
+ //
+ // Let the default message handler process this message.
+ //
+ return(WidgetDefaultMsgProc(psWidget, ui32Msg, ui32Param1,
+ ui32Param2));
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Initializes a strip chart widget.
+//!
+//! \param psWidget is a pointer to the strip chart widget to initialize.
+//! \param psDisplay is a pointer to the display on which to draw the chart.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param pcTitle is the label text for the strip chart
+//! \param psFont is the font to use for drawing text on the chart.
+//! \param ui32BackgroundColor is the colr of the background for the chart.
+//! \param ui32TextColor is the color used for drawing text.
+//! \param ui32Y0Color is the color used for drawing the Y=0 line and the frame
+//! around the chart.
+//! \param ui32GridColor is the color of the X/Y grid
+//! \param psAxisX is a pointer to the X-axis object
+//! \param psAxisY is a pointer to the Y-axis object
+//! \param psOffscreenDisplay is a pointer to an offscreen display that will
+//! be used for rendering the strip chart prior to drawing it on the
+//! physical display.
+//!
+//! This function initializes the caller provided strip chart widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+StripChartInit(tStripChartWidget *psWidget, const tDisplay *psDisplay,
+ int32_t i32X, int32_t i32Y, int32_t i32Width, int32_t i32Height,
+ char * pcTitle, tFont *psFont,
+ uint32_t ui32BackgroundColor,
+ uint32_t ui32TextColor,
+ uint32_t ui32Y0Color,
+ uint32_t ui32GridColor,
+ tStripChartAxis *psAxisX, tStripChartAxis *psAxisY,
+ tDisplay *psOffscreenDisplay)
+{
+ uint32_t ui32Idx;
+
+ //
+ // Check the arguments.
+ //
+ ASSERT(psWidget);
+ ASSERT(psDisplay);
+ ASSERT(psAxisX);
+ ASSERT(psAxisY);
+ ASSERT(psOffscreenDisplay);
+
+ //
+ // Clear out the widget structure.
+ //
+ for(ui32Idx = 0; ui32Idx < sizeof(tStripChartWidget); ui32Idx += 4)
+ {
+ ((uint32_t *)psWidget)[ui32Idx / 4] = 0;
+ }
+
+ //
+ // Set the size of the widget structure.
+ //
+ psWidget->sBase.i32Size = sizeof(tStripChartWidget);
+
+ //
+ // Mark this widget as fully disconnected.
+ //
+ psWidget->sBase.psParent = 0;
+ psWidget->sBase.psNext = 0;
+ psWidget->sBase.psChild = 0;
+
+ //
+ // Save the display pointer.
+ //
+ psWidget->sBase.psDisplay = psDisplay;
+
+ //
+ // Set the extents of the display area.
+ //
+ psWidget->sBase.sPosition.i16XMin = i32X;
+ psWidget->sBase.sPosition.i16YMin = i32Y;
+ psWidget->sBase.sPosition.i16XMax = i32X + i32Width - 1;
+ psWidget->sBase.sPosition.i16YMax = i32Y + i32Height - 1;
+
+ //
+ // Initialize the widget fields
+ //
+ psWidget->pcTitle = pcTitle;
+ psWidget->psFont = psFont;
+ psWidget->ui32BackgroundColor = ui32BackgroundColor;
+ psWidget->ui32TextColor = ui32TextColor;
+ psWidget->ui32Y0Color = ui32Y0Color;
+ psWidget->ui32GridColor = ui32GridColor;
+ psWidget->psAxisX = psAxisX;
+ psWidget->psAxisY = psAxisY;
+ psWidget->psOffscreenDisplay = psOffscreenDisplay;
+
+ //
+ // Use the strip chart message handler to process messages to this widget.
+ //
+ psWidget->sBase.pfnMsgProc = StripChartMsgProc;
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
diff --git a/boards/ek-lm4f232/drivers/stripchartwidget.h b/boards/ek-lm4f232/drivers/stripchartwidget.h
new file mode 100644
index 0000000..2c64f6a
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/stripchartwidget.h
@@ -0,0 +1,392 @@
+//*****************************************************************************
+//
+// stripchartwidget.h - Prototypes for a strip chart widget.
+//
+// Copyright (c) 2011-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#ifndef __STRIPCHARTWIDGET_H__
+#define __STRIPCHARTWIDGET_H__
+
+//*****************************************************************************
+//
+//! \addtogroup stripchartwidget_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! A structure that represents a data series to be shown on the strip chart.
+//
+//*****************************************************************************
+typedef struct _StripChartSeries
+{
+ //
+ //! A pointer to the next series in the chart.
+ //
+ struct _StripChartSeries *psNextSeries;
+
+ //
+ //! A pointer to the brief name of the data set
+ //
+ char *pcName;
+
+ //
+ //! The color of the data series.
+ //
+ uint32_t ui32Color;
+
+ //
+ //! The number of bytes of the data type (1, 2, or 4)
+ //
+ uint8_t ui8DataTypeSize;
+
+ //
+ //! The stride of the data. This can be used when this data set is
+ //! part of a larger set of samples that appear in a large array
+ //! interleaved at a regular interval. Use a value of 1 if the data set
+ //! is not interleaved.
+ //
+ uint8_t ui8Stride;
+
+ //
+ //! The number of items in the data set
+ //
+ uint16_t ui16NumItems;
+
+ //
+ //! A pointer to the first data item.
+ //
+ void *pvData;
+}
+tStripChartSeries;
+
+//*****************************************************************************
+//
+//! A structure that represents an axis of the strip chart.
+//
+//*****************************************************************************
+typedef struct _StripChartAxis
+{
+ //
+ //! A brief name for the axis. Leave null for no name to be shown.
+ //
+ char *pcName;
+
+ //
+ //! Label for the minimum extent of the axis. Leave null for no label.
+ //
+ char *pcMinLabel;
+
+ //
+ //! Label for the max extent of the axis. Leave null for no label.
+ //
+ char *pcMaxLabel;
+
+ //
+ //! The minimum units value for the axis.
+ //
+ int32_t i32Min;
+
+ //
+ //! The maximum units value for the axis
+ //
+ int32_t i32Max;
+
+ //
+ //! The grid interval for the axis. Use 0 for no grid.
+ //
+ int32_t i32GridInterval;
+} tStripChartAxis;
+
+//*****************************************************************************
+//
+//! A structure that represents a strip chart widget.
+//
+//*****************************************************************************
+typedef struct _StripChartWidget
+{
+ //
+ //! The generic widget information.
+ //
+ tWidget sBase;
+
+ //
+ //! The title for the strip chart. Leave null for no title.
+ //
+ char *pcTitle;
+
+ //
+ //! The font to use for drawing text on the chart.
+ //
+ const tFont *psFont;
+
+ //
+ //! The background color of the chart.
+ //
+ uint32_t ui32BackgroundColor;
+
+ //
+ //! The color for text that is drawn on the chart (titles, etc).
+ //
+ uint32_t ui32TextColor;
+
+ //
+ //! The color of the Y-axis 0-crossing line.
+ //
+ uint32_t ui32Y0Color;
+
+ //
+ //! The color of the grid lines.
+ //
+ uint32_t ui32GridColor;
+
+ //
+ //! The X axis
+ //
+ tStripChartAxis *psAxisX;
+
+ //
+ //! The Y axis
+ //
+ tStripChartAxis *psAxisY;
+
+ //
+ //! A pointer to the first data series for the strip chart.
+ //
+ tStripChartSeries *psSeries;
+
+ //
+ //! A pointer to an off-screen display to be used for rendering the chart.
+ //
+ const tDisplay *psOffscreenDisplay;
+
+ //
+ //! The current X-grid alignment. This value changes in order to give the
+ //! appearance of the grid moving as the strip chart advances.
+ //
+ int32_t i32GridX;
+} tStripChartWidget;
+
+//*****************************************************************************
+//
+//! Declares an initialized strip chart widget data structure.
+//!
+//! \param psParent is a pointer to the parent widget.
+//! \param psNext is a pointer to the sibling widget.
+//! \param psChild is a pointer to the first child widget.
+//! \param psDisplay is a pointer to the off-screen display on which to draw.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param pcTitle is a string for the chart title, NULL for no title.
+//! \param psFont is the font used for rendering text on the chart.
+//! \param ui32BackgroundColor is the background color for the chart.
+//! \param ui32TextColor is the color of text (titles, labels, etc.)
+//! \param ui32Y0Color is the color of the Y-axis gridline at Y=0
+//! \param ui32GridColor is the color of grid lines.
+//! \param psAxisX is a pointer to the axis structure for the X-axis.
+//! \param psAxisY is a pointer to the axis structure for the Y-axis.
+//! \param psOffscreenDisplay is a buffer for rendering the chart before
+//! showing on the physical display. The dimensions of the off-screen display
+//! should match the drawing area of psDisplay.
+//!
+//! This macro provides an initialized strip chart widget data structure, which
+//! can be used to construct the widget tree at compile time in global
+//! variables (as opposed to run-time via function calls). This must be
+//! assigned to a variable, such as:
+//!
+//! \verbatim
+//! tStripChartWidget g_sStripChart = StripChartStruct(...);
+//! \endverbatim
+//!
+//! Or, in an array of variables:
+//!
+//! \verbatim
+//! tStripChartWidget g_psStripChart[] =
+//! {
+//! StripChartStruct(...),
+//! StripChartStruct(...)
+//! };
+//! \endverbatim
+//!
+//! \return Nothing; this is not a function.
+//
+//*****************************************************************************
+#define StripChartStruct(psParent, psNext, psChild, psDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ pcTitle, psFont, ui32BackgroundColor, ui32TextColor, \
+ ui32Y0Color, ui32GridColor, psAxisX, psAxisY, \
+ psOffscreenDisplay) \
+ { \
+ { \
+ sizeof(tStripChartWidget), \
+ (tWidget *)(psParent), \
+ (tWidget *)(psNext), \
+ (tWidget *)(psChild), \
+ psDisplay, \
+ { \
+ i32X, \
+ i32Y, \
+ (i32X) + (i32Width) - 1, \
+ (i32Y) + (i32Height) - 1 \
+ }, \
+ StripChartMsgProc \
+ }, \
+ pcTitle, psFont, ui32BackgroundColor, ui32TextColor, ui32Y0Color, \
+ ui32GridColor, psAxisX, psAxisY, 0, psOffscreenDisplay, 0 \
+ }
+
+//*****************************************************************************
+//
+//! Declares an initialized variable containing a strip chart widget data
+//! structure.
+//!
+//! \param sName is the name of the variable to be declared.
+//! \param psParent is a pointer to the parent widget.
+//! \param psNext is a pointer to the sibling widget.
+//! \param psChild is a pointer to the first child widget.
+//! \param psDisplay is a pointer to the off-screen display on which to draw.
+//! \param i32X is the X coordinate of the upper left corner of the canvas.
+//! \param i32Y is the Y coordinate of the upper left corner of the canvas.
+//! \param i32Width is the width of the canvas.
+//! \param i32Height is the height of the canvas.
+//! \param pcTitle is a string for the chart title, NULL for no title.
+//! \param psFont is the font used for rendering text on the chart.
+//! \param ui32BackgroundColor is the background color for the chart.
+//! \param ui32TextColor is the color of text (titles, labels, etc.)
+//! \param ui32Y0Color is the color of the Y-axis gridline at Y=0
+//! \param ui32GridColor is the color of grid lines.
+//! \param psAxisX is a pointer to the axis structure for the X-axis.
+//! \param psAxisY is a pointer to the axis structure for the Y-axis.
+//! \param psOffscreenDisplay is a buffer for rendering the chart before
+//! showing on the physical display. The dimensions of the off-screen display
+//! should match the drawing area of psDisplay.
+//!
+//! This macro declares a variable containing an initialized strip chart widget
+//! data structure, which can be used to construct the widget tree at compile
+//! time in global variables (as opposed to run-time via function calls).
+//!
+//! \return Nothing; this is not a function.
+//
+//*****************************************************************************
+#define StripChart(sName, psParent, psNext, psChild, psDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ pcTitle, psFont, ui32BackgroundColor, ui32TextColor, \
+ ui32Y0Color, ui32GridColor, psAxisX, psAxisY, \
+ psOffscreenDisplay) \
+ tStripChartWidget sName = \
+ StripChartStruct(psParent, psNext, psChild, psDisplay, \
+ i32X, i32Y, i32Width, i32Height, \
+ pcTitle, psFont, ui32BackgroundColor, \
+ ui32TextColor, ui32Y0Color, ui32GridColor, \
+ psAxisX, psAxisY, psOffscreenDisplay)
+
+//*****************************************************************************
+//
+//! Sets the X-axis of the strip chart.
+//!
+//! \param psStripChartWidget is a pointer to the strip chart widget to modify.
+//! \param psAxis is the new X-axis structure for the strip chart.
+//!
+//! This function sets the X-axis for the widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define StripChartXAxisSet(psStripChartWidget, psAxis) \
+ do \
+ { \
+ (psStripChartWidget)->psAxisX = psAxis; \
+ } while(0)
+
+//*****************************************************************************
+//
+//! Sets the Y-axis of the strip chart.
+//!
+//! \param psStripChartWidget is a pointer to the strip chart widget to modify.
+//! \param psAxis is the new Y-axis structure for the strip chart.
+//!
+//! This function sets the Y-axis for the widget.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#define StripChartYAxisSet(psStripChartWidget, psAxis) \
+ do \
+ { \
+ (psStripChartWidget)->psAxisY = psAxis; \
+ } while(0)
+
+//*****************************************************************************
+//
+// Prototypes for the strip chart widget APIs.
+//
+//*****************************************************************************
+extern int32_t StripChartMsgProc(tWidget *psWidget, uint32_t ui32Msg,
+ uint32_t ui32Param1, uint32_t ui32Param2);
+extern void StripChartInit(tStripChartWidget *psWidget,
+ const tDisplay *psDisplay,
+ int32_t i32X, int32_t i32Y,
+ int32_t i32Width, int32_t i32Height,
+ char * pcTitle, tFont *psFont,
+ uint32_t ui32BackgroundColor,
+ uint32_t ui32TextColor,
+ uint32_t ui32Y0Color,
+ uint32_t ui32GridColor,
+ tStripChartAxis *psAxisX, tStripChartAxis *psAxisY,
+ tDisplay *psOffscreenDisplay);
+extern void StripChartSeriesAdd(tStripChartWidget *psWidget,
+ tStripChartSeries *psSeries);
+extern void StripChartSeriesRemove(tStripChartWidget *psWidget,
+ tStripChartSeries *psSeries);
+extern void StripChartAdvance(tStripChartWidget *psChartWidget,
+ int32_t i32Count);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
+#endif // __STRIPCHARTWIDGET_H__
diff --git a/boards/ek-lm4f232/drivers/usb_sound.c b/boards/ek-lm4f232/drivers/usb_sound.c
new file mode 100644
index 0000000..332f556
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/usb_sound.c
@@ -0,0 +1,804 @@
+//*****************************************************************************
+//
+// usb_sound.c - USB host audio handling functions.
+//
+// Copyright (c) 2012-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_types.h"
+#include "inc/hw_memmap.h"
+#include "drivers/usb_sound.h"
+#include "driverlib/gpio.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/udma.h"
+#include "driverlib/usb.h"
+#include "usblib/usblib.h"
+#include "usblib/usbmsc.h"
+#include "usblib/host/usbhost.h"
+#include "usblib/host/usbhaudio.h"
+
+//*****************************************************************************
+//
+// The size of the host controller's memory pool in bytes.
+//
+//*****************************************************************************
+#define HCD_MEMORY_SIZE 768
+
+//*****************************************************************************
+//
+// The memory pool to provide to the Host controller driver.
+//
+//*****************************************************************************
+uint8_t g_pHCDPool[HCD_MEMORY_SIZE];
+
+//*****************************************************************************
+//
+// The instance data for the USB host audio driver.
+//
+//*****************************************************************************
+tUSBHostAudioInstance *g_psAudioInstance = 0;
+
+//*****************************************************************************
+//
+// Declare the USB Events driver interface.
+//
+//*****************************************************************************
+DECLARE_EVENT_DRIVER(g_sUSBEventDriver, 0, 0, USBHCDEvents);
+
+//*****************************************************************************
+//
+// This structure holds the state information for the USB audio device.
+//
+//*****************************************************************************
+static struct
+{
+ //
+ // Save the application provided callback function.
+ //
+ tUSBBufferCallback pfnCallbackOut;
+
+ //
+ // Save the application provided callback function.
+ //
+ tUSBBufferCallback pfnCallbackIn;
+
+ //
+ // The event callback for the application.
+ //
+ tEventCallback pfnCallbackEvent;
+
+ //
+ // Volume control multipliers calculated from the information received
+ // from the audio device.
+ //
+ uint32_t pui32Steps[3];
+
+ //
+ // The currently pending audio device events.
+ //
+ uint32_t ui32EventFlags;
+
+ //
+ // The current state for the audio device.
+ //
+ volatile enum
+ {
+ //
+ // No device is present.
+ //
+ STATE_NO_DEVICE,
+
+ //
+ // Audio device is ready.
+ //
+ STATE_DEVICE_READY,
+
+ //
+ // An unsupported device has been attached.
+ //
+ STATE_UNKNOWN_DEVICE,
+
+ //
+ // A power fault has occurred.
+ //
+ STATE_POWER_FAULT
+ } eState;
+
+} g_sAudioState;
+
+//*****************************************************************************
+//
+// These defines are used with the ui32EventFlags in the g_sAudioState structure.
+//
+//*****************************************************************************
+#define EVENT_OPEN 0x00000001
+#define EVENT_CLOSE 0x00000002
+
+//*****************************************************************************
+//
+// The global that holds all of the host drivers in use in the application.
+// In this case, only the host audio class is loaded.
+//
+//*****************************************************************************
+static tUSBHostClassDriver const * const g_ppHostClassDrivers[] =
+{
+ &g_sUSBHostAudioClassDriver
+ ,&g_sUSBEventDriver
+};
+
+//*****************************************************************************
+//
+// This global holds the number of class drivers in the g_ppHostClassDrivers
+// list.
+//
+//*****************************************************************************
+static const uint32_t g_ui32NumHostClassDrivers =
+ sizeof(g_ppHostClassDrivers) / sizeof(tUSBHostClassDriver *);
+
+//*****************************************************************************
+//
+// The control table used by the uDMA controller. This table must be aligned
+// to a 1024 byte boundary. In this application uDMA is only used for USB,
+// so only the first 6 channels are needed.
+//
+//*****************************************************************************
+#if defined(ewarm)
+#pragma data_alignment=1024
+tDMAControlTable g_sDMAControlTable[64];
+#elif defined(ccs)
+#pragma DATA_ALIGN(g_sDMAControlTable, 1024)
+tDMAControlTable g_sDMAControlTable[64];
+#else
+tDMAControlTable g_sDMAControlTable[64] __attribute__ ((aligned(1024)));
+#endif
+
+//*****************************************************************************
+//
+// This function was the callback function registered with the USB host audio
+// class driver. The only two events that are handled at this point are the
+// USBH_AUDIO_EVENT_OPEN and USBH_AUDIO_EVENT_CLOSE which indicate that a new
+// audio device has been found or that an existing audio device has been
+// disconnected.
+//
+//*****************************************************************************
+static void
+AudioCallback(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Event,
+ uint32_t ui32MsgParam,
+ void *pvBuffer)
+{
+ switch(ui32Event)
+ {
+ //
+ // New USB audio device has been enabled.
+ //
+ case USBH_AUDIO_EVENT_OPEN:
+ {
+ //
+ // Set the EVENT_OPEN flag and let the main routine handle it.
+ //
+ HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN) = 1;
+
+ break;
+ }
+
+ //
+ // USB audio device has been removed.
+ //
+ case USBH_AUDIO_EVENT_CLOSE:
+ {
+ //
+ // Set the EVENT_CLOSE flag and let the main routine handle it.
+ //
+ HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE) = 1;
+
+ break;
+ }
+ default:
+ {
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Initializes the sound output.
+//
+// \param ui32Flags is unused as this point but is included for future
+// functionality.
+// \param pfnCallback is the event callback function for audio devices.
+//
+// This function prepares the sound driver to enumerate an audio device and
+// prepares to play audio once a valid audio device is detected. The
+// \e pfnCallback function can be used to receive callbacks when there are
+// changes related to the audio device. The ui32Event parameter to the callback
+// will be one of the SOUND_EVENT_* values.
+//
+// \return None
+//
+//*****************************************************************************
+void
+USBSoundInit(uint32_t ui32Flags, tEventCallback pfnCallback)
+{
+ //
+ // Enable the peripherals used by this example.
+ //
+ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
+
+ //
+ // Set the USB power pins to be controlled by the USB controller.
+ //
+ GPIOPinTypeUSBDigital(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
+
+ //
+ // Enable the uDMA controller and set up the control table base.
+ //
+ SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
+ uDMAEnable();
+ uDMAControlBaseSet(g_sDMAControlTable);
+
+ //
+ // Initialize the USB stack mode to OTG.
+ //
+ USBStackModeSet(0, eUSBModeOTG, 0);
+
+ //
+ // Register the host class drivers.
+ //
+ USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers);
+
+ //
+ // Open an instance of the audio class driver.
+ //
+ g_psAudioInstance = USBHostAudioOpen(0, AudioCallback);
+
+ //
+ // Initialize the power configuration. This sets the power enable signal
+ // to be active high and does not enable the power fault.
+ //
+ USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER);
+
+ //
+ // Initialize the USB controller for OTG operation with a 2ms polling
+ // rate.
+ //
+ USBOTGModeInit(0, 2000, g_pHCDPool, HCD_MEMORY_SIZE);
+
+ //
+ // Save the event callback function.
+ //
+ g_sAudioState.pfnCallbackEvent = pfnCallback;
+}
+
+//*****************************************************************************
+//
+// Sets the volume of the audio device.
+//
+// \param ui32Percent is the volume percentage, which must be between 0%
+// (silence) and 100% (full volume), inclusive.
+//
+// This function sets the volume of the sound output to a value between
+// silence (0%) and full volume (100%).
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USBSoundVolumeSet(uint32_t ui32Percent)
+{
+ uint32_t ui32Value;
+
+ //
+ // Ignore volume changes if there is no device present.
+ //
+ if(g_sAudioState.eState == STATE_DEVICE_READY)
+ {
+ //
+ // Scale the voltage percentage to the decibel range provided by the
+ // USB audio device.
+ //
+ ui32Value = (g_sAudioState.pui32Steps[1] * ui32Percent) / 100;
+ USBHostAudioVolumeSet(g_psAudioInstance, 0, 1, ui32Value);
+
+ ui32Value = (g_sAudioState.pui32Steps[2] * ui32Percent) / 100;
+ USBHostAudioVolumeSet(g_psAudioInstance, 0, 2, ui32Value);
+ }
+}
+
+//*****************************************************************************
+//
+// Returns the current volume level.
+//
+// \param ui32Channel is the 0 based channel number to query.
+//
+// This function returns the current volume, specified as a percentage between
+// 0% (silence) and 100% (full volume), inclusive. The \e ui32Channel value
+// starts with 0 which is the master audio volume control interface. The
+// remaining \e ui32Channel values provide access to various other audio
+// channels, with 1 and 2 being left and right audio channels.
+//
+// \return Returns the current volume.
+//
+//*****************************************************************************
+uint32_t
+USBSoundVolumeGet(uint32_t ui32Channel)
+{
+ uint32_t ui32Volume;
+
+ //
+ // Initialize the return value in case there is no USB device present.
+ //
+ ui32Volume = 0xffffffff;
+
+ //
+ // Ignore volume request if there is no device present.
+ //
+ if(g_sAudioState.eState == STATE_DEVICE_READY)
+ {
+ ui32Volume = USBHostAudioVolumeGet(g_psAudioInstance, 0, ui32Channel);
+ }
+
+ return(ui32Volume);
+}
+
+//*****************************************************************************
+//
+// This will set the current output audio format of the USB audio device.
+//
+// \param ui32SampleRate is the sample rate.
+// \param ui32BitsPerSample is the number of bits per sample.
+// \param ui32Channels is the number of channels.
+//
+// This sets the current audio format for the USB device that is currently
+// connected. If there is no USB device connected or the format is not
+// supported then the function will return a non-zero value. The function
+// will return zero if the USB audio device was successfully configured to the
+// requested audio format.
+//
+// \return Returns zero if the format was successfully set or returns an
+// non-zero value if the format was not able to be set.
+//
+//*****************************************************************************
+uint32_t
+USBSoundOutputFormatSet(uint32_t ui32SampleRate,
+ uint32_t ui32BitsPerSample, uint32_t ui32Channels)
+{
+ //
+ // Just return if there is no device at this time.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(1);
+ }
+
+ //
+ // Call the USB Host Audio function to set the format.
+ //
+ return(USBHostAudioFormatSet(g_psAudioInstance, ui32SampleRate,
+ ui32BitsPerSample, ui32Channels,
+ USBH_AUDIO_FORMAT_OUT));
+}
+
+//*****************************************************************************
+//
+// This will set the current input audio format of the USB audio device
+//
+// \param ui32SampleRate is the sample rate.
+// \param ui32BitsPerSample is the number of bits per sample.
+// \param ui32Channels is the number of channels.
+//
+// This sets the current format for the USB device that is currently connect.
+// If there is no USB device connected or the format is not supported then the
+// function will return 0. The function will return 1 if the USB audio device
+// was successfully configured to the requested format.
+//
+// \return Returns 1 if the format was successfully set or returns 0 if the
+// format was not changed.
+//
+//*****************************************************************************
+uint32_t
+USBSoundInputFormatSet(uint32_t ui32SampleRate,
+ uint32_t ui32BitsPerSample, uint32_t ui32Channels)
+{
+ //
+ // Just return if there is no device at this time.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(0);
+ }
+
+ return(USBHostAudioFormatSet(g_psAudioInstance, ui32SampleRate,
+ ui32BitsPerSample, ui32Channels,
+ USBH_AUDIO_FORMAT_IN));
+}
+
+//*****************************************************************************
+//
+// Returns the current sample rate.
+//
+// This function returns the sample rate that was set by a call to
+// USBSoundSetFormat(). This is needed to retrieve the exact sample rate that is
+// in use in case the requested rate could not be matched exactly.
+//
+// \return The current sample rate in samples/second.
+//
+//*****************************************************************************
+uint32_t
+USBSoundOutputFormatGet(uint32_t ui32SampleRate, uint32_t ui32Bits,
+ uint32_t ui32Channels)
+{
+ //
+ // Just return if there is no device at this time.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(0);
+ }
+
+ return(USBHostAudioFormatGet(g_psAudioInstance, ui32SampleRate, ui32Bits,
+ ui32Channels, USBH_AUDIO_FORMAT_OUT));
+}
+
+//*****************************************************************************
+//
+// Returns the current sample rate.
+//
+// This function returns the sample rate that was set by a call to
+// USBSoundSetFormat(). This is needed to retrieve the exact sample rate that is
+// in use in case the requested rate could not be matched exactly.
+//
+// \return The current sample rate in samples/second.
+//
+//*****************************************************************************
+uint32_t
+USBSoundInputFormatGet(uint32_t ui32SampleRate, uint32_t ui32Bits,
+ uint32_t ui32Channels)
+{
+ //
+ // Just return if there is no device at this time.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(0);
+ }
+
+ return(USBHostAudioFormatGet(g_psAudioInstance, ui32SampleRate, ui32Bits,
+ ui32Channels, USBH_AUDIO_FORMAT_IN));
+}
+
+//*****************************************************************************
+//
+// This is the generic callback from host stack.
+//
+// \param pvData is actually a pointer to a tEventInfo structure.
+//
+// This function will be called to inform the application when a USB event has
+// occurred that is outside those related to the audio device. At this
+// point this is used to detect unsupported devices being inserted and removed.
+// It is also used to inform the application when a power fault has occurred.
+// This function is required when the g_USBGenerii8EventDriver is included in
+// the host controller driver array that is passed in to the
+// USBHCDRegisterDrivers() function.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USBHCDEvents(void *pvData)
+{
+ tEventInfo *psEventInfo;
+
+ //
+ // Cast this pointer to its actual type.
+ //
+ psEventInfo = (tEventInfo *)pvData;
+
+ switch(psEventInfo->ui32Event)
+ {
+ //
+ // Unknown device detected.
+ //
+ case USB_EVENT_UNKNOWN_CONNECTED:
+ {
+ //
+ // An unknown device was detected.
+ //
+ g_sAudioState.eState = STATE_UNKNOWN_DEVICE;
+
+ //
+ // Call the general event handler if present.
+ //
+ if(g_sAudioState.pfnCallbackEvent)
+ {
+ g_sAudioState.pfnCallbackEvent(SOUND_EVENT_UNKNOWN_DEV, 1);
+ }
+
+ break;
+ }
+
+ //
+ // Device unplugged.
+ //
+ case USB_EVENT_DISCONNECTED:
+ {
+ //
+ // Handle the case where an unknown device is disconnected.
+ //
+ if(g_sAudioState.eState == STATE_UNKNOWN_DEVICE)
+ {
+ g_sAudioState.eState = STATE_NO_DEVICE;
+
+ //
+ // Call the general event handler if present.
+ //
+ if(g_sAudioState.pfnCallbackEvent)
+ {
+ g_sAudioState.pfnCallbackEvent(SOUND_EVENT_UNKNOWN_DEV, 0);
+ }
+ }
+ else
+ {
+ //
+ // Call the general event handler if present.
+ //
+ if(g_sAudioState.pfnCallbackEvent)
+ {
+ g_sAudioState.pfnCallbackEvent(SOUND_EVENT_DISCONNECT, 0);
+ }
+ }
+
+ break;
+ }
+
+ //
+ // A power fault has occurred.
+ //
+ case USB_EVENT_POWER_FAULT:
+ {
+ //
+ // No power means no device is present.
+ //
+ g_sAudioState.eState = STATE_POWER_FAULT;
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function passes along a buffer callback from the USB host audio driver
+// so that the application can process or release the buffers.
+//
+//*****************************************************************************
+void
+USBHostAudioCallback(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Event, uint32_t ui32Param, void *pvBuffer)
+{
+ //
+ // Only call the callback if it is actually present.
+ //
+ if(g_sAudioState.pfnCallbackOut)
+ {
+ g_sAudioState.pfnCallbackOut(pvBuffer, ui32Event);
+ }
+
+ //
+ // Only call the callback if it is actually present.
+ //
+ if(g_sAudioState.pfnCallbackIn)
+ {
+ g_sAudioState.pfnCallbackIn(pvBuffer, ui32Event);
+ }
+}
+
+//*****************************************************************************
+//
+// Starts output of a block of PCM audio samples.
+//
+// \param pvBuffer is a pointer to the audio data to play.
+// \param ui32Size is the length of the data in bytes.
+// \param pfnCallback is a function to call when this buffer has be played.
+//
+// This function starts the output of a block of PCM audio samples.
+//
+// \return This function returns a non-zero value if the buffer was accepted,
+// and returns zero if the buffer was not accepted.
+//
+//*****************************************************************************
+uint32_t
+USBSoundBufferOut(const void *pvBuffer, uint32_t ui32Size,
+ tUSBBufferCallback pfnCallback)
+{
+ //
+ // If there is no device present or there is a pending buffer then just
+ // return with a failure.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(0);
+ }
+
+ //
+ // Save this buffer callback.
+ //
+ g_sAudioState.pfnCallbackOut = pfnCallback;
+
+ //
+ // Pass the buffer aint32_t to the USB host audio driver for playback.
+ //
+ return(USBHostAudioPlay(g_psAudioInstance, (void *)pvBuffer, ui32Size,
+ USBHostAudioCallback));
+}
+
+//*****************************************************************************
+//
+// Requests a new block of PCM audio samples from a USB audio device.
+//
+// \param pvBuffer is a pointer to a location to store the audio data.
+// \param ui32Size is the size of the pvData buffer in bytes.
+// \param pfnCallback is a function to call when this buffer has new data.
+//
+// This function request a new block of PCM audio samples from a USB audio
+// device.
+//
+// \return This function returns a non-zero value if the buffer was accepted,
+// and returns zero if the buffer was not accepted.
+//
+//*****************************************************************************
+uint32_t
+USBSoundBufferIn(const void *pvBuffer, uint32_t ui32Size,
+ tUSBBufferCallback pfnCallback)
+{
+ //
+ // If there is no device present or there is a pending buffer then just
+ // return with a failure.
+ //
+ if(g_sAudioState.eState != STATE_DEVICE_READY)
+ {
+ return(0);
+ }
+
+ //
+ // Save this buffer callback.
+ //
+ g_sAudioState.pfnCallbackIn = pfnCallback;
+
+ //
+ // Pass the buffer aint32_t to the USB host audio driver for input.
+ //
+ return(USBHostAudioRecord(g_psAudioInstance, (void *)pvBuffer, ui32Size,
+ USBHostAudioCallback));
+}
+
+//*****************************************************************************
+//
+// This function reads the audio volume settings for the USB audio device and
+// saves them so that the volume can be scaled correctly.
+//
+//*****************************************************************************
+static void
+GetVolumeParameters(void)
+{
+ uint32_t ui32Max, ui32Min, ui32Res, ui32Channel;
+
+ for(ui32Channel = 0; ui32Channel < 3; ui32Channel++)
+ {
+ ui32Max = USBHostAudioVolumeMaxGet(g_psAudioInstance, 0, ui32Channel);
+ ui32Min = USBHostAudioVolumeMinGet(g_psAudioInstance, 0, ui32Channel);
+ ui32Res = USBHostAudioVolumeResGet(g_psAudioInstance, 0, ui32Channel);
+
+ g_sAudioState.pui32Steps[ui32Channel] = (ui32Max - ui32Min) / ui32Res;
+ }
+}
+
+//*****************************************************************************
+//
+// The main routine for handling USB audio, this should be called periodically
+// by the main program and pass in the amount of time in milliseconds that has
+// elapsed since the last call.
+//
+//*****************************************************************************
+void
+USBMain(uint32_t ui32Ticks)
+{
+ //
+ // Tell the OTG library code how much time has passed in
+ // milliseconds since the last call.
+ //
+ USBOTGMain(ui32Ticks);
+
+ switch(g_sAudioState.eState)
+ {
+ //
+ // This is the running state where buttons are checked and the
+ // screen is updated.
+ //
+ case STATE_DEVICE_READY:
+ {
+ if(HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE))
+ {
+ HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE) = 0;
+ g_sAudioState.eState = STATE_NO_DEVICE;
+
+ //
+ // Call the general event handler if present.
+ //
+ if(g_sAudioState.pfnCallbackEvent)
+ {
+ g_sAudioState.pfnCallbackEvent(SOUND_EVENT_DISCONNECT, 0);
+ }
+ }
+ break;
+ }
+
+ //
+ // If there is no device then just wait for one.
+ //
+ case STATE_NO_DEVICE:
+ {
+ if(HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN))
+ {
+ g_sAudioState.eState = STATE_DEVICE_READY;
+
+ HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN) = 0;
+
+ GetVolumeParameters();
+
+ //
+ // Call the general event handler if present.
+ //
+ if(g_sAudioState.pfnCallbackEvent)
+ {
+ g_sAudioState.pfnCallbackEvent(SOUND_EVENT_READY, 0);
+ }
+ }
+ break;
+ }
+
+ //
+ // An unknown device was connected.
+ //
+ case STATE_UNKNOWN_DEVICE:
+ {
+ break;
+ }
+
+ //
+ // Something has caused a power fault.
+ //
+ case STATE_POWER_FAULT:
+ {
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
diff --git a/boards/ek-lm4f232/drivers/usb_sound.h b/boards/ek-lm4f232/drivers/usb_sound.h
new file mode 100644
index 0000000..04bf459
--- /dev/null
+++ b/boards/ek-lm4f232/drivers/usb_sound.h
@@ -0,0 +1,81 @@
+//*****************************************************************************
+//
+// usb_sound.h - USB host audio handling header definitions.
+//
+// Copyright (c) 2012-2014 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 2.1.0.12573 of the EK-LM4F232 Firmware Package.
+//
+//*****************************************************************************
+
+#ifndef USB_SOUND_H_
+#define USB_SOUND_H_
+
+//*****************************************************************************
+//
+// The following are defines for the ui32Event value that is returned with the
+// tEventCallback function provided to the USBSoundInit() function.
+//
+//*****************************************************************************
+
+//
+// A USB audio device has been connected.
+//
+#define SOUND_EVENT_READY 0x00000001
+
+//
+// A USB device has been disconnected.
+//
+#define SOUND_EVENT_DISCONNECT 0x00000002
+
+//
+// An unknown device has been connected.
+//
+#define SOUND_EVENT_UNKNOWN_DEV 0x00000003
+
+typedef void (* tUSBBufferCallback)(void *pvBuffer, uint32_t ui32Event);
+typedef void (* tEventCallback)(uint32_t ui32Event, uint32_t ui32Param);
+
+extern void USBMain(uint32_t ui32Ticks);
+
+extern void USBSoundInit(uint32_t ui32EnableReceive,
+ tEventCallback pfnCallback);
+extern void USBSoundVolumeSet(uint32_t ui32Percent);
+extern uint32_t USBSoundVolumeGet(uint32_t ui32Channel);
+
+extern uint32_t USBSoundOutputFormatGet(uint32_t ui32SampleRate,
+ uint32_t ui32Bits,
+ uint32_t ui32Channels);
+extern uint32_t USBSoundOutputFormatSet(uint32_t ui32SampleRate,
+ uint32_t ui32Bits,
+ uint32_t ui32Channels);
+extern uint32_t USBSoundInputFormatGet(uint32_t ui32SampleRate,
+ uint32_t ui32BitsPerSample,
+ uint32_t ui32Channels);
+extern uint32_t USBSoundInputFormatSet(uint32_t ui32SampleRate,
+ uint32_t ui32Bits,
+ uint32_t ui32Channels);
+
+extern uint32_t USBSoundBufferOut(const void *pvData,
+ uint32_t ui32Length,
+ tUSBBufferCallback pfnCallback);
+
+extern uint32_t USBSoundBufferIn(const void *pvData,
+ uint32_t ui32Length,
+ tUSBBufferCallback pfnCallback);
+
+#endif