ATtiny26 controlling 12 leds with 4 IO-lines with charlieplexing
Source code for blinking leds
/*
cycle 12 leds with attiny2313
Tomi Leppikangas 25.5.2010
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
typedef struct {
uint8_t ddr;
uint8_t bits;
} leds_t;
/* bit values for 12 leds */
const leds_t led_values [] PROGMEM = {
// 3210 3210
{ 0b00001100, 0b00000100 }, // 1
{ 0b00000110, 0b00000010 }, // 2
{ 0b00000011, 0b00000001 }, // 3
{ 0b00000011, 0b00000010 }, // 4
{ 0b00000110, 0b00000100 }, // 5
{ 0b00001100, 0b00001000 }, // 6
{ 0b00001010, 0b00001000 }, // 7
{ 0b00001010, 0b00000010 }, // 8
{ 0b00001001, 0b00000001 }, // 9
{ 0b00001001, 0b00001000 }, // 10
{ 0b00000101, 0b00000100 }, // 11
{ 0b00000101, 0b00000001 }, // 12
};
volatile uint8_t current = 0; // current led
volatile uint8_t old[3] = {0}; // old leds
/* timer/counter0 compare interrupt */
ISR(TIMER0_COMPA_vect)
{
static uint8_t count = 0;
if(count <20) {
DDRB = pgm_read_byte(&led_values[current].ddr);
PORTB = pgm_read_byte(&led_values[current].bits);
} else if(count < 30) {
DDRB = pgm_read_byte(&led_values[old[0]].ddr);
PORTB = pgm_read_byte(&led_values[old[0]].bits);
} else if(count < 35) {
DDRB = pgm_read_byte(&led_values[old[1]].ddr);
PORTB = pgm_read_byte(&led_values[old[1]].bits);
} else {
DDRB = pgm_read_byte(&led_values[old[2]].ddr);
PORTB = pgm_read_byte(&led_values[old[2]].bits);
}
count ++;
if(count == 36) count = 0;
}
/* timer/counter1 compare interrupt */
ISR(TIMER1_COMPA_vect)
{
static int8_t direction = 1;
old[2] = old[1]; // remember old leds
old[1] = old[0];
old[0] = current;
current = current + direction;
if(current == 11) direction = -1;
else if (current == 0) direction = 1;
}
int main(void)
{
// init timer 0
TCCR0A |= (1<<WGM01); // CTC
TCCR0B |= (1<<CS02 | 1<<CS00); // scale 1024
TIMSK |= (1<<OCIE0A); // enable output compare int a
OCR0A = 1;
// init timer 1 t
TCCR1A &= ~(1<<WGM11 | 1<<WGM10); // CTC
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12 | 1<<CS12 ); // CTC + scale 256
TIMSK |= (1<<OCIE1A); // enable output compare int a
OCR1A = F_CPU/256/20;
//OCR1AL = 1000;
DDRB |= (1 << PB0); // port B0 out
DDRB |= (1 << PB1); // port B1 out
PORTB |= (1 << PB0); // BO = 1
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
sei();
while(1) {
sleep_cpu();
}
return 0;
}
Tomi Leppikangas 27.5.2010 [home]