Três olhos penduram em um pilar, ou a história de que cinco pernas de ATtiny13 são suficientes


KDPV "Oh, é isso."


Há pouca chance de que essa tristeza se torne uma fonte de sabedoria vital para intelectuais, sofisticada nos segredos da adivinhação nas cartas de Carnot e conhecendo o significado secreto da Terceira Forma Normal. Mas se, por algum motivo, você tocou o arduino com as mãos, um ferro de solda está acumulando poeira na despensa, você entende por que a bateria tem mais um e o C ++ tem dois, então milagres verdadeiramente mágicos e surpreendentes não o deixarão indiferente. Por isso, tenho o prazer de recomendar os números da apresentação de hoje do vagabundo circo “Saman with Boxwood” :


  • Adicionando RAM e ROM ao ATtiny13!
  • Inteligência artificial em um microprocessador - pró e contra, ou uma bela adormecida - bem, ela não é uma tola?
  • Ou ainda é dura lex sed lex?
  • Como adicionar pernas ao ATtiny13?
  • Algumas palavras sobre a quinta dimensão: como amontoar o insuportável?
  • Serrar ao meio sem virgens misturando o conteúdo das metades (com garantia de recuperação).
  • “Alimentando os Aflitos” (veja o caso anterior de cinco mil pessoas saturadas com cinco pães de cevada e dois peixes).

Se pelo menos um dos truques for útil no futuro para cada vigésimo leitor, ficarei satisfeito, o artigo não foi escrito em vão.


O primeiro semáforo ou Kaa leva a luta.


A história começou, como em um vídeo clássico de Natal antes do Natal, quando a câmera olha através de uma janela fosca para uma pequena sala aconchegante: uma árvore de Natal em enfeites, algodão e brinquedos, o cheiro de tangerina e vinho quente, o calor quente das sombras à luz das velas. No grande sofá, ela endireita a manta e pressiona suavemente a bochecha contra o ombro dele, ouvindo distraidamente a menininha gesticulando com entusiasmo, como um anjo ...


Aqueles com experiência parental sabem perfeitamente o que exatamente nesse momento você pode ouvir. Vou explicar para aqueles que ainda não adquiriram essa habilidade - com um alto grau de probabilidade, os pais agora estão pasmos com algo como: “Pai! Nós amanhã! Para o jardim de infância! Eu tenho que! Traga artesanato para o concurso de árvores de Natal! E eu quero o primeiro lugar!


É necessário. Amanhã. Para nós. Artesanato. O melhor


A entrevista envolvida com o cliente mostra os contornos da declaração de trabalho: precisamos de um semáforo. E ser bonita e brilhar como uma verdadeira. Já nesta fase, as fileiras de candidatos ao projeto ISU estão diminuindo drasticamente: papai não consegue substanciar a ideia de que um bonito, macio, costurado com retalhos ou semáforos de malha é uma representação incorporada dos sonhos do Cliente: o semáforo deve estar aceso - o que não está claro?


A noite rolou pelo país e o trabalho começou a ferver em nosso país.


O material do corpo do semáforo é uma manga de papel higiênico, comprimida para formar uma caixa. A moeda de dez rublos foi cercada com um lápis e, em seguida, foram cortados buracos com uma faca de escritório sob as luzes da sinalização luminosa (trabalho traumático não é confiável para as crianças).



As tampas da parte superior e inferior do semáforo são cortadas de papelão no lugar. Os picos sobre as lâmpadas de acordo com o padrão realizado foram circulados em papel comum de 80 gramas e cortados manualmente.



Em seguida, eles foram colados ao PVA.



As estruturas montadas foram arrastadas para o pátio e pintadas com tintas spray acrílicas: prata generosa, depois levemente preta por cima.



Em caso de danos em qualquer estágio, três cópias foram feitas ao mesmo tempo. Três tiras de papel colorido - vermelho, amarelo e verde - foram coladas com filtros de luz nas mais bem-sucedidas.


O destaque interno foi decidido por um par de LEDs brancos super brilhantes das caixas generosas da pátria (SHZR). O sapo Kaptershchitskaya recusou-se a ceder ao pai da presença do SCHR até três baterias de lítio para tablets, e os LEDs não concordaram em brilhar de um, afirmando que eram brancos e brilhantes, e a queda de tensão neles era de 2,8 a 3,9 volts. O máximo que conseguimos negociar com o sapo foi para uma bateria AA, um anel de ferrite do acelerador da placa-mãe queimada e do transistor KT315. Pensando e pesquisando, o pai teve que aceitar a oferta. E considerando o número de canetas divertidas em cada grupo do jardim de infância, a idéia com baterias de lítio não parecia particularmente atraente.


Os cascos dos semáforos da bateria substituíram os aromas de agulhas e tangerinas por um forte cheiro de tinta, meu pai pensativamente cutucou um ferro de solda na resina, as crianças transformaram as bobinas para bloquear os geradores (duplicação de cópias), tudo correu conforme o planejado ...


E não, “de repente” naquela noite não aconteceu: todos os truques ao ligar um transformador são imediatamente enrolar o número máximo possível de voltas com um fio dobrado. Não confunda o ânodo e o cátodo do LED e os terminais do transistor KT315 e conecte corretamente as extremidades dos enrolamentos (ou troque-as se não estiverem acesas) de acordo com o diagrama de circuitos. J1 - botão liga / desliga de um jumper de computador, exibido posteriormente "no teto" de um semáforo.


Um circuito completamente simples para produzir tensão CA com picos de 3-7V a partir de uma bateria G1 de 1,5V é conhecido há muito tempo.



Fisicamente, o diagrama de circuitos é incorporado da seguinte forma:



A fita vermelha possui uma bateria alcalina AA.


E o próprio semáforo é assim.



De manhã, a criança orgulhosa arrastou o produto para o jardim de infância, onde o brinquedo se espalhou e ocupou o centro da árvore de Natal.



É verdade que não deu certo com o primeiro lugar na competição - o prazo para enviar inscrições era, como se viu, já há alguns dias.


Em casa, havia dois prédios no parapeito da janela e a insatisfação do meu pai com a solução para a tarefa "eu quero isso como um verdadeiro semáforo". E a idéia estava girando "é possível encaixar uma solução completa, digamos na 13ª coisa, que o sapo esteja no ShchZR por um longo tempo? Haverá cinco pernas suficientes, um kilobyte para o código e 64 bytes de RAM e que, como ordenado, como um real?"


Então, tudo isso foi apenas um ditado, um conto de fadas sobre a solução final da questão do semáforo à frente.


O segundo semáforo, como um real


Ferramentas, materiais e documentação usados


Idioma / estrutura : C / Arduino 1.6 / 1.8.
IDE : MS Visual Studio 2012 + plugin do Visual Micro + git.
CAD : DipTrace.
HW : MK ATtiny13, clone do Arduino Nano no ATmega328, USB-UART no FT232R, programador USBISP de nome chinês.
Tecnologia PP : LUT .
Ferramentas : Ferro de soldar, pistola de cola, forno de cozinha, faca, tesoura, alicate.
ShchZR - 4 LEDs de saída vermelhos, amarelos e verdes da marca noname, capacitor de tântalo SMD e um par de resistores 0805 cada 10k, meia dúzia de resistores limitadores de corrente de saída 0,25W MF-25, conversor chinês DC-DC 5V, latas de aerossol com tinta prata e preta, papel A4, argila de polímero da venda.


Fontes e documentos estão disponíveis no Github sob a licença MIT, o código-fonte confirma coincidir com a iteração do firmware descrito abaixo, todos os caminhos de arquivo mencionados são relativos à raiz do repositório.


Documentação :
./docs/ATtiny13A datasheet.pdf [Especificação para MK Atmel ATtiny13A]
./docs/ATmega328 datasheet.pdf [Especificação Atmel ATmega328 MK]
./docs/AVR4027 - Dicas e truques para otimizar seu código C.pdf [Atmel AVR4027: Dicas e truques para otimizar seu código C para microcontroladores AVR de 8 bits]
./docs/AVR4013 - PicoPower basics.pdf [Notas sobre modos de economia de energia]


Do IDE do Arduino, como um cobertor da nuvem. O Wiz deles é a sutil zombaria jesuíta de tudo o que pode ser sagrado entre os programadores incorporados. Mas o Arduino, como um ecossistema, viveu, viverá e viverá, e devido à simplicidade de instalar o ambiente em computadores em vários sistemas operacionais, e porque eles foram os primeiros a habilitar, sem despesas especiais para um depurador de hardware, usando um centavo UART e um gerenciador de inicialização proprietário, desenvolvimento em um MK de enchimento bastante sério. E aqui está o tio Liao, pronto para vender um punhado de clones pelo preço de um original. O fato de que em atmegs sênior você pode depurar a lógica e a operação do programa e, em seguida, com alterações mínimas para transferir para o mesmo tinka - isso também é um argumento.


É normal e confortável trabalhar no MS VisualStudio , não tenho muito espaço para o AtmelStudio ou o WinAVR e não quero encontrá-lo, sem um depurador de hardware, eles não têm as melhores comodidades. Sobre o plug-in VisualMicro, que adiciona suporte ao Arduino no MS VisualStudio , ele já foi escrito em detalhes suficientes e de forma inteligente no Haber.
O foco do "Arduino no ATtiny13" no hub também foi considerado há muito tempo e repetidamente .


Resumidamente, adicione o módulo MicroCore à instalação instalada do ambiente Arduino, após o que se torna possível selecionar o ATtiny13 MK nas placas de destino.



Git - nenhuma alternativa para nenhum, mesmo para os projetos mais domésticos. O hábito é simples, mas correto: ao iniciar o trabalho em qualquer programa, basta digitar "git init" no diretório na linha de comando. O suporte interno do MS Visual Studio para confirmações no repositório local economizará tempo e tempo mais de uma vez.


O DipTrace, como o CAD para circuitos e uma placa de circuito impresso, é conveniente, doméstico, o circuito e a fiação são fáceis de usar, é fácil adicionar componentes personalizados (UGO, contatos); se desejado, uma placa de circuito impresso com componentes pode ser torcida em 3D, incluindo ajuda de alta qualidade e aulas de treinamento. Além disso, estou impressionado com a política de licenciamento: as limitações da licença padrão sem fins lucrativos (1000 pinos, 4 camadas de sinal), gratuita para a Rússia, a Ucrânia e a República da Bielorrússia, em 99% dos casos são suficientes para artesanato doméstico.


Não consegui fazer o Arduino Nano funcionar corretamente, como programador minúsculo, mas com um programador de ISP USB, o problema é resolvido facilmente. Arquivos em lote rapidamente esboçados para compilação / firmware - no diretório ./gcc do projeto.


O arquivo .ino (mas realmente é C / C ++) pode ser compilado corretamente no estúdio "no arduino no ATtiny13", é simplesmente servido pelo parâmetro desse arquivo em lotes na linha de comando:


>"./gcc/0_MAKE & upload.cmd" MyArduinoFile.ino

ISP , , .


>"./gcc/0_MAKE & asm.cmd" MyArduinoFile.ino

, , — , AVR . : , .



Upgrade ROM&RAM Arduino ATtiny13


Arduino ( setup(){...}; loop(){...};) "" - int main(){setup(); loop();}, by Arduino.


uint8_t cnt;
void setup() {
    cnt=0;
}
void loop() {
  cnt++;
}
//Program size: 164 bytes (used 16% of a 1 024 byte maximum) (0,57 secs)
//Minimum Memory Usage: 5 bytes (8% of a 64 byte maximum)

, :


uint8_t cnt;
int main(){
    cnt=0;      // < setup()
    while(1){
        cnt++;  // < loop()
    }
}
//Program size: 60 bytes (used 6% of a 1 024 byte maximum) (1,23 secs)
//Minimum Memory Usage: 1 bytes (2% of a 64 byte maximum)

16% 6% , , 6% . , — 64 .



, , : . , , , , . , , , . , : CPU , . — , N . ""-CPU , (9.6 / 1024 = 9370 , ) 1/9370 = 0.0001067 . 8- . , , , " ". , , , "". 37 (256 0.0001067 = 0.027315; 0.027315 37 = 1.01065 ~= 1s).


: - (HW , 1024 ), 8 — , , .


: globalTimer volatile, , , , CPU , .


#include <avr/io.h>         //     IDE -  
#include <avr/sleep.h>      // ,  
#include <avr/interrupt.h>          //   
volatile uint16_t  globalTimer;     //     64   
//  -    globalTimer  1/37 
ISR(TIM0_OVF_vect){
    globalTimer++;  //       . , ,  while(1)   .
}
int main() {
    //     "  -". 
    set_sleep_mode(SLEEP_MODE_IDLE);    //   - .
    sleep_enable();                 //    
    TCCR0B = _BV(CS02) | _BV(CS00); //  0 - clock frequency / 1024
    TIMSK0 |= _BV(TOIE0);           //      overflow interrupt
    sei();                          //    
    while(1){
        //.........   
        sleep_cpu();    //     -   .
    }
}
//Program size: 128 bytes (used 13% of a 1 024 byte maximum) (0,86 secs)
//Minimum Memory Usage: 2 bytes (3% of a 64 byte maximum)

" 4 : , , "()


, , .
, , CPU, / / . GPIO.


Arduino : Arduino pin_number ( ):


pinMode(pin_number, OUTPUT); //   INPUT -   

/ , — .


Value = digitalRead(pin_input_number);  //Value -  HIGH  LOW (1  0)
digitalWrite(pin_outpit_number, Value);       //   pin_outpit_number - HIGH  LOW

"" , Wiring , , Arduino ( ) ( ) ( ) ( ).



.. Arduino 7 11 PD7 — D.
digitalRead, digitalWrite, pinMode .., , , , Wiring- , .


— , . , DIHALT .



- (GPIO) , 8- — 8 . , 6 (. ATtiny13 pinout, ), PB0 PB5, PB5 — MK . - : ( "B") DDRB, PINB PORTB. — , , . PB0, PB1, PB2, PB3, PB4, PB5 — B. #include <avr/io.h> ( iotn13.h ), (PB0 0,..., PB5 — 5) IDE, Arduino.


: , , . , - , , , DDRx GPIO , — . PORTx — , "- ", , — , PINx. , 50 0 1. , .


,

PB2 HIGH, +5, PB3 LOW, 0, PB0 , — .
DDRB , PB0, ( ) = 0 (PB0 ), = 1 (PB2, PB3 — ), .. 110, — , 1 0 — .


DDRB = 12;  //  000001100    - 12
//        (!)
//        pinMode().

— PORTB , =1 (PB2 HIGH), — (PB3 LOW), — , 01


PORTB = 8;  //(dec)8 === (bin)000001000
//  -        .

PINB, , — .
, — .
3 (PB3) : 1 , 3 .
3<<00000001 === PB3<<1 // — 00001000
, _BV(x), (x<<1), .. _BV(PB3) — 1.
_BV(PB3) | _BV(PB2) 00001100 (| — ).
: , , .


PORTB |= _BV(PB3) | _BV(PB2); // 2  3   == 1,     PB2  PB3  HIGH,   PORTB  

0 , , . 0 1 . , , 1 , 0 — 0 .


PORTB &= ~(_BV(PB3) | _BV(PB2)); //   PORTB 2  3  -  , LOW,   .

HW , - 0, Timer0. GPIO, , , datasheet ATtiny13, - -, Ilya Ananev - 0 ATmega328.


, , .


TCCR0B = _BV(CS02) | _BV(CS00);    //    CS02  CS00  1 -   0 = clock frequency / 1024
TIMSK0 |= _BV(TOIE0);           //   TOIE0  1 -     TIM0_OVF
//      TIMSK0 = _BV(TOIE0);

.


, . , , . - , , , (!) .


, . " 27.02.13" 7 52289-2004 , .
( ): , , , , , .


"* " " 2 , — 3 .


3 1 /.*"


, ( , / — PERIOD_0 PERIOD_4, — ).


#define ONE_SECOND  37      //     1 
#define QT_SECOND   9       //  

#define PERIOD_FLASH_GREEN  QT_SECOND           //    ( ) -    
#define PERIOD_FLASH_YELLOW ONE_SECOND * 1      //    -    - 
                                                        //  --- 
#define PERIOD_0    ONE_SECOND * 10 //R G R G   0.  ---   (10 )
#define PERIOD_1    ONE_SECOND * 3  //R g R g   1.  ---   (3 )     
#define PERIOD_2    ONE_SECOND * 1  //R Y R Y   2.  ---  (1 )
#define PERIOD_3    ONE_SECOND * 2  //RY Y RY Y 3. + ---  (2 ) 
#define PERIOD_4    ONE_SECOND * 7  //G R G R   4.  ---   (7 )
#define PERIOD_5    ONE_SECOND * 3  //g R g R   5.   --- (3 )
#define PERIOD_6    ONE_SECOND * 1  //Y R Y R   6.  ---  (1 )
#define PERIOD_7    ONE_SECOND * 2  //Y RY Y RY 7.  --- + (2 )

, , .


typedef struct{
    const uint8_t ddr_val_0;    // DDRB value -   
    const uint8_t port_val_0;   // PORTB value   -   
    const uint8_t ddr_val_1;    // DDRB value  -   "",   
    const uint8_t port_val_1;   // PORTB value - 
    const uint16_t flash_period;    // period of flashing -   _val_1  _val_0
    const uint16_t signal_period;   // period of this lighting state
}lightSignalization;            //   , _0  _1 -   , flash_long -   
// flash_period == 0,   ,   _val_0.
// signal_period == 0,         .

, 128 — , .


ATtiny13 ( ?) -


, , - - , : 6 . - denvo " ? RESET" 5- , , , , - .


- : --, .. , 7 .


— , , , 8, ?


, -, "reset", PB5, .


, ? , , , . , , , , , .


, , 8 9 - , 8 — . , -, , , , .


— .


: — . .


:



1 PORTB |= _BV(GREEN_PIN) — ( ) , 0 .. PORTB &= ~(_BV(GREEN_PIN)) — ( ).
, , ?
(DDRB |= _BV(GREEN_PIN)) , DDRB &= ~(_BV(GREEN_PIN)), GREEN_PIN Hi-Z . (2.2 * 4) 5, .


.
— .. , , .


, ,

, . , — , 37/2=18 , , . :
) , , , , ;
) — , " " 4 ;
) , 4 ( PERIOD_2->PERIOD_3 PERIOD_6->PERIOD_7);
) 4 .


.



// PINB === 0 0 0 g r y0 btt y1
#define RED_PIN     PB3     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 
#define YELLOW0_PIN PB2     // OUT: 1 -  "-" 
#define YELLOW1_PIN PB0     // OUT: 1 -  "-" 
#define GREEN_PIN   PB4     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 

#define RED     _BV(RED_PIN)        // _BV -     (), 1<<VALUE
#define YELL0   _BV(YELLOW0_PIN)        //    -
#define YELL1   _BV(YELLOW1_PIN)
#define GREEN   _BV(GREEN_PIN)      //    - (  0 -   -)  DDRB.GreenPin=1

. , , — , .


#define BUTTON_PIN      PB1
#define BUTTON_ON  !(PINB & _BV(BUTTON_PIN))    //( (PINB & _BV(BUTTON_PIN)) == 0)  //  " " -   LOW
#define BUTTON_OFF (PINB & _BV(BUTTON_PIN))     //  " " -    HIGH, (     )

, , n ( ) n(n−1) = n²−n . 4 12 , . « , » « , » .


12 LED


*** — , DDRx|PORTx, , .. . — , , .


.***


: ?


lightSignalization. lightSignalization . 0 7 , 8 — , 9 — , "" . , 0 7, . , , . 3 ( 0 7) 8 -- . if- , . , .


lightSignalization traffic_signals[] = {//   
 // {DDRB0, PORTB0,   DDRB_when_flashingif, PORTB_when_flasingif (if flashing),   continous of half-period flashing,   continous curr mode runing}
    {RED|GREEN, RED,   0, 0,   0, PERIOD_0},                    // R G R G
    {RED, RED,  RED|GREEN, RED,   QT_SECOND, PERIOD_1},     // R g R g - flash east green
    {RED|YELL1, RED|YELL1,   0, 0,   0, PERIOD_2 },         // R Y1 R Y1
    {RED|YELL0|YELL1, RED|YELL0|YELL1,  0, 0,   0, PERIOD_3 },  // RY0 Y1 RY0 Y1
    {RED|GREEN, GREEN,   0, 0,   0, PERIOD_4},              // G R G R
    {RED|GREEN, GREEN,   RED, 0,    QT_SECOND, PERIOD_5 },  // g R g R - flash nord green
    {RED|YELL0, YELL0,   0, 0,   0, PERIOD_6},                  // Y0 R Y0 R
    {RED|YELL0|YELL1,  YELL0|YELL1,   0, 0,   0, PERIOD_7  },       // Y0 RY1 Y0 RY1

    {YELL0|YELL1, YELL0|YELL1,   YELL0|YELL1, 0,  ONE_SECOND, 0},   // y0 y1 y0 y1 - flash yellows lights 
    {0, 0,   0, 0,   0, 0}          // traffic lights off, DDR in, Hi-Z
};

//       lightSignalization traffic_signals[]
#define LIGHT_NUM_YELLOW_FLASH  8       //       -  - flash yellows lights
#define LIGHT_NUM_STD_START     0       //       
#define LIGHT_NUM_LIGHTS_OFF    9       //      -   - traffic lights off

lightSignalization 8 . .. traffic_signals[] 10 80 (, 64 , 2 ). , .


, , , — ROM, , RAM , .


-


const lightSignalization traffic_signals[] PROGMEM= {...

,


<avr/pgmspace.h> pgm_read_byte_near()  pgm_read_word_near()

char shortint .


3 .


  1. , .
    traffic_signals[] — LIGHT_NUM_LIGHTS_OFF
    {0, 0, 0, 0, 0, 0} // traffic lights off
    — lightSignalization , — , lightSignalization.signal_period==0 (.. ), lightSignalization.flash_period==0, .. .


  2. , .
    traffic_signals[] — LIGHT_NUM_YELLOW_FLASH
    {YELL0|YELL1, YELL0|YELL1, YELL0|YELL1, 0, ONE_SECOND, 0}, // y0 y1 y0 y1 — flash yellows lights
    : lightSignalization.signal_period==0. lightSignalization.flash_period=ONE_SECOND, :


    DDRB = YELL0|YELL1;     // YELL0, YELL1 - 
    PORTB = YELL0|YELL1;    // YELL0, YELL1 = HIGH -  


    DDRB = YELL0|YELL1;     // // YELL0, YELL1 -   
    PORTB = 0;              // YELL0, YELL1 = LOW -  

  3. , --.



, .


traffic_signals[] — LIGHT_NUM_STD_START
{RED|GREEN, RED, 0, 0, 0, PERIOD_0}, // R G R G
: lightSignalization.flash_period==0.
DDRB = RED|GREEN; //RED GREEN — , .
PORTB = RED; // RED — HIGH (- )
// GREEN — LOW ( , - — )
lightSignalization.signal_period==PERIOD_0, .


current_signal. 2 — , lightSignalization.


uint8_t current_signal;     // 1    ,   traffic_signals
uint16_t tl_flash_end;      // 2       ( !0), 
uint16_t tl_signal_end;     // 2            ( !0)

tl_signal_end != 0, globalTimer>tl_signal_end current_signal. 0 current_signal, 3, .
current_signal = current_signal & B00000111;


current_signal &= LIGHT_NUM_STD_MASK ;   //current_signal & B00000111;

current_signal , 0 7.
globalTimer — .


#include <limits.h>         // USHRT_MAX
#include <avr/sleep.h>      // ,  
#include <avr/interrupt.h>  //   
#include <avr/pgmspace.h>   //    

#define ONE_SECOND  37      //     1 
#define QT_SECOND   9       //  
#define MAX_GLOBAL_TIMER_VALUE  (USHRT_MAX / 2)     // uint16_t globalTimer -   . 65535 /2 
//     ,  MAX_GLOBAL_TIMER_VALUE - 1
#define PERIOD_FLASH_GREEN  QT_SECOND           //    ( ) -    
#define PERIOD_FLASH_YELLOW ONE_SECOND * 1      //    -    - 
                                                        //  --- 
#define PERIOD_0        ONE_SECOND * 10     //R G R G   0.  ---   (15 )
#define PERIOD_1        ONE_SECOND * 3      //R g R g   1.  ---   (3 )     
#define PERIOD_2        ONE_SECOND * 1      //R Y R Y   2.  ---  (1 )
#define PERIOD_3        ONE_SECOND * 2      //RY Y RY Y 3. + ---  (2 ) 
#define PERIOD_4        ONE_SECOND * 7      //G R G R   4.  ---   (10 )
#define PERIOD_5        ONE_SECOND * 3      //g R g R   5.   --- (3 )
#define PERIOD_6        ONE_SECOND * 1      //Y R Y R   6.  ---  (1 )
#define PERIOD_7        ONE_SECOND * 2      //Y RY Y RY 7.  --- + (2 )

typedef struct{
    const uint8_t ddr_val_0;    // DDRB value    
    const uint8_t port_val_0;   // PORTB value  
    const uint8_t ddr_val_1;    // DDRB value    
    const uint8_t port_val_1;   // PORTB value
    const uint16_t flash_period;    // period of flashing -   _val_1  _val_0
    const uint16_t signal_period;   // period of this lighting state
}lightSignalization;            //   , _0  _1 -   , flash_long -   

//    (PINS === 0 0 0 g r y0 btt y1):
 //     ""     
#define BUTTON      PB1
#define RED_PIN     PB3     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 
#define YELLOW0_PIN PB2     // OUT: 1 -  "-" 
#define YELLOW1_PIN PB0     // OUT: 1 -  "-" 
#define GREEN_PIN   PB4     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 

#define BUTTON_ON  !(PINB & _BV(BUTTON))    //( (PINB & _BV(BUTTON)) == 0)  //  " "
#define BUTTON_OFF  (PINB & _BV(BUTTON))    // ~(PINB & _BV(BUTTON)) -\\- " "

#define RED     _BV(RED_PIN)            // _BV -     (), 1<<VALUE
#define YELL0   _BV(YELLOW0_PIN)        //
#define YELL1   _BV(YELLOW1_PIN)
#define GREEN   _BV(GREEN_PIN)

//       lightSignalization traffic_signals[]
#define LIGHT_NUM_YELLOW_FLASH  8       //       -  - flash yellows lights
#define LIGHT_NUM_STD_START     0       //       
#define LIGHT_NUM_LIGHTS_OFF    9       //      -   - traffic lights off
#define LIGHT_NUM_STD_MASK      7       // ___++ &LIGHT_NUM_STD_MASK -    0  7   

//....................................  
// 
const lightSignalization traffic_signals[] PROGMEM= {   //   ,  ,   -, PINS === 0 0 0 g r y0 btt y1
 // {DDRB0, PORTB0,   DDRB_flashing, PORTB_flasinf (if flashing),   continuous of half-period flashing,   continuous id mode running}
    {RED|GREEN, RED,   0, 0,   0, PERIOD_0},                    // R G R G
    {RED, RED,  RED|GREEN, RED,   QT_SECOND, PERIOD_1},     // R g R g - flash east green
    {RED|YELL1, RED|YELL1,   0, 0,   0, PERIOD_2 },             // R Y1 R Y1
    {RED|YELL0|YELL1, RED|YELL0|YELL1,  0, 0,   0, PERIOD_3 },  // RY0 Y1 RY0 Y1
    {RED|GREEN, GREEN,   0, 0,   0, PERIOD_4},                  // G R G R
    {RED|GREEN, GREEN,   RED, 0,    QT_SECOND, PERIOD_5 },      // g R g R - flash nord green
    {RED|YELL0, YELL0,   0, 0,   0, PERIOD_6},                  // Y0 R Y0 R
    {RED|YELL0|YELL1,  YELL0|YELL1,   0, 0,   0, PERIOD_7  },   // Y0 RY1 Y0 RY1

    {YELL0|YELL1, YELL0|YELL1,   YELL0|YELL1, 0,  ONE_SECOND, 0},   // y0 y1 y0 y1 - flash yellows lights 
    {0, 0,   0, 0,   0, 0}              //  traffic lights off, 
};

volatile uint16_t  globalTimer;     //     64   
uint8_t current_signal;     // 1    ,   traffic_signals
uint16_t tl_flash_end;      // 2       ( !0), 
uint16_t tl_signal_end;     // 2            ( !0)

//....................................  
void setPeriods(uint8_t num, bool set_both_flash_and_signal);   //  tl_flash_end, tl_signal_end
void setPorts(uint8_t num, bool use_main_values);               //    

//....................................  
//
//  -    globalTimer  1/37 
ISR(TIM0_OVF_vect){
    globalTimer++;  //       . ,   while(1)   .
}

int main() {
//
bool use_main_values = true;            // lightSignalization._val_0 (1)  lightSignalization._val_1 (0)? -  
current_signal = LIGHT_NUM_STD_START;   //   .     .

    //     "  -". 
    set_sleep_mode(SLEEP_MODE_IDLE);    //   - .
    sleep_enable();                 //    

    TCCR0B = _BV(CS02) | _BV(CS00); //  0 - clock frequency / 1024
    TIMSK0 |= _BV(TOIE0);           //      overflow interrupt

    sei();      //    
    while(1){
        //   ? 
        if(globalTimer > MAX_GLOBAL_TIMER_VALUE){
            globalTimer -= MAX_GLOBAL_TIMER_VALUE;          //   
            // 
            if(tl_flash_end){
                tl_flash_end -= MAX_GLOBAL_TIMER_VALUE;     //   ,  
            }
            if(tl_signal_end){
                tl_signal_end -= MAX_GLOBAL_TIMER_VALUE;    // //   ,  
            }
            // setPeriods(currentMode, false); //   12  ,  tl_.._end   ,     
        }

                //      (tl_flash_end !=0 )
        if(tl_flash_end){
            //     
            if(globalTimer > tl_flash_end){
                use_main_values = !use_main_values;             // !use_main_values -      ))
                setPorts(current_signal, use_main_values);      //      
                setPeriods(current_signal, false);              //     ,   
            }
        }

        //         -    operating_std     - --
        if(tl_signal_end){
            //       (use_main_values -       -  )
            if((globalTimer > tl_signal_end)  && use_main_values){
                current_signal ++;                          //   
                current_signal &= LIGHT_NUM_STD_MASK;       //    3-,        0  7
                use_main_values = true;                     //  -    
                setPorts(current_signal, use_main_values);  //        
                setPeriods(current_signal, true);           //       
            }
        }

        sleep_cpu();    //      -   .
    }
}

    //   
 void setPorts(uint8_t num, bool use_main_values){
    uint8_t val;
    DDRB = 0; PORTB = 0;
    //    () - ddr_val_0, else = ddr_val_1
//  val = (use_main_values) ? pgm_read_byte_near(&(traffic_signals[num].ddr_val_0))
//                          : pgm_read_byte_near(&(traffic_signals[num].ddr_val_1));

    //   ,  , ,  ,   ,   14 (!!!)   .
    val = pgm_read_byte_near(&(traffic_signals[num].ddr_val_0)+( (use_main_values) ? 0 : 2) ); 
    val &= ~_BV(BUTTON);    //     - 
    DDRB = val;             //    

    val = (use_main_values) ? pgm_read_byte_near(&(traffic_signals[num].port_val_0)) 
                            : pgm_read_byte_near(&(traffic_signals[num].port_val_1));
    val|= _BV(BUTTON);  //     -  -    
    PORTB = val;        //      
}

 //     ( 
void setPeriods(uint8_t num, bool set_both_flash_and_signal){
//  
    tl_flash_end = pgm_read_word_near (&(traffic_signals[num].flash_period));   //  
    tl_flash_end = (tl_flash_end)? tl_flash_end + globalTimer : 0;  //    -      
    //if(tl_flash_end){         tl_flash_end += globalTimer;    } <-     8  

    //     -    
    if(set_both_flash_and_signal){
        tl_signal_end = pgm_read_word_near(&(traffic_signals[num].signal_period));  
        tl_signal_end = (tl_signal_end)? tl_signal_end + globalTimer : 0;           //     ,    
    }
}

//Program size: 610 bytes (used 60% of a 1 024 byte maximum) (0,58 secs)
//Minimum Memory Usage: 7 bytes (11% of a 64 byte maximum)


, . — btn_cnt ( ), ( ) .


#define PERIOD_PRESS_BUTTON_SHORT   QT_SECOND           //      -  
#define PERIOD_PRESS_BUTTON_LONG    QT_SECOND*6         //      - /
uint8_t scan_button_cnt;    //    
        //  
        if(BUTTON_ON){
            if(scan_button_cnt<USHRT_MAX){
                scan_button_cnt++;      //   1/37     
            }
            if(scan_button_cnt > PERIOD_PRESS_BUTTON_SHORT){
                    // ,     
            }
            if(scan_button_cnt > PERIOD_PRESS_BUTTON_LONG){
                    //     
            }
        }

— .



SLEEP_MODE_IDLE ( CPU), PwrDown SLEEP_MODE_PWR_DOWN — watchdog INT0, , — INT0.



. 7.Power management and sleep modes ATtiny13 , 5-10 , .


8- , — 2 .


//  uint8_t f_button_state_flags;       //        

//      MODES:  wakeup 11 -> work 00 -> tosleep 01 -> pwrdown 11 -> wakeup 11
#define MODE_LBIT 0
#define MODE_HBIT 1
#define FORCE_SET_NEW_SIGNAL_BIT        2   //             current_signal
//    3
#define LIGHT_SIGNAL_ALT_MODE_BIT       4   // =0 (--)  =1 ( )   
#define USE_FIRST_VALUES_LIGHT_BIT      5   //     -  lightSignalization  
#define SHORT_PRESS_FLAG_BIT    6   // , 1       
#define LONG_PRESS_FLAG_BIT     7 // , 1       

, — , — CPU . , if-.


#include <limits.h>         // USHRT_MAX
#include <avr/io.h>         //     IDE
#include <avr/sleep.h>      // ,     
#include <avr/interrupt.h>  //   
#include <avr/pgmspace.h>   //    

#ifdef GIMSK    //  ATtiny13 -       
#define F_CPU 9600000UL     //      ,   
#define ONE_SECOND  37      //     1 
#define QT_SECOND   9       //  
// GIMSK &= ~_BV(INT0); -   INT0  
#define DISABLE_EXTERNAL_INT0   GIMSK &= ~(_BV(INT0)); GIFR  &= ~(_BV(INTF0))   //EIMSK/EIFR  
//GIMSK |= _BV(INT0) -   INT0
#define ENABLE_EXTERNAL_INT0    GIMSK |= _BV(INT0)  ; GIFR  &= ~(_BV(INTF0))
#else           // 328 -   
#define F_CPU 16000000UL
#define ONE_SECOND  64      //     1  - .   
#define QT_SECOND   16      //  
// 328 INT0 -  PD2...     ,       (,  ),            
#define DISABLE_EXTERNAL_INT0   EIMSK &= ~(_BV(INT0)); EIFR  &= ~(_BV(INTF0)) 
// ,   -  EICRA - ISC00-ISC01 == 00, lo level, EIMSK - INT0, EIFR-INTF0  
#define ENABLE_EXTERNAL_INT0    EIMSK |= _BV(INT0)  ; EIFR  &= ~(_BV(INTF0))
#endif

#define MAX_GLOBAL_TIMER_VALUE  (USHRT_MAX / 2)     // uint16_t globalTimer -   . 65535 /2 
//     ,  MAX_GLOBAL_TIMER_VALUE - 1
#define PERIOD_PRESS_BUTTON_SHORT   QT_SECOND/2         //      ( - ) -  
#define PERIOD_PRESS_BUTTON_LONG    QT_SECOND*4         //      - /
#define PERIOD_FLASH_GREEN          QT_SECOND           //     ( ) -    
#define PERIOD_FLASH_YELLOW         ONE_SECOND * 1      //     -    - 

                                            //  --- 
#define PERIOD_0        ONE_SECOND * 5      // R G R G  0.  ---   (5 )
#define PERIOD_1        ONE_SECOND * 3      //R g R g   1.  ---   (3 )     
#define PERIOD_2        ONE_SECOND * 1      //R Y R Y   2.  ---  (1 )
#define PERIOD_3        ONE_SECOND * 2      //RY Y RY Y 3. + ---  (2 ) 
#define PERIOD_4        ONE_SECOND * 7      // G R G R  4.  ---   (7 )
#define PERIOD_5        ONE_SECOND * 3      //g R g R   5.   --- (3 )
#define PERIOD_6        ONE_SECOND * 1      //Y R Y R   6.  ---  (1 )
#define PERIOD_7        ONE_SECOND * 2      //Y RY Y RY 7.  --- + (2 )

//  /  .     -     
typedef struct{
    const uint8_t ddr_val_0;    // DDRB value    
    const uint8_t port_val_0;   // PORTB value  
    const uint8_t ddr_val_1;    // DDRB value    
    const uint8_t port_val_1;   // PORTB value
    const uint16_t flash_period;    // period of flashing -   _val_1  _val_0 ( =0,  )
    const uint16_t signal_period;   // period of this lighting state ( =0,       )
}lightSignalization;            //   , _0  _1 -   , flash_long -   

//    (PINS === 0 0 0 g r y0 btt y1):
 //     ""     
#define BUTTON_PIN  PB1     // ,   INT0. ,   ,  = LOW
#define RED_PIN     PB3     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 
#define YELLOW0_PIN PB2     // OUT: 1 -  "-" 
#define YELLOW1_PIN PB0     // OUT: 1 -  "-" 
#define GREEN_PIN   PB4     // OUT: 1 - "-" , 0 - "-" , IN -  , ,  (!) 

#define BUTTON_ON  !(PINB & _BV(BUTTON_PIN))    //( (PINB & _BV(BUTTON)) == 0)  //  " "
#define BUTTON_OFF  (PINB & _BV(BUTTON_PIN))    // ~(PINB & _BV(BUTTON)) -\\- " "

#define RED     _BV(RED_PIN)            // _BV -     (), 1<<VALUE
#define YELL0   _BV(YELLOW0_PIN)        //    -
#define YELL1   _BV(YELLOW1_PIN)
#define GREEN   _BV(GREEN_PIN)          //    - (  0 -   -)  DDR=1

//      lightSignalization traffic_signals[]
#define LIGHT_NUM_YELLOW_FLASH  8       //       ( ) -  - flash yellows lights
#define LIGHT_NUM_STD_START     0       //        (--)
#define LIGHT_NUM_LIGHTS_OFF    9       //      -   - traffic lights off
#define LIGHT_NUM_START_SHOW    10      //         
#define LIGHT_NUM_ERR           11      //   -     

#define MASK_LIGHT_NUM_STD      7       // ___++ &= LIGHT_NUM_STD_MASK -    0  7   

//....................................  
// 
const lightSignalization traffic_signals[] PROGMEM= {   //   ,  ,   -, PINS === 0 0 0 g r y0 btt y1
 // {DDRB0, PORTB0,   DDRB_flashing, PORTB_flasinf (if flashing),   continuous of half-period flashing,   continuous id mode running}
    {RED|GREEN, RED,   0, 0,   0, PERIOD_0},                    // R G R G
    {RED, RED,  RED|GREEN, RED,   QT_SECOND, PERIOD_1},         // R g R g - flash east green
    {RED|YELL1, RED|YELL1,   0, 0,   0, PERIOD_2 },             // R Y1 R Y1
    {RED|YELL0|YELL1, RED|YELL0|YELL1,  0, 0,   0, PERIOD_3 },  // RY0 Y1 RY0 Y1
    {RED|GREEN, GREEN,   0, 0,   0, PERIOD_4},                  // G R G R
    {RED|GREEN, GREEN,   RED, 0,    QT_SECOND, PERIOD_5 },      // g R g R - flash nord green
    {RED|YELL0, YELL0,   0, 0,   0, PERIOD_6},                  // Y0 R Y0 R
    {RED|YELL0|YELL1,  YELL0|YELL1,   0, 0,   0, PERIOD_7  },   // Y0 RY1 Y0 RY1

    {YELL0|YELL1, YELL0|YELL1,   YELL0|YELL1, 0,  ONE_SECOND, 0},   // y0 y1 y0 y1 - flash yellows lights 
    {0, 0,   0, 0,   0, 0},             //  traffic lights off, 
    {RED|GREEN|YELL0, RED|YELL0,   RED|GREEN|YELL1, GREEN|YELL1,   1, PERIOD_2},        //  PERIOD_2  -      ,     

    {YELL0|GREEN, YELL0,   YELL1|GREEN, YELL1|GREEN,  1, 0}     //  -     
};

volatile uint16_t  globalTimer; //      64   
uint8_t scan_button_cnt;        //      
uint16_t tl_flash_end;          // 2       ( !0), 
uint16_t tl_signal_end;         // 2            ( !0) 
uint8_t f_button_state_flags;   // 1,        
// , 8    

#pragma region bits_of_f_button_state_flags 
    //      MODES:  wakeup 11 -> work 00 -> tosleep 01 -> pwrdown 11 -> wakeup 11
#define MODE_LBIT 0
#define MODE_HBIT 1
#define MODE_VALUE          ( f_button_state_flags & 3 )    //  -   MODE_
#define SET_MODE_WORK       f_button_state_flags &= ~(_BV(MODE_HBIT) );  f_button_state_flags &= ~(_BV(MODE_LBIT) );// 00 - work
//  f_button_state_flags &= ~( _BV(MODE_HBIT) | _BV(MODE_LBIT) ) -    ,  
#define MODE_WORK_VALUE     0
#define SET_MODE_TOSLEEP    f_button_state_flags &= ~(_BV(MODE_HBIT)); f_button_state_flags |= _BV(MODE_LBIT)   // 01 - tosleep
#define MODE_TOSLEEP_VALUE  1
#define SET_MODE_PWRDOWN    f_button_state_flags |= _BV(MODE_HBIT); f_button_state_flags &= ~(_BV(MODE_LBIT))   // 10 - pwrdown 
#define MODE_PWRDOWN_VALUE  2
#define SET_MODE_WAKEUP     f_button_state_flags |= _BV(MODE_HBIT); f_button_state_flags |= _BV(MODE_LBIT)      // 11 - wakeup  
#define MODE_WAKEUP_VALUE   3

#define FORCE_SET_NEW_SIGNAL_BIT        2   //             current_signal
#define IF_FORCE_SET_SIGNAL_FLAG        ( f_button_state_flags & _BV(FORCE_SET_NEW_SIGNAL_BIT) )    // IF_ -    
#define SET_FORCE_SET_SIGNAL_FLAG       f_button_state_flags |=  _BV(FORCE_SET_NEW_SIGNAL_BIT)      // SET_ -    1
#define RES_FORCE_SET_SIGNAL_FLAG       f_button_state_flags &= ~( _BV(FORCE_SET_NEW_SIGNAL_BIT) )  // RES_ -    0

//  3   

#define LIGHT_SIGNAL_ALT_MODE_BIT       4   // =0 (--)  =1 ( )   
#define IF_LIGHT_SIGNAL_ALT_MODE_FLAG   ( f_button_state_flags & _BV(LIGHT_SIGNAL_ALT_MODE_BIT) )   //1( )  0(--)   ?
#define SET_LIGHT_SIGNAL_ALT_MODE_FLAG  f_button_state_flags |=  _BV(LIGHT_SIGNAL_ALT_MODE_BIT)
#define RES_LIGHT_SIGNAL_ALT_MODE_FLAG  f_button_state_flags &= ~( _BV(LIGHT_SIGNAL_ALT_MODE_BIT) )
#define FLIP_LIGHT_SIGNAL_ALT_MODE_FLAG f_button_state_flags ^= _BV(LIGHT_SIGNAL_ALT_MODE_BIT)

#define USE_FIRST_VALUES_LIGHT_BIT      5   //     -  lightSignalization  
#define IF_USE_FIRST_VALUES_LIGHT_FLAG  (f_button_state_flags & _BV(USE_FIRST_VALUES_LIGHT_BIT)) // lightSignalization._val_0 (1)  lightSignalization._val_1 (0)? -  
#define SET_USE_FIRST_VALUES_LIGHT_FLAG     f_button_state_flags |= _BV(USE_FIRST_VALUES_LIGHT_BIT)
#define RES_USE_FIRST_VALUES_LIGHT_FLAG     f_button_state_flags &= ~( _BV(USE_FIRST_VALUES_LIGHT_BIT))
#define FLIP_USE_FIRST_VALUES_LIGHT_FLAG    f_button_state_flags ^= _BV(USE_FIRST_VALUES_LIGHT_BIT)     //  

#define SHORT_PRESS_FLAG_BIT    6   // , 1       
#define IF_SHORT_PRESS_FLAG     ( f_button_state_flags & _BV(SHORT_PRESS_FLAG_BIT) )        // -   == 1
#define SET_SHORT_PRESS_FLAG    f_button_state_flags |= _BV(SHORT_PRESS_FLAG_BIT)
#define RES_SHORT_PRESS_FLAG    f_button_state_flags &= ~(_BV(SHORT_PRESS_FLAG_BIT))

#define LONG_PRESS_FLAG_BIT     7 // , 1       
#define IF_LONG_PRESS_FLAG      ( f_button_state_flags & _BV(LONG_PRESS_FLAG_BIT) )     // -   == 1
#define SET_LONG_PRESS_FLAG     f_button_state_flags |= _BV(LONG_PRESS_FLAG_BIT)
#define RES_LONG_PRESS_FLAG     f_button_state_flags &= ~(_BV(LONG_PRESS_FLAG_BIT))
#pragma endregion

//....................................  
void setPeriods(uint8_t num, bool set_both_flash_and_signal);   //  tl_flash_end, tl_signal_end
void setPorts(uint8_t num, bool use_main_values);               //    
void inline init_timer_clock(){     //     
#ifdef GIMSK    //  ATtiny13 - 
    TCCR0B = _BV(CS02) | _BV(CS00); //  0 - clock frequency / 1024
    TIMSK0 |= _BV(TOIE0);           //      overflow interrupt
#else           //   , 328/16
    // 100 - prescaler 64; Foverflow = 16M/64*256 ~=976.56Hz,
    TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20) ;  // 111 - CLK/1024, 16M/1024*254 - 1/64 
    TIMSK2 |=(1<<TOIE0);  // interrupt ovfl enable
    //Serial.begin(115200);
#endif
}

//....................................  
//
//  -  -    globalTimer  1/37 
#ifdef GIMSK    //  ATtiny13
ISR(TIM0_OVF_vect){
    globalTimer++;  //       . ,   while(1)   .
}
#else
//   0 -     , -   - -     2
ISR(TIMER2_OVF_vect){
    globalTimer++;
}
#endif
//   -    (,  ,    0)
ISR(INT0_vect){
    DISABLE_EXTERNAL_INT0;
    SET_MODE_WAKEUP;        //      POWER DOWN
    globalTimer = 0;        //  -  
    scan_button_cnt = 0;    //   
    RES_SHORT_PRESS_FLAG;   //
    RES_LONG_PRESS_FLAG;    //  
}

/*
//   - 
void inline dbg(){
    DDRB |= YELL0; PORTB ^= YELL0;
}
*/

//....................................  
//
int main() {
    uint8_t current_signal;             // 1    ,   traffic_signals

#pragma region Initialisation&setup
    //     "  -". 
    set_sleep_mode(SLEEP_MODE_IDLE);    //   - .
    sleep_enable();             //    

    init_timer_clock();         //     

    globalTimer = 0;            //  -  
    SET_MODE_WORK;              //    
    SET_USE_FIRST_VALUES_LIGHT_FLAG;    //  
    scan_button_cnt = 0;        //   

    //       
    current_signal = LIGHT_NUM_START_SHOW;  //     -   /
    SET_FORCE_SET_SIGNAL_FLAG;              //    current_signal

    sei();      //    

#pragma endregion
    while(1){

#pragma region TimerOVF
        //   ? 
        if(globalTimer > MAX_GLOBAL_TIMER_VALUE){
            globalTimer -= MAX_GLOBAL_TIMER_VALUE;          //   
            // 
            if(tl_flash_end){
                tl_flash_end -= MAX_GLOBAL_TIMER_VALUE;     //   ,  
            }
            if(tl_signal_end){
                tl_signal_end -= MAX_GLOBAL_TIMER_VALUE;    // //   ,  
            }
            // setPeriods(currentMode, false); //   12  ,  tl_.._end   ,     
        }
#pragma endregion

#pragma region ButtonState
        //  
        if(BUTTON_ON){
            if(scan_button_cnt < USHRT_MAX){
                scan_button_cnt++;              //   1/37     
            }
            //   -  ,    
            if(scan_button_cnt > PERIOD_PRESS_BUTTON_SHORT){
                SET_SHORT_PRESS_FLAG;       // ,     , 
            }
            if(scan_button_cnt > PERIOD_PRESS_BUTTON_LONG){
                SET_LONG_PRESS_FLAG;        //     
            }
        }
#pragma endregion
#pragma region LightWorkLogic
        //      (tl_flash_end !=0 )
        if(tl_flash_end){
            //     
            if(globalTimer > tl_flash_end){
                FLIP_USE_FIRST_VALUES_LIGHT_FLAG;               // !use_main_values -      ))
                setPorts(current_signal, IF_USE_FIRST_VALUES_LIGHT_FLAG);       //      
                setPeriods(current_signal, false);          //     ,   
            }
        }

        //         
        // -    operating_std     - -- 
        //    ,   +1   7
        if(tl_signal_end){
            //       (use_main_values -       -  )
            if((globalTimer > tl_signal_end)  && IF_USE_FIRST_VALUES_LIGHT_FLAG){
                current_signal ++;                          //   
                current_signal &= MASK_LIGHT_NUM_STD;       //    3-,        0  7
                SET_FORCE_SET_SIGNAL_FLAG;      //    current_signal
            }
        }
#pragma endregion

#pragma region MODE_VALUELogic
        //   , 2  f_button_state_flags
        //? MODE_VALUE === pwrdown -> wakeup -> work -> tosleep -> pwrdown
        switch (MODE_VALUE){
        case (MODE_WAKEUP_VALUE):
            set_sleep_mode(SLEEP_MODE_IDLE);        //  !
            //   ,       - IF_BUTTON_LONG_FLAG
            if(IF_LONG_PRESS_FLAG){
                //      ?   !
                if(current_signal == LIGHT_NUM_LIGHTS_OFF){
                    //          ? LIGHT_NUM_ERR
                    current_signal = (IF_LIGHT_SIGNAL_ALT_MODE_FLAG) ? LIGHT_NUM_YELLOW_FLASH : LIGHT_NUM_STD_START;
                    SET_FORCE_SET_SIGNAL_FLAG;      //    current_signal
                }
            }
            //,  ...
            if(BUTTON_OFF){
                //      ,   
                if(IF_LONG_PRESS_FLAG){
                    SET_MODE_WORK;
                }else{  
                    //  , ,   ,  
                    SET_MODE_PWRDOWN;   //        
                }
                scan_button_cnt = 0;    //       
                RES_SHORT_PRESS_FLAG;   //   , 
                RES_LONG_PRESS_FLAG;
            }
            break;

        case (MODE_WORK_VALUE):
            //  ?
            if(scan_button_cnt > 0){
                //   ?
                if(IF_LONG_PRESS_FLAG){
                    current_signal = LIGHT_NUM_LIGHTS_OFF;      //  
                    SET_FORCE_SET_SIGNAL_FLAG;                  //   -   " "
                    SET_MODE_TOSLEEP;                           //   !
                }
                // ? 
                if(BUTTON_OFF){
                    //     ?
                    if(IF_SHORT_PRESS_FLAG){
                        FLIP_LIGHT_SIGNAL_ALT_MODE_FLAG;    //     
                        current_signal = (IF_LIGHT_SIGNAL_ALT_MODE_FLAG) ? LIGHT_NUM_YELLOW_FLASH : LIGHT_NUM_STD_START; //    . 
                        SET_FORCE_SET_SIGNAL_FLAG;          //      current_signal
                    }
                    scan_button_cnt=0;
                    RES_SHORT_PRESS_FLAG; //    
                    RES_LONG_PRESS_FLAG;
                }
            }
            break;

        case (MODE_TOSLEEP_VALUE):
            //    -    .
            if(BUTTON_OFF){
                SET_MODE_PWRDOWN;       //    
            }
            break;

        case (MODE_PWRDOWN_VALUE):
            // !  , !  ?
            if(BUTTON_ON){
                set_sleep_mode(SLEEP_MODE_IDLE);
                SET_MODE_WAKEUP;
            }else{  
                //  ?  .
                scan_button_cnt = 0;
                RES_LONG_PRESS_FLAG;
                RES_SHORT_PRESS_FLAG;
                current_signal = LIGHT_NUM_LIGHTS_OFF;      // 
                SET_FORCE_SET_SIGNAL_FLAG;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);    //    -   while(1)
                ENABLE_EXTERNAL_INT0;                   //     
            }
            break;

        default:
            //!       -    .  -      
            current_signal = LIGHT_NUM_ERR;
            SET_FORCE_SET_SIGNAL_FLAG;
            //setPorts(current_signal,true);
            //setPeriods(current_signal,true);
            break;
        }
#pragma endregion

        //   ,      - ?
        if(IF_FORCE_SET_SIGNAL_FLAG){       //       current_signal
            RES_FORCE_SET_SIGNAL_FLAG;      //  
            SET_USE_FIRST_VALUES_LIGHT_FLAG;    //   -   0-   -
            setPorts(current_signal, IF_USE_FIRST_VALUES_LIGHT_FLAG);   //      #current_signal  
            setPeriods(current_signal, true);
        }

        //    1/37 . , ,  .
        sleep_cpu();    //       -   .
        }
}

//.................................... 
//
//    
 void setPorts(uint8_t num, bool  use_main_values){
    uint8_t val;
    DDRB = 0; PORTB = 0;
    //    () - ddr_val_0, else = ddr_val_1
//  val = (use_main_values) ? pgm_read_byte_near(&(traffic_signals[num].ddr_val_0))
//                          : pgm_read_byte_near(&(traffic_signals[num].ddr_val_1));

    //   ,    ,  ,   ,   14 (!!!)   .
    val = pgm_read_byte_near(&(traffic_signals[num].ddr_val_0)+( (use_main_values) ? 0 : sizeof(uint8_t)*2 ) ); 

    val &= ~_BV(BUTTON_PIN);    //    ,    - 
    DDRB = val;                 //    

    val = (use_main_values) ? pgm_read_byte_near(&(traffic_signals[num].port_val_0)) 
                            : pgm_read_byte_near(&(traffic_signals[num].port_val_1));
    val|= _BV(BUTTON_PIN);  //     -  -    
    PORTB = val;        //      
}

 //     (    )
void setPeriods(uint8_t num, bool set_both_flash_and_signal){
//  
    tl_flash_end = pgm_read_word_near (&(traffic_signals[num].flash_period));   //  
    tl_flash_end = (tl_flash_end)? tl_flash_end + globalTimer : 0;  //    -      
    //if(tl_flash_end){         tl_flash_end += globalTimer;    } <-     8  

    //     -    
    if(set_both_flash_and_signal){
        tl_signal_end = pgm_read_word_near(&(traffic_signals[num].signal_period));  
        tl_signal_end = (tl_signal_end)? tl_signal_end + globalTimer : 0;           //     ,    
    }
}
//Program size: 976 bytes (used 95% of a 1 024 byte maximum) (0,83 secs)
//Minimum Memory Usage: 8 bytes (13% of a 64 byte maximum)

Program size: 976 bytes (used 95% of a 1 024 byte maximum) (0,83 secs)
Minimum Memory Usage: 8 bytes (13% of a 64 byte maximum)


.


ATtiny13 .


-


( ?) . — . , , , . , , .


,


DipTrace «» «PCB Layout», . , .



— .



, , .


( , 80- ).



CD .



, , , .



— .


: , .


, , . — , .




— . - - "Craft&Clay" 50- 70. , .



.



15 130 .



— .




— .



— .



.



4 , 2-3 ,
, .



. , , , " ".



, .



KSP. — 4 LED 5 .



, , DC-DC 0.9-5 , .



. , , .




, , , .



ISP 10- .




, , , - . , , " ". 1.5 , — . , .


,, %/,
CR12121810.250
CR16206810.950
CR203221013
NiCD AAA3502098
NiMH AAA90030375
NiCd AA100020270
Alkaline AAA1250235
NiMH AA2400301000
Alkaline AA2890280
Li-Ion440010600

, . , , (2/100)2890/(2430) = 80 . , 2 , 32 ATtiny13.


: , GPIO, . — , ( 4 14 ""), , 40 .


, — . , . , : 5 DC-DC , , DC-DC 1.5 -> 5 . , - +-20%, .



, "" 4-5 (5 ) , , 25 (1.5 ),



.. 2890 116 , . ATtiny13 POWER DOWN . , — . 20-50 , , Hi-Z, 1 . , DC-DC .


2 5 . : .


,


, :


  • , — , R2, , . .
  • . — 1/37 , .
  • , , . POWER_DOWN 30 , , , .
  • traffic_signals 8 4, . 4 pin — 1 DDR PORTB
  • uint16_t signal_period flash_period — , , 1 .
  • — ROM 2 , — - .
  • /UART.
  • main — — +50 ROM.
  • 9,6 128 , .

.


: " ", , 8 , , «» .


.




Github, MIT.

Source: https://habr.com/ru/post/pt443188/


All Articles