Created
June 13, 2018 09:57
-
-
Save dpslwk/607e6281ed98e765ea6db4d4ab25a0cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//***************************************************************************** | |
// | |
// very hacked together WS2812 example for the MPS432E4 | |
// baseed on https://github.com/joewa/WS2812-LED-Driver_ChibiOS | |
// and some bits to come from https://github.com/hubmartin/STM32F4_WS2812B | |
// and http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library | |
//***************************************************************************** | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include "ti/devices/msp432e4/driverlib/driverlib.h" | |
//***************************************************************************** | |
// | |
// The error routine that is called if the driver library encounters an error. | |
// | |
//***************************************************************************** | |
#ifdef DEBUG | |
void | |
__error__(char *pcFilename, uint32_t ui32Line) | |
{ | |
} | |
#endif | |
/* The control table used by the uDMA controller. This table must be aligned | |
* to a 1024 byte boundary. */ | |
#if defined(__ICCARM__) | |
#pragma data_alignment=1024 | |
uint8_t pui8ControlTable[1024]; | |
#elif defined(__TI_ARM__) | |
#pragma DATA_ALIGN(pui8ControlTable, 1024) | |
uint8_t pui8ControlTable[1024]; | |
#else | |
uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024))); | |
#endif | |
#define WS2812_LED_N 2 // Number of LEDs | |
#define WS2812_RESET_BIT_N (30) | |
#define WS2812_COLOR_BIT_N (WS2812_LED_N*24) /**< Number of data bits */ | |
#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ | |
#define WS_800HZ 800000 | |
#define WS_400HZ 400000 | |
#define WS_FREQ WS_800HZ | |
#define SYSCLOCK 120000000 | |
#define WS2812_TIMER_INTVAL (SYSCLOCK/WS_FREQ) | |
#define WS2812_DUTYCYCLE_0 ((10*WS2812_TIMER_INTVAL)/15) | |
#define WS2812_DUTYCYCLE_1 ((10*WS2812_TIMER_INTVAL)/36) | |
#define WS2812_DUTYCYCLE_RESET (WS2812_TIMER_INTVAL-1) | |
#define WS2812_BIT(led, byte, bit) (24*(led) + 8*(byte) + (7 - (bit))) | |
#define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit)) | |
#define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit)) | |
#define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) | |
static uint32_t ws2812_frame_buffer[WS2812_BIT_N]; | |
volatile bool bWsDMADoneFlag; | |
void | |
TIMER3B_IRQHandler(void) | |
{ | |
uint32_t getTimerIntStatus; | |
/* Get the timer interrupt status and clear the same */ | |
getTimerIntStatus = MAP_TimerIntStatus(TIMER3_BASE, true); | |
MAP_TimerIntClear(TIMER3_BASE, getTimerIntStatus); | |
MAP_uDMAChannelTransferSet(UDMA_CH3_TIMER3B | UDMA_PRI_SELECT, | |
UDMA_MODE_BASIC, | |
(void *)&ws2812_frame_buffer, (void*)&TIMER3->TAMATCHR, | |
sizeof(ws2812_frame_buffer)/4); | |
MAP_uDMAChannelEnable(UDMA_CH3_TIMER3B); | |
} | |
int ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b) | |
{ | |
// Check for valid LED | |
if (led_number >= WS2812_LED_N) return 1; | |
// Write color to frame buffer | |
uint32_t bit; | |
for (bit = 0; bit < 8; bit++) { | |
ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | |
ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | |
ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | |
} | |
// Success | |
return 0; | |
} | |
//***************************************************************************** | |
// | |
// This example application demonstrates the use of the timers to generate | |
// periodic interrupts. | |
// | |
//***************************************************************************** | |
int | |
main(void) | |
{ | |
// | |
// Set the clocking to run directly from the crystal at 120MHz. | |
// | |
MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | | |
SYSCTL_OSC_MAIN | | |
SYSCTL_USE_PLL | | |
SYSCTL_CFG_VCO_480), SYSCLOCK); | |
uint32_t i; | |
for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle | |
ws2812_frame_buffer[WS2812_COLOR_BIT_N] = WS2812_DUTYCYCLE_0; // stupid GMTP, just push out one more 0 before we start the reset latch | |
for (i = 1; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = WS2812_DUTYCYCLE_RESET; // All reset bits are zero | |
// | |
// Enable processor interrupts. | |
// | |
MAP_IntMasterEnable(); | |
// LWK neo | |
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); | |
MAP_GPIOPinConfigure(GPIO_PD4_T3CCP0); | |
MAP_GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_4); | |
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3); | |
MAP_TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PERIODIC_UP); | |
MAP_TimerLoadSet(TIMER3_BASE, TIMER_BOTH, WS2812_TIMER_INTVAL); | |
MAP_TimerMatchSet(TIMER3_BASE, TIMER_A, WS2812_TIMER_INTVAL-1); | |
MAP_TimerIntEnable(TIMER3_BASE, TIMER_TIMB_DMA); | |
MAP_TimerDMAEventSet(TIMER3_BASE, TIMER_DMA_TIMEOUT_B); | |
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); | |
MAP_uDMAEnable(); | |
MAP_uDMAControlBaseSet(pui8ControlTable); | |
MAP_uDMAChannelAssign(UDMA_CH3_TIMER3B); | |
MAP_uDMAChannelAttributeDisable(UDMA_CH3_TIMER3B, | |
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | | |
UDMA_ATTR_HIGH_PRIORITY | | |
UDMA_ATTR_REQMASK); | |
MAP_uDMAChannelAttributeEnable(UDMA_CH3_TIMER3B, | |
UDMA_ATTR_HIGH_PRIORITY | |
); | |
MAP_uDMAChannelControlSet(UDMA_CH3_TIMER3B | UDMA_PRI_SELECT, | |
UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE | | |
UDMA_ARB_1); | |
MAP_uDMAChannelTransferSet(UDMA_CH3_TIMER3B | UDMA_PRI_SELECT, | |
UDMA_MODE_BASIC, | |
(void *)&ws2812_frame_buffer, (void*)&TIMER3->TAMATCHR, | |
sizeof(ws2812_frame_buffer)/4); | |
MAP_uDMAChannelEnable(UDMA_CH3_TIMER3B); | |
MAP_IntEnable(INT_TIMER3B); | |
bWsDMADoneFlag = 0; | |
MAP_TimerEnable(TIMER3_BASE, TIMER_BOTH); | |
int s = 0; | |
while(1) | |
{ | |
for (int n = 0; n < WS2812_LED_N; n++) { | |
int s0 = s + 10*n; | |
ws2812_write_led(n, s0%255, (s0+85)%255, (s0+170)%255); | |
} | |
s += 10; | |
MAP_SysCtlDelay(g_ui32SysClock/2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment