Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * LedClock_Super.c
- *
- * Created: 24.11.2019 4:29:21
- * Author : redfern89
- */
- #define F_CPU 16000000UL
- #define SPEAKER_DDR DDRC
- #define SPEAKER_PORT PORTC
- #define SPEAKER PC0
- #define SPEAKER_ON { SPEAKER_PORT |= (1 << SPEAKER); }
- #define SPEAKER_OFF { SPEAKER_PORT &= ~(1 << SPEAKER); }
- #define AL_STOP_BTN PD5
- #define AL_SET_BTN PD6
- #define TIME_SET_BTN PD7
- #define PLUS_BTN PB0
- #define MINUS_BTN PB1
- #define MODE_BTN PB2
- #define AL_STOP_BTN_DDR DDRD
- #define AL_SET_BTN_DDR DDRD
- #define TIME_SET_BTN_DDR DDRD
- #define MINUS_BTN_DDR DDRB
- #define PLUS_BTN_DDR DDRB
- #define MODE_BTN_DDR DDRB
- #define AL_STOP_BTN_PIN PIND
- #define AL_SET_BTN_PIN PIND
- #define TIME_SET_BTN_PIN PIND
- #define MINUS_BTN_PIN PINB
- #define PLUS_BTN_PIN PINB
- #define MODE_BTN_PIN PINB
- #define RCLK PC3
- #define SCLK PC2
- #define DATA PD4
- #define RCLK_DDR DDRC
- #define SCLK_DDR DDRC
- #define DATA_DDR DDRD
- #define RCLK_PORT PORTC
- #define SCLK_PORT PORTC
- #define DATA_PORT PORTD
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #include <stdlib.h>
- #include "i2c.h"
- #include "i2c.cpp"
- #include "DS1307.h"
- #include "DS1307.c"
- #include "24cxx.h"
- #include "24cxx.c"
- #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
- #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
- #define button_click(button, button_pin, event_code) { static int interration_cnt = 0; if (!(button_pin & (1 << button))) { _delay_ms(15); if (!(button_pin & (1 << button))) { interration_cnt++; if (interration_cnt == 1) { event_code; } } else { interration_cnt = 0; }}}
- //#define button_click(button, button_pin, event_code) { static int e = 0; while (e == 0) { if ((button_pin & (1 << button)) == 0x00) { _delay_ms(50); if ((button_pin & (1 << button)) == 0x00) { e++; event_code; while((button_pin & (1 << button)) == 0x00); }}}}
- #define if_button_pressed(button, button_pin, event_code) { if (!(button_pin & (1 << button))) { event_code; } }
- #define if_long_button_click(button, button_pin, event_code) { static int int_cnt = 0; if (!(button_pin & (1 << button))) { _delay_ms(5); if (!(button_pin & (1 << button))) { int_cnt++; if (int_cnt >= 200) { event_code; int_cnt = 0; } } else { int_cnt = 0; }}}
- // Упарвление защелкой и сдвигом регистров
- #define _74hc595_RegisterLatch() { RCLK_PORT |= (1 << RCLK); asm("NOP"); RCLK_PORT &= ~(1 << RCLK); }
- #define _74hc595_RegisterShift() { SCLK_PORT |= (1 << SCLK); asm("NOP"); SCLK_PORT &= ~(1 << SCLK); }
- #define MAX_GROUPS 21
- #define T2_START { TCCR2B = (1 << CS20) | (1 << CS21) | (0 << CS22); }
- #define T2_STOP { TCCR2B = 0x00; }
- // Макросы для USART'а (использовал только при отладке и щас они нах ненужны)
- #define FOSC 16000000L
- #define BAUD 9600L
- #define MYUBRR FOSC / 16 / BAUD - 1
- #define DIVIDER_ON { display_data[1] = 0b10000000; }
- #define DIVIDER_OFF { display_data[1] = 0b00000000; }
- /* Протокол NEC */
- const int IRDA_MIN_CLK = 5; // Минимальное значение, при котором следует начинать захват
- volatile int NEC_REPEAT_FLAG = 0;
- volatile int NEC_START_FLAG = 0;
- volatile unsigned long int IRDA_SCLK = 0; // Тактовые синхроимпульсы (64 мкс)
- volatile unsigned long int IRDA_RECV_CNT = 0; // Кол-во принятых битов
- const static int IRDA_MAX_RESET = 1200;
- const static int IRDA_MAX_PACKET_LENGTH = 32;
- volatile int IRDA_READ_DONE = 0;
- volatile int IRDA_RECV_DONE = 0;
- volatile uint8_t IRDA_PACKET[32] = {};
- volatile int remote_setting_flag = 0; // Флаг настроек пульта
- volatile int COMMAND_NUM = 0;
- const uint8_t POWER_OFF = 0;
- const uint8_t MENU = 1;
- const uint8_t RETURN = 2;
- const uint8_t PLAY = 3;
- const uint8_t PLUS = 4;
- const uint8_t MINUS = 5;
- const uint8_t FWND = 6;
- const uint8_t RWND = 7;
- uint8_t buttons[8][32] = {{}};
- // Расшифровка групп
- /* Большие цифры */
- const unsigned char BIG_DIGIT1 = 3;
- const unsigned char BIG_DIGIT2 = 2;
- const unsigned char BIG_DIGIT3 = 0;
- const unsigned char BIG_DIGIT4 = 20;
- /* Индикатор дата/год */
- const unsigned char I1D1 = 7;
- const unsigned char I1D2 = 6;
- const unsigned char I1D3 = 5;
- const unsigned char I1D4 = 4;
- /* Индикатор температуры */
- const unsigned char I2D1 = 18;
- const unsigned char I2D2 = 17;
- const unsigned char I2D3 = 16;
- const unsigned char I2D4 = 19;
- /* Шкала */
- const unsigned char SCALE_GROUP1 = 13;
- const unsigned char SCALE_GROUP2 = 14;
- const unsigned char SCALE_GROUP3 = 10;
- const unsigned char SCALE_GROUP4 = 9;
- const unsigned char SCALE_GROUP5 = 8;
- const unsigned char SCALE_GROUP6 = 15;
- const unsigned char SCALE_GROUP7 = 11;
- const unsigned char SCALE_GROUP8 = 12;
- volatile unsigned long long int millis = 0; // Колличество миллисекунд с момента запуска
- // Таймер без delay
- #define setInterval(n, tmr, code) { if ((millis - tmr) >= n) { tmr = millis; code; }}
- // ( это ааааадовый костыль, который, я надеюсь потом уберу )
- // Переменные-таймеры/счетчики...так думаю, что нахуй они не нужны,
- // ибо более одной задержки одновременно не планирую в программе ...
- unsigned long long int tmr0 = 0;
- unsigned long long int tmr1 = 0;
- unsigned long long int tmr2 = 0;
- unsigned long long int tmr3 = 0;
- volatile unsigned long int FTIME = 0;
- volatile int sqw_flag = 0; // Флаг прохождения одной секунды
- // Структура DateTime (для удобства работы)
- typedef struct {
- int Sec;
- int Min;
- int Hour;
- int Month;
- int Day;
- int Year;
- int WeekDay;
- int AMPM;
- int H12_24;
- } TDateTime;
- TDateTime DateTime;
- void buttons_init( void ) {
- AL_STOP_BTN_DDR &= ~(1 << AL_STOP_BTN);
- AL_SET_BTN_DDR &= ~(1 << AL_SET_BTN);
- TIME_SET_BTN_DDR &= ~(1 << TIME_SET_BTN);
- MINUS_BTN_DDR &= ~(1 << PLUS_BTN);
- PLUS_BTN_DDR &= ~(1 << MINUS_BTN);
- MODE_BTN_DDR &= ~(1 << MODE_BTN);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- USART functions
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- void USORT_Init(unsigned char ubrr) {
- UBRR0H = (unsigned char)(ubrr>>8);
- UBRR0L = (unsigned char)ubrr;
- /*Enable receiver and transmitter */
- UCSR0B = (1<<RXEN0)|(1<<TXEN0);
- /* Set frame format: 8data, 2stop*/
- UCSR0C = (1<<USBS0)|(3<<UCSZ00);
- }
- void USORT_Transmit( unsigned char data ) {
- /* Wait for empty transmit buffer */
- while ( !( UCSR0A & (1<<UDRE0)) );
- /* Put data into buffer, sends the data */
- UDR0 = data;
- }
- // Коды цифр на индикаторах
- uint8_t digits[10] = {
- 0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000
- };
- // Группы с 1 по 2 регистр
- uint8_t groups1[8] = {
- 0b10000000,
- 0b01000000,
- 0b00100000,
- 0b00010000,
- 0b00001000,
- 0b00000100,
- 0b00000010,
- 0b00000001
- };
- // Группы для 3го регистра
- uint8_t groups2[5] = {
- 0b00010000,
- 0b00001000,
- 0b00000100,
- 0b00000010,
- 0b00000001
- };
- // Массив индикации
- volatile uint8_t display_data[21] = {};
- // Текущее положение разряда
- volatile unsigned int display_pos = 0;
- // Инициализация сдвиговых регистров
- void _74hc595_SPI_Init( void ) {
- RCLK_DDR |= _BV(RCLK);
- SCLK_DDR |= _BV(SCLK);
- DATA_DDR |= _BV(DATA);
- }
- // Отправка данных в регистр
- void _74hc595_SPI_send(char data, char LSBFIRST) {
- int i;
- unsigned char val;
- for (i = 0; i < 8; i++) {
- if (!LSBFIRST)
- val = !!(data & (1 << (7 - i)));
- else val = !!(data & (1 << i));
- if (val) DATA_PORT |= 1 << DATA;
- else DATA_PORT &= ~(1 << DATA);
- asm("NOP");
- _74hc595_RegisterShift();
- }
- }
- // Динамическая индикация
- ISR (TIMER0_OVF_vect) {
- TCNT0 = 0xfb;
- /* Отсылаем текущие данные в сдвиговые регистры */
- if (display_pos >= 0 && display_pos <= 7) {
- _74hc595_SPI_send(0x00);
- _74hc595_SPI_send(display_data[display_pos]);
- _74hc595_SPI_send(groups1[display_pos]);
- _74hc595_SPI_send(0x00);
- }
- if (display_pos >= 8 && display_pos <= 15) {
- _74hc595_SPI_send(0x00);
- _74hc595_SPI_send(display_data[display_pos]);
- _74hc595_SPI_send(0x00);
- _74hc595_SPI_send(groups1[display_pos -8]);
- }
- if (display_pos >= 16 && display_pos <= 21) {
- _74hc595_SPI_send(groups2[display_pos - 16]);
- _74hc595_SPI_send(display_data[display_pos]);
- _74hc595_SPI_send(0x00);
- _74hc595_SPI_send(0x00);
- }
- // Закрываем защелку
- _74hc595_RegisterLatch();
- // Переключаем разряды
- display_pos = (display_pos + 1) % MAX_GROUPS;
- }
- // Отображение больших цифр
- // Тут все значения идут с инверсией. ибо UDN2981A управляется лог. 1, как и ULN2803A
- void print_HM_Display(int Hours, int Minutes, int HoursVisible, int MinutesVisible) {
- if (!HoursVisible) {
- if (Hours == 0) {
- display_data[BIG_DIGIT1] = ~digits[0];
- display_data[BIG_DIGIT2] = ~digits[0];
- } else if (Hours >= 1 && Hours <= 9) {
- display_data[BIG_DIGIT1] = ~digits[0];
- display_data[BIG_DIGIT2] = ~digits[Hours];
- } else if (Hours >= 10 && Hours <= 99) {
- display_data[BIG_DIGIT1] = ~digits[(unsigned int)round((Hours % 100) / 10)];
- display_data[BIG_DIGIT2] = ~digits[(unsigned int)round(Hours % 10)];
- }
- } else {
- display_data[BIG_DIGIT1] = 0x00;
- display_data[BIG_DIGIT2] = 0x00;
- }
- if (!MinutesVisible) {
- if (Minutes == 0) {
- display_data[BIG_DIGIT3] = ~digits[0];
- display_data[BIG_DIGIT4] = ~digits[0];
- } else if (Minutes >= 1 && Minutes <= 9) {
- display_data[BIG_DIGIT3] = ~digits[0];
- display_data[BIG_DIGIT4] = ~digits[Minutes];
- } else if (Minutes >= 10 && Minutes <= 99) {
- display_data[BIG_DIGIT3] = ~digits[(unsigned int)round((Minutes % 100) / 10)];
- display_data[BIG_DIGIT4] = ~digits[(unsigned int)round(Minutes % 10)];
- }
- } else {
- display_data[BIG_DIGIT3] = 0x00;
- display_data[BIG_DIGIT4] = 0x00;
- }
- }
- // Отображение текущей даты и года
- // Если год равен нулю - отображается дата
- // Если год больше нуля - отображается год
- void print_DM_Display( int Day, int Month, int Year, int DayVisible, int MontVisible, int YearsVisible ) {
- if (Year == 0) {
- if (!DayVisible) {
- if (Month == 0) {
- display_data[I1D1] = digits[0] & ~(1 << 7);
- display_data[I1D2] = digits[0];
- } else if (Day >= 1 && Day <= 9) {
- display_data[I1D1] = digits[0] & ~(1 << 7);
- display_data[I1D2] = digits[Day];
- } else if (Day >= 10 && Day <= 99) {
- display_data[I1D1] = digits[(unsigned int)round(Day % 100) / 10] & ~(1 << 7);
- display_data[I1D2] = digits[(unsigned int)round(Day % 10)];
- }
- } else {
- display_data[I1D1] = 0xFF;
- display_data[I1D2] = 0xFF;
- }
- if (!MontVisible) {
- if (Month == 0) {
- display_data[I1D3] = digits[0];
- display_data[I1D4] = digits[0];
- } else if (Month >= 1 && Month <= 9) {
- display_data[I1D3] = digits[0];
- display_data[I1D4] = digits[Month];
- } else if (Month >= 10 && Month <= 99) {
- display_data[I1D3] = digits[(unsigned int)round(Month % 100) / 10];
- display_data[I1D4] = digits[(unsigned int)round(Month % 10)];
- }
- } else {
- display_data[I1D3] = 0xFF;
- display_data[I1D4] = 0xFF;
- }
- } else {
- if (!YearsVisible) {
- display_data[I1D1] = digits[2];
- display_data[I1D2] = digits[0];
- display_data[I1D3] = digits[(unsigned int)round((Year % 100) / 10)];
- display_data[I1D4] = digits[(unsigned int)round(Year % 10)];
- } else {
- display_data[I1D1] = 0xFF;
- display_data[I1D2] = 0xFF;
- display_data[I1D3] = 0xFF;
- display_data[I1D4] = 0xFF;
- }
- }
- }
- // Отображение температуры
- void print_TEMP_Display( int temp ) {
- if (temp == 0) {
- display_data[I2D1] = 0xff;
- display_data[I2D2] = digits[0];
- display_data[I2D3] = 0b10011100;
- display_data[I2D4] = 0xff;
- } else if (temp >= 1 && temp <= 9) {
- display_data[I2D1] = 0xff;
- display_data[I2D2] = digits[temp];
- display_data[I2D3] = 0b10011100;
- display_data[I2D4] = 0xff;
- } else if (temp >= 10 && temp <= 99) {
- display_data[I2D1] = digits[(unsigned int)round(temp % 100) / 10];
- display_data[I2D2] = digits[(unsigned int)round(temp % 10)];
- display_data[I2D3] = 0b10011100;
- display_data[I2D4] = 0xff;
- }
- if (temp < 0) {
- temp = abs(temp);
- if (temp >= 1 && temp <= 9) {
- display_data[I2D1] = 0xff;
- display_data[I2D2] = 0b10111111;
- display_data[I2D3] = digits[temp];
- display_data[I2D4] = 0b10011100;
- } else if (temp >= 10 && temp <= 99) {
- display_data[I2D1] = 0b10111111;
- display_data[I2D2] = digits[(unsigned int)round(temp % 100) / 10];
- display_data[I2D3] = digits[(unsigned int)round(temp % 10)];
- display_data[I2D4] = 0b10011100;
- }
- }
- }
- // Вход во внешнее прерывание. DS1307 (SQW)
- ISR ( INT0_vect ) {
- sqw_flag = 1;
- }
- void DS1307_ReadDateTime( void ) {
- unsigned char temp;
- // Читаем данные и преобразуем из BCD в двоичную систему
- DS1307Read(0x00, &temp); // Чтение регистра секунд
- DateTime.Sec = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- DS1307Read(0x01,&temp); // Чтение регистра минут
- DateTime.Min = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- DS1307Read(0x02,&temp); // Чтение регистра часов
- DateTime.Hour = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- DS1307Read(0x04, &temp); // Чтение регистра дней
- DateTime.Day = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- DS1307Read(0x05, &temp); // Десятки месяца
- DateTime.Month = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- DS1307Read(0x06, &temp); // Десятки года
- DateTime.Year = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
- }
- // Функция пропорционально переносит значение (value) из текущего диапазона
- // значений (fromLow .. fromHigh) в новый диапазон (toLow .. toHigh), заданный параметрами
- // честно спижжено мной с ARDUINO
- long map(long x, long in_min, long in_max, long out_min, long out_max) {
- return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
- }
- void print_remote_button(int button) {
- display_data[I1D1] = 0b10001100;
- display_data[I1D2] = 0xff;
- display_data[I1D3] = 0xff;
- display_data[I1D4] = digits[button];
- }
- void print_RDY_( void ) {
- display_data[BIG_DIGIT1] = 0b01010000;
- display_data[BIG_DIGIT2] = 0b01011110;
- display_data[BIG_DIGIT3] = 0b01101110;
- display_data[BIG_DIGIT4] = 0b00001000;
- }
- void print_DONE ( void ) {
- display_data[I2D1] = 0b10100001;
- display_data[I2D2] = digits[0];
- display_data[I2D3] = 0b11001000;
- display_data[I2D4] = 0b10000110;
- }
- void print_____( void ) {
- display_data[I2D1] = 0b11110111;
- display_data[I2D2] = 0b11110111;
- display_data[I2D3] = 0b11110111;
- display_data[I2D4] = 0b11110111;
- }
- void printIRReceived( void ) {
- uint8_t G = 0b10111111;
- uint8_t AD = 0b11110110;
- for (int i = 0; i <= 3; i++) {
- display_data[I2D1] = G;
- display_data[I2D2] = AD;
- display_data[I2D3] = G;
- display_data[I2D4] = AD;
- _delay_ms(70);
- display_data[I2D1] = AD;
- display_data[I2D2] = G;
- display_data[I2D3] = AD;
- display_data[I2D4] = G;
- _delay_ms(70);
- }
- }
- void print_IRDA( void ) {
- display_data[BIG_DIGIT1] = 0b00000110;
- display_data[BIG_DIGIT2] = 0b01010000;
- display_data[BIG_DIGIT3] = 0b01011110;
- display_data[BIG_DIGIT4] = 0b01110111;
- }
- void print_Save ( void ) {
- display_data[I2D1] = digits[5];
- display_data[I2D2] = 0b10001000;
- display_data[I2D3] = 0b11000001;
- display_data[I2D4] = 0b10000110;
- }
- void print_Err( void ) {
- display_data[I2D1] = 0b10000110;
- display_data[I2D2] = 0b10101111;
- display_data[I2D3] = 0b10101111;
- display_data[I2D4] = 0b11111111;
- }
- void clear_display1( void ) {
- display_data[I1D1] = 0xFF;
- display_data[I1D2] = 0xFF;
- display_data[I1D3] = 0xFF;
- display_data[I1D4] = 0xFF;
- }
- void clear_display2( void ) {
- display_data[I2D1] = 0xFF;
- display_data[I2D2] = 0xFF;
- display_data[I2D3] = 0xFF;
- display_data[I2D4] = 0xFF;
- }
- void clearScale( void ) {
- display_data[SCALE_GROUP1] = 0xFF;
- display_data[SCALE_GROUP2] = 0xFF;
- display_data[SCALE_GROUP3] = 0xFF;
- display_data[SCALE_GROUP4] = 0xFF;
- display_data[SCALE_GROUP5] = 0xFF;
- display_data[SCALE_GROUP6] = 0xFF;
- display_data[SCALE_GROUP7] = 0xFF;
- display_data[SCALE_GROUP8] = 0xFF;
- }
- // Процедура записи в микросхему из структуры TDateTime
- void DS1307_WriteDateTime() {
- unsigned char tmp;
- tmp = ((DateTime.Sec / 10) << 4) | (DateTime.Sec % 10);
- DS1307Write(0x00, tmp);
- tmp = ((DateTime.Min / 10) << 4) | (DateTime.Min % 10);
- DS1307Write(0x01, tmp);
- tmp = ((DateTime.Hour / 10) << 4) | (DateTime.Hour % 10);
- DS1307Write(0x02, tmp);
- tmp = ((DateTime.WeekDay / 10) << 4) | (DateTime.WeekDay % 10);
- DS1307Write(0x03, tmp);
- tmp = ((DateTime.Day / 10) << 4) | (DateTime.Day % 10);
- DS1307Write(0x04, tmp);
- tmp = ((DateTime.Month / 10) << 4) | (DateTime.Month % 10);
- DS1307Write(0x05, tmp);
- tmp = ((DateTime.Year / 10) << 4) | (DateTime.Year % 10);
- DS1307Write(0x06, tmp);
- }
- unsigned char ReverseBits(unsigned char number) {
- number = (number & 0x55) << 1 | (number & 0xAA) >> 1;
- number = (number & 0x33) << 2 | (number & 0xCC) >> 2;
- number = (number & 0x0F) << 4 | (number & 0xF0) >> 4;
- return number;
- }
- void initADC1 ( void ) {
- // 2.56v internal reference
- ADMUX |= (1 << REFS1) | (1 << REFS0);
- // ADC1
- ADMUX |= (0 << MUX3) | (0 << MUX1) | (1 << MUX0);
- // /= 8 ADC Frequencu
- ADCSRA |= (1 << ADEN);
- sbi(ADCSRA, ADPS2);
- cbi(ADCSRA, ADPS1);
- sbi(ADCSRA, ADPS0);
- }
- unsigned int read_adc( void ) {
- unsigned int v;
- ADCSRA |= (1 << ADSC);
- while ((ADCSRA & (1 << ADIF)) == 0);
- v = (ADCL | ADCH << 8);
- return v;
- }
- // Таймер подсчета промежутков между спадами на внешнем прерывании
- ISR ( TIMER2_OVF_vect ) {
- TCNT2 = 0xF0;
- if (++IRDA_SCLK >= IRDA_MAX_RESET) {
- T2_STOP;
- IRDA_SCLK = 0;
- NEC_START_FLAG = 0;
- NEC_REPEAT_FLAG = 0;
- if (IRDA_RECV_CNT < 32) IRDA_RECV_CNT = 0;
- }
- }
- // Таймер подсчета миллисекунд
- ISR (TIMER1_OVF_vect) {
- TCNT1 = 0xFF06;
- /*
- Знаю, по-идиотски, но умнее лень было придумывать
- Суть такая, что мы ждем, пока завершиться чтение
- пакета импульсов с ИК-датчика. Как только насобирали 32 значения
- - ждем 500мс. Затем все пришедшие вновь импульсы считаются новым пакетом
- */
- if (IRDA_RECV_DONE) {
- if (millis - FTIME >= 500) {
- if (IRDA_RECV_CNT == 32) {
- EIMSK |= (1 << INT1);
- IRDA_RECV_CNT = 0;
- IRDA_RECV_DONE = 0;
- } else {
- // Пока еще не решил, что тут делать
- }
- }
- }
- // Прибавляем по 1мс за такт
- millis++;
- if (millis == 9223372036854775807) millis = 0; // НХУЯ СЕ!!!!
- }
- // Вход в 1е внешние прерывание (ножка DATA с ИК-датчика)
- ISR ( INT1_vect ) {
- static int CURRENT_SCLK = 0;
- static int EEPROM_SCLK = 0;
- static int AVERAGE = 0;
- static int COINCIDENCE_CNT = 0;
- T2_START; // Как только что-то началось, запускаем таймер
- /*
- Тут стоит учитывать, что IRDA_SCLK - синхроимпульс, длящийся 64мкс.
- */
- // Если входящее значение не меньше ожиадаемого
- if (IRDA_SCLK > 5) {
- // Набираем пакет импульсов
- IRDA_PACKET[IRDA_RECV_CNT] = IRDA_SCLK;
- // Инкрементируем счетчик входящих значений
- IRDA_RECV_CNT++;
- IRDA_SCLK = 0;
- // Как только насобирали 32 значения - тормозим и запрещаем внешнее прерывание
- if (IRDA_RECV_CNT == 32) {
- EIMSK &= ~(1 << INT1);
- T2_STOP;
- FTIME = millis; // Говорим системе сколько миллисекунд прошло с завершения чтения
- IRDA_RECV_CNT = 33; // Вывыаливаем переменную за пределы чтения, что-бы не перезаписать 1е значение
- /* Чтение завершено */
- IRDA_READ_DONE = 1;
- IRDA_RECV_DONE = 1;
- // Если мы не добавляем новый пульт в систему
- if (!remote_setting_flag) {
- // Начинаем сравнения
- for (int i = 0; i <= 7; i++) { // в сисетме 8 кнопок пульта управления
- COINCIDENCE_CNT = 0; // Обнуляем счетчик совпадений
- for (int j = 0; j <= 31; j++) { // Каждые 8 кнопок - содежат в себе 32 значения синхроимпульсов
- // Берем два значения
- CURRENT_SCLK = IRDA_PACKET[j]; // Значение, которое пришло с датчика
- EEPROM_SCLK = buttons[i][j]; // Значение из внешней памяти
- // Тут получаем коэфицент усреднения
- if (CURRENT_SCLK >= EEPROM_SCLK) AVERAGE = CURRENT_SCLK - EEPROM_SCLK;
- else if (CURRENT_SCLK <= EEPROM_SCLK) AVERAGE = EEPROM_SCLK - CURRENT_SCLK;
- // Если коэфицент меньше... ну скажем 5, то
- if (AVERAGE <= 5) {
- COINCIDENCE_CNT++; // Прибавляем счетчик совпадений
- }
- if (COINCIDENCE_CNT == 31) {
- COMMAND_NUM = i; // Если совпало все 32 значения - то это текущая команда
- break;
- } else {
- COMMAND_NUM = 255; // Если нет совпадений, то вываливаемся за пределы массива
- }
- }
- if (COMMAND_NUM >= 0 && COMMAND_NUM <= 9) {
- break;
- }
- }
- }
- }
- }
- }
- // процедура сложения всех значений массива
- int array_sum(uint8_t* array, int size) {
- int sum = 0;
- for (int i = 0; i < size; i++) {
- sum = sum + array[i];
- }
- return sum;
- }
- // Процедура заполнения массива
- void fill_array(uint8_t* array, int size, uint8_t fChar) {
- for (int i = 0; i < size; i++) {
- array[i] = fChar;
- }
- }
- // Функция инициализации..
- // Просто читаем все значения кнопок из EEPROM
- void init_IRDAEeprom( void ) {
- uint8_t code_addr = 0x00;
- uint8_t read = 0x00;
- for (int i = 0; i <= 7; i++) {
- for (int j = 0; j <= 31; j++) {
- code_addr = (j + (i * 32));
- eep_read_byte(code_addr, &read);
- buttons[i][j] = read;
- }
- }
- }
- // Началась основная программа
- int main(void) {
- asm("CLI"); // пока что запрещаем все прерывания
- // Инициализация usart на скорости 9600 B/S
- USORT_Init(MYUBRR);
- // Внешнее прерывание
- EICRA |= (1 << ISC10) | (1 << ISC11);
- EICRA |= (1 << ISC01) | (0 << ISC00);
- EIMSK |= (1 << INT1) | (1 << INT0);
- // Инициализация таймера/счестчика 0 для динамической индикации
- TCCR0B |= (1 << CS00) | (1 << CS02) | (0 << CS01);
- TIMSK0 |= (1 << TOIE0);
- TCNT0 = 0xCC;
- // Инициализация таймера/счестчика 1 для подсчета миллисекунд
- TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
- TIMSK1 |= (1 << TOIE1);
- TCNT1 = 0xFF06;
- // Таймер для работы с NEC-протоколом IRDA
- TCCR2B = (1 << CS20) | (1 << CS21) | (0 << CS22);
- TIMSK2 |= (1 << TOIE2);
- TCNT2 = 0xF0;
- _74hc595_SPI_Init(); // Инициализация портов сдвиговых регистров
- initADC1(); // Инициализация АЦП №1
- i2c_init(); // Инициализация i2c
- DS1307Init(); // Инициализация DS1307
- buttons_init(); // Инициализация портов кнопок
- DS1307Write(0x07, 0b10010000); // Настраиваем выход SQW на частоту 1Hz
- init_IRDAEeprom(); // Читаем значения конопок пульта из EEPROM
- SPEAKER_DDR |= (1 << SPEAKER); // Порт динамика будильника - как вывход
- // Разрешаем прерывания
- asm("SEI");
- // Переменные для работы интерфейса
- int menu_level = 0; // позиция в главном меню
- int menu_flag = 0; // Говорит о том, что открыто меню в данный момент или нет
- int s_hour = 0, s_min = 0, s_day = 0, s_month = 0, s_year = 0; // Настраиваемые значения
- int enter_menu_flag = 0; // Флаг входа в меню. выполняется каждый раз при входе в меню для приравнивания значений
- int DMY_Mode = 0; // Режим отображения (для переключения) число.месяц -> год
- int blink_flag = 0; // Флаг мигания чего-либо на дисплее
- int pass_cnt = 4; // Счетчик колличества проходов по шкале
- int interval = 7; // Интервал перемещения по проходу
- int pass_end_flag = 0; // Флаг сброса прохода
- unsigned long long int scale = 0x7FFFFFFFFFFFFFF; // Представление шкалы (последние 5 бит не используются)
- int temp_flag = 0; // Флаг обновления температуры
- int s_button = 1;
- int enter_remote_settings_flag = 0;
- // Значения для усреднения и преобразвания
- const int ADC_SAMPLES_CNT = 20; // Выборок за раз
- const float REFERENCE = 1.1F; // Опорное напряжение
- const float ADC_MAX_VALUE = 1024.0F; // Максимальное значение АЦП
- const float TMP36_BIAS_VOLTAGE = 0.5F; // Напряжение смещения датчика
- int readIndex = 0, samplesTotal = 0; // Текущий индекс чтения АЦП и общее кол-во значений
- int adcValues[ADC_SAMPLES_CNT]; // Массив со значениями АЦП
- int tempC = 0; // Температура
- float average = 0.0F;
- uint16_t CODE_ADDR = 0x0000;
- // Забиваем текущий массив нулями
- for (int i = 0; i < ADC_SAMPLES_CNT; i++) {
- adcValues[i] = 0;
- }
- while (1) {
- // Берем текущие значения из микросхемы
- DS1307_ReadDateTime();
- // Если "началась секунда"
- if (sqw_flag && !menu_flag) {
- // Тут распихиваем данные из переменной в массив индикации. Все значения после изменений в коде для работы со
- // сдвиговыми регистрами 74hc595 стали лезть старшим битом наружу. Все пошло по пизде и пришлось развернуть каждую группу битов,
- // что-бы как-то все это компенсировать. я конечно могу и дальше копать в сторону чего там не так, но нахуй это надо и так все работает ))))
- display_data[SCALE_GROUP1] = ReverseBits((unsigned char)(scale >> 56));
- display_data[SCALE_GROUP2] = ReverseBits((unsigned char)(scale >> 48));
- display_data[SCALE_GROUP3] = ReverseBits((unsigned char)(scale >> 40));
- display_data[SCALE_GROUP4] = ReverseBits((unsigned char)(scale >> 32));
- display_data[SCALE_GROUP5] = ReverseBits((unsigned char)(scale >> 24));
- display_data[SCALE_GROUP6] = ReverseBits((unsigned char)(scale >> 16));
- display_data[SCALE_GROUP7] = ReverseBits((unsigned char)(scale >> 8));
- display_data[SCALE_GROUP8] = ReverseBits((unsigned char)(scale >> 0));
- // Переносим из одного множества в другое, для того, что-бы светодиод бежал медленнее
- // по мере заполнения шкалы
- interval = map(DateTime.Sec, 0, 59, 7, 30);
- /*
- !!! КАК Я С ЭТИМ ЗАЕБАЛСЯ !!!
- */
- // Начинаем анимацию
- setInterval(interval, tmr3, {
- pass_cnt++; // Прибавляем текущий проход
- // Если проходов больше, чем оставшееся кол-во секунд - обнуляем все счетчики
- // и говорим, что все проходы проёдены
- if (pass_cnt > 59 - (DateTime.Sec)) {
- pass_cnt = 0;
- sqw_flag = 0;
- pass_end_flag = 1;
- }
- // Бежим светодиодом по шкале
- scale &= ~(1ULL << (pass_cnt + 4));
- // Убираем ебучий шлейф за бегущим диодом
- for (int i = 0; i <= (pass_cnt - 1); i++) {
- scale |= (1ULL << (i + 4));
- }
- });
- }
- // Если шкалу прошли
- if (pass_end_flag && !menu_flag) {
- // то отображаем текущее значение
- for (int i = 59; i >= (59 - DateTime.Sec); i--) {
- scale &= ~(1ULL << (i +4));
- }
- pass_end_flag = 0;
- }
- if (!menu_flag) {
- if_long_button_click(TIME_SET_BTN, TIME_SET_BTN_PIN, {
- //setInterval(5000, tmr2, {
- menu_flag = 1;
- enter_menu_flag = 1;
- menu_level = 0;
- //});
- });
- }
- if (menu_flag) {
- clearScale();
- if (!remote_setting_flag) {
- button_click(MODE_BTN, MODE_BTN_PIN, {
- menu_level++;
- if (menu_level > 5) menu_level = 0;
- });
- }
- if_long_button_click(MODE_BTN, MODE_BTN_PIN, {
- menu_level = 0;
- menu_flag = 0;
- remote_setting_flag = 0;
- });
- if_long_button_click(TIME_SET_BTN, TIME_SET_BTN_PIN, {
- if (menu_level >= 0 && menu_level <= 4) {
- DateTime.Sec = 0;
- DateTime.Min = s_min;
- DateTime.Hour = s_hour;
- DateTime.Day = s_day;
- DateTime.Month = s_month;
- DateTime.Year = s_year;
- DS1307_WriteDateTime();
- }
- menu_flag = 0;
- menu_level = 0;
- });
- if (menu_level == 5) {
- if (!remote_setting_flag) {
- print_IRDA();
- DIVIDER_OFF;
- clear_display1();
- clear_display2();
- }
- if (!remote_setting_flag) {
- button_click(TIME_SET_BTN, TIME_SET_BTN_PIN, {
- remote_setting_flag = 1;
- enter_remote_settings_flag = 1;
- print_remote_button(s_button);
- print_____();
- });
- }
- }
- if (remote_setting_flag) {
- button_click(TIME_SET_BTN, TIME_SET_BTN_PIN, {
- if (array_sum((uint8_t*)IRDA_PACKET, 32) > 20) {
- clear_display2();
- for (int i = 0; i <= 31; i++) {
- CODE_ADDR = (i + ((s_button - 1) * 32));
- eep_write_byte(CODE_ADDR, IRDA_PACKET[i]);
- _delay_ms(10);
- }
- print_Save();
- fill_array((uint8_t*)IRDA_PACKET, 32, 0x00);
- } else {
- if (!enter_remote_settings_flag) {
- print_Err();
- _delay_ms(600);
- print_____();
- }
- }
- enter_remote_settings_flag = 0;
- });
- }
- button_click(PLUS_BTN, PLUS_BTN_PIN, {
- if (menu_level == 0) {
- s_hour++;
- if (s_hour > 23) s_hour = 0;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 1) {
- s_min++;
- if (s_min > 59) s_min = 0;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 2) {
- s_day++;
- if (s_day > 31) s_day = 0;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 3) {
- s_month++;
- if (s_month > 12) s_month = 0;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 4) {
- s_year++;
- if (s_year > 99) s_year = 0;
- print_DM_Display(0, 0, s_year, 0, 0, 0);
- }
- if (menu_level == 5) {
- s_button++;
- if (s_button > 8) s_button = 1;
- print_remote_button(s_button);
- print_____();
- }
- });
- button_click(MINUS_BTN, MINUS_BTN_PIN, {
- if (menu_level == 0) {
- s_hour--;
- if (s_hour < 0) s_hour = 23;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 1) {
- s_min--;
- if (s_min < 0) s_min = 59;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 2) {
- s_day--;
- if (s_day < 0) s_day = 31;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 3) {
- s_month--;
- if (s_month < 0) s_month = 12;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 4) {
- s_year--;
- if (s_year < 0) s_year = 99;
- print_DM_Display(0, 0, s_year, 0, 0, 0);
- }
- if (menu_level == 5) {
- s_button--;
- if (s_button < 1) s_button = 8;
- print_remote_button(s_button);
- print_____();
- }
- });
- }
- // Если пришла команда с пульта
- if (IRDA_READ_DONE) {
- IRDA_READ_DONE = 0; // уже нет
- if (remote_setting_flag) {
- printIRReceived();
- //_delay_ms(500);
- print_DONE();
- }
- // Если мы вошли в меню
- if (COMMAND_NUM == MENU) {
- menu_flag = 1; // Говорим, что мы в меню
- menu_level = 0; // Выставляем уровень в начало
- enter_menu_flag = 1; // Говорим, что мы ВОШЛИ в меню
- }
- if (COMMAND_NUM == FWND && menu_flag) {
- menu_level++;
- if (menu_level > 5) menu_level = 0;
- }
- if (COMMAND_NUM == RWND && menu_flag) {
- menu_level--;
- if (menu_level < 0) menu_level = 5;
- }
- if (COMMAND_NUM == RETURN && menu_flag) {
- menu_flag = 0;
- remote_setting_flag = 0;
- s_button = 0;
- }
- if (COMMAND_NUM == PLUS && menu_flag) {
- if (menu_level == 0) {
- s_hour++;
- if (s_hour > 23) s_hour = 0;
- print_HM_Display(s_hour, s_min, 0, 0);
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 1) {
- s_min++;
- if (s_min > 59) s_min = 0;
- print_HM_Display(s_hour, s_min, 0, 0);
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 2) {
- s_day++;
- if (s_day > 31) s_day = 1;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 3) {
- s_month++;
- if (s_month > 12) s_month = 1;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 4) {
- s_year++;
- if (s_year > 99) s_year = 0;
- print_DM_Display(0, 0, s_year, 0, 0, 0);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- }
- if (COMMAND_NUM == MINUS && menu_flag) {
- if (menu_level == 0) {
- s_hour--;
- if (s_hour < 0) s_hour = 23;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 1) {
- s_min--;
- if (s_min < 0) s_min = 59;
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 2) {
- s_day--;
- if (s_day < 1) s_day = 31;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 3) {
- s_month--;
- if (s_month < 1) s_month = 12;
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 4) {
- s_year--;
- if (s_year < 0) s_year = 99;
- print_DM_Display(0, 0, s_year, 0, 0, 0);
- }
- }
- if (COMMAND_NUM == PLAY && menu_flag) {
- if (menu_level >= 0 && menu_level <= 4) {
- DateTime.Sec = 0;
- DateTime.Min = s_min;
- DateTime.Hour = s_hour;
- DateTime.Day = s_day;
- DateTime.Month = s_month;
- DateTime.Year = s_year;
- DS1307_WriteDateTime();
- menu_flag = 0;
- menu_level = 0;
- }
- if (menu_level == 5) {
- print_Err();
- print_____();
- }
- }
- }
- if (menu_flag) {
- if (enter_menu_flag) {
- enter_menu_flag = 0;
- s_hour = DateTime.Hour;
- s_min = DateTime.Min;
- s_day = DateTime.Day;
- s_month = DateTime.Month;
- s_year = DateTime.Year;
- }
- setInterval(540, tmr1, {
- blink_flag ^= 1;
- if (menu_level == 0) {
- print_HM_Display(s_hour, s_min, blink_flag, 0);
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 1) {
- print_HM_Display(s_hour, s_min, 0, blink_flag);
- print_DM_Display(s_day, s_month, 0, 0, 0, 0);
- }
- if (menu_level == 2) {
- print_DM_Display(s_day, s_month, 0, blink_flag, 0, 0);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 3) {
- print_DM_Display(s_day, s_month, 0, 0, blink_flag, 0);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- if (menu_level == 4) {
- print_DM_Display(0, 0, s_year, 0, 0, blink_flag);
- print_HM_Display(s_hour, s_min, 0, 0);
- }
- });
- }
- if (!menu_flag) {
- DS1307_ReadDateTime();
- print_HM_Display(DateTime.Hour, DateTime.Min, 0, 0);
- if (DateTime.Sec % 2) DIVIDER_ON else DIVIDER_OFF;
- setInterval(2500, tmr0, {
- DMY_Mode ^= 1;
- temp_flag = 1;
- if (DMY_Mode)
- print_DM_Display(DateTime.Day, DateTime.Month, 0, 0, 0, 0);
- else
- print_DM_Display(0, 0, DateTime.Year, 0, 0, 0);
- });
- if (temp_flag) {
- temp_flag = 0;
- // Поиск среднего арифметического значения АЦП
- while (readIndex < ADC_SAMPLES_CNT) {
- samplesTotal = samplesTotal - adcValues[readIndex];
- adcValues[readIndex] = read_adc();
- samplesTotal = samplesTotal + adcValues[readIndex];
- readIndex++;
- }
- if (readIndex >= ADC_SAMPLES_CNT) readIndex = 0;
- average = samplesTotal / ADC_SAMPLES_CNT;
- // Преобразование усредненного-арифметического значения АЦП в температуру
- tempC = floor((((average * REFERENCE) / ADC_MAX_VALUE) - TMP36_BIAS_VOLTAGE) * 100.0F);
- print_TEMP_Display(tempC);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment