Redfern_89

sss.c

Nov 28th, 2019
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.94 KB | None | 0 0
  1. /*
  2. * LedClock_Super.c
  3. *
  4. * Created: 24.11.2019 4:29:21
  5. * Author : redfern89
  6. */
  7.  
  8. #define F_CPU 16000000UL
  9.  
  10. #define RCLK PC3
  11. #define SCLK PC2
  12. #define DATA PD4
  13.  
  14. #define RCLK_DDR DDRC
  15. #define SCLK_DDR DDRC
  16. #define DATA_DDR DDRD
  17.  
  18. #define RCLK_PORT PORTC
  19. #define SCLK_PORT PORTC
  20. #define DATA_PORT PORTD
  21.  
  22. #include <avr/io.h>
  23. #include <avr/interrupt.h>
  24. #include <util/delay.h>
  25. #include <stdlib.h>
  26. #include "I2C.h"
  27. #include "I2C.c"
  28. #include "DS1307.h"
  29. #include "DS1307.c"
  30.  
  31. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  32. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  33.  
  34. // Упарвление защелкой и сдвигом регистров
  35. #define _74hc595_RegisterLatch() { RCLK_PORT |= (1 << RCLK); asm("NOP"); RCLK_PORT &= ~(1 << RCLK); }
  36. #define _74hc595_RegisterShift() { SCLK_PORT |= (1 << SCLK); asm("NOP"); SCLK_PORT &= ~(1 << SCLK); }
  37.  
  38. #define MAX_GROUPS 21
  39.  
  40. #define T2_START { TCCR2 = (1 << CS20) | (1 << CS21) | (0 << CS22); }
  41. #define T2_STOP { TCCR2 = 0x00; }
  42.  
  43.  
  44. // Макросы для USART'а (использовал только при отладке и щас они нах ненужны)
  45. #define FOSC 16000000L
  46. #define BAUD 9600L
  47. #define MYUBRR FOSC / 16 / BAUD - 1
  48.  
  49. #define DIVIDER_ON { display_data[1] = 0b10000000; }
  50. #define DIVIDER_OFF { display_data[1] = 0b00000000; }
  51.  
  52. /* Протокол NEC */
  53. const int NEC_MIN_CLK = 5; // Минимальное значение, при котором следует начинать захват
  54. volatile int NEC_REPEAT_FLAG = 0;
  55. volatile int NEC_START_FLAG = 0;
  56. volatile int NEC_IR_DONE = 0;
  57. volatile unsigned long int NEC_SCLK = 0; // Тактовые синхроимпульсы (64 мкс)
  58. volatile unsigned long int NEC_RECV_CNT = 0; // Кол-во принятых битов
  59. const static int NEC_MIN_HEADER_MESSAGE_CLK = 108; // Преамбула+пауза (минимальное время)
  60. const static int NEC_MAX_HEADER_MESSAGE_CLK = 130; // Преамбула+пауза (максимальное время)
  61. const static int NEC_MIN_REPEAT = 75;
  62. const static int NEC_MAX_REPEAT = 170;
  63. const int NEC_MIN_ONE_BIT_CLK = 48;
  64. const int NEC_MAX_ONE_BIT_CLK = 58;
  65. const int NEC_MIN_NUL_BIT_CLK = 21;
  66. const int NEC_MAX_NUL_BIT_CLK = 30;
  67. const static int NEC_MAX_RESET_OVF = 1200;
  68. const static int NEC_PACKET_LENGTH = 32;
  69. volatile unsigned char addr1 = 0x00; // Адрес
  70. volatile unsigned char addr2 = 0x00; // Инверсия адреса
  71. volatile unsigned char cmd1 = 0x00; // Команда
  72. volatile unsigned char cmd2 = 0x00; // Инверсия команды
  73. volatile uint16_t command = 0x0000; // Команда пульта
  74. int mode = 0;
  75.  
  76. // Смещения для создания битовой маски сообщенй (адрес1, адрес2, команда1, команда2)
  77. const int offset1_addr1 = 0;
  78. const int offset2_addr1 = 9;
  79. const int offset1_addr2 = 9;
  80. const int offset2_addr2 = 17;
  81. const int offset1_cmd1 = 17;
  82. const int offset2_cmd1 = 25;
  83. const int offset1_cmd2 = 25;
  84. const int offset2_cmd2 = 33;
  85.  
  86. // Коды с пульта
  87. const uint16_t POWER_OFF = 0xFF45;
  88. const uint16_t MENU = 0xFF47;
  89. const uint16_t TEST = 0xFF44;
  90. const uint16_t PLUS = 0xFF40;
  91. const uint16_t RETURN = 0xFF43;
  92. const uint16_t RWND = 0xFF07;
  93. const uint16_t PLAY = 0xFF15;
  94. const uint16_t FWND = 0xFF09;
  95. const uint16_t MINUS = 0xFF19;
  96. const uint16_t CLEAR = 0xFF0D;
  97. const uint16_t D0 = 0xFF16;
  98. const uint16_t D1 = 0xFF0C;
  99. const uint16_t D2 = 0xFF18;
  100. const uint16_t D3 = 0xFF5E;
  101. const uint16_t D4 = 0xFF08;
  102. const uint16_t D5 = 0xFF1C;
  103. const uint16_t D6 = 0xFF5A;
  104. const uint16_t D7 = 0xFF42;
  105. const uint16_t D8 = 0xFF52;
  106. const uint16_t D9 = 0xFF4A;
  107.  
  108. // Расшифровка групп
  109.  
  110. /* Большие цифры */
  111. const unsigned char BIG_DIGIT1 = 3;
  112. const unsigned char BIG_DIGIT2 = 2;
  113. const unsigned char BIG_DIGIT3 = 0;
  114. const unsigned char BIG_DIGIT4 = 20;
  115. /* Индикатор дата/год */
  116. const unsigned char I1D1 = 5;
  117. const unsigned char I1D2 = 4;
  118. const unsigned char I1D3 = 7;
  119. const unsigned char I1D4 = 6;
  120. /* Индикатор температуры */
  121. const unsigned char I2D1 = 18;
  122. const unsigned char I2D2 = 17;
  123. const unsigned char I2D3 = 16;
  124. const unsigned char I2D4 = 19;
  125. /* Шкала */
  126. const unsigned char SCALE_GROUP1 = 13;
  127. const unsigned char SCALE_GROUP2 = 14;
  128. const unsigned char SCALE_GROUP3 = 10;
  129. const unsigned char SCALE_GROUP4 = 9;
  130. const unsigned char SCALE_GROUP5 = 8;
  131. const unsigned char SCALE_GROUP6 = 15;
  132. const unsigned char SCALE_GROUP7 = 11;
  133. const unsigned char SCALE_GROUP8 = 12;
  134.  
  135. volatile unsigned long long int millis = 0; // Колличество миллисекунд с момента запуска
  136.  
  137. // Таймер без delay
  138. #define setInterval(n, tmr, code) { if ((millis - tmr) >= n) { tmr = millis; code; }}
  139.  
  140. // ( это ааааадовый костыль, который, я надеюсь потом уберу )
  141. // Переменные-таймеры/счетчики...так думаю, что нахуй они не нужны,
  142. // ибо более одной задержки одновременно не планирую в программе ...
  143. unsigned long long int tmr0 = 0;
  144. unsigned long long int tmr1 = 0;
  145. unsigned long long int tmr2 = 0;
  146. unsigned long long int tmr3 = 0;
  147.  
  148. volatile int sqw_flag = 0; // Флаг прохождения одной секунды
  149. // Структура DateTime (для удобства работы)
  150. typedef struct {
  151. int Sec;
  152. int Min;
  153. int Hour;
  154. int Month;
  155. int Day;
  156. int Year;
  157. int WeekDay;
  158. int AMPM;
  159. int H12_24;
  160. } TDateTime;
  161. TDateTime DateTime;
  162.  
  163. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  164. USART functions
  165. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  166. void USORT_Init(unsigned char ubrr) {
  167. UBRRH = (unsigned char)(ubrr >> 8);
  168. UBRRL = (unsigned char)ubrr;
  169. UCSRB = (1 << RXEN) | (1 << TXEN);
  170. UCSRC = (1 << USBS) | (3 << UCSZ0) | (1 << URSEL);
  171. }
  172.  
  173. void USORT_Transmit( unsigned char data ) {
  174. while ( !( UCSRA & (1 << UDRE)) );
  175. UDR = data;
  176. }
  177.  
  178. // Коды цифр на индикаторах
  179. uint8_t digits[10] = {
  180. 0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000
  181. };
  182.  
  183. // Группы с 1 по 2 регистр
  184. uint8_t groups1[8] = {
  185. 0b10000000,
  186. 0b01000000,
  187. 0b00100000,
  188. 0b00010000,
  189. 0b00001000,
  190. 0b00000100,
  191. 0b00000010,
  192. 0b00000001
  193. };
  194.  
  195. // Группы для 3го регистра
  196. uint8_t groups2[5] = {
  197. 0b00010000,
  198. 0b00001000,
  199. 0b00000100,
  200. 0b00000010,
  201. 0b00000001
  202. };
  203. // Массив индикации
  204. volatile uint8_t display_data[21] = {};
  205. // Текущее положение разряда
  206. volatile unsigned int display_pos = 0;
  207.  
  208. // Инициализация сдвиговых регистров
  209. void _74hc595_SPI_Init( void ) {
  210. RCLK_DDR |= _BV(RCLK);
  211. SCLK_DDR |= _BV(SCLK);
  212. DATA_DDR |= _BV(DATA);
  213. }
  214.  
  215. // Отправка данных в регистр
  216. void _74hc595_SPI_send(char data) {
  217. int i;
  218. unsigned char val;
  219.  
  220. for (i = 0; i < 8; i++) {
  221. val = !!(data & (1 << (7 - i)));
  222.  
  223. if (val) DATA_PORT |= 1 << DATA;
  224. else DATA_PORT &= ~(1 << DATA);
  225.  
  226. asm("NOP");
  227.  
  228. _74hc595_RegisterShift();
  229. }
  230. }
  231.  
  232. // Таймер подсчета промежутков между спадами на внешнем прерывании
  233. ISR ( TIMER2_OVF_vect ) {
  234. TCNT2 = 0xF0;
  235.  
  236. if (++NEC_SCLK >= NEC_MAX_RESET_OVF) {
  237. T2_STOP;
  238. NEC_SCLK = 0;
  239. NEC_START_FLAG = 0;
  240. NEC_REPEAT_FLAG = 0;
  241. command = 0x0000;
  242. }
  243.  
  244. // Это не обязательно, но для перестраховки оставлю тут
  245. // Если в течении 1200 тиков пришло менее 32 бит, обнуляем счетчики и переходим в режим ожидания
  246. if (NEC_SCLK >= NEC_MAX_RESET_OVF && NEC_RECV_CNT < NEC_PACKET_LENGTH) {
  247. T2_STOP;
  248. NEC_SCLK = 0;
  249. NEC_RECV_CNT = 0;
  250. command = 0x0000;
  251. }
  252. }
  253.  
  254. // Динамическая индикация
  255. ISR (TIMER0_OVF_vect) {
  256. TCNT0 = 0xfb;
  257.  
  258. /* Отсылаем текущие данные в сдвиговые регистры */
  259. if (display_pos >= 0 && display_pos <= 7) {
  260. _74hc595_SPI_send(0x00);
  261. _74hc595_SPI_send(display_data[display_pos]);
  262. _74hc595_SPI_send(groups1[display_pos]);
  263. _74hc595_SPI_send(0x00);
  264. }
  265. if (display_pos >= 8 && display_pos <= 15) {
  266. _74hc595_SPI_send(0x00);
  267. _74hc595_SPI_send(display_data[display_pos]);
  268. _74hc595_SPI_send(0x00);
  269. _74hc595_SPI_send(groups1[display_pos -8]);
  270. }
  271. if (display_pos >= 16 && display_pos <= 21) {
  272. _74hc595_SPI_send(groups2[display_pos - 16]);
  273. _74hc595_SPI_send(display_data[display_pos]);
  274. _74hc595_SPI_send(0x00);
  275. _74hc595_SPI_send(0x00);
  276. }
  277. // Закрываем защелку
  278. _74hc595_RegisterLatch();
  279. // Переключаем разряды
  280. display_pos = (display_pos + 1) % MAX_GROUPS;
  281. }
  282.  
  283. // Отображение больших цифр
  284. void print_HM_Display(int Hours, int Minutes, int HoursVisible, int MinutesVisible) {
  285. if (!HoursVisible) {
  286. if (Hours == 0) {
  287. display_data[BIG_DIGIT1] = ~digits[0];
  288. display_data[BIG_DIGIT2] = ~digits[0];
  289. } else if (Hours >= 1 && Hours <= 9) {
  290. display_data[BIG_DIGIT1] = ~digits[0];
  291. display_data[BIG_DIGIT2] = ~digits[Hours];
  292. } else if (Hours >= 10 && Hours <= 99) {
  293. display_data[BIG_DIGIT1] = ~digits[(unsigned int)round((Hours % 100) / 10)];
  294. display_data[BIG_DIGIT2] = ~digits[(unsigned int)round(Hours % 10)];
  295. }
  296. } else {
  297. display_data[BIG_DIGIT1] = 0x00;
  298. display_data[BIG_DIGIT2] = 0x00;
  299. }
  300.  
  301. if (!MinutesVisible) {
  302. if (Minutes == 0) {
  303. display_data[BIG_DIGIT3] = ~digits[0];
  304. display_data[BIG_DIGIT4] = ~digits[0];
  305. } else if (Minutes >= 1 && Minutes <= 9) {
  306. display_data[BIG_DIGIT3] = ~digits[0];
  307. display_data[BIG_DIGIT4] = ~digits[Minutes];
  308. } else if (Minutes >= 10 && Minutes <= 99) {
  309. display_data[BIG_DIGIT3] = ~digits[(unsigned int)round((Minutes % 100) / 10)];
  310. display_data[BIG_DIGIT4] = ~digits[(unsigned int)round(Minutes % 10)];
  311. }
  312. } else {
  313. display_data[BIG_DIGIT3] = 0x00;
  314. display_data[BIG_DIGIT4] = 0x00;
  315. }
  316. }
  317.  
  318. // Отображение текущей даты и года
  319. // Если год равен нулю - отображается дата
  320. // Если год больше нуля - отображается год
  321. void print_DM_Display( int Day, int Month, int Year, int DayVisible, int MontVisible, int YearsVisible ) {
  322. if (Year == 0) {
  323. if (!DayVisible) {
  324. if (Day == 0) {
  325. display_data[I1D1] = digits[0];
  326. display_data[I1D2] = digits[0];
  327. } else if (Day >= 1 && Day <= 9) {
  328. display_data[I1D1] = digits[0];
  329. display_data[I1D2] = digits[Day];
  330. } else if (Day >= 10 && Day <= 99) {
  331. display_data[I1D1] = digits[(unsigned int)round(Day % 100) / 10];
  332. display_data[I1D2] = digits[(unsigned int)round(Day % 10)];
  333. }
  334. } else {
  335. display_data[I1D1] = 0xFF;
  336. display_data[I1D2] = 0xFF;
  337. }
  338.  
  339. if (!MontVisible) {
  340. if (Month == 0) {
  341. display_data[I1D3] = digits[0] & ~(1 << 7);
  342. display_data[I1D4] = digits[0];
  343. } else if (Month >= 1 && Month <= 9) {
  344. display_data[I1D3] = digits[0] & ~(1 << 7);
  345. display_data[I1D4] = digits[Month];
  346. } else if (Month >= 10 && Month <= 99) {
  347. display_data[I1D3] = digits[(unsigned int)round(Month % 100) / 10] & ~(1 << 7);
  348. display_data[I1D4] = digits[(unsigned int)round(Month % 10)];
  349. }
  350. } else {
  351. display_data[I1D3] = 0xFF;
  352. display_data[I1D4] = 0xFF;
  353. }
  354. } else {
  355. if (!YearsVisible) {
  356. display_data[I1D1] = digits[2];
  357. display_data[I1D2] = digits[0];
  358. display_data[I1D3] = digits[(unsigned int)round((Year % 100) / 10)];
  359. display_data[I1D4] = digits[(unsigned int)round(Year % 10)];
  360. } else {
  361. display_data[I1D1] = 0xFF;
  362. display_data[I1D2] = 0xFF;
  363. display_data[I1D3] = 0xFF;
  364. display_data[I1D4] = 0xFF;
  365. }
  366. }
  367. }
  368.  
  369. // Отображение температуры
  370. void print_TEMP_Display( int temp ) {
  371. if (temp == 0) {
  372. display_data[I2D1] = 0xff;
  373. display_data[I2D2] = digits[0];
  374. display_data[I2D3] = 0b10011100;
  375. display_data[I2D4] = 0xff;
  376. } else if (temp >= 1 && temp <= 9) {
  377. display_data[I2D1] = 0xff;
  378. display_data[I2D2] = digits[temp];
  379. display_data[I2D3] = 0b10011100;
  380. display_data[I2D4] = 0xff;
  381. } else if (temp >= 10 && temp <= 99) {
  382. display_data[I2D1] = digits[(unsigned int)round(temp % 100) / 10];
  383. display_data[I2D2] = digits[(unsigned int)round(temp % 10)];
  384. display_data[I2D3] = 0b10011100;
  385. display_data[I2D4] = 0xff;
  386. }
  387.  
  388. if (temp < 0) {
  389. temp = abs(temp);
  390. if (temp >= 1 && temp <= 9) {
  391. display_data[I2D1] = 0xff;
  392. display_data[I2D2] = 0b10111111;
  393. display_data[I2D3] = digits[temp];
  394. display_data[I2D4] = 0b10011100;
  395. } else if (temp >= 10 && temp <= 99) {
  396. display_data[I2D1] = 0b10111111;
  397. display_data[I2D2] = digits[(unsigned int)round(temp % 100) / 10];
  398. display_data[I2D3] = digits[(unsigned int)round(temp % 10)];
  399. display_data[I2D4] = 0b10011100;
  400. }
  401. }
  402. }
  403.  
  404. // Таймер подсчета миллисекунд
  405. ISR (TIMER1_OVF_vect) {
  406. TCNT1 = 0xFF06;
  407.  
  408. millis++;
  409. if (millis > 9223372036854775807) millis = 0; // НХУЯ СЕ!!!!
  410. }
  411.  
  412. // Вход во внешнее прерывание. DS1307 (SQW)
  413. ISR ( INT0_vect ) {
  414. sqw_flag = 1;
  415. }
  416.  
  417. // Вход во внешнее прерывание. IRDA/NEC
  418. ISR ( INT1_vect ) {
  419. T2_START;
  420. if (NEC_SCLK > NEC_MIN_CLK) {
  421. //USORT_Transmit(NEC_SCLK);
  422. // Тут определяем стартовое сообщение (преамбулу)
  423. if (NEC_SCLK >= NEC_MIN_HEADER_MESSAGE_CLK && NEC_SCLK < NEC_MAX_HEADER_MESSAGE_CLK) {
  424. NEC_START_FLAG = 1;
  425. NEC_REPEAT_FLAG = 0;
  426. NEC_RECV_CNT = 0;
  427. }
  428.  
  429. if (NEC_SCLK >= NEC_MIN_REPEAT && NEC_SCLK < NEC_MAX_REPEAT && NEC_START_FLAG) {
  430. NEC_REPEAT_FLAG = 1;
  431. }
  432.  
  433. /* Знаю, по идиотски, Но умнее лень было придумывать */
  434.  
  435. // Тут определяем биты нулевого значения
  436. if ((NEC_SCLK >= NEC_MIN_NUL_BIT_CLK && NEC_SCLK < NEC_MAX_NUL_BIT_CLK) && NEC_START_FLAG) {
  437. NEC_RECV_CNT++; // Инкрементируем колличество принятых нулей
  438. // ну а тут мутнаые процедуры записи значений в переменные
  439. if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) { // Если мы в диапозоне 1-8, ...
  440. addr1 &= ~(1 << (NEC_RECV_CNT - offset1_addr1)); // добавляем в addr1 нули в нужные места
  441. }
  442. // Остальные диапозоны тоже самое
  443. if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
  444. addr2 &= ~(1 << (NEC_RECV_CNT - offset1_addr2));
  445. }
  446. if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
  447. cmd1 &= ~(1 << (NEC_RECV_CNT - offset1_cmd1));
  448. }
  449. if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
  450. cmd2 &= ~(1 << (NEC_RECV_CNT - offset1_cmd2));
  451. }
  452. // IRActiveLed(0);
  453.  
  454. }
  455.  
  456. // Тут определяем биты положительного значения (такая-же хуйня как и с нулями, только интервалы у NEC_SCLK больше)
  457. if ((NEC_SCLK >= NEC_MIN_ONE_BIT_CLK && NEC_SCLK < NEC_MAX_ONE_BIT_CLK) && NEC_START_FLAG) {
  458. NEC_RECV_CNT++; // Инкрементируем колличество принятых едениц
  459.  
  460. if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
  461. addr1 |= (1 << (NEC_RECV_CNT - offset1_addr1));
  462. }
  463. if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
  464. addr2 |= (1 << (NEC_RECV_CNT - offset1_addr2));
  465. }
  466. if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
  467. cmd1 |= (1 << (NEC_RECV_CNT - offset1_cmd1));
  468. }
  469. if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
  470. cmd2 |= (1 << (NEC_RECV_CNT - offset1_cmd2));
  471. }
  472. // IRActiveLed(1);
  473. }
  474.  
  475. NEC_SCLK = 0;
  476.  
  477. // Колличество нулей и едениц в конечном счете должно быть 32, на этом и остановимся
  478. if (NEC_RECV_CNT == NEC_PACKET_LENGTH) {
  479. // Выставляем в стартовое положение все счетчики и останавлиеваем подсчет
  480. NEC_RECV_CNT = 0;
  481. NEC_START_FLAG = 0;
  482. T2_STOP;
  483.  
  484. // Проверка сообщения на целостность
  485. // В версии протокола 2.0 адрес имеет расширеное пространство и не имеет инверсии
  486. // Значит проверяем либо сложив обе инверсии (адреса и команды), либо только инверсии команды
  487. if ((((addr1 + addr2 == 0xFF) && (cmd1 + cmd2) == 0xFF)) || (cmd1 + cmd2 == 0xFF)) {
  488. NEC_IR_DONE = 1; // Сообщаем системе, что чтение завершено
  489. // Команду склеиваем с адресом (16 бит)
  490. command = ((addr1 + addr2) << 8) | cmd1;
  491. }
  492. }
  493.  
  494. }
  495. }
  496.  
  497. void DS1307_ReadDateTime( void ) {
  498. unsigned char temp;
  499.  
  500. // Читаем данные и преобразуем из BCD в двоичную систему
  501. DS1307Read(0x00, &temp); // Чтение регистра секунд
  502. DateTime.Sec = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  503. DS1307Read(0x01,&temp); // Чтение регистра минут
  504. DateTime.Min = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  505. DS1307Read(0x02,&temp); // Чтение регистра часов
  506. DateTime.Hour = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  507. DS1307Read(0x04, &temp); // Чтение регистра дней
  508. DateTime.Day = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  509. DS1307Read(0x05, &temp); // Десятки месяца
  510. DateTime.Month = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  511. DS1307Read(0x06, &temp); // Десятки года
  512. DateTime.Year = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F);
  513. }
  514.  
  515. // Функция пропорционально переносит значение (value) из текущего диапазона
  516. // значений (fromLow .. fromHigh) в новый диапазон (toLow .. toHigh), заданный параметрами
  517. // честно спижжено мной с ARDUINO
  518. long map(long x, long in_min, long in_max, long out_min, long out_max) {
  519. return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
  520. }
  521.  
  522. // Процедура записи в микросхему из структуры TDateTime
  523. void DS1307_WriteDateTime() {
  524. unsigned char tmp;
  525. tmp = ((DateTime.Sec / 10) << 4) | (DateTime.Sec % 10);
  526. DS1307Write(0x00, tmp);
  527. tmp = ((DateTime.Min / 10) << 4) | (DateTime.Min % 10);
  528. DS1307Write(0x01, tmp);
  529. tmp = ((DateTime.Hour / 10) << 4) | (DateTime.Hour % 10);
  530. DS1307Write(0x02, tmp);
  531. tmp = ((DateTime.WeekDay / 10) << 4) | (DateTime.WeekDay % 10);
  532. DS1307Write(0x03, tmp);
  533.  
  534. tmp = ((DateTime.Day / 10) << 4) | (DateTime.Day % 10);
  535. DS1307Write(0x04, tmp);
  536. tmp = ((DateTime.Month / 10) << 4) | (DateTime.Month % 10);
  537. DS1307Write(0x05, tmp);
  538.  
  539. tmp = ((DateTime.Year / 10) << 4) | (DateTime.Year % 10);
  540. DS1307Write(0x06, tmp);
  541. }
  542.  
  543. unsigned char ReverseBits(unsigned char number) {
  544. number = (number & 0x55) << 1 | (number & 0xAA) >> 1;
  545. number = (number & 0x33) << 2 | (number & 0xCC) >> 2;
  546. number = (number & 0x0F) << 4 | (number & 0xF0) >> 4;
  547.  
  548. return number;
  549. }
  550.  
  551. void initADC1 ( void ) {
  552. // 2.56v internal reference
  553. ADMUX |= (1 << REFS1) | (1 << REFS0);
  554. // ADC1
  555. ADMUX |= (0 << MUX3) | (0 << MUX1) | (1 << MUX0);
  556. // /= 8 ADC Frequencu
  557. ADCSRA |= (1 << ADEN);
  558. sbi(ADCSRA, ADPS2);
  559. cbi(ADCSRA, ADPS1);
  560. sbi(ADCSRA, ADPS0);
  561. }
  562.  
  563. unsigned int read_adc( void ) {
  564. unsigned int v;
  565. ADCSRA |= (1 << ADSC);
  566.  
  567. while ((ADCSRA & _BV(ADIF)) == 0x00);
  568.  
  569. v = (ADCL | ADCH << 8);
  570.  
  571. return v;
  572. }
  573.  
  574. int main(void) {
  575. asm("CLI");
  576.  
  577. //USORT_Init(MYUBRR);
  578.  
  579. // Внешнее прерывание
  580. MCUCR |= (1 << ISC10) | (1 << ISC11);
  581. MCUCR |= (1 << ISC01) | (0 << ISC00);
  582. GICR |= (1 << INT1) | (1 << INT0);
  583. GIFR |= (1 << INTF1) | (1 << INTF0);
  584.  
  585. // Инициализация таймера/счестчика 0 для динамической индикации
  586. TCCR0 |= (1 << CS00) | (1 << CS02) | (0 << CS01);
  587. TIMSK |= (1 << TOIE0);
  588. TCNT0 = 0xCC;
  589.  
  590. // Инициализация таймера/счестчика 1 для подсчета миллисекунд
  591. TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
  592. TIMSK |= (1 << TOIE1);
  593. TCNT1 = 0xFF06;
  594.  
  595. // Таймер для работы с NEC-протоколом IRDA
  596. TCCR2 = (1 << CS20) | (1 << CS21) | (0 << CS22);
  597. TIMSK |= (1 << TOIE2);
  598. TCNT2 = 0xF0;
  599.  
  600. asm("SEI");
  601.  
  602. _74hc595_SPI_Init();
  603. initADC1();
  604. I2CInit();
  605. DS1307Init();
  606. DS1307Write(0x07, 0b10010000); // Настраиваем выход SQW на частоту 1Hz
  607.  
  608. // Переменные для работы интерфейса
  609. int menu_level = 0; // позиция в главном меню
  610. int menu_flag = 0; // Говорит о том, что открыто меню в данный момент или нет
  611. int s_hour = 0, s_min = 0, s_day = 0, s_month = 0, s_year = 0; // Настраиваемые значения
  612. int enter_menu_flag = 0; // Флаг входа в меню. выполняется каждый раз при входе в меню для приравнивания значений
  613. int DMY_Mode = 0; // Режим отображения (для переключения) число.месяц -> год
  614. int blink_flag = 0; // Флаг мигания чего-либо на дисплее
  615. int pass_cnt = 4; // Счетчик колличества проходов по шкале
  616. int interval = 7; // Интервал перемещения по проходу
  617. int pass_end_flag = 0; // Флаг сброса прохода
  618. unsigned long long int scale = 0x7FFFFFFFFFFFFFF; // Представление шкалы (последние 5 бит не используются)
  619. int temp_flag = 0; // Флаг обновления температуры
  620.  
  621. // Значения для усреднения и преобразвания
  622. const int ADC_SAMPLES_CNT = 10; // Выборок за раз
  623. const float REFERENCE = 2.56F; // Опорное напряжение
  624. const float ADC_MAX_VALUE = 1024.0F; // Максимальное значение АЦП
  625. const float BIAS_VOLTAGE = 0.5F; // Напряжение смещения датчика
  626. int readIndex = 0, samplesTotal = 0; // Текущий индекс чтения АЦП и общее кол-во значений
  627. int adcValues[ADC_SAMPLES_CNT]; // Массив со значениями АЦП
  628. int tempC = 0; // Температура
  629.  
  630. // Забиваем текущий массив нулями
  631. for (int i = 0; i < ADC_SAMPLES_CNT; i++) {
  632. adcValues[i] = 0;
  633. }
  634.  
  635. while (1) {
  636. // Тут распихиваем данные из переменной в массив индикации. Все значения после изменений в коде для работы со
  637. // сдвиговыми регистрами 74hc595 стали лезть старшим битом наружу. Все пошло по пизде и пришлось развернуть каждую группу битов,
  638. // что-бы как-то все это компенсировать. я конечно могу и дальше копать в сторону чего там не так, но нахуй это надо и так все работает ))))
  639. display_data[SCALE_GROUP1] = ReverseBits((unsigned char)(scale >> 56));
  640. display_data[SCALE_GROUP2] = ReverseBits((unsigned char)(scale >> 48));
  641. display_data[SCALE_GROUP3] = ReverseBits((unsigned char)(scale >> 40));
  642. display_data[SCALE_GROUP4] = ReverseBits((unsigned char)(scale >> 32));
  643. display_data[SCALE_GROUP5] = ReverseBits((unsigned char)(scale >> 24));
  644. display_data[SCALE_GROUP6] = ReverseBits((unsigned char)(scale >> 16));
  645. display_data[SCALE_GROUP7] = ReverseBits((unsigned char)(scale >> 8));
  646. display_data[SCALE_GROUP8] = ReverseBits((unsigned char)(scale >> 0));
  647.  
  648. // Берем текущие значения из микросхемы
  649. DS1307_ReadDateTime();
  650.  
  651. // Если "началась секунда"
  652. if (sqw_flag && !menu_flag) {
  653. // Переносим из одного множества в другое, для того, что-бы светодиод бежал медленнее
  654. // по мере заполнения шкалы
  655. interval = map(DateTime.Sec, 0, 59, 7, 30);
  656.  
  657. // Начинаем анимацию
  658. setInterval(interval, tmr3, {
  659. pass_cnt++; // Прибавляем текущий проход
  660.  
  661. // Если проходов больше, чем оставшееся кол-во секунд - обнуляем все счетчики
  662. // и говорим, что все проходы проёдены
  663. if (pass_cnt > 59 - (DateTime.Sec)) {
  664. pass_cnt = 0;
  665. sqw_flag = 0;
  666. pass_end_flag = 1;
  667. }
  668. // Бежим светодиодом по шкале
  669. scale &= ~(1ULL << (pass_cnt + 4));
  670.  
  671. // Убираем ебучий шлейф за бегущим диодом
  672. for (int i = 0; i <= (pass_cnt - 1); i++) {
  673. scale |= (1ULL << (i + 4));
  674. }
  675. });
  676. }
  677. // Если шкалу прошли
  678. if (pass_end_flag && !menu_flag) {
  679. // то отображаем текущее значение
  680. for (int i = 59; i >= (59 - DateTime.Sec); i--) {
  681. scale &= ~(1ULL << (i +4));
  682. }
  683. pass_end_flag = 0;
  684. }
  685.  
  686. // Если пришла команда с пульта
  687. if (NEC_IR_DONE) {
  688. NEC_IR_DONE = 0; // уже нет
  689.  
  690. // Если мы вошли в меню
  691. if (command == MENU) {
  692. menu_flag = 1; // Говорим, что мы в меню
  693. menu_level = 0; // Выставляем уровень в начало
  694. enter_menu_flag = 1; // Говорим, что мы ВОШЛИ в меню
  695. }
  696.  
  697. if (command == FWND && menu_flag) {
  698. menu_level++;
  699. if (menu_level > 4) menu_level = 0;
  700. }
  701.  
  702. if (command == RWND && menu_flag) {
  703. menu_level--;
  704. if (menu_level < 0) menu_level = 4;
  705. }
  706.  
  707. if (command == RETURN && menu_flag) {
  708. menu_flag = 0;
  709. }
  710.  
  711. if (command == PLUS && menu_flag) {
  712. if (menu_level == 0) {
  713. s_hour++;
  714. if (s_hour > 23) s_hour = 0;
  715. print_HM_Display(s_hour, s_min, 0, 0);
  716. }
  717. if (menu_level == 1) {
  718. s_min++;
  719. if (s_min > 59) s_min = 0;
  720. print_HM_Display(s_hour, s_min, 0, 0);
  721. }
  722. if (menu_level == 2) {
  723. s_day++;
  724. if (s_day > 31) s_day = 1;
  725. print_DM_Display(s_month, s_day, 0, 0, 0, 0);
  726. }
  727. if (menu_level == 3) {
  728. s_month++;
  729. if (s_month > 12) s_month = 1;
  730. print_DM_Display(s_month, s_day, 0, 0, 0, 0);
  731. }
  732. if (menu_level == 4) {
  733. s_year++;
  734. if (s_year > 99) s_year = 0;
  735. print_DM_Display(0, 0, s_year, 0, 0, 0);
  736. }
  737. }
  738.  
  739. if (command == MINUS && menu_flag) {
  740. if (menu_level == 0) {
  741. s_hour--;
  742. if (s_hour < 0) s_hour = 23;
  743. print_HM_Display(s_hour, s_min, 0, 0);
  744. }
  745. if (menu_level == 1) {
  746. s_min--;
  747. if (s_min < 0) s_min = 59;
  748. print_HM_Display(s_hour, s_min, 0, 0);
  749. }
  750. if (menu_level == 2) {
  751. s_day--;
  752. if (s_day < 1) s_day = 31;
  753. print_DM_Display(s_month, s_day, 0, 0, 0, 0);
  754. }
  755. if (menu_level == 3) {
  756. s_month--;
  757. if (s_month < 1) s_month = 12;
  758. print_DM_Display(s_month, s_day, 0, 0, 0, 0);
  759. }
  760. if (menu_level == 4) {
  761. s_year--;
  762. if (s_year < 0) s_year = 99;
  763. print_DM_Display(0, 0, s_year, 0, 0, 0);
  764. }
  765. }
  766.  
  767. if (command == PLAY && menu_flag) {
  768. DateTime.Sec = 0;
  769. DateTime.Min = s_min;
  770. DateTime.Hour = s_hour;
  771. DateTime.Day = s_day;
  772. DateTime.Month = s_month;
  773. DateTime.Year = s_year;
  774. DS1307_WriteDateTime();
  775.  
  776. menu_flag = 0;
  777. menu_level = 0;
  778. }
  779. }
  780.  
  781. if (menu_flag) {
  782. if (enter_menu_flag) {
  783. enter_menu_flag = 0;
  784. s_hour = DateTime.Hour;
  785. s_min = DateTime.Min;
  786. s_day = DateTime.Day;
  787. s_month = DateTime.Month;
  788. s_year = DateTime.Year;
  789. }
  790. setInterval(540, tmr1, {
  791. blink_flag ^= 1;
  792. if (menu_level == 0) {
  793. print_HM_Display(s_hour, s_min, blink_flag, 0);
  794. print_DM_Display(s_month, s_day, 0, 0, 0, 0);
  795. }
  796. if (menu_level == 1)
  797. print_HM_Display(s_hour, s_min, 0, blink_flag);
  798. if (menu_level == 2)
  799. print_DM_Display(s_month, s_day, 0, 0, blink_flag, 0);
  800. if (menu_level == 3)
  801. print_DM_Display(s_month, s_day, 0, blink_flag, 0, 0);
  802. if (menu_level == 4)
  803. print_DM_Display(0, 0, s_year, 0, 0, blink_flag);
  804. });
  805.  
  806. }
  807.  
  808. if (!menu_flag) {
  809. DS1307_ReadDateTime();
  810. print_HM_Display(DateTime.Hour, DateTime.Min, 0, 0);
  811.  
  812. if (DateTime.Sec % 2) DIVIDER_ON else DIVIDER_OFF;
  813.  
  814. setInterval(2500, tmr0, {
  815. DMY_Mode ^= 1;
  816. temp_flag = 1;
  817. if (DMY_Mode)
  818. print_DM_Display(DateTime.Month, DateTime.Day, 0, 0, 0, 0);
  819. else
  820. print_DM_Display(0, 0, DateTime.Year, 0, 0, 0);
  821. });
  822.  
  823. if (temp_flag) {
  824. temp_flag = 0;
  825. // Поиск среднего арифметического значения АЦП
  826. while (readIndex < ADC_SAMPLES_CNT) {
  827. samplesTotal = samplesTotal - adcValues[readIndex];
  828. adcValues[readIndex] = read_adc();
  829. samplesTotal = samplesTotal + adcValues[readIndex];
  830. readIndex++;
  831. }
  832. if (readIndex >= ADC_SAMPLES_CNT) readIndex = 0;
  833.  
  834. // Преобразование усредненного-арифметического значения АЦП в температуру
  835. tempC = floor(((((samplesTotal / ADC_SAMPLES_CNT) * REFERENCE) / ADC_MAX_VALUE) - BIAS_VOLTAGE) * 100.0F);
  836. print_TEMP_Display(tempC);
  837. }
  838. }
  839. }
  840. }
Advertisement
Add Comment
Please, Sign In to add comment