123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- /**
- * My Nixie Clock IN-12
- * Vladimir N. Shilov <shilow@ukr.net>
- * 2019.01.18
- */
- /* Compiler libs */
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <avr/eeprom.h>
- #include <avr/pgmspace.h>
- /* Project libs */
- #include "i2c.h"
- #include "ds3231.h"
- #include "rtos.h"
- #include "event-system.h"
- #include "common.h"
- #include "main.h"
- /* Defines */
- /* Timer2 settings */
- #define TIMER2_HZ 400
- #define TIMER2_PRESCALER 1024
- #define TIMER2_CS (1<<CS22 | 1<<CS21 | 1<<CS20)
- #define TIMER2_CNT (0x100 - (F_CPU / TIMER2_PRESCALER / TIMER2_HZ))
- /* Display timeout, sec */
- #define DISP_WDT_TIME 10
- #ifdef USE_UART
- /* USART */
- #define BAUD 19200UL
- #define BAUD_PRESCALE (uint8_t)((F_CPU / BAUD / 16UL) - 1)
- #define CHAR_NEWLINE '\n'
- #define CHAR_RETURN '\r'
- #define RETURN_NEWLINE "\r\n"
- #endif // USE_UART
- #ifdef USE_BRIGHT_CONTROL
- /* Lamp brightness */
- #define BRIGHT_IDX_MAX 4
- #define FULL_BRIGHT_ON 0x06
- #define FULL_BRIGHT_OFF 0x22
- static const uint8_t PROGMEM brightConv[BRIGHT_IDX_MAX+1] = {
- 218, 225, 230, 240, 255
- };
- #endif // USE_BRIGHT_CONTROL
- #ifdef USE_DHT
- // timeout in timer tiks, step 4 mks
- #define DHT_TIMEOUT 1500
- #define DHT_TOUT1 55
- static struct {
- uint8_t Humidity;
- uint16_t Temperature;
- } dhtData;
- #endif // USE_DHT
- /* Variables */
- static volatile uint8_t Digit[4] = {1, 2, 3, 4};
- static rtc_t RTC, setRTC;
- static volatile struct {
- uint8_t RTC_Int: 1;
- uint8_t saveCal: 1;
- uint8_t blinkC: 1;
- uint8_t blink0: 1;
- uint8_t blink1: 1;
- uint8_t blink2: 1;
- uint8_t blink3: 1;
- uint8_t saveEEP: 1;
- } Flag;
- static btn_t Button[BTN_NUM] = {
- {0, evBTN1Pressed, evBTN1Holded, BUTTON1_PIN},
- {0, evBTN2Pressed, evBTN2Pressed, BUTTON2_PIN},
- {0, evBTN3Pressed, evBTN3Pressed, BUTTON3_PIN}
- };
- static volatile uint8_t DISP_WDT = 0;
- static EEMEM uint8_t EEP_BrightIdx;
- static uint8_t brightIdx;
- static EEMEM uint8_t EEP_SummerTime;
- /* Function prototypes */
- static void Board_Init(void);
- static void dotOn(void);
- static void btnProcess(void);
- static void valIncrease(uint8_t * val, uint8_t max);
- static void valDecrease(uint8_t * val, uint8_t max);
- static void blink(void);
- static void setSummerWinterTime(void);
- #ifdef USE_DHT
- static void dhtStart(void);
- static void dhtProcess(void);
- static void dhtEnd(void);
- static void dhtTimeout(void);
- static void dhtNoAck(void);
- #endif // USE_DHT
- #ifdef USE_UART
- void usart_putc (char send);
- void usart_puts (const char *send);
- #endif // USE_UART
- void main(void) {
- /**
- * Локальные переменные
- */
- uint8_t event = 0;
- Flag.RTC_Int = 0;
- Flag.saveCal = 0;
- Flag.blink0 = 0;
- Flag.blink1 = 0;
- Flag.blink2 = 0;
- Flag.blink3 = 0;
- Flag.blinkC = 0;
- Flag.saveEEP = 0;
- #ifdef USE_BRIGHT_CONTROL
- brightIdx = eeprom_read_byte(&EEP_BrightIdx);
- if (brightIdx > BRIGHT_IDX_MAX) {
- brightIdx = BRIGHT_IDX_MAX;
- }
- #endif // USE_BRIGHT_CONTROL
- /**
- * Инициализация, настройка...
- */
- Board_Init();
- /* Initialize Scheduler */
- RTOS_Init();
- tdelay_ms(1000); // warm up
- /* Initialize I2C Bus and RTC */
- I2C_Init();
- RTC_Init();
- RTC_ReadAll(&RTC);
- /* Initialize Event State Machine */
- ES_Init(stShowTime);
- showTime();
- RTOS_SetTask(btnProcess, 3, BTN_SCAN_PERIOD);
- #ifdef USE_DHT
- RTOS_SetTask(dhtStart, 2000, 15000);
- #endif // USE_DHT
- /** main loop */
- do {
- /* new second interrupt from RTC */
- if (Flag.RTC_Int != 0) {
- Flag.RTC_Int = 0;
- ES_PlaceEvent(evNewSecond);
- RTC_ReadTime(&RTC);
- if (RTC.Sec == 0 && RTC.Min == 0) {
- // begin of new hour
- if (RTC.Hr == 0) {
- RTC_ReadCalendar(&RTC);
- ES_PlaceEvent(evRefreshCal);
- }
- #ifdef USE_BRIGHT_CONTROL
- if (RTC.Hr >= FULL_BRIGHT_ON && RTC.Hr < FULL_BRIGHT_OFF) {
- OCR2 = pgm_read_byte(&brightConv[BRIGHT_IDX_MAX]);
- } else {
- OCR2 = pgm_read_byte(&brightConv[brightIdx]);
- }
- #endif // USE_BRIGHT_CONTROL
- setSummerWinterTime();
- } // begin new hour
- if (DISP_WDT != 0) {
- DISP_WDT --;
- if (DISP_WDT == 0) {
- ES_PlaceEvent(evDisplayWDT);
- if (Flag.saveCal != 0) {
- Flag.saveCal = 0;
- RTC_WriteCalendar(&RTC);
- }
- if (Flag.saveEEP != 0) {
- Flag.saveEEP = 0;
- eeprom_update_byte(&EEP_BrightIdx, brightIdx);
- }
- }
- }
- } // End of New Second
- event = ES_GetEvent();
- if (event) {
- ES_Dispatch(event);
- }
- // крутим диспетчер
- RTOS_DispatchTask();
- // делать нечего -- спим, ждём прерывание
- set_sleep_mode(SLEEP_MODE_IDLE);
- sleep_mode();
- } while(1);
- }
- /**
- * П о д п р о г р а м м ы
- */
- /**
- * @brief Initialize peripheral
- */
- static void Board_Init(void) {
- /* power off Analog Comparator */
- ACSR = ACD;
- /* GPIO */
- PORTB = BUTTON_PINS; // enable pull-up
- DDRC = DIGIT_PINS; // as output
- DDRD = (DOT_PIN | ANOD_PINS); // as output
- #ifdef USE_DHT
- /* Timer1, IC negative edge, CTC mode, 64 prescaler, 4 mks one tick */
- TCCR1B = ((0<<ICES1) | (1<<CS11) | (1<<CS10));
- #endif // USE_DHT
- /* Timer2 - refresh Nixie values */
- TCCR2 = TIMER2_CS;
- TCNT2 = TIMER2_CNT;
- TIMSK = _BV(TOIE2);
- #ifdef USE_BRIGHT_CONTROL
- OCR2 = pgm_read_byte(&brightConv[BRIGHT_IDX_MAX]);
- TIMSK |= _BV(OCIE2);
- #endif // USE_BRIGHT_CONTROL
- /* Interrupt from RTC */
- MCUCR = _BV(ISC11); // falling edge
- GICR = _BV(INT1);
- #ifdef USE_UART
- /* USART */
- // Turn on USART hardware (no RX, TX)
- UCSRB |= (0 << RXEN) | (1 << TXEN);
- // 8 bit char sizes
- UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
- // Set baud rate
- UBRRH = (BAUD_PRESCALE >> 8);
- UBRRL = BAUD_PRESCALE;
- #endif // USE_UART
- /* Enable Interrupts */
- sei();
- }
- /**
- * @brief Correct current time for Sun or Winter
- */
- static void setSummerWinterTime(void) {
- uint8_t sunTime = eeprom_read_byte(&EEP_SummerTime);
- /* Переход на летнее время */
- if ((RTC.Mon == 3) && (RTC.WD == 7) && (RTC.Hr == 3) && (sunTime != 0)) {
- if ((RTC.Day + 7) > 31) {
- RTC.Hr = 4;
- RTC_WriteHHMM(&RTC);
- sunTime = 0;
- }
- }
- /* Переход на зимнее время */
- if ((RTC.Mon == 10) && (RTC.WD == 7) && (RTC.Hr == 4) && (sunTime == 0)) {
- if ((RTC.Day + 7) > 31) {
- RTC.Hr = 3;
- RTC_WriteHHMM(&RTC);
- sunTime = 1;
- }
- }
- eeprom_update_byte(&EEP_SummerTime, sunTime);
- }
- static void dotOn(void) {
- PORTD |= DOT_PIN;
- }
- void dotOff(void) {
- PORTD &= ~(DOT_PIN);
- }
- void dotOnPersistent(void) {
- RTOS_DeleteTask(dotOff);
- PORTD |= DOT_PIN;
- }
- #ifdef USE_DHT
- static void dhtStart(void) {
- RTOS_SetTask(dhtProcess, 2, 0);
- DHT_PIN_LOW;
- }
- static void dhtProcess(void) {
- uint8_t cnt1, cnt2, buf;
- uint16_t tcnt_old, hmdt, tmprtr;
- DHT_PIN_INPUT;
- TCNT1 = 0;
- // ждём первого "0"
- while(bit_is_set(PINB, PB0) && TCNT1<DHT_TOUT1);
- if (TCNT1 >= DHT_TOUT1) {
- RTOS_SetTask(dhtNoAck, 0, 0);
- return;
- }
- // white for end of preamble
- while(bit_is_clear(PINB, PB0));
- while(bit_is_set(PINB, PB0) && TCNT1<DHT_TIMEOUT);
- if (TCNT1 >= DHT_TIMEOUT) {
- RTOS_SetTask(dhtTimeout, 0, 0);
- }
- hmdt = 0; tmprtr = 0;
- for (cnt1=0; cnt1<32; cnt1+=8) { // 0 8 16 24 32
- buf = 0;
- for (cnt2=0; cnt2<8; cnt2++) {
- buf <<= 1;
- // "0", начало периода
- while(bit_is_clear(PINB, PB0)); // ждём начало импульса
- tcnt_old = TCNT1; // начало импульса
- while(bit_is_set(PINB, PB0) && TCNT1<DHT_TIMEOUT); // ждём конец импульса
- if ((TCNT1 - tcnt_old) > 10) {
- buf |= 1;
- }
- }
- switch (cnt1) {
- case 0:
- hmdt = buf << 8;
- break;
- case 8:
- hmdt |= buf;
- break;
- case 16:
- tmprtr = buf << 8;
- break;
- case 24:
- tmprtr |= buf;
- break;
- }
- }
- if (TCNT1 >= DHT_TIMEOUT) {
- RTOS_SetTask(dhtTimeout, 0, 0);
- return;
- }
- dhtData.Humidity = (uint8_t)((hmdt + 5) / 10);
- dhtData.Temperature = tmprtr;
- RTOS_SetTask(dhtEnd, 0, 0);
- }
- static void dhtEnd(void) {
- #ifdef USE_UART
- char buffer[6];
- usart_puts("Humidity: ");
- itoa(dhtData.Humidity, buffer, 10);
- usart_puts(buffer);
- usart_puts(" %\t\t");
- usart_puts("Temperature: ");
- itoa(dhtData.Temperature/10, buffer, 10);
- usart_puts(buffer);
- usart_putc('.');
- itoa(dhtData.Temperature%10, buffer, 10);
- usart_puts(buffer);
- usart_puts("oC\r\n");
- #endif // USE_UART
- }
- static void dhtNoAck(void) {
- #ifdef USE_UART
- usart_puts("DHT22 no ACK occurred.\r\n");
- #endif // USE_UART
- }
- static void dhtTimeout(void) {
- #ifdef USE_UART
- usart_puts("DHT22 Timeout occurred.\r\n");
- #endif // USE_UART
- }
- void showTemperature(void) {
- dotOn();
- uint8_t a = dhtData.Temperature / 10;
- uint8_t b = dhtData.Temperature % 10;
- Digit[0] = a / 10;
- Digit[1] = a % 10;
- Digit[2] = b;
- Digit[3] = DIGIT_BLANK;
- }
- void showHumidity(void) {
- dotOff();
- Digit[0] = DIGIT_BLANK;
- Digit[1] = DIGIT_BLANK;
- Digit[2] = dhtData.Humidity / 10;
- Digit[3] = dhtData.Humidity % 10;}
- #endif // USE_DHT
- /**
- * @brief Обработка кнопок.
- * @param : None
- * @retval : None
- */
- static void btnProcess(void) {
- uint8_t i;
- for (i=0; i<BTN_NUM; i++) {
- if (Button[i].pin != 0) {
- // button pressed
- if (BUTTON_STATE(Button[i].pin) == 0) {
- Button[i].time ++;
- if (Button[i].time >= BTN_TIME_HOLDED) {
- Button[i].time -= BTN_TIME_REPEATED;
- if (Button[i].holded == Button[i].pressed) {
- // if pressed and holded - same function, then button pressed auto repeat
- ES_PlaceEvent(Button[i].pressed);
- }
- }
- } else {
- // button released
- if (Button[i].time >= (BTN_TIME_HOLDED - BTN_TIME_REPEATED)) {
- ES_PlaceEvent(Button[i].holded); // process long press
- } else if (Button[i].time >= BTN_TIME_PRESSED) {
- ES_PlaceEvent(Button[i].pressed); // process short press
- }
- Button[i].time = 0;
- RTOS_SetTask(btnProcess, BTN_TIME_PAUSE, BTN_SCAN_PERIOD);
- }
- } /* end (pin == 0) */
- } /* end FOR */
- }
- void showTime(void) {
- switch(RTC.Sec) {
- #ifdef USE_DHT
- case 0x20:
- case 0x50:
- showTemperature();
- break;
- case 0x22:
- case 0x52:
- showHumidity();
- break;
- #endif // USE_DHT
- case 0x27:
- case 0x28:
- case 0x29:
- case 0x57:
- case 0x58:
- case 0x59:
- dotOn();
- showMMSS();
- break;
- default:
- dotOn();
- RTOS_SetTask(dotOff, 500, 0);
- if (RTC.Hr > 0x09) {
- Digit[0] = RTC.Hr >> 4;
- } else {
- Digit[0] = DIGIT_BLANK;
- }
- Digit[1] = RTC.Hr & 0x0F;
- Digit[2] = RTC.Min >> 4;
- Digit[3] = RTC.Min & 0x0F;
- }
- }
- void showMMSS(void) {
- Digit[0] = RTC.Min >> 4;
- Digit[1] = RTC.Min & 0x0F;
- Digit[2] = RTC.Sec >> 4;
- Digit[3] = RTC.Sec & 0x0F;
- }
- void showWDay(void) {
- DISP_WDT = DISP_WDT_TIME;
- Digit[0] = DIGIT_BLANK;
- Digit[1] = DIGIT_BLANK;
- Digit[2] = RTC.WD & 0x0F;
- Digit[3] = DIGIT_BLANK;
- }
- void showMDay(void) {
- DISP_WDT = DISP_WDT_TIME;
- Digit[0] = RTC.Day >> 4;
- Digit[1] = RTC.Day & 0x0F;
- Digit[2] = DIGIT_BLANK;
- Digit[3] = DIGIT_BLANK;
- }
- void showMonth(void) {
- DISP_WDT = DISP_WDT_TIME;
- Digit[0] = DIGIT_BLANK;
- Digit[1] = DIGIT_BLANK;
- Digit[2] = RTC.Mon >> 4;
- Digit[3] = RTC.Mon & 0x0F;
- }
- void showYear(void) {
- DISP_WDT = DISP_WDT_TIME;
- Digit[0] = 0x02;
- Digit[1] = 0x00;
- Digit[2] = RTC.Year >> 4;
- Digit[3] = RTC.Year & 0x0F;
- }
- void incWDay(void) {
- if (RTC.WD < 7) {
- RTC.WD ++;
- } else {
- RTC.WD = 1;
- }
- Flag.saveCal = 1;
- }
- void decWDay(void) {
- if (RTC.WD > 1) {
- RTC.WD --;
- } else {
- RTC.WD = 7;
- }
- Flag.saveCal = 1;
- }
- void incMDay(void) {
- valIncrease(&RTC.Day, 31);
- Flag.saveCal = 1;
- }
- void decMDay(void) {
- valDecrease(&RTC.Day, 31);
- Flag.saveCal = 1;
- }
- void incMonth(void) {
- valIncrease(&RTC.Mon, 12);
- if (RTC.Mon == 0) {
- RTC.Mon = 1;
- }
- Flag.saveCal = 1;
- }
- void decMonth(void) {
- valDecrease(&RTC.Mon, 12);
- if (RTC.Mon == 0) {
- RTC.Mon = 0x12;
- }
- Flag.saveCal = 1;
- }
- void incYear(void) {
- valIncrease(&RTC.Year, 99);
- Flag.saveCal = 1;
- }
- void decYear(void) {
- valDecrease(&RTC.Year, 99);
- Flag.saveCal = 1;
- }
- #ifdef USE_BRIGHT_CONTROL
- void showBright(void) {
- DISP_WDT = DISP_WDT_TIME;
- Digit[0] = DIGIT_BLANK;
- Digit[1] = DIGIT_BLANK;
- Digit[2] = brightIdx;
- Digit[3] = DIGIT_BLANK;
- }
- void incBright(void) {
- if (brightIdx < BRIGHT_IDX_MAX) {
- brightIdx ++;
- OCR2 = pgm_read_byte(&brightConv[brightIdx]);
- Flag.saveEEP = 1;
- }
- }
- void decBright(void) {
- if (brightIdx > 0 ) {
- brightIdx --;
- OCR2 = pgm_read_byte(&brightConv[brightIdx]);
- Flag.saveEEP = 1;
- }
- }
- #endif // USE_BRIGHT_CONTROL
- static void blink(void) {
- static uint8_t s = 0;
- switch (s) {
- case 0:
- Flag.blinkC = 0;
- RTOS_SetTask(blink, 750, 0);
- s = 1;
- break;
- case 1:
- Flag.blinkC = 1;
- RTOS_SetTask(blink, 250, 0);
- s = 0;
- break;
- default:
- s = 0;
- }
- }
- void setTimeShow(void) {
- dotOn();
- RTOS_SetTask(dotOff, 500, 0);
- Digit[0] = setRTC.Hr >> 4;
- Digit[1] = setRTC.Hr & 0x0F;
- Digit[2] = setRTC.Min >> 4;
- Digit[3] = setRTC.Min & 0x0F;
- }
- void setTimeBegin(void) {
- RTC_ReadTime(&setRTC);
- RTOS_SetTask(btnProcess, 500, BTN_SCAN_PERIOD);
- }
- void setHHBegin(void) {
- Flag.blink0 = 1;
- Flag.blink1 = 1;
- Flag.blink2 = 0;
- Flag.blink3 = 0;
- RTOS_SetTask(blink, 0, 0);
- setTimeShow();
- }
- void setHHInc(void) {
- valIncrease(&setRTC.Hr, 23);
- }
- void setHHDec(void) {
- valDecrease(&setRTC.Hr, 23);
- }
- void setMMBegin(void) {
- Flag.blink0 = 0;
- Flag.blink1 = 0;
- Flag.blink2 = 1;
- Flag.blink3 = 1;
- RTOS_SetTask(blink, 0, 0);
- setTimeShow();
- }
- void setMMInc(void) {
- valIncrease(&setRTC.Min, 59);
- }
- void setMMDec(void) {
- valDecrease(&setRTC.Min, 59);
- }
- void setTimeEnd(void) {
- RTOS_SetTask(btnProcess, 500, BTN_SCAN_PERIOD);
- setRTC.Sec = 0;
- RTC_WriteTime(&setRTC);
- RTOS_DeleteTask(blink);
- Flag.blink0 = 0;
- Flag.blink1 = 0;
- Flag.blink2 = 0;
- Flag.blink3 = 0;
- Flag.blinkC = 0;
- RTC_ReadTime(&RTC);
- }
- /**
- * @brief Increase BCD value.
- * @param : val, max
- * @retval : None
- */
- static void valIncrease(uint8_t * val, uint8_t max) {
- uint8_t bin = 10 * (*val >> 4) + (*val & 0x0f);
- if (bin < max) {
- bin ++;
- } else {
- bin = 0;
- }
- *val = ((bin / 10 ) << 4) | (bin % 10);
- }
- /**
- * @brief Decrease BCD value.
- * @param : value, max
- * @retval : None
- */
- static void valDecrease(uint8_t * val, uint8_t max) {
- uint8_t bin = 10 * (*val >> 4) + (*val & 0x0f);
- if (bin > 0) {
- bin --;
- } else {
- bin = max;
- }
- *val = ((bin / 10 ) << 4) | (bin % 10);
- }
- #ifdef USE_UART
- void usart_putc (char send) {
- // Do nothing for a bit if there is already
- // data waiting in the hardware to be sent
- while ((UCSRA & (1 << UDRE)) == 0) {};
- UDR = send;
- }
- void usart_puts (const char *send) {
- // Cycle through each character individually
- while (*send) {
- usart_putc(*send++);
- }
- }
- #endif // USE_UART
- /**
- * П р е р ы в а н и я
- */
- /**
- * @brief RTC one seconds interrupt
- */
- ISR (INT1_vect) {
- Flag.RTC_Int = 1;
- }
- /**
- * @brief Refresh Nixie output
- * @note Digit[] must be in range 0x00 - 0x0F
- */
- #pragma GCC optimize ("O3")
- ISR(TIMER2_OVF_vect) {
- static uint8_t idx = 0;
- // reload timer
- TCNT2 = TIMER2_CNT;
- // read current register value and clean bits
- uint8_t pd = PORTD & ~ANOD_PINS;
- uint8_t pc = PORTC & ~DIGIT_PINS;
- #ifndef USE_BRIGHT_CONTROL
- // power off lamps
- PORTD = pd;
- PORTC = pc;
- #endif
- switch (idx) {
- case 0:
- // output lamp value
- PORTC = pc | Digit[0];
- // power on lamp
- if (Digit[0] != DIGIT_BLANK) {
- if (Flag.blink0 == 0 || Flag.blinkC == 0) {
- PORTD = pd | ANOD1;
- }
- }
- idx = 1;
- break;
- case 1:
- PORTC = pc | Digit[1];
- if (Digit[1] != DIGIT_BLANK) {
- if (Flag.blink1 == 0 || Flag.blinkC == 0) {
- PORTD = pd | ANOD2;
- }
- }
- idx = 2;
- break;
- case 2:
- PORTC = pc | Digit[2];
- if (Digit[2] != DIGIT_BLANK) {
- if (Flag.blink2 == 0 || Flag.blinkC == 0) {
- PORTD = pd | ANOD3;
- }
- }
- idx = 3;
- break;
- case 3:
- PORTC = pc | Digit[3];
- if (Digit[3] != DIGIT_BLANK) {
- if (Flag.blink3 == 0 || Flag.blinkC == 0) {
- PORTD = pd | ANOD4;
- }
- }
- idx = 0;
- break;
- default:
- idx = 0;
- break;
- }
- }
- #ifdef USE_BRIGHT_CONTROL
- /**
- * @brief Power Off Nixie output
- * @note For Brightnes dimming
- */
- #pragma GCC optimize ("O3")
- ISR(TIMER2_COMP_vect) {
- // power off lamps
- PORTD &= ~ANOD_PINS;
- PORTC &= ~DIGIT_PINS;
- }
- #endif // USE_BRIGHT_CONTROL
- /**
- * @brief заглушка для неиспользуемых прерываний
- */
- ISR(__vector_default,ISR_NAKED) {
- reti();
- }
|