ATtiny10 Button fun

There were several ATtiny Buttons.. So I thought I would make one out of an ATtiny10 (which I'm sure has been done before..). But here is how I made this one. Its now a very nice Fridge Magnet.

This is just 2 modes.. I just had the PCB's made at OshPark.. I love there work..

Actual size of ATtiny10

/*

* Tiny 10 Button

* Sherman Stebbins

* 2021-10-21

*

* Firmware v1 updated 11/28/21

* added use of reset button to change modes:

* 1 Light Check, Diagnostics

* 2 Alternate mode

* 3 Circle back and forth

* 4 round fast and slow

* 5 random flash

* 6 strobe mode

*

* Attiny10

; +====+

; SCK -> PB0 |* | PB3 (RESET)

; GND | | Vcc

; MOSI -> PB1 | | PB2

; +====+



Test showed in sleep .09uA !!!!!!

*/

#include <util/delay.h>

#define F_CPU 1000000UL

#define MAXLEDS 6

#define EXT_RESET (1 << EXTRF)


volatile unsigned char count __attribute__((section(".noinit"))); // Not cleared on RESET


//DDRB direction config for each LED (1 = output)

const uint8_t led_dir[7] = {


( 1<<PB0 | 1<<PB1 ),

( 1<<PB0 | 1<<PB1 ),

( 1<<PB1 | 1<<PB2 ),

( 1<<PB0 | 1<<PB2 ),

( 1<<PB0 | 1<<PB2 ),

( 1<<PB1 | 1<<PB2 ),

};


//PORTB output config for each LED (1 = High, 0 = Low)

const uint8_t led_out[7] = {

( 1<<PB0 ),

( 1<<PB1 ),

( 1<<PB2 ),

( 1<<PB0 ),

( 1<<PB2 ),

( 1<<PB1 ),

};


//sudo random, not really

const uint8_t ledRand[5][6] = {

{3,2,5,0,1,4},

{1,3,5,2,0,4},

{4,0,3,1,5,2},

{2,4,0,5,1,3},

{0,3,1,2,4,5}

};


int main(void){


//reset status page 52 datasheet:

if ((RSTFLR & EXT_RESET) != 0) {

// If External RESET then increment count and output to pins

RSTFLR = RSTFLR & ~EXT_RESET; //for attiny10

count++; //change mode

}

if (count>5){

count=0;

}

//count=5; //for debug

while(1){

switch(count){

case 0:

flashAll(0);

//for(int i=0;i<2;i++){

lightCheck();

allOff();

_delay_ms(500);

//}

break;


case 1: //Alternate mode

flashAll(1);

for(uint8_t i=0;i<10;i++){

for(uint8_t j=0;j<50;j++){ //50 is max

alternateLed(j);

}

for(uint8_t j=50;j>0;j++){ //50 is max

alternateLed(j);

}

}

break;

case 2: //back and forth

flashAll(2);

for(uint8_t k=0;k<10;k++){

for(uint8_t i=40;i>0;i--){

for(int8_t j = 5; j >= 0; j--){ //had to change to int8_t for backwards to work

lightLed(j);

my_delay_ms(2*i);

}

for(uint8_t j = 0;j<MAXLEDS;j++){

lightLed(j);

my_delay_ms(2*i);

}

}

for(uint8_t i=0;i<40;i++){

for(uint8_t j = 0;j<MAXLEDS;j++){

lightLed(j);

my_delay_ms(2*i);

}

}

}

break;


case 3: //round fast and slow

flashAll(3);

for(uint8_t k=0;k<10;k++){

for(uint8_t i=0;i<40;i++){

for(uint8_t j = 0;j<MAXLEDS;j++){

lightLed(j);

my_delay_ms(2*i);

}

}

for(uint8_t i=40;i>0;i--){

for(uint8_t j = 0;j<MAXLEDS;j++){

lightLed(j);

my_delay_ms(2*i);

}

}

}

break;

case 4: //random flash

flashAll(4);

for(uint8_t i=0;i<40;i++){

for(uint8_t j=0;j<5;j++){

for(uint8_t i=0;i<MAXLEDS;i++){

//lightLed(ledRand[1][i]);

DDRB = led_dir[ledRand[j][i]];

PORTB = led_out[ledRand[j][i]];

_delay_ms(150);

}

}

}

break;

case 5:

for(uint8_t j=0;j<10;j++){

for(uint8_t i=0;i<40;i++){

allOn(2*i);

allOff();

my_delay_ms(2*i);

}

allOff();

for(uint8_t c=40;c>=1;c--){

allOff();

for(int i;i<1000;i++){

_delay_ms(1);

}

allOn(2*c);

my_delay_ms(50);

}

}


default:

// hearBeat();

break;

}

allOn(400); //4 sec

allOff();

goToSleep(); //go to sleep.. no wake up other then reset.

}

}


void lightLed(uint8_t led_num) {

DDRB = led_dir[led_num];

PORTB = led_out[led_num];

}


void allOff() {

DDRB = 0;

//PORTB = 0b00000000;

}


void allOn(int loops){

for(int i=0;i<loops;i++){

for(int j=0;j<MAXLEDS;j++){

lightLed(j);

_delay_ms(1);

}

}

allOff();

}


void my_delay_ms(uint16_t n){

while(n--) {

_delay_ms(1);

}

}


void flashAll(uint8_t flashCount){

for(uint8_t i=0;i<=flashCount;i++){

allOn(100); //1 second

_delay_ms(250);

allOff();

_delay_ms(250);

}

_delay_ms(700);

}

void alternateLed(uint8_t speed){

if(speed>50){speed=50;}

for(uint8_t i=0;i<speed;i++){

for(uint8_t i=0;i<MAXLEDS;i+=2){

lightLed(i);

_delay_ms(1);

}

//_delay_ms(500);

}

for(uint8_t i=0;i<speed;i++){

for(uint8_t i=1;i<MAXLEDS;i+=2){

lightLed(i);

_delay_ms(1);

}

}

}

/*

static uint16_t prng_lfsr16(void)

{

static uint16_t cnt16 = LFSR_SEED;

return (cnt16 = (cnt16 >> 1) ^ (-(cnt16 & 1) & 0xB400));

}*/


void lightCheck(void){


for(int i=0;i<MAXLEDS;i++){

for(int j=0;j<=i;j++){

lightLed(i);

_delay_ms(200);

allOff();

_delay_ms(150);

}

}

}



void goToSleep(void)

{

SMCR |= (1<<2); //SMCR.SM bit 2 (010) Power-down

SMCR |= (1<<0); //SMCR.SE =1; SET JUST before Sleep starts

sei() ; //set Global Interrupt Enable

__asm__ __volatile__("sleep") ; //enter sleep, waiting for interrupt -- This worked great!!!

}