Created
March 25, 2018 05:10
-
-
Save darconeous/98791c78538959c21590d0b205d351ec to your computer and use it in GitHub Desktop.
ATTiny LED Twinkler
This file contains 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
/* 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