/* * main.c * * Created on: 22 нояб. 2018 г. * Author: maxx */ #include #include #include #include #include //sbi, cbi etc.. #include "avr/wdt.h" // WatchDog #include // printf etc.. #include "uart_extd.h" #include "spi.h" #include "globals.h" //Global definitions for project #include "stdbool.h" #include "Ethernet/socket.h" #include "Ethernet/wizchip_conf.h" #include "Application/Blynk/blynk.h" #include "Internet/DNS/dns.h" #define _MAIN_DEBUG_ //***********BLYNK related: BEGIN #define SOCK_BLYNK_CLIENT 6 //My auth token for my android test application MEGA+USB: uint8_t auth[] = "c113f724351444fc872ae586d70b18cd"; // You should get Auth Token in the Blynk App // IP: 139.59.206.133 for via WIN7 nslookup - actually need to use DNS resolving //Resolve here via DNS query see below Domain_IP[4] //uint8_t blynk_server_ip[4] = {139, 59, 206, 133}; // Blynk cloud server IP (cloud.blynk.cc, 8422) //uint8_t BLYNK_RX_BUF[DATA_BUF_SIZE]; uint8_t BLYNK_TX_BUF[BLYNK_DATA_BUF_SIZE]; //***********BLYNK related: END //***************** DNS: BEGIN ////////////////////////////////////////////////// // Socket & Port number definition for Examples // ////////////////////////////////////////////////// #define SOCK_DNS 5 unsigned char gDATABUF_DNS[512]; //#define IP_WORK //////////////// // DNS client // //////////////// uint8_t Domain_name[] = BLYNK_DEFAULT_DOMAIN; // Public russian ntp server - works good via GSM Modem uint8_t Domain_IP[4] = {0, }; // Translated IP address by DNS Server //***************** DNS: END /* * (19)OK (v1.0) Trying port to WIZNET5500 BLYNK IOT app (look: https://blynk.io/) * TODO: * OK (v1.2) Add DNS resolve before BLYNK app running to * OK (v1.1) Add LED_ON/LED_OFF handle on LED D13 BLYNK Android application * GPIO OUT - works OK (look ./Application/Blynk/blynkDependency.c digitalWrite(..) && pinMode(..))! * OK(v1.2) Add printout server metrics on start-up * Need to try next: * OK (v1.3)GPIO IN - fixed bug (remove redundant space symbol in ) * Virtual IN/OUT -Not fully supported yet, so decide not use here.. * OK (v1.4)Analog Read/Write * OK (v1.5)Restore pins state on board reboot * OK ??3.Try fix frequent reconnection with blynk server - every ~22sec may be this OK. * OK (v1.6) Add push event (P13/PD.5 toggle every 10 sec && send state P13 to BLYNK server) * Need compare local blynk.c code with modern library - (Too old version here - 0.2.1 (On git blynk March 2019 - 0.6.x) ) * * (3) Trying WIZNET5500 init with using official Wiznet ioLibrary_Driver * working ping, assign static IP * LED1 = ON when phy_link detected * and loopback test on TCP-IP:5000 and UDP:3000 ports. * use Hercules terminal utility to check network connection see: * * https://wizwiki.net/wiki/doku.php?id=osh:cookie:loopback_test * https://www.hw-group.com/software/hercules-setup-utility * */ //***********Prologue for fast WDT disable & and save reason of reset/power-up: END uint8_t mcucsr_mirror __attribute__ ((section (".noinit"))); // This is for fast WDT disable & and save reason of reset/power-up void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcucsr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } //***********Prologue for fast WDT disable & and save reason of reset/power-up: END //*********Global vars #define TICK_PER_SEC 1000UL volatile unsigned long _millis; // for millis tick !! Overflow every ~49.7 days //*********Program metrics const char compile_date[] PROGMEM = __DATE__; // Mmm dd yyyy - Дата компиляции const char compile_time[] PROGMEM = __TIME__; // hh:mm:ss - Время компиляции const char str_prog_name[] PROGMEM = "\r\nAtMega1284p v1.6 Static IP BLYNK WIZNET_5500 ETHERNET 14/03/2019\r\n"; // Program name #if defined(__AVR_ATmega128__) const char PROGMEM str_mcu[] = "ATmega128"; //CPU is m128 #elif defined (__AVR_ATmega2560__) const char PROGMEM str_mcu[] = "ATmega2560"; //CPU is m2560 #elif defined (__AVR_ATmega2561__) const char PROGMEM str_mcu[] = "ATmega2561"; //CPU is m2561 #elif defined (__AVR_ATmega328P__) const char PROGMEM str_mcu[] = "ATmega328P"; //CPU is m328p #elif defined (__AVR_ATmega32U4__) const char PROGMEM str_mcu[] = "ATmega32u4"; //CPU is m32u4 #elif defined (__AVR_ATmega644P__) const char PROGMEM str_mcu[] = "ATmega644p"; //CPU is m644p #elif defined (__AVR_ATmega1284P__) const char PROGMEM str_mcu[] = "ATmega1284p"; //CPU is m1284p #else const char PROGMEM str_mcu[] = "Unknown CPU"; //CPU is unknown #endif //FUNC headers static void avr_init(void); void timer0_init(void); //Wiznet FUNC headers void print_network_information(void); // RAM Memory usage test int freeRam (void) { extern int __heap_start, *__brkval; int v; int _res = (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); return _res; } //******************* MILLIS ENGINE: BEGIN //ISR (TIMER0_COMP_vect ) ISR (TIMER0_COMPA_vect) { // Compare match Timer0 // Here every 1ms _millis++; // INC millis tick // Тест мигаем при в ходе в прерывание // 500Hz FREQ OUT // LED_TGL; } unsigned long millis(void) { unsigned long i; cli(); // Atomic tick reading i = _millis; sei(); return i; } //******************* MILLIS ENGINE: END //***************** UART0: BEGIN // Assign I/O stream to UART /* define CPU frequency in Mhz here if not defined in Makefile */ //#ifndef F_CPU //#define F_CPU 16000000UL //#endif /* 19200 baud */ //#define UART_BAUD_RATE 19200 //#define UART_BAUD_RATE 38400 #define UART_BAUD_RATE 115200 static int uart0_putchar(char ch,FILE *stream); static void uart0_rx_flash(void); static FILE uart0_stdout = FDEV_SETUP_STREAM(uart0_putchar, NULL, _FDEV_SETUP_WRITE); //PS. stdin не переназначаю, т.к. удобнее с ним работать через uart.h - api: /* * Т.е. например так c = uart1_getc(); if (( c & UART_NO_DATA ) == 0) { uart1_putc( (unsigned char)c ); } При этом чекаем что буфер приема не пуст и опрос идет неблокирующий (+ работаем через UART RX RINGBUFFER), а если работаем в стиле stdin->getchar() там опрос блокируется пока символ не будет принят (поллинг) через UART1_RX, т.е. неудобно. */ // STDOUT UART0 TX handler static int uart0_putchar(char ch,FILE *stream) { uart_putc(ch); return 0; } // Очищаем буфер приема UART1 RX (иногда нужно) static void uart0_rx_flash(void) { // Считываем все из ring-buffer UART1 RX unsigned int c; do { c = uart_getc(); } while (( c & UART_NO_DATA ) == 0); // Check RX1 none-empty } //***************** UART0: END //***************** ADC: BEGIN #ifndef ADC_DIV //12.5MHz or over use this ADC reference clock #define ADC_DIV (1<> MCU is: %S; CLK is: %luHz\r\n", str_mcu, F_CPU);// MCU Name && FREQ PRINTF(">> Free RAM is: %d bytes\r\n", freeRam()); //Wizchip WIZ5500 Ethernet initialize IO_LIBRARY_Init(); //After that ping must working print_network_information(); /* DNS client Initialization */ PRINTF("> [BLYNK] Target Domain Name : %s\r\n", Domain_name); DNS_init(SOCK_DNS, gDATABUF_DNS); /* DNS processing */ int32_t ret; if ((ret = DNS_run(netInfo.dns, Domain_name, Domain_IP)) > 0) // try to 1st DNS { #ifdef _MAIN_DEBUG_ PRINTF("> 1st DNS Respond\r\n"); #endif } else if ((ret != -1) && ((ret = DNS_run(DNS_2nd, Domain_name, Domain_IP))>0)) // retry to 2nd DNS { #ifdef _MAIN_DEBUG_ PRINTF("> 2nd DNS Respond\r\n"); #endif } else if(ret == -1) { #ifdef _MAIN_DEBUG_ PRINTF("> MAX_DOMAIN_NAME is too small. Should be redefined it.\r\n"); #endif ; } else { #ifdef _MAIN_DEBUG_ PRINTF("> DNS Failed\r\n"); #endif ; } if(ret > 0) { #ifdef _MAIN_DEBUG_ printf("> Translated %s to [%d.%d.%d.%d]\r\n\r\n",Domain_name,Domain_IP[0],Domain_IP[1],Domain_IP[2],Domain_IP[3]); #endif //IOT BLYK app init: /* Blynk client Initialization */ PRINTF("Try connect to BLYNK SERVER [%s]: %d.%d.%d.%d:%d..\n\r",Domain_name,Domain_IP[0],Domain_IP[1],Domain_IP[2],Domain_IP[3],BLYNK_DEFAULT_PORT); blynk_begin(auth, Domain_IP, BLYNK_DEFAULT_PORT, BLYNK_TX_BUF, SOCK_BLYNK_CLIENT); } else { PRINTF("> [BLYNK] Target Domain Name : %s resolve ERROR\r\nReboot board..\r\n", Domain_name); while(1); } //Short Blink LED 3 times on startup unsigned char i = 3; while(i--) { led1_high(); _delay_ms(100); led1_low(); _delay_ms(400); wdt_reset(); } /* Loopback Test: TCP Server and UDP */ // Test for Ethernet data transfer validation uint32_t timer_tick_1sec = millis(); uint8_t blynk_restore_connection = 1; uint8_t timer_led2_push_10sec = 0; while(1) { //Here at least every 1sec wdt_reset(); // WDT reset at least every sec // Blynk process handler blynk_run(); //Here every 1sec event if((millis()-timer_tick_1sec)> 1000) { //here every 1 sec timer_tick_1sec = millis(); //To restore GPIO state on start-up application if(blynk_restore_connection) { if(is_blynk_connection_available()) { blynk_restore_connection = 0; //Requests Server to re-send current values for all widgets PRINTF("++blynk_syncAll event\r\n"); //Just for debug blynk_syncAll(); } } //Every 10sec event for LED2 PIN13 if(++timer_led2_push_10sec == 10) { timer_led2_push_10sec = 0; //Clear timer_led2.. //Every 10sec toggle, and push LED2 PIN13/PD5 state to BLYNK server led2_tgl(); blynk_push_pin(13); } } } return 0; } // Timer0 // 1ms IRQ // Used for millis() timing void timer0_init(void) { /* * * For M128 TCCR0 = (1<250kHz:250-=>1kHz) TIMSK |= 1<250kHz:250-=>1kHz) TIMSK0 |= 1<