;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Sending experimental data from MenuetOS in UDP packet
;;
;;  Compile with FASM for Menuet
;;
;;  In this sample I have 
;;  a. deleted all incremental rotary counters drivers
;;  b. deleted A/D board drivers
;;
;;  UDP packet size - 96 bytes
;;
;;  Sending of cca 250 packets WITHOUT queue overflow
;;  but with >10 miliseconds between each UDP packet
;;
;;  HW  Assus P4S800D motherboard, Celeron 2.66GHz, 512MB ram SiS900 chipset
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

use32

    org  0x0

    db   'MENUET00'                 ; 8 byte id
    dd   38                         ; required os
    dd   START                      ; program start
    dd   I_END                      ; program image size
    dd   0x100000                   ; required amount of memory
    dd   0x00000000                 ; reserved=no extended header

START:                              ; start of execution

    call rdtsc_timeoverhead         ; measure the timeoverhead zero the DataRamp

    call apply_stack_setup          ; configure TCP/IP stack

    mov  eax, 0xff                  ; Nr. of packets to send
    mov  dword [samples], eax

    mov  dword [udpdatalen], expdatalen - expdata
                                    ; length od the datastructure to send

    mov  eax, 53                    ; open UDP socket
    mov  ebx, 0
    mov  ecx, 0x3000                ; local port        0x3000 - 12288dec
    mov  edx, 0x3000                ; remote port
    mov  esi, dword [remote_ip]     ; remote IP         192.168.000.190
    int  0x40

    mov  [socketNum], eax           ; store the socketNum

vik1:

    inc  dword [DataRamp]           ; One based increment DataRamp counter

    call rdtsc_now                  ; Actualise DataTime
    call read_irc_a
    call read_irc_b
    call read_irc_c
    call read_irc_t
    call read_irc_d
    call read_irc_r
    call read_irc_i00               ; i/o from irc_a - irc_c
    call read_irc_i01               ; i/o from irc_t - irc_r

    mov  eax, 53                    ; write UDP socket
    mov  ebx, 4
    mov  ecx, [socketNum]
    mov  edx, [udpdatalen]          ; length of the datastructure
    mov  esi, expdata
    int  0x40

    dec  dword [samples]
    jnz  vik1

    mov  eax, 53                    ; close UDP socket
    mov  ebx, 1
    mov  ecx, [socketNum]
    int  0x40

    mov  [socketNum], dword 0       ; redundant

    mov  eax, -1                    ; end
    int  0x40


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_a:

    mov  eax, 0x00001001
    mov  dword [irc_a], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_b:

    mov  eax, 0x00001002
    mov  dword [irc_b], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_c
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_c:

    mov  eax, 0x00001003
    mov  dword [irc_c], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_t
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_t:

    mov  eax, 0x00001004
    mov  dword [irc_t], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_d
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_d:

    mov  eax, 0x00001005
    mov  dword [irc_d], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_r
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_r:

    mov  eax, 0x00001006
    mov  dword [irc_r], eax

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_i00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_i00:

    mov  al, 0x07
    mov  byte [irc_i00], al

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  read_irc_r
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

read_irc_i01:

    mov  al, 0x08
    mov  byte [irc_i01], al

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; apply stack setup
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

