Skip to content

Instantly share code, notes, and snippets.

@darconeous
Created March 25, 2018 05:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darconeous/98791c78538959c21590d0b205d351ec to your computer and use it in GitHub Desktop.
Save darconeous/98791c78538959c21590d0b205d351ec to your computer and use it in GitHub Desktop.
ATTiny LED Twinkler
/* ATTiny LED Twinkler
*
* This is come code I wrote a while back to "twinkle"
* four GPIO outputs that would drive LEDs. It was designed
* to be run on an eight-pin ATTiny13 chip. It works
* quite well, even considering how inefficient it is.
*
* - Robert Quattlebaum, 2012
*/
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#define sbi(x,y) x|=(1<<y)
#define cbi(x,y) x&=~(1<<y)
void delay_ms(uint8_t ms) {
uint16_t delay_count = F_CPU / 17500;
volatile uint16_t i;
while(ms!=0) {
for(i=0;i!=delay_count;i++);
wdt_reset();
ms--;
}
}
#define LED0_on() sbi(PORTB,0)
#define LED1_on() sbi(PORTB,4)
#define LED2_on() sbi(PORTB,3)
#define LED3_on() sbi(PORTB,1)
#define LED0_off() cbi(PORTB,0)
#define LED1_off() cbi(PORTB,4)
#define LED2_off() cbi(PORTB,3)
#define LED3_off() cbi(PORTB,1)
uint8_t led0_v=200;
uint16_t led0_e;
uint16_t led1_v=200;
uint16_t led1_e;
uint16_t led2_v=200;
uint16_t led2_e;
uint16_t led3_v=200;
uint16_t led3_e;
#if 0
#define add_ret_c(x,y) (asm volatile ( \
"clr __tmp_reg__\n" \
"add %0, %1\n" \
"adc __tmp_reg__, __zero_reg__\n" \
: \
"=r" (x), \
"=r" (y) \
),r0)
#else
uint16_t argh;
#define add_ret_c(x,y) ( argh=x, x+=y, argh<x )
#endif
void update_leds() {
if(add_ret_c(led0_e,led0_v*led0_v))
LED0_on();
else
LED0_off();
if(add_ret_c(led1_e,led1_v*led1_v))
LED1_on();
else
LED1_off();
if(add_ret_c(led2_e,led2_v*led2_v))
LED2_on();
else
LED2_off();
if(add_ret_c(led3_e,led3_v*led3_v))
LED3_on();
else
LED3_off();
}
ISR(TIM0_COMPA_vect) {
update_leds();
}
uint8_t fastrand() {
static uint8_t ret;
ret*=97;
ret+=101;
return ret;
}
void main(void) {
int i;
// Stop the timer, if it happens to be running.
TCCR0B = 0;
OCR0A = 128;
TCNT0 = 0; // Reset counter.
// Start timer with prescaler of 1/8.
TCCR0B = (1 << 1);
sbi(TIMSK0, OCIE0A);
// Enable interrupts.
sei();
// LED 0 = B0
// LED 1 = B4
// LED 2 = B3
// LED 3 = B1
sbi(DDRB,0);
sbi(DDRB,4);
sbi(DDRB,3);
sbi(DDRB,1);
uint8_t led0_t=fastrand();
uint8_t led1_t=fastrand();
uint8_t led2_t=fastrand();
uint8_t led3_t=fastrand();
led0_v=fastrand();
led1_v=fastrand();
led2_v=fastrand();
led3_v=fastrand();
while(1) {
if(led0_t==led0_v) led0_t=fastrand();
if(led1_t==led1_v) led1_t=fastrand();
if(led2_t==led2_v) led2_t=fastrand();
if(led3_t==led3_v) led3_t=fastrand();
if(led0_t<led0_v) led0_v--;
else led0_v++;
if(led1_t<led1_v) led1_v--;
else led1_v++;
if(led2_t<led2_v) led2_v--;
else led2_v++;
if(led3_t<led3_v) led3_v--;
else led3_v++;
delay_ms(2);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment