192 lines
4.4 KiB
C
192 lines
4.4 KiB
C
//ColorChordEmbedded implementation on the STM32F407 for the stm32f4-discovery.
|
|
//Uses on-board microphone and outputs WS2812 signal for configurable number of LEDs
|
|
//on PB5 via DMA+SPI
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <systems.h>
|
|
#include <math.h>
|
|
#include <stm32f4xx_exti.h>
|
|
#include <DFT32.h>
|
|
#include <embeddednf.h>
|
|
#include <embeddedout.h>
|
|
#include "spi2812.h"
|
|
#include "adc.h"
|
|
|
|
volatile int wasclicked = 0; //Used for if the root change button was clicked.
|
|
|
|
RCC_ClocksTypeDef RCC_Clocks;
|
|
|
|
|
|
//Circular buffer for incoming data so we don't spend much time servicing the interrupt and we can handle colorchord in the main thread.
|
|
#define CIRCBUFSIZE 256
|
|
volatile int last_samp_pos;
|
|
int16_t sampbuff[CIRCBUFSIZE];
|
|
volatile int samples;
|
|
|
|
//This gets called by the ADC/Microphone
|
|
void GotSample( int samp )
|
|
{
|
|
//printf("[GOT-SMP] %d\r\n", samp);
|
|
sampbuff[last_samp_pos] = samp;
|
|
last_samp_pos = ((last_samp_pos+1)%CIRCBUFSIZE);
|
|
samples++;
|
|
}
|
|
|
|
//Call this once we've stacked together one full colorchord frame.
|
|
void NewFrame()
|
|
{
|
|
// uint8_t led_outs[NUM_LIN_LEDS*3];
|
|
int i;
|
|
HandleFrameInfo();
|
|
|
|
UpdateLinearLEDs();
|
|
//UpdateAllSameLEDs();
|
|
|
|
SendSPI2812( ledOut, NUM_LIN_LEDS );
|
|
}
|
|
|
|
|
|
void Configure_PA0(void) {
|
|
/* Set variables used */
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
EXTI_InitTypeDef EXTI_InitStruct;
|
|
NVIC_InitTypeDef NVIC_InitStruct;
|
|
|
|
/* Enable clock for GPIOD */
|
|
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
|
|
/* Enable clock for SYSCFG */
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
|
|
|
/* Set pin as input */
|
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
|
|
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
|
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
|
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
|
|
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
|
|
/* Tell system that you will use PA0 for EXTI_Line0 */
|
|
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
|
|
|
|
/* PA0 is connected to EXTI_Line0 */
|
|
EXTI_InitStruct.EXTI_Line = EXTI_Line0;
|
|
/* Enable interrupt */
|
|
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
|
|
/* Interrupt mode */
|
|
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
|
|
/* Triggers on rising and falling edge */
|
|
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
|
|
/* Add to EXTI */
|
|
EXTI_Init(&EXTI_InitStruct);
|
|
|
|
/* Add IRQ vector to NVIC */
|
|
/* PA0 is connected to EXTI_Line0, which has EXTI0_IRQn vector */
|
|
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
|
|
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00; /* Set priority */
|
|
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; /* Set sub priority */
|
|
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; /* Enable interrupt */
|
|
NVIC_Init(&NVIC_InitStruct); /* Add to NVIC */
|
|
}
|
|
|
|
//Handle button press on PA0.
|
|
void EXTI0_IRQHandler(void)
|
|
{
|
|
static int rootoffset;
|
|
|
|
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
|
|
{
|
|
if( wasclicked == 0 )
|
|
wasclicked = 10;
|
|
EXTI_ClearITPendingBit(EXTI_Line0);
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
uint32_t i = 0;
|
|
|
|
RCC_GetClocksFreq( &RCC_Clocks );
|
|
|
|
ConfigureLED();
|
|
|
|
LED_OFF;
|
|
|
|
// SysTick end of count event each 10ms
|
|
SysTick_Config( RCC_Clocks.HCLK_Frequency / 100);
|
|
|
|
float fv = RCC_Clocks.HCLK_Frequency / 1000000.0f;
|
|
|
|
ConfigureUART();
|
|
InitColorChord();
|
|
Configure_PA0();
|
|
InitSPI2812();
|
|
adc_init();
|
|
|
|
printf("Operating at %.3fMHz\r\n", fv );
|
|
|
|
int this_samp = 0;
|
|
int wf = 0;
|
|
|
|
|
|
LED_ON;
|
|
|
|
int c = 1;
|
|
while (1) {
|
|
for (int a=0; a < NUM_LIN_LEDS; a++) {
|
|
ledOut[a*3 + 0] = c/2;
|
|
ledOut[a*3 + 1] = (64-c)/2 % 255;
|
|
ledOut[a*3 + 2] = a/8 % 256;
|
|
}
|
|
|
|
SendSPI2812(ledOut, NUM_LIN_LEDS);
|
|
_delay_us(10*1000);
|
|
c++;
|
|
if (c==64)
|
|
break;
|
|
}
|
|
|
|
|
|
SendSPI2812(ledOut, NUM_LIN_LEDS);
|
|
while(1)
|
|
{
|
|
if( this_samp != last_samp_pos )
|
|
{
|
|
LED_OFF; //Use led on the board to show us how much CPU we're using. (You can also probe PB15)
|
|
|
|
PushSample32( sampbuff[this_samp] ); //Can't put in full volume. (here was /2)
|
|
|
|
this_samp = (this_samp+1)%CIRCBUFSIZE;
|
|
|
|
wf++;
|
|
if( wf == 128 )
|
|
{
|
|
NewFrame();
|
|
wf = 0;
|
|
}
|
|
LED_ON;
|
|
}
|
|
LED_ON; //Take up a little more time to make sure we don't miss this.
|
|
}
|
|
}
|
|
|
|
void TimingDelay_Decrement()
|
|
{
|
|
static int rootoffset;
|
|
|
|
//A way of making sure we debounce the button.
|
|
if( wasclicked )
|
|
{
|
|
if( wasclicked == 10 )
|
|
{
|
|
if( rootoffset++ >= 12 ) rootoffset = 0;
|
|
RootNoteOffset = (rootoffset * NOTERANGE) / 12;
|
|
}
|
|
|
|
wasclicked--;
|
|
}
|
|
|
|
}
|
|
|
|
|