Tiga mata tergantung pada pilar, atau kisah bahwa lima kaki ATtiny13 sudah cukup


KDPV "Oh, itu dia."


Ada kemungkinan kecil bahwa longrid ini akan menjadi sumber kebijaksanaan yang memberi kehidupan bagi para intelektual, canggih dalam rahasia ramalan pada kartu Carnot dan mengetahui makna rahasia dari Bentuk Normal Ketiga. Tetapi jika karena alasan tertentu Anda menyentuh Arduino Anda dengan tangan Anda, besi solder mengumpulkan debu di dapur, Anda mengerti mengapa baterai memiliki satu plus, dan C ++ memiliki dua, maka keajaiban yang benar-benar ajaib dan menakjubkan tidak akan membuat Anda acuh tak acuh. Jadi, dengan senang hati saya merekomendasikan kepada Anda jumlah pertunjukan sirkus gelandangan "Saman dengan Boxwood" hari ini :


  • Menambahkan RAM dan ROM ke ATtiny13!
  • Kecerdasan buatan dalam mikroprosesor - pro dan kontra, atau kecantikan tidur - yah, bukankah dia bodoh?
  • Atau masih dura lex sed lex?
  • Bagaimana cara menambahkan kaki ke ATtiny13?
  • Beberapa kata tentang dimensi kelima: bagaimana menjejalkan yang tak tertahankan?
  • Menggergaji setengah non-perawan dengan mencampur isi bagian (dengan jaminan pemulihan).
  • β€œMemberi Makan Penderitaan” (lihat kasus sebelumnya tentang lima ribu orang yang jenuh dengan lima roti jelai dan dua ikan).

Jika setidaknya salah satu trik berguna di masa depan bagi setiap pembaca kedua puluh, saya akan puas, artikel itu ditulis tidak sia-sia.


Lampu lalu lintas pertama atau Kaa melakukan perlawanan.


Ceritanya dimulai, seperti dalam video Natal pra-Natal klasik, ketika kamera melihat melalui jendela buram ke sebuah ruangan kecil yang nyaman: pohon Natal di perada, kapas dan mainan, aroma jeruk keprok dan anggur yang dipoles, getaran hangat bayangan dari cahaya lilin. Di sofa besar, Dia meluruskan kotak-kotak dan dengan lembut menempelkan pipinya ke bahu-Nya, tanpa sadar mendengarkan gadis kecil yang penuh semangat seperti malaikat ...


Mereka yang memiliki pengalaman sebagai orang tua tahu betul apa yang pada saat seperti itu dapat Anda dengar. Saya akan menjelaskan kepada mereka yang belum memperoleh keterampilan seperti itu - dengan tingkat probabilitas tinggi, orang tua sekarang tercengang oleh sesuatu seperti: "Ayah! Kita besok! Ke TK! Saya harus! Bawa kerajinan ke kontes pohon Natal! Dan saya ingin tempat pertama! "


Itu perlu. Besok Untuk kita Kerajinan tangan Yang terbaik


Wawancara yang terlibat dengan pelanggan menunjukkan kontur pernyataan kerja: kita membutuhkan lampu lalu lintas. Dan untuk menjadi cantik dan bersinar seperti yang asli. Sudah pada tahap ini, jajaran kandidat untuk proyek ISU secara dramatis menipis: Ayah tidak dapat mendukung gagasan bahwa lampu lalu lintas yang cantik, lembut, dijahit dari tambal sulam atau rajutan atau kaitan adalah representasi yang diwujudkan dari mimpi Pelanggan: lampu lalu lintas harus menyala - apa yang tidak jelas?


Malam bergulir di seluruh negeri, dan pekerjaan mulai mendidih di negara kita.


Bahan tubuh lampu lalu lintas adalah selongsong kertas toilet, dikompresi untuk membentuk sebuah kotak. Koin sepuluh rubel itu dikelilingi oleh pensil, dan kemudian lubang-lubang dipotong dengan pisau klerikal di bawah lampu-lampu pensinyalan cahaya (pekerjaan traumatis tidak dipercaya oleh anak-anak).



Tutup bagian atas dan bawah lampu lalu lintas dipotong dari karton di tempat. Puncak atas lampu sesuai dengan pola yang dibuat dilingkari pada kertas 80 gram biasa dan dipotong secara manual.



