Add DSS sources to separate folder

This commit is contained in:
boykovra 2024-07-12 16:04:26 +03:00
parent b3c9e21fd5
commit d65eba132e
25 changed files with 2687 additions and 316 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*.exe
*.sld
*.labels
*.tmp
*.bak
*.lst
*.list
.tmp/

View File

@ -1,4 +1,12 @@
ESPKit for Sprinter computer
============================
Библиотеки и приложения для работы с картой Sprinter-WiFi на базе модуля ESP8266.
Библиотека и приложения для карты Sprinter-WiFi, ISA8-карты на модуле ESP8266 (ESP12-E,ESP12F).
Исходные коды для [Sprinter DSS](sources/DSS) и для [MS-DOS](sources/DOS)
[Sprinter-WiFi](https://github.com/romychs/SprinterESP)
[Спринтер в Телеграм](https://t.me/zx_sprinter)
[Спринтер в Web](https://www.sprinter.ru/)

339
sources/DOS/esplib.c Normal file
View File

@ -0,0 +1,339 @@
/*
==================================================
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);
}
}

View File

@ -12,6 +12,6 @@
#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"
#define MSG_HLP "\nEnter ESP AT command or QUIT to close terminal.\n"
#endif

173
sources/DSS/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,173 @@
{
"version": "0.2.0",
"configurations": [
// {
// "type": "dezog",
// "request": "launch",
// "name": "WSET Internal Simulator",
// "remoteType": "zsim",
// "zsim": {
// "visualMemory": true,
// "memoryModel": "CUSTOM",
// "customMemory": {
// "slots": [
// {
// "name": "PAGE0",
// "range": ["0x0000","0x3FFF"],
// "banks": [{"index": [0, 255]}],
// "initialBank": 0
// },
// {
// "name": "PAGE1",
// "range": ["0x4000","0x7FFF"],
// "banks": [{"index": [0, 255]}],
// "initialBank": 1
// },
// {
// "name": "PAGE2",
// "range": ["0x8000","0xBFFF"],
// "banks": [{"index": [0, 255]}],
// "initialBank": 2
// },
// {
// "name": "PAGE3",
// "range": ["0xC000","0xFFFF"],
// "banks": [{"index": [0, 255]}],
// "initialBank": 3
// }
// ],
// "ioMmu": [
// "if (portAddress == 0x82) {",
// " bank = portValue;",
// " PAGE0 = bank;",
// "}",
// "if (portAddress == 0xA2) {",
// " bank = portValue;",
// " PAGE1 = bank;",
// "}",
// "if (portAddress == 0xC2) {",
// " bank = portValue;",
// " PAGE2 = bank;",
// "}",
// "if (portAddress == 0xE2) {",
// " bank = portValue;",
// " PAGE3 = bank;",
// "}"
// ]
// },
// "customCode": {
// "debug": false,
// "jsPath": "sim/ports.js"
// },
// },
// "sjasmplus": [
// {
// "path": "espset.sld"
// }
// ],
// "history": {
// "reverseDebugInstructionCount": 1000000,
// "spotCount": 10,
// "codeCoverageEnabled": true
// },
// "startAutomatically": false,
// "commandsAfterLaunch": [],
// "rootFolder": "${workspaceFolder}",
// "topOfStack": "STACK_TOP",
// "loadObjs": [
// {
// "path": "espset.exe",
// "start": "0x0000"
// }
// ],
// "execAddress": "0x8100",
// "smallValuesMaximum": 513,
// "tmpDir": ".tmp"
// },
{
"type": "dezog",
"request": "launch",
"name": "WTERM Internal Simulator",
"remoteType": "zsim",
"zsim": {
"visualMemory": true,
"memoryModel": "CUSTOM",
"customMemory": {
"slots": [
{
"name": "PAGE0",
"range": ["0x0000","0x3FFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 0
},
{
"name": "PAGE1",
"range": ["0x4000","0x7FFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 1
},
{
"name": "PAGE2",
"range": ["0x8000","0xBFFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 2
},
{
"name": "PAGE3",
"range": ["0xC000","0xFFFF"],
"banks": [{"index": [0, 255]}],
"initialBank": 3
}
],
"ioMmu": [
"if (portAddress == 0x82) {",
" bank = portValue;",
" PAGE0 = bank;",
"}",
"if (portAddress == 0xA2) {",
" bank = portValue;",
" PAGE1 = bank;",
"}",
"if (portAddress == 0xC2) {",
" bank = portValue;",
" PAGE2 = bank;",
"}",
"if (portAddress == 0xE2) {",
" bank = portValue;",
" PAGE3 = bank;",
"}"
]
},
"customCode": {
"debug": false,
"jsPath": "sim/ports.js"
},
},
"sjasmplus": [
{
"path": "wterm.sld"
}
],
"history": {
"reverseDebugInstructionCount": 1000000,
"spotCount": 10,
"codeCoverageEnabled": true
},
"startAutomatically": false,
"commandsAfterLaunch": [],
"rootFolder": "${workspaceFolder}",
"topOfStack": "STACK_TOP",
"loadObjs": [
{
"path": "wterm.exe",
"start": "0x0000"
}
],
"execAddress": "0x8100",
"smallValuesMaximum": 513,
"tmpDir": ".tmp"
}
]
}

70
sources/DSS/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,70 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "make ESPSET (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=espset.sld",
"--sym=espset.labels",
"--raw=espset.exe",
"--fullpath",
"espset.asm"
],
"problemMatcher": {
"owner": "sjasmplus",
"fileLocation": "autoDetect",
"pattern": {
"regexp": "^(.*)\\((\\d+)\\):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"severity": 3,
"message": 4
}
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "make WTERM (sjasmplus)",
"type": "shell",
"command": "sjasmplus",
"args": [
"--sld=wterm.sld",
"--sym=wterm.labels",
"--raw=wterm.exe",
"--fullpath",
"wterm.asm"
],
"problemMatcher": {
"owner": "sjasmplus",
"fileLocation": "autoDetect",
"pattern": {
"regexp": "^(.*)\\((\\d+)\\):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"severity": 3,
"message": 4
}
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "start mame",
"type": "shell",
"command": "while true; do ./mame spectrum -window -debugger gdbstub -debug -debugger_port 12000 -verbose -resolution 512x384 ; sleep 2 ; done",
"options": {
"cwd": "${config:mame_dir}"
},
"problemMatcher": []
}
]
}

367
sources/DSS/dss.asm Normal file
View File

@ -0,0 +1,367 @@
; ======================================================
; DSS Estex dumb for debug code in VSC with DEZOG plugin
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; ======================================================
ORG 0x0000
RESET:
JP NOT_IMPL
DS 5, 0xFF
RST08:
JP NOT_IMPL
DS 5, 0xFF
ORG 0x0010
RST10:
JP DSS_HANDLER
DS 5, 0xFF
RST18:
JP NOT_IMPL
DS 5, 0xFF
RST20:
JP NOT_IMPL
DS 5, 0xFF
RST28:
JP NOT_IMPL
DS 5, 0xFF
RST30:
JP NOT_IMPL
DS 5, 0xFF
RST38:
JP NOT_IMPL
DS 5, 0xFF
DSS_HANDLER
PUSH HL
PUSH BC
LD A, C
CP DSS_CURDISK
JP Z, _CURDISK
CP 0x0B
JP Z, _CREATE_FILE
CP 0x11
JP Z, _OPEN_FILE
CP 0x12
JP Z, _CLOSE_FILE
CP 0x13
JP Z, _READ_FILE
CP 0x14
JP Z, _WRITE_FILE
CP 0x19
JP Z, _FIND_FIRST
CP 0x1D
JP Z, _CH_DIR
CP 0x1E
JP Z, _CURDIR
CP DSS_WAITKEY
JP Z, _WAITKEY
CP DSS_SCANKEY
JP Z, _SCANKEY
CP DSS_ECHOKEY
JP Z, _ECHOKEY
CP DSS_SETVMOD
JP Z, _SETVMOD
CP DSS_GETVMOD
JP Z, _GETVMOD
CP low DSS_CLEAR
JP Z, _CLEAR
CP DSS_PUTCHAR
JP Z, _PUTCHAR
CP DSS_PCHARS
JP Z, _PCHARS
CP 0x41
JP Z, _EXIT
POP BC
POP HL
NOT_IMPL
LD A,0x01
SCF
RET
_PUTCHAR
LD BC, 0x9000
OUT (C),A
JR NORM_EXIT
_PCHARS
LD BC, 0x9000
NXT_PCHAR
LD A, (HL)
OUT (C),A
INC HL
OR A
JR NZ, NXT_PCHAR
NORM_EXIT
AND A ; CF=0
POP BC
POP HL
RET
BAD_EXIT
SCF
POP BC
POP HL
RET
_CURDISK
LD A, 3
JP NORM_EXIT
; Входные значения:
; HL - указатель на файловую спецификацию
; A - атрибут файла
; Выходные значения:
; A — код ошибки, если CF=1
; A - файловый манипулятор, если CF=0
_CREATE_FILE
JP _OPEN_FILE
; Входные значения:
; HL - указатель на файловую спецификацию
; A - режим доступа
; A=0 чтение/запись
; A=1 чтение
; A=2 запись
; Выходные значения:
; A - код ошибки, если CF=1
; A - файловый манипулятор, если CF=0
CUR_FILE_MAN
DB 0x4F
CUR_DIR
DB "\\FOLDER",0
CUR_DIR_END
CUR_DIR_SIZE EQU CUR_DIR_END-CUR_DIR
_OPEN_FILE
LD HL, CUR_FILE_MAN
INC (HL)
LD A, (HL)
JP NORM_EXIT
_CLOSE_FILE
JP NORM_EXIT
CUR_F_PTR
DW ZIP_FILE
REMAINS_IN_ZIP
DW 0
; Входные значения:
; A - файловый манипулятор
; HL - адрес в памяти
; DE - количество читаемых байт
; Выходные значения:
; A - код ошибки, если CF=1
; DE - реальное количество прочитанных байт
; если CF=0:
; A = 0 прочитаны все байты
; A = 0FFh прочитано меньшее число байт
_READ_FILE
OR A
JP Z, BAD_EXIT
PUSH DE
POP BC ; BC - bytes to read
PUSH HL
LD HL, (CUR_F_PTR) ; HL -> IN ZIP_FILE
LD DE, ZIP_FILE_END
EX HL, DE
SUB HL, DE ; HL = remain bytes
LD (REMAINS_IN_ZIP), HL
SBC HL, BC
LD A, 0
JR NC, NO_OUT_OF_ZIP
DEC A
LD HL,(REMAINS_IN_ZIP)
LD BC, HL
NO_OUT_OF_ZIP
LD HL, (CUR_F_PTR)
POP DE ; DE - Buffer to write
PUSH BC
LDIR
POP DE ; DE = bytes read, A = 0 or 0xFF
LD (CUR_F_PTR), HL
JP NORM_EXIT
; Входные значения:
; A - файловый манипулятор
; HL - адрес в памяти
; DE - количество записываемых байт
; Выходные значения:
; A - код ошибки, если CF=1
; DE - реальное количество записанных байт
_WRITE_FILE
PUSH DE
POP BC
LD DE,UNZIP_FILE
PUSH BC
LDIR
POP DE
JP NORM_EXIT
; Входные значения:
; HL - указатель на файловую спецификацию
; Выходные значения:
; A - код ошибки, если CF=1
_CH_DIR
JP NORM_EXIT
; 1Eh (30) CURDIR (Информация о текущем каталоге)
; Входные значения:
; HL - буфер в памяти 256 байт
; Выходные значения:
; A - код ошибки, если CF=1
_CURDIR
PUSH DE
LD DE, CUR_DIR
EX HL,DE
LD BC, CUR_DIR_SIZE
LDIR
POP DE
JP NORM_EXIT
_ECHOKEY
PUSH HL
LD HL,EC
LD C,DSS_PCHARS
RST DSS
POP HL
LD A,(EC)
JP NORM_EXIT
EC DB "3",0
; Входные значения:
; HL - указатель на файловую спецификацию
; DE - рабочий буфер 44 байта, если B=0, иначе 256 байт
; A - атрибуты, используемые при поиске
; B = 0 - имя найденного файла в формате 11 байт "FilenameExt"
; B = 1 - имя найденного файла в формате DOS "filename.ext",0
; C - 19h
; Выходные значения:
; A - код ошибки, если CF=1
_FIND_FIRST
PUSH DE
LD HL, 33 ; offset of file name
ADD HL, DE
EX HL, DE
LD HL, ZIP_FILE_NAME
LD BC,9
LDIR
POP DE
JP NORM_EXIT
_SCANKEY
XOR A
JP NORM_EXIT
; Выходные значения:
; A - код символа
; D - позиционный код
; Е - ASCII код
; C - режим клавиатуры:
_WAITKEY
XOR A
LD D, A
LD C, A
LD E,65
LD A,65
JP NORM_EXIT
CUR_VMOD
DB 1
; 50h (80) SETVMOD (Выбор режима экрана)
; Входные значения:
; A - режим экрана:
; 02h - текстовый 40x32x16 цветов;
; 03h - текстовый 80x32x16 цветов;
; 81h - графический 320x256x256 цветов;
; 82h - графический 640x256x16 цветов;
; B - страница экрана 0/1
; C - 50h
; Выходные значения:
; A - код ошибки, если CF=1
_SETVMOD
LD (CUR_VMOD),A
JP NORM_EXIT
; 51h (81) GETVMOD (Получить текущий режим экрана)
; Входные значения:
; C - 51h
; Выходные значения:
; A - код ошибки, если CF=1
; A - текущий режим экрана, если CF=0
; B - страница экрана 0/1
_GETVMOD
LD A,(CUR_VMOD)
JP NORM_EXIT
; 56h (86) CLEAR (Очистка окна)
; Входные значения:
; D - строка левого верхнего угла окна
; E - столбец левого верхнего угла окна
; H - высота окна
; L - ширина окна
; B - атрибут заполнитель
; A - символ заполнитель
; C - 56h
; Выходные значения:
; нет
_CLEAR
JP NORM_EXIT
_EXIT
; LOGPOINT STOPPED!
HALT
JP _EXIT
ZIP_FILE_NAME
DB "file.zip",0
ZIP_FILE
DS 1024,0
ZIP_FILE_END
UNZIP_FILE
DS 1024,0
ALIGN 16384, 0

43
sources/DSS/dss.inc Normal file
View File

@ -0,0 +1,43 @@
; ======================================================
; Defines for DSS Estex for Sprinter computer
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; ======================================================
; DSS RST Entry
DSS EQU 0x10
; DSS Functions
DSS_CURDISK EQU 0x02
DSS_CREATE_FILE EQU 0x0B
DSS_OPEN_FILE EQU 0x11
DSS_CLOSE_FILE EQU 0x12
DSS_READ_FILE EQU 0x13
DSS_WRITE EQU 0x14
DSS_MOVE_FP_CP EQU 0x0115
DSS_FIND_FIRST EQU 0x0119
DSS_FIND_NEXT EQU 0x011A
DSS_MKDIR EQU 0x1B
DSS_CHDIR EQU 0x1D
DSS_CURDIR EQU 0x1E
DSS_SCANKEY EQU 0x31
DSS_ECHOKEY EQU 0x32
DSS_EXIT EQU 0x41
DSS_WAITKEY EQU 0x48
DSS_SETVMOD EQU 0x50
DSS_GETVMOD EQU 0x51
DSS_CLEAR EQU 0x56
DSS_PUTCHAR EQU 0x5B
DSS_PCHARS EQU 0x5C
DSS_VMOD_T40 EQU 0x02 ; text 40x32, 16 colors
DSS_VMOD_T80 EQU 0x03 ; text 80x32, 16 colors
DSS_VMOD_G320 EQU 0x81 ; graphics 320x256, 256 colors
DSS_VMOD_G640 EQU 0x82 ; graphics 640x256, 16 colors
; DSS Error codes
E_FILE_EXISTS EQU 7
E_FILE_NOT_FOUND EQU 3

483
sources/DSS/esplib.asm Normal file
View File

@ -0,0 +1,483 @@
; ======================================================
; Library for Sprinter-WiFi ESP ISA Card
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
;ISA_BASE_A EQU 0xC000 ; Базовый адрес портов ISA в памяти
PORT_UART EQU 0x03E8 ; Базовый номер порта COM3
PORT_UART_A EQU ISA_BASE_A + PORT_UART ; Порты чипа UART в памяти
; UART TC16C550 Registers in memory
REG_RBR EQU PORT_UART_A
REG_THR EQU PORT_UART_A
REG_IER EQU PORT_UART_A + 1
REG_IIR EQU PORT_UART_A + 2
REG_FCR EQU PORT_UART_A + 2
REG_LCR EQU PORT_UART_A + 3
REG_MCR EQU PORT_UART_A + 4
REG_LSR EQU PORT_UART_A + 5
REG_MSR EQU PORT_UART_A + 6
REG_SCR EQU PORT_UART_A + 7
REG_DLL EQU PORT_UART_A
REG_DLM EQU PORT_UART_A + 1
REG_AFR EQU PORT_UART_A + 2
; UART TC16C550 Register bits
MCR_DTR EQU 0x01
MCR_RTS EQU 0x02
MCR_RST EQU 0x04
MCR_PGM EQU 0x08
MCR_LOOP EQU 0x10
MCR_AFE EQU 0x20
LCR_WL8 EQU 0x03 ; 8 bits word len
LCR_SB2 EQU 0x04 ; 1.5 or 2 stp bits
LCR_DLAB EQU 0x80 ; Enable Divisor latch
FCR_FIFO EQU 0x01 ; Enable FIFO for rx and tx
FCR_RESET_RX EQU 0x02 ; Reset Rx FIFO
FCR_RESET_TX EQU 0x04 ; Reset Tx FIFO
FCR_DMA EQU 0x08 ; Set -RXRDY, -TXRDY to "1"
FCR_TR1 EQU 0x00 ; Trigger on 1 byte in fifo
FCR_TR4 EQU 0x40 ; Trigger on 4 bytes in fifo
FCR_TR8 EQU 0x80 ; Trigger on 8 bytes in fifo
FCR_TR14 EQU 0xC0 ; Trigger on 14 bytes in fifo
LSR_DR EQU 0x01 ; Data Ready
LSR_OE EQU 0x02 ; Overrun Error
LSR_PE EQU 0x04 ; Parity Error
LSR_FE EQU 0x08 ; Framing Error
LSR_BI EQU 0x10 ; Break Interrupt
LSR_THRE EQU 0x20 ; Transmitter Holding Register Empty
LSR_TEMT EQU 0x40 ; Transmitter empty
LSR_RCVE EQU 0x80 ; Error in receiver FIFO
; Speed divider for UART
BAUD_RATE EQU 115200 ; Скорость соединения с ESP8266
XIN_FREQ EQU 14745600 ; Частота генератора для TL16C550
DIVISOR EQU XIN_FREQ / (BAUD_RATE * 16) ; Делитель частоты для передачи/приема данных
RS_BUFF_SIZE EQU 2048 ; Receive buffer size
MAX_BUFF_SIZE EQU 16384
LSTR_SIZE EQU 20 ; Size of buffer for last response line
LF EQU 0x0A
CR EQU 0x0D
; --
RES_OK EQU 0
RES_ERROR EQU 1
RES_FAIL EQU 2
RES_TX_TIMEOUT EQU 3
RES_RS_TIMEOUT EQU 4
RES_CONNECTED EQU 5
RES_NOT_CONN EQU 6
RES_ENABLED EQU 7
RES_DISABLED EQU 8
MODULE WIFI
; -- UART Registers offset
_RBR EQU 0
_THR EQU 0
_IER EQU 1
_IIR EQU 2
_FCR EQU 2
_LCR EQU 3
_MCR EQU 4
_LSR EQU 5
_MSR EQU 6
_SCR EQU 7
_DLL EQU 0
_DLM EQU 1
_AFR EQU 2
; ------------------------------------------------------
; Find TL550C in ISA slot
; Out: CF=1 - Not found, CF=0 - ISA.ISA_SLOT found in slot
; ------------------------------------------------------
UART_FIND
PUSH HL
XOR A
CALL UT_T_SLOT
JR Z, UF_T_FND
LD A,1
CALL UT_T_SLOT
JR Z, UF_T_FND
SCF
UF_T_FND
POP HL
RET
; Test slot, A - ISA Slot no. 0 or 1
UT_T_SLOT
; check IER hi bits, will be 0
LD (ISA.ISA_SLOT), A
LD HL, REG_IER
CALL UART_READ
AND 0xF0
RET NZ
; check SCR register
LD DE,0x5555
CALL CHK_SCR
RET NZ
LD DE,0xAAAA
CALL CHK_SCR
RET
CHK_SCR
LD HL, REG_SCR
CALL UART_WRITE
CALL UART_READ
CP D
RET
; ------------------------------------------------------
; Init UART device TL16C550
; ------------------------------------------------------
UART_INIT
PUSH AF, IX
CALL ISA.ISA_OPEN
LD IX, PORT_UART_A
LD A, FCR_TR8 | FCR_FIFO ; Enable FIFO buffer, trigger to 14 byte
LD (IX+_FCR),A
XOR A
LD (IX+_IER), A ; Disable interrupts
; Set 8bit word and Divisor for speed
LD A, LCR_DLAB | LCR_WL8
LD (IX+_LCR), A ; Enable Baud rate latch
LD A, DIVISOR
LD (IX+_DLL), A ; 8 - 115200
XOR A
LD (IX+_DLM), A
LD A, LCR_WL8 ; 8bit word, disable latch
LD (IX+_LCR), A
CALL ISA.ISA_CLOSE
POP IX,AF
RET
; ------------------------------------------------------
; Read TL16C550 register
; Inp: HL - register
; Out: A - value from register
; ------------------------------------------------------
UART_READ
CALL ISA.ISA_OPEN
LD A, (HL)
CALL ISA.ISA_CLOSE
RET
; ------------------------------------------------------
; Write TL16C550 register
; Inp: HL - register, E - value
; ------------------------------------------------------
UART_WRITE
CALL ISA.ISA_OPEN
LD (HL), E
CALL ISA.ISA_CLOSE
RET
; ------------------------------------------------------
; Wait for transmitter ready
; Out: CF=1 - tr not ready, CF=0 ready
; ------------------------------------------------------
UART_WAIT_TR
CALL ISA.ISA_OPEN
CALL UART_WAIT_TR_INT
CALL ISA.ISA_CLOSE
RET
;
; Wait, without open/close ISA
;
UART_WAIT_TR_INT
PUSH AF, BC, HL
LD BC, 500
LD HL, REG_LSR
WAIT_TR_BZY
LD A,(HL)
AND A, LSR_THRE
JR NZ,WAIT_TR_RDY
CALL UTIL.DELAY_100uS ; ~11 bit tx delay
DEC BC
LD A, C
OR B
JR NZ,WAIT_TR_BZY
SCF
WAIT_TR_RDY
POP HL, BC, AF
RET
; ------------------------------------------------------
; Transmit byte
; Inp: E - byte
; Out: CF=1 - Not ready
; ------------------------------------------------------
UART_TX_BYTE
CALL UART_WAIT_TR
JP C, UTB_NOT_R
LD HL, REG_THR
CALL UART_WRITE
XOR A
UTB_NOT_R
RET
; ------------------------------------------------------
; Transmit buffer
; Inp: HL -> buffer, BC - size
; Out: CF=0 - Ok, CF=1 - Timeout
; ------------------------------------------------------
UART_TX_BUFFER
PUSH BC,DE,HL
LD DE, REG_THR
CALL ISA.ISA_OPEN
UTX_NEXT
; buff not empty?
LD A, B
OR C
JR Z,UTX_EMP
; check transmitter ready
CALL UART_WAIT_TR_INT
JR C, UTX_TXNR
; transmitt byte
LD A,(HL)
INC HL
LD (DE),A
DEC BC
JR UTX_NEXT
; CF=0
UTX_EMP
AND A
UTX_TXNR
CALL ISA.ISA_CLOSE
POP HL,DE,BC
RET
; ------------------------------------------------------
; Transmit zero ended string
; Inp: HL -> buffer
; Out: CF=0 - Ok, CF=1 - Timeout
; ------------------------------------------------------
UART_TX_STRING
PUSH DE,HL
LD DE, REG_THR
CALL ISA.ISA_OPEN
UTXS_NEXT
LD A,(HL)
AND A
JR Z,UTXS_END
; check transmitter ready
CALL UART_WAIT_TR_INT
JR C, UTXS_TXNR
; transmitt byte
LD A,(HL)
INC HL
LD (DE),A
JR UTXS_NEXT
; CF=0
UTXS_END
AND A
UTXS_TXNR
CALL ISA.ISA_CLOSE
POP HL,DE
RET
; ------------------------------------------------------
; Empty receiver FIFO buffer
; ------------------------------------------------------
UART_EMPTY_RS
PUSH DE, HL
LD E, FCR_TR8 | FCR_RESET_RX | FCR_FIFO
LD HL, REG_FCR
CALL UART_WRITE
POP HL, DE
RET
; ------------------------------------------------------
; Wait byte in receiver fifo
; Inp: BC - Wait ms
; Out: CF=1 - Timeout, FIFO is EMPTY
; ------------------------------------------------------
UART_WAIT_RS1
PUSH BC,HL
WAIT_MS+* LD BC,0x2000
JR UVR_NEXT
UART_WAIT_RS
PUSH BC,HL
UVR_NEXT
LD HL, REG_LSR
CALL UART_READ
AND LSR_DR
JR NZ,UVR_OK
CALL UTIL.DELAY_1MS
DEC BC
LD A,B
OR C
JR NZ,UVR_NEXT
UVR_TO
IF TRACE
PUSH AF,BC,DE,HL
PRINTLN MSG_RCV_EMPTY
POP HL,DE,BC,AF
ENDIF
SCF
UVR_OK
POP HL,BC
RET
; ------------------------------------------------------
; Reset ESP module
; ------------------------------------------------------
ESP_RESET
PUSH AF,HL
CALL ISA.ISA_OPEN
LD HL, REG_MCR
LD A, MCR_RST ;| MCR_RTS ; -OUT1=0 -> RESET ESP
LD (REG_MCR), A
CALL UTIL.DELAY_1MS
LD A, MCR_AFE | MCR_RTS ; 0x22 -OUT1=1 RTS=1 AutoFlow enabled
LD (HL), A
CALL ISA.ISA_CLOSE
; wait 2s for ESP firmware boot
LD HL,2000
CALL UTIL.DELAY
POP HL,AF
RET
; Receive block size
BSIZE DW 0
; Received message for OK result
MSG_OK DB "OK", 0
; Received message for Error
MSG_ERROR DB "ERROR", 0
; Received message for Failure
MSG_FAIL DB "FAIL", 0
; ------------------------------------------------------
; UART TX Command
; Inp: HL - ptr to command,
; DE - ptr to receive buffer,
; BC - wait ms
; Out: CF=1 if Error
; ------------------------------------------------------
UART_TX_CMD
PUSH BC, DE, HL
LD A, low RS_BUFF_SIZE
LD (BSIZE), A
LD A, high RS_BUFF_SIZE
LD (BSIZE+1), A
;LD (RESBUF),DE
XOR A
LD (DE), A
LD (WAIT_MS), BC
CALL UART_EMPTY_RS
; HL - Buffer, BC - Size
;CALL UTIL.STRLEN
CALL UART_TX_STRING
JR NC, UTC_STRT_RX
; error, transmit timeout
LD A, RES_TX_TIMEOUT
JR UTC_RET
UTC_STRT_RX
; no transmit timeout, receive response
; IX - pointer to begin of current line
LD IXH, D
LD IXL, E
LD BC,(BSIZE)
UTC_RCV_NXT
; wait receiver ready
;LD BC,(WAIT_MS)
CALL UART_WAIT_RS1
JR NC, UTC_NO_RT
; error, read timeout
LD A, RES_RS_TIMEOUT
JR UTC_RET
; no receive timeout
UTC_NO_RT
; read symbol from tty
LD HL, REG_RBR
CALL UART_READ
CP CR
JP Z, UTC_RCV_NXT ; Skip CR
CP LF
JR Z, UTC_END ; LF - last symbol in responce
LD (DE),A
INC DE
DEC BC
LD A, B
OR C
JR NZ, UTC_RCV_NXT
UTC_END
XOR A
LD (DE),A ; temporary mark end of string
PUSH DE ; store DE
POP IY
PUSH IX
POP DE ; DE - ptr to begin pf current line
; It is 'OK<LF>'?
LD HL, MSG_OK
CALL UTIL.STRCMP
JR NC, UTC_RET
; It is 'ERROR<LF>'?
LD HL,MSG_ERROR
CALL UTIL.STRCMP
JR C, UTC_CP_FAIL
LD A, RES_ERROR
; It is 'FAIL<LF>'?
JR UTC_RET
UTC_CP_FAIL
LD HL,MSG_FAIL
CALL UTIL.STRCMP
JR C, UTC_NOMSG
LD A, RES_FAIL
JR UTC_RET
UTC_NOMSG
; no resp message, continue receive
PUSH IY
POP DE
LD A, LF
LD (DE),A ; change 0 - EOL to LF
INC DE
LD IXH,D ; store new start line ptr
LD IXL,E
JR UTC_RCV_NXT
UTC_RET
POP HL, DE, BC
RET
IF TRACE
MSG_RCV_EMPTY
DB "Receiver is empty!",0
ENDIF
; Buffer to receive response from ESP
RS_BUFF DS RS_BUFF_SIZE, 0
ENDMODULE

301
sources/DSS/espset.asm Normal file
View File

@ -0,0 +1,301 @@
; ======================================================
; ESPSET for Sprinter-WiFi for Sprinter computer
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
; Set to 1 to turn debug ON with DeZog VSCode plugin
; Set to 0 to compile .EXE
DEBUG EQU 0
; Set to 1 to output TRACE messages
TRACE EQU 1
; Version of EXE file, 1 for DSS 1.70+
EXE_VERSION EQU 0
; Timeout to wait ESP response
DEFAULT_TIMEOUT EQU 2000
SLDOPT COMMENT WPMEM, LOGPOINT, ASSERTION
DEVICE NOSLOT64K
IF DEBUG == 1
INCLUDE "dss.asm"
DB 0
ALIGN 16384, 0
DS 0x80, 0
ENDIF
INCLUDE "macro.inc"
INCLUDE "dss.inc"
INCLUDE "sprinter.inc"
MODULE MAIN
ORG 0x8080
; ------------------------------------------------------
EXE_HEADER
DB "EXE"
DB EXE_VERSION ; EXE Version
DW 0x0080 ; Code offset
DW 0
DW 0 ; Primary loader size
DW 0 ; Reserved
DW 0
DW 0
DW START ; Loading Address
DW START ; Entry Point
DW STACK_TOP ; Stack address
DS 106, 0 ; Reserved
ORG 0x8100
@STACK_TOP
; ------------------------------------------------------
START
IF DEBUG == 1
; LD IX,CMD_LINE1
LD SP, STACK_TOP
ENDIF
CALL ISA.ISA_RESET
PRINTLN MSG_START
CALL FIND_SWF
; Turn local echo Off
CALL INIT_ESP
; Display main menu to make selection
MENU_AGAIN
CALL SELECT_MAIN_MENU
; Do somethink with selected item
AND A
JR Z, MENU_EXIT
DEC A
JP Z, MENU_SELECT_WIFI
DEC A
JP Z, MENU_CONFIGURE_IP
DEC A
JP Z, MENU_DISPLAY_INFO
JP MENU_AGAIN
MENU_EXIT
LD B,0
JP EXIT
MENU_SELECT_WIFI
MENU_CONFIGURE_IP
MENU_DISPLAY_INFO
JP MENU_AGAIN
NO_TL_FOUND
PRINTLN MSG_SWF_NOF
LD B,2
JP EXIT
CHECK_ERROR
RET NC
ADD A,'0'
LD (COMM_ERROR_NO), A
PRINTLN MSG_COMM_ERROR
LD B,3
POP HL ; ret addr reset
EXIT
LD C,DSS_EXIT
RST DSS
FIND_SWF
; Find Sprinter-WiFi
CALL WIFI.UART_FIND
JP C, NO_TL_FOUND
LD A,(ISA.ISA_SLOT)
ADD A,'1'
LD (MSG_SLOT_NO),A
PRINTLN MSG_SWF_FOUND
LD C,DSS_PCHARS
RST DSS
RET
; ------------------------------------------------------
; Init basic parameters of ESP
; ------------------------------------------------------
INIT_ESP
PUSH BC, DE
LD DE, WIFI.RS_BUFF
LD BC, DEFAULT_TIMEOUT
TRACELN MSG_ECHO_OFF
SEND_CMD CMD_ECHO_OFF
TRACELN MSG_STATIOJN_MODE
SEND_CMD CMD_STATION_MODE
TRACELN MSG_NO_SLEEP
SEND_CMD CMD_NO_SLEEP
TRACELN MSG_SET_UART
SEND_CMD CMD_SET_SPEED
TRACELN MSG_SET_OPT
SEND_CMD CMD_CWLAP_OPT
POP DE,BC
RET
; ------------------------------------------------------
; Set DHCP mode
; Out: CF=1 if error
; ------------------------------------------------------
SET_DHCP_MODE
PUSH BC,DE
LD DE, WIFI.RS_BUFF
LD BC, DEFAULT_TIMEOUT
TRACELN MSG_SET_DHCP
SEND_CMD CMD_SET_DHCP
POP DE,BC
RET
; ------------------------------------------------------
; Output main menu to select user action
; Ret: A = selected menu item
; ------------------------------------------------------
SELECT_MAIN_MENU
PUSH BC
PRINTLN MSG_MAIN_MENU
SMM_L1
PRINT MSG_ENT_NO
; SCANF
LD C, DSS_ECHOKEY
RST DSS
SUB '0'
; Test A in range [0..3]
AND A
JP M, SMM_L1
CP 4
JP P, SMM_L1
POP BC
RET
; ------------------------------------------------------
; Messages DB "\r\n1 - Select WiFi Network\r\n"
DB "2 - Configure IP parameters\r\n"
DB "3 - Display info\r\n"
DB "0 - Exit",0
; ------------------------------------------------------
MSG_START
DB "Setup for Sprinter-WiFi by Sprinter Team, ", __DATE__ ,"\r\n", 0
MSG_SWF_NOF
DB "Sprinter-WiFi not found!",0
MSG_SWF_FOUND
DB "Sprinter-WiFi found in ISA#"
MSG_SLOT_NO
DB "n slot.",0
MSG_COMM_ERROR
DB "Error communication with Sprinter-WiFi #"
COMM_ERROR_NO
DB "n!",0
MSG_MAIN_MENU
DB "\r\n1 - Select WiFi Network\r\n"
DB "2 - Configure IP parameters\r\n"
DB "3 - Display info\r\n"
DB "0 - Exit",0
MSG_ENT_NO
DB "\r\nEnter number 0..3: ",0
; ------------------------------------------------------
; Debug messages
; ------------------------------------------------------
IF TRACE
MSG_ECHO_OFF
DB "Echo off",0
MSG_STATIOJN_MODE
DB "Station mode",0
MSG_NO_SLEEP
DB "No sleep",0
MSG_SET_UART
DB "Setup uart",0
MSG_SET_OPT
DB "Set options",0
MSG_SET_DHCP
DB "Set DHCP mode",0
ENDIF
; ------------------------------------------------------
; Commands
; ------------------------------------------------------
CMD_SET_SPEED
DB "AT+UART_CUR=115200,8,1,0,3\r\n",0
CMD_ECHO_OFF
DB "ATE0\r\n",0
CMD_STATION_MODE
DB "AT+CWMODE=1\r\n",0
CMD_NO_SLEEP
DB "AT+SLEEP=0\r\n",0
CMD_CHECK_CONN_AP
DB "AT+CWJAP?\r\n",0
CMD_CWLAP_OPT
DB "AT+CWLAPOPT=1,23\r\n",0
CMD_GET_AP_LIST
DB "AT+CWLAP\r\n",0
CMD_GET_DHCP
DB "AT+CWDHCP?\r\n",0
CMD_SET_DHCP
DB "AT+CWDHCP=1,1\r\n",0
CMD_GET_IP
DB "AT+CIPSTA?\r\n",0
LINE_END
DB "\r\n",0
IF DEBUG == 1
CMD_TEST1 DB "ATE0\r\n",0
BUFF_TEST1 DS RS_BUFF_SIZE,0
ENDIF
ENDMODULE
INCLUDE "util.asm"
INCLUDE "isa.asm"
INCLUDE "esplib.asm"
END MAIN.START
; PUSH IX ; IX ptr to cmd line
; POP HL
; INC HL ; Skip size of Command line
; LD DE,ZIP_FILE
; CALL GET_CMD_PARAM
; JR C,INVALID_CMDLINE
; LD DE,FILES_TO_ZIP
; CALL GET_CMD_PARAM
; JR C,INVALID_CMDLINE

80
sources/DSS/isa.asm Normal file
View File

@ -0,0 +1,80 @@
; ======================================================
; ISA Library for Sprinter computer
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
PORT_ISA EQU 0x9FBD
PORT_SYSTEM EQU 0x1FFD
ISA_BASE_A EQU 0xC000 ; Базовый адрес портов ISA в памяти
; --- PORT_ISA bits
ISA_A14 EQU 0x01
ISA_A15 EQU 0x02
ISA_A16 EQU 0x04
ISA_A17 EQU 0x08
ISA_A18 EQU 0x10
ISA_A19 EQU 0x20
ISA_AEN EQU 0x40
ISA_RST EQU 0x80
MODULE ISA
; ------------------------------------------------------
; Reset ISA device
; ------------------------------------------------------
ISA_RESET
LD BC, PORT_ISA
LD A,ISA_RST | ISA_AEN ; RESET=1 AEN=1
OUT (C), A
CALL UTIL.DELAY_1MS
XOR A
OUT (C), A ; RESET=0 AEN=0
LD HL,100
CALL UTIL.DELAY
RET
; ------------------------------------------------------
; Open access to ISA ports as memory
; Inp: A = 0 - ISA slot 0, 1 - ISA SLOT 1
; ------------------------------------------------------
ISA_OPEN
PUSH AF,BC
LD BC, PAGE3
IN A,(C)
LD (SAVE_MMU3), A
LD BC, PORT_SYSTEM
LD A, 0x11
OUT (C), A
ISA_SLOT+* LD A,0x01
SLA A
OR A, 0xD4 ; D4 - ISA1, D6 - ISA2
LD BC, PAGE3
OUT (C), A
LD BC, PORT_ISA
XOR A
OUT (C), A
POP BC,AF
RET
; ------------------------------------------------------
; Close access to ISA ports
; ------------------------------------------------------
ISA_CLOSE
PUSH AF,BC
LD A,0x01
LD BC,PORT_SYSTEM
OUT (C),A
LD BC,PAGE3
LD A,(SAVE_MMU3)
OUT (C),A
POP BC,AF
RET
; To save memory page 3
SAVE_MMU3 DB 0
ENDMODULE

39
sources/DSS/macro.inc Normal file
View File

@ -0,0 +1,39 @@
; ======================================================
; Macros for Sprinter-WiFi utilities
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
; Transmit data|command via UART and check response
MACRO SEND_CMD data
LD HL, data
CALL WIFI.UART_TX_CMD
CALL CHECK_ERROR
ENDM
; Print data ASCIIZ string to screen
MACRO PRINT data
LD HL,data
LD C,DSS_PCHARS
RST DSS
ENDM
; Print data ASCIIZ string to screen and CR+LF
MACRO PRINTLN data
LD HL,data
LD C,DSS_PCHARS
RST DSS
LD C,DSS_PCHARS
LD HL, WCOMMON.LINE_END
RST DSS
ENDM
; Print data ASCIIZ string to screen if TRACE enabled
MACRO TRACELN data
IF TRACE == 1
PUSH BC,DE
PRINTLN data
POP DE,BC
ENDIF
ENDM

44
sources/DSS/sim/ports.js Normal file
View File

@ -0,0 +1,44 @@
port_p0 = 0;
port_p1 = 1;
port_p2 = 2;
port_p3 = 3;
message = "";
// This function is called when time (t-states) advances.
API.tick = () => {
}
// This function is called when an 'out' is executed in Z80.
API.writePort = (port, value) => {
// Go through all ports
if (port == 0x9000) {
if (value != 0) {
message += String.fromCharCode(value);
} else {
API.log("> " + message);
message = "";
}
} else if (port == 0x82) {
port_p0 = value;
} else if (port == 0xA2) {
port_p1 = value;
} else if (port == 0xC2) {
port_p2 = value;
} else if (port == 0xE2) {
port_p3 = value;
}
}
API.readPort = (port) => {
if (port == 0x82) {
return port_p0;
} else if (port == 0xA2) {
return port_p1;
} else if (port == 0xC2) {
return port_p2;
} else if (port == 0xE2) {
return port_p3;
}
}

32
sources/DSS/sprinter.inc Normal file
View File

@ -0,0 +1,32 @@
; ======================================================
; Defines for Sprinter computer hardware
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; ======================================================
; Memory pages
PAGE0_ADDR EQU 0x0000
PAGE1_ADDR EQU 0x4000
PAGE2_ADDR EQU 0x8000
PAGE3_ADDR EQU 0xC000
; Sprinter ports to switch mem pages
PAGE0 EQU 0x82
PAGE1 EQU 0xA2
PAGE2 EQU 0xC2
PAGE3 EQU 0xE2
; CTC Control register ports
CTC_CH0 EQU 0x10
CTC_CH1 EQU 0x11
CTC_CH2 EQU 0x12
CTC_CH3 EQU 0x13
CTC_CR_VEC EQU 0x01 ; 1 - Vector, 0 - Control
CTC_CR_SWR EQU 0x02 ; 1 - Software Reset, 0 - Continued operation
CTC_CR_TCF EQU 0x04 ; 1 - TYime const follows
CTC_CR_TTR EQU 0x08 ; 1 - Time trigger
CTC_CT_TRE EQU 0x10 ; 1 - Trigger Edge
CTC_CT_PRE EQU 0x20 ; 1 - 256 Prescaler, 0 - 16
CTC_CT_CTR EQU 0x40 ; 0 - Timer, 1 - Counter
CTC_CT_EI EQU 0x80 ; Interrupt 1 - enable, 0 - disable

184
sources/DSS/util.asm Normal file
View File

@ -0,0 +1,184 @@
; ======================================================
; Utility code for Sprinter-WiFi utilities
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
MODULE UTIL
; ------------------------------------------------------
; Small delay
; Inp: HL - number of cycles, if HL=0, then 2000
; ------------------------------------------------------
DELAY
PUSH AF,BC,HL
LD A,H
OR L
JR NZ,DELAY_NXT
LD HL,20
DELAY_NXT
CALL DELAY_1MS_INT
DEC HL
LD A,H
OR L
JP NZ,DELAY_NXT
POP HL,BC,AF
RET
DELAY_1MS_INT
LD BC,400
SBD_NXT
DEC BC
LD A, B
OR C
JR NZ, SBD_NXT
RET
DELAY_1MS
PUSH BC
CALL DELAY_1MS_INT
POP BC
RET
DELAY_100uS
PUSH BC
LD BC,40
CALL SBD_NXT
POP BC
RET
; ------------------------------------------------------
; Calc length of zero ended string
; Inp: HL - pointer to string
; Out: BC - length of string
; ------------------------------------------------------
STRLEN
PUSH DE,HL,HL
LD BC,MAX_BUFF_SIZE
XOR A
CPIR
POP DE
SUB HL,DE ; llength of zero ended string
LD BC,HL
LD A, B
OR C
JR Z, STRL_NCOR
DEC BC
STRL_NCOR
POP HL,DE
RET
; ------------------------------------------------------
; Compare zero-ended strings
; Inp: HL, DE - pointers to strinngs to compare
; Out: CF=0 - equal, CF=1 - not equal
; ------------------------------------------------------
STRCMP
PUSH DE,HL
STC_NEXT
LD A, (DE)
CP (HL)
JR NZ, STC_NE
AND A
JR Z, STC_EQ
INC DE
INC HL
JR STC_NEXT
STC_NE
SCF
STC_EQ
POP HL,DE
RET
; ------------------------------------------------------
; Convert string to number
; Inp: DE - ptr to zero ended string
; Out: HL - Result
; ------------------------------------------------------
ATOU
PUSH BC
LD HL,0x0000
ATOU_L1
LD A,(DE)
AND A
JR Z, ATOU_LE
SUB 0x30
CP 10
JR NC, ATOU_LE
INC DE
LD B,H
LD C,L
ADD HL,HL
ADD HL,HL
ADD HL,BC
ADD HL,HL
ADD A,L
LD L,A
JR NC,ATOU_L1
INC H
JP ATOU_L1
ATOU_LE
POP BC
RET
; ------------------------------------------------------
; Find char in string
; Inp: HL - ptr to zero endeds string
; A - char to find
; Outp: CF=0, HL points to char if found
; CF=1 - Not found
; ------------------------------------------------------
STRCHR
PUSH BC
STCH_NEXT
LD C,A
LD A,(HL)
AND A
JR Z, STCH_N_FOUND
CP C
JR Z, STCH_FOUND
INC HL
JR STCH_NEXT
STCH_N_FOUND
SCF
STCH_FOUND
POP BC
RET
; ------------------------------------------------------
; Convert Byte to hex
; Inp: C
; Out: (DE)
; ------------------------------------------------------
HEXB
LD A,C
RRA
RRA
RRA
RRA
CALL CONV_NIBLE
LD A,C
CONV_NIBLE
AND 0x0f
ADD A,0x90
DAA
ADC A,0x40
DAA
LD (DE), A
INC DE
RET
ENDMODULE

272
sources/DSS/wcommon.asm Normal file
View File

@ -0,0 +1,272 @@
; ======================================================
; Common code for Sprinter-WiFi utilities
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
MODULE WCOMMON
; ------------------------------------------------------
; Ckeck for error (CF=1) print message and exit
; ------------------------------------------------------
CHECK_ERROR
RET NC
ADD A,'0'
LD (COMM_ERROR_NO), A
PRINTLN MSG_COMM_ERROR
CALL DUMP_UART_REGS
LD B,3
POP HL ; ret addr reset
EXIT
CALL REST_VMODE
LD C,DSS_EXIT
RST DSS
; ------------------------------------------------------
; Search Sprinter WiFi card
; ------------------------------------------------------
FIND_SWF
; Find Sprinter-WiFi
CALL WIFI.UART_FIND
JP C, NO_TL_FOUND
LD A,(ISA.ISA_SLOT)
ADD A,'1'
LD (MSG_SLOT_NO),A
PRINTLN MSG_SWF_FOUND
RET
NO_TL_FOUND
POP BC
PRINTLN MSG_SWF_NOF
LD B,2
JP EXIT
IF TRACE
; ------------------------------------------------------
; Dump all UTL16C550 registers to screen for debug
; ------------------------------------------------------
DUMP_UART_REGS
; Dump, DLAB=0 registers
LD BC, 0x0800
CALL DUMP_REGS
; Dump, DLAB=1 registers
LD HL, REG_LCR
LD E, LCR_DLAB | LCR_WL8
CALL WIFI.UART_WRITE
LD BC, 0x0210
CALL DUMP_REGS
LD HL, REG_LCR
LD E, LCR_WL8
CALL WIFI.UART_WRITE
RET
DUMP_REGS
LD HL, PORT_UART_A
DR_NEXT
LD DE,MSG_DR_RN
CALL UTIL.HEXB
INC C
CALL WIFI.UART_READ
PUSH BC
LD C,A
LD DE,MSG_DR_RV
CALL UTIL.HEXB
PUSH HL
PRINTLN MSG_DR
POP HL,BC
INC HL
DJNZ DR_NEXT
RET
ENDIF
; ------------------------------------------------------
; Store old video mode, set 80x32 and clear
; ------------------------------------------------------
INIT_VMODE
PUSH BC,DE,HL
; Store previous vmode
LD C,DSS_GETVMOD
RST DSS
LD (SAVE_VMODE),A
CP DSS_VMOD_T80
; Set vmode 80x32
JR Z, IVM_ALRDY_80
LD C,DSS_SETVMOD
LD A,DSS_VMOD_T80
RST DSS
IVM_ALRDY_80
; Clear screen
LD A,' '
LD B,0x07
LD C,DSS_CLEAR
LD HL,0x2050
LD DE,0x0000
RST DSS
POP HL,DE,BC
RET
; ------------------------------------------------------
; Restore saved video mode
; ------------------------------------------------------
REST_VMODE
PUSH BC
LD A,(SAVE_VMODE)
CP DSS_VMOD_T80
JR Z, RVM_SAME
; Restore mode
PRINTLN MSG_PRESS_AKEY
LD C, DSS_WAITKEY
RST DSS
LD C,DSS_SETVMOD
RST DSS
RVM_SAME
POP BC
RET
; ------------------------------------------------------
; Init basic parameters of ESP
; ------------------------------------------------------
INIT_ESP
PUSH BC, DE
LD DE, WIFI.RS_BUFF
LD BC, DEFAULT_TIMEOUT
TRACELN MSG_ECHO_OFF
SEND_CMD CMD_ECHO_OFF
TRACELN MSG_STATIOJN_MODE
SEND_CMD CMD_STATION_MODE
TRACELN MSG_NO_SLEEP
SEND_CMD CMD_NO_SLEEP
TRACELN MSG_SET_UART
SEND_CMD CMD_SET_SPEED
TRACELN MSG_SET_OPT
SEND_CMD CMD_CWLAP_OPT
POP DE,BC
RET
; ------------------------------------------------------
; Set DHCP mode
; Out: CF=1 if error
; ------------------------------------------------------
SET_DHCP_MODE
PUSH BC,DE
LD DE, WIFI.RS_BUFF
LD BC, DEFAULT_TIMEOUT
TRACELN MSG_SET_DHCP
SEND_CMD CMD_SET_DHCP
POP DE,BC
RET
; ------------------------------------------------------
; Messages
; ------------------------------------------------------
MSG_SWF_NOF
DB "Sprinter-WiFi not found!",0
MSG_SWF_FOUND
DB "Sprinter-WiFi found in ISA#"
MSG_SLOT_NO
DB "n slot.",0
MSG_COMM_ERROR
DB "Error communication with Sprinter-WiFi #"
COMM_ERROR_NO
DB "n!",0
MSG_PRESS_AKEY
DB "Press any key to continue...",0
MSG_ESP_RESET
DB "Reset ESP module.",0
MSG_UART_INIT
DB "Reset UART.",0
LINE_END
DB "\r\n",0
SAVE_VMODE
DB 0
; ------------------------------------------------------
; Debug messages
; ------------------------------------------------------
IF TRACE
MSG_DR
DB "Reg[0x"
MSG_DR_RN
DB "vv]=0x"
MSG_DR_RV
DB "vv",0
MSG_ECHO_OFF
DB "Echo off",0
MSG_STATIOJN_MODE
DB "Station mode",0
MSG_NO_SLEEP
DB "No sleep",0
MSG_SET_UART
DB "Setup uart",0
MSG_SET_OPT
DB "Set options",0
MSG_SET_DHCP
DB "Set DHCP mode",0
ENDIF
; ------------------------------------------------------
; Commands
; ------------------------------------------------------
CMD_QUIT
DB "QUIT\r",0
CMD_VERSION
DB "AT+GMR\r\n",0
CMD_SET_SPEED
DB "AT+UART_CUR=115200,8,1,0,3\r\n",0
CMD_ECHO_OFF
DB "ATE0\r\n",0
CMD_STATION_MODE
DB "AT+CWMODE=1\r\n",0
CMD_NO_SLEEP
DB "AT+SLEEP=0\r\n",0
CMD_CHECK_CONN_AP
DB "AT+CWJAP?\r\n",0
CMD_CWLAP_OPT
DB "AT+CWLAPOPT=1,23\r\n",0
CMD_GET_AP_LIST
DB "AT+CWLAP\r\n",0
CMD_GET_DHCP
DB "AT+CWDHCP?\r\n",0
CMD_SET_DHCP
DB "AT+CWDHCP=1,1\r\n",0
CMD_GET_IP
DB "AT+CIPSTA?\r\n",0
ENDMODULE

242
sources/DSS/wterm.asm Normal file
View File

@ -0,0 +1,242 @@
; ======================================================
; WTERM terminal for Sprinter-WiFi ISA Card
; For Sprinter computer DSS
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; License: BSD 3-Clause
; ======================================================
; Set to 1 to turn debug ON with DeZog VSCode plugin
; Set to 0 to compile .EXE
DEBUG EQU 0
; Set to 1 to output TRACE messages
TRACE EQU 1
; Version of EXE file, 1 for DSS 1.70+
EXE_VERSION EQU 0
; Timeout to wait ESP response
DEFAULT_TIMEOUT EQU 2000
SLDOPT COMMENT WPMEM, LOGPOINT, ASSERTION
DEVICE NOSLOT64K
IF DEBUG == 1
INCLUDE "dss.asm"
DB 0
ALIGN 16384, 0
DS 0x80, 0
ENDIF
INCLUDE "macro.inc"
INCLUDE "dss.inc"
INCLUDE "sprinter.inc"
MODULE MAIN
ORG 0x8080
; ------------------------------------------------------
EXE_HEADER
DB "EXE"
DB EXE_VERSION ; EXE Version
DW 0x0080 ; Code offset
DW 0
DW 0 ; Primary loader size
DW 0 ; Reserved
DW 0
DW 0
DW START ; Loading Address
DW START ; Entry Point
DW STACK_TOP ; Stack address
DS 106, 0 ; Reserved
ORG 0x8100
@STACK_TOP
; ------------------------------------------------------
START
IF DEBUG == 1
; LD IX,CMD_LINE1
LD SP, STACK_TOP
ENDIF
CALL ISA.ISA_RESET
CALL WCOMMON.INIT_VMODE
PRINTLN MSG_START
CALL WCOMMON.FIND_SWF
PRINTLN WCOMMON.MSG_UART_INIT
CALL WIFI.UART_INIT
PRINTLN WCOMMON.MSG_ESP_RESET
CALL WIFI.ESP_RESET
CALL WCOMMON.INIT_ESP
PRINTLN MSG_HLP
CALL WIFI.UART_EMPTY_RS
XOR A
LD (Q_POS),A
MAIN_LOOP
; handle key pressed
LD C,DSS_SCANKEY
RST DSS
JP Z,HANDLE_RECEIVE ; if no key pressed
; check for QUIT command
LD A,(Q_POS)
CP 4
JP P,NO_QUIT
LD IX, CMD_QUIT
Q_POS EQU $+2
LD A,(IX+0x00)
; compare current char with "QUIT" str
CP E
JR NZ,NO_QUIT
LD HL,Q_POS
INC (HL)
LD A,(HL)
CP 5
JP Z,OK_EXIT
JR OUT_CHAR
NO_QUIT
XOR A
LD (Q_POS), A
OUT_CHAR
LD A, E
CP CR
JR Z, PUT_CHAR
CP 0x20
JP M, HANDLE_CR_LF
PUT_CHAR
CALL PUT_A_CHAR
HANDLE_CR_LF
CALL WIFI.UART_TX_BYTE
JP C,TX_WARN
LD A, E
CP CR
JR NZ,NO_TX_LF
LD E,LF
CALL WIFI.UART_TX_BYTE
JP C,TX_WARN
JR HANDLE_RECEIVE
NO_TX_LF
CP LF
JR NZ,HANDLE_RECEIVE
LD E,CR
CALL WIFI.UART_TX_BYTE
JP C,TX_WARN
; check receiver and handle received bytes
HANDLE_RECEIVE
; check receiver status
LD HL,REG_LCR
CALL WIFI.UART_READ
CP LSR_RCVE
JP NZ, RX_WARN
CP LSR_DR
JP Z, CHECK_FOR_END
; rx queue is not empty, read
LD HL,REG_RBR
CALL WIFI.UART_READ
LD E,A
CP CR
JR NZ, CHK_1F
; print CR+LF
CALL PUT_A_CHAR
LD A,LF
CALL PUT_A_CHAR
JP CHECK_FOR_END
CHK_1F
CP 0x20
CALL P, PUT_A_CHAR
CHECK_FOR_END
LD A,(Q_POS)
CP 5
JP Z, OK_EXIT
JP MAIN_LOOP
RX_WARN
LD C,A
LD DE,MSG_LSR_VALUE
CALL UTIL.HEXB
PRINTLN MSG_RX_ERROR
JP MAIN_LOOP
TX_WARN
PRINTLN MSG_TX_ERROR
JP MAIN_LOOP
PUT_A_CHAR
PUSH BC,DE
LD C,DSS_PUTCHAR
RST DSS
POP DE,BC
RET
; ------------------------------------------------------
; Do Some
; ------------------------------------------------------
OK_EXIT
LD B,0
JP WCOMMON.EXIT
; ------------------------------------------------------
; Custom messages
; ------------------------------------------------------
MSG_START
DB "Terminal for Sprinter-WiFi by Sprinter Team. v1.0.1, ", __DATE__, "\r\n", 0
MSG_HLP
DB"\r\nEnter ESP AT command or QUIT to close terminal.",0
MSG_TX_ERROR
DB "Transmitter not ready",0
MSG_RX_ERROR
DB "Receiver error LSR: 0x"
MSG_LSR_VALUE
DB "xx",0
; TX_DATA
; DB " ",0
; ------------------------------------------------------
; Custom commands
; ------------------------------------------------------
CMD_QUIT
DB "QUIT\r",0
IF DEBUG == 1
CMD_TEST1 DB "ATE0\r\n",0
BUFF_TEST1 DS RS_BUFF_SIZE,0
ENDIF
ENDMODULE
INCLUDE "wcommon.asm"
INCLUDE "util.asm"
INCLUDE "isa.asm"
INCLUDE "esplib.asm"
END MAIN.START

View File

@ -1,314 +0,0 @@
/*
==================================================
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);
}
}