apply_stack_setup:

    mov  eax, [com_irq]             ; pack values for config
    shl  eax, 8
    mov  ebx, [com_add]
    shl  ebx, 16
    add  eax, ebx
    add  eax, [interface]
    mov  ebx, [assigned]
    shl  ebx, 7
    add  eax, ebx
    mov  [config], eax

    mov  eax, 52                    ; set ip_address
    mov  ebx, 3
    mov  ecx, dword [ip_address]
    int  0x40

    mov  eax, 52                    ; set gateway_ip
    mov  ebx, 11
    mov  ecx, dword [gateway_ip]
    int  0x40

    mov  eax, 52                    ; set subnet_mask
    mov  ebx, 12
    mov  ecx, dword [subnet_mask]
    int  0x40

    mov  eax, 52                    ; set dns_ip
    mov  ebx, 14
    mov  ecx, dword [dns_ip]
    int  0x40

    mov  eax, 52
    mov  ebx, 2
    mov  ecx, [config]              ; set config
    int  0x40

    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  RDTSC start to count clock cycles:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rdtsc_start:

    xor  eax, eax
    cpuid                           ; serialize
    rdtsc                           ; read clock counter
    mov  dword [StartTime], eax     ; LSB
    mov  dword [StartTime+4], edx   ; MSB
    xor  eax, eax
    cpuid                           ; serialize again
    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  RDTSC now and evaluate time delay
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rdtsc_now:

    xor  eax, eax
    cpuid                           ; serialize
    rdtsc                           ; read clock
    mov  dword [DataTime], eax      ; store clock count
    mov  dword [DataTime+4], edx
    xor  eax, eax
    cpuid                           ; serialize again
    mov  eax, dword [StartTime]
    mov  edx, dword [StartTime+4]
    add  eax, [TimeOverhead]        ; subtract the number of clocks used by surrounding code
    adc  edx, 0
    sub  dword [DataTime], eax      ; subtract overhead from clock count
    sbb  dword [DataTime+4], edx
    mov  eax, dword [DataTime]
    mov  dword [TimeStamp], eax     ; UDP TimeStamp
    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  RDTSC actualize timeoverhead on local machine. Must be called first
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rdtsc_timeoverhead:

    xor  eax, eax                   ; clear eax
    mov  dword [TimeOverhead], eax  ; zero the TimeOverhead
    mov  dword [DataRamp], eax      ; zero the DataRamp
    call rdtsc_start                ; start overhead measurement
    call rdtsc_now                  ; stop overhead measurement
    mov  eax, dword [DataTime]      ; poiter to LSB 32 bit result
    mov  dword [TimeOverhead], eax  ; store as TimeOverhead
    ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

remote_ip       db  192,168,000,190     ; WINPC IP

ip_address      db  192,168,000,191     ; MENOS IP
gateway_ip      db  192,168,000,001     ; my LAN
subnet_mask     db  255,255,255,000     ;
dns_ip          db  217,011,229,001     ;

com_irq         dd  0                   ; no irq for slip/ppp
com_add         dd  0                   ; no COMX port address for slip/ppp
interface       dd  3                   ; not active,slip,ppp,packet driver
assigned        dd  0                   ; 0 or 1 = get ip from server

config          dd  0                   ; summary from com settings

socketNum       dd  0x0                 ; Socket Number

StartTime       dq  ?                   ; RDTSC clock cycles start count
DataTime        dq  ?                   ; RDTSC clock cycles from start
TimeOverhead    dd  0                   ; RDTSC machine & calling structure

irc_a           dd  0x00000001          ; irc_a actual value
;samples         dd  0                   ; Nr pf samples = packets to send

udpdatalen:     dd  0x00                ; length of datastructure to transfer

expdata:                                ; start of the datastructure to transfer

DataRamp        dd  0                   ; UDP data ramp counter
TimeStamp       dd  0                   ; UDP time stamp = LSB of DataTime
;irc_a           dd  0x00000001          ; irc_a actual value
samples         dd  0                   ; Nr pf samples = packets to send
irc_b           dd  0x00000002          ; irc_b actual value
irc_c           dd  0x00000003          ; irc_c actual value
irc_t           dd  0x00000004          ; irc_t actual value
irc_d           dd  0x00000005          ; irc_d actual value
irc_r           dd  0x00000006          ; irc_r actual value
a00             dw  0x00000010          ; Analog value channel 0 
a01             dw  0x00000011          ; Analog value channel 1 
a02             dw  0x00000012          ; Analog value channel 2 
a03             dw  0x00000013          ; Analog value channel 3 
a04             dw  0x00000014          ; Analog value channel 4 
a05             dw  0x00000015          ; Analog value channel 5 
a06             dw  0x00000016          ; Analog value channel 6 
a07             dw  0x00000017          ; Analog value channel 7 
irc_i00         db  0x5A                ; Digital input 00
irc_i01         db  0xA5                ; Digital input 01

expdatalen:                             ; end of the datastructure to transfer

I_END:

