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 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.c"
- #include "DS1307.h"
- #include "DS1307.c"
- #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
- #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
- // Упарвление защелкой и сдвигом регистров
- #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 { TCCR2 = (1 << CS20) | (1 << CS21) | (0 << CS22); }
- #define T2_STOP { TCCR2 = 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 NEC_MIN_CLK = 5; // Минимальное значение, при котором следует начинать захват
- volatile int NEC_REPEAT_FLAG = 0;
- volatile int NEC_START_FLAG = 0;
- volatile int NEC_IR_DONE = 0;
- volatile unsigned long int NEC_SCLK = 0; // Тактовые синхроимпульсы (64 мкс)
- volatile unsigned long int NEC_RECV_CNT = 0; // Кол-во принятых битов
- const static int NEC_MIN_HEADER_MESSAGE_CLK = 108; // Преамбула+пауза (минимальное время)
- const static int NEC_MAX_HEADER_MESSAGE_CLK = 130; // Преамбула+пауза (максимальное время)
- const static int NEC_MIN_REPEAT = 75;
- const static int NEC_MAX_REPEAT = 170;
- const int NEC_MIN_ONE_BIT_CLK = 48;
- const int NEC_MAX_ONE_BIT_CLK = 58;
- const int NEC_MIN_NUL_BIT_CLK = 21;
- const int NEC_MAX_NUL_BIT_CLK = 30;
- const static int NEC_MAX_RESET_OVF = 1200;
- const static int NEC_PACKET_LENGTH = 32;
- volatile unsigned char addr1 = 0x00; // Адрес
- volatile unsigned char addr2 = 0x00; // Инверсия адреса
- volatile unsigned char cmd1 = 0x00; // Команда
- volatile unsigned char cmd2 = 0x00; // Инверсия команды
- volatile uint16_t command = 0x0000; // Команда пульта
- int mode = 0;
- // Смещения для создания битовой маски сообщенй (адрес1, адрес2, команда1, команда2)
- const int offset1_addr1 = 0;
- const int offset2_addr1 = 9;
- const int offset1_addr2 = 9;
- const int offset2_addr2 = 17;
- const int offset1_cmd1 = 17;
- const int offset2_cmd1 = 25;
- const int offset1_cmd2 = 25;
- const int offset2_cmd2 = 33;
- // Коды с пульта
- const uint16_t POWER_OFF = 0xFF45;
- const uint16_t MENU = 0xFF47;
- const uint16_t TEST = 0xFF44;
- const uint16_t PLUS = 0xFF40;
- const uint16_t RETURN = 0xFF43;
- const uint16_t RWND = 0xFF07;
- const uint16_t PLAY = 0xFF15;
- const uint16_t FWND = 0xFF09;
- const uint16_t MINUS = 0xFF19;
- const uint16_t CLEAR = 0xFF0D;
- const uint16_t D0 = 0xFF16;
- const uint16_t D1 = 0xFF0C;
- const uint16_t D2 = 0xFF18;
- const uint16_t D3 = 0xFF5E;
- const uint16_t D4 = 0xFF08;
- const uint16_t D5 = 0xFF1C;
- const uint16_t D6 = 0xFF5A;
- const uint16_t D7 = 0xFF42;
- const uint16_t D8 = 0xFF52;
- const uint16_t D9 = 0xFF4A;
- // Расшифровка групп
- /* Большие цифры */
- 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 = 5;
- const unsigned char I1D2 = 4;
- const unsigned char I1D3 = 7;
- const unsigned char I1D4 = 6;
- /* Индикатор температуры */
- 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 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;
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- USART functions
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- void USORT_Init(unsigned char ubrr) {
- UBRRH = (unsigned char)(ubrr >> 8);
- UBRRL = (unsigned char)ubrr;
- UCSRB = (1 << RXEN) | (1 << TXEN);
- UCSRC = (1 << USBS) | (3 << UCSZ0) | (1 << URSEL);
- }
- void USORT_Transmit( unsigned char data ) {
- while ( !( UCSRA & (1 << UDRE)) );
- UDR = 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) {
- int i;
- unsigned char val;
- for (i = 0; i < 8; i++) {
- val = !!(data & (1 << (7 - i)));
- if (val) DATA_PORT |= 1 << DATA;
- else DATA_PORT &= ~(1 << DATA);
- asm("NOP");
- _74hc595_RegisterShift();
- }
- }
- // Таймер подсчета промежутков между спадами на внешнем прерывании
- ISR ( TIMER2_OVF_vect ) {
- TCNT2 = 0xF0;
- if (++NEC_SCLK >= NEC_MAX_RESET_OVF) {
- T2_STOP;
- NEC_SCLK = 0;
- NEC_START_FLAG = 0;
- NEC_REPEAT_FLAG = 0;
- command = 0x0000;
- }
- // Это не обязательно, но для перестраховки оставлю тут
- // Если в течении 1200 тиков пришло менее 32 бит, обнуляем счетчики и переходим в режим ожидания
- if (NEC_SCLK >= NEC_MAX_RESET_OVF && NEC_RECV_CNT < NEC_PACKET_LENGTH) {
- T2_STOP;
- NEC_SCLK = 0;
- NEC_RECV_CNT = 0;
- command = 0x0000;
- }
- }
- // Динамическая индикация
- 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;
- }
- // Отображение больших цифр
- 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 (Day == 0) {
- display_data[I1D1] = digits[0];
- display_data[I1D2] = digits[0];
- } else if (Day >= 1 && Day <= 9) {
- display_data[I1D1] = digits[0];
- display_data[I1D2] = digits[Day];
- } else if (Day >= 10 && Day <= 99) {
- display_data[I1D1] = digits[(unsigned int)round(Day % 100) / 10];
- 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] & ~(1 << 7);
- display_data[I1D4] = digits[0];
- } else if (Month >= 1 && Month <= 9) {
- display_data[I1D3] = digits[0] & ~(1 << 7);
- display_data[I1D4] = digits[Month];
- } else if (Month >= 10 && Month <= 99) {
- display_data[I1D3] = digits[(unsigned int)round(Month % 100) / 10] & ~(1 << 7);
- 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;
- }
- }
- }
- // Таймер подсчета миллисекунд
- ISR (TIMER1_OVF_vect) {
- TCNT1 = 0xFF06;
- millis++;
- if (millis > 9223372036854775807) millis = 0; // НХУЯ СЕ!!!!
- }
- // Вход во внешнее прерывание. DS1307 (SQW)
- ISR ( INT0_vect ) {
- sqw_flag = 1;
- }
- // Вход во внешнее прерывание. IRDA/NEC
- ISR ( INT1_vect ) {
- T2_START;
- if (NEC_SCLK > NEC_MIN_CLK) {
- //USORT_Transmit(NEC_SCLK);
- // Тут определяем стартовое сообщение (преамбулу)
- if (NEC_SCLK >= NEC_MIN_HEADER_MESSAGE_CLK && NEC_SCLK < NEC_MAX_HEADER_MESSAGE_CLK) {
- NEC_START_FLAG = 1;
- NEC_REPEAT_FLAG = 0;
- NEC_RECV_CNT = 0;
- }
- if (NEC_SCLK >= NEC_MIN_REPEAT && NEC_SCLK < NEC_MAX_REPEAT && NEC_START_FLAG) {
- NEC_REPEAT_FLAG = 1;
- }
- /* Знаю, по идиотски, Но умнее лень было придумывать */
- // Тут определяем биты нулевого значения
- if ((NEC_SCLK >= NEC_MIN_NUL_BIT_CLK && NEC_SCLK < NEC_MAX_NUL_BIT_CLK) && NEC_START_FLAG) {
- NEC_RECV_CNT++; // Инкрементируем колличество принятых нулей
- // ну а тут мутнаые процедуры записи значений в переменные
- if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) { // Если мы в диапозоне 1-8, ...
- addr1 &= ~(1 << (NEC_RECV_CNT - offset1_addr1)); // добавляем в addr1 нули в нужные места
- }
- // Остальные диапозоны тоже самое
- if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
- addr2 &= ~(1 << (NEC_RECV_CNT - offset1_addr2));
- }
- if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
- cmd1 &= ~(1 << (NEC_RECV_CNT - offset1_cmd1));
- }
- if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
- cmd2 &= ~(1 << (NEC_RECV_CNT - offset1_cmd2));
- }
- // IRActiveLed(0);
- }
- // Тут определяем биты положительного значения (такая-же хуйня как и с нулями, только интервалы у NEC_SCLK больше)
- if ((NEC_SCLK >= NEC_MIN_ONE_BIT_CLK && NEC_SCLK < NEC_MAX_ONE_BIT_CLK) && NEC_START_FLAG) {
- NEC_RECV_CNT++; // Инкрементируем колличество принятых едениц
- if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
- addr1 |= (1 << (NEC_RECV_CNT - offset1_addr1));
- }
- if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
- addr2 |= (1 << (NEC_RECV_CNT - offset1_addr2));
- }
- if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
- cmd1 |= (1 << (NEC_RECV_CNT - offset1_cmd1));
- }
- if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
- cmd2 |= (1 << (NEC_RECV_CNT - offset1_cmd2));
- }
- // IRActiveLed(1);
- }
- NEC_SCLK = 0;
- // Колличество нулей и едениц в конечном счете должно быть 32, на этом и остановимся
- if (NEC_RECV_CNT == NEC_PACKET_LENGTH) {
- // Выставляем в стартовое положение все счетчики и останавлиеваем подсчет
- NEC_RECV_CNT = 0;
- NEC_START_FLAG = 0;
- T2_STOP;
- // Проверка сообщения на целостность
- // В версии протокола 2.0 адрес имеет расширеное пространство и не имеет инверсии
- // Значит проверяем либо сложив обе инверсии (адреса и команды), либо только инверсии команды
- if ((((addr1 + addr2 == 0xFF) && (cmd1 + cmd2) == 0xFF)) || (cmd1 + cmd2 == 0xFF)) {
- NEC_IR_DONE = 1; // Сообщаем системе, что чтение завершено
- // Команду склеиваем с адресом (16 бит)
- command = ((addr1 + addr2) << 8) | cmd1;
- }
- }
- }
- }
- 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;
- }
- // Процедура записи в микросхему из структуры 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 & _BV(ADIF)) == 0x00);
- v = (ADCL | ADCH << 8);
- return v;
- }
- int main(void) {
- asm("CLI");
- //USORT_Init(MYUBRR);
- // Внешнее прерывание
- MCUCR |= (1 << ISC10) | (1 << ISC11);
- MCUCR |= (1 << ISC01) | (0 << ISC00);
- GICR |= (1 << INT1) | (1 << INT0);
- GIFR |= (1 << INTF1) | (1 << INTF0);
- // Инициализация таймера/счестчика 0 для динамической индикации
- TCCR0 |= (1 << CS00) | (1 << CS02) | (0 << CS01);
- TIMSK |= (1 << TOIE0);
- TCNT0 = 0xCC;
- // Инициализация таймера/счестчика 1 для подсчета миллисекунд
- TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
- TIMSK |= (1 << TOIE1);
- TCNT1 = 0xFF06;
- // Таймер для работы с NEC-протоколом IRDA
- TCCR2 = (1 << CS20) | (1 << CS21) | (0 << CS22);
- TIMSK |= (1 << TOIE2);
- TCNT2 = 0xF0;
- asm("SEI");
- _74hc595_SPI_Init();
- initADC1();
- I2CInit();
- DS1307Init();
- DS1307Write(0x07, 0b10010000); // Настраиваем выход SQW на частоту 1Hz
- // Переменные для работы интерфейса
- 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; // Флаг обновления температуры
- // Значения для усреднения и преобразвания
- const int ADC_SAMPLES_CNT = 10; // Выборок за раз
- const float REFERENCE = 2.56F; // Опорное напряжение
- const float ADC_MAX_VALUE = 1024.0F; // Максимальное значение АЦП
- const float BIAS_VOLTAGE = 0.5F; // Напряжение смещения датчика
- int readIndex = 0, samplesTotal = 0; // Текущий индекс чтения АЦП и общее кол-во значений
- int adcValues[ADC_SAMPLES_CNT]; // Массив со значениями АЦП
- int tempC = 0; // Температура
- // Забиваем текущий массив нулями
- for (int i = 0; i < ADC_SAMPLES_CNT; i++) {
- adcValues[i] = 0;
- }
- while (1) {
- // Тут распихиваем данные из переменной в массив индикации. Все значения после изменений в коде для работы со
- // сдвиговыми регистрами 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));
- // Берем текущие значения из микросхемы
- DS1307_ReadDateTime();
- // Если "началась секунда"
- if (sqw_flag && !menu_flag) {
- // Переносим из одного множества в другое, для того, что-бы светодиод бежал медленнее
- // по мере заполнения шкалы
- 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 (NEC_IR_DONE) {
- NEC_IR_DONE = 0; // уже нет
- // Если мы вошли в меню
- if (command == MENU) {
- menu_flag = 1; // Говорим, что мы в меню
- menu_level = 0; // Выставляем уровень в начало
- enter_menu_flag = 1; // Говорим, что мы ВОШЛИ в меню
- }
- if (command == FWND && menu_flag) {
- menu_level++;
- if (menu_level > 4) menu_level = 0;
- }
- if (command == RWND && menu_flag) {
- menu_level--;
- if (menu_level < 0) menu_level = 4;
- }
- if (command == RETURN && menu_flag) {
- menu_flag = 0;
- }
- if (command == 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);
- }
- 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 = 1;
- print_DM_Display(s_month, s_day, 0, 0, 0, 0);
- }
- if (menu_level == 3) {
- s_month++;
- if (s_month > 12) s_month = 1;
- print_DM_Display(s_month, s_day, 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 (command == 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_month, s_day, 0, 0, 0, 0);
- }
- if (menu_level == 3) {
- s_month--;
- if (s_month < 1) s_month = 12;
- print_DM_Display(s_month, s_day, 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 == PLAY && menu_flag) {
- 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_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_month, s_day, 0, 0, 0, 0);
- }
- if (menu_level == 1)
- print_HM_Display(s_hour, s_min, 0, blink_flag);
- if (menu_level == 2)
- print_DM_Display(s_month, s_day, 0, 0, blink_flag, 0);
- if (menu_level == 3)
- print_DM_Display(s_month, s_day, 0, blink_flag, 0, 0);
- if (menu_level == 4)
- print_DM_Display(0, 0, s_year, 0, 0, blink_flag);
- });
- }
- 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.Month, DateTime.Day, 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;
- // Преобразование усредненного-арифметического значения АЦП в температуру
- tempC = floor(((((samplesTotal / ADC_SAMPLES_CNT) * REFERENCE) / ADC_MAX_VALUE) - BIAS_VOLTAGE) * 100.0F);
- print_TEMP_Display(tempC);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment