Mon 16 Mar 11:09:06 CET 2026
This commit is contained in:
parent
0ce3ca9e74
commit
d402bb4128
200
src/net.h
Normal file
200
src/net.h
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
#ifndef _NET_H
|
||||||
|
#define _NET_H
|
||||||
|
#if HAS_NET > 0
|
||||||
|
/*
|
||||||
|
==== Communication Ports ====
|
||||||
|
Link: Connection between ports
|
||||||
|
|
||||||
|
Logical/virtual ports are buffered async. IO devices:
|
||||||
|
- External access via buffers only,
|
||||||
|
- Internal reading and writing from physical serial channels in the background (via main IO loop).
|
||||||
|
Ports and links between ports operate message-based. VM send messages to port.
|
||||||
|
Serial Channel -> PortReceiver(L) -> AllocateMessage(M) -> Process(M) -> FinalizeMessage(M=
|
||||||
|
VM IN/OUT API via generic INBYTE/OUTBYTE passed to port InByte(M),OutByte(M)
|
||||||
|
Outgoing messages: PortOutByte -> AllocateMessage(M) -> PortRoute(P)
|
||||||
|
INBYTE/OUTBYTE: IO multiplexer: Real file desciptor IO and logical port access …(via port structures and buffers)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTBUFFERSIZE
|
||||||
|
#define PORTBUFFERSIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EOM
|
||||||
|
#define EOM '\n'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Maximal number of ports
|
||||||
|
#ifndef NUMPORTS
|
||||||
|
#define NUMPORTS 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NETTIMEOUT
|
||||||
|
// rx timeout in ms
|
||||||
|
#define NETTIMEOUT 200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RINGDECR(index,size) index=(index==0?size-1:index-1)
|
||||||
|
#define RINGINCR(index,size) index=((index+1)%size)
|
||||||
|
#define RINGLEN(start,end,size) end<start?end+size-start:end-start+1
|
||||||
|
|
||||||
|
#define MSGRX 0x1000
|
||||||
|
#define MSGTX 0x2000
|
||||||
|
#define MSGTYPEMASK 0x1F
|
||||||
|
#define MSGTYPE(t) t&MSGTYPEMASK
|
||||||
|
#define MSGDIR(t) t&(MSGRX|MSGTX)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MSGCOMMAND = 1, // ]command[ : one single program line executed immed. if VM is PIDLE
|
||||||
|
MSGPROGRAM, // [program] : one single (multi-line) main program, compiled, reset VM, run
|
||||||
|
MSGPROGRAMPART, // [[program]] : one part of a main program, compiled
|
||||||
|
MSGDATA, // !data! : not passed to VM program, must be processed by host application
|
||||||
|
MSGEVENT, // %event% : raises VM event
|
||||||
|
MSGUSER, // $message$ : passed to VM program, can be processed by ? operator
|
||||||
|
MSGNET, // Prefix control message (for routing), @dx,dy@, @^@, @~@, @*@, @id..@, @locate..@
|
||||||
|
MSGCONSOLE, // #message# : like MSGDATA
|
||||||
|
MSGMAXNUM,
|
||||||
|
MSGSKIP, // A virtual marker that requires a ring buffer wrap around (to bottom of buffer),
|
||||||
|
// i.e., the next message starts at 0 (remaining space cannot hold buffer mapped binary structures, which must be linear in memory)
|
||||||
|
MSGFREE // free message block in rx/tx buffer
|
||||||
|
} message_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LDEAD=0,
|
||||||
|
LIDLE,
|
||||||
|
LSTART, // waiting for first message delimiter
|
||||||
|
LPARSING, // processing content of a message
|
||||||
|
LPREEND, // awaiting second message delimiter?
|
||||||
|
LEND // finalize, go to start
|
||||||
|
} port_state_t;
|
||||||
|
|
||||||
|
#if HAS_NET_ROUTING > 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Message handled by ports (input as well as output), administrative message header stored in rx/tx buffers
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
index_t type; //message_type_t
|
||||||
|
index_t start;
|
||||||
|
index_t end; // wrap around in ring buffer?
|
||||||
|
index_t port;
|
||||||
|
} message_t;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Network module with extended routing, ingoing (rx) and outgoing (tx) messages are buffered.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Network control message (prefix of another message or stand-alone)
|
||||||
|
It is directly mappend in rx/tx buffer (parsed in place(
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NCMUP = 'u',
|
||||||
|
NCMDOWN = 'd',
|
||||||
|
NCMMULTICAST = 'm',
|
||||||
|
NCMUNICAST = '1',
|
||||||
|
NCMID = 'i',
|
||||||
|
NCMDELTA = 'D'
|
||||||
|
} control_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(Optional) Message prefix for routing
|
||||||
|
@u@ | @u,hopx,hopy@
|
||||||
|
@d@ | @d,hopx,hopy@
|
||||||
|
@D,dx,dy,dx0,dy0@
|
||||||
|
@m,range@
|
||||||
|
Some messages have default routing strategies:
|
||||||
|
!! => Up
|
||||||
|
[] => Down (always broadcast)
|
||||||
|
%% => Down (always broadcast)
|
||||||
|
## => Up
|
||||||
|
*/
|
||||||
|
#ifndef MAXNCMARGS
|
||||||
|
#define MAXNCMARGS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
char type; // control_type_t
|
||||||
|
int8_t narg; // number of args
|
||||||
|
int8_t args[MAXNCMARGS]; // dynamic array
|
||||||
|
} message_control_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* linear buffer */
|
||||||
|
char *rxBuffer;
|
||||||
|
/* ring buffer */
|
||||||
|
char *txBuffer;
|
||||||
|
index_t rxBottom;
|
||||||
|
index_t rxTop; // points to next free message block
|
||||||
|
index_t txBottom;
|
||||||
|
index_t txTop;
|
||||||
|
char busy;
|
||||||
|
index_t rd; // unix: fd
|
||||||
|
index_t wr; // unix: fd
|
||||||
|
port_state_t state; // message parser state
|
||||||
|
message_t *rxCurrent; // currently processed (non-fixed) message
|
||||||
|
message_t *txCurrent;
|
||||||
|
int (**handlers)(); // int foo(port_t *,message_t *)
|
||||||
|
index_t index;
|
||||||
|
} port_t;
|
||||||
|
|
||||||
|
extern port_t **Ports;
|
||||||
|
message_t *CurrentInputMessage[NUMPORTS]; // for PLX ? operator
|
||||||
|
message_t *CurrentOutputMessage[NUMPORTS]; // for PLX ! operator
|
||||||
|
int PortsDown[NUMPORTS],PortsUp[NUMPORTS]; // keep track for up and down ports
|
||||||
|
|
||||||
|
/* if buffer==NULL the rx+tx buffer is allocated, else buffer=char[NUMPORTS*PORTBUFFERSIZE] */
|
||||||
|
void NetInit(int (**handlers)(),port_t **ports, char *buffer);
|
||||||
|
|
||||||
|
message_t *AllocateMessage(port_t *P,message_type_t t);
|
||||||
|
message_t *FinalizeMessage(message_t *m);
|
||||||
|
void FreeMessage(message_t *m);
|
||||||
|
#if HAS_NET_ROUTING > 0
|
||||||
|
int NetControlMessage(port_t *P, char type,index_t a, index_t b);
|
||||||
|
#endif
|
||||||
|
int PortReceiver(port_t *L);
|
||||||
|
/*
|
||||||
|
Read one byte from message
|
||||||
|
*/
|
||||||
|
int PortInByte(message_t *m);
|
||||||
|
/*
|
||||||
|
Add one byte to message
|
||||||
|
*/
|
||||||
|
int PortOutByte(message_t *m, char ch);
|
||||||
|
|
||||||
|
void PrintPortMessages(port_t *L);
|
||||||
|
#else /* ! HAS_NET_ROUTING: NET0 */
|
||||||
|
/* net0: only 1 port */
|
||||||
|
typedef struct {
|
||||||
|
/* shared buffer=[rxBuffer,inputBuffer] */
|
||||||
|
/* linear buffer, grows to top */
|
||||||
|
char *rxBuffer; // all messages not passed to the VM input layer
|
||||||
|
/* circular buffer, grows to bottom, wrap around at PORTBUFFERSIZE/2, reset to high water if top==bottom */
|
||||||
|
char *inputBuffer; // all messages passed to the VM input layer
|
||||||
|
index_t rxBottom;
|
||||||
|
index_t rxTop; // points to next free byte
|
||||||
|
index_t rxStart; // begin of current message in buffer (rx/input)
|
||||||
|
int rxLast; // timestamp of last received char
|
||||||
|
index_t inputBottom;
|
||||||
|
index_t inputTop; // points to next free byte
|
||||||
|
message_type_t rxCurrent; // current received message
|
||||||
|
|
||||||
|
char busy;
|
||||||
|
index_t rd; // unix: fd
|
||||||
|
index_t wr; // unix: fd
|
||||||
|
port_state_t rxState; // receiver message parser state
|
||||||
|
int (**handlers)(); // int foo(port_t *,message_type_t)
|
||||||
|
} port_t;
|
||||||
|
|
||||||
|
extern port_t *Port;
|
||||||
|
/* if buffer==NULL the rx+in buffer is allocated, else buffer=char[NUMPORTS*PORTBUFFERSIZE] */
|
||||||
|
void NetInit(int (**handlers)(),port_t *port, char *buffer);
|
||||||
|
int PortAvailByte(int id);
|
||||||
|
int PortInByte(int id);
|
||||||
|
int PortOutByte(int od, char ch);
|
||||||
|
int PortReceiver();
|
||||||
|
#endif
|
||||||
|
#endif /* !HAS_NET */
|
||||||
|
#endif /* _NET_H */
|
||||||
Loading…
Reference in New Issue
Block a user