mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-06-28 13:29:37 +00:00
Added context to W5100 UDP driver.
In order to ease exploring the W5100 UDP driver a simple test program using it was added. Additionally a communication peer program was introduced. The latter builds as-is for Windows using i.e. the VC++ command line 'cl w5100_peer.c'.
This commit is contained in:
parent
ae98e5c01d
commit
c9af38790a
|
@ -29,24 +29,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
******************************************************************************/
|
||||
|
||||
ptr := $06 ; 2 byte pointer value
|
||||
tmp := $08 ; 1 byte temporary value
|
||||
bas := $09 ; 1 byte socket 1 Base Address (hibyte)
|
||||
sha := $19 ; 2 byte physical addr shadow ($F000-$FFFF)
|
||||
len := $1B ; 2 byte frame length
|
||||
adv := $1D ; 2 byte pointer register advancement
|
||||
|
||||
mode := $C0C4
|
||||
addr := $C0C5
|
||||
data := $C0C7
|
||||
|
||||
.export init
|
||||
.export recv_init, recv_byte, recv_done
|
||||
.export send_init, send_byte, send_done
|
||||
|
||||
ptr := $06 ; 2 byte pointer value
|
||||
sha := $08 ; 2 byte physical addr shadow ($F000-$FFFF)
|
||||
adv := $EB ; 2 byte pointer register advancement
|
||||
len := $ED ; 2 byte frame length
|
||||
tmp := $FA ; 1 byte temporary value
|
||||
bas := $FB ; 1 byte socket 1 Base Address (hibyte)
|
||||
|
||||
mode := $C0B4
|
||||
addr := $C0B5
|
||||
data := $C0B7
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
init:
|
||||
; Input
|
||||
; AX: Address of ip_parms (serverip, cfg_ip, cfg_netmask, cfg_gateway)
|
||||
; Output
|
||||
; None
|
||||
; Remark
|
||||
; The ip_parms are only accessed during this function.
|
||||
|
||||
; Set ip_parms pointer
|
||||
sta ptr
|
||||
stx ptr+1
|
||||
|
@ -99,6 +106,11 @@ init:
|
|||
; -> A is still $0A
|
||||
sta data
|
||||
|
||||
; Socket 1 Source Port Register: 6502
|
||||
ldy #$04
|
||||
jsr set_addrsocket1
|
||||
jsr set_data6502
|
||||
|
||||
; Socket 1 Destination IP Address Register: Destination IP address
|
||||
; This has to be the last call to set_ipv4value because it writes
|
||||
; as a side effect to 'hdr' and it is the destination IP address
|
||||
|
@ -112,11 +124,6 @@ init:
|
|||
; -> addr is already set
|
||||
jsr set_data6502
|
||||
|
||||
; Socket 1 Source Port Register: 6502
|
||||
ldy #$04
|
||||
jsr set_addrsocket1
|
||||
jsr set_data6502
|
||||
|
||||
; Socket 1 Mode Register: UDP
|
||||
ldy #$00
|
||||
jsr set_addrsocket1
|
||||
|
@ -124,7 +131,7 @@ init:
|
|||
sta data
|
||||
|
||||
; Socket 1 Command Register: OPEN
|
||||
; addr is already set
|
||||
; -> addr is already set
|
||||
lda #$01
|
||||
sta data
|
||||
rts
|
||||
|
@ -153,12 +160,20 @@ set_data6502:
|
|||
;------------------------------------------------------------------------------
|
||||
|
||||
recv_init:
|
||||
; Input
|
||||
; None
|
||||
; Output
|
||||
; C: Clear if ready to receive
|
||||
; AX: If C is clear then number of bytes to receive
|
||||
; Remark
|
||||
; To be called before recv_byte.
|
||||
|
||||
; Socket 1 RX Received Size Register: 0 or volatile ?
|
||||
lda #$26 ; Socket RX Received Size Register
|
||||
jsr prolog
|
||||
bcs :+++
|
||||
|
||||
; Socket 0 RX Read Pointer Register
|
||||
; Socket 1 RX Read Pointer Register
|
||||
; -> addr already set
|
||||
|
||||
; Calculate and set pyhsical address
|
||||
|
@ -207,6 +222,13 @@ recv_init:
|
|||
;------------------------------------------------------------------------------
|
||||
|
||||
send_init:
|
||||
; Input
|
||||
; AX: Number of bytes to send
|
||||
; Output
|
||||
; C: Clear if ready to send
|
||||
; Remark
|
||||
; To be called before send_byte.
|
||||
|
||||
; Set pointer advancement
|
||||
sta adv
|
||||
stx adv+1
|
||||
|
@ -219,7 +241,7 @@ send_init:
|
|||
; Socket 1 TX Free Size Register: < advancement ?
|
||||
cpx adv ; Lobyte
|
||||
sbc adv+1 ; Hibyte
|
||||
bcc rts_cs
|
||||
bcc sec_rts ; Not enough free size -> error
|
||||
|
||||
; Socket 1 TX Write Pointer Register
|
||||
ldy #$24
|
||||
|
@ -240,7 +262,7 @@ prolog:
|
|||
; Socket 1 Command Register: 0 ?
|
||||
jsr set_addrcmdreg1
|
||||
ldx data
|
||||
bne rts_cs ; Not completed -> error
|
||||
bne sec_rts ; Not completed -> error
|
||||
|
||||
; Socket Size Register: not 0 ?
|
||||
tay ; Select Size Register
|
||||
|
@ -249,21 +271,30 @@ prolog:
|
|||
sta ptr+1 ; Hibyte
|
||||
ora ptr
|
||||
bne :+
|
||||
rts_cs: sec ; Error (size == 0)
|
||||
|
||||
sec_rts:
|
||||
sec ; Error (size == 0)
|
||||
rts
|
||||
|
||||
; Socket Size Register: volatile ?
|
||||
: jsr get_wordsocket1
|
||||
cpx ptr ; Lobyte
|
||||
bne rts_cs ; Volatile size -> error
|
||||
bne sec_rts ; Volatile size -> error
|
||||
cmp ptr+1 ; Hibyte
|
||||
bne rts_cs ; Volatile size -> error
|
||||
clc ; Sucess (size != 0)
|
||||
bne sec_rts ; Volatile size -> error
|
||||
clc ; Success (size != 0)
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
recv_byte:
|
||||
; Input
|
||||
; None
|
||||
; Output
|
||||
; A: Byte received
|
||||
; Remark
|
||||
; May be called as often as indicated by recv_init.
|
||||
|
||||
; Read byte
|
||||
lda data
|
||||
|
||||
|
@ -275,6 +306,13 @@ recv_byte:
|
|||
;------------------------------------------------------------------------------
|
||||
|
||||
send_byte:
|
||||
; Input
|
||||
; A: Byte to send
|
||||
; Output
|
||||
; None
|
||||
; Remark
|
||||
; Should be called as often as indicated to send_init.
|
||||
|
||||
; Write byte
|
||||
sta data
|
||||
|
||||
|
@ -283,14 +321,24 @@ send_byte:
|
|||
beq incsha
|
||||
rts
|
||||
|
||||
incsha:
|
||||
; Increment physical addr shadow hibyte
|
||||
incsha: inc sha+1
|
||||
inc sha+1
|
||||
beq set_addrbase
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
recv_done:
|
||||
; Input
|
||||
; None
|
||||
; Output
|
||||
; None
|
||||
; Remark
|
||||
; Mark data indicated by recv_init as processed (independently from how
|
||||
; often recv_byte was called), if not called then next call of recv_init
|
||||
; will just indicate the very same data again.
|
||||
|
||||
; Set parameters for commit code
|
||||
lda #$40 ; RECV
|
||||
ldy #$28 ; Socket RX Read Pointer Register
|
||||
|
@ -299,12 +347,22 @@ recv_done:
|
|||
;------------------------------------------------------------------------------
|
||||
|
||||
send_done:
|
||||
; Input
|
||||
; None
|
||||
; Output
|
||||
; None
|
||||
; Remark
|
||||
; Actually send data indicated to send_init (independently from how often
|
||||
; send_byte was called), if not called then send_init (and send_byte) are
|
||||
; just NOPs.
|
||||
|
||||
; Set parameters for commit code
|
||||
lda #$20 ; SEND
|
||||
ldy #$24 ; Socket TX Write Pointer Register
|
||||
|
||||
epilog:
|
||||
; Advance pointer register
|
||||
epilog: jsr set_addrsocket1
|
||||
jsr set_addrsocket1
|
||||
tay ; Save command
|
||||
clc
|
||||
lda ptr
|
||||
|
@ -319,7 +377,7 @@ epilog: jsr set_addrsocket1
|
|||
tya ; Restore command
|
||||
jsr set_addrcmdreg1
|
||||
sta data
|
||||
sec ; When coming from _recv_init -> error
|
||||
sec ; When coming from recv_init -> error
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
@ -336,6 +394,7 @@ set_addrphysical:
|
|||
ora #>$F000 ; Move sha/sha+1 to $F000-$FFFF
|
||||
sty sha
|
||||
sta sha+1
|
||||
|
||||
set_addr:
|
||||
stx addr ; Hibyte
|
||||
sty addr+1 ; Lobyte
|
||||
|
@ -345,6 +404,7 @@ set_addr:
|
|||
|
||||
set_addrcmdreg1:
|
||||
ldy #$01 ; Socket Command Register
|
||||
|
||||
set_addrsocket1:
|
||||
ldx #>$0500 ; Socket 1 register base address
|
||||
bne set_addr ; Always
|
||||
|
|
|
@ -118,8 +118,16 @@ ip65demo.dsk: httpd.bin httpd-slotscan.bin
|
|||
java -jar $(AC) -cc65 $@ webserver-slot3 B < httpd.bin
|
||||
java -jar $(AC) -cc65 $@ webserver-slotscan B < httpd-slotscan.bin
|
||||
|
||||
w5100_%.bin: ../supplement/w5100_%.s w5100_%_s.s w5100_%_c.c
|
||||
cl65 -o $@ -t apple2enh -m $(basename $@).map $^
|
||||
|
||||
w5100.dsk: w5100_udp.bin
|
||||
cp prodos.dsk $@
|
||||
java -jar $(AC) -cc65 $@ udp bin < w5100_udp.bin
|
||||
|
||||
clean:
|
||||
make -C ../ip65 clean
|
||||
make -C ../drivers clean
|
||||
-rm -f *.prg *.bin *.vicprg *.map
|
||||
-rm -f ip65.d64 ip65.dsk ip65demo.dsk
|
||||
-rm -f ../supplement/*.o
|
||||
-rm -f *.o *.prg *.bin *.vicprg *.map
|
||||
-rm -f ip65.d64 ip65.dsk ip65demo.dsk w5100.dsk
|
||||
|
|
112
test/w5100_peer.c
Normal file
112
test/w5100_peer.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printf("Init\n");
|
||||
WSADATA wsa;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_DGRAM , IPPROTO_UDP);
|
||||
if (s == INVALID_SOCKET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u_long arg = 1;
|
||||
if (ioctlsocket(s, FIONBIO, &arg) == SOCKET_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SOCKADDR_IN local;
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_addr.s_addr = INADDR_ANY;
|
||||
local.sin_port = htons(6502);
|
||||
if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SOCKADDR_IN remote;
|
||||
remote.sin_addr.s_addr = INADDR_NONE;
|
||||
|
||||
printf("(S)end or e(X)it\n");
|
||||
char key;
|
||||
do
|
||||
{
|
||||
int len;
|
||||
unsigned char buf[1500];
|
||||
|
||||
if (kbhit())
|
||||
{
|
||||
key = getch();
|
||||
}
|
||||
else
|
||||
{
|
||||
key = '\0';
|
||||
}
|
||||
|
||||
if (key == 's')
|
||||
{
|
||||
if (remote.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
printf("Peer Addr Unknown As Yet\n", len);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
len = 512;
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
buf[i] = i;
|
||||
}
|
||||
printf("Send Len $%04X To %s", len, inet_ntoa(remote.sin_addr));
|
||||
if (sendto(s, buf, len, 0, (SOCKADDR *)&remote, sizeof(remote)) == SOCKET_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
printf(".\n");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned remote_size = sizeof(remote);
|
||||
len = recvfrom(s, buf, sizeof(buf), 0, (SOCKADDR *)&remote, &remote_size);
|
||||
if (len == SOCKET_ERROR)
|
||||
{
|
||||
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
len = 0;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
printf("Recv Len $%04X From %s", len, inet_ntoa(remote.sin_addr));
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
if ((i % 24) == 0)
|
||||
{
|
||||
printf("\n$%04X:", i);
|
||||
}
|
||||
printf(" %02X", buf[i]);
|
||||
}
|
||||
printf(".\n");
|
||||
}
|
||||
}
|
||||
while (key != 'x');
|
||||
|
||||
closesocket(s);
|
||||
WSACleanup();
|
||||
printf("Done\n");
|
||||
}
|
96
test/w5100_udp_c.c
Normal file
96
test/w5100_udp_c.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
|
||||
void __fastcall__ init(void *parms);
|
||||
|
||||
unsigned recv_init(void);
|
||||
unsigned char recv_byte(void);
|
||||
void recv_done(void);
|
||||
|
||||
unsigned __fastcall__ send_init(unsigned len);
|
||||
void __fastcall__ send_byte(unsigned char val);
|
||||
void send_done(void);
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned char serverip [4];
|
||||
unsigned char cfg_ip [4];
|
||||
unsigned char cfg_netmask[4];
|
||||
unsigned char cfg_gateway[4];
|
||||
}
|
||||
parms =
|
||||
{
|
||||
{192, 168, 0, 2},
|
||||
{192, 168, 0, 123},
|
||||
{255, 255, 255, 0},
|
||||
{192, 168, 0, 1}
|
||||
};
|
||||
|
||||
void main(void)
|
||||
{
|
||||
char key;
|
||||
|
||||
videomode(VIDEOMODE_80COL);
|
||||
printf("Init\n");
|
||||
init(&parms);
|
||||
|
||||
printf("(S)end or e(X)it\n");
|
||||
do
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if (kbhit())
|
||||
{
|
||||
key = cgetc();
|
||||
}
|
||||
else
|
||||
{
|
||||
key = '\0';
|
||||
}
|
||||
|
||||
if (key == 's')
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
len = 512;
|
||||
printf("Send Len $%04X To %d.%d.%d.%d", len, parms.serverip[0],
|
||||
parms.serverip[1],
|
||||
parms.serverip[2],
|
||||
parms.serverip[3]);
|
||||
while (!send_init(len))
|
||||
{
|
||||
printf("!");
|
||||
}
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
send_byte(i);
|
||||
}
|
||||
send_done();
|
||||
printf(".\n");
|
||||
}
|
||||
|
||||
len = recv_init();
|
||||
if (len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
printf("Recv Len $%04X From %d.%d.%d.%d", len, parms.serverip[0],
|
||||
parms.serverip[1],
|
||||
parms.serverip[2],
|
||||
parms.serverip[3]);
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
if ((i % 24) == 0)
|
||||
{
|
||||
printf("\n$%04X:", i);
|
||||
}
|
||||
printf(" %02X", recv_byte());
|
||||
}
|
||||
recv_done();
|
||||
printf(".\n");
|
||||
}
|
||||
}
|
||||
while (key != 'x');
|
||||
|
||||
printf("Done\n");
|
||||
}
|
41
test/w5100_udp_s.s
Normal file
41
test/w5100_udp_s.s
Normal file
|
@ -0,0 +1,41 @@
|
|||
.export _init
|
||||
.export _recv_init, _recv_byte, _recv_done
|
||||
.export _send_init, _send_byte, _send_done
|
||||
|
||||
.import init
|
||||
.import recv_init, recv_byte, recv_done
|
||||
.import send_init, send_byte, send_done
|
||||
|
||||
_init:
|
||||
jmp init
|
||||
|
||||
_recv_init:
|
||||
jsr recv_init
|
||||
bcc :+
|
||||
lda #<$0000
|
||||
ldx #>$0000
|
||||
: rts
|
||||
|
||||
_recv_byte:
|
||||
jsr recv_byte
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
_recv_done:
|
||||
jmp recv_done
|
||||
|
||||
_send_init:
|
||||
jsr send_init
|
||||
bcc :+
|
||||
lda #<$0000
|
||||
ldx #>$0000
|
||||
rts
|
||||
: lda #<$0001
|
||||
ldx #>$0001
|
||||
rts
|
||||
|
||||
_send_byte:
|
||||
jmp send_byte
|
||||
|
||||
_send_done:
|
||||
jmp send_done
|
Loading…
Reference in New Issue
Block a user