Kemudian mereka terpaku pada PVA.



Struktur yang dirakit diseret ke halaman dan dicat dengan cat semprot akrilik: murah hati perak, kemudian sedikit hitam di atasnya.



Jika terjadi kerusakan pada tahap apa pun, tiga salinan dibuat sekaligus. Tiga strip kertas berwarna - merah, kuning, dan hijau - ditempel dengan filter cahaya di dalam yang paling sukses.


Menyoroti dari dalam diputuskan oleh sepasang LED putih super terang dari tempat sampah yang luas di tanah air (SHZR). Kodok Kaptershchitskaya dengan datar menolak untuk memberikan kepada ayah kehadiran SCHR bahkan tiga baterai lithium tablet, dan LED tidak setuju untuk bersinar dari satu, menyatakan bahwa mereka putih dan cerah, dan tegangan jatuh pada mereka dari 2,8 menjadi 3,9 volt. Maksimum yang berhasil kami tawar-menawar dengan kodok adalah untuk satu baterai AA, cincin ferit dari throttle motherboard yang terbakar dan transistor KT315. Berpikir dan googling, ayah harus menerima tawaran itu. Dan mengingat jumlah pena lucu di setiap kelompok TK, ide dengan baterai lithium tidak terlihat sangat menarik.


Lambung lampu lalu lintas pada baterai menggantikan aroma jarum dan jeruk keprok dengan aroma cat yang keras, ayahku dengan hati-hati menyodok besi solder pada rosin, anak-anak melukai transformator untuk memblokir generator (duplikasi salinan), semuanya berjalan sesuai rencana ...


Dan tidak, "tiba-tiba" malam itu tidak terjadi: semua trik ketika melilitkan trafo adalah dengan segera memutar jumlah belokan maksimum yang mungkin dengan kawat ganda. Jangan bingung antara anoda dan katoda LED dan terminal transistor KT315 dan hubungkan ujung gulungan dengan benar (atau tukar jika tidak menyala) sesuai dengan diagram sirkuit. J1 - saklar daya dari jumper komputer, kemudian ditampilkan "di atap" lampu lalu lintas.


Sirkuit yang benar-benar sederhana untuk menghasilkan tegangan AC dengan puncak 3-7V dari baterai 1.5V G1 telah lama dikenal .



Secara fisik, diagram rangkaian diwujudkan sebagai berikut:



Pita merah memiliki baterai alkaline AA.


Dan lampu lalu lintas itu sendiri seperti itu.



Di pagi hari, anak yang sombong menyeret produk itu ke taman kanak-kanak, tempat mainan membuat percikan dan menjadi pusat perhatian di pohon Natal.



Benar, itu tidak berhasil dengan tempat pertama dalam kompetisi - batas waktu untuk mengirimkan entri, ternyata, sudah beberapa hari yang lalu.


Di rumah, ada dua bangunan di ambang jendela dan ketidakpuasan gatal ayah saya dengan solusi untuk tugas "Saya ingin itu seperti lampu lalu lintas yang nyata". Dan idenya berputar "apakah mungkin untuk mencocokkan solusi yang lengkap, katakanlah pada hal ke-13, bahwa katak telah berbaring di ShchZR untuk waktu yang lama? Apakah akan ada cukup lima kaki, satu kilobyte untuk kode dan 64 byte RAM dan itu, seperti yang dipesan, seperti yang asli?"


Jadi semua ini hanya perkataan, dongeng tentang solusi akhir dari masalah lampu lalu lintas di depan.


Lampu lalu lintas kedua, seperti yang asli


Alat, bahan, dan dokumentasi bekas


Bahasa / kerangka kerja : C / Arduino 1.6 / 1.8.
IDE : MS Visual Studio 2012 + Plugin Visual Micro + git.
CAD : DipTrace.
HW : ATtiny13 MK, klon Arduino Nano pada ATmega328, USB-UART pada FT232R, programmer USBISP china-noname.
Teknologi PP : LUT .
Alat : Solder, pistol lem, oven dapur, pisau, gunting, pemotong kawat.
Bahan : Dari ShchZR - 4 LED keluaran merah, kuning, hijau dari merek noname, kapasitor tantalum SMD dan sepasang resistor 0805 masing-masing 10k, setengah lusin output 0,25W resistor pembatas arus MF-25, konverter DC-DC 5V pembatas arus Cina, kaleng aerosol dengan cat perak dan hitam, kertas A4, tanah liat polimer dari penjualan.


Sumber dan dokumen tersedia di Github di bawah lisensi MIT, kode sumber melakukan bersamaan dengan iterasi dari firmware yang dijelaskan di bawah, semua jalur file yang disebutkan relatif terhadap akar repositori.


Dokumentasi :
./docs/ATtiny13A datasheet.pdf [Spesifikasi untuk MK Atmel ATtiny13A]
./docs/ATmega328 datasheet.pdf [Spesifikasi Atmel ATmega328 MK]
./docs/AVR4027 - Kiat dan Trik untuk Mengoptimalkan Kode C Anda.pdf [Atmel AVR4027: Kiat dan Trik untuk Mengoptimalkan Kode C Anda untuk Mikrokontroler AVR 8-bit]
./docs/AVR4013 - PicoPower basics.pdf [Catatan tentang Mode Penghematan Daya]


Dari IDE Arduino, seperti selimut dari awan. Wiz mereka adalah ejekan halus Jesuit tentang segala hal yang dapat disakralkan di kalangan programmer embed. Tetapi Arduino, sebagai ekosistem, hidup, akan hidup dan akan hidup, dan karena kesederhanaan menginstal lingkungan pada komputer di bawah berbagai OS, dan karena mereka adalah yang pertama kali mengaktifkan, tanpa biaya khusus untuk debugger perangkat keras, menggunakan sen UART dan bootloader eksklusif, pengembangan dalam isian MK yang cukup serius. Dan di sini adalah Paman Liao, siap untuk menjual beberapa klon dengan harga satu asli. Fakta bahwa di atmegs senior Anda dapat men-debug logika dan operasi program, dan kemudian dengan perubahan minimal untuk mentransfer ke tinka yang sama - ini juga merupakan argumen.


Itu normal dan nyaman bagi saya untuk bekerja di MS VisualStudio , saya tidak punya terlalu banyak ruang untuk AtmelStudio atau WinAVR dan saya tidak ingin menemukannya, tanpa debugger perangkat keras mereka tidak memiliki fasilitas terbaik. Tentang plugin VisualMicro, yang menambahkan dukungan Arduino ke MS VisualStudio , sudah ditulis dengan cukup detail dan ditulis dengan cerdas di Haber.
Fokus "Arduino pada ATtiny13" pada hub juga telah dipertimbangkan sejak lama dan berulang kali .


Secara singkat, tambahkan modul MicroCore ke instalasi yang diinstal dari lingkungan Arduino, setelah itu menjadi mungkin untuk memilih ATtiny13 MK dalam kartu target.



Git - tidak ada alternatif untuk apa pun, bahkan sebagian besar proyek rumah. Kebiasaannya sederhana, tetapi benar: ketika mulai bekerja pada program apa pun, cukup ketik "git init" di direktori pada baris perintah. Dukungan bawaan MS Visual Studio untuk komit di repositori lokal akan menghemat waktu dan waktu lebih dari sekali.


DipTrace, seperti CAD untuk sirkuit dan papan sirkuit tercetak, nyaman, domestik, sirkuit dan kabel ramah pengguna, mudah untuk menambahkan komponen khusus (UGO, kontak), jika diinginkan, papan sirkuit cetak dengan komponen dapat diputar dalam 3D, bantuan berkualitas tinggi dan pelajaran pelatihan disertakan. Selain itu, saya terkesan dengan kebijakan lisensi mereka: batasan lisensi standar nirlaba (1000 pin, 4 lapisan sinyal), gratis untuk Rusia, Ukraina, dan Republik Belarus, dalam 99% kasus sudah cukup untuk kerajinan rumah.


Saya tidak bisa mengatur agar Arduino Nano berfungsi dengan baik, sebagai programmer yang cerdik, tetapi dengan programmer ISP USB, masalahnya diselesaikan dengan mudah. Dengan cepat membuat sketsa file batch untuk kompilasi / firmware - di direktori ./gcc di proyek.


File .ino (tetapi sebenarnya C / C ++) dapat dikompilasi dengan benar di studio "di bawah arduino di bawah ATtiny13", itu hanya dilayani oleh parameter file batch ini pada baris perintah:


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


All Articles