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!!!
}