 # ATtiny13 – disco lights using DFT

This is my another “disco lights” project which is an upgraded version of ATtiny13 – dance lights with DFT. This time I used a full implementation of optimized DFT algorithm with reduced memory access to compute a power spectrum of audio signal. This version has also 3-channel lights but visual effects are much-much better!

## Circuit Diagram ## Software

This code is written in C and can be compiled using the avr-gcc. All information about how to compile this project is here.

```/**
* Copyright (c) 2019, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
* ATtiny13/026
* Disco lights using DFT (Discrete Fourier Transformation)
*/

#include <avr/io.h>
#include <avr/interrupt.h>

#define LED_LOW              PB0
#define LED_MID              PB1
#define LED_HIGH             PB2

#define LOW_THRESHOLD        (48000UL)
#define MID_THRESHOLD        (128)
#define HIGH_THRESHOLD       (64)

#define N                    (7) // N-points (DFT)
#define B                    (3 * N / 4) // b-value (DFT)

const int8_t W[N] = {10, 6, -2, -9, -9, -2, 6}; // twiddle factors (DFT)
int8_t samples[N]; // raw samples (ADC)
uint16_t power[N>>1]; // power spectrum (DFT)
volatile uint8_t counter = 0;

static void dft(void);

int
main(void)
{

/* setup */
DDRB |= _BV(LED_LOW)|_BV(LED_MID)|_BV(LED_HIGH); // set LED pins as OUTPUT
ADMUX = _BV(MUX1); // set ADC4 (PB4) as audio input
sei(); // enable global interrupts

ADCSRA |= _BV(ADSC); // start first signal acquisition

/* loop */
while (1) {
if (counter == N) {
dft(); // do some DSP

/* LOW freqency band */
if (power > LOW_THRESHOLD) {
PORTB |= _BV(LED_LOW);
} else {
PORTB &= ~_BV(LED_LOW);
}

/* MID freqency band */
if (power > MID_THRESHOLD) {
PORTB |= _BV(LED_MID);
} else {
PORTB &= ~_BV(LED_MID);
}

/* HIGH frequency band */
if (power > HIGH_THRESHOLD) {
PORTB |= _BV(LED_HIGH);
} else {
PORTB &= ~_BV(LED_HIGH);
}

counter = 0; // reset samples counter
ADCSRA |= _BV(ADSC); // trigger next signal acqusistion
}
}
}

{

if (counter < N) {
samples[counter++] = ADCH - 128; // read raw sample <-128; 127>
ADCSRA |= _BV(ADSC); // trigger next signal acquisition
}
}

/**
* Twiddle-factor-based DFT algorithm with reduced memory access.
*/
void
dft(void)
{
uint8_t a, b, i, j;
int16_t re[N];
int16_t im[N];

for (i = 0; i < N; ++i) {
re[i] = 0;
im[i] = 0;
}

for (i = 0; i < (N>>1); ++i) {
a = 0;
b = B;
for (j = 0; j < N; ++j) {
re[i] += W[a%N] * samples[j];
im[i] -= W[b%N] * samples[j];
a += i;
b += i;
}
power[i] = (re[i] * re[i] + im[i] * im[i]) >> 4;
}
}```

### 6 thoughts on “ATtiny13 – disco lights using DFT”

1. Sven

Hi, great little project!
it’s working for me. I did the upload using Arduino IDE.
I am using an arduino nano to program attiny with Arduino IDE software.

Board: DiY ATtiny13 (in my case, does work only by choosing this board; otherwise, there is an DFP error)
Programmer: Arduino as ISP

If you have no 100k trim resistor, just use something below 100k. I am using 68k.

thanks a lot!

2. jumi

Hi,

please provide hex code and how should fuse settings be

3. Łukasz Podkalicki

Yes, should be fine. I’ve edited this page few days ago and I forgot to change function definition. Sorry for that. Now is up to date.

4. Jack

I use MkCLIPSE
logs:
main.c:45:13: warning: implicit declaration of function ‘dft’ [-Wimplicit-function-declaration]
dft(); // do some DSP
^
main.c: At top level:
main.c:87:1: warning: conflicting types for ‘dft’
dft(void)
^
main.c:45:13: note: previous implicit declaration of ‘dft’ was here
dft(); // do some DSP
^
main.c:26:13: warning: ‘fft’ declared ‘static’ but never defined [-Wunused-function]
static void fft(void);

I fixed the code, but I’m not sure it’s okay (now I can compile)

#include
#include

#define LED_LOW PB0
#define LED_MID PB1
#define LED_HIGH PB2

#define LOW_THRESHOLD (48000UL)
#define MID_THRESHOLD (128)
#define HIGH_THRESHOLD (64)

#define N (7) // N-points (FFT)
#define B (3 * N / 4) // b-value (FFT)

const int8_t W[N] = {10, 6, -2, -9, -9, -2, 6}; // twiddle factors (FFT)
int8_t samples[N]; // raw samples (ADC)
uint16_t power[N>>1]; // power spectrum (FFT)
volatile uint8_t counter = 0;

{

if (counter < N) {
samples[counter++] = ADCH – 128; // read raw sample
ADCSRA |= _BV(ADSC); // trigger next signal acquisition
}
}

static void
dft(void)
{
uint8_t a, b, i, j;
int16_t re[N];
int16_t im[N];

for (i = 0; i < N; ++i) {
re[i] = 0;
im[i] = 0;
}

for (i = 0; i >1); ++i) {
a = 0;
b = B;
for (j = 0; j > 4;
}
}

int
main(void)
{

/* setup */
DDRB |= _BV(LED_LOW)|_BV(LED_MID)|_BV(LED_HIGH); // set LED pins as OUTPUT
ADMUX = _BV(MUX1); // set ADC4 (PB4) as audio input
sei(); // enable global interrupts

ADCSRA |= _BV(ADSC); // start first signal acquisition

/* loop */
while (1) {
if (counter == N) {
dft(); // do some DSP

/* LOW freqency band */
if (power > LOW_THRESHOLD) {
PORTB |= _BV(LED_LOW);
} else {
PORTB &= ~_BV(LED_LOW);
}

/* MID freqency band */
if (power > MID_THRESHOLD) {
PORTB |= _BV(LED_MID);
} else {
PORTB &= ~_BV(LED_MID);
}

/* HIGH frequency band */
if (power > HIGH_THRESHOLD) {
PORTB |= _BV(LED_HIGH);
} else {
PORTB &= ~_BV(LED_HIGH);
}

counter = 0; // reset samples counter
ADCSRA |= _BV(ADSC); // trigger next signal acqusistion
}
}
}

5. Jack

Hi
I have a code problem, my compiler shows a bug in “dft(); // do some DSP ”
How can I solve this?

• Łukasz Podkalicki

Hi Jacek,
could provide some logs describing this error?

Btw. in a december edition an EP (Elektronika Praktyczna) will publish my article about optimized DFT for microcontrollers. If it’s something you would like to dive deeper then I recommend to read it.
/L