Initial commit

This commit is contained in:
Roman Boykov 2023-03-07 17:15:12 +03:00
commit b3c9e21fd5
11 changed files with 1765 additions and 0 deletions

29
LICENSE Normal file
View File

@ -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.

4
README.md Normal file
View File

@ -0,0 +1,4 @@
ESPKit for Sprinter computer
============================
Библиотеки и приложения для работы с картой Sprinter-WiFi на базе модуля ESP8266.

86
sources/espdef.h Normal file
View File

@ -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

314
sources/esplib.c Normal file
View File

@ -0,0 +1,314 @@
/*
==================================================
Implementation of Sprinter-WiFi ISA Card Library
Author: Roman A. Boykov
License: BSD 3-Clause
==================================================
*/
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <string.h>
#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<LSTR_SIZE && rcv != CR && rcv != LF) {
lstr[lstrp++] = rcv;
}
} else {
#ifdef DEBUG
printf("No ansver to CMD, RCVR empty! %s\n", lstr);
#endif
return RESULT_RS_TIMEOUT;
}
}
if (uart_wait_rs(1)) {
rcv = uart_read(REG_RBR); // read last LF
}
if (size > 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);
}
}

148
sources/esplib.h Normal file
View File

@ -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

653
sources/wset.c Normal file
View File

@ -0,0 +1,653 @@
/*
=====================================================
ESP Setup program for Sprinter-WiFi ISA Card
Author: Roman A. Boykov
License: BSD 3-Clause
=====================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#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);
}
}
}
}

25
sources/wset.h Normal file
View File

@ -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

159
sources/wterm.c Normal file
View File

@ -0,0 +1,159 @@
/*
=====================================================
Simple terminal program for Sprinter-WiFi ISA Card
Author: Roman A. Boykov
License: BSD 3-Clause
=====================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#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("<LF> 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("<LF> 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");
}

17
sources/wterm.h Normal file
View File

@ -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

302
sources/wtime.c Normal file
View File

@ -0,0 +1,302 @@
/*
=====================================================
NTP Time program for Sprinter-WiFi ISA Card
Author: Roman A. Boykov
License: BSD 3-Clause
=====================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#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);
}
}

28
sources/wtime.h Normal file
View File

@ -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