commit b3c9e21fd56e1393d013f9f5612b444a7b923dd0 Author: Roman Boykov Date: Tue Mar 7 17:15:12 2023 +0300 Initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ce058e --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023, Roman Boykov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2fc821 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +ESPKit for Sprinter computer +============================ + +Библиотеки и приложения для работы с картой Sprinter-WiFi на базе модуля ESP8266. diff --git a/sources/espdef.h b/sources/espdef.h new file mode 100644 index 0000000..5cf453d --- /dev/null +++ b/sources/espdef.h @@ -0,0 +1,86 @@ +/* +========================================================== + Header file with Definitions for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +========================================================== +*/ + +#ifndef __ESPDEF_H +#define __ESPDEF_H + +//#define ESTEXT + +#define PORT_ISA 0x9FBD +#define PORT_SYSTEM 0x1FFD +#define PORT_MMU3 0xE2 + +#ifdef ESTEX +#define PORT_UART 0xC3E8 // COM3 base port in memory +#else +#define PORT_UART 0x03E8 // COM3 base port +#endif + +/* UART TC16C550 Registers */ +#define REG_RBR PORT_UART + 0 +#define REG_THR PORT_UART + 0 +#define REG_IER PORT_UART + 1 +#define REG_IIR PORT_UART + 2 +#define REG_FCR PORT_UART + 2 +#define REG_LCR PORT_UART + 3 +#define REG_MCR PORT_UART + 4 +#define REG_LSR PORT_UART + 5 +#define REG_MSR PORT_UART + 6 +#define REG_SCR PORT_UART + 7 +#define REG_DLL PORT_UART + 0 +#define REG_DLM PORT_UART + 1 +#define REG_AFR PORT_UART + 2 + +/* UART TC16C550 Register bits */ +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_RST 0x04 +#define MCR_PGM 0x08 +#define MCR_LOOP 0x10 +#define MCR_AFE 0x20 + +#define LCR_WL8 0x03 // 8 bits word len +#define LCR_SB2 0x04 // 1.5 or 2 stp bits +#define LCR_DLAB 0x80 // enable Divisor latch + +#define FCR_FIFO 0x01 // Enable FIFO for rx and tx +#define FCR_RESET_RX 0x02 // Reset Rx FIFO +#define FCR_RESET_TX 0x04 // Reset Tx FIFO +#define FCR_DMA 0x08 // set -RXRDY, -TXRDY to "1" +#define FCR_TR1 0x00 // trigger on 1 byte in fifo +#define FCR_TR4 0x40 // trigger on 4 bytes in fifo +#define FCR_TR8 0x80 // trigger on 8 bytes in fifo +#define FCR_TR14 0xC0 // trigger on 14 bytes in fifo + +#define LSR_DR 0x01 // Data Ready +#define LSR_OE 0x02 // Overrun Error +#define LSR_PE 0x04 // Parity Error +#define LSR_FE 0x08 // Framing Error +#define LSR_BI 0x10 // Break Interrupt +#define LSR_THRE 0x20 // Transmitter Holding Register +#define LSR_TEMT 0x40 // Transmitter empty +#define LSR_RCVE 0x80 // Error in receiver FIFO + + + +/* PORT_ISA bits */ +#define ISA_A14 0x01 +#define ISA_A15 0x02 +#define ISA_A16 0x04 +#define ISA_A17 0x08 +#define ISA_A18 0x10 +#define ISA_A19 0x20 +#define ISA_AEN 0x40 +#define ISA_RESET 0x80 + +/* Speed divider for UART */ +#define BAUD_RATE 115200 // Connection speed with ESP8266 +#define XIN_FREQ 14745600 // On board frequency generator for TL16C550 +#define DIVISOR 8 // XIN_FREQ / (BAUD_RATE * 16) Frequency divider for Transmitter/Receiver + +#endif \ No newline at end of file diff --git a/sources/esplib.c b/sources/esplib.c new file mode 100644 index 0000000..108c63b --- /dev/null +++ b/sources/esplib.c @@ -0,0 +1,314 @@ +/* +================================================== + Implementation of Sprinter-WiFi ISA Card Library + Author: Roman A. Boykov + License: BSD 3-Clause +================================================== +*/ + +#include +#include +#include +#include +#include "esplib.h" + +#ifdef ESTEX +#pragma nonrec +#define outb(port, b) mset(port, b); +#define inb(port) mget(port); +#else +#define outb(port, b) outp(port, b); +#define inb(port) inp(port); +#endif + + +void util_delay(unsigned delay_ms) +{ +#ifdef ESTEX + if (delay_ms==0) { + delay_ms = 20; + } + unsigned ctr; + for (ctr = 0; ctr < delay_ms*1000; ctr++) + { + } +#else + clock_t t; + t = clock() + delay_ms; + while (clock() < t) { + } + + //delay(delay_ms); +#endif +} + +char save_mmu3 = 0; // Variable to save Sprinter memory mapping +char isa_slot = -1; // Variable to storeISA slot number where WiFi card found + +char isa_init() +{ + char wifi_found; + wifi_found = find_wifi(); + if (wifi_found) { + isa_reset(); + return 1; + } else { + return 0; + } +} + + +void isa_reset() +{ +#ifdef ESTEX + outp(port_isa, ISA_RESET | ISA_AEN); // RESET=1 AEN=1 + delay(20); + outp(port_isa, 0); // RESET=0 AEN=0 + delay(40); +#endif +} + + +void isa_open() +{ +#ifdef ESTEX + save_mmu3 = inp(PORT_MMU3); + outp(PORT_SYSTEM, 0x11); + outp(PORT_MMU3, ((isa_slot & 0x01) << 1) | 0xd4); +#endif +} + +void isa_close() +{ +#ifdef ESTEX + outp(PORT_SYSTEM, 0x01); + // restore mmu3 (Close ISA ports memory mapping) + outp(PORT_MMU3, save_mmu3); +#endif +} + +char isa_get_slot() +{ + return isa_slot; +} + +char check_slot(char slot) +{ + char irr; + isa_slot = slot; + isa_open(); + irr = inb(REG_IIR); + isa_close(); + return irr & 0x3F; +} + + +char find_wifi() +{ + // check isa slot 0 + char exists; + exists = check_slot(0); + if (exists) { + return 1; + } else { +#ifdef ESTEX + return check_slot(1); +#else + return 0; +#endif + } +} + + +// MODULE uart + +void uart_init() +{ + isa_open(); + // enable FIFO buffer, trigger to 14 byte + outb(REG_FCR, FCR_TR14 | FCR_FIFO); + // Disable interrupts + outb(REG_IER, 0x00); + // Set 8bit word and Divisor for speed + outb(REG_LCR, LCR_DLAB | LCR_WL8); // enable Baud rate latch + outb(REG_DLL, DIVISOR); + outb(REG_DLM, 0x00); + outb(REG_LCR, LCR_WL8); // 8bit word + isa_close(); +} + +char uart_read(reg) +unsigned reg; +{ + char res; + isa_open(); + res = inb(reg); + isa_close(); + return res; +} + +void uart_write(reg, value) +unsigned reg; +char value; +{ + isa_open(); + outb(reg, value); + isa_close(); +} + +char uart_wait_tr() +{ + char res; + char loops = 100; + while (loops>0) + { + res = uart_read(REG_LSR); + + if (res & LSR_THRE) { + break; + } + + loops--; + util_delay(1); + } + return loops; +} + +char uart_tx_byte(byte) +char byte; +{ + char ready = uart_wait_tr(); + if (ready){ + uart_write(REG_THR, byte); + } + return ready; +} + +char uart_tx_buffer(char* tbuff, int size) +{ + int ctr = size; + while (ctr--) { + if (uart_wait_tr()) { + uart_write(REG_THR, *tbuff++); + } else { + return RESULT_TX_TIMEOUT; + } + } + return RESULT_OK; +} + +char uart_tx_cmd(char* tx_buff, char* rs_buff, int size, int wait_ms) +{ + char resp = RESULT_OK; + char rcv, *buff; + char lstr[LSTR_SIZE]; + int lstrp = 0; + buff = rs_buff; + buff[size-1] = 0; // mark last byte of buffer as end of string + size--; + uart_empty_rs(); + + if (uart_tx_buffer(tx_buff, strlen(tx_buff)) == RESULT_OK) { + while (1) { + if (uart_wait_rs(wait_ms)) { + rcv = uart_read(REG_RBR); + if (size > 0 && rcv != CR) { // ignore CR + *buff++ = rcv; + size--; + } + if (rcv == CR || rcv == LF) { + + lstr[lstrp] = 0; + + if (strcmp(lstr, "OK")==0) { + break; + } + + if (strcmp(lstr, "ERROR")==0) { + resp = RESULT_ERROR; + break; + } + + if (strcmp(lstr, "FAIL")==0) { + resp = RESULT_FAIL; + break; + } + + lstrp = 0; + } + + if (lstrp 0) { + *buff = 0; // mark end of string + } +#ifdef DEBUG + printf(": '%s'\n", lstr); +#endif + } else { +#ifdef DEBUG + printf("Cmd transmit error, TR not ready!\n"); +#endif + return RESULT_TX_TIMEOUT; + } + return resp; +} + + +void uart_empty_rs() +{ + uart_write(REG_FCR, FCR_TR14 | FCR_RESET_RX | FCR_FIFO); +} + +char uart_wait_rs(wait_ms) +int wait_ms; +{ + char res; + unsigned loops; + + if (wait_ms<0) { + loops = 1; + } else { + loops = wait_ms; + } + + while (loops>0) { + res = uart_read(REG_LSR) & LSR_DR; + if (res){ + break; + } + loops--; + util_delay(1); + } + + return loops>0; +} + + + +void esp_reset(char full) +{ + isa_open(); + if (full) { + outb(REG_MCR, MCR_RST | MCR_RTS) // 0110b ESP -PGM=1, -RST=0, -RTS=0 + util_delay(20); + } + outb(REG_MCR, MCR_AFE | MCR_RTS) // 0x0202 -RST = 1 -RTS=0 AutoFlow enabled + isa_close(); + if (full) { + util_delay(1000); + } +} + diff --git a/sources/esplib.h b/sources/esplib.h new file mode 100644 index 0000000..2513926 --- /dev/null +++ b/sources/esplib.h @@ -0,0 +1,148 @@ +/* +================================================ + Header file for Sprinter-WiFi ISA Card Library + Author: Roman A. Boykov + License: BSD 3-Clause +================================================ + */ + +#include "espdef.h" + +#ifndef __ESPLIB_H +#define __ESPLIB_H + + +#define DEBUG + +/* Size of buffer for last response line */ +#define LSTR_SIZE 20 +#define LF 0x0A +#define CR 0x0D + +enum CMD_RESULT { RESULT_OK, RESULT_ERROR, RESULT_FAIL, RESULT_TX_TIMEOUT, RESULT_RS_TIMEOUT, RESULT_CONNECTED, RESULT_NOT_CONNECTED, RESULT_ENABLED, RESULT_DISABLED }; + + + + /* + Small delay + delay - number of ms, if delay=0, then 20ms + */ +void util_delay(unsigned delay_ms); + +/* + Init ISA card + Result: + 0 - Not Found + 1 - Sprinter WiFi Found and initialized +*/ +char isa_init(void); + +/* + Reset ISA device +*/ +void isa_reset(void); + +/* + Open access to ISA ports as memory +*/ +void isa_open(void); + +/* + Close access to ISA ports +*/ +void isa_close(void); + + +char isa_get_slot(void); + +/* + Find UART device TL16C550 + return 0 - Not found +*/ +char find_wifi(void); + +/* + Init UART device TL16C550 + Input: + slot - ISA Slot number +*/ +void uart_init(void); + +/* + Read TL16C550 register + Input: + reg - Port number + Output: + value from register +*/ +char uart_read(unsigned reg); + +/* + Write TL16C550 register + Input: + reg - Port number + value - value to write toregister +*/ +void uart_write(unsigned reg, char value); + +/* + Wait for transmitter ready + Output: + 0 - tr not ready, !=0 - tr ready +*/ +char uart_wait_tr(void); + +/* + Empty receiver FIFO buffer +*/ +void uart_empty_rs(void); + +/* + Wait byte in receiver fifo + Input: + wait_ms milliseconds to wait response + Output: + 0 - fifo still empty, !=0 - receiver fifo is not empty +*/ +char uart_wait_rs(int wait_ms); + + +/* + Transmitt one byte + Input: + byte to transmit + Output: + 0 - failure, transmitter not ready, !=0 - success +*/ +char uart_tx_byte(char byte); + +/* + Transmitt bytes + Input: + tbuff - pointer to buffer + size - number of bytes to transmitt from buffer + Output: + RESULT_OK if ok and RESULT_TX_TIMEOUT otherwise +*/ +char uart_tx_buffer(char* tbuff, int size); + +/* + Transmitt AT-command to ESP and wait response + Input: + tx_buff - command, zero ended string + rs_buff - buffer to place response from ESP + size - size of response buffer + wait_ms - time to wait AT-command response from ESP +*/ +char uart_tx_cmd(char* tx_buff, char* rs_buff, int size, int wait_ms); + + +// MODULE esp + +/* + Reset ESP device +*/ +void esp_reset(char full); + + +#endif \ No newline at end of file diff --git a/sources/wset.c b/sources/wset.c new file mode 100644 index 0000000..2b1fe1e --- /dev/null +++ b/sources/wset.c @@ -0,0 +1,653 @@ +/* +===================================================== + ESP Setup program for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +===================================================== +*/ + +#include +#include +#include +#include +#include "esplib.h" +#include "wset.h" + +char* set_speed = "AT+UART_CUR=115200,8,1,0,3\r\n\0"; +char* echo_off = "ATE0\r\n\0"; +char* station_mode = "AT+CWMODE=1\r\n\0"; +char* no_sleep = "AT+SLEEP=0\r\n\0"; +char* check_conn_ap_cmd = "AT+CWJAP?\r\n\0"; +char* cwlap_opt = "AT+CWLAPOPT=1,23\r\n\0"; +char* get_ap_list_cmd = "AT+CWLAP\r\n\0"; +char* get_dhcp_cmd = "AT+CWDHCP?\r\n\0"; +char* set_dhcp_cmd = "AT+CWDHCP=1,1\r\n\0"; +char* get_ip_cmd = "AT+CIPSTA?\r\n\0"; + +char* cmd_end = "\r\n\0"; + +char rs_buff[RS_BUFF_SIZE]; + +/* + Encription mode names +*/ +char* ecn[] = {"Open", "WEP", "WPA_PSK", "WPA2_PSK", "WPA_WPA2_PSK", + "WPA2_ENTERPRISE", "WPA3_PSK", "WPA2_WPA3_PSK"}; + +/* + Cause of connection errors +*/ +char* conn_fault[] = {"None", "Connection timeout", "Wrong password", + "Can not find network", "Connection failed"}; + +void init_console() +{ + clrscr(); +} + +/* + Init basic parameters of ESP +*/ +void init_esp(void) { +#ifdef DEBUG + printf("Echo off"); +#endif + uart_tx_cmd(echo_off, NULL, 0, 100); +#ifdef DEBUG + printf("Station mode"); +#endif + uart_tx_cmd(station_mode, NULL, 0, 100); +#ifdef DEBUG + printf("No sleep"); +#endif + uart_tx_cmd(no_sleep, NULL, 0, 100); +#ifdef DEBUG + printf("Setup uart"); +#endif + uart_tx_cmd(set_speed, NULL, 0, 500); +#ifdef DEBUG + printf("Setup options"); +#endif + uart_tx_cmd(cwlap_opt, NULL, 0, 100); + +} + + +/* + Check connection to AP + Input: + ssid - pointer to buffer for Network ID + size - size of ssid buffer + Output: + RESULT_CONNECTED - if Ok + ssid - ID of network with which connection established + RESULT_NOT_CONNECTED - if no connections +*/ +char esp_check_conn_ap(char* ssid, int size) +{ + char *eol, *eos; + char res; + int len; + + res = uart_tx_cmd(check_conn_ap_cmd, rs_buff, RS_BUFF_SIZE, 2000); + if (res == RESULT_OK) { + eol = (char *) strchr(rs_buff, LF); + if (eol) { + len = eol - rs_buff; + if (len>8 && strncmp("+CWJAP:\"", rs_buff,8) == 0) { + res = RESULT_CONNECTED; + if (ssid != NULL) { + eos = (char *) strchr(rs_buff+8, '"'); + if (eos) { + len = eos-rs_buff-8; + if (len > (size-1)) { + len = size-1; + } + strncpy(ssid, rs_buff+8, len); + *(ssid+len) = 0; + } + } + } else { + if (strncmp("No AP",rs_buff,5) == 0) { + res = RESULT_NOT_CONNECTED; + } else { + printf("Unknown ESP response:\n%s\n", rs_buff); + res = RESULT_ERROR; + } + } + } else { + res = RESULT_NOT_CONNECTED; + } + } + return res; +} + +/* + Parse info about Access Point + Input: + buff - pointer to line in response with info about AP + item - pointer to structure with info about AP + Output: + RESULT_OK - if parsing complete without errors + item - pointer with filled info about AP +*/ +char parse_ap_info(char *buff, struct ap_info *item) +{ + int res; + char *bol, *eol; // pointers to begin and end of line fragment + bol = buff; + eol = (char *) strchr(bol, ','); + if (eol != NULL) { + *eol = 0; + item->ecn = atoi(bol); + bol = eol+2; + eol = (char *) strchr(bol, '"'); + if (eol != NULL) { + *eol = 0; + item->ssid = bol; + bol = eol+2; + eol = (char *) strchr(bol, ','); + if (eol) { + *eol = 0; + item->rssi = atoi(bol); + res = RESULT_OK; + } else { + res = RESULT_ERROR; + } + } else { + res = RESULT_ERROR; + } + } else { + res = RESULT_ERROR; + } + return res; +} + +/* + Get list of Access Points (Wireless networks) + Input: + ap_list - array to put info about AP + size - size of array ap_list + Output: + ap_list - array with AP + result_size - number of found AP in ap_list + */ +char esp_get_ap_list(struct ap_info ap_list[], int size, int *result_size) +{ + char *bol, *eol, *buff; + char res; + int ctr; + ctr = 0; + + res = uart_tx_cmd(get_ap_list_cmd, rs_buff, RS_BUFF_SIZE, 5000); + if (res == RESULT_OK) { + buff = rs_buff; + while (buff < rs_buff + RS_BUFF_SIZE && ctr < size) { + // search begin of response line + bol = (char *) strstr(buff, "+CWLAP:("); + if (bol) { + // search end of response line + eol = (char *) strchr(buff, LF); + if (eol) { + *eol = 0; // mark end of line + buff = eol+1; + if ( parse_ap_info(bol+8, &ap_list[ctr]) != RESULT_OK ) { + printf("Can not parse AP Item!\n%s\n", bol+8); + break; + } else { + ctr++; + } + } else { + buff += 8; + } + } else { + break; + } + } + *result_size = ctr; + + } + + return res; +} + + +/* + Try to connect to specified Wireles network + Input: + ssid - Network identifier + passwd - password to use + Output: + RESULT_OK - if all Ok + RESULT_FAIL - if error and message with details displayed +*/ +char connect_network(char *ssid, char *passwd) { + char *resp, *cmd, *bol, *eol; + char res, code; + + resp = (char *)malloc(512); + cmd = (char *)malloc(512); + if (resp == NULL || cmd == NULL) { + printf("CN Out of memory!\n"); + exit(1); + } + + strset(cmd, 0); + sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, passwd); + cmd = strcat(cmd, cmd_end); + res = uart_tx_cmd(cmd, resp, 512, 1000); + if (res != RESULT_OK) { + if (res == RESULT_FAIL) { + bol = (char *) strstr(resp, "+CWJAP:"); + if (bol) { + bol += 7; + eol = (char *) strchr(bol, LF); + if (eol) { + *eol = 0; + code = atoi(bol); + if (code>0 && code<5) { + printf("%s", conn_fault[code]); + } else { + printf("Unknown error code: %d; '%s'", code, bol); + } + } else { + printf("no EOL\n"); + } + } else { + printf("no +cwjap\n %s", resp); + } + } + } + + free(resp); + free(cmd); + + return res; +} + +/* + Output main menu to select user action +*/ +char select_main_menu(void) +{ + char select; + printf("\n1 - Select WiFi Network\n"); + printf("2 - Configure IP parameters\n"); + printf("3 - Display info\n0 - Exit\n"); + while (1) { + printf("\nEnter number 0..3: "); + scanf("%1d", &select); + fflush(stdin); + if (select >= 0 && select < 4) { + break; + } + } + return select; +} + +/* + Output list of available Wireles networks. + Try to connect to network if required by user. +*/ +void select_network(void) +{ + char *passwd, yn, res; + int ap_list_size, ctr, select; + struct ap_info ap_list[AP_LIST_SIZE]; + + passwd = (char *)malloc(21); + if (passwd == NULL) { + printf("SN Out of memory!"); + exit(1); + } + + while (1) { +#ifdef DEBUG + printf("Get Network List"); +#endif + esp_get_ap_list(ap_list, AP_LIST_SIZE, &ap_list_size); + + printf("Select Wireless network to connect: \n\n"); + for (ctr = 0; ctr< ap_list_size; ctr++) { + printf("%d - %s, %ddBm, %s\n",ctr+1, ap_list[ctr].ssid, + ap_list[ctr].rssi, ecn[ap_list[ctr].ecn]); + } + + while (1) { + printf("\nEnter number 1..%d or 0 to exit: ", ap_list_size); + scanf("%2d", &select); + fflush(stdin); + if (select >= 0 && select <= ap_list_size) { + break; + } + } + if (select == 0) { + break; + } + select--; + + printf("Enter password for %s: ", ap_list[select].ssid); + scanf("%20s", passwd); + fflush(stdin); + + printf("Connecting to Network %s: ", ap_list[select].ssid); + res = connect_network(ap_list[select].ssid, passwd); + if (res != RESULT_OK) { + printf("\nTry again Y|n?", ap_list[select].ssid); + scanf("%c",&yn); + fflush(stdin); + if (yn == 'N' || yn == 'n') { + break; + } + } else { + break; + } + } + + free(passwd); +} + +/* + Get info about AP with which communication is established +*/ +void get_current_ap(void) +{ + char found, *ssid; + ssid = (char *)malloc(128); + if (ssid != NULL) { +#ifdef DEBUG + printf("Get WiFi Network"); +#endif + found = esp_check_conn_ap(ssid, 128); + if (found == RESULT_CONNECTED) { + printf("Connected to Wireles net: %s\n", ssid); + } else if (found == RESULT_NOT_CONNECTED) { + printf("Not connected to Wireles net!\n"); + } else { + printf("CAP Unexpected error: %d\n", found); + exit(1); + } + free(ssid); + } else { + printf("CAP Out of memory!"); + exit(1); + } +} + +char set_dhcp_mode(void) +{ +#ifdef DEBUG + printf("Set DHCP mode"); +#endif + return uart_tx_cmd(set_dhcp_cmd, rs_buff, RS_BUFF_SIZE, 1000); +} + +char is_byte(char *byte) +{ + int i; + i = atoi(byte); + return (i >= 0 && i <= 255); +} + +#define ADDR_LENGTH 16 + +/* + Check string to looks like IP address + Input: + ip_str - pointer to string with IP + Output: + 1 - look like IP + 0 - not +*/ +char is_ip_addr(char *ip_str) +{ + char *p1, *p2, *p3, *ip; + char res; + res = 0; + if (strlen(ip_str) < ADDR_LENGTH) { + ip = malloc(ADDR_LENGTH); + if (ip == NULL) { + printf("IIP Out of memory!\n"); + exit(1); + } + strcpy(ip, ip_str); + p1 = (char *) strchr(ip, '.'); + if (p1) { + p2 = (char *) strchr(p1+1, '.'); + if (p2) { + p3 = (char *) strchr(p2+1, '.'); + if (p3) { + *p1 = 0; + *p2 = 0; + *p3 = 0; + res = (is_byte(ip) && is_byte(p1+1) && + is_byte(p2+1) && is_byte(p3+1)); + } + } + } + free(ip); + } + return res; +} + + +void enter_ip(char *message, char *ip) +{ + char is_ip; + do { + printf("Enter %s: ", message); + scanf("%15s", ip); + fflush(stdin); + is_ip = is_ip_addr(ip); + if (!is_ip) { + printf("Invalid address, not in nnn.nnn.nnn.nnn format! Where nnn=0..255\n"); + } + } while (!is_ip); +} + +char set_ip_config(char *ip, char *gateway, char *netmask) +{ + char res, *resp, *cmd; + resp = (char *)malloc(512); + cmd = (char *)malloc(256); + if (resp == NULL || cmd == NULL) { + printf("SIP Out of memory!\n"); + exit(1); + } + + strset(cmd, 0); + sprintf(cmd, "AT+CIPSTA=\"%s\",\"%s\",\"%s\"", ip, gateway, netmask); + cmd = strcat(cmd, cmd_end); +#ifdef DEBUG + printf("Set ip config"); +#endif + res = uart_tx_cmd(cmd, resp, 512, 2000); + if (res != RESULT_OK) { + +/* + if (res == RESULT_FAIL) { + bol = (char *) strstr(resp, "+CWJAP:"); + if (bol) { + } + } +*/ + } + free(cmd); + free(resp); + return res; +} + +/* + Allow the user to select DHCP or manual IP-configuration +*/ +void config_ip(void) +{ + char select, *ip, *netmask, *gateway; + ip = malloc(ADDR_LENGTH); + netmask = malloc(ADDR_LENGTH); + gateway = malloc(ADDR_LENGTH); + if (ip == NULL || netmask == NULL || gateway == NULL) { + printf("CIP Out of memory!\n"); + exit(1); + } + strnset(ip,0,ADDR_LENGTH); + strnset(netmask,0,ADDR_LENGTH); + strnset(gateway,0,ADDR_LENGTH); + + printf("Select mode:\n1 - Automatic via DHCP\n"); + printf("2 - Specify IP-address, netmask and gateway\n0 - Exit.\n"); + + while (1) { + printf("\nEnter number 0..2: "); + scanf("%1d", &select); + fflush(stdin); + if (select >= 0 && select < 3) { + break; + } + } + + switch (select) { + case 1 : { + set_dhcp_mode(); + break; + } + case 2 : { + enter_ip("IP-address", ip); + enter_ip("Gateway", gateway); + enter_ip("Net mask", netmask); + set_ip_config(ip, gateway, netmask); + break; + } + } + free(ip); + free(gateway); + free(netmask); +} + +/* + Get state of DHCP + Output: + RESULT_ENABLED - if DHCP enabled + RESULT_DISABLED - DHCP is disabled +*/ +char get_dhcp_state(void) { + char *bol, *eol, res; + +#ifdef DEBUG + printf("Get DHCP info"); +#endif + res = uart_tx_cmd(get_dhcp_cmd, rs_buff, RS_BUFF_SIZE, 1000); + if (res == RESULT_OK) { + bol = (char *) strstr(rs_buff, "+CWDHCP:"); + if (bol) { + bol += 8; + eol = (char *) strchr(bol, LF); + if (eol) { + *eol = 0; + if (atoi(bol) & 0x02) { // for new AT versions, it is changed to 0x01 + printf("DHCP enabled\n"); + res = RESULT_ENABLED; + } else { + printf("DHCP disabled\n"); + res = RESULT_DISABLED; + } + } + } else { + printf("No +CWDHCP!\n %s", rs_buff); + } + } + return res; +} + +/* + Display configurtion of IP adresses +*/ +void get_ip_config(void) +{ + char *bol, *eol, *name, res, ctr; + +#ifdef DEBUG + printf("Get IP config"); +#endif + res = uart_tx_cmd(get_ip_cmd, rs_buff, RS_BUFF_SIZE, 1000); + bol = rs_buff; + if (res == RESULT_OK) { + ctr = 0; + while (ctr++ < 4) { + bol = (char *) strstr(bol, "+CIPSTA:"); + if (bol) { + bol += 8; + eol = (char *) strchr(bol, ':'); + if (eol) { + *eol = 0; + name = bol; + bol = eol+1; + eol = (char *) strchr(bol, LF); + if (eol) { + *eol = 0; + printf("%s: %s\n", name, bol); + } + bol = eol+1; + } + } else { + break; + } + } + } +} + +/* + Display currenf Info, configured in ESP +*/ +void display_info(void) +{ + printf("\n--- Current info ---\n"); + get_current_ap(); + get_dhcp_state(); + get_ip_config(); + printf("\n--------------------\n"); +} + +/* + -------------------------------------------------------------------------- +*/ +void main() +{ + char found; + + clrscr(); + + printf(MSG_START); + found = isa_init(); + if (!found) { + printf(MSG_NOT_FOUND); + exit(EXIT_FAILURE); + } + printf(MSG_FOUND, isa_get_slot()); + + uart_init(); + esp_reset(1); + init_esp(); + + while (1) { + switch(select_main_menu()) { + case 1: { + select_network(); + break; + } + case 2: { + config_ip(); + break; + } + case 3: { + display_info(); + break; + } + default: { + printf("Bye!\n"); + exit(0); + } + } + } + +} \ No newline at end of file diff --git a/sources/wset.h b/sources/wset.h new file mode 100644 index 0000000..2469c3e --- /dev/null +++ b/sources/wset.h @@ -0,0 +1,25 @@ +/* +==================================================== + Setup program for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +==================================================== +*/ + +#ifndef __WSET_H +#define __WSET_H + +#define MSG_START "Setup for Sprinter WiFi Card (ESP8266)\nv1.0.0 by Romych (Boykov Roman)\n\n",0 +#define MSG_NOT_FOUND "No Sprinter WiFi card found!\n" +#define MSG_FOUND "Sprinter WiFi card found at slot: %d\n" + +#define RS_BUFF_SIZE 4098 +#define AP_LIST_SIZE 20 + +struct ap_info { + char ecn; + char* ssid; + int rssi; +}; + +#endif diff --git a/sources/wterm.c b/sources/wterm.c new file mode 100644 index 0000000..63683e0 --- /dev/null +++ b/sources/wterm.c @@ -0,0 +1,159 @@ +/* +===================================================== + Simple terminal program for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +===================================================== +*/ + + +#include +#include +#include +#include +#include "esplib.h" +#include "wterm.h" + +#define RS_BUFF_SIZE 2048 + +char* quit = "QUIT\r"; +char* version = "AT+GMR\r\n\0"; +char* set_speed = "AT+UART_CUR=115200,8,1,0,3\r\n\0"; +char* echo_off = "ATE0\r\n\0"; +char* station_mode = "AT+CWMODE=1\r\n\0"; +char* no_sleep = "AT+SLEEP=0\r\n\0"; +char* check_conn_ap_cmd = "AT+CWJAP?\r\n\0"; +char rs_buff[RS_BUFF_SIZE]; + +void init_console() +{ + clrscr(); +} + +char esp_check_conn_ap(char* ssid, int size) +{ + char *eol, *eos; + char res; + int len; + + res = uart_tx_cmd(check_conn_ap_cmd, rs_buff, RS_BUFF_SIZE, 2000); + if (res == RESULT_OK) { + eol = (char *) strchr(rs_buff, LF); + if (eol) { + len = eol - rs_buff; + printf(" found at: %d\n", len); + if (len>8 && strncmp("+CWJAP:\"", rs_buff,8) == 0) { + res = RESULT_CONNECTED; + if (ssid != NULL) { + eos = (char *) strchr(rs_buff+8, '"'); + if (eos) { + printf("end bracket found at %d\n", eos-rs_buff); + len = eos-rs_buff-8; + if (len > (size-1)) { + len = size-1; + } + strncpy(ssid, rs_buff+8, len); + *(ssid+len) = 0; + } + } + } else { + if (strncmp("No AP",rs_buff,5) == 0) { + res = RESULT_NOT_CONNECTED; + } else { + printf("Unknown ESP response:\n%s\n", rs_buff); + res = RESULT_ERROR; + } + } + } else { + printf(" not found!\n"); + res = RESULT_NOT_CONNECTED; + } + } + return res; +} + +void init_esp(void) { +#ifdef DEBUG + printf("Echo off"); +#endif + uart_tx_cmd(echo_off, NULL, 0, 100); +#ifdef DEBUG + printf("Station mode"); +#endif + uart_tx_cmd(station_mode, NULL, 0, 100); +#ifdef DEBUG + printf("No sleep"); +#endif + uart_tx_cmd(no_sleep, NULL, 0, 100); +#ifdef DEBUG + printf("Setup uart"); +#endif + uart_tx_cmd(set_speed, NULL, 0, 500); +} + + +void main() +{ + char found, q, tx_data, rx_data; + + clrscr(); + + printf(MSG_START); + found = isa_init(); + if (!found) { + printf(MSG_NOT_FOUND); + exit(EXIT_FAILURE); + } + printf(MSG_FOUND, isa_get_slot()); + + uart_init(); + esp_reset(1); + init_esp(); + + printf(MSG_HLP); + uart_empty_rs(); + rx_data = 0; + q = 0; + + do { + if(kbhit()) { + tx_data = getch(); + + // check for QUIT + if (q <= 4 && tx_data == quit[q]) { + q++; + if (q > 4) break; + } else q = 0; + + if ((tx_data == CR) || (tx_data > 0x1f)) putchar(tx_data); + uart_tx_byte(tx_data); + if (tx_data == CR) { + putchar(LF); + uart_tx_byte(LF); + } + if (tx_data == LF) { + uart_tx_byte(CR); + } + } + + while (1) { + rx_data = uart_read(REG_LSR); + if (rx_data & 0x80) { + printf("Receiver error LSR: %2x\n", (unsigned char)rx_data); + uart_empty_rs(); + break; + } else { + if (rx_data & 0x01) { + rx_data = uart_read(REG_RBR); + if ((rx_data == CR)||(rx_data > 0x1f)) putchar(rx_data); + if (rx_data == CR) putchar(LF); + } else { + break; + } + } + } + + } while(q < 5); + printf("\nBye!\n"); + +} diff --git a/sources/wterm.h b/sources/wterm.h new file mode 100644 index 0000000..d0b0079 --- /dev/null +++ b/sources/wterm.h @@ -0,0 +1,17 @@ +/* +==================================================== + Simple terminal program for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +==================================================== +*/ + +#ifndef __WTERM_H +#define __WTERM_H + +#define MSG_START "Terminal for Sprinter WiFi Card (ESP8266)\nv1.0.0 by Romych (Boykov Roman)\n\n",0 +#define MSG_NOT_FOUND "No Sprinter WiFi card found!\n" +#define MSG_FOUND "Sprinter WiFi card found at slot: %d\n" +#define MSG_HLP "\nEnter ESP AT comand or QUIT to close terminal.\n" + +#endif \ No newline at end of file diff --git a/sources/wtime.c b/sources/wtime.c new file mode 100644 index 0000000..459250e --- /dev/null +++ b/sources/wtime.c @@ -0,0 +1,302 @@ +/* +===================================================== + NTP Time program for Sprinter-WiFi ISA Card + Author: Roman A. Boykov + License: BSD 3-Clause +===================================================== +*/ + +#include +#include +#include +#include +#include "esplib.h" +#include "wtime.h" + +char* set_speed = "AT+UART_CUR=115200,8,1,0,3\r\n\0"; +char* echo_off = "ATE0\r\n\0"; +char* get_sntp_cmd = "AT+CIPSNTPCFG?\r\n\0"; +char* set_sntp_cmd = "AT+CIPSNTPCFG=1,%d\r\n\0"; +char* get_sntp_time_cmd = "AT+CIPSNTPTIME?\r\n\0"; + +char* cmd_end = "\r\n\0"; +char rs_buff[RS_BUFF_SIZE]; + +char* m_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +/* + Get time shift from TZ environment variable + Output: + -11..13 - time shift from GMT +*/ +char get_timezone(void) +{ + char *tze, *gmtp, ss, off; + tze = getenv("TZ"); + if (tze == NULL) { + tze = getenv("tz"); + } + if (tze == NULL) { + printf("TZ environment variable not found, default value GMT+3\n"); + return 3; + } else { + gmtp = (char *) strstr(tze, "GMT"); + if (gmtp == tze) { + ss = *(tze+3); // sign symbol + if (ss == '+' || ss == '-') { + off = atoi(tze+4); + if (off>-12 && off<14) { + return off; + } + } + } + printf("TZ environment variable will have format GMT+nn or GMT-nn, nn=[-11..13]\nUsed default value, GMT+3\n"); + return 3; + } + +} + + + +/* + Get time via SNTP protocol +*/ +char get_sntp_time(char *time_str) +{ + char *bol, *eol, res; + +#ifdef DEBUG + printf("Get SNTP time"); +#endif + uart_empty_rs(); + res = uart_tx_cmd(get_sntp_time_cmd, rs_buff, RS_BUFF_SIZE, 1000); + if (res == RESULT_OK) { + bol = (char *) strstr(rs_buff, "+CIPSNTPTIME:"); + if (bol) { + bol += 13; + eol = (char *) strchr(bol, LF); + if (eol) { + *eol = 0; + //printf("Net time %s\n", bol); + strcpy(time_str, bol); + } + } else { + printf("No +CIPSNTPTIME!\n %s", rs_buff); + } + } + return res; +} + + + +/* + Get SNTP configuration state + Output: + RESULT_ENABLED - if SNTP enabled and configured + RESULT_DISABLED - SNTP is disabled +*/ +char get_sntp_state(void) +{ + char *bol, *eol, *comma, res, en, offset; + uart_empty_rs(); +#ifdef DEBUG + printf("Get SNTP info"); +#endif + res = uart_tx_cmd(get_sntp_cmd, rs_buff, RS_BUFF_SIZE, 1000); + if (res == RESULT_OK) { + bol = (char *) strstr(rs_buff, "+CIPSNTPCFG:"); + if (bol) { + bol += 12; + en = *bol; + if (en == '0') { + res = RESULT_DISABLED; +#ifdef DEBUG + printf("SNTP Disabled\n"); +#endif + } + if (en == '1') { + res = RESULT_ENABLED; +#ifdef DEBUG + printf("SNTP Enabled, TZ "); + comma = (char *) strchr(bol, ','); + if (comma) { + bol = comma+1; + eol = (char *) strchr(bol, ','); + if (eol) { + *eol = 0; + offset = atoi(bol); + if (offset > 0) { + printf("UTC+%d\n", offset); + } else { + printf("UTC%d\n", offset); + } + } + } +#endif + } + } else { + printf("No +CIPSNTPCFG!\n %s", rs_buff); + } + } + return res; +} + +char enable_sntp(void) +{ + char *cmd_buff, res, time_shift; + time_shift = 3; + cmd_buff = malloc(256); + if (cmd_buff == NULL) { + printf("ES Out of memory!\n"); + exit(1); + } + + time_shift = get_timezone(); + // turn SNTP On + + sprintf(cmd_buff, set_sntp_cmd, time_shift); +#ifdef DEBUG + printf("Enable SNTP"); +#endif + uart_empty_rs(); + res = uart_tx_cmd(cmd_buff, NULL, 0, 100); + free(cmd_buff); + return res; +} + +/* + Init basic parameters of ESP +*/ +void init_esp(void) { + uart_empty_rs(); +#ifdef DEBUG + printf("Echo off"); +#endif + uart_tx_cmd(echo_off, NULL, 0, 100); +#ifdef DEBUG + printf("Setup uart"); +#endif + uart_tx_cmd(set_speed, NULL, 0, 500); +} + +/* + Parse text string rsponse from ESP to structure + Input: + time_str - pointer to string like 'Mon Mar 06 10:11:12 2023' + ti - pointer to result + Output: + ti - filled winh parsed values + RESULT_OK - if no errors, + RESULT_ERROR - can not parse, illegal format +*/ +char parse_time(char *time_str, struct time_info *ti) +{ + char *p[4], cnt, *ptr, mon; + ptr = time_str; + cnt = 0; + // Find all spaces + while (*ptr != 0 && cnt<4) { + if (*ptr == ' ') { + p[cnt++] = ptr+1; + *ptr = 0; + } + ptr++; + } + // will be 4 space separators + if (cnt != 4) { + printf("Illegal time format!\n"); + return 0; + } + // convert month name to number + mon = 0; + for (mon=0; mon<12; mon++) { + if (strcmp(p[0],m_name[mon]) == 0) { + break; + } + } + if (mon == 12) { + printf("Month not found: %s\n", p[0]); + return RESULT_ERROR; + } + // erase ':' in time + *(p[2]+2) = 0; + *(p[2]+5) = 0; + // fill result + ti->mon = mon; + ti->day = atoi(p[1]); + ti->year = atoi(p[3]); + ti->h = atoi(p[2]); + ti->m = atoi(p[2]+3); + ti->s = atoi(p[2]+6); + return RESULT_OK; +} + + + +/* + -------------------------------------------------------------------------- +*/ +void main() +{ + char res, sntp_status, *time_str, delay; + struct time_info ti; + + + clrscr(); + + printf(MSG_START); + res = isa_init(); + if (!res) { + printf(MSG_NOT_FOUND); + exit(EXIT_FAILURE); + } + printf(MSG_FOUND, isa_get_slot()); + uart_init(); + esp_reset(0); + init_esp(); + + + printf("Time shift: %d\n", get_timezone()); + + + + sntp_status = get_sntp_state(); + + if (sntp_status == RESULT_DISABLED) { + res = enable_sntp(); + if (res != RESULT_OK) { + printf("Failed to enabable SNTP protocol! Error: %d;\n", res); + exit(1); + } + sntp_status = get_sntp_state(); + printf("Wait for apply changes"); + for (delay = 0; delay<10; delay++) { + printf("."); util_delay(500); + } + printf("\n"); + } + + if (sntp_status == RESULT_ENABLED) { + time_str = malloc(1024); + if (time_str == NULL) { + printf("TS Out of memory!\n"); + exit(2); + } + + res = get_sntp_time(time_str); + if (res == RESULT_OK) { + printf("Net time %s\n", time_str); + } else { + printf("Failed to get time! Error: %d;\n", res); + } + + if ( parse_time(time_str, &ti) == RESULT_OK ) { + printf("Day: %d; Year: %d", ti.day, ti.year); + printf(" Time %d:%d:%d\n", ti.h, ti.m, ti.s); + } else { + printf("Error parsing date-time string: '%s'!\n", time_str); + } + free(time_str); + } + +} \ No newline at end of file diff --git a/sources/wtime.h b/sources/wtime.h new file mode 100644 index 0000000..d57c210 --- /dev/null +++ b/sources/wtime.h @@ -0,0 +1,28 @@ +/* +==================================================== + NTP Time program for Sprinter-WiFi ISA Card + Header file + Author: Roman A. Boykov + License: BSD 3-Clause +==================================================== +*/ + +#ifndef __WTIME_H +#define __WTIME_H + +#define MSG_START "NTP Time for Sprinter WiFi Card (ESP8266)\nv1.0.0 by Romych (Boykov Roman)\n\n",0 +#define MSG_NOT_FOUND "No Sprinter WiFi card found!\n" +#define MSG_FOUND "Sprinter WiFi card found at slot: %d\n" + +#define RS_BUFF_SIZE 1024 + +struct time_info { + char mon; + char day; + char h; + char m; + char s; + int year; +}; + +#endif