Trois yeux pendent sur un pilier, ou l'histoire que cinq jambes d'ATtiny13 suffisent


KDPV "Oh, c'est tout."


Il y a peu de chances que ce longrid devienne une source de sagesse vivifiante pour les intellectuels, sophistiqués dans les secrets de la divination sur les cartes Carnot et connaissant la signification secrÚte de la troisiÚme forme normale. Mais si pour une raison quelconque vous avez touché votre arduino avec vos mains, un fer à souder accumule de la poussiÚre dans le garde-manger, vous comprenez pourquoi la batterie en a un plus, et C ++ en a deux, alors les miracles vraiment magiques et incroyables ne vous laisseront pas indifférent. J'ai donc le plaisir de vous recommander les numéros de la représentation d'aujourd'hui du cirque vagabond «Saman avec buis» :


  • Ajout de RAM et ROM Ă  ATtiny13!
  • L'intelligence artificielle dans un microprocesseur - pour et contre, ou une beautĂ© endormie - eh bien, n'est-elle pas une idiote?
  • Ou est-ce encore dura lex sed lex?
  • Comment ajouter des jambes Ă  ATtiny13?
  • Quelques mots sur la cinquiĂšme dimension: comment entasser l'insupportable?
  • Sciage en demi non-vierges avec mĂ©lange du contenu des moitiĂ©s (avec une garantie de rĂ©cupĂ©ration).
  • «Nourrir les affligĂ©s» (voir le cas prĂ©cĂ©dent de cinq mille personnes saturĂ©es de cinq pains d'orge et de deux poissons).

Si au moins l'une des astuces est utile à l'avenir pour chaque vingtiÚme lecteur, je serai satisfait, l'article n'a pas été écrit en vain.


Le premier feu tricolore ou Kaa prend le combat.


L'histoire a commencĂ©, comme dans une vidĂ©o classique de NoĂ«l avant NoĂ«l, lorsque la camĂ©ra regarde Ă  travers une fenĂȘtre givrĂ©e dans une petite piĂšce confortable: un arbre de NoĂ«l en guirlandes, du coton et des jouets, l'odeur de la mandarine et du vin chaud, le chaud tremblement d'ombres de la bougie. Sur le grand canapĂ©, Elle redresse le plaid et presse doucement sa joue contre Son Ă©paule, Ă©coutant distraitement la petite fille aux anges aux gestes enthousiastes ...


Ceux qui ont une expérience parentale savent parfaitement ce que vous pouvez entendre à un tel moment. Je vais expliquer à ceux qui n'ont pas encore acquis une telle compétence - avec un haut degré de probabilité, les parents sont maintenant abasourdis par quelque chose comme: «Papa! Nous demain! Au jardin d'enfants! Je dois! Apportez de l'artisanat au concours d'arbres de Noël! Et je veux la premiÚre place! "


C'est nécessaire. Demain. Pour nous. Artisanat. Le meilleur.


L'entretien avec le client montre les contours du TOR: nous avons besoin d'un feu de signalisation. Et pour ĂȘtre belle et rayonner comme une vraie. DĂ©jĂ  Ă  ce stade, les rangs des candidats au projet ISU s'amincissent considĂ©rablement: Papa est incapable de justifier l'idĂ©e qu'un joli feu doux cousu Ă  partir de patchwork ou de feu de signalisation tricotĂ© ou crochetĂ© est une reprĂ©sentation incarnĂ©e des rĂȘves du client: le feu de circulation doit ĂȘtre allumĂ© - qu'est-ce qui n'est pas clair?


La nuit a roulé sur le pays et le travail a commencé à bouillir dans notre pays.


Le corps du feu de circulation est un manchon en papier hygiénique, comprimé pour former une boßte. La piÚce de dix roubles a été encerclée avec un crayon, puis des trous ont été découpés avec un couteau de bureau sous les lumiÚres de la signalisation lumineuse (le travail traumatisant n'est pas confié aux enfants).



Les couvercles du haut et du bas du feu de circulation sont découpés dans du carton en place. Les pics au-dessus des lampes selon le motif fait ont été encerclés sur du papier ordinaire de 80 grammes et découpés manuellement.



Ensuite, ils ont été collés au PVA.



Les structures assemblées ont été traßnées dans la cour et peintes avec des peintures acryliques: généreusement argentées, puis légÚrement noires sur le dessus.



En cas de dommage à quelque stade que ce soit, trois copies ont été réalisées à la fois. Trois bandes de papier de couleur - rouge, jaune et vert - ont été collées avec des filtres lumineux à l'intérieur des plus réussies.


La mise en Ă©vidence de l'intĂ©rieur a Ă©tĂ© dĂ©cidĂ©e par une paire de LED blanches super brillantes provenant des gĂ©nĂ©reux bacs de la patrie (SHZR). Le crapaud de Kaptershchitskaya a catĂ©goriquement refusĂ© de donner au pĂšre de la prĂ©sence de SCHR mĂȘme trois piles au lithium pour tablettes, et les LED n'ont pas acceptĂ© de briller d'une seule, dĂ©clarant qu'elles Ă©taient blanches et lumineuses, et la chute de tension sur elles Ă©tait de 2,8 Ă  3,9 volts. Le maximum que nous avons rĂ©ussi Ă  nĂ©gocier avec le crapaud Ă©tait pour une batterie AA, un anneau de ferrite de l'accĂ©lĂ©rateur de la carte mĂšre brĂ»lĂ©e et le transistor KT315. En rĂ©flĂ©chissant et en cherchant sur Google, papa a dĂ» accepter l'offre. Et compte tenu du nombre de stylos ludiques dans chaque groupe du jardin d'enfants, l'idĂ©e avec des piles au lithium ne semblait pas particuliĂšrement attrayante.


Les coques des feux de circulation sur la batterie ont remplacé les arÎmes d'aiguilles et de mandarines par une odeur dure de peinture, mon pÚre a réfléchi avec précaution un fer à souder sur la colophane, les enfants ont enroulé des transformateurs pour bloquer les générateurs (duplication de copies), tout s'est passé comme prévu ...


Et non, «tout d'un coup» cette nuit-là n'a pas eu lieu: toutes les astuces lors de l'enroulement d'un transformateur sont d'enrouler immédiatement le nombre maximum de tours possible avec un fil doublé. Ne confondez pas l'anode et la cathode de la LED et les bornes du transistor KT315 et connectez correctement les extrémités des enroulements (ou échangez-les s'ils ne sont pas allumés) selon le schéma de circuit. J1 - interrupteur d'alimentation d'un cavalier d'ordinateur, affiché plus tard "sur le toit" d'un feu de circulation.


Un circuit complĂštement simple pour produire une tension alternative avec des pics de 3-7V Ă  partir d'une batterie 1.5V G1 est connu depuis longtemps.



Physiquement, le schéma de circuit est réalisé comme suit:



La paperasse a une pile alcaline AA.


Et le feu de circulation lui-mĂȘme est comme ça.



Le matin, l'enfant fier a traĂźnĂ© le produit au jardin d'enfants, oĂč le jouet a fait sensation et a pris le devant de la scĂšne sur l'arbre de NoĂ«l.



Certes, cela n'a pas fonctionné avec la premiÚre place du concours - la date limite pour soumettre des candidatures était, comme il s'est avéré, il y a déjà plusieurs jours.


À la maison, il y avait deux bĂątiments sur le rebord de la fenĂȘtre et le mĂ©contentement de mon pĂšre Ă  propos de la solution Ă  la tĂąche «Je le veux comme un vrai feu de circulation». Et l'idĂ©e tournait "est-il possible de trouver une solution complĂšte, disons dans la 13Ăšme chose, que le crapaud se trouve depuis longtemps dans le ShchZR ? Y aura-t-il assez de cinq jambes, un kilo-octet pour le code et 64 octets de RAM et cela, comme commandĂ©, comme une vraie?"


Donc, tout cela n'était qu'un dicton, un conte de fées sur la solution finale du problÚme des feux de circulation à venir.


Le deuxiĂšme feu de circulation, comme un vrai


Outils, matériaux et documentation utilisés


Langage / framework : C / Arduino 1.6 / 1.8.
IDE : MS Visual Studio 2012 + plugin Visual Micro + git.
CAD : DipTrace.
HW : MK ATtiny13, clone d'Arduino Nano sur ATmega328, USB-UART sur FT232R, programmeur USBISP de Chine non-nom.
Technologie PP : LUT .
Outils : fer Ă  souder, pistolet Ă  colle, four de cuisine, couteau, ciseaux, coupe-fil.
Matériaux : De ShchZR - 4 LED de sortie rouges, jaunes, vertes de marque noname, condensateur au tantale SMD et une paire de résistances 0805 chacune 10k, une demi-douzaine de résistances de limitation de courant de 0,25 W MF-25, convertisseur intensif DC-DC 5V chinois, bombes aérosol avec peinture argent et noir, papier A4, pùte polymÚre de la vente.


Les sources et documents sont disponibles sur Github sous la licence MIT, les validations de code source coïncident avec l'itération du firmware décrit ci-dessous, tous les chemins de fichiers mentionnés sont relatifs à la racine du référentiel.


Documentation :
./docs/ATtiny13A datasheet.pdf [Spécifications pour MK Atmel ATtiny13A]
./docs/ATmega328 datasheet.pdf [Spécification Atmel ATmega328 MK]
./docs/AVR4027 - Trucs et astuces pour optimiser votre code C.pdf [Atmel AVR4027: Trucs et astuces pour optimiser votre code C pour les microcontrĂŽleurs AVR 8 bits]
./docs/AVR4013 - PicoPower basics.pdf [Notes sur les modes d'économie d'énergie]


De l' IDE Arduino, comme une couverture du cloud. Leur Wiz est la moquerie subtile jĂ©suite de tout ce qui peut ĂȘtre sacrĂ© parmi les programmeurs intĂ©grĂ©s. Mais Arduino, en tant qu'Ă©cosystĂšme, a vĂ©cu, vivra et vivra, et en raison de la simplicitĂ© d'installation de l'environnement sur des ordinateurs sous diffĂ©rents systĂšmes d'exploitation, et parce qu'ils ont Ă©tĂ© les premiers Ă  permettre, sans frais particuliers pour un dĂ©bogueur matĂ©riel, d'utiliser un UART penny et un chargeur de dĂ©marrage propriĂ©taire, dĂ©veloppement dans un bourrage MK assez sĂ©rieux. Et voici Oncle Liao, prĂȘt Ă  vendre une poignĂ©e de clones au prix d'un original. Le fait que dans les atmegs supĂ©rieurs, vous pouvez dĂ©boguer la logique et le fonctionnement du programme, puis avec des modifications minimales pour les transfĂ©rer dans le mĂȘme tinka - c'est Ă©galement un argument.


C'est normal et confortable pour moi de travailler dans MS VisualStudio , je n'ai pas trop d'espace pour AtmelStudio ou WinAVR et je ne veux pas le trouver, sans dĂ©bogueur matĂ©riel, ils n'ont pas les commoditĂ©s ultimes. À propos du plugin VisualMicro, qui ajoute le support Arduino Ă  MS VisualStudio , il a dĂ©jĂ  Ă©tĂ© Ă©crit avec suffisamment de dĂ©tails et intelligemment Ă©crit dans Haber.
La focalisation d'Arduino sur ATtiny13 sur le hub a également été considérée il y a longtemps et à plusieurs reprises .


BriÚvement, ajoutez le module MicroCore à l'installation installée de l'environnement Arduino, aprÚs quoi il devient possible de sélectionner l'ATtiny13 MK dans les cartes cibles.



Git - aucune alternative pour aucun, mĂȘme les projets les plus Ă  la maison. L'habitude est simple, mais correcte: lorsque vous commencez Ă  travailler sur n'importe quel programme, tapez simplement "git init" dans le rĂ©pertoire sur la ligne de commande. La prise en charge intĂ©grĂ©e de MS Visual Studio pour les validations dans le rĂ©fĂ©rentiel local fera gagner du temps et du temps plus d'une fois.


DipTrace, comme la CAO pour les circuits et une carte de circuit imprimĂ©, est pratique, domestique, les circuits et le cĂąblage sont conviviaux, il est facile d'ajouter des composants personnalisĂ©s (UGO, contacts), si vous le souhaitez, une carte de circuit imprimĂ© avec des composants peut ĂȘtre tordue en 3D, une aide de haute qualitĂ© et des leçons de formation sont incluses. De plus, je suis impressionnĂ© par leur politique d'octroi de licences: les limites de la licence standard Ă  but non lucratif (1000 broches, 4 couches de signal) gratuite pour la Russie, l'Ukraine et la RĂ©publique du BĂ©larus, dans 99% des cas, c'est suffisant pour l'artisanat domestique.


Je ne pouvais pas réussir à faire fonctionner Arduino Nano correctement, en tant que programmeur tinky, mais avec un programmeur USB ISP, le problÚme est résolu facilement. Fichiers batch rapidement esquissés pour la compilation / firmware - dans le répertoire ./gcc du projet.


Le fichier .ino (mais il s'agit bien de C / C ++) peut ĂȘtre correctement compilĂ© en studio "sous arduino sous ATtiny13", il est simplement servi par le paramĂštre de ce fichier batch sur la ligne de commande:


>"./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/fr443188/


All Articles