Bdyssh! // Бдыщщь!

fapfapfapfapfapfap, %username%!

14.09.2012, 13:07
Uncategorized // http://bdyssh.ru/?p=988

Исходный код микропрограммы устройства OSCaR / OSCaR microcontroller source code

Additionally to GPL, this program is catware.  
If you find it useful in any way, pay for this program by spending one hour petting one or several cats.
14-04-2014: SNMP v2c traps (snmptrap) added, port 162.
14-09-2013: SNMP v2c works, 8-bytes only community name,
 snmpwalk, snmpget & snmpset fully supported (string/hexstring, int).
10-02-2014: MIDI (qmidinet iface) small error fixed.

ВАЖНО: При том, что код является рабочим, это тем не менее ещё даже не первая выпущенная версия, а пока ещё, пре-релиз. Код сейчас проходит длительное производственное тестирование. Релиз будет выпущен только после получения данных об устойчивости кода при длительном тестировании в промышленных условиях.

Здесь находится текущая версия исходного кода микропрограммы для МК Atmel ATmega32a-AU TQFP44, который входит в состав платы OSCaR.

Язык программирования — Ассемблер, подмножество команд — Atmel AVR assembler instruction set.

Код состоит из одного файла. Логически код содержит постоянную часть, необходимую, в основном, для работы с Wiznet W5100, и изменяемые части, для поддержки различных подключаемых к плате OSCaR дочерних плат (функций). Переключение производится командой .define <имя_функции>.

Типы дочерних плат-потребителей PoE могут меняться произвольно и независимо от кода.

Предыдущие версии кода недоступны.

Для компиляции необходим файл Atmel m32def.inc.

Проверена компиляция транслятором avra, командой avra <имя_файла.asm>.

IMPORTANT: While this code is working well, this is still not even first release version. This is currently pre-release for beta testing. The code is under heavily testing at industrial conditions now. Release version will be issued after these stress-testings pass.

Here is the primary place to get current source code for Atmel ATmega32a-AU TQFP44 microcontroller, which is included in OSCaR module main board.

It is written in Assembly language, and assembler command subset is Atmel AVR assembler instruction set.

The code contains only one file.

It can be logically divided to constant part, which is daughterboard-independent, and changeable part of code, for particular daughterboard. They switches using .define <function> command.

The PoE daughterboards can be changed freely without changes in source code.

Previous versions of this source code are not available.

You need Atmel m32def.inc for compile this code.

I use avra for compile it, and command is avra <filename.asm>.

 

Tip: To select all code, use double-click on the code, and wait a bit.

; inc/dec DO NOT AFFECT CARRY FLAG!

.define mega32
; default xtal is 14.7456, but for 3.3 volts we need 7.3728.
.define xtal73728

.ifdef mega32
.INCLUDE "m32def.inc"
;.message "OJ!!"	; compile-time only
.endif

.ifdef mega16
.INCLUDE "m16def.inc"
.endif

; universal w5100 OSCAR board 76*29 mm
; author: jopka1@gmail.com, license: Creative Commons
; thanks to avrfreaks site for quick start in AVR world.
; some of daughterboards supported:
; rs232telnet
; rs485telnet    ; both 422, 485 has same software (mode select pin exist)
; changed to srvctrl? -- rs232srvctrl
; at17prog    uses twi
; ad7680 - two type, ad8318 & ad8223 sensors, same time.

; define only one of... :

; MIDI multicast also  rs232telnet mode, but see below.

;.define rs232telnet
;.define serial_setup



;.define eeprom_prog


;;;.define reserved_at17prog ; else - work spi

;.define at17prog
;.define at45spiprog


; this also may be used for initial config (new eeprom populate),
; then use rs232 console to config, select at least 'defaults' and 'random MAC addr' in console.
;.define srvctrl

; adf4350, adf4360, ad9910, probably other SPI
;.define adSPIctl

;.define ad9910
.ifdef ad9910
	.define adSPIctl 
.endif


; for midi work - use 16M xtal.
;.define midi

;.define ad7680


; R00 uses:
; - when serial, it is timeout for auto disconnect
; - when eeprom_prog, it is detected daughterboard type (SPI, TWI, both, etc)
; snmp - parameter index.
; ... add your own


; new proect - finger sensor. 256 byte packets contains just readed
; digital inputs. Then software try to knows bio-potentials when compare
; boundaries of level change in inputs, caused by AC 100/120 Hz signals
; from fingers.
;.define aura

; test web server. It's work! woohoo!
;.define webserver

; snmp v2c.   uses udp port 161, so use this port in settings.
.define snmp

.ifdef snmp
	.ifndef xtal73728
		.define xtal73728
	.endif
	.define udp
;	.define	multicast
;   .define sendid
	.define	use_serial_port_rx
	.define	use_serial_port_tx
	.define	use_serial_ctrl0_pins
; enable it for anything except "snmp_smarthome".
	.define	use_serial_leds

	.define	use_ds18b20_pin

; enable only one of the following SNMP submodules:
;	.define	snmp_mtf ; MTF modems ISTOK - read/write (get/set) strings
;	.define	snmp_floks
	.define	snmp_smarthome
		.undef	use_serial_leds
		.define rotary_encoder
;		.define irtransmit
;		.define rcpwm
;		.define rcpwm2
	.define	snmptrap
.endif

; this is not work, unfortunately. :-(
;.ifdef snmp_smarthome
;	.ifdef use_serial_leds
;		.undef use_serial_leds
;	.endif
;.endif


;.define rs232_RTSCTS_printer

.ifdef rs232_RTSCTS_printer
;	.define	SNI
	.define	use_serial_port_tx
	.define	use_serial_ctrl1_pins
	.define	use_serial_leds
.endif


; auto read something and send via ethernet without request.
; can be unicast and multicast.
; when unicast, need to test for opened TCP conn. before each send.
.ifdef aura
    ;.define autosend
;    .define sendid
;.define old_board	; remove it as soon as old boards are gone.
    .equ capabilitybyte0 = 0x11
    .equ capabilitybyte1 = 0x33
    .equ capabilitybyte2 = 0x55
    .equ capabilitybyte3 = 0x77
.endif


.ifdef srvctrl
	.define rs232telnet
	.define serial_setup
;    .define sendid
;    .equ capabilitybyte0 = 0x12
;    .equ capabilitybyte1 = 0x34
;    .equ capabilitybyte2 = 0x56
;    .equ capabilitybyte3 = 0x78
.endif


; for midi work - use 16M xtal.
.ifdef midi
	.define multicast ; currently probably only for rs232telnet
	.define rs232telnet
;	.define sendid

.endif


; define it for true matrix 8x8 keyboard (piano, etc).
; remember, if you need multiple pressed keys detection (chords at piano),
; the diode should be placed in series with each key button.
; see http://utmrobocon2011.blogspot.com/2011/03/matrix-keypad.html
; my comments to this article: it is more common to use running zero,
; rather than running '1', at scanning outputs. The reasons are:-
; 1. 74HC154 can be used to uC pins save. They mostly have inverted outputs.
; 2. inputs of uC will need pullups for running '0', or pulldowns for
; running '1'. You know than most uCs have only pullups.
; 3. These outputs often multiplexed with 7-seg. indicator, etc, they
; require running '0' for cathodes more often.
;.define matrix_keyboard

.ifdef matrix_keyboard
    .define multicast
    .define autosend
.endif

;.ifdef multicast
;.define rs232telnet
;.endif

.ifdef multicast
	.define udp
.endif

; added 09-09-2012: at least when MIDI, we do not need serial setup,
; because XTAL freq (16 MHz) not suitable for serial config.
.ifdef rs232telnet
    .define SNI
	.define	use_serial_port_rx
	.define	use_serial_port_tx
	.define	use_serial_leds
	.define	use_serial_ctrl0_pins
	.define	use_serial_ctrl1_pins
    .equ capabilitybyte0 = 0x54
    .equ capabilitybyte1 = 0x43
    .equ capabilitybyte2 = 0x32
    .equ capabilitybyte3 = 0x21
.endif

.ifdef rs485telnet
    .define SNI
    .equ capabilitybyte0 = 0x54
    .equ capabilitybyte1 = 0x43
    .equ capabilitybyte2 = 0x32
    .equ capabilitybyte3 = 0x21
.endif


; 31.03.2012 Trying to use DHCP.
; It is too hard :( and it requires seperate socket, port and UDP protocol,
; and IP must be re-requested periodically, but we do not have time for it. :(


; there are two mainboard leds and some different leds on some daughterboards.
; common indication: these are normal (grounded) unlike w5100 leds tied to vcc.
; ready led
.equ    ledRDYport = portd
.equ    ledRDYddr = ddrd
.ifdef old_board
  .equ    ledRDYbit = 3
.else
  .equ    ledRDYbit = 4        ; pin 13 (pd4)
.endif
; tcp connect led
.equ    ledTCPCONport = portc
.equ    ledTCPCONddr = ddrc
.equ    ledTCPCONbit = 2    ; pin 21 (pc2)

; swap pd3 and pd4 (rdy led and upper PCB port pin 4)
; due to pd3 is INT1 and need for PC Keyboard connect
; on all new boards.

; ! OLD ! ports on pcb:
;        (+3,3v)    pc1.sda    pd7    pd5    pd1.txd GND    <-- pin1
;        (+5v)    DCPU    pc0.scl    pd6    pd4 pd0.rxd    <-- pin2

; new	11	9	7	5	3	 1		(top)
;	(+3,3v)	pc1.sda	pd7	pd5	pd1.txd	 GND
;	(+5v)	DCPU	pc0.scl	pd6	pd3	 pd0.rxd
;	12	10	8	6	4	 2
		
;		2	4	6	8	 10		(bottom)
;		pb0	pb2	pb4.ss*	pb6.miso DCPU
;		GND	pb1	pb3	pb5.mosi pb7.sck
;		1	3	5	7	 9

; * if spi enabled (by fuses), pb4 not work :(

; DCPU - VCC of controller, should be connected to one of 3.3 or 5 volts
; on main pcb, and deliver power to daugter boards.

.ifdef srvctrl ; define additional to rs232telnet.
	.equ    mbledreadport = portb
	.equ    mbledreadddr = ddrb
	.equ    mbledreadpin = pinb
	.equ    mbled0inbit = 0        ; in & pullups:  "mbled" on sch
	.equ    mbled1inbit = 1
	.equ    mbled2inbit = 2
	.equ    mbled3inbit = 3
.endif

;.ifdef SNI
;	.define	use_serial_port_rx
;	.define	use_serial_port_tx
;	.define	use_serial_leds
;.endif

.ifdef use_serial_leds
	.equ    ledport = portb
	.equ    ledddr = ddrb
	.equ    ledIPRXbit = 7        ; out - "statusled" on schematic
	.equ    ledIPTXbit = 6
	.equ    ledRSRXbit = 5
	.equ    ledRSTXbit = 4
.endif

; pins 8,9 X1 - pc0, pc1
.ifdef use_serial_ctrl0_pins
; for rs232telnet - IN 9600 bit reset controls, IN echo
; for srvctrl     - IN 9600 bit reset controls, OUT channel
	.equ    ctl0port = portc
	.equ    ctl0ddr = ddrc
	.equ    ctl0pin = pinc
	.equ    ctl0force9600_and_relaybit = 0    ; in & pullup ; added 01-04-2012: this bit
; also used for relay control (becomes `out` after init; inverted.).
	.equ    ctl0channel_or_echobit = 1        ; for srvctrl, OUT - channel (motherboard) select 0 / 1,
; for rs232telnet,  IN: echo, 0 (short) = echo ON (for test wiring)
.endif

; pins 4,5,6,7 X1 - pd3, pd5, pd6, pd7
.ifdef use_serial_ctrl1_pins
; for srvctrl - srv ctrl b-uttons OUTs
	.equ    btnport = portd
	.equ    btnddr = ddrd
; for rs232telnet - OUT txen (for simplex), IN duplex, IN (deprecated) rs422rs485 levels active
	.equ    ctl1port = portd 
	.equ    ctl1ddr = ddrd
	.equ    ctl1pin = pind        ; inputs for rs232telnet 
; for srvctrl, OUT - commands to motherboards
	.equ    mbsw0bit_or_ctl1TXENbit = 3        ; for rs232telnet, OUT: rs485 TX en
	.equ    mbsw1bit_or_ctl1NODUPLEXbit = 5    ; for rs232telnet, IN: 0=duplex (rs422)  1 = simplex (rs485), (on 232 board must be 0=duplex but simplex should work also)
	.equ    mbsw2bit_or_ctl1INCTSbit = 6	; for rs232telnet IN: 0 = CTS-ready, 1 = CTS-busy
	.equ    mbsw3bit_or_ctl1OUTRTSbit = 7	; for rs232telnet OUT: 0 = RTS-ready, 1 = RTS-busy (not used now, and probably even don't configured as output - TODO)
.endif

; ds18b20 to-92   1-gnd, 2-DQ, 3-vcc
.ifdef use_ds18b20_pin
  .ifdef use_serial_ctrl1_pins
	Throw compiler error, conflict pins.
  .endif
	.equ    ds18b20port = portd
	.equ    ds18b20ddr = ddrd
	.equ    ds18b20pin = pind
	.equ    ds18b20IObit = 3	; pd3 pin 4 X1 - onewire i/f, dont forget to add R 4,7k
.endif


.ifdef snmp_smarthome
	.equ	smarthomeIOport = portb
	.equ	smarthomeIOddr = ddrb
	.equ	smarthomeIOportin = pinb
.endif

.ifdef irtransmit
 .define use_timer2_out
.endif

.ifdef rcpwm
 .define use_timer2_out
.endif

.ifdef use_timer2_out
	.equ	tm2port = portd
	.equ	tm2ddr = ddrd
	.equ	tm2bit = 7 		; pd7 pin 16: OC2 - HW TX IR/PWM generation.
.endif 

.ifdef rcpwm2
 .define use_timer0_out
	.equ	tm0port = portb
	.equ	tm0ddr = ddrb
	.equ	tm0bit = 3 		; pb3 pin 43: OC0 out.
.endif

; new	11	9	7	5	3	 1		(top)
;	(+3,3v)	pc1.sda	pd7	pd5	pd1.txd	 GND
;	(+5v)	DCPU	pc0.scl	pd6	pd3	 pd0.rxd
;	12	10	8	6	4	 2
		
;		2	4	6	8	 10		(bottom)
;		pb0	pb2	pb4.ss*	pb6.miso DCPU
;		GND	pb1	pb3	pb5.mosi pb7.sck
;		1	3	5	7	 9

.ifdef eeprom_prog

; twi (i2c) section: for AT17LV512A, etc.
.equ    progTWIport = portc
.equ    progTWIddr = ddrc
.equ    progTWIpin = pinc
.equ    progTWISCLbit = 0
.equ    progTWISDAbit = 1

; spi section: for at45db021d, en25f016, etc.
.equ    progSPIport = portb    ; this part use bits 4-7 for SPI programming
.equ    progSPIddr = ddrb
.equ    progSPIpin = pinb
.equ    progSPISCKbit = 7    ; o    pin 3 (pb7)    SCK out --> at45 CLK pin 2
.equ    progSPIMISObit = 6    ; i    pin 2 (pb6)    MISO in <--  at45 SO pin 8
.equ    progSPIMOSIbit = 5    ; o    pin 1 (pb5)    MOSI out --> at45 SI pin 1
.equ    progSPISSbit = 4    ; o    pin 44 (pb4)    SS out --> at45 /CS pin 4

; common parts:
; LED and power control (output)
.equ    progCTRLport = portb ; used bits 0-3 when SPI, or all bits when others (TWI etc)
.equ    progCTRLddr = ddrb
; these bits same on all programmer boards: some may be unused, but not changed.
.equ    progCTRLbit0 = 0	; red LED,  pin 40
.equ    progCTRLbit1 = 1	; green LED, pin 41
.equ    progCTRLbit2 = 2	; blue LED, pin 42
.equ    progCTRLbit3 = 3	; EEPROM power on/off (inverted), pin 43
; these bits are eeprom-dependent, but currently for at17 just tie to '1'... (fixme / add others)
.equ    progCTRLbit4 = 4	; bits 4-7 currently unconnected, future use
.equ    progCTRLbit5 = 5	;  for EN, CE,... etc. for control TWI chip.
.equ    progCTRLbit6 = 6	;  currently (unused) must outs '0'.
.equ    progCTRLbit7 = 7

; daughterboard type (capabilities) read (input), 4 bits, type 0...15
; type 0 - error / no board / reserved
; type 1 - TWI AT17 board
; type 2 - SPI AT45, EN25 board
; type 3 - both AT17 and AT45, EN25 supported
; type 4...15 reserved.
.equ    progTYPEport = portd
.equ    progTYPEddr = ddrd
.equ    progTYPEpin = pind
.equ    progTYPEbit0 = 3
.equ    progTYPEbit1 = 5
.equ    progTYPEbit2 = 6
.equ    progTYPEbit3 = 7

.endif



;.ifdef at17prog ; will become obsolete soon
;.equ    progTWIport = portc
;.equ    progTWIddr = ddrc
;.equ    progTWIpin = pinc
;.equ    progTWISCLbit = 0
;.equ    progTWISDAbit = 1
;.equ    eepromCTRLport = portb
;.equ    eepromCTRLddr = ddrb
;; probably two-color LED is controlled under software as other status pins,
;; so it not defined here. (?)
;.endif

;.ifdef at45spiprog
;; SPI i/o
;.equ    progSPIport = portb    ; this part use bits 4-7 for SPI programming
;.equ    progSPIddr = ddrb
;.equ    progSPIpin = pinb
;.equ    progSPISCKbit = 7    ; o    pin 3 (pb7)    SCK out --> at45 CLK pin 2
;.equ    progSPIMISObit = 6    ; i    pin 2 (pb6)    MISO in <--  at45 SO pin 8
;.equ    progSPIMOSIbit = 5    ; o    pin 1 (pb5)    MOSI out --> at45 SI pin 1
;.equ    progSPISSbit = 4    ; o    pin 44 (pb4)    SS out --> at45 /CS pin 4
;; here is 4-bit GPIO controlled by software, two bits used for two-color LED,
;; two other for CS pin and/or power on/off for AT17 series, or whatever.
;.equ    progCTRLport = portb ; this part uses bits 0-3
;.equ    progCTRLddr = ddrb
;.equ    progCTRLbit0 = 0 ; pin 40
;.equ    progCTRLbit1 = 1
;.equ    progCTRLbit2 = 2
;.equ    progCTRLbit3 = 3 ; pin 43
;.endif



.ifdef adSPIctl
.equ    adSPIctlddr=ddrb        ; bit0-bit3    bit4-7 is SPI programming
.equ    adSPIctlport=portb    ; if spi enabled (by fuses), bit4 not work :(
.equ    adSPIctlpin=pinb
.equ    adSPIctlCLKbit=7        ; o    pin 3 (pb7)    SCK out --> adSPIctl CLK
.equ    adSPIctlnotusedbit=6 
.equ    adSPIctlDATAbit=5    ; o    pin 1 (pb5)    MOSI out --> adSPIctl DATA
.equ    adSPIctlSSbit=4  
; two adSPIctl's
	.equ    adSPIctlaLEbit=0        ; o
	.equ    adSPIctlaLOCKbit=1    ; i
 .ifndef ad9910
	.equ    adSPIctlbLEbit=2        ; o
	.equ    adSPIctlbLOCKbit=3    ; i
 .else
	.equ    adSPIctlRESETbit=2    ; oot - positive active
	.equ    adSPIctlOSKbit=3    ; out - amplitude mod.
 .endif
.endif


.ifdef ad7680
.equ    ad7680ddr=ddrb        ; bit4-7 is SPI programming
.equ    ad7680port=portb    ; if spi enabled (by fuses), bit4 not work :(
.equ    ad7680pin=pinb
.equ    ad7680CLKbit=7        ; o     pin 3 (pb7)    SCK out -->  SCLK
.equ    ad7680DATAbit=6        ; i    pin 2 (pb6)    MISO in <--  SDATA
; two channels
.equ    ad7680aCSbit=0        ; o
.equ    ad7680aLEDbit=1        ; o
.equ    ad7680bCSbit=2        ; o
.equ    ad7680bLEDbit=3        ; o
.endif

;.ifdef aura
;;; try to use 8 bit now: pb0-pb3, pd4-pd7
;.equ    aura0ddr=ddrb        ; bit4-7 is SPI programming
;.equ    aura0port=portb        ; if spi enabled (by fuses), bit4 not work :(
;.equ    aura0pin=pinb
;.equ    aura1ddr=ddrd
;.equ    aura1port=portd
;.equ    aura1pin=pind
;.endif ; aura

.ifdef webserver
; reserved:
; add your i/o here.

.endif ; webserver

.ifdef matrix_keyboard
; we need 8 outputs and 8 inputs.
; or 3 outputs and HC154 3-to-8 multiplexer. And still 8 inputs.
; (74HC154, it's not error, 4-to-16 used as 3-to-8. Just because
; HC154 is "must have" part. Note that outputs are active "0".)
; .....but we don't have the mux now. So 8+8 pins need.
.equ    mkout0ddr=ddrd        ; pd0,1,4,5,6,7
.equ    mkout1ddr=ddrc        ; pc0,1
.equ    mkout0port=portd
.equ    mkout1port=portc
.equ    mkout0bit0 = 0     ; pd0
.equ    mkout0bit1 = 1     ; pd1
;.equ    mkout0bit2 = 4     ; pd4
.equ    mkout0bit2 = 3     ; pd4
.equ    mkout0bit3 = 5     ; pd5
.equ    mkout0bit4 = 6     ; pd6
.equ    mkout0bit5 = 7     ; pd7
.equ    mkout1bit6 = 0     ; pc0
.equ    mkout1bit7 = 1     ; pc1

.equ    mkinddr=ddrb
.equ    mkinport=portb
.equ    mkinpin=pinb
.endif    ; matrix_keyboard


; mainboard - common pins
.equ    eep_settings_base=0
.ifdef snmp_MTF
	.equ    eep_SNMPsettings_base=0x40
.endif
.ifdef snmp_floks
	.equ    eep_SNMPsettings_base=0x40
.endif
.ifdef snmp_smarthome
	.equ    eep_SNMPsettings_base=0x40
.endif
.ifdef srvctrl
	.equ    eep_keywords_base=0x100
.endif
.equ    w5100ctrlport=portc
.equ    w5100ctrlddr=ddrc
.equ    RDbit = 3    ; pin 22
.equ    WRbit = 4    ; pin 23
.equ    CSbit = 5    ; pin 24
.equ    A0bit = 6    ; pin 25
.equ    A1bit = 7    ; pin 26

.ifdef aura
; maximize tx q'ty. maybe for web server we need the same.
    .equ    rxpktmaxlen = 256
.else
 .ifdef mega16 ; 1kb RAM
    .equ    rxpktmaxlen = 512
 .endif
 .ifdef mega32 ; 2kb RAM
    .equ    rxpktmaxlen = 1024+256
 .endif
.endif

.ifdef mega16 ; 1kb RAM
	.equ    txpktmaxlen = SRAM_SIZE - rxpktmaxlen - 0xb0
.else
	.equ    txpktmaxlen = 1536 - rxpktmaxlen
.endif

.dseg    ; 0x60
;.ORG    SRAM_START
;.ORG    SRAM_START+1024
.org 0x0100
;buf:    ;;;; only for initial setup use, before rx interrupt enabled,
;;;; we can use all RAM as one buffer (usually tx buf)
txbuf:
    .byte txpktmaxlen
txbufend:
rxbuf:
    .byte rxpktmaxlen
rxbufend:

.ifdef matrix_keyboard
; if we use 8x8 keyboard then to detect press and releases,
; we need 64 bits. Almost can't hold it in registers... :-(
    mkstate:    .byte 8
.endif    ; matrix_keyboard



;.ifdef rs232telnet  ; changed 21-04-2013
.ifdef srvctrl  
; commands are zero-term.  commands #0..#7 are user (modifiable).
; "command" #8 for ignore telnet's answer looks like 'ff fd 01 ff fd 03'
; command #9 - try to make http loopback... can it work?!

; max 11 due to RAM limit :-(
.equ    cmd_qty_total = 11    ; no more than 16 allowed due to 'swap' instruction
; commands modified by user:
.equ    cmd_qty_user = 8    ; no more than 16 allowed due to 'swap' instruction

    ram_kw:        .byte 32*cmd_qty_total ; ram keywords (copy from eeprom)
    ram_kw_end:
.equ    ignoreseq_num = 8;
.equ    httpreply_num = 9;
.equ    cmdconfig_num = 10;
.endif

; ----------------------------------
.cseg

.ifdef mega32
    jmp    reset    ; 1  $000  RESET   External Pin, Power-on Reset, Brown-out Reset,
            ;                         Watchdog Reset, and JTAG AVR Reset
    jmp    ext_interrupt_0    ; 2  $002         INT0 External Interrupt Request 0
    jmp    dummy    ; 3  $004         INT1   External Interrupt Request 1
    jmp    dummy    ; 4  $006         INT2   External Interrupt Request 2
;    jmp    ext_interrupt_2    ; 4  $006         INT2 External Interrupt Request 2
    jmp    dummy    ; 5  $008    TIMEr2 COMP Timer/Counter2 Compare Match
    jmp    dummy    ; 6  $00A     TIMEr2 OVF Timer/Counter2 Overflow
    jmp    dummy    ; 7  $00C    TIMEr1 CAPT Timer/Counter1 Capture Event
    jmp    int_timer1_ovf    ; 8  $00E   TIMEr1 COMPA Timer/Counter1 Compare Match A
    jmp    dummy    ; 9  $010   TIMEr1 COMPB Timer/Counter1 Compare Match B
    jmp    dummy    ;10  $012     TIMEr1 OVF Timer/Counter1 Overflow
    jmp    dummy    ;11  $014    TIMEr0 COMP Timer/Counter0 Compare Match
    jmp    int_timer0_ovf    ;12  $016     TIMEr0 OVF Timer/Counter0 Overflow
    jmp    dummy     ;13  $018       SPI, STC Serial Transfer Complete
.ifdef SNI
;.ifdef use_serial_port_rx
    jmp    int_usartrx    ;14  $01A     USART, RXC USART, Rx Complete
.else
    jmp    dummy    ;14  $01A     USART, RXC USART, Rx Complete
.endif
;.ifdef use_serial_port_tx
.ifdef SNI
;.ifdef rs232telnet
    jmp    int_usartudre    ;15  $01C    USART, UDRE USART Data Register Empty
.else
    jmp    dummy    ;15  $01C    USART, UDRE USART Data Register Empty
.endif
    jmp    dummy    ;16  $01E     USART, TXC USART, Tx Complete
    jmp    dummy    ;17  $020         ADC    ADC Conversion Complete
    jmp    dummy    ;18  $022       EE_RDY   EEPROM Ready
    jmp    dummy    ;19  $024     ANA_COMP   Analog Comparator
    jmp    dummy    ;20  $026          TWI   Two-wire Serial Interface
    jmp    dummy    ;21  $028      SPM_RDY   Store Program Memory Ready
.endif

.ifdef mega16
	jmp	RESET ; Reset Handler
	jmp	ext_interrupt_0 ; EXT_INT0 ; IRQ0 Handler
	jmp	dummy ; EXT_INT1 ; IRQ1 Handler
	jmp	dummy ; TIM2_COMP ; Timer2 Compare Handler
	jmp	dummy ; TIM2_OVF ; Timer2 Overflow Handler
	jmp	dummy ; TIM1_CAPT ; Timer1 Capture Handler
	jmp	int_timer1_ovf ; dummy ; TIM1_COMPA ; Timer1 CompareA Handler
	jmp	dummy ; TIM1_COMPB ; Timer1 CompareB Handler
	jmp	dummy ; TIM1_OVF ; Timer1 Overflow Handler
	jmp	int_timer0_ovf ; dummy ; TIM0_OVF ; Timer0 Overflow Handler
	jmp	dummy ; SPI_STC ; SPI Transfer Complete Handler
;	jmp	dummy ; USART_RXC ; USART RX Complete Handler
.ifdef SNI
    jmp    int_usartrx    ;14  $01A     USART, RXC USART, Rx Complete
.else
    jmp    dummy    ;14  $01A     USART, RXC USART, Rx Complete
.endif
;	jmp	dummy ; USART_UDRE ; UDR Empty Handler
.ifdef SNI
;.ifdef rs232telnet
    jmp    int_usartudre    ;15  $01C    USART, UDRE USART Data Register Empty
.else
    jmp    dummy    ;15  $01C    USART, UDRE USART Data Register Empty
.endif
	jmp	dummy ; USART_TXC ; USART TX Complete Handler
	jmp	dummy ; ADC ; ADC Conversion Complete Handler
	jmp	dummy ; EE_RDY ; EEPROM Ready Handler
	jmp	dummy ; ANA_COMP ; Analog Comparator Handler
	jmp	dummy ; TWSI ; Two-wire Serial Interface Handler
	jmp	dummy ; EXT_INT2 ; IRQ2 Handler
	jmp	dummy ; TIM0_COMP ; Timer0 Compare Handler
	jmp	dummy ; SPM_RDY ; Store Program Memory Ready Handler
.endif




    nop

; in final production, place flag here to ensure no unneeded interrupts
dummy:
;    ldi    r16, 255
;    out    ledport, r16
;sbi ctlport, 5
    reti

reset:
;    rcall    vb
;sbi ctlport, 5
;xc: rjmp xc
;vb:
    ldi    r16, high(RAMEND)
    out    SPH, r16
    ldi    r16, low(RAMEND)
    out    SPL, r16
    cli


; first, avoid floating any pin :
; configure all pins as input with pullup

; warning: now with long 1 second hardware reset, all pins float this time.
; must pullup at least TXD pin externally, due to random transmission
; occurs during reset!
; later, we need software long reset for w5100. but we lack a pin for this. :-(

    ldi    r16, 0
    out    ddra, r16
    out    ddrb, r16
    out    ddrc, r16
    out    ddrd, r16
    ldi    r16, 255
	out    porta, r16
    out    portb, r16
    out    portc, r16
    out    portd, r16

;ldi r16, 0b10100000 ; 0.6 ma
;ldi r16, 0b10110000 ; 0.6 ma
;ldi r16, 0b10000000 ; idle 15 ma
;ldi r16, 0b11110000 ; extended standby 2.5 ma
;out MCUCR, r16

;sleep			
;xcv: rjmp xcv	; full / active 30 ma


; setup common w5100 ctl lines
ldi r16, (1<<RDbit) | (1<<WRbit) | (1<<CSbit) | (1<<A0bit) | (1<<A1bit)
    out    w5100ctrlddr, r16
    out    w5100ctrlport, r16
; configure mainboard LEDs
    sbi    ledRDYddr, ledRDYbit        ; out
    sbi    ledTCPCONddr, ledTCPCONbit    ; out
    cbi    ledRDYport, ledRDYbit        ; initial 0
    cbi    ledTCPCONport, ledTCPCONbit    ; initial 0

;ldi    r16, 255
;out    ddrc, r16
;ldi    r16, 255
;out    portc, r16

;sssss: rjmp sssss

; ... timers ................ ; dont forget, timers stops when sleep!

; TIMER2 used:
;  * as HW out pin - for RC PWM ch.0 and for IR transmit.
.ifdef irtransmit
	sbi	tm2ddr, tm2bit
	ldi	r16, 24 		; try to get 38 khz
; 23 = 38404 kHz measured
; 24 = 36.86 kHz measured, 36.80 calculated
	out	ocr2, r16
	rcall	timer2_off
.endif
.ifdef rcpwm
	sbi	tm2ddr, tm2bit
	ldi	r16, 26 		; initial
	out	ocr2, r16
	ldi	r16, 127 		; initial - middle
	mov	r22, r16
	rcall	timer2_on_rcpwm
.endif

; TIMER0 used:
;  * as interrupt - for auto send (keyboards, aura etc), for rotary encoder input.
;    for interrupts dont forget to enable ints later, after w5100 init.
;  * as HW out pin - for RC PWM 2nd channel.
.ifdef rcpwm2	; timer0
	sbi	tm0ddr, tm0bit
	ldi	r16, 26 		; initial
	out	ocr0, r16
	ldi	r16, 127 		; initial - middle
	mov	r23, r16
	rcall	timer0_on_rcpwm2
.endif
.ifdef rotary_encoder
	ldi	r16, 0b00000100
	out	tccr0, r16
.endif ; rotary_encoder
.ifdef autosend
	ldi    r16, 0b00000101    ; clkio/1024 div 256 ovf ~4 Hz or 8hz if 2M tact (e2 lfuse)
;    ldi    r16, 0b00000011    ; /64 div 256 ~10-100Hz       011 010
	out    tccr0, r16
.endif

; TIMER1 used:
;  * for interruprs for timeout measure for TCP/IP disconnect when no activity.
;    for interrupts dont forget to enable ints later, after w5100 init.
.ifndef udp
    ldi    r16, 0b00000101 + 0b00001000    ; clkio/1024 div (x) ; mode 4
    out    tccr1b, r16
    ldi    r16, 0                ; (lo x)
    ldi    r17, 64                ; (hi x) 0, 64 = 1 Hz
    out    ocr1ah, r17
    out    ocr1al, r16
.endif

; ... done timers setup. .................


    rcall    ringbufferinit

	rjmp	nx2


.ifdef use_timer2_out
timer2_on:
	ldi	r18, 0b00011010		; prescaler 14745600 div 8 
	out	TCCR2, r18
	ret

timer2_on_rcpwm:
;xtal 16.000M, t0=16 ms (60 Hz),
; really measured timing for HES-388 servo:
; tmin=0.6 ms (ocr2=9)
; tmax=2.3 ms (ocr2=40)
; so for exactly precise, 1ms=17, 2ms=34. Delta is 17, it's good for calculate:
; 255=17*15.
; But gives only 17 atomic steps.
	push	r16
	ldi	r16, 0b01101111		; prescaler 14745600 div 1024
; this prescaler work, but servo very noisy when idle. :-(
;	ldi	r16, 0b01101110		; prescaler 14745600 div 256
	out	TCCR2, r16
	pop	r16
	ret

timer2_off:
	push	r16
	ldi	r16, 0b00000000	
	out	TCCR2, r16
	cbi	tm2port, tm2bit
	pop	r16
	ret
.endif

; timer0 looks not works exactly as timer2 prescaler is different.
.ifdef use_timer0_out
;timer0_on:
;	ldi	r18, 0b00011010		; prescaler 14745600 div 8 
;	out	TCCR0, r18
;	ret

timer0_on_rcpwm2:
	push	r16
	ldi	r16, 0b01101101		; prescaler 14745600 div 1024
	out	TCCR0, r16
	pop	r16
	ret

timer0_off:
	push	r16
	ldi	r16, 0b00000000	
	out	TCCR0, r16
	cbi	tm0port, tm0bit
	pop	r16
	ret
.endif



ringbufferinit:
ldi r16, low(rxbuf)
mov r04, r16
mov r06, r16
ldi r16, high(rxbuf)
mov r05, r16
mov r07, r16
    ret

nx2:


; setup static daughter ports, i/o & hardware interfaces.
; this is daughterboard specific. Please modify it.


; eeprom programmer with changeable daughter boards.

.ifdef eeprom_prog
	rjmp	prog_init

prog_board_detect:
; get eeprom prog daughterboard type
; inverted bits: short to GND (jumper) = '1'
	ldi	r16, 0
	sbis	progTYPEpin, progTYPEbit0
	ori	r16, 1
	sbis	progTYPEpin, progTYPEbit1
	ori	r16, 2
	sbis	progTYPEpin, progTYPEbit2
	ori	r16, 4
	sbis	progTYPEpin, progTYPEbit3
	ori	r16, 8
	mov	r00, r16	; save for future use, don't rewrite it.
	ret

prog_init:
; setup common ports
    sbi    progCTRLddr,  progCTRLbit0	; LEDs
    cbi    progCTRLport, progCTRLbit0
    sbi    progCTRLddr,  progCTRLbit1
    cbi    progCTRLport, progCTRLbit1
    sbi    progCTRLddr,  progCTRLbit2
    cbi    progCTRLport, progCTRLbit2
    sbi    progCTRLddr,  progCTRLbit3	; EEPROM power (inverted)
    sbi    progCTRLport, progCTRLbit3	; EEPROM power (inverted)

	cbi	progTYPEddr, progTYPEbit0
	sbi	progTYPEport, progTYPEbit0	; input with pullup
	cbi	progTYPEddr, progTYPEbit1
	sbi	progTYPEport, progTYPEbit1	; input with pullup
	cbi	progTYPEddr, progTYPEbit2
	sbi	progTYPEport, progTYPEbit2	; input with pullup
	cbi	progTYPEddr, progTYPEbit3
	sbi	progTYPEport, progTYPEbit3	; input with pullup

; daughterboard type (capabilities) read (input), 4 bits, type 0...15
; type 0 - error / no board / reserved
; type 1 - 3,3V TWI AT17 board
; type 2 - 3,3V SPI AT45, EN25 board
; type 3 - 3,3V both AT17 and AT45, EN25 supported
; type 4 reserved.
; type 5 - 5V TWI AT17 board
; type 6 - 5V SPI AT45, EN25 board
; type 7 - 5V both AT17 and AT45, EN25 supported

; type 4...15 reserved.

; test for daughterboard detected and known type.
; note that some boards have more than one i/f, i.e. sometimes SPI and TWI should both
; be initialized.
	rcall	prog_board_detect
;out progCTRLport, r16	; debug out to rgb led
mov r16, r00
	cpi	r16, 1
	breq	prog_TWI_init
	cpi	r16, 3
	breq	prog_TWI_init
	cpi	r16, 5
	breq	prog_TWI_init
	cpi	r16, 7
	breq	prog_TWI_init
	rjmp	p_next

prog_TWI_init:
; ! OBSOLETE ?
; FIXME: fix PCB to get these bits connected.
;   ldi    r16, 0b00011111
;out     eepromCTRLddr, r16
;   ldi    r16, 0
;out     eepromCTRLport, r16
	sbi    progCTRLddr,  progCTRLbit4	
	cbi    progCTRLport, progCTRLbit4	; tie all to '0'... fixme for others than AT17
	sbi    progCTRLddr,  progCTRLbit5
	cbi    progCTRLport, progCTRLbit5
	sbi    progCTRLddr,  progCTRLbit6
	cbi    progCTRLport, progCTRLbit6
	sbi    progCTRLddr,  progCTRLbit7
	cbi    progCTRLport, progCTRLbit7
; twi init
; it is not documented, but try to set sda & scl as inputs with pull-up
; ... try to remove ?
    cbi    progTWIddr, progTWISCLbit
    cbi    progTWIddr, progTWISDAbit
    sbi    progTWIport, progTWISCLbit
    sbi    progTWIport, progTWISDAbit
    ldi    r16, 0
    out    TWSR, r16
; // SCL frequency = 11059200 / (16 + 2 * 48 * 1) = 98.743 khz
    ldi    r16, 12
    out    TWBR, r16

p_next:
;	rcall	prog_board_detect
	mov	r16, r00
	cpi	r16, 2
	breq	prog_SPI_init
	cpi	r16, 3
	breq	prog_SPI_init
	cpi	r16, 6
	breq	prog_SPI_init
	cpi	r16, 7
	breq	prog_SPI_init
	rjmp	p_next2

prog_SPI_init:
; setup the /SS pin as output BEFORE spi init! Else it not work as output!
; also searching was not helpful including these, but [1] still looks some good to know:
; [1] http://bleaklow.com/2010/06/13/avr_spi_gotcha.html
; [2] http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=116846&start=0
    sbi    progSPIddr,  progSPISSbit
    sbi    progSPIport,  progSPISSbit
; Set MOSI and SCK output, all others input ; (but really SS now also output)
;    ldi r17,(1<<DD_MOSI)|(1<<DD_SCK)
;    out adSPIctlddr, r17
; do not remove:
    sbi    progSPIddr,  progSPISCKbit
    cbi    progSPIport,  progSPISCKbit
    sbi    progSPIddr,  progSPIMOSIbit
    cbi    progSPIport,  progSPIMOSIbit ;  but here pin still outputs '1'! well,
;                        we hope it is now under HW SPI engine control.
    cbi    progSPIddr,  progSPIMISObit    ; remove pullup, and
    cbi    progSPIport,  progSPIMISObit    ; must be added h/w pulldown here (led+R also exist sometimes on this pin)

; Enable SPI, Master, set clock rate fck/4
    ldi    r17, (1<<SPE)|(1<<MSTR)
    out    SPCR, r17
    ldi    r17, (1<<SPI2X) ; set clock rate fck/2 (approx 7 MHz)
    out    SPSR,r17
; setup the /SS pin
; this just not work AFTER spi init! bu unknown reason.
;    sbi    progSPIddr,  progSPISSbit
;    sbi    progSPIport,  progSPISSbit

p_next2:
;	rcall	prog_board_detect
	mov	r16, r00
	cpi	r16, 1
	breq	prog_known_type
	cpi	r16, 2
	breq	prog_known_type
	cpi	r16, 3
	breq	prog_known_type
	cpi	r16, 5
	breq	prog_known_type
	cpi	r16, 6
	breq	prog_known_type
	cpi	r16, 7
	breq	prog_known_type
	jmp	error

prog_known_type:

.endif




;; at17 programmer:
;.ifdef at17prog
;    ldi    r16, 0b00011111
;    out     eepromCTRLddr, r16
;    ldi    r16, 0
;    out     eepromCTRLport, r16
;; static pins.....
;    sbi    ddrd, 4
;    sbi    ddrd, 5
;    sbi    ddrd, 6
;    sbi    ddrd, 7
;;    cbi    portd, 4
;    cbi    portd, 3
;    cbi    portd, 5
;    cbi    portd, 6
;    cbi    portd, 7
;; twi init... first time test
;; it is not documented, but try to set sda & scl as inputs with pull-up;;
;
;; ... try to remove ?
;    cbi    progTWIddr, progTWISCLbit
;    cbi    progTWIddr, progTWISDAbit
;    sbi    progTWIport, progTWISCLbit
;    sbi    progTWIport, progTWISDAbit;;
;
;    ldi    r16, 0
;    out    TWSR, r16
;; // SCL frequency = 11059200 / (16 + 2 * 48 * 1) = 98.743 khz
;    ldi    r16, 12
;    out    TWBR, r16
;.endif ; at17prog


;; at45db programmer:
;.ifdef at45spiprog
;; setup the /SS pin as output BEFORE spi init! Else it not work as output!
;; also searching was not helpful including these, but [1] still looks some good to know:
;; [1] http://bleaklow.com/2010/06/13/avr_spi_gotcha.html
;; [2] http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=116846&start=0
;    sbi    progSPIddr,  progSPISSbit
;    sbi    progSPIport,  progSPISSbit
;SPI_MasterInit:
;; Set MOSI and SCK output, all others input ; (but really SS now also output)
;;    ldi r17,(1<<DD_MOSI)|(1<<DD_SCK)
;;    out adSPIctlddr, r17
;; do not remove:
;    sbi    progSPIddr,  progSPISCKbit
;    cbi    progSPIport,  progSPISCKbit
;    sbi    progSPIddr,  progSPIMOSIbit
;    cbi    progSPIport,  progSPIMOSIbit ;  but here pin still outputs '1'! well,
;;                        we hope it is now under HW SPI engine control.
;    cbi    progSPIddr,  progSPIMISObit    ; remove pullup, and
;    cbi    progSPIport,  progSPIMISObit    ; must be added h/w pulldown here (led+R also exist sometimes on this ;pin)
;
;; Enable SPI, Master, set clock rate fck/4
;    ldi    r17, (1<<SPE)|(1<<MSTR)
;    out    SPCR, r17
;    ldi    r17, (1<<SPI2X) ; set clock rate fck/2 (approx 7 MHz)
;    out    SPSR,r17
; setup the /SS pin
; this just not work AFTER spi init! bu unknown reason.
;    sbi    progSPIddr,  progSPISSbit
;    sbi    progSPIport,  progSPISSbit

;; setup GPIO
;    sbi    progCTRLddr,  progCTRLbit0
;    cbi    progCTRLport, progCTRLbit0
;    sbi    progCTRLddr,  progCTRLbit1
;    cbi    progCTRLport, progCTRLbit1
;    sbi    progCTRLddr,  progCTRLbit2
;    cbi    progCTRLport, progCTRLbit2
;    sbi    progCTRLddr,  progCTRLbit3
;    cbi    progCTRLport, progCTRLbit3
;.endif ; at45spiprog



.ifdef adSPIctl
; without this, SPI outputs just not work when idle, but how was all work before?!?!?!
; maybe then SPI only work when active???.....
; o! found it! all work berofe due to new boards is LEDS on all SPI pins which pull it down!
; so exclipt state of all SPI pins required!
    sbi    adSPIctlddr, adSPIctlSSbit
    sbi    adSPIctlport, adSPIctlSSbit

; this all must be combined with other SPI inits into one SPI init procedure.
    sbi    adSPIctlddr, adSPIctlCLKbit
    cbi    adSPIctlport, adSPIctlCLKbit
    sbi    adSPIctlddr, adSPIctlDATAbit
    cbi    adSPIctlport, adSPIctlDATAbit

    cbi    adSPIctlddr, adSPIctlnotusedbit
    cbi    adSPIctlport, adSPIctlnotusedbit

; Enable SPI, Master, set clock rate fck/16
;    ldi r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
; Enable SPI, Master, set clock rate fck/4
    ldi    r17, (1<<SPE)|(1<<MSTR)
    out    SPCR, r17
    ldi    r17, (1<<SPI2X) ; set clock rate fck/2 (approx 7 MHz)
    out    SPSR,r17

    sbi    adSPIctlddr, adSPIctlaLEbit
    cbi    adSPIctlport, adSPIctlaLEbit
    cbi    adSPIctlddr, adSPIctlaLOCKbit    ; in
    cbi    adSPIctlport, adSPIctlaLOCKbit    ; no pull-up
.ifndef ad9910
    sbi    adSPIctlddr, adSPIctlbLEbit
    cbi    adSPIctlport, adSPIctlbLEbit
    cbi    adSPIctlddr, adSPIctlbLOCKbit    ; in
    cbi    adSPIctlport, adSPIctlbLOCKbit    ; no pull-up
.else
;	.equ    adSPIctlRESETbit=2    ; oot - positive active
;	.equ    adSPIctlOSKbit=3    ; out - amplitude mod.
	cbi	adSPIctlport, adSPIctlRESETbit	; out '0' first
	sbi	adSPIctlddr, adSPIctlRESETbit	; out

	sbi	adSPIctlddr, adSPIctlOSKbit	; out
	sbi	adSPIctlport, adSPIctlOSKbit	; out '1'

;	cbi	ledTCPCONport, ledTCPCONbit
	rcall	delay100ms
	sbi	adSPIctlport, adSPIctlRESETbit
	sbi	ledTCPCONport, ledTCPCONbit
	rcall	delay100ms
	cbi	adSPIctlport, adSPIctlRESETbit
	cbi	ledTCPCONport, ledTCPCONbit
	
.endif
	rjmp	init_cont

delay100ms:
;	ldi	r19, 2
;ddy1:
	ldi	r18, 40 ; 500 ms at 14MHz
ddy2:
	ldi	r17, 0
ddy3:
	ldi	r16, 0
ddy4:	
	dec	r16
	brne	ddy4
	dec	r17
	brne	ddy3
	dec	r18
	brne	ddy2
;	dec	r19
;	brne	ddy1
	ret
	



init_cont:
; set attenuator - modify it later to host control.
	sbi	ddrc, 1
	cbi	portc, 1
	sbi	ddrc, 0
	cbi	portc, 0

	sbi	ddrd, 7
	cbi	portd, 7
	sbi	ddrd, 6
	cbi	portd, 6
	sbi	ddrd, 5
	cbi	portd, 5
	sbi	ddrd, 3
	cbi	portd, 3

.endif ; adSPIctl



.ifdef ad7680
    sbi    ad7680ddr, ad7680CLKbit        ; out
    cbi    ad7680port, ad7680CLKbit
    cbi    ad7680ddr, ad7680DATAbit    ; in
    cbi    ad7680port, ad7680DATAbit

    sbi    ad7680ddr, ad7680aCSbit
    sbi    ad7680port, ad7680aCSbit    ; CS=1 when idle
    sbi    ad7680ddr, ad7680bCSbit
    sbi    ad7680port, ad7680bCSbit    ; CS=1 when idle
    sbi    ad7680ddr, ad7680aLEDbit
    cbi    ad7680port, ad7680aLEDbit
    sbi    ad7680ddr, ad7680bLEDbit
    cbi    ad7680port, ad7680bLEDbit
; Enable SPI, set clock rate fck/16; ad7680 Fsclk max = 2.5 MHz, use 14M/8
    ldi    r17, (1<<SPE) | (1<<MSTR) | (1<<SPR0)
    out    SPCR,r17
    ldi    r17, (1<<SPI2X)
    out    SPSR,r17
.endif ; ad7680



.ifdef aura
; we hope all needed ports already inputs now, so only remove pullups -
; ports must float. Not sure if it is good for uC.
	cbi	portd, 0
	cbi	portd, 1
.ifdef old_board
	cbi	portd, 4	; replace
.else
	error
.endif
	cbi	portd, 5
	cbi	portd, 6
	cbi	portd, 7
	cbi	portc, 0
	cbi	portc, 1
	ldi	r16, 0
	out	portb, r16
.endif



.ifdef webserver
; prepare i/o, if any

.endif ; webserver



.ifdef matrix_keyboard
; we need 8 outputs and 8 inputs.
; or 3 outputs and HC154 3-to-8 multiplexer. And still 8 inputs.
; (74HC154, it's not error, 4-to-16 used as 3-to-8. Just because
; HC154 is "must have" part. Note that outputs are active "0".)
; .....but we don't have the mux now. So 8+8 pins need.

    sbi    mkout0ddr, mkout0bit0    ; pd0,1,4,5,6,7
    sbi    mkout0ddr, mkout0bit1
    sbi    mkout0ddr, mkout0bit2
    sbi    mkout0ddr, mkout0bit3
    sbi    mkout0ddr, mkout0bit4
    sbi    mkout0ddr, mkout0bit5
    sbi    mkout1ddr, mkout1bit6    ; pc0,1
    sbi    mkout1ddr, mkout1bit7

    sbi    mkout0port, mkout0bit0
    sbi    mkout0port, mkout0bit1
    sbi    mkout0port, mkout0bit2
    cbi    mkout0port, mkout0bit3    ; some random bit selected
    sbi    mkout0port, mkout0bit4
    sbi    mkout0port, mkout0bit5
    sbi    mkout1port, mkout1bit6
    sbi    mkout1port, mkout1bit7

    ldi    r16, 0
    out    mkinddr, r16    ; all 8 bits inputs.
    nop
    ldi    r16, 255
    out    mkinport, r16    ; pullups.

; initialize all keys as released (unpressed)
    ldi    r28, low(mkstate)
    ldi    r29, high(mkstate)
    ldi    r16, 0xff
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16 ; we hope size of 'mkstate' at least 8 bytes.
.endif    ; matrix_keyboard


; there is two mode of using serial, interrupt based and polling.
; select mode after this section (enable int) if you need interrupts.
; example: SNI uses interrupts, but SNMP uses polling.
.ifdef use_serial_port_rx
	.define	serial_port_configure
;    ldi    r16, (1<<RXEN)
	sbi	UCSRB, RXEN
; moved to only use after configuration.
	cbi	UCSRB, RXCIE            ; rs232 read interrupt off
.endif

.ifdef use_serial_port_tx
	.ifndef	serial_port_configure
	.define	serial_port_configure
	.endif
;    ldi    r16, (1<<TXEN)
	sbi	UCSRB, TXEN
.endif

.ifdef serial_port_configure
;    ldi    r16, (1<<RXEN)|(1<<TXEN)    ; Enable receiver and transmitter
;    out    UCSRB,r16
	ldi	r16, (1<<URSEL)|(3<<UCSZ0)    ; Set frame format
	out	UCSRC, r16

; if not used bps-reset to 9600 pin, not use hardly set 9600.
.ifdef use_serial_ctrl0_pins
	sbic	ctl0pin, ctl0force9600_and_relaybit ; spd, 0 (short) = 9600, open = software
.endif
	rjmp	mode_softwarebps

mode_9600:
.ifdef xtal73728
	ldi    r18, low(47)    ; baud rate divider for 7.3728M
	ldi    r19, high(47)
.else
	ldi    r18, low(95)    ; baud rate divider for 14.7456M
	ldi    r19, high(95)
.endif
	rjmp    setspd

mode_softwarebps:
    ldi    r24, low(eep_settings_base + (defaults_bps-defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_bps-defaults_part0)*2)
    rcall    EEPROM_read
    mov    r18, r16
    rcall    EEPROM_read
    mov    r19, r16
setspd:
    out    UBRRH, r19
    out    UBRRL, r18
;.ifdef rs232telnet
.ifdef use_serial_leds
    sbi    ledddr, ledIPRXbit    ; setup initial leds
    sbi    ledddr, ledIPTXbit
    sbi    ledddr, ledRSRXbit
    sbi    ledddr, ledRSTXbit
    cbi    ledport, ledIPRXbit    ; oops! they are inverted now
    cbi    ledport, ledIPTXbit    ; (common anode)...
    cbi    ledport, ledRSRXbit    ; lets buy common-catode double-color leds.
    cbi    ledport, ledRSTXbit
.endif ; use_serial_leds
; moved to srvctrl
;.ifdef rs232telnet
;    sbi    ctlddr, ctl0force9600_and_relaybit ; now becomes out for relay
;    sbi    ctlport, ctl0force9600_and_relaybit ; out '1' - inverted relay.
.ifdef use_serial_ctrl0_pins
	cbi	ctl0ddr, ctl0channel_or_echobit ; prepare to read 'echo' bit,
	sbi	ctl0port, ctl0channel_or_echobit ; but it may be overrided later for srvctrl
.endif
;.endif ; rs232telnet
.endif ;  serial_port_configure

; init one-wire interface
.ifdef	use_ds18b20_pin
	cbi	ds18b20port, ds18b20IObit	; permanent out '0'
	cbi	ds18b20ddr, ds18b20IObit	; and control by ddr (out 0 / in+ext.pullup)
.endif

.ifdef srvctrl
; setup output ports.
    sbi    btnddr, mbsw0bit_or_ctl1TXENbit     ; out
    sbi    btnddr, mbsw1bit_or_ctl1NODUPLEXbit     ; out
    sbi    btnddr, mbSW2bit     ; out
    sbi    btnddr, mbSW3bit     ; out
; new NL27WZ07DTT1 buffers has inverter.
; active '0's has advantage of remove bounces and unknown pin
; state before uC starts, via simple pullups.
    sbi    btnport, mbsw0bit_or_ctl1TXENbit     ; out '1'
    sbi    btnport, mbsw1bit_or_ctl1NODUPLEXbit     ; out '1'
    sbi    btnport, mbSW2bit     ; out '1'
    sbi    btnport, mbSW3bit     ; out '1'
    sbi    ctl0ddr, ctl0channel_or_echobit
    cbi    ctl0port, ctl0channel_or_echobit    ; out - set default channel
; portc input & pullup need to be re-initialize due to "setup common w5100 ctl lines"
    sbi    ctl0ddr, ctl0force9600_and_relaybit ; now becomes out for relay
    sbi    ctl0port, ctl0force9600_and_relaybit ; out '1' - inverted relay.
.endif


.ifdef snmp_smarthome
;	sbi	smarthomeIOddr,  0
;	cbi	smarthomeIOport, 0
;	sbi	smarthomeIOddr,  1
;	cbi	smarthomeIOport, 1
;	sbi	smarthomeIOddr,  2
;	cbi	smarthomeIOport, 2
;	sbi	smarthomeIOddr,  3
;	cbi	smarthomeIOport, 3
	sbi	smarthomeIOddr,  4
	cbi	smarthomeIOport, 4
	sbi	smarthomeIOddr,  5
	cbi	smarthomeIOport, 5
	sbi	smarthomeIOddr,  6
	cbi	smarthomeIOport, 6
	sbi	smarthomeIOddr,  7
	cbi	smarthomeIOport, 7
.endif


; done setup static daughter ports!



; SERIAL SETUP MODE
; power-on delay available to enter setup mode
.ifdef serial_setup

; added 09-09-2012: when MIDI (multicast), we do not need it,
; because pins txd, rxd occuped, and XTAL freq (16 MHz) not suitable
; for serial config...
;.ifdef multicast
; nothing
;.else
    ldi    r19, 0	; q'ty of 'z's
    ldi    r18, 0
setup0:

.ifdef xtal73728 ; two times slower
    ldi    r17, 64
.else
    ldi    r17, 128    ; 63 = approx. 1 sec
.endif

setdly:
    ldi    r16, 0
setdly2:
    nop
    dec    r16
    brne    setdly2
    dec    r17
    brne    setdly
    sbic    UCSRA, RXC    ; Wait for data to be received
    rjmp    setup1    ; char entered
	sbrc	r18, 4	; flashing RDY led while waiting for three 'z'
	cbi    ledRDYport, ledRDYbit
	sbrs	r18, 4
	sbi    ledRDYport, ledRDYbit
    dec    r18
    brne    setup0
    jmp    no_setup

setup1:
    in    r16, UDR
;    rcall   USART_Transmit ; echo back
    call   USART_Transmit ; echo back
    cpi    r16, 'z'
    brne    setup0
    inc    r19
    cpi    r19, 3
    brne    setup0

; here three 'z' entered. Setup mode.
    ldi    r30, low(txtsetup0*2)
    ldi    r31, high(txtsetup0*2)
    rcall    print
    ldi    r18, 0     ; pseudorandom
    ldi    r19, 0     ; pseudorandom
setup_main:
    rcall    input
    cpi    r16, 13
    breq    setup_main
    cpi    r16, 'h'
    breq    setup_showhelp
    cpi    r16, 9    ; tab
    breq    setup_showhelp
    cpi    r16, 'q'
    breq    setup_done
    cpi    r16, 'l'
    breq    setup_loaddefaults
    cpi    r16, 'd'
    breq    setup_display
;    cpi    r16, 'm'
;    breq    setup_modify
    cpi    r16, '0'
    breq    setup_modifya
    cpi    r16, '1'
    breq    setup_modifyb
    cpi    r16, '2'
    breq    setup_modifyc
    cpi    r16, '3'
    breq    setup_modifyd
.ifdef srvctrl ; keywords used only when srv ctrl
    cpi    r16, 's'
    breq    setup_showkeywords
    cpi    r16, 'i'
    breq    setup_inputignoreseq
    cpi    r16, 'c'
    breq    setup_inputkeywords
    cpi    r16, 'a'
    breq    setup_loaddefaultkeywords
.endif ; srvctrl
    cpi    r16, 'r'
    breq    setup_randommac

    ldi    r30, low(txterr2*2)
    ldi    r31, high(txterr2*2)
    rcall    print
    rjmp    setup_main

setup_showhelp:
    jmp    setup_showhelp0
setup_loaddefaults:
    jmp    setup_loaddefaults0

setup_done:
    jmp    setup_done2

setup_display:
    jmp    setup_display0

setup_modifya:
    jmp    setup_modify0
setup_modifyb:
    jmp    setup_modify1
setup_modifyc:
    jmp    setup_modify2
setup_modifyd:
    jmp    setup_modify3

.ifdef srvctrl ; keywords used only when srv ctrl
setup_showkeywords:
    jmp    setup_showkeywords0
setup_inputkeywords:
    jmp    setup_inputkeywords0
setup_inputignoreseq:
    jmp    setup_inputignoreseq0
setup_loaddefaultkeywords:
    jmp    setup_loaddefaultkeywords0
.endif ; srvctrl

setup_randommac:
    jmp    setup_randommac0


input:
    ldi    r16,':'
    rcall    wchar
;    rcall    USART_Receive
USART_Receive2:
    inc    r18    ; pseudo random...
    cpi    r18,0
    brne    usr2
    inc    r19
usr2:
    sbis    UCSRA, RXC    ; Wait for data to be received
    rjmp    USART_Receive2
    in    r16, UDR     ; Get and return received data from buffer
    rcall    wchar
    push    r16
    ldi    r16,13
    rcall    wchar
    ldi    r16,10
    rcall    wchar
    pop    r16
    ret

setup_showhelp0:
    ldi    r30, low(txthelp*2)
    ldi    r31, high(txthelp*2)
    rcall    print
    rjmp    setup_main

setup_loaddefaults0:
    ldi    r30, low(txtconfirm*2)
    ldi    r31, high(txtconfirm*2)
    rcall    print
    rcall    input
    cpi    r16, 'y'
    brne    ld2
; load defaults
    ldi    r17, (defaults_end - defaults_part0)*2
    ldi    r30, low(defaults_part0*2)
    ldi    r31, high(defaults_part0*2)
    ldi    r24, low(eep_settings_base + 0*2)
    ldi    r25, high(eep_settings_base + 0*2)
ld3:
    lpm    r16, z+
    rcall    EEPROM_write
    dec    r17
    brne    ld3
    ldi    r30, low(txtloaded*2)
    ldi    r31, high(txtloaded*2)
    rcall    print
ld2:
    rjmp    setup_main

setup_randommac0:
    ldi    r30, low(txtconfirm*2)
    ldi    r31, high(txtconfirm*2)
    rcall    print
    rcall    input
    cpi    r16, 'y'
    brne    rm2
;    ldi    r17, (defaults_end - defaults_mcast)*2
; modify last 3 bytes of mac
    ldi    r24, low(eep_settings_base + (defaults_mac - defaults_part0)*2 + 3)
    ldi    r25, high(eep_settings_base + (defaults_mac - defaults_part0)*2 + 3)

    ldi    r17, '#'
    eor    r17, r18
    eor    r17, r19 ; generate 3rd 'random' byte
    mov    r16, r18
    rcall    EEPROM_write
    mov    r16, r17
    rcall    EEPROM_write
    mov    r16, r19
    rcall    EEPROM_write
; removed random multicast MACs. 20-10-2012
; due to mcast MACs calculated from IP. see W5100_App_HowtoMulticasting.zip
;    ldi    r24, low(eep_settings_base + (defaults_mcast_mac - defaults_part0)*2 + 3)
;    ldi    r25, high(eep_settings_base + (defaults_mcast_mac - defaults_part0)*2 + 3)
;    mov    r16, r18
;    rcall    EEPROM_write
;    mov    r16, r17
;    rcall    EEPROM_write
;    mov    r16, r19
;    rcall    EEPROM_write
rm2:
    rjmp    setup_main


setup_display0:
    ldi    r30, low(txtcfg0*2)
    ldi    r31, high(txtcfg0*2)
    rcall    print
    ldi    r17, part0_len
    ldi    r24, low(eep_settings_base + 0*2)
    ldi    r25, high(eep_settings_base + 0*2)
    rcall    disp

    ldi    r30, low(txtcfg1*2)
    ldi    r31, high(txtcfg1*2)
    rcall    print
    ldi    r17, part1_len
    ldi    r24, low(eep_settings_base + (defaults_part1 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part1 - defaults_part0)*2)
    rcall    disp

    ldi    r30, low(txtcfg2*2)
    ldi    r31, high(txtcfg2*2)
    rcall    print
    ldi    r17, part2_len
    ldi    r24, low(eep_settings_base + (defaults_part2 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part2 - defaults_part0)*2)
    rcall    disp

    ldi    r30, low(txtcfg3*2)
    ldi    r31, high(txtcfg3*2)
    rcall    print
    ldi    r17, part3_len
    ldi    r24, low(eep_settings_base + (defaults_part3 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part3 - defaults_part0)*2)
    rcall    disp

    rjmp    setup_main

disp:
    rcall    EEPROM_read
;    rcall    whexbyte
    call    whexbyte
    ldi    r16,' '
    rcall    wchar
    ldi    r16,' '
    rcall    wchar
    dec    r17
    brne    disp
    ldi    r16,13
    rcall    wchar
    ldi    r16,10
    rcall    wchar
    ret


modifyconfirm:
    ldi    r30, low(txtmodify*2)
    ldi    r31, high(txtmodify*2)
    rcall    print
    ldi    r30, low(txtconfirm*2)
    ldi    r31, high(txtconfirm*2)
    rcall    print
    rcall    input
    ret

.ifdef srvctrl ; keywords used only when srv ctrl
setup_inputignoreseq0:
    rcall    modifyconfirm
    cpi    r16, 'y'
    brne    setup_modify_b
    ldi    r30, low(txtmodify2*2)
    ldi    r31, high(txtmodify2*2)
    rcall    print

    ldi    r17, ignore_cmd_len
    ldi    r24, low(eep_keywords_base + 32*ignoreseq_num)
    ldi    r25, high(eep_keywords_base + 32*ignoreseq_num)
    rjmp    setup_modify_a
.endif ; srvctrl


setup_modify0:
    rcall    modifyconfirm
    cpi    r16, 'y'
    brne    setup_modify_b
    ldi    r30, low(txtmodify2*2)
    ldi    r31, high(txtmodify2*2)
    rcall    print

    ldi    r30, low(txtcfg0*2)
    ldi    r31, high(txtcfg0*2)
    rcall    print

    ldi    r17, part0_len
;    ldi    r30, low(defaults_part0*2)
;    ldi    r31, high(defaults_part0*2)
    ldi    r24, low(eep_settings_base + 0*2)
    ldi    r25, high(eep_settings_base + 0*2)

setup_modify_a:
;    rcall     modifyvalues
modifyvalues:
    rcall     inputhexnibble
    swap    r16
    mov    r20, r16
    rcall     inputhexnibble
    add    r20, r16
    ldi    r16,' '
    rcall    wchar
    ldi    r16,' '
    rcall    wchar
    mov    r16, r20
    rcall    EEPROM_write
    dec    r17
    brne    modifyvalues
;    ret

    ldi    r30, low(txtmodified*2)
    ldi    r31, high(txtmodified*2)
    rcall    print
setup_modify_b:
    rjmp    setup_main

setup_modify1:
    rcall    modifyconfirm
    cpi    r16, 'y'
    brne    setup_modify_b
    ldi    r30, low(txtmodify2*2)
    ldi    r31, high(txtmodify2*2)
    rcall    print
    ldi    r30, low(txtcfg1*2)
    ldi    r31, high(txtcfg1*2)
    rcall    print
    ldi    r17, part1_len
;    ldi    r30, low(defaults_part1*2)
;    ldi    r31, high(defaults_part1*2)
    ldi    r24, low(eep_settings_base + (defaults_part1 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part1 - defaults_part0)*2)
    rjmp    setup_modify_a

setup_modify2:
    rcall    modifyconfirm
    cpi    r16, 'y'
    brne    setup_modify_b
    ldi    r30, low(txtmodify2*2)
    ldi    r31, high(txtmodify2*2)
    rcall    print
    ldi    r30, low(txtcfg2*2)
    ldi    r31, high(txtcfg2*2)
    rcall    print
    ldi    r17, part2_len
;    ldi    r30, low(defaults_part2*2)
;    ldi    r31, high(defaults_part2*2)
    ldi    r24, low(eep_settings_base + (defaults_part2 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part2 - defaults_part0)*2)
    rjmp    setup_modify_a

setup_modify3:
    rcall    modifyconfirm
    cpi    r16, 'y'
    brne    setup_modify_b
    ldi    r30, low(txtmodify2*2)
    ldi    r31, high(txtmodify2*2)
    rcall    print
    ldi    r30, low(txtcfg3*2)
    ldi    r31, high(txtcfg3*2)
    rcall    print
    ldi    r17, part3_len
;    ldi    r30, low(defaults_part3*2)
;    ldi    r31, high(defaults_part3*2)
    ldi    r24, low(eep_settings_base + (defaults_part3 - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_part3 - defaults_part0)*2)
    rjmp    setup_modify_a




    ldi    r16,13
    rcall    wchar
    ldi    r16,10
    rcall    wchar

;;;    ldi    r30, low(txtconfig1*2)
    ;;;ldi    r31, high(txtconfig1*2)
    rcall    print

;;;    ldi    r17, (defaults_end - defaults_mcast)*2
;;;    ldi    r30, low(defaults*2)
    ;;;ldi    r31, high(defaults*2)
;;;    ldi    r24, low(eep_settings_base + (defaults_mcast - defaults)*2)
    ;;;ldi    r25, high(eep_settings_base + (defaults_mcast - defaults)*2)
md3:
    rcall     inputhexnibble
    swap    r16
    mov    r20, r16
    rcall     inputhexnibble
    add    r20, r16
    ldi    r16,' '
    rcall    wchar
    mov    r16, r20
    rcall    EEPROM_write
    dec    r17
    brne    md3
    ldi    r30, low(txtmodified*2)
    ldi    r31, high(txtmodified*2)
    rcall    print

md4:
    rjmp    setup_main

.EQU    ignore_cmd_len = 6

.ifdef srvctrl ; keywords used only when srv ctrl
setup_showkeywords0:
    ldi    r30, low(txtkwcurrent*2)
    ldi    r31, high(txtkwcurrent*2)
    rcall    print

    ldi    r17, 0
kw0:
    mov    r18, r17
    ldi    r19, 0
    swap    r18
    lsl    r18
    rol    r19    ; r18:r19 = r18:r19 * 32 - shift to print and input
    ldi    r30, low(txtkwnames*2)
    ldi    r31, high(txtkwnames*2)
    add    r30, r18
    adc    r31, r19
    rcall    print    ; uses r16
    ldi    r24, low(eep_keywords_base)
    ldi    r25, high(eep_keywords_base)
    add    r24, r18
    adc    r25, r19
    rcall    print_eeprom    ; prints zero-term string. uses r16
    ldi    r16,13
    rcall    wchar
    ldi    r16,10
    rcall    wchar
    inc    r17
    cpi    r17, ignoreseq_num
    brne    kw0

    ldi    r30, low(txtignorecurrent*2)
    ldi    r31, high(txtignorecurrent*2)
    rcall    print

    ldi    r17, ignore_cmd_len
    ldi    r24, low(eep_keywords_base + 32*ignoreseq_num)
    ldi    r25, high(eep_keywords_base + 32*ignoreseq_num)
    rcall    disp

    rjmp    setup_main

setup_inputkeywords0:
    ldi    r30, low(txtconfirm*2)
    ldi    r31, high(txtconfirm*2)
    rcall    print
    rcall    input
    cpi    r16, 'y'
    brne    kw5
    ldi    r30, low(txtkwinput*2)
    ldi    r31, high(txtkwinput*2)
    rcall    print
    ldi    r17, 0
kw1:
    mov    r18, r17
    ldi    r19, 0
    swap    r18
    lsl    r18
    rol    r19    ; r18:r19 = r18:r19 * 32 - shift to print and input
    ldi    r30, low(txtkwnames*2)
    ldi    r31, high(txtkwnames*2)
    add    r30, r18
    adc    r31, r19
    rcall    print    ; uses r16
    ldi    r24, low(eep_keywords_base)
    ldi    r25, high(eep_keywords_base)
    add    r24, r18
    adc    r25, r19
    ldi    r20, 0
kw2:
    rcall    USART_Receive
    cpi    r16, 13
    breq    kw3
;    cpi    r16, 10
;    breq    kw3
    rcall    wchar
    rcall    EEPROM_write
    inc    r20
    cpi    r20, 31    ; max length
    brne    kw2
kw3:
    ldi    r16, 0    ; end of string
    rcall    EEPROM_write
    ldi    r16,13
    rcall    wchar
    ldi    r16,10
    rcall    wchar
    inc    r17
    cpi    r17, cmd_qty_user
    brne    kw1
kw5:
    rjmp    setup_main


setup_loaddefaultkeywords0:
    ldi    r30, low(txtconfirm*2)
    ldi    r31, high(txtconfirm*2)
    rcall    print
    rcall    input
    cpi    r16, 'y'
;    brne    ld4
    breq    kww
    rjmp    setup_main
kww:
    ldi    r17, 0
kw6:
    mov    r18, r17
    ldi    r19, 0
    swap    r18
    lsl    r18
    rol    r19    ; r18:r19 = r18:r19 * 32 - shift to print and input
    ldi    r24, low(eep_keywords_base)
    ldi    r25, high(eep_keywords_base)
    add    r24, r18
    adc    r25, r19
;    ldi    r20, 0


cpi r17, ignoreseq_num
breq uiui
cpi r17, httpreply_num
breq uiui3
; its work, but for test, we use 'tst:' default command #10.
;cpi r17, cmdconfig_num
;breq uiui4

    ldi    r16, 't'
    rcall    EEPROM_write
    ldi    r16, 's'
    rcall    EEPROM_write
    ldi    r16, 't'
    rcall    EEPROM_write
    ldi    r16, '0'
    add    r16, r17
    rcall    EEPROM_write
    rjmp    uiui2
uiui3:
    ldi    r16, 'G'
    rcall    EEPROM_write
    ldi    r16, 'E'
    rcall    EEPROM_write
    ldi    r16, 'T'
    rcall    EEPROM_write
    ldi    r16, ' '
    rcall    EEPROM_write
    ldi    r16, '/'
    rcall    EEPROM_write
;    ldi    r16, ' '
;    rcall    EEPROM_write
    rjmp    uiui2

uiui4:
;  67 ef 66 f2 67 eb 6e ee 6f ef 6e e2 7f 1b b6 2e
;  a7 3f c6 42 c7 5b ee 7e 0f 9f 2e b2 3f cb 56 00
    ldi    r20, 31
    ldi    r16, 'g'    ; 'random' stuff...
uiw1:
    rcall    EEPROM_write
    subi    r16, 0x77    ; 'random' stuff...
    eor    r16, r20    ; 'random' stuff...
    dec    r20
    brne    uiw1

    rjmp    uiui2
uiui:
    ldi    r16, 0xff
    rcall    EEPROM_write
    ldi    r16, 0xfd
    rcall    EEPROM_write
    ldi    r16, 0x01
    rcall    EEPROM_write
    ldi    r16, 0xff
    rcall    EEPROM_write
    ldi    r16, 0xfd
    rcall    EEPROM_write
    ldi    r16, 0x03
    rcall    EEPROM_write

uiui2:
    ldi    r16, 0    ; end of string
    rcall    EEPROM_write
;    ldi    r16,13
;    rcall    wchar
;    ldi    r16,10
;    rcall    wchar
    inc    r17
    cpi    r17, cmd_qty_total
    brne    kw6
ld4:
    rjmp    setup_main

.endif ; srvctrl ; keywords used only when srv ctrl


inputhexnibble:
    rcall    USART_Receive
    rcall    wchar
    andi    r16, 0b01111111
    subi    r16, '0'
    cpi    r16, 'a'-'0'
    brlo    inp2
    subi    r16, 'a'-'0'-0x0a
inp2:
    andi    r16, 0b00001111
    ret

setup_done2:
    ldi    r30, low(txtpwroff*2)
    ldi    r31, high(txtpwroff*2)
    rcall    print
    cli
halt:
    sleep
    nop
    rjmp halt

no_setup:
;    sbi     UCSRB, RXCIE            ; rs232 read interrupt en.
    jmp     done_serial_setup

;.endif ; ifndef multicast

done_serial_setup:
;    jmp    w5100init

.endif ; serial_setup

    jmp    w5100init

; all sections maybe need to be 16 bytes length.
defaults_part0:
.equ part0_len = 14
defaults_ip:
.db     1,1,1,2            ;myip
.db     255,255,255,0        ;mask
.db     1,1,1,1            ;gwip
defaults_port:
.dw    0x5555            ;port
.db    0,0         ; (padding)

defaults_part1:
.equ part1_len = 12
defaults_mcast_ip:
.db     225,0,0,37    ;mcast myip - must match mcast macaddr. (except MSB) see W5100_HowtoMulticasting
defaults_mcast_port:
.dw    21928        ;mcast port - def. 21928 for QMidiNet
defaults_mcast_idsend_ip:
.db     226,227,228,229
defaults_mcast_idsend_port:
.dw    65210
.db    0,0,0,0

defaults_part2:
.equ part2_len = 6
defaults_mac:
.db    0x00,0x08,0xdc,0,0,37    ; macaddr: wiznet.
;defaults_mcast_mac:
;.db    1,0,0x5e,0,0,37    ; mcast macaddr.
.db 0,0,0,0,0,0
.db    0,0,0,0

defaults_part3:
.equ part3_len = 3

defaults_bps:
;.dw    119            ;bps divider - set baudrate
.ifdef xtal73728
	.dw    47            ;bps divider - set baudrate
.else
	.dw    95            ;bps divider - set baudrate
.endif
defaults_mode:
.db    0,0    ; telnet mode
.db     0,0,0,0,0,0,0,0,0,0,0,0

defaults_end:


.ifdef serial_setup

txtsetup0:
 .db 0x0c,13,10,10
 .db "    * OSCaR Serial Network Interface *     Version 03.05.2013",13,10,10
.ifdef srvctrl
 .db "Linked-in modules:",13,10
 .db "1. OSCaR Server control (Pwr, Reset, LEDs)   [Two servers]",13,10
 .db "2. OSCaR Relay control",13,10
.endif
 .db 13,10
 .db "This is an open source project. No any warranties.",13,10
 .db "Author: http://93.182.12.2:888",13,10
 .db "Mail me: radiomaster@freemail.ru",13,10
 .db 13,10
 .db "You entered setup mode. Use lowercase. Type <h> for help. ",13,10
 .db 13,10
 .db 0,0

txterr2:
.db "Unknown command.",13,10,0,0

txtmodify:
.db "Entered values will be saved immediately! ",13,10,0,0

txtmodify2:
.db "Enter two-digit hex values.",13,10,0

txtconfirm:
.db "Are you sure? Type y or n ",0,0

txtloaded:
.db "Defaults loaded.",13,10,0,0

txtmodified:
.db 13,10,"Settings saved.",13,10,0

txtcfg0:
.db " Section 0: My__IP_address  My_____Netmask  My__GW_address  MyPort",13,10," Value:     ",0,0
txtcfg1:
.db " Section 1: MultiCastIPadr  MCPort  IDmulticast_IP  IDPort",13,10," Value:     ",0,0
txtcfg2:
.db " Section 2: My_____MAC_____address",13,10," Value:     ",0,0
txtcfg3:
.db " Section 3: BPSdiv  Mode",13,10," Value:     ",0,0

txtkwcurrent:
.db "The current keywords is",13,10,0
txtignorecurrent:
.db "The current telnet's"
.db ' ',ignore_cmd_len+'0'
.db "-byte ignore sequence is ",13,10,0

txtkwinput:
.db "Enter keywords. No duplicates allowed. Max 31 char each.",13,10,0,0

txtkwnames: ; myst be 32 bytes each
.db "           Switch to Server 0: ",0
.db "           Switch to Server 1: ",0
.db "   Press PWR button for 1 sec: ",0
.db "  Press PWR button for 5 secs: ",0
.db "           Press RESET button: ",0
.db "        Show motherboard LEDs: ",0
.db "            External relay ON: ",0
.db "           External relay OFF: ",0
.db 0,0

txthelp:
 .db "d  Display current settings ",13,10
 .db "0..3  Modify settings section# [!]",13,10
 .db "l  Load all default settings [!]",13,10
 .db "r  Random MAC address [!] ",13,10
.ifdef srvctrl
 .db "s  Show current keywords and ignore sequence",13,10
 .db "c  Change keywords [!]",13,10
 .db "i  Change ignore sequence [!] ",13,10
 .db "a  Assign demo keywords and default ignore sequence [!] ",13,10
.endif
 .db "q  Quit ",13,10
 .db " BPS divider = xtal[Hz] / 16 / bps - 1",13,10
 .db "    Example: xtal 14.7456M, bps 115200: BPSdiv=7 (07 00)",13,10
 .db "    Example: xtal 16.000M, bps 31250: BPSdiv=31 (1f 00) ",13,10
 .db "    Example: xtal 18.432M, bps 300: BPSdiv=3839 (ff 0e) ",13,10
 .db " Mode: 00 = raw (Windows / EventGhost / Commands only), ",13,10
 .db "       01 = telnet (Linux / TTY via serial).",13,10
 .db 0,0

txtpwroff:
 .db "Setup done. Please power off me. Bye =)",13,10,0

;;;.endif ; serial_setup

;;;.ifdef SNI
print:
pr3:
    lpm    r16, z+
    cpi    r16, 0
    breq    pr2
    cpi    r16, 255
    breq    pr2
    rcall    USART_Transmit    ;  r16
    rjmp    pr3
pr2:
    ret

print_eeprom:
pr4:
    rcall    EEPROM_read    ; r24:r25+
    cpi    r16, 0
    breq    pr5
    cpi    r16, 255
    breq    pr5
    rcall    USART_Transmit    ;  r16
    rjmp    pr4
pr5:
    ret
.endif

.ifdef use_serial_port_tx
wchar:
USART_Transmit:
; Wait for empty transmit buffer
    sbis    UCSRA,UDRE
    rjmp    USART_Transmit
; Put data (r16) into buffer, sends the data
    out    UDR,r16
    ret
.endif

.ifdef use_serial_port_rx
; polling (no interrupt driven) used for setup user dialog
USART_Receive:
    sbis    UCSRA, RXC    ; Wait for data to be received
    rjmp    USART_Receive
    in    r16, UDR     ; Get and return received data from buffer
;    rcall    USART_Transmit     ; echo back
    ret
.endif 

; end of serial setup section.

;	jmp	w5100init
	jmp	error



; additional settings for multicast.
; R24:r25 point to mcast IP addr in eeprom.
; mcast MAC addr will be constructed from mcast IP.
w5100mcastinit1:
;    ldi    r24, low(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
;    ldi    r25, high(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
    push    r25
    push    r24
    rcall    EEPROM_read ; first IP byte not used - dropped
    ldi    r16, low(S0_DHAR)    ; mcast mac addr
    ldi    r17, high(S0_DHAR)
    rcall    w5100outaddr
    ldi    r16, 0x01    ; const.
    rcall    w5100outdata
    ldi    r16, 0x00    ; const.
    rcall    w5100outdata
    ldi    r16, 0x5e    ; const.
    rcall    w5100outdata
    rcall    EEPROM_read
    andi    r16, 0x7f    ; 23 lower bits of IP used to build MAC
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
;    ldi    r24, low(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
;    ldi    r25, high(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
    pop    r24
    pop    r25
    ldi    r16, low(S0_DIPR)    ; mcast ip
    ldi    r17, high(S0_DIPR)
    rcall    w5100outaddr
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    ret

w5100mcastinit2:
    ldi    r16, low(S0_MR)
    ldi    r17, high(S0_MR)
    rcall    w5100outaddr

;;;; test!
;;;.ifdef udp
;;;    ldi    r16, 0b00000010
;;;.else
;;;; must be only this...
    ldi    r16, 0b10000010    ; * set UDP, Multicasting on socket 0 mode register *
;;;.endif

    rcall    w5100outdata
;    ldi    r24, low(eep_settings_base + (defaults_port-defaults_part0)*2)
;    ldi    r25, high(eep_settings_base + (defaults_port-defaults_part0)*2)
push r25
push r24
    rcall    EEPROM_read    ; port
    mov    r20, r16
    rcall    EEPROM_read
    mov    r21, r16
    ldi    r16, low(S0_PORT)
    ldi    r17, high(S0_PORT)
    rcall    w5100outaddr
    mov    r16, r21        ; port - msb first
    rcall    w5100outdata
    mov    r16, r20
    rcall    w5100outdata

;    ldi    r24, low(eep_settings_base + (defaults_mcast_port-defaults_part0)*2)
;    ldi    r25, high(eep_settings_base + (defaults_mcast_port-defaults_part0)*2)
pop r24
pop r25
    rcall    EEPROM_read    ; port
    mov    r20, r16
    rcall    EEPROM_read
    mov    r21, r16
    ldi    r16, low(S0_DPORT)
    ldi    r17, high(S0_DPORT)
    rcall    w5100outaddr
    mov    r16, r21        ; port - msb first
    rcall    w5100outdata
    mov    r16, r20
    rcall    w5100outdata

    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_OPEN
    rcall    w5100outdata

    ret

dly10ms:
	push	r20
	ldi	r20, 200
dly10a:			; 10 ms
	rcall	delayx50us
	dec	r20
	brne	dly10a
	pop	r20
	ret


w5100init:
.ifdef SNI
; when not SNI, simple reads allowed, say for SNMP string r/w.
    sbi     UCSRB, RXCIE            ; rs232 read interrupt en.
.endif
; now true hardware reset via lp3470im5 used,
; so reset delay not need.

;    ldi    r16, 0b00000011    ; indirect & auto-increment
; added 04/09/2014
	ldi	r16, 0b10000011	; SW RESET and indirect / auto increment
	rcall	w5100outmode
	rcall	dly10ms

	ldi	r16, 0b00000011
	rcall	w5100outmode
	rcall	dly10ms


;    ldi    r24, low(eep_settings_base + 0)
;    ldi    r25, high(eep_settings_base + 0)
    ldi    r24, low(eep_settings_base + (defaults_mac - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mac - defaults_part0)*2)
    ldi    r16, low(SHAR)    ; mac addr
    ldi    r17, high(SHAR)
    rcall    w5100outaddr
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    ldi    r24, low(eep_settings_base + (defaults_ip - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_ip - defaults_part0)*2)
    ldi    r16, low(SIPR)    ; my ip
    ldi    r17, high(SIPR)
    rcall    w5100outaddr
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    ldi    r16, low(SUBR)    ; mask
    ldi    r17, high(SUBR)
    rcall    w5100outaddr
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    ldi    r16, low(GWR)    ; gw
    ldi    r17, high(GWR)
    rcall    w5100outaddr
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata
    rcall    EEPROM_read
    rcall    w5100outdata

; sockets size (use only one S0 here)
; try to move this section up.
; if anything not work, see w5100uni (20th copy)
    ldi    r16, low(RMSR)
    ldi    r17, high(RMSR)
    rcall    w5100outaddr
    ldi    r16, 0b00000011    ; all 8k RX memory to s0
    rcall    w5100outdata
    rcall    w5100outdata    ; TMSR... 8k TX memory to s0


; send multicast ID packets.
; it is 4 byte capabilities + 1024 bytes content of EEPROM, so 1028 total.
.ifdef sendid
; ! TODO: mega16 and mega32 different EEPROMs.
    ldi    r24, low(eep_settings_base + (defaults_mcast_idsend_ip - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mcast_idsend_ip - defaults_part0)*2)
    rcall    w5100mcastinit1
    ldi    r24, low(eep_settings_base + (defaults_mcast_idsend_port-defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mcast_idsend_port-defaults_part0)*2)
    rcall    w5100mcastinit2


	ldi    r20, 5
idsend4:
	ldi	r16, 10	
	rcall	flash_rdy_led
    dec    r20
    brne    idsend4
	


    ldi    r20, 5    ; q'ty of packets
idsend1:
; before rx int enabled, we can use all RAM as tx buf,
; so here tx buf can be more than 256 bytes. (eat part of rx buf)
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
; TODO - fix it
;    ldi    r16, capabilitybyte0
    st    y+, r16
;    ldi    r16, capabilitybyte1
    st    y+, r16
;    ldi    r16, capabilitybyte2
    st    y+, r16
;    ldi    r16, capabilitybyte3
    st    y+, r16
    ldi    r24, low(0) ; eeprom start
    ldi    r25, high(0)
    ldi    r26, low(EEPROMEND+1)
    ldi    r27, high(EEPROMEND+1)
idsnd2:
    rcall    eeprom_read
    st    y+, r16
    sbiw    r26, 1
    brne    idsnd2
; should it be optimized ?..
    ldi    r24, low(EEPROMEND+1 + 4) ; pkt sz
    ldi    r25, high(EEPROMEND+1 + 4)
    rcall    tx_packet_data

;	ldi	r16, 5	; 500 ms
;	rcall	flash_rdy_led

    sbi    ledRDYport, ledRDYbit ; light for 500 ms
    ldi    r19, 5 ; 10
; uses r17, r18, r19
    rcall    dly    ; 50 ms * r19
    cbi    ledRDYport, ledRDYbit ; dark for 500 ms
    ldi    r19, 5 ; 10
    rcall    dly    ; 50 ms * r19
    dec    r20
    brne    idsend1
;;; return to unicast mode
;    ldi    r16, low(S0_MR)
;    ldi    r17, high(S0_MR)
;    rcall    w5100outaddr
;.ifdef udp
;    ldi    r16, 0b00000010    ; udp ; ? not tested...
;.else
;    ldi    r16, 0
;.endif
;    rcall    w5100outdata
; done send ID
.endif ; sendid




.ifdef udp

.ifdef multicast
    ldi    r24, low(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mcast_ip - defaults_part0)*2)
    rcall    w5100mcastinit1
    ldi    r24, low(eep_settings_base + (defaults_mcast_port-defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mcast_port-defaults_part0)*2)
    rcall    w5100mcastinit2
;.endif

.else


;udpopen:
udp1:
    ldi    r16, low(S0_MR)
    ldi    r17, high(S0_MR)
    rcall    w5100outaddr
    ldi    r16, 0b00000010    ; udp
    rcall    w5100outdata
    ldi    r24, low(eep_settings_base + (defaults_port-defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_port-defaults_part0)*2)
    rcall    EEPROM_read    ; port
    mov    r20, r16
    rcall    EEPROM_read
    mov    r21, r16
    ldi    r16, low(S0_PORT)
    ldi    r17, high(S0_PORT)
    rcall    w5100outaddr
    mov    r16, r21        ; port - msb first
    rcall    w5100outdata
    mov    r16, r20
    rcall    w5100outdata
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_OPEN
    rcall    w5100outdata
    ldi    r16, low(S0_SR)
    ldi    r17, high(S0_SR)
    rcall    w5100outaddr
    rcall    w5100rd    ; port dir. change
    rcall    w5100read
;    cpi    r16, SR_SOCK_INIT
    cpi    r16, SR_SOCK_UDP
    breq    udp2
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_CLOSE
    rcall    w5100outdata
    rjmp    udp1; - not work...
udp2:
;    ldi    r16, 0
;.ifdef SNI
;	mov r00, r16 ; disconnection timer reset
;.endif
;    mov    r02, r16
;    mov    r03, r16
;    rcall    ringbufferinit


.endif

.endif


    ldi    r16, 0
;.ifdef SNI
;	mov r00, r16 ; disconnection timer reset
;.endif
    mov    r02, r16
    mov    r03, r16
    rcall    ringbufferinit


; prepare interrupts
; int2 - falling edge
;    in     r16, GICR
;    ori    r16, 0b00100000 ; int2 enable
;    out    GICR, r16
; int0 - low level
;     in    r16, MCUCR
;    ori    r16, 0b00000000
    in     r16, GICR
    ori    r16, 0b01000000 ; int0 enable
    out    GICR, r16

    ldi    r16, low(IMR)
    ldi    r17, high(IMR)
    rcall    w5100outaddr
    ldi    r16, 0b00000001    ; socket 0 interrupts en.
    rcall    w5100outdata



; copy eeprom to ram keywords for fast access
.ifdef srvctrl
    ldi    r24, low(eep_keywords_base)
    ldi    r25, high(eep_keywords_base)
    ldi    r28, low(ram_kw)
    ldi    r29, high(ram_kw)

    ldi    r27, high(ram_kw_end - ram_kw)
    ldi    r26, low(ram_kw_end - ram_kw)
cpy1:
    rcall    eeprom_read
    st    y+, r16
    sbiw    r26, 1
    brne    cpy1
.endif


;.ifdef multicast
.ifdef udp
; nope
.else
    rcall    timer1_int_enable
.endif


.ifdef autosend
	rcall	timer0_int_enable
.endif

.ifdef rotary_encoder
	rcall	timer0_int_enable
.endif


;   !!!!  added 10-11-2013: before, 'sleep' just not work.

ldi r16, 0b10000000 ; idle 15 ma
;ldi r16, 0b11110000 
out MCUCR, r16
; - ; full when not sleep - 30 ma

    sei

main:
    sbi    ledRDYport, ledRDYbit
.ifdef udp
    cbi    ledTCPCONport, ledTCPCONbit
.endif

    nop
    sleep
    nop
    rjmp    main
    rjmp    main


;=============================================
; subroutines...

flash_rdy_led:	; r16 - cycle duration
	sbi    ledRDYport, ledRDYbit ; light for 500 ms
;    ldi    r19, 5 ; 10
	mov	r19, r16
; uses r17, r18, r19
	rcall    dly    ; 50 ms * r19
	cbi    ledRDYport, ledRDYbit ; dark for 500 ms
;    ldi    r19, 5 ; 10
	mov	r19, r16
	rcall	dly    ; 50 ms * r19
	ret


error:	; permanent / unrecoverable / kernel panic / Ctulhu arrive
	ldi	r16, 2
	rcall	flash_rdy_led
	rjmp	error


dly:	; r19 - 50ms of pause (14M xtal)
	push	r18
	push	r17
dly4:
.ifdef xtal73728
    ldi    r18, 128
.else
    ldi    r18, 0
.endif
dly2:
    ldi    r17, 0
dly3:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    dec    r17
    brne    dly3
    dec    r18
    brne    dly2
    dec    r19
    brne    dly4
	pop	r17
	pop	r18
    ret


; hardware signal from w5100
;ext_interrupt_2:
;.ifdef multicast
.ifdef udp
ext_interrupt_0:
    cbi    ledRDYport, ledRDYbit
    sbi    ledTCPCONport, ledTCPCONbit
; clear int flag(s)
    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    sbrc     r16, INTERRUPT_RECV_BIT
    jmp    int_receive
    sbrc     r16, INTERRUPT_SEND_OK_BIT
    jmp    int_send_ok
; timeout here, or other unneeded interrupt:
	ldi    r16, low(S0_IR)
	ldi    r17, high(S0_IR)
	rcall    w5100outaddr
;	ldi    r16, (0xff) ; clear all remaining flags
; OR
;	ldi    r16, (0b00001000) ; clear only specific flag when search for error - use 'reti' below.
	rcall    w5100outdata
	jmp kernel_panic
; OR
;	reti

int_send_ok:
    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr
    ldi    r16, (1<<INTERRUPT_SEND_OK_BIT)
    rcall    w5100outdata

;;; - if multicast, always serial ?
; no, not always.
;.ifdef SNI
.ifdef use_serial_leds
    cbi    ledport, ledIPTXbit
;;; - if multicast, always serial ?
; no, not always.
.endif ; serial
	reti

;.else ;.ifndef multicast
.else ; tcp
ext_interrupt_0:    ; low level instead of (buggy?) edge detect int2
    rcall    timer1_int_disable
    cbi    ledRDYport, ledRDYbit
; clear int flag.
    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
;;;    mov    r00, r16    ; r00 - interrupt flags.
;;;    ldi    r16, low(S0_IR)
;;;    ldi    r17, high(S0_IR)
;;;    rcall    w5100outaddr

;;;    sbrc     r00, INTERRUPT_RECV_BIT
    sbrc     r16, INTERRUPT_RECV_BIT
    jmp    int_receive
;;;    sbrc     r00, INTERRUPT_CON_BIT
    sbrc     r16, INTERRUPT_CON_BIT
    jmp    int_established
;;;    sbrc     r00, INTERRUPT_SEND_OK_BIT
    sbrc     r16, INTERRUPT_SEND_OK_BIT
    jmp    int_send_ok
int_close:

    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr

    ldi    r16, (1<<INTERRUPT_DISCON_BIT|1<<INTERRUPT_TIMEOUT_BIT)
    rcall    w5100outdata
;    cbi    ledTCPCONport, ledTCPCONbit
    rcall    tcpclose
    rcall    timer1_int_enable
    reti
int_established:

    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr

    ldi    r16, (1<<INTERRUPT_CON_BIT)
    rcall    w5100outdata
    sbi    ledTCPCONport, ledTCPCONbit

; telnet control word taken from http://stackoverflow.com/questions/4532344/send-data-over-telnet-without-pressing-enter and bytes taken from Lantronix xport negotiation: it sends ff fb 01 ff fb 03
.ifdef srvctrl
    ldi    r24, low(eep_settings_base + (defaults_mode - defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_mode - defaults_part0)*2)
    rcall    EEPROM_read
;    mov    r18, r16
    cpi    r16, 0
    breq    mode_raw
mode_telnet:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0xfb
    st    y+, r16
    ldi    r16, 0x01
    st    y+, r16
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0xfb
    st    y+, r16
    ldi    r16, 0x03
    st    y+, r16
    ldi    r24, 6    ; answer size
    ldi    r25, 0
    rcall    tx_packet_data
mode_raw:
.endif ; .ifdef srvctrl

    rcall    timer1_int_enable
    reti
int_send_ok:

    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr

    ldi    r16, (1<<INTERRUPT_SEND_OK_BIT)
    rcall    w5100outdata
;.ifdef SNI
.ifdef use_serial_leds
    cbi    ledport, ledIPTXbit
.endif ; serial
    rcall    timer1_int_enable
    reti
;.endif
;.endif ; multicast
.endif ; tcp / udp



kernel_panic:
	sbi    ledRDYport, ledRDYbit 
	cbi    ledTCPCONport, ledTCPCONbit 
	ldi    r19, 2 ; 10
	rcall    dly 
	cbi    ledRDYport, ledRDYbit 
	sbi    ledTCPCONport, ledTCPCONbit 
	ldi    r19, 2 ; 10
	rcall    dly 
	rjmp	kernel_panic

;----------------------
.ifdef SNI
int_usartrx:
.ifdef udp
.else
    rcall    timer1_int_disable
;    ldi    r16, 0
;    mov    r00, r16 ; disconnection timer reset
.endif

    cbi    ledport, ledRDYbit

;.ifdef udp
;    sbi    ledTCPCONport, ledTCPCONbit
;.endif
.ifdef use_serial_leds
    sbi    ledport, ledRSRXbit
.endif

; test rs hardware using echo
.ifdef use_serial_ctrl0_pins
	sbic	ctl0pin, ctl0channel_or_echobit ; echo
	rjmp	no_echo
	in	r16, UDR
	rcall	USART_Transmit ; echo back
.ifdef use_serial_leds
	cbi	ledport, ledRSRXbit
.endif

.ifdef udp
.else
    rcall    timer1_int_enable
.endif

	reti
no_echo:
.endif

; if no tcp connection, drop incoming symbol and print error
;    rjmp     no_tcp_conn
    rcall    tx_packet_text
;in r16, UDR
.ifdef use_serial_leds
    cbi    ledport, ledRSRXbit
.endif
;.ifdef multicast
.ifdef udp
.else
    rcall    timer1_int_enable
.endif
    reti
.endif ; SNI





;------------------------
; two modes exist:
; 1.  txmode_text
;  Telnet mode: Tx packet size is unknown before starting transmission.
;  data reads directly from UART.
;  it is common to rs232/485 telnets, keyboard input, and other
;  slow stuff. So we collect bytes for tx in w5100's buffer,
;  and signal w5100 to start TX if:
;  * get CR - optional, useful on user text console;
;  * timeout or gap in byte flow; (agjustable timeout value)
;  * PKTLEN bytes collected in buffer. (max is 1514 probably)
;    UART (UDR) - tx data.
; 2.  txmode_data
;  Data mode: Tx packet size known before starting transmission.
;  data reads from RAM (y+) so RAM must be prepared.
;  high speed boards with well predefined data sizes, like eeprom prog,
;  DAC/ADC boards, GPIO, etc.
;         r24:r25 - tx packet size.
;      txbuf    - tx data.

tx_packet_text:    ; r12:r13 - used (only in this procedure)
        ; r02:r03 - used and don't touch.
.equ    PKTLEN = 512    ; probably need to be less than 'pktmaxlen'
            ; to avoid rx buf overrun
    rcall     txp_part1

txp1:
    in    r16, UDR  ; Get rs232 byte - hope it's not overwritten by nest byte  interrupt
;    mov    r01, r16    ; save - used for 'CR' detect send packet flag
    rcall    w5100outdata    ; since start of interrupt...
    inc     r02        ; r02:r03 = r02:r03 + 1
;;;    brcc    txp2        ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    txp2
    inc     r03
txp2:

; this must be optimized!
    dec    r12
;    brcc    txp3    ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    txp3
; here r12=0
    cp    r12, r13    ; 0x0000 - special case
    breq    txp5
    dec    r13
    rjmp    txp3
txp5:
    rcall     txp_part2

txp3:
; it's work.
;    mov    r16, r01    ; reason 1 of 3: 'CR' ('enter') receive
;    cpi    r16, 13 ; 'CR'
;    breq    sendpkt

;             reason 2 of 3: packet size limit
;    mov    r16, r02    ; or mov r16, r03
    mov    r16, r03
    cpi    r16, high(PKTLEN)
    breq    sendpkt

.ifdef multicast ; midi
    ldi    r17, 100 ; midi    ; agjust this. ; 90 still too small for
; cheap "49 MIDI key roll piano keyboard", H6188P-F44 based. It gives
; three MIDI bytes (ex. 90 4E 7F) with H_U_G_E gaps.

; OR use 3-byte counter for less sound latency!
.else
    ldi    r17, 2 ; agjust this.
.endif
; 1,0 (256) enough for 115200 bod at 14M xtal, but not enough for 18M xtal;
; 512 and 2,192 (384) probably norm for 115200 at 18M
txp4a:
    ldi    r16, 192        ; agjust this.
; 128 - small for 115200 but 255 normal. (r17=1)
txp4:
    sbic    UCSRA, RXC
    rjmp    txp1        ; new rs232 data exist
    dec    r16
    brne    txp4    ; reason 3 of 3: timeout when waiting next rs232 byte
    dec    r17
    brne    txp4a    ; reason 3 of 3: timeout when waiting next rs232 byte

    rjmp    txp_part3

;------------------------
tx_packet_data:    ; r12:r13 - used (only in this procedure)
        ; r02:r03 - used and don't touch.
    movw    r02, r24    ; save packet size if it known.
; waitforbuffer uses r02-r03 but it undefined in text mode.
    rcall    waitforbuffer

    rcall     txp_part1

    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)

txd1:
    ld    r16, y+
    rcall    w5100outdata

; this must be optimized!
    dec    r12
;    brcc    txp3    ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    txd3
; here r12=0
    cp    r12, r13    ; 0x0000 - special case
    breq    txd5
    dec    r13
    rjmp    txd3
txd5:
    rcall     txp_part2

txd3:
    sbiw    r24, 1
    brne    txd1

txp_part3:
sendpkt:
    ldi    r16, low(S0_TX_WR)
    ldi    r17, high(S0_TX_WR)
    rcall    w5100outaddr
    add    r14, r02
    adc    r15, r03
    mov    r16, r15
    rcall    w5100outdata
    mov    r16, r14
    rcall    w5100outdata
; socket send
;.ifdef SNI
.ifdef use_serial_leds
    sbi    ledport, ledIPTXbit
.endif
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_SEND
    rcall    w5100outdata
    ldi    r16, 0
    mov    r02, r16
    mov    r03, r16
;    rjmp    sendpk1
;no_tcp_conn:
;    in    r16, UDR
;    ldi    r30, low(txterr1*2)
;    ldi    r31, high(txterr1*2)
;    rcall    print
;sendpk1:
;no_tx_packet:

;wee: rjmp wee

    ret


txp_part1:
; init transmitting
    ldi    r16, low(S0_TX_WR)
    ldi    r17, high(S0_TX_WR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    mov    r15, r16
    mov    r17, r16
    rcall    w5100read
    mov    r14, r16    ; r14:r15 save prevoius place

    andi    r17, high(S0_TX_LENGTH-1)
    andi    r16, low(S0_TX_LENGTH-1)
; calculate size to end of buffer
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
    sub    r12, r16
    sbc    r13, r17

    ori    r17, high(S0_TX_BASE)    ; add base address
    ori    r16, low(S0_TX_BASE)
    rcall    w5100outaddr    ; prepare writing into memory
    ret

txp_part2:
; end of memory - turn to start
    ldi    r16, low(S0_TX_BASE)
    ldi    r17, high(S0_TX_BASE)
    rcall    w5100outaddr
; reinit r12-r13
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
    ret




.ifdef FALSE
read_ad7680:
; try to use dedicated spi.    pin 3 (pb7)    SCK out -->  SCLK
;                pin 2 (pb6)    MISO in <--  SDATA
;    ldi    r28, low(ram_pckt)
;    ldi    r29, high(ram_pckt)
;    ldi    r16, 0
;    st    y+, r16
    cbi    ad7680port, ad7680aCSbit    ; CS=0 when active
    sbi    ad7680port, ad7680aLEDbit

    nop
    out     SPDR, r16    ; dummy write
wait01:
    sbis    SPSR, SPIF
    rjmp    wait01
    in    r16, SPDR
;    st    y+, r16
    out     SPDR, r16    ; dummy write
wait02:
    sbis    SPSR, SPIF
    rjmp    wait02
    in    r16, SPDR
;    st    y+, r16
    out     SPDR, r16    ; dummy write
wait03:
    sbis    SPSR, SPIF
    rjmp    wait03
    in    r16, SPDR
;    st    y+, r16
    sbi    ad7680port, ad7680aCSbit    ; CS=1 when idle
    cbi    ad7680port, ad7680aLEDbit

    ret
.endif ; ad7680




; r08:r09 - freq.
;    ldi    r16, low(3000)    ; initial...
;    mov    r08, r16
;    ldi    r16, high(3000)
;    mov    r09, r16
; r10 - freq. fractional 0-63
;    ldi    r16, 0
;    mov    r10, r16
.ifdef adSPIctl
set_freq_adSPIctl:
    push    r27
    push     r26
    push    r25
    push    r24
; r5
    ldi    r27, 0
    ldi    r26, 0    ; error??? fig 29 page 17 adSPIctl
    ldi    r25, 0
    ldi    r24, 0b00000101    ; r5
    rcall     write_adSPIctl
; r4
    ldi    r27, 0
    ldi    r26, 0
; for fractional mode
;    ldi    r25, 255    ; band select divider: 30MHz/255=117kHz (max 125 kHz)
; for int mode (Fdet=1MHz)
    ldi    r25, 8        ; band select divider: 1MHz/8 (max 125 kHz)

    lsl    r25
    rol    r26
    lsl    r25
    rol    r26
    lsl    r25
    rol    r26        ; db8:db15 -> db12:db19
    ori    r26, 0b10000000    ; feedback select: 1 = fundamental
; ori r26, 0b00010000 ; test - divide-by-2 - work.
    ori    r25, 0b00000110    ; MTLD
    ldi    r24, 0b00111100 ; r4
    rcall     write_adSPIctl
; r3
    ldi    r27, 0
    ldi    r26, 0
    ldi    r25, 0
    ldi    r24, 0b00000011    ; r3
    rcall     write_adSPIctl
; r2
    ldi    r27, 0b00011000
;    ldi    r26, 40        ; xtal 40M, int mode, step 1 MHz
    ldi    r26, 32        ; xtal 32M, int mode, step 1 MHz
    ldi    r25, 0
    lsr    r26
    ror    r25
    lsr    r26
    ror    r25    ; R counter: bits 16:23 -> 14:21
    ori    r25, 0b00011111    ; icp=1111, ldf=1

    ldi    r24, 0b01000010    ; r2
    rcall     write_adSPIctl
; r1
    ldi    r27, 0b00001000
    ldi    r26, 0
    ldi    r25, 0b10000000    ; phase=1 - recommended
    ldi    r24, 0b00000001    ; r1
    rcall     write_adSPIctl
; r0
; r09:r08 - freq
    mov    r27, r09
    mov    r26, r08
;ldi    r26, low(3000)
;ldi    r27, high(3000)
    ldi    r25, 0
    lsr    r27
    ror    r26
    ror    r25    ; db15-db30 - N divider

    ldi    r24, 0b0000000    ; r0
    rcall     write_adSPIctl

    pop    r24
    pop    r25
    pop    r26
    pop    r27
    ret

; r24:r27 - 32-bit word for adSPIctl
write_adSPIctl:
; try to use dedicated spi.    pin 3 (pb7)    SCK out --> adSPIctl CLK
;                pin 1 (pb5)    MOSI out --> adSPIctl DATA
    out     SPDR, r27
wait01:
    sbis    SPSR, SPIF
    rjmp    wait01
;write_adf4360:
    out     SPDR, r26
wait02:
    sbis    SPSR, SPIF
    rjmp    wait02
    out     SPDR, r25
wait03:
    sbis    SPSR, SPIF
    rjmp    wait03
    out     SPDR, r24
wait04:
    sbis    SPSR, SPIF
    rjmp    wait04
nop
nop
    sbi    adSPIctlport, adSPIctlaLEbit
nop
nop
nop
nop
    cbi    adSPIctlport, adSPIctlaLEbit
    ret
.endif ; adSPIctl




.ifdef eeprom_prog

;.ifdef at17prog
.def   temp = r16
.equ   TW_START    = 0x8
.equ   TW_REP_START   = 0x10
.equ   TW_MT_SLA_ACK   = 0x18
.equ   TW_MT_SLA_NACK   = 0x20
.equ   TW_MT_DATA_ACK   = 0x28
.equ   TW_MT_DATA_NACK   = 0x30

.equ   TW_MR_SLA_ACK   = 0x40
.equ   TW_MR_SLA_NACK   = 0x48
.equ   TW_MR_DATA_ACK   = 0x50
.equ   TW_MR_DATA_NACK   = 0x58

I2C_Start:
   ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWSTA)
   out   TWCR,temp
   rcall   i2c_wait
   in   temp,TWSR
   andi   temp,0xF8
   cpi   temp,TW_START
   breq   I2C_free
   cpi   temp,TW_REP_START
   brne   i2c_xit
I2C_free:
   sec
   ret
i2c_xit: clc
   ret

I2C_Stop:
   ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
   out   TWCR,temp
   ret

i2c_write:
   out   TWDR,r17
   ldi   temp,(1<<TWINT)|(1<<TWEN)
   out   TWCR,temp
   rcall   i2c_wait
   in   temp,TWSR
   andi   temp,0xF8
   cpi   temp,TW_MT_SLA_ACK
   breq   i2c_ack
   cpi   temp,TW_MT_DATA_ACK
   breq   i2c_ack
   cpi   temp,TW_MR_SLA_ACK
   breq   i2c_ack
   cpi   temp,TW_MR_DATA_ACK
   breq   i2c_ack
   clc
   ret
i2c_ack:
   sec
   ret

i2c_read:
;   clc         ; comment out this for ACK if .cs
   ldi   temp,(1<<TWINT)|(1<<TWEN)
   brcc   i2c_nak
   ori   temp,(1<<TWEA)
i2c_nak:
   out   TWCR,temp
   rcall   i2c_wait
   in   r17,TWDR
   ret

;***** internal function wait for TWI operation to complete ***
i2c_wait:
   in   temp,TWCR   ; use register cos sfr is out of range
   sbrs   temp,TWINT
   rjmp   i2c_wait
   ret

i2c_off:
; Added to prevent lock up TWI when power of slave is off.
; Power cycle is req'd by at17 series eeprom when read ID code.
; But when no power on slave, bus locks up, and 'i2c_wait' never return.
; So we switch off TWI hardware here.
; Dont worry, it automatically start again in 'I2C_Start'.
    ldi   temp, 0  ; twi full off
    out   TWCR, temp
    ret
;.endif ; at17prog
.endif	; eeprom_prog


EEPROM_read:
; Wait for completion of previous write
    sbic    EECR, EEWE
    rjmp    EEPROM_read
; Set up address in address register
    out    EEARH, r25
    out    EEARL, r24
; Start eeprom read by writing EERE
    sbi    EECR, EERE
; Read data from data register
    in    r16, EEDR
    adiw    r24, 1
    ret

.ifdef serial_setup    ; only need to write if serial console and user setup exist
; taken from atmel doc
EEPROM_write:
; Wait for completion of previous write
    sbic    EECR, EEWE
    rjmp    EEPROM_write
; Set up address in address register
    out    EEARH, r25
    out    EEARL, r24
; Write data to data register
    out    EEDR, r16
; Write logical one to EEMWE
    sbi    EECR, EEMWE
; Start eeprom write by setting EEWE
    sbi    EECR, EEWE
    adiw    r24, 1
    ret
.endif





;-----------------
.ifdef udp
; oj
.else
tcpopen:
tcp1:
    ldi    r16, low(S0_MR)
    ldi    r17, high(S0_MR)
    rcall    w5100outaddr
    ldi    r16, 0b00100001    ; tcp and no delayed ACK send
    rcall    w5100outdata
    ldi    r24, low(eep_settings_base + (defaults_port-defaults_part0)*2)
    ldi    r25, high(eep_settings_base + (defaults_port-defaults_part0)*2)
;    ldi    r24, low(eep_settings_base + 18)
;    ldi    r25, high(eep_settings_base + 18)
    rcall    EEPROM_read    ; port
    mov    r20, r16
    rcall    EEPROM_read
    mov    r21, r16
    ldi    r16, low(S0_PORT)
    ldi    r17, high(S0_PORT)
    rcall    w5100outaddr
    mov    r16, r21        ; port - msb first
    rcall    w5100outdata
    mov    r16, r20
    rcall    w5100outdata
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_OPEN
    rcall    w5100outdata
    ldi    r16, low(S0_SR)
    ldi    r17, high(S0_SR)
    rcall    w5100outaddr
    rcall    w5100rd    ; port dir. change
    rcall    w5100read
    cpi    r16, SR_SOCK_INIT
    breq    tcp2
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_CLOSE
    rcall    w5100outdata
    rjmp    tcp1
tcp2:
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_LISTEN
    rcall    w5100outdata
    ldi    r16, low(S0_SR)
    ldi    r17, high(S0_SR)
    rcall    w5100outaddr
    rcall    w5100rd    ; port dir. change
    rcall    w5100read
    cpi    r16, SR_SOCK_LISTEN
    breq    tcp3
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_CLOSE
    rcall    w5100outdata
    rjmp    tcp1
tcp3:
    ldi    r16, 0
.ifdef SNI
	mov r00, r16 ; disconnection timer reset
.endif
    mov    r02, r16
    mov    r03, r16
    rcall    ringbufferinit
    ret

tcpdisconnect:
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_DISCON
    rcall    w5100outdata
    cbi    ledTCPCONport, ledTCPCONbit
    ret

tcpclose:
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_CLOSE
    rcall    w5100outdata
    cbi    ledTCPCONport, ledTCPCONbit
    ret
.endif ; udp

;-----------------------------
;When interrupt-driven data
;transmission is used, the Data Register Empty Interrupt routine must either write new data to
;UDR in order to clear UDRE or disable the Data Register empty Interrupt, otherwise a new inter-
;rupt will occur once the interrupt routine terminates.

; uses ring buffer r04:r05 increases when writes to buf, r06:r07 increase when readout.

; one interrupt per transmitted byte.
;.ifdef rs232tx_interrupt_mode
.ifdef SNI
int_usartudre:
    cp    r04, r06
    brne    txdataexist
    cp    r05, r07
    brne    txdataexist
;    rjmp    nomoretxdata
nomoretxdata:
.ifdef use_serial_leds
    cbi    ledport, ledRSTXbit
.endif
;disable the Data Register empty Interrupt
    cbi     UCSRB, UDRIE
    reti

txdataexist:
    push    r31
    push    r30
    push    r16

; wait for RTS ready
;.ifdef	rs232_RTSCTS_printer
;wait_for_rts:
;	nop
;	sbic	ctl1pin, mbsw2bit_or_ctl1INCTSbit
;	rjmp	wait_for_rts	
;.endif

    movw    r30, r06
    ld    r16, z


; workaround against insane and heretic behaviour of GtkTerm (or entire Ubuntu
; system?) when "Telnet control flags" (ff xx xx, ff xx xx) used. When these
; flags are present, telnet replaces 0x0d 0x0a -> 0x0d 0x00. When Gtkterm receives
; 0x00, it randomly damages some symbols after this byte.
; So we not transmit zeroes at rs232 transmitter. this is bad if unicode used,
; i do not know if zero is allowed at all in unicode byte sequence.

;.ifdef	rs232_RTSCTS_printer
;	out	UDR, r16
;.else

cpi r16, 0
;brne aqaq
breq aqaq
;ldi r16,'*'
	out	UDR, r16
aqaq:

;.endif


;    out    UDR, r16
    adiw    r30, 1
    cpi    r31, high(rxbufend)
    brne    txx1
    ldi    r31, high(rxbuf)
txx1:
    movw    r06, r30

    pop    r16
    pop    r30
    pop    r31
    reti

.endif

;-------------------------------------
; rx packet:
int_receive:
; uses r08-r11: r08-r09 - rcv size, r10-r11 - read address pointer
;    rcall    timer1_int_disable
;ldi r24, 0
readmultiplepackets:        ; it's even exist really?
; get rcv size
    ldi    r16, low(S0_RX_RSR)
    ldi    r17, high(S0_RX_RSR)
    rcall    w5100outaddr
    rcall    w5100rd    ; port dir. change
    rcall    w5100read
    mov    r09, r16
    rcall    w5100read
    mov    r08, r16    ; r08:r09 - RX Received Size
    or    r16, r09    ; zero if both = 0
    brne    dataexist
;    jmp    donereadmultiple
;    jmp    rxint_ret    ; no rx data
;rxint_ret:
    ldi    r16, low(S0_IR)
    ldi    r17, high(S0_IR)
    rcall    w5100outaddr
    ldi    r16, (1<<INTERRUPT_RECV_BIT)
    rcall    w5100outdata
.ifdef multicast
;
.else
    rcall    timer1_int_enable
.endif
    reti

w5100rdstart:
.ifdef use_serial_leds
    sbi    ledport, ledRSTXbit
.endif
.ifdef SNI
    movw    r28, r04    ; ring buffer
.else
    ldi    r28, low(rxbuf)        ; not ring buffer - starts always from 1st byte
    ldi    r29, high(rxbuf)
.endif

;.ifdef at17prog
;    ldi    r28, low(rxbuf)        ; not ring buffer - starts always from 1st byte
;    ldi    r29, high(rxbuf)
;.endif ; at17prog

;.ifdef adSPIctl
;    ldi    r28, low(rxbuf)        ; not ring buffer - starts always from 1st byte
;    ldi    r29, high(rxbuf)
;.endif ; adSPIctl
;
;.ifdef ad7680
;    ldi    r28, low(rxbuf)        ; not ring buffer - starts always from 1st byte
;    ldi    r29, high(rxbuf)
;.endif ; adSPIctl


w5100rdcont:
    movw    r24, r08
w5100rd1:
    rcall    w5100read
.ifdef SNI
;    rcall    USART_Transmit    ;  r16
.endif
;.ifdef at17prog
    st    y+, r16
;.endif at17prog

.ifdef SNI    ; catch rollover of ring buffer.
    cpi    r29, high(rxbufend)
    brne    rxx1
    ldi    r29, high(rxbuf)
rxx1:
.endif

    sbiw    r24, 1
    brne    w5100rd1
.ifdef SNI
    movw    r04, r28    ; ring buffer save

;    cbi    ledport, ledRSTXbit
.endif
    ret




; really read - data is exist
dataexist:
.ifdef use_serial_leds
    sbi    ledport, ledIPRXbit
.endif

.ifdef SNI
;.ifdef multicast
.ifdef udp
.else
    ldi    r16, 0
    mov    r00, r16 ; disconnection timer reset
.endif
.endif

; get address
    ldi    r16, low(S0_RX_RD)
    ldi    r17, high(S0_RX_RD)
    rcall    w5100outaddr
    rcall    w5100rd    ; port dir. change
    rcall    w5100read
    mov    r11, r16
    mov    r17, r16
    rcall    w5100read
    mov    r10, r16
    andi    r17, high(S0_RX_LENGTH-1)    ; masking
    andi    r16, low(S0_RX_LENGTH-1)
    ori    r17, high(S0_RX_BASE)    ; add base address
    ori    r16, low(S0_RX_BASE)
    rcall    w5100outaddr
    rcall    w5100rd
    mov    r16, r10
    mov    r17, r11
    andi    r16, low(S0_RX_LENGTH-1)
    andi    r17, high(S0_RX_LENGTH-1)
    add    r16, r08    ; here is end-of-packet address and it may overlap boundary.
    adc    r17, r09
    cpi    r17, high(S0_RX_LENGTH)
    brlo    rcv1
    cpi    r16, low(S0_RX_LENGTH)
    brlo    rcv1
    breq    rcv1

;zxc:
    subi    r16, low(S0_RX_LENGTH)    ; overrun q'ty
    sbci    r17, high(S0_RX_LENGTH)
    push    r09    ; originall full length - must saved to use for save next addr.
    push    r08
    sub     r08, r16
    sbc    r09, r17        ; remaining q'ty
    push    r17
    push    r16
;    ldi    r19, 0
    rcall    w5100rdstart        ; start to middle of packet
    pop    r08    ; swap
    pop    r09
    ldi    r17, high(S0_RX_BASE)    ; start from base address
    ldi    r16, low(S0_RX_BASE)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100rdcont        ; middle to end of packet
    pop    r08
    pop    r09
    rjmp    rcv3
rcv1:
;    ldi    r19, 0
    rcall    w5100rdstart        ; full packet
rcv3:
; save new place for next read
    ldi    r16, low(S0_RX_RD)
    ldi    r17, high(S0_RX_RD)
    rcall    w5100outaddr
    add    r10, r08
    adc    r11, r09
    mov    r16, r11
    rcall    w5100outdata
    mov    r16, r10
    rcall    w5100outdata


.ifdef SNI
; when too many ethernet data arrives, signalling always 'socket read done' 
; signals to host to send new data (?), so may owerflow buffer.
; wait for processing data before signalling read done?
; read interrupt state, if active, serial transmission in progress.
;wait_for_serialINTdriven_tx_done:
;	nop
; not work because inside this interrupt, another interrupt not work (awaiting)
; so this flag never cleared if wait here for it.
;	sbic	UCSRB, UDRIE
;	rjmp	wait_for_serialINTdriven_tx_done    
; but how to detect emptying of rs232 tx buf?
; here is impossible because here inside interrupt, tx not work.
.endif

; socket read done signal
    ldi    r16, low(S0_CR)
    ldi    r17, high(S0_CR)
    rcall    w5100outaddr
    ldi    r16, CR_RECV
    rcall    w5100outdata
;rcall txtest
;    jmp    readmultiplepackets

;donereadmultiple:
.ifdef use_serial_leds
;.ifdef SNI
    cbi    ledport, ledIPRXbit
.endif


; now packet in RAM and we process it.
; process received data: ........
; this is depend on daughterboard installed, so here is different sections.


; for server ctrl we need to check incoming packet if it is command for
; server pwr/rst buttons control. if no, pass it to usart like in plain serial mode.
.ifdef srvctrl
;    push    r05
;    push    r04

;    ldi    r20, 0    ; flag
    ldi    r21, 0
cc0:
    mov    r18, r21
    ldi    r19, 0
    swap    r18
    lsl    r18
    rol    r19    ; r18:r19 = r18:r19 * 32 - shift
    ldi    r28, low(ram_kw)
    ldi    r29, high(ram_kw)
    add    r28, r18
    adc    r29, r19    ; start adress of next string in ram
    movw    r30, r06    ; start of rx packet in ring buffer
    ldi    r20, 0        ; position in string
cc1:    ld    r16, y+        ; original: keyword for compare
    cpi    r16, 0
    breq    zz1
;    cpi    r16, 255    ; found end of string - must check if it first
;    breq    zz1        ; byte (zero-length string) or no
    rjmp    cc5
zz1:    cpi    r20, 0
    breq    compare_fail
    rjmp    compare_ok    ; found delimiter but it not first symbol - then previous are identical.
cc5:
    ld    r17, z+        ; not end of string - must be compared.
    cp    r16, r17
    brne    compare_fail
; rollover of the end of RAM buffer - jump to start of buffer
    cpi    r31, high(rxbufend)
    brne    cc3
    ldi    r31, high(rxbuf)
cc3:
    inc    r20
    cpi    r20, 32        ; here need to limit comparing symbols to received string size
    brne    cc1        ; but we hope we never reach 32 value here.
compare_fail:
    inc    r21
    cpi    r21, cmd_qty_total
    brne    cc0
    rjmp    cmd_not_found

compare_ok:
; need to throw away received symbols in ring buffer - it is keyword and
; not need to be passed to server telnet console.
;    movw    r04, r06 - it work.
; moved to end of command processing,
; due to some commands maybe need to process additional data which
; exist in packet after command text.
;    rcall    ringbufferinit



    call    ringbufferinit





; then process command (number in r21)
;ldi    r16, '0'
;add    r16, r21
;rcall    wchar    ;- it work.

    cpi    r21, 0
    breq    cmd0
    cpi    r21, 1
    breq    cmd1
    cpi    r21, 2
    breq    cmd2
    cpi    r21, 3
    breq    cmd3
    cpi    r21, 4
    breq    cmd4
    cpi    r21, 5
    breq    cmd5
    cpi    r21, 6
    breq    cmd6
    cpi    r21, 7
    breq    cmd7

;    cpi    r21, httpreply_num ; 9
;    breq    cmd_httpreply
;    cpi    r21, cmdconfig_num ; 10
;    breq    cmd_config
    rjmp    cmddone

cmd_httpreply:
    jmp    cmd_httpreply2

cmd_config:
    jmp    cmd_config2


cmd6:
    cbi    ctl0port, ctl0force9600_and_relaybit ; out '0' - inverted relay.
    rjmp    cmddone

cmd7:
    sbi    ctl0port, ctl0force9600_and_relaybit ; out '1' - inverted relay.
    rjmp    cmddone

cmd0:
    cbi    ctl0port, ctl0channel_or_echobit    ; set channel
    rjmp    cmddone

cmd1:
    sbi    ctl0port, ctl0channel_or_echobit    ; set channel
    rjmp    cmddone

cmd3:
    rcall    sendwait5
    ldi    r19, 100    ; 5 seconds
    rjmp    chp
cmd2:
    rcall    sendwait1
    ldi    r19, 20
chp:
    sbic    ctl0pin, ctl0channel_or_echobit    ; read current channel
    rjmp    chp1
chp0:
    cbi    btnport, mbsw0bit_or_ctl1TXENbit
    rcall    dly
    rcall    senddone
    sbi    btnport, mbsw0bit_or_ctl1TXENbit
    rjmp    cmddone

chp1:
;    rcall    sendwait
    cbi    btnport, mbsw2bit
    rcall    dly
    rcall    senddone
    sbi    btnport, mbsw2bit
    rjmp    cmddone

cmd4:
    rcall    sendwait1
    ldi    r19, 20
    sbic    ctl0pin, ctl0channel_or_echobit    ; read current channel
    rjmp    rst1
rst0:
    cbi    btnport, mbsw1bit_or_ctl1NODUPLEXbit
    rcall    dly
    rcall    senddone
    sbi    btnport, mbsw1bit_or_ctl1NODUPLEXbit
    rjmp    cmddone

rst1:
    cbi    btnport, mbsw3bit
    rcall    dly
    rcall    senddone
    sbi    btnport, mbsw3bit
    rjmp    cmddone

cmd5:
    ldi    r18, 10 ; probes q'ty to determine 'sleep' state
; (pwr led blink) or see how hdd led blinks

ledprobe:
    ldi    r30, low(txtleds*2)
    ldi    r31, high(txtleds*2)
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    rcall     txtmemcpy

    in    r16, mbledreadpin
    andi    r16, 0x0f
    mov    r17, r16

;    subi    r16, 255-'0'    ; fix it. currently ls266 pinout wrong. :(
;    st    y+, r16
    rcall    wbit
    rcall    wbit
    rcall    wbit
    rcall    wbit
    ldi    r16, 13
    st    y+, r16
    ldi    r16, 10
    st    y+, r16
    ldi    r16, 0
    st    y+, r16

    ldi    r24,46    ; answer size
    ldi    r25,0
push r18
    rcall    tx_packet_data
pop r18

push r18
    ldi    r19, 5    ; 1/4 second delay between probes
    rcall    dly
pop r18

    dec    r18
    brne    ledprobe

    rjmp    cmddone

wbit:
    mov    r16, r17
    andi    r16, 1
    ori    r16, '0'
    st    y+, r16
    ldi    r16, ' '
    st    y+, r16
    lsr    r17
    ret


;    ld    r17, z+        ; not end of string - must be compared.
;    cp    r16, r17

cmd_httpreply2:
    ld    r16, z+
    cpi    r16, ' '    ; 'GET / '
    brne    htterr

    ldi    r30, low(httpreplytext*2)
    ldi    r31, high(httpreplytext*2)
    ldi    r24, low ( (httpreplytextend-httpreplytext) * 2)
    ldi    r25, high ( (httpreplytextend-httpreplytext) * 2)
    rjmp    repl2
htterr:
    ldi    r30, low(err404string*2)
    ldi    r31, high(err404string*2)
    ldi    r24, low ( (err404stringend-err404string) * 2)
    ldi    r25, high ( (err404stringend-err404string) * 2)
repl2:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    rcall    txtmemcpy
    rcall    tx_packet_data
    rcall    tcpdisconnect
;;;    jmp    cmddone
;;    jmp    readmultiplepackets

    rjmp    cmddone

httpreplytext:
; must update to new reply from web server.
 .db "HTTP/1.0 200 OK",13,10,"Content-Type: text/html",13,10,13,10
 .db "<html><body text=",34,"#eee",34," bgcolor=",34,"#111",34,"><h1>It works! </h1>"
 .db "<p>JOPA. </p> "
 .db "<p>JOPA2.</p> "
 .db "<hr><address>OSCaR Server </address>"
 .db "</body></html>"
httpreplytextend:
 .db 0,0



cmd_config2:

    rjmp    cmddone



; send 'Wait' message back to telnet
; unfortunately there is no space in RAM for txbuf, so can't send any messages =(
; but maybe small txbuf enough???
sendwait5:
    ldi    r30, low(txtwait5*2)
    ldi    r31, high(txtwait5*2)
    rjmp    sendwait
sendwait1:
    ldi    r30, low(txtwait1*2)
    ldi    r31, high(txtwait1*2)
sendwait:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    rcall     txtmemcpy
    ldi    r24,18        ; answer size
    ldi    r25,0
    rcall    tx_packet_data
    ret

senddone:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ldi    r30, low(txtdone*2)
    ldi    r31, high(txtdone*2)
    rcall     txtmemcpy
    ldi    r24,7        ; answer size
    ldi    r25,0
    rcall    tx_packet_data
    ret

txtwait1:
 .db "Wait 1 second...  ",0,0
txtwait5:
 .db "Wait 5 seconds... ",0,0
txtdone:
 .db "Done!",13,10,0
txtleds:
 .db " * LEDs: hdd0, pwr0, hdd1, pwr1:   ",0,0,0



cmddone:
;    pop    r04
;    pop    r05

    call    ringbufferinit

    rjmp    nnn

cmd_not_found:
.endif ; srvctrl(2)


    rjmp    nxtt
txtmemcpy:
tm1:
    lpm    r16, z+
    st    y+, r16
    cpi    r16, 0
    breq    tm2
;    st    y+, r16  -- moved up 06-01-2013
    rjmp    tm1
tm2:
    ret
nxtt:


; process for serial   and   process for srvctrl when received data is not command.
.ifdef SNI
    sbi     UCSRB, UDRIE    ; start interrupt-driven transmission of ram buffer
; --> search for: int_usartudre:
.endif

;.ifdef srvctrl
;nnn:
.ifdef use_serial_leds
    cbi    ledport, ledRSTXbit
.endif


; --- next section...

.ifdef rs232_RTSCTS_printer
	ldi	r26, low(rxbuf)
	ldi	r27, high(rxbuf)
	movw	r24, r08    ; rx length
prn_out:
wait_for_rts:	; wait for RTS ready
	nop
	sbic	ctl1pin, mbsw2bit_or_ctl1INCTSbit
	rjmp	wait_for_rts	

	ld	r16, x+
	rcall	wchar
	sbiw	r24, 1
	brne	prn_out

	ldi	r28, low(txbuf)
	ldi	r29, high(txbuf)
	ldi	r16, 'O'
	st	y+, r16
	ldi	r16, 'K'
	st	y+, r16
	ldi	r16, 0x0a
	st	y+, r16
	ldi	r24, 3        ; answer size
	ldi	r25, 0
	rcall	tx_packet_data
	jmp	readmultiplepackets
.endif


; --- next section...
;
;	DEPRECATED since 12.06.2013 due to TWI and I2C combined in next section
; 	(universal eeprom prog)
;
.ifdef at17prog
.equ    ctrlpacketsize = 8
.equ capabilitybyte0 = 0x11
.equ capabilitybyte1 = 0x22
.equ capabilitybyte2 = 0x33
.equ capabilitybyte3 = 0x44
    ldi    r26, low(rxbuf)
    ldi    r27, high(rxbuf)

    movw    r24, r08    ; rx length

    cpi    r24, low(ctrlpacketsize)
    brne    iodata_received2
    cpi    r25, high(ctrlpacketsize)
    brne    iodata_received2
    rjmp     cmd_received
iodata_received2:
    jmp    iodata_received

cmd_received:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ldi    r16, 0x33    ; prefill buf for debug
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ld    r16, x+
    cpi    r16, 0x55
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xaa
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0x00
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xff
    brne    wrongpkt
    ld    r16, x+
    ld    r16, x+        ; 5th byte
    cpi    r16, 1
    brne    xx0
; read from at17 and send pkt
;    jmp    at17readandsend
    rcall    at17readandsend
;    rjmp    rxint_ret        changed 31-08-11 due to maybe this is bug
    jmp    readmultiplepackets

xx0:
    ld    r16, x+        ; 6th byte
; select mode:
    cpi    r16, 0
    brne    xx1
    jmp    getid_answer
xx1:
    cpi    r16, 1
    brne    xx2
; set mode
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
    ld    r16, x+        ; 7th byte - here it's mode
;    out    ctlport, r16
;swap r16
;andi r16, 0b
out    eepromCTRLport, r16
    rjmp    cmddone
xx2:
    cpi    r16, 2
    brne    xx3
; set START
    ldi    r24,1
    ldi    r25,0
;    st    y+, r16        ; prepare simple answer
    rcall    I2C_Start
    ld    r16, x+        ; 7th byte - addr to write to eep, + set R / W
    mov    r17, r16
    andi    r16, 0b00000001
    mov    r01, r16    ; mode for next data flow: 0 - write, 1 - read
    rcall    eepwrbyte    ; write address
    st    y+, r16        ; store ack
    rjmp    cmddone
xx3:
    cpi    r16, 3
    brne    xx4
;sbi ctlport, 5
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
; set STOP
    rcall    I2C_Stop
    ld    r16, x+        ; 7th byte - full TWI off or no
    andi    r16, 0b00000001
    cpi    r16, 0
    breq     nostoptwi
    rcall    I2C_Off
nostoptwi:
    rjmp    cmddone
xx4:
cmddone:
iodone:
    rcall    tx_packet_data
wrongpkt:
    jmp    readmultiplepackets

iodata_received:
eew:
    ld    r17, x+
    rcall    eepwrbyte
    sbiw    r24, 1
    brne    eew
    st    y+, r16        ; store last ack
    ldi    r24,1        ; answer to write many bytes - one byte pkt
    ldi    r25,0
    rjmp    iodone

eepwrbyte:
    rcall    i2c_write
    brcc    eep_ack
eep_nak:
    ldi    r16, 0xff
    rjmp    eep2
eep_ack:
    ldi    r16, 0
eep2:
;    st    y+, r16        ; store ack
    ret

getid_answer:
; get id cmd receive
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0x00
    st    y+, r16
    ldi    r16, 0xaa
    st    y+, r16
    ldi    r16, 0x55
    st    y+, r16
    ldi    r16, capabilitybyte0
    st    y+, r16
    ldi    r16, capabilitybyte1
    st    y+, r16
    ldi    r16, capabilitybyte2
    st    y+, r16
    ldi    r16, capabilitybyte3
    st    y+, r16
    ldi    r30, low(idstring*2)
    ldi    r31, high(idstring*2)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
;    ldi    r24, (idstringend-idstring)+8
    ldi    r24, (idstringend-idstring)*2+8
    ldi    r25,0
    jmp    cmddone

idstring:
;.db " * SDEL Ethernet EEPROM programmer v0.1 14-07-2011 * ",13,10,0,0,0,0,0
.db " * SDEL Ethernet EEPROM programmer v0.1 14-07-2011 *", 0
idstringend:



; must rewrite this using txp_part1, txp_part2 etc.

at17readandsend:
; packet length and read q'ty
    ld    r24, x+        ; 6th byte
    ld    r25, x+        ; 7th byte
;tx_packet:    ; r12:r13 - used (only in this procedure)
    movw    r02, r24    ; packet size
    rcall    waitforbuffer
; init transmitting
    ldi    r16, low(S0_TX_WR)
    ldi    r17, high(S0_TX_WR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    mov    r15, r16
    mov    r17, r16
    rcall    w5100read
    mov    r14, r16    ; r14:r15 save prevoius place

    andi    r17, high(S0_TX_LENGTH-1)
    andi    r16, low(S0_TX_LENGTH-1)
; calculate size to end of buffer
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
    sub    r12, r16
    sbc    r13, r17

    ori    r17, high(S0_TX_BASE)    ; add base address
    ori    r16, low(S0_TX_BASE)
    rcall    w5100outaddr    ; prepare writing into memory

    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
snd1:
    sec            ; set ACK
    rcall    i2c_read
;    st    y+, r17
;    ld    r16, y+
    mov    r16, r17
;ldi r16, 0x55
    rcall    w5100outdata

; this must be optimized!
    dec    r12
;    brcc    usa3    ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    snd3
; here r12=0
    cp    r12, r13    ; 0x0000 - special case
    breq    snd5
    dec    r13
    rjmp    snd3
snd5:
; end of memory - turn to start
    ldi    r16, low(S0_TX_BASE)
    ldi    r17, high(S0_TX_BASE)
    rcall    w5100outaddr
; reinit r12-r13
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
snd3:
    sbiw    r24, 1
    brne    snd1

;sendpkt2:

    rjmp    sendpkt
.endif    ; at17prog
; end DEPRECATED





; --- next section...
;.ifdef at45spiprog
.ifdef eeprom_prog
.equ    ctrlpacketsize = 8
.equ capabilitybyte0 = 0x11
.equ capabilitybyte1 = 0x22
.equ capabilitybyte2 = 0x33
;.equ capabilitybyte3 = 0x44
    ldi    r26, low(rxbuf)
    ldi    r27, high(rxbuf)
    ldi    r28, low(txbuf) ; moved here from (*) 21-03-13
    ldi    r29, high(txbuf)

    movw    r24, r08    ; rx length

    cpi    r24, low(ctrlpacketsize)
    brne    iodata_received2
    cpi    r25, high(ctrlpacketsize)
    brne    iodata_received2
    rjmp     cmd_received
iodata_received2:
    jmp    iodata_received

cmd_received:
;    ldi    r28, low(txbuf) (*)
;    ldi    r29, high(txbuf)
    ldi    r16, 0x33    ; prefill buf for debug
    st    y+, r16
    st    y+, r16
    st    y+, r16
    st    y+, r16
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ld    r16, x+
    cpi    r16, 0x55
    brne    wrongpkt2
    ld    r16, x+
    cpi    r16, 0xaa
    brne    wrongpkt2
    ld    r16, x+
    cpi    r16, 0x00
    brne    wrongpkt2
    ld    r16, x+
    cpi    r16, 0xff
    brne    wrongpkt2
    ld    r16, x+
    ld    r16, x+        ; 5th byte
    cpi    r16, 1
    brne    xx0
; read from at17 and send pkt
;    jmp    at17readandsend

	mov	r16, r01
	cpi	r16, 0
	breq	eep_read_twi
eep_read_spi:
	rcall    spireadandsend
;    rjmp    rxint_ret        changed 31-08-11 due to maybe this is bug
    jmp    readmultiplepackets
;	rjmp	eep_read_done

eep_read_twi:
	rcall    at17readandsend

eep_read_done:


;    rjmp    rxint_ret        changed 31-08-11 due to maybe this is bug
    jmp    readmultiplepackets

wrongpkt2:
    jmp    wrongpkt

xx0:
    ld    r16, x+        ; 6th byte
; select mode:
    cpi    r16, 0
    brne    xx1
    jmp    getid_answer

xx1:
    cpi    r16, 1
    brne    xx2
; set mode
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
    ld    r16, x+        ; 7th byte - here it's mode
; due to absence 'set I/O bit from T flag' instruction, here is big but understandable workaround.
; note, we can't just use one bulky OUT instruction due to it disturbs other 4 bits!
    sbrs    r16, 0
    cbi    progCTRLport, progCTRLbit0
    sbrc    r16, 0
    sbi    progCTRLport, progCTRLbit0
    sbrs    r16, 1
    cbi    progCTRLport, progCTRLbit1
    sbrc    r16, 1
    sbi    progCTRLport, progCTRLbit1
    sbrs    r16, 2
    cbi    progCTRLport, progCTRLbit2
    sbrc    r16, 2
    sbi    progCTRLport, progCTRLbit2
    sbrs    r16, 3
    cbi    progCTRLport, progCTRLbit3
    sbrc    r16, 3
    sbi    progCTRLport, progCTRLbit3
    rjmp    cmddone

xx2:
    cpi    r16, 2
    brne    xx3
; set mode for next data blocks writing:
	ldi	r16, 0	; 0 = twi
	mov	r01, r16

; set START for twi
    ldi    r24,1
    ldi    r25,0
;    st    y+, r16        ; prepare simple answer

;.ifdef reserved_at17prog
    rcall    I2C_Start
;   ld    r16, x+        ; 7th byte - addr to write to eep, + set R / W
;    mov    r17, r16
   ld    r17, x+        ; 7th byte - addr to write to eep, + set R / W

; not used ?...........
;    andi    r16, 0b00000001
;    mov    r01, r16    ; mode for next data flow: 0 - write, 1 - read

    rcall    eepwrbyte    ; write address
    st    y+, r16        ; store ack
;.else
;; here we operate SS pin for AT45 in manner it is start/stop condition for AT17,
;; to unify software programming flows.
;    cbi    progSPIport,  progSPISSbit ; enable /SS - 'start'
;    nop
;    nop
;    ld    r16, x+        ; 7th byte - cmd
;   out     SPDR, r16    ; write this to spi...
;dly02:
;    sbis    SPSR, SPIF
;    rjmp    dly02
;;    out     SPDR, r16    ; ... and write dummy byte to read answer: - moved to software layer
;;dly03:
;;    sbis    SPSR, SPIF
;;    rjmp    dly03
;    in    r16, SPDR
;;ldi r16,0x77
;    st    y+, r16        ; (store ack for AT17 or) spi readed byte for AT45
;.endif ; reserved_at17prog
    rjmp    cmddone

xx3:
    cpi    r16, 3
    brne    xx4
;sbi ctlport, 5
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
;.ifdef reserved_at17prog
; set STOP
    rcall    I2C_Stop
    ld    r16, x+        ; 7th byte - full TWI off or no
    andi    r16, 0b00000001
    cpi    r16, 0
    breq     nostoptwi
    rcall    I2C_Off
nostoptwi:
;.else
;; here we operate SS pin for AT45 in manner it is start/stop condition for AT17,
;; to unify software programming flows.
;    sbi    progSPIport,  progSPISSbit ; disable /SS - 'stop'
;    nop
;    nop
;.endif ; reserved_at17prog
    rjmp    cmddone

xx4:
    cpi    r16, 4
    brne    xx5

; set mode for next data blocks writing:
	ldi	r16, 1	; 1 = spi
	mov	r01, r16

    ldi    r24,1
    ldi    r25,0
;    st    y+, r16        ; prepare simple answer

;.ifdef reserved_at17prog
;    rcall    I2C_Start
;    ld    r16, x+        ; 7th byte - addr to write to eep, + set R / W
;    mov    r17, r16
;    andi    r16, 0b00000001
;    mov    r01, r16    ; mode for next data flow: 0 - write, 1 - read
;    rcall    eepwrbyte    ; write address
;    st    y+, r16        ; store ack
;.else
; here we operate SS pin for AT45 in manner it is start/stop condition for AT17,
; to unify software programming flows.
    cbi    progSPIport,  progSPISSbit ; enable /SS - 'start'
    nop
    nop
    ld    r16, x+        ; 7th byte - cmd
    out     SPDR, r16    ; write this to spi...
dly03:
    sbis    SPSR, SPIF
    rjmp    dly03
;    out     SPDR, r16    ; ... and write dummy byte to read answer: - moved to software layer
;dly03:
;    sbis    SPSR, SPIF
;    rjmp    dly03
    in    r16, SPDR
;ldi r16,0x77
    st    y+, r16        ; store  spi readed byte 
;.endif ; reserved_at17prog
    rjmp    cmddone

xx5:
    cpi    r16, 5
    brne    xx6
;sbi ctlport, 5
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
;.ifdef reserved_at17prog
;; set STOP
;    rcall    I2C_Stop
;    ld    r16, x+        ; 7th byte - full TWI off or no
;    andi    r16, 0b00000001
;    cpi    r16, 0
;    breq     nostoptwi
;    rcall    I2C_Off
;nostoptwi:
;.else
; here we operate SS pin for AT45 in manner it is start/stop condition for AT17,
; to unify software programming flows.
    sbi    progSPIport,  progSPISSbit ; disable /SS - 'stop'
    nop
    nop
;.endif ; reserved_at17prog
    rjmp    cmddone


xx6:

cmddone:
iodone:
    rcall    tx_packet_data
wrongpkt:
    jmp    readmultiplepackets

iodata_received:
;sdf: rjmp sdf

	mov	r16, r01
	cpi	r16, 0
	breq	eep_write_twi

eep_write_spi:
	ld	r16, x+
	out     SPDR, r16
dly01:
	sbis    SPSR, SPIF
	rjmp    dly01
	in	r16, SPDR
	sbiw    r24, 1
	brne    eep_write_spi
	rjmp	eep_write_done

eep_write_twi:
	ld	r17, x+
	rcall	eepwrbyte
	sbiw    r24, 1
	brne    eep_write_twi


eep_write_done:
    st    y+, r16        ; store last ack (for at17)
                ; -or-
                ; store ONE LAST!!! readed SPI data (for at45)
    ldi    r24,1        ; answer to write many bytes - one byte pkt
    ldi    r25,0
    rjmp    iodone


;.ifdef reserved_at17prog
eepwrbyte:
    rcall    i2c_write
    brcc    eep_ack
eep_nak:
    ldi    r16, 0xff
    rjmp    eep2
eep_ack:
    ldi    r16, 0
eep2:
;    st    y+, r16        ; store ack
    ret
;.endif ; reserved_at17prog



getid_answer:
; get id cmd receive
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0x00
    st    y+, r16
    ldi    r16, 0xaa
    st    y+, r16
    ldi    r16, 0x55
    st    y+, r16
    ldi    r16, capabilitybyte0
    st    y+, r16
    ldi    r16, capabilitybyte1
    st    y+, r16
    ldi    r16, capabilitybyte2
    st    y+, r16
;    ldi    r16, capabilitybyte3

;rcall prog_board_detect
	mov	r16, r00
    st    y+, r16
    ldi    r30, low(idstring*2)
    ldi    r31, high(idstring*2)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
;    ldi    r24, (idstringend-idstring)+8
    ldi    r24, (idstringend-idstring)*2+8
    ldi    r25,0
    jmp    cmddone

idstring:
; GTK text markup dont love '&'
;.db " * SDEL Ethernet TWI/I2C & SPI programmer v0.1 12-06-2013 *", 0
.db " * SDEL Ethernet TWI/I2C &amp; SPI programmer v0.1 12-06-2013 *", 0
idstringend:


; must rewrite this using txp_part1, txp_part2 etc.

at17readandsend:
; packet length and read q'ty
    ld    r24, x+        ; 6th byte
    ld    r25, x+        ; 7th byte
;tx_packet:    ; r12:r13 - used (only in this procedure)
    movw    r02, r24    ; packet size
    rcall    waitforbuffer
; init transmitting
    ldi    r16, low(S0_TX_WR)
    ldi    r17, high(S0_TX_WR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    mov    r15, r16
    mov    r17, r16
    rcall    w5100read
    mov    r14, r16    ; r14:r15 save prevoius place

    andi    r17, high(S0_TX_LENGTH-1)
    andi    r16, low(S0_TX_LENGTH-1)
; calculate size to end of buffer
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
    sub    r12, r16
    sbc    r13, r17

    ori    r17, high(S0_TX_BASE)    ; add base address
    ori    r16, low(S0_TX_BASE)
    rcall    w5100outaddr    ; prepare writing into memory

    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
snd1:
;.ifdef reserved_at17prog
    sec            ; set ACK
    rcall    i2c_read
;    st    y+, r17
;    ld    r16, y+
    mov    r16, r17
;.else
;    out     SPDR, r16 ; any byte out
;dly00:
;    sbis    SPSR, SPIF
;    rjmp    dly00
;ldi r16, 0x55
;    in     r16, SPDR
;.endif

    rcall    w5100outdata
; this must be optimized!
    dec    r12
;    brcc    usa3    ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    snd3
; here r12=0
    cp    r12, r13    ; 0x0000 - special case
    breq    snd5
    dec    r13
    rjmp    snd3
snd5:
; end of memory - turn to start
    ldi    r16, low(S0_TX_BASE)
    ldi    r17, high(S0_TX_BASE)
    rcall    w5100outaddr
; reinit r12-r13
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
snd3:
    sbiw    r24, 1
    brne    snd1
;sendpkt2:
    rjmp    sendpkt



; must rewrite this using txp_part1, txp_part2 etc.

spireadandsend:
; packet length and read q'ty
    ld    r24, x+        ; 6th byte
    ld    r25, x+        ; 7th byte
;tx_packet:    ; r12:r13 - used (only in this procedure)
    movw    r02, r24    ; packet size
    rcall    waitforbuffer
; init transmitting
    ldi    r16, low(S0_TX_WR)
    ldi    r17, high(S0_TX_WR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    mov    r15, r16
    mov    r17, r16
    rcall    w5100read
    mov    r14, r16    ; r14:r15 save prevoius place

    andi    r17, high(S0_TX_LENGTH-1)
    andi    r16, low(S0_TX_LENGTH-1)
; calculate size to end of buffer
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
    sub    r12, r16
    sbc    r13, r17

    ori    r17, high(S0_TX_BASE)    ; add base address
    ori    r16, low(S0_TX_BASE)
    rcall    w5100outaddr    ; prepare writing into memory

    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
spisnd1:
;.ifdef reserved_at17prog
;    sec            ; set ACK
;    rcall    i2c_read
;;    st    y+, r17
;;    ld    r16, y+
;    mov    r16, r17
;.else
    out     SPDR, r16 ; any byte out
dly00:
    sbis    SPSR, SPIF
    rjmp    dly00
;ldi r16, 0x55
    in     r16, SPDR
;.endif

    rcall    w5100outdata
; this must be optimized!
    dec    r12
;    brcc    usa3    ; inc/dec DO NOT AFFECT CARRY FLAG!
    brne    spisnd3
; here r12=0
    cp    r12, r13    ; 0x0000 - special case
    breq    spisnd5
    dec    r13
    rjmp    spisnd3
spisnd5:
; end of memory - turn to start
    ldi    r16, low(S0_TX_BASE)
    ldi    r17, high(S0_TX_BASE)
    rcall    w5100outaddr
; reinit r12-r13
    ldi    r18, low(S0_TX_LENGTH)
    mov    r12, r18
    ldi    r18, high(S0_TX_LENGTH)
    mov    r13, r18
spisnd3:
    sbiw    r24, 1
    brne    spisnd1
;sendpkt2:
    rjmp    sendpkt



;.endif    ; at45spiprog
.endif    ; eeprom_prog






.ifdef adSPIctl
.equ capabilitybyte0 = 0x11
.equ capabilitybyte1 = 0x22
.equ capabilitybyte2 = 0x33
.equ capabilitybyte3 = 0x44
    ldi    r26, low(rxbuf)
    ldi    r27, high(rxbuf)
; remove? used only for know rcv size ?
    movw    r24, r08    ; rx length
;    cpi    r24, low(ctrlpacketsize)
;    brne    iodata_received2
;    cpi    r25, high(ctrlpacketsize)
;    brne    iodata_received2
;    rjmp     cmd_received
;iodata_received2:
;    jmp    iodata_received

;cmd_received:
;    ldi    r28, low(txbuf)
;    ldi    r29, high(txbuf)
;    ldi    r16, 0x33    ; prefill buf for debug
;    st    y+, r16
;    st    y+, r16
;    st    y+, r16
;    st    y+, r16
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ld    r16, x+
    cpi    r16, 0x55
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xaa
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0x00
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xff
    brne    wrongpkt
    ld    r16, x+
    ld    r16, x+        ; 5th byte
;    cpi    r16, 1
;    brne    xx0
;;;; read from at17 and send pkt
;;;;    jmp    at17readandsend
;    rcall    readandsend
;;;;    rjmp    rxint_ret        changed 31-08-11 due to maybe this is bug
;    jmp    freadmultiplepackets

xx0:
    ld    r16, x+        ; 6th byte
; select mode:
    cpi    r16, 0
    brne    xx1
    jmp    getid_answer
xx1:
    cpi    r16, 1
    brne    xx2
; set mode
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
    ld    r16, x+        ; 7th byte - here it's mode
;    out    ctlport, r16
;swap r16
;andi r16, 0b
; place here any control for output port...

;out    eepromCTRLport, r16
    rjmp    cmddone
xx2:
    cpi    r16, 2
    brne    xx3

    ldi    r24,2        ; answer - 2-byte pkt
    ldi    r25,0
; analyze 'lock's state before change freq.
    ldi    r16, 0
    sbic    adSPIctlpin, adSPIctlaLOCKbit
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0
.ifndef ad9910
    sbic    adSPIctlpin, adSPIctlbLOCKbit
    ldi    r16, 0xff
.endif
    st    y+, r16

    ld    r16, x+        ; 7th byte - channel
; add code to change channel# 0/1 of adSPIctl here:
; ......
; read freq.
    push    r09
    push    r08
    ld    r16, x+        ; 8th byte - freq
    mov    r08, r16
    ld    r16, x+        ; 9th byte - freq
    mov    r09, r16
;set frequency (smart, only freq value needed instead of all registers)
; but probably slow in continuous use...
    rcall     set_freq_adSPIctl
    pop    r08
    pop    r09
    rjmp    cmddone

xx4:
cmddone:
iodone:
    rcall    tx_packet_data
wrongpkt:
    jmp    readmultiplepackets

xx3:
    cpi    r16, 3
    brne    xx4
    ldi    r24,2        ; answer - 2-byte pkt
    ldi    r25,0
; analyze 'lock's state before change freq.
    ldi    r16, 0
    sbic    adSPIctlpin, adSPIctlaLOCKbit
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0
.ifndef ad9910
    sbic    adSPIctlpin, adSPIctlbLOCKbit
    ldi    r16, 0xff
.endif
    st    y+, r16

    ld    r16, x+        ; 7th byte - mode
; add code to change mode adSPIctl/4360 here:
; ......
; mode adSPIctl: 4 bytes per register
; adf4360 need 3 bytes but work with 4 byte words also, because extra (first)
;word just lost in it.
; but now, we need also ad9910, it uses different length control words,
; so 05-01-2013 added q'ty byte before bytes sequence.
next_adSPIctl_word:

;    ld    r16, x+        ; 8th byte - first byte of register content...
    ld    r17, x+        ; 8th byte - q'ty of bytes in first word.
                ; but it not include 'channel' byte with 'last' flag bit.
next_adSPIctl_byte:
    ld    r16, x+        ; 9th byte - first byte of word.
    out     SPDR, r16
dly00:
    sbis    SPSR, SPIF
    rjmp    dly00

    dec    r17
    brne    next_adSPIctl_byte

;    ld    r16, x+
;    out     SPDR, r16
;dly01:
;    sbis    SPSR, SPIF
;    rjmp    dly01
;
;    ld    r16, x+
;    out     SPDR, r16
;dly02:
;    sbis    SPSR, SPIF
;    rjmp    dly02
;
;    ld    r16, x+
;    out     SPDR, r16
;dly03:
;    sbis    SPSR, SPIF
;    rjmp    dly03

    nop
    nop
    nop
    nop

    ld    r16, x+        ; this byte - channel and MSB=1 - last byte.
    sbrc    r16, 0        ; instead of CPI, this not need to value be ANDed.
    rjmp    ch_1
ch_0:
    sbi    adSPIctlport, adSPIctlaLEbit
    nop
    nop
    nop
    nop
    cbi    adSPIctlport, adSPIctlaLEbit
    rjmp    ch_done
ch_1:
.ifndef ad9910
    sbi    adSPIctlport, adSPIctlbLEbit
    nop
    nop
    nop
    nop
    cbi    adSPIctlport, adSPIctlbLEbit
.endif
ch_done:
    sbrs    r16, 7        ; MSB
    rjmp    next_adSPIctl_word
    rjmp    cmddone

    rjmp    cmddone


getid_answer:
; get id cmd receive
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0x00
    st    y+, r16
    ldi    r16, 0xaa
    st    y+, r16
    ldi    r16, 0x55
    st    y+, r16
    ldi    r16, capabilitybyte0
    st    y+, r16
    ldi    r16, capabilitybyte1
    st    y+, r16
    ldi    r16, capabilitybyte2
    st    y+, r16
    ldi    r16, capabilitybyte3
    st    y+, r16
    ldi    r30, low(idstring*2)
    ldi    r31, high(idstring*2)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
;    ldi    r24, (idstringend-idstring)+8
    ldi    r24, (idstringend-idstring)*2+8
    ldi    r25,0
    jmp    cmddone

idstring:
.db " * SDEL Ethernet adf4350/4360/9910 module (two channels) v0.1 06-05-2012 * ",0
idstringend:

.endif ; adSPIctl





.ifdef ad7680
.equ capabilitybyte0 = 0x11
.equ capabilitybyte1 = 0x22
.equ capabilitybyte2 = 0x33
.equ capabilitybyte3 = 0x44
    ldi    r26, low(rxbuf)
    ldi    r27, high(rxbuf)
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    ld    r16, x+
    cpi    r16, 0x55
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xaa
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0x00
    brne    wrongpkt
    ld    r16, x+
    cpi    r16, 0xff
    brne    wrongpkt
    ld    r16, x+
    ld    r16, x+        ; 5th byte
    ld    r16, x+        ; 6th byte
; select mode:
    cpi    r16, 0
    brne    xx1
    jmp    getid_answer
xx1:
    cpi    r16, 1
    brne    xx2
; set mode
    ldi    r24,1
    ldi    r25,0
    st    y+, r16        ; prepare simple answer
    ld    r16, x+        ; 7th byte - here it's mode
; place here any control for output port...
;    out    ctlport, r16
; ...........
    rjmp    cmddone
xx2:
;    cpi    r16, 2
;    brne    xx3

;    ldi    r24,4        ; answer - 4-byte pkt
    ldi    r24,8        ; just test two ad7680s
    ldi    r25,0

    ld    r16, x+        ; 7th byte - channel
; add code to change channel# 0/1 of adSPIctl here:
; ......

; read ad7680
    cbi    ad7680port, ad7680aCSbit    ; CS=0 when active
    sbi    ad7680port, ad7680aLEDbit
;    nop
    rcall rrrrr
    sbi    ad7680port, ad7680aCSbit    ; CS=1 when idle
    cbi    ad7680port, ad7680aLEDbit

; ch. 1
    cbi    ad7680port, ad7680bCSbit    ; CS=0 when active
    sbi    ad7680port, ad7680bLEDbit
    rcall rrrrr
    sbi    ad7680port, ad7680bCSbit    ; CS=1 when idle
    cbi    ad7680port, ad7680bLEDbit


    rjmp    cmddone

xx4:
cmddone:
iodone:
    rcall    tx_packet_data
wrongpkt:
    jmp    readmultiplepackets


rrrrr:
    ldi    r16, 0x00
    st    y+, r16
    out     SPDR, r16    ; dummy write
wait01:
    sbis    SPSR, SPIF
    rjmp    wait01
    in    r16, SPDR
    st    y+, r16
    out     SPDR, r16    ; dummy write
wait02:
    sbis    SPSR, SPIF
    rjmp    wait02
    in    r16, SPDR
    st    y+, r16
    out     SPDR, r16    ; dummy write
wait03:
    sbis    SPSR, SPIF
    rjmp    wait03
    in    r16, SPDR
    st    y+, r16
    ret


getid_answer:
; get id cmd receive
    ldi    r16, 0xff
    st    y+, r16
    ldi    r16, 0x00
    st    y+, r16
    ldi    r16, 0xaa
    st    y+, r16
    ldi    r16, 0x55
    st    y+, r16
    ldi    r16, capabilitybyte0
    st    y+, r16
    ldi    r16, capabilitybyte1
    st    y+, r16
    ldi    r16, capabilitybyte2
    st    y+, r16
    ldi    r16, capabilitybyte3
    st    y+, r16
    ldi    r30, low(idstring*2)
    ldi    r31, high(idstring*2)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
;    ldi    r24, (idstringend-idstring)+8
    ldi    r24, (idstringend-idstring)*2+8
    ldi    r25,0
    jmp    cmddone

idstring:
;.db " * SDEL Ethernet AD7680 ADC module (two channels) v0.1 08-05-2012 * ",13,10,0,0,0,0,0,0
.db " * SDEL Ethernet AD7680 ADC module (two channels) v0.1 08-05-2012 *", 0
idstringend:

.endif ; ad7680





;.ifdef aura
; we don't need to receive anything,
; but keep possibility to get ID and capabilites...
.ifdef aura2
;.equ capabilitybyte0 = 0x11
;.equ capabilitybyte1 = 0x22
;.equ capabilitybyte2 = 0x33
;.equ capabilitybyte3 = 0x44
;    ldi    r26, low(rxbuf)
;    ldi    r27, high(rxbuf)

; only prepare http answer
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)

;    ld    r16, x+
;    cpi    r16, 0x55
;    brne    wrongpkt
;    ld    r16, x+
;    cpi    r16, 0xaa
;    brne    wrongpkt
;    ld    r16, x+
;    cpi    r16, 0x00
;    brne    wrongpkt
;    ld    r16, x+
;    cpi    r16, 0xff
;    brne    wrongpkt
;    ld    r16, x+
;    ld    r16, x+        ; 5th byte
;    ld    r16, x+        ; 6th byte
;; select mode:
;    cpi    r16, 0
;;    brne    xx1
;    jmp    getid_answer
;xx1:
;cmddone:
;iodone:
;    rcall    tx_packet_data
;wrongpkt:
;    jmp    readmultiplepackets



getid_answer:
; get id cmd receive
    ldi    r30, low(httpreplystring*2)
    ldi    r31, high(httpreplystring*2)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
.equ     csvbytes = 256    ; max 256?
.equ    csvbytesize = 4    ; '255,' or so
;answer size
; max allowed - txpktmaxlen! (approx 1024+256 bytes for 'aura')

;    ldi    r24, low ( ( (httpreplystringend-httpreplystring) * 2) + (csvbytes * csvbytesize) + 2)
;    ldi    r25, high ( ( (httpreplystringend-httpreplystring) * 2) + (csvbytes * csvbytesize) + 2)

    ldi    r24, low ( (httpreplystringend-httpreplystring) * 2)
    ldi    r25, high ( (httpreplystringend-httpreplystring) * 2)

;ldi r16, 254
ldi r16, low(csvbytes)
mov r00, r16

au2:
;ldi r16, 0x55

ldi r16, '0'
st y+, r16
st y+, r16

in r16, aura0pin
andi r16, 0x0f
subi r16, 256-'0'
st y+, r16

ldi r16, ','
st y+, r16


; delay
; hope r17 can be used??
;    ldi    r17, 1 ; agjust
;au4:
    ldi    r16, 0
au3:
    nop
    nop
    dec    r16
    brne    au3
;    dec    r17
;    brne    au4


dec r00
brne au2

ldi r16, 13
st y+, r16
ldi r16, 10
st y+, r16

    rcall    tx_packet_data

; without disconnect, web server never work!
; browser never display anything, and waiting...
rcall    tcpdisconnect

;    jmp    cmddone
    jmp    readmultiplepackets


; for auto refresh?
;plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html
;\r\nPragma: no-cache\r\nRefresh: 300\r\n\r\n"));

httpreplystring:
.db "HTTP/1.0 200 OK",13,10,"Content-Type: text/html",13,10,13,10
.db "<html><body><h1>It works! </h1>",10
.db "<p>This is the default web page for this server. </p>",10
.db "<p>The web server software is running but no content has been added, yet.</p>",10
.db "</body></html> ",10

httpreplystringend:
.db 0,0
.db 0,0,0,0
.endif ; aura2



.ifdef aura
    ldi    r30, low(httpreplystring*2)
    ldi    r31, high(httpreplystring*2)
    ldi    r24, low((httpreplystringend-httpreplystring) * 2)
    ldi    r25, high((httpreplystringend-httpreplystring) * 2)
    rjmp    httpreplysend

httpreplysend:
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    rcall    txtmemcpy
;cm1:
;    lpm    r16, z+
;    cpi    r16, 0
;    breq    cm2
;    st    y+, r16
;    rjmp    cm1
;cm2:
.equ     csvbytes = 256    ; max 256?
.equ    csvbytesize = 4    ; '255,' or so
;answer size
; max allowed - txpktmaxlen! (approx 1024+256 bytes for 'aura')
    ldi    r24, low ( ( (httpreplystringend-httpreplystring) * 2) + (csvbytes * csvbytesize) + 2)
    ldi    r25, high ( ( (httpreplystringend-httpreplystring) * 2) + (csvbytes * csvbytesize) + 2)
;ldi r16, 254
    ldi    r16, low(csvbytes)
    mov    r00, r16

au2:
;ldi r16, 0x55
;    ldi    r16, '0'
;    st    y+, r16
;    st    y+, r16

;;; ports/pins list
;	cbi	portd, 0
;	cbi	portd, 1
;	cbi	portd, 4	; replace for new boards
;	cbi	portd, 5
;	cbi	portd, 6
;	cbi	portd, 7
;	cbi	portc, 0
;	cbi	portc, 1
;	ldi	r16, 0
;	out	portb, r16



;    in    r17, aura0pin
;    andi    r17, 0x0f
;    in    r16, aura1pin
;    andi    r16, 0xf0
;    add    r17, r16

; first need to input after prev. delay from some 8 pins
	in	r17, pinb
; then output new state into other 8 pins:
; for output we try to take r00 counter, byt maybe it should be random.
	sbi	ddrd, 0
	sbi	ddrd, 1
	sbi	ddrd, 4	; replace for new boards
	sbi	ddrd, 5
	sbi	ddrd, 6
	sbi	ddrd, 7
	sbi	ddrc, 0
	sbi	ddrc, 1
; output all zeros
	cbi	portd, 0
	cbi	portd, 1
	cbi	portd, 4	; replace for new boards
	cbi	portd, 5
	cbi	portd, 6
	cbi	portd, 7
	cbi	portc, 0
	cbi	portc, 1
; then set some bits
	mov	r16, r00


	sbrc	r16, 0
	sbi	portd, 0
	lsr	r16
	sbrc	r16, 0
	sbi	portd, 1
	lsr	r16
	sbrc	r16, 0
	sbi	portd, 4
	lsr	r16
	sbrc	r16, 0
	sbi	portd, 5
	lsr	r16
	sbrc	r16, 0
	sbi	portd, 6
	lsr	r16
	sbrc	r16, 0
	sbi	portd, 7
	lsr	r16
	sbrc	r16, 0
	sbi	portc, 0
	lsr	r16
	sbrc	r16, 0
	sbi	portc, 1
	lsr	r16


www33:
    ldi    r16, '0'
www2:
    subi    r17, 100
    brlo    www1
    inc    r16
    rjmp    www2
www1:
    subi    r17, -100    ; add 100
    st    y+, r16

www11:
    ldi    r16, '0'
www4:
    subi    r17, 10
    brlo    www3
    inc    r16
    rjmp    www4
www3:
    subi    r17, -10-'0'    ; addi 10 + '0' butt addi not exist
    st    y+, r16
www12:
    st    y+, r17

    ldi    r16, ','
    st    y+, r16
; delay
; hope r17 can be used??
;    ldi    r17, 1 ; agjust
;au4:
    ldi    r16, 0
au3:
;    nop
;    nop
    dec    r16
    brne    au3
;    dec    r17
;    brne    au4

    dec    r00
;    brne    au2
	breq	au4
	jmp	au2
au4:

    ldi    r16, 13
    st    y+, r16
    ldi    r16, 10
    st    y+, r16

    rcall    tx_packet_data

;      info is OLD, deprecated:
; without disconnect, web server never work!
; browser never display anything, and waiting...
; but not sure if we can just disconnect here. So if our server
; become insane, maybe something should be modified here,
; like adding timer1 enabling, or jmp to another point.
    rcall    tcpdisconnect

;    jmp    cmddone
    jmp    readmultiplepackets

httpreplystring:
;.db "HTTP/1.0 200 OK",13,10,"Content-Type: application/csv",13,10
.db "HTTP/1.0 200 OK",13,10,"Content-Type: text/plain ",13,10
; i need to specify file name, which can be used for 'save as' action
; when you suddenly wish to open this with a browser, instead of script.
; but it not work :-( so commented out.
;.db "Location: /file1.csv",13,10
.db 13,10

httpreplystringend:
.db 0,0

.endif ; aura



; 13.08.2013: NEW, http 1.1 with keep-alive connection and one socket,
; connection closes when browser closes or 10 mins timeout (browser-related).
; Currently, no intentional disconnect.
.ifdef webserver
    ldi    r26, low(rxbuf)
    ldi    r27, high(rxbuf)
; test for 'GET / HTTP/1.1' (only first six bytes), else error return.
    ld    r16, x+
    cpi    r16, 'G'
    brne    err404
    ld    r16, x+
    cpi    r16, 'E'
    brne    err404
    ld    r16, x+
    cpi    r16, 'T'
    brne    err404
    ld    r16, x+
    cpi    r16, ' '
    brne    err404
    ld    r16, x+
    cpi    r16, '/'
    brne    err404
    ld    r16, x+
	cpi	r16, ' '
	breq	http200ok
	cpi	r16, '1' ; 1.jpg
	breq	httpimg1
	cpi	r16, '2' ; 2.jpg
	breq	httpimg2
	cpi	r16, '3' ; 2.jpg
	breq	httpimg3
	cpi	r16, 'f' ; favicon.ico
	breq	httpfavicon
	rjmp	err404

err404:
	jmp err_404

httpfavicon:
    ldi    r30, low(favicon*2)
    ldi    r31, high(favicon*2)
    ldi    r24, low((faviconend-favicon)*2)
    ldi    r25, high((faviconend-favicon)*2)
    rjmp    httpreplysend

httpimg2:
    ldi    r30, low(img2*2)
    ldi    r31, high(img2*2)
    ldi    r24, low((img2end-img2)*2)
    ldi    r25, high((img2end-img2)*2)
    rjmp    httpreplysend

httpimg3:
    ldi    r30, low(img3*2)
    ldi    r31, high(img3*2)
    ldi    r24, low((img3end-img3)*2)
    ldi    r25, high((img3end-img3)*2)
    rjmp    httpreplysend

httpimg1:
    ldi    r30, low(img1*2)
    ldi    r31, high(img1*2)
    ldi    r24, low((img1end-img1)*2)
    ldi    r25, high((img1end-img1)*2)
    rjmp    httpreplysend

http200ok:
    ldi    r30, low(httpreplystring*2)
    ldi    r31, high(httpreplystring*2)
    ldi    r24, low((httpreplystringend-httpreplystring)*2)
    ldi    r25, high((httpreplystringend-httpreplystring)*2)
    rjmp    httpreplysend

httpreplysend:
	ldi	r28, low(txbuf)
	ldi	r29, high(txbuf)
;    rcall    txtmemcpy
	rcall	datamemcpy
	rcall	tx_packet_data

;    rcall    tcpdisconnect ; - test!

    jmp    readmultiplepackets


datamemcpy:
	push	r25
	push	r24
cpcp:
	lpm	r16, z+
	st	y+, r16
	sbiw	r24, 1
	brne	cpcp
	pop	r24
	pop	r25
	ret

err_404:
    ldi    r30, low(err404string*2)
    ldi    r31, high(err404string*2)
    ldi    r24, low((err404stringend-err404string)*2)
    ldi    r25, high((err404stringend-err404string)*2)

    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
    rcall    txtmemcpy

    rcall    tx_packet_data

;    rcall    tcpdisconnect ; - test!

    jmp    readmultiplepackets


; for auto refresh?
;plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html
;\r\nPragma: no-cache\r\nRefresh: 300\r\n\r\n"));

httpreplystring: ; WORK!
.db "HTTP/1.1 200 OK ",13,10
;.db "Date: Fri, 09 Aug 2013 10:31:11 GMT ",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
;.db "Server: Apache/2.2.22 (Ubuntu)",13,10
;.db "Last-Modified: Fri, 09 Aug 2013 09:06:43 GMT",13,10
;.db "ETag: ",34,"c25cb-b1-4e38017e44ec0",34, 13,10
.db "Accept-Ranges: bytes",13,10
;.db "Content-Length: 177 ",13,10		; <-- without this - NOT WORK AT ALL
.db "Content-Length: 0242",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Content-Length: 242 ",13,10		; <-- without this - NOT WORK AT ALL
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10 ; no any difference timeout 100 or 5...
.db "Connection: Keep-Alive",13,10
.db "Content-Type: text/html ",13,10
.db 13,10
.db "<html><body><h1>It works!</h1> ",10
.db "<p>This is the default web page for this server.</p> ",10
.db "<p>The web server software is running but no content has been added, yet.</p>",10
.db "<p>1<img src=",34,"1.gif",34,">2<img src=",34,"2.gif",34,">3<img src=",34,"3.gif",34,"> </p>"
.db "</body></html> ",10
httpreplystringend:

img1:
.db "HTTP/1.1 200 OK ",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
.db "Accept-Ranges: bytes",13,10
.db "Content-Length: 0142",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10
.db "Connection: Keep-Alive",13,10
.db "Content-Type: image/gif ",13,10
.db 13,10
.db 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x10, 0x00, 0x10, 0x00, 0xe3, 0x07, 0x00, 0x00, 0x00, 0x00,
.db 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
.db 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xdb, 0xdb, 0xb6, 0xb6, 0xb6, 0x92, 0x92, 0x92, 0x6d, 0x6d,
.db 0x6d, 0x49, 0x49, 0x49, 0x24, 0x24, 0x24, 0xdb, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x21, 0xfe, 0x11,
.db 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d,
.db 0x50, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x04, 0x2d, 0x10, 0xc8,
.db 0x20, 0x6b, 0xa5, 0x36, 0x68, 0x3b, 0x77, 0xd7, 0xd8, 0xb7, 0x81, 0xa4, 0x08, 0x02, 0x64, 0x9a,
.db 0x5e, 0xea, 0x9a, 0xb5, 0x1e, 0x07, 0x73, 0xac, 0x4a, 0xa3, 0x70, 0x68, 0xb6, 0x75, 0x3e, 0xda,
.db 0xb8, 0x95, 0xcb, 0x54, 0xa3, 0x9d, 0x32, 0x37, 0x54, 0x25, 0x02, 0x00, 0x3b, 0
img1end:

img2:
.db "HTTP/1.1 200 OK ",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
.db "Accept-Ranges: bytes",13,10
.db "Content-Length: 0112",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10
.db "Connection: Keep-Alive",13,10
.db "Content-Type: image/gif ",13,10
.db 13,10
.db 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00,
.db 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
.db 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xdb, 0xdb, 0xb6, 0xb6, 0xb6, 0x92, 0x92, 0x92, 0x6d, 0x6d,
.db 0x6d, 0x49, 0x49, 0x49, 0x24, 0x24, 0x24, 0xdb, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x2c, 0x00, 0x00,
.db 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x04, 0x25, 0x10, 0xc8, 0x49, 0xab, 0xbd, 0x38, 0x03,
.db 0xa1, 0xa9, 0xf8, 0xdd, 0x06, 0x76, 0x1f, 0x37, 0x99, 0x55, 0xe9, 0x8d, 0x27, 0x2b, 0xaa, 0x12,
.db 0xbc, 0xaa, 0x72, 0x5a, 0xd6, 0xd6, 0x8d, 0x66, 0x38, 0x1f, 0xfe, 0xc0, 0x49, 0x04, 0x00, 0x3b,
img2end:

img3:
.db "HTTP/1.1 200 OK ",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
.db "Accept-Ranges: bytes",13,10
.db "Content-Length: 0110",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10
.db "Connection: Keep-Alive",13,10
.db "Content-Type: image/gif ",13,10
.db 13,10
.db 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00,
.db 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
.db 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xdb, 0xdb, 0xb6, 0xb6, 0xb6, 0x92, 0x92, 0x92, 0x6d, 0x6d,
.db 0x6d, 0x49, 0x49, 0x49, 0x24, 0x24, 0x24, 0xdb, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x2c, 0x00, 0x00,
.db 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x04, 0x22, 0x10, 0xc8, 0x09, 0x08, 0xa1, 0x98, 0x5a,
.db 0x9b, 0xf3, 0xbe, 0xdd, 0xf4, 0x71, 0x61, 0x35, 0x96, 0xe6, 0x87, 0xa6, 0x20, 0xaa, 0xae, 0x2f,
.db 0xdc, 0xca, 0x6b, 0xdd, 0x91, 0x32, 0x5e, 0xc6, 0xee, 0x3c, 0x45, 0x00, 0x3b, 0,
img3end:


favicon:
.db "HTTP/1.1 200 OK ",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
.db "Accept-Ranges: bytes",13,10
.db "Content-Length: 0326",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10
.db "Connection: Keep-Alive",13,10
.db "Content-Type: image/gif ",13,10
.db 13,10
.db 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x20, 0x00, 0x20, 0x00, 0xe3, 0x08, 0x00, 0x00, 0x00, 0x00,
.db 0xa8, 0x00, 0x00, 0xfc, 0x54, 0x54, 0x00, 0xa8, 0x00, 0xa8, 0xa8, 0x00, 0x54, 0xfc, 0x54, 0xfc,
.db 0xfc, 0x54, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
.db 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x21, 0xfe, 0x11,
.db 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d,
.db 0x50, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x0a, 0x00, 0x08, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x20,
.db 0x00, 0x20, 0x00, 0x00, 0x04, 0xdd, 0x10, 0xc9, 0x49, 0xab, 0xbd, 0x38, 0xeb, 0xcd, 0xbb, 0xff,
.db 0x60, 0x28, 0x52, 0x00, 0x30, 0x66, 0xe5, 0x61, 0x94, 0x67, 0x05, 0x1c, 0xaa, 0xa1, 0x9a, 0xad,
.db 0xf4, 0x1a, 0x04, 0x81, 0xd3, 0x24, 0xdb, 0xdd, 0x84, 0xd4, 0x8e, 0x74, 0x28, 0x14, 0x78, 0x1a,
.db 0xa0, 0x30, 0x38, 0x79, 0x15, 0x8f, 0x3f, 0x55, 0x50, 0x69, 0x83, 0x15, 0x06, 0x03, 0xa4, 0xa5,
.db 0x04, 0x30, 0x78, 0xbf, 0x5f, 0xae, 0x15, 0xab, 0xed, 0x7d, 0x05, 0x06, 0xb4, 0x3a, 0x2d, 0x10,
.db 0x8c, 0xb3, 0x28, 0xaf, 0xba, 0xcd, 0x9e, 0xb7, 0x8b, 0xe4, 0x78, 0x9a, 0x5d, 0x67, 0x07, 0x04,
.db 0x01, 0x01, 0x46, 0x79, 0x17, 0x5d, 0x75, 0x6d, 0x88, 0x89, 0x88, 0x82, 0x84, 0x5b, 0x72, 0x73,
.db 0x87, 0x8b, 0x80, 0x8c, 0x70, 0x8e, 0x7b, 0x8a, 0x98, 0x89, 0x82, 0x57, 0x50, 0x2e, 0x6c, 0x25,
.db 0x8a, 0x7f, 0x6d, 0xa2, 0x93, 0x03, 0x9c, 0x65, 0x5d, 0x25, 0x3b, 0x00, 0x80, 0x92, 0xa3, 0xa3,
.db 0x58, 0xa7, 0x96, 0x39, 0x3b, 0x99, 0xa0, 0x01, 0x25, 0x46, 0xba, 0x5a, 0x5d, 0x53, 0x39, 0xac,
.db 0x7f, 0x7f, 0xaa, 0x53, 0x36, 0xba, 0x46, 0x3c, 0xbd, 0x5c, 0xc9, 0x81, 0xb8, 0x5e, 0xb4, 0x4c,
.db 0x08, 0x00, 0x83, 0x9d, 0xd1, 0xbf, 0x5c, 0xab, 0xd7, 0xbe, 0xd0, 0xd1, 0x83, 0x48, 0xc9, 0xc9,
.db 0x4d, 0xd8, 0xe0, 0x36, 0x3e, 0x4d, 0xb4, 0x38, 0xdb, 0x00, 0xd6, 0xc3, 0x65, 0x5b, 0xea, 0xc4,
.db 0x24, 0xab, 0x43, 0x1e, 0xe5, 0x24, 0xe7, 0xbf, 0x35, 0x4d, 0xef, 0xf5, 0xf9, 0xd1, 0xed, 0xfd,
.db 0x1e, 0x22, 0x00, 0x00, 0x3b, 0	; extra zero added, looks like gifs dont worry about it.
faviconend:

;	jmp	readmultiplepackets
.endif ; webserver


.ifdef aura
    .define need_err404text
.endif
.ifdef webserver
    .define need_err404text
.endif
.ifdef srvctrl
    .define need_err404text
.endif

; not work :( .EQU webserver_id  = .db "Server: OSCaR Wiznet+AVR 0.1"

.ifdef need_err404text
err404string:
;.message "QWE!"	; compile-time only
.db "HTTP/1.1 404 Not Found",13,10
.db "Server: OSCaR Wiznet+AVR 0.1",13,10
.db "Accept-Ranges: bytes",13,10
.db "Content-Length: 0254",13,10	;  must include extra zero (if exist), we must calculate exactly.
;.db "Keep-Alive: timeout=5, max=100",13,10
;.db "Keep-Alive: timeout=1, max=5",13,10
.db "Connection: Keep-Alive",13,10
.db "Content-Type: text/html; charset=iso-8859-1 ",13,10
.db 13,10
.db "<!DOCTYPE HTML PUBLIC ",34,"-//IETF//DTD HTML 2.0//EN",34,">"
.db "<html><head><title>404 Not Found </title></head><body text=",34,"#eee",34," bgcolor=",34,"#111",34,"><h1>Not Found</h1><p>The requested URL was not found on this server.</p><hr> "
.db "<address>Server: OSCaR Wiznet+AVR 0.1</address></body></html>",10
err404stringend:
.endif


; sudo nmap -P0 -sU -p 161 1.1.1.0/24
; snmpset -v 2c -c testtest 1.1.1.20 "1.3.6.1.2.1.1.1.3" x 0011223344556677
; first time SNMP work: 11-09-2013

; Hex-STRING: 71 74 63 63 05 7F 00 00 88 
; Hex-STRING: 61 74 63 63 05 7F 00 00 88 02 3E 7C BA 

; remote action:
;Hex-STRING: 71 74 63 63 06 7F 00 00 1C 
;Hex-STRING: 71 74 63 63 06 7F 00 00 61 74 63 63 06 7F 00 00 
;1C 02 3E 7C BA 

; верх 5 34 136
; низ 6 34 28

.ifdef snmp
	.equ	snmpslength=32
	.equ	passwordlength=6

.ifdef snmp_mtf
	.equ snmpqty=16
.endif
.ifdef snmp_floks
	.equ snmpqty=26
.endif
.ifdef snmp_smarthome
	.equ snmpqty=20
.endif

	push	r15	; is stack depth enough?!
	push	r14
	push	r13
	push	r12
	push	r11
	push	r10
	push	r09
	push	r08
; In case of UDP, 8byte header is attached to receiving data.
	ldi	r26, low(rxbuf)
	ldi	r27, high(rxbuf)
; each time we need to fill dest addr and dest port.
	ldi	r16, low(S0_DIPR)
	ldi	r17, high(S0_DIPR)
	rcall	w5100outaddr
	ld	r16, x+
	rcall	w5100outdata
	ld	r16, x+
	rcall	w5100outdata
	ld	r16, x+
	rcall	w5100outdata
	ld	r16, x+
	rcall	w5100outdata
	ldi	r16, low(S0_DPORT)
	ldi	r17, high(S0_DPORT)
	rcall	w5100outaddr
	ld	r16, x+
	rcall	w5100outdata
	ld	r16, x+
	rcall	w5100outdata
; save data size
	ld	r16, x+ ; Data Size (2 bytes)
;	mov	r20, r16	; currently not used.
	ld	r16, x+	
;	mov	r21, r16	; currently not used.
; prepare tx buf
	ldi	r28, low(txbuf)
	ldi	r29, high(txbuf)
; continue processing from first byte of actual data block.
; we build tx packet almost copypasting from rx packet.
	ld	r16, x+	
	st	y+, r16

	movw	r14, r28 ; r28:r29 = 'y' - save pointer in TX buf for fill later.
	ld	r16, x+	
	st	y+, r16 ; MUST be overwritten later if packet size changes.

	ld	r16, x+	
	st	y+, r16
	ld	r16, x+	
	st	y+, r16
	ld	r16, x+	; 4th byte
	st	y+, r16
; removed due to php's snmprealwalk() gives this byte 0x0 (snmp v.1).
;	cpi	r16, 0x01 ; snmp version: 0x1 - v2c
;	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	ld	r16, x+	; 6th byte
	st	y+, r16
;	cpi	r16, 0x08 ; community name length
	cpi	r16, passwordlength ; community name length
	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 'p'
	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 'a'
	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 's'
	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 's'
	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 'w'
	brne	snmpsilenterr
;	ld	r16, x+	
;	st	y+, r16
;	cpi	r16, 'o'
;	brne	snmpsilenterr
;	ld	r16, x+	
;	st	y+, r16
;	cpi	r16, 'r'
;	brne	snmpsilenterr
	ld	r16, x+	
	st	y+, r16
	cpi	r16, 'd'
	brne	snmpsilenterr
	rjmp	snmp2
snmpsilenterr:
	jmp	snmpsilenterr2
snmp2:
; a0 - get request (rx), a1 - get next request (rx), 
; a2 - seng responce (tx)	a3 = "SET" request
	ld	r16, x+
	mov	r18, r16	; a0, a1, or a3
	ldi	r16, 0xa2
	st	y+, r16

	movw	r12, r28 ; r28:r29 = 'y' - save pointer in TX buf for fill later.
	ld	r16, x+	
	st	y+, r16 ; MUST be overwritten later if packet size changes.

; unfortunately, request id can be less than 4 bytes exactly. :-(
;	ldi	r17, 6
;snmp7:
;	ld	r16, x+	; 02, 04, request id (4 bytes), 02, 01, 00, 02, 01, 00
;	st	y+, r16
;	ld	r16, x+
;	st	y+, r16
;	dec	r17
;	brne	snmp7
	ld	r16, x+
	st	y+, r16	; 02
	ld	r21, x+
	st	y+, r21	; 04 - reqid length - saved for later
	mov	r17, r21
snmp7:
	cpi	r17, 0
	breq	snmp7a
	ld	r16, x+
	st	y+, r16
	dec	r17
	rjmp	snmp7
snmp7a:
	ld	r16, x+	; 02, 01, 00, 02, 01, 00
	st	y+, r16
	ld	r16, x+
	st	y+, r16
	ld	r16, x+
	st	y+, r16
	ld	r16, x+
	st	y+, r16
	ld	r16, x+
	st	y+, r16
	ld	r16, x+
	st	y+, r16

	ld	r16, x+	; 30
	st	y+, r16

	movw	r10, r28 ; r28:r29 = 'y' - save pointer in TX buf for fill later.
	ld	r16, x+	
	st	y+, r16 ; MUST be overwritten later if packet size changes.

	ld	r16, x+	; 30 ; variable bindings - 1 item
	st	y+, r16

	movw	r08, r28 ; r28:r29 = 'y' - save pointer in TX buf for fill later.
	ld	r16, x+	
	st	y+, r16 ; MUST be overwritten later if packet size changes.

	ld	r16, x+	; 06 
	st	y+, r16
	ld	r16, x+	; 08 ; OID "string" length
	mov	r17, r16
	andi	r17, 0b00111111 ; safety and correct less_than / greater_than compare
	ldi	r16, 8	; returned OID always 8 bytes regardless of requested
	st	y+, r16
	ld	r16, x+	; 2b
	st	y+, r16
	cpi	r16, 0x2b
	brne	snmpsilenterr
; here we need to prefill some bytes if r17 < 8.
; snmpwalk -v 2c -c testtest 1.1.1.16 "iso.3.6"
	ld	r16, x+	; 06
	ldi	r16, 6
	st	y+, r16
	ld	r16, x+	; 01
	ldi	r16, 1
	st	y+, r16
	ld	r16, x+	; 02
	ldi	r16, 2
	st	y+, r16
	ld	r16, x+	; 01
	ldi	r16, 1
	st	y+, r16
	ld	r16, x+	; 01
	ldi	r16, 1
	st	y+, r16
	ld	r16, x+	; 01
	ldi	r16, 1
	st	y+, r16
	ld	r16, x+	; 00 -- last byte - increase it

	cpi	r17, 8	;  OID exactly given
	breq	snmp4
	ldi	r16, 0	; OID not 8 bytes, consider it less than 8 bytes (partial) so we reset snmpgetnext's counter to first value in tree.
snmp4:
	cpi	r18, 0xa0 ; a0 - get, a1 - get_next
	breq	snmp5
	cpi	r18, 0xa3 ; a3 - set
	breq	snmp5
	cpi	r17, 8	;  OID was exactly given
	brne	snmp5
	inc	r16
snmp5:
	andi	r16, 0b01111111
	st	y+, r16
	mov	r00, r16 ; parameter index, WARNING, max q'ty=127. (126) due to coding changes above 128.
	cpi	r16, snmpqty
;	brsh	snmpdoneanswer	; eq or greater
	brlo	snmp6			; less than
	jmp	snmpdoneanswer

snmp6:
	cpi	r18, 0xa3	; snmp_set
	breq	snmp_set
	cpi	r18, 0xa0
	breq	snmp_get_getnext
	cpi	r18, 0xa1
	breq	snmp_get_getnext
	rjmp	snmpsilenterr	; unknown operation


; === SNMP SET section ===

snmp_set:
	cpi	r17, 8	;  OID exactly given
	breq	snmpset2
	jmp	snmpsilenterr	; can't SET parameter if OID not exactly given.
snmpset2:

.ifdef snmp_mtf
	mov	r16, r00
	cpi	r16, 11
	brne	snmpset3
;	breq	snmp_MTF_set_string
	jmp	snmpset_ram
snmpset3:
	cpi	r16, 7
	brne	snmpset4
	ldi	r30, low(eep_SNMPsettings_base + 0x20)
	ldi	r31, high(eep_SNMPsettings_base + 0x20)
	ldi	r18, 1	; flag
	jmp	snmp_set_string_eeprom
snmpset4:
	cpi	r16, 1
	brne	snmpset5
	ldi	r30, low(eep_SNMPsettings_base + 0x40)
	ldi	r31, high(eep_SNMPsettings_base + 0x40)
	ldi	r18, 1	; flag
	jmp	snmp_set_string_eeprom
snmpset5:
	cpi	r16, 5	; ip addr, mask...etc
	brne	snmpset6
	ldi	r30, low(eep_settings_base)
	ldi	r31, high(eep_settings_base)
	ldi	r18, 0	; flag
	jmp	snmp_set_string_eeprom
snmpset6:
	cpi	r16, 3	; s/n
	brne	snmpset7
	ldi	r30, low(eep_SNMPsettings_base + 0)
	ldi	r31, high(eep_SNMPsettings_base + 0)
	ldi	r18, 0	; flag
	jmp	snmp_set_string_eeprom
snmpset7:
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif ; snmp_mtf


.ifdef snmp_floks
	mov	r16, r00
	cpi	r16, 1	; hw name: disable this for final product.
	brne	snmpset9
	ldi	r30, low(eep_SNMPsettings_base + 0x40)
	ldi	r31, high(eep_SNMPsettings_base + 0x40)
	ldi	r18, 1	; flag
	jmp	snmp_set_string_eeprom
snmpset9:
	cpi	r16, 5	; ip addr, mask...etc
	brne	snmpset8
	ldi	r30, low(eep_settings_base)
	ldi	r31, high(eep_settings_base)
	ldi	r18, 0	; flag
	jmp	snmp_set_string_eeprom
snmpset8:
	cpi	r16, 11 	; Main control Request/Reply [R/W]
	brne	snmpset10
	jmp	snmpset_ram
snmpset10:
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif ; floks

.ifdef snmp_smarthome
	mov	r16, r00
	cpi	r16, 1	
	brne	snmpset1
	ldi	r30, low(eep_SNMPsettings_base + 0x40)
	ldi	r31, high(eep_SNMPsettings_base + 0x40)
	ldi	r18, 1	; flag
	jmp	snmp_set_string_eeprom
snmpset1:
	cpi	r16, 3	; "Daughterboard / model / function" 
	brne	snmpset3
;	ldi	r30, low(eep_SNMPsettings_base + 0)
;	ldi	r31, high(eep_SNMPsettings_base + 0)
;	ldi	r18, 0	; flag
	ldi	r30, low(eep_SNMPsettings_base + 0x20)
	ldi	r31, high(eep_SNMPsettings_base + 0x20)
	ldi	r18, 1	; flag
	jmp	snmp_set_string_eeprom
snmpset3:
	cpi	r16, 5	; ip addr, mask...etc
	brne	snmpset5
	ldi	r30, low(eep_settings_base)
	ldi	r31, high(eep_settings_base)
	ldi	r18, 0	; flag
	jmp	snmp_set_string_eeprom
snmpset5:
	cpi	r16, 7	
	brne	snmpset7
	jmp	snmp_smarthome_setport
snmpset7:
	cpi	r16, 15
	brne	snmpset15
.ifdef irtransmit
	jmp	snmp_irtransmit
.else
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif
snmpset15:
	cpi	r16, 17
	brne	snmpset17
.ifdef rcpwm
	jmp	snmp_setrcpwm0
.else
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif
snmpset17:
	cpi	r16, 19
	brne	snmpset19
.ifdef rcpwm
	jmp	snmp_setrcpwm1
.else
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif
snmpset19:
	rjmp	snmpdoneanswer	; answer 0x81 error
.endif ; smarthome


; === SNMP READ section ===

snmp_get_getnext:
; remaining rx bytes not used here... 
	mov	r16, r00	; parameter #
	andi	r16, 0b00000001	; even / odd parameters, even - strings, odd - integers
	breq	snmpstringanswer2

	mov	r16, r00

.ifdef snmp_mtf
	cpi	r16, 1
	breq	snmp_read_string_eeprom_hwname
	cpi	r16, 3
	breq	snmp_getsernumber
	cpi	r16, 5
	breq	snmp_getip
	cpi	r16, 7
	breq	snmp_read_string_eeprom_3
	cpi	r16, 9
;	breq	snmp_MTF_get_string_internal
	breq	snmpset_eeprom_3
	cpi	r16, 11	; can't just GET string, should use SET to get answer from MTF, so raise error.
	breq	snmp_return_null
	cpi	r16, 13
	breq	snmp_ds18b20_readtemp
	cpi	r16, 15
	breq	snmp_ds18b20_readserial
; here should never occurs, because of previous checks.
	rjmp	snmpsilenterr	; unknown operation
.endif

.ifdef snmp_floks
	cpi	r16, 1
	breq	snmp_read_string_eeprom_hwname
	cpi	r16, 3
	breq	snmp_getsernumber
	cpi	r16, 5
	breq	snmp_getip
	cpi	r16, 7
	breq	snmp_read_string_eeprom_3
	cpi	r16, 9
	breq	snmpset_eeprom_3
	cpi	r16, 11
	breq	snmp_return_null
	cpi	r16, 13
	breq	snmp_ds18b20_readserial

	cpi	r16, 15
	breq	snmpget_txagc
	cpi	r16, 17
	breq	snmpget_rxagc

	cpi	r16, 19
	breq	snmp_ds18b20_readtemp
	cpi	r16, 21
	breq	snmpget_temper1
	cpi	r16, 23
	breq	snmpget_heater
	cpi	r16, 25
	breq	snmpget_uptime

	rjmp	snmpsilenterr	; unknown operation
.endif

.ifdef snmp_smarthome
	cpi	r16, 1
	breq	snmp_read_string_eeprom_hwname
	cpi	r16, 3
;	breq	snmp_getsernumber	; text. "Daughterboard / model / function" 
	breq	snmp_read_string_eeprom_3	; text. "Daughterboard / model / function" 
	cpi	r16, 5
	breq	snmp_getip
	cpi	r16, 7
	breq	snmp_smarthome_readport_
	cpi	r16, 9
	breq	snmp_ds18b20_readtemp
	cpi	r16, 11
	breq	snmp_ds18b20_readserial
	cpi	r16, 13
.ifdef rotary_encoder
	breq	snmp_smarthome_readencoder_
.else
	breq	snmp_return_null
.endif
	cpi	r16, 15	; TODO - IR receiver here
	breq	snmp_return_null
	cpi	r16, 17
.ifdef rcpwm
	breq	snmp_getrcpwm0_
.else
	breq	snmp_return_null
.endif
	cpi	r16, 19
.ifdef rcpwm
	breq	snmp_getrcpwm1_
.else
	breq	snmp_return_null
.endif
; here should never occurs, because of previous checks.
	rjmp	snmpsilenterr	; unknown operation

snmp_smarthome_readport_:
	rjmp	snmp_smarthome_readport
snmp_smarthome_readencoder_:
	rjmp	snmp_smarthome_readencoder

.ifdef rcpwm
snmp_getrcpwm0_:
	rjmp	snmp_getrcpwm0
.endif
.ifdef rcpwm2
snmp_getrcpwm1_:
	rjmp	snmp_getrcpwm1
.endif

.endif

	rjmp	snmpsilenterr	; unknown operation


snmpstringanswer2:
	rjmp	snmpstringanswer

snmp_ds18b20_readserial:
	rjmp	snmp_ds18b20_readserial_

snmp_ds18b20_readtemp:
	rjmp	snmp_ds18b20_readtemp_


snmpget_txagc:
	ldi	r18, 0	; here are pointers (index) to values (bytes) from Floks.
em1:
	ldi	r17, 1	; record size
em2:
;	ldi	r16, 0x42	; record type: unsigned integer32 (no type for 8-bit unsigned)
	ldi	r16, 2	; record type: integer
	rjmp	snmpget_emulate_ram
snmpget_rxagc:
	ldi	r18, 1	; here are pointers (index) to values (bytes) from Floks.
	rjmp	em1
snmpget_heater:
	ldi	r18, 4	; here are pointers (index) to values (bytes) from Floks.
	rjmp	em1
snmpget_uptime:
	ldi	r18, 12	; here are pointers (index) to values (bytes) from Floks.
	ldi	r17, 4	; record size
	ldi	r16, 0x42	; record type: unsigned integer32 (no type for 8-bit unsigned)
	rjmp	snmpget_emulate_ram

snmpget_temper1:
	ldi	r18, 3	; here are pointers (index) to values (bytes) from Floks.
	rjmp	em1
;	ldi	r17, 1	; record size
;	ldi	r16, 2	; record type: integer
;	rjmp	snmpget_emulate_ram

snmpset_eeprom_3:
	jmp	snmpget_eeprom

snmp_getip:
	ldi	r30, low(eep_settings_base+0)
	ldi	r31, high(eep_settings_base+0)
;	ldi	r16, 0x40	; record type = "ip address"
;	ldi	r17, 12
	ldi	r17, 8	; ip addr, mask
	rjmp	snmpget2

; 1.3.6.1.2.1.1.1.1  
snmp_read_string_eeprom_hwname:
	ldi	r30, low(eep_SNMPsettings_base + 0x40)
	ldi	r31, high(eep_SNMPsettings_base + 0x40)
	rjmp	snmp_read_string_eeprom


snmp_read_string_eeprom_3:
	ldi	r30, low(eep_SNMPsettings_base + 0x20)
	ldi	r31, high(eep_SNMPsettings_base + 0x20)
	jmp	snmp_read_string_eeprom


snmp_getsernumber:
	ldi	r30, low(eep_SNMPsettings_base)
	ldi	r31, high(eep_SNMPsettings_base)
.ifdef snmp_mtf
	ldi	r17, 5	; modem - 5 bytes hexstring
.else
	ldi	r17, 6	; floks - 6 digits ascii string
.endif
snmpget2:
	ldi	r16, 0x04	; string, or HEX string if contains non-ASCII
	st	y+, r16
	mov	r19, r17	; length
	st	y+, r19
snmpget3:
	rcall	eep_read
	st	y+, r16
	dec	r17
	brne	snmpget3
	rjmp	snmpanswer


snmp_return_null:
; can't just GET string, should use SET to get answer from MTF, so raise error.
	ldi	r16, 0x05	; NULL
	st	y+, r16
	ldi	r19, 0
	st	y+, r19
	rjmp	snmpanswer



snmpdoneanswer:
;	ldi	r19, snmpdonelength
	ldi	r19, 0

	cpi	r18, 0xa0 ; a0 - get, a1 - get_next
	breq	snmpd1
	cpi	r18, 0xa3 ; a3 - set
	breq	snmpd3
	ldi	r16, 0x82	; type - end of MIB
	rjmp	snmpd2
snmpd1:
	ldi	r16, 0x80	; type - no object  - both 80 & 82 work for snmpwalk.
	rjmp	snmpd2
snmpd3:
	ldi	r16, 0x81	; NoSuchInstance 
snmpd2:
	st	y+, r16
;	ldi	r16, snmpdonelength 
	ldi	r16, 0
	st	y+, r16
	rjmp	snmpanswer

snmpstringanswer:
	ldi	r19, snmpslength

	ldi	r16, 0x04	; type = string
	st	y+, r16
	ldi	r16, snmpslength ; length
	st	y+, r16

	ldi	r24, low(snmpslength)
	ldi	r25, high(snmpslength)
	ldi	r30, low(snmpstrings*2)
	ldi	r31, high(snmpstrings*2)
	mov	r16, r00
	ldi	r17, 0
	lsl	r16
	rol	r17
	lsl	r16
	rol	r17
	lsl	r16
	rol	r17
	lsl	r16
	rol	r17
;	lsl	r16
;	rol	r17
	add	r30, r16
	adc	r31, r17

	rcall	datamemcpy
	rjmp	snmpanswer


snmp_read_string_eeprom:
	ldi	r16, 0x04
	st	y+, r16
	rjmp	snmp_MTF_read_string_eeprom_2


; set eeprom content. first byte in eeprom = length when string (r18=1),
;  no special first byte when fixed length parameters like IP addr etc.
; before:	set r30, r31, r18
snmp_set_string_eeprom:
	ld	r16, x+	;  record type: 04 = string
	st	y+, r16
	cpi 	r16, 0x04	; known type - string
	brne	snmpdoneanswer	; answer 0x81 error
	ld	r17, x+	;  record size (hope it < 255... or even < 127 ? )
	andi	r17, 0b00111111
;;;;	st	y+, r16

;	ldi	r30, low(eep_MTFsettings_base + 0x20)
;	ldi	r31, high(eep_MTFsettings_base + 0x20)
	push	r31
	push	r30
	push	r17	; try to replace
.ifdef use_serial_leds
	sbi	ledport, ledIPTXbit ; treat as eeprom write led
.endif
	cpi	r18, 0	; flag=0 - no length byte written.
	breq	eep_wrt
	mov	r16, r17	; first byte - length
	rcall	eep_write
eep_wrt:
	cpi	r17, 0
	breq	eep_wrt_done
	ld	r16, x+
	rcall	eep_write
	dec	r17
	rjmp	eep_wrt
eep_wrt_done:
.ifdef use_serial_leds
	cbi	ledport, ledIPTXbit ; treat as eeprom write led
.endif
	pop	r17	; try to replace
	pop	r30
	pop	r31
snmp_MTF_read_string_eeprom_2:
;	ldi	r30, low(eep_MTFsettings_base + 0x20)
;	ldi	r31, high(eep_MTFsettings_base + 0x20)
	mov	r16, r17
	cpi	r18, 0	; flag=0 - no length byte written.
	breq	eep_rd2
	rcall	eep_read	; first byte = length
	andi	r16, 0b00111111
eep_rd2:
	st	y+, r16	; set answer length (0 allowed)
	mov	r19, r16
	mov	r17, r16
eep_rd:
	cpi	r17, 0
	breq	eep_rd_done
	rcall	eep_read
	st	y+, r16
	dec	r17
	rjmp	eep_rd
eep_rd_done:
	rjmp	snmpanswer


.ifdef uio
; emulate memory content as like we receive it via snmpset, but it just snmpget.
snmpget_txagc:
	push	r27
	push	r26
;	ldi	r16, 4	; record type: 04 = string 
	ldi	r16, 2	; record type: integer
	st	x+, r16
	ldi	r16, 1	; record size
	st	x+, r16		
; integer answer - MSB FIRST!
	ldi	r16, 0	; here are pointers (index) to values (bytes) from Floks.
	st	x+, r16
	pop	r26
	pop	r27
	rjmp	snmpset_ram
.endif


; emulate memory content as like we receive it via snmpset, but it just snmpget.
snmpget_emulate_ram:
	push	r27
	push	r26
	st	x+, r16	; record type
	st	x+, r17	; record size
; integer answer - MSB FIRST!
;	ldi	r16, 13	; here are pointers (index) to values (bytes) from Floks.
	st	x+, r18
	inc	r18
	st	x+, r18
	inc	r18
	st	x+, r18
	inc	r18
	st	x+, r18		; max. 4 bytes...
	pop	r26
	pop	r27
	rjmp	snmpset_ram




; send request from eeprom or ram, read answer.
snmpget_eeprom:
	ldi	r30, low(eep_SNMPsettings_base + 0x20)
	ldi	r31, high(eep_SNMPsettings_base + 0x20)
	set
	rjmp	snmpgetset_eeprom_ram
snmpset_ram:
	clt
snmpgetset_eeprom_ram:
; ideally, we must here turn off Ethernet receiver until we completely send answer.
; because if rs232 tx+rx time takes more than one second, repeatable requests 
; from SNMPGET stays in eth rx buffer and leads to more than one answer.

; TODO: stop  Ethernet receiver here.
; ...
	in	r16, UDR     ; flush 3-byte HW atmega rx buffer
	in	r16, UDR     
	in	r16, UDR     
	in	r16, UDR

	ld	r16, x+	;  record type: 04 = string - for RAM mode, it exist in 'snmpset' request,
; but for eeprom, there is no type (or 'null' type in snmpget)
; so different processing:
	brtc	snmp_use_ram4
	ldi	r16, 0x04
snmp_use_ram4:
	st	y+, r16
;	cpi 	r16, 0x04	; known type - string
;;;	brne	snmpdoneanswer	; answer 0x81 error
;	breq	snmp_tx3
;	rjmp	snmpdoneanswer	; answer 0x81 error
;snmp_tx3:

	brts	snmp_use_eeprom
snmp_use_ram:	
	ld	r17, x+	;  record size (hope it < 255... or even < 127 ? )
	andi	r17, 0b01111111
	cpi	r17, 0
	brne	snmp_tx2
;	breq	snmpdoneanswer	; answer 0x81 error
	jmp	snmpdoneanswer	; answer 0x81 error
snmp_tx2:
	rjmp	snmp_mem_selected

snmp_use_eeprom:
;	ldi	r30, low(eep_SNMPsettings_base + 0x20)
;	ldi	r31, high(eep_SNMPsettings_base + 0x20)
	rcall	eep_read	; first byte = length
	andi	r16, 0b00111111
	mov	r17, r16
snmp_mem_selected:
.ifdef use_serial_leds
	sbi	ledport, ledRSTXbit
.endif

; mode MTF - send whole request packet, then receive anything
.ifdef snmp_mtf

; TODO! Check it! because not tested.

;	brts	snmp_use_eeprom2
;snmp_use_ram2:
;snmp_tx:
;	ld	r16, x+
;	rcall	wchar
;	dec	r17
;	brne	snmp_tx
;	rjmp	qpqp
;snmp_use_eeprom2:
;eep_rrd:
;	cpi	r17, 0		; TODO: optimize zero length checking for both cases...
;	breq	eep_rrd_done
;	rcall	eep_read
;	rcall	wchar
;	dec	r17
;	rjmp	eep_rrd
;eep_rrd_done:
;qpqp:


eep_rrd:
	cpi	r17, 0
	breq	eep_rrd_done
	rcall	snmp_getnextbyte
	rjmp	eep_rrd
eep_rrd_done:


.endif



; mode floks - send byte by byte and receive answer byte after each.
.ifdef snmp_floks
; here we send only one first byte:
	rcall	snmp_getnextbyte
.endif
.ifdef use_serial_leds
	cbi	ledport, ledRSTXbit
.endif

snmp_getanswer:
	push	r29	; save pointer in TX buf for fill later.
	push	r28
;	ldi	r16, 0	; length now unknown, fill it later.
; use any value.
	st	y+, r16	; keep pointer at right place
	ldi	r19, 0
snmp_rx5:
.ifdef snmp_floks ; 115200
	ldi	r20, 2	; ~ 0,08 seconds overall time window for answer
.else
	ldi	r20, 16	; ~ 0,8 seconds overall time window for answer
.endif

.ifdef xtal73728
	lsr	r20
.endif
snmp_rx3:
	ldi	r18, 0
snmp_rx2:
	ldi	r16, 0
snmp_rx:
	push	r16
.ifdef use_serial_leds
	cbi	ledport, ledRSRXbit
.endif
	sbis	UCSRA, RXC
	rjmp	serial_nodata
.ifdef use_serial_leds
	sbi	ledport, ledRSRXbit
.endif
	in	r16, UDR	; rs232 rx byte
;rcall wchar
	st	y+, r16
	inc	r19	; answer size

; mode floks - send byte by byte and receive answer byte after each.
; here we send remaining bytes, except first byte.
.ifdef snmp_floks
	cpi	r17, 0
	breq	snmp_floks_rxdone
	sbi	ledport, ledRSTXbit
	rcall	snmp_getnextbyte
	cbi	ledport, ledRSTXbit
.endif

	ldi	r16, 0	; delay, for RX LED noticeable...
snmp_rx6:
	nop
	nop
	dec	r16
	brne	snmp_rx6

serial_nodata:
	pop	r16

	dec	r16
	brne	snmp_rx	;   remove only for test! it works.
	dec	r18
	brne	snmp_rx2	; remove only for test! it works.
	dec	r20
	brne	snmp_rx3	; remove only for test! it works.
	rjmp	serial_done_or_timeout

snmp_floks_rxdone:
	pop	r16
serial_done_or_timeout:
	pop	r28
	pop	r29
	st	y+, r19	; fill string length
; TODO: start Ethernet receiver here.
; ...
	rjmp	snmpanswer

; here r19 - answer record lendth (not include 'record type' byte and 'length' byte itself)
snmpanswer:
; fill length's bytes - 4 pcs.
	add	r19, r21	; reqid length

	movw	r30, r14
	subi	r19, -(31+passwordlength)
	st	z+, r19
	movw	r30, r12  
	subi	r19, 7+passwordlength
	st	z+, r19

	sub	r19, r21	; reqid length

	movw	r30, r10
	subi	r19, 28-14-4
	st	z+, r19
	movw	r30, r08
	subi	r19, 14-12
	st	z+, r19
	pop	r08
	pop	r09
	pop	r10
	pop	r11
	pop	r12
	pop	r13
	pop	r14
	pop	r15	; is stack depth enough?!

; r24:r25 - packet length. hope packet always less than 255 bytes.
;	ldi	r24, 33
	ldi	r24, 21+passwordlength ; 6 bytes commynity name
; here r19 used after all subtractions...
;	add	r24, r21	; reqid length
	add	r19, r21	; reqid length
	add	r24, r19	; remaining bytes length
	ldi	r25, 0
	rcall	tx_packet_data
;	rcall    tcpdisconnect -- no! we use UDP!
	jmp	readmultiplepackets

snmpsilenterr2:
	pop	r08	;; is stack depth enough?!
	pop	r09
	pop	r10
	pop	r11
	pop	r12
	pop	r13
	pop	r14
	pop	r15
	jmp	readmultiplepackets


;.ifdef snmp_floks
snmp_getnextbyte:
	brts	snmp_use_eeprom2
snmp_use_ram2:
	ld	r16, x+
	rjmp	qpqp
snmp_use_eeprom2:
	rcall	eep_read
qpqp:
	rcall	wchar
	dec	r17
	ret
;.endif


.ifdef rcpwm
snmp_setrcpwm0:
	ldi	r18, 0		; channel #
	rjmp	snmp_setrcpwm
snmp_setrcpwm1:
	ldi	r18, 1

snmp_setrcpwm:
	ld	r16, x+	;  record type
;	st	y+, r16
	cpi 	r16, 0x42	; known type
	breq	rcpwm1
	jmp	snmpdoneanswer	; answer 0x81 error
rcpwm1:
	ld	r16, x+	; length
; unfortunately, even if we set only one byte,
; if it is 128...255 (snmpset .... u 255), two bytes received 
; with first is zero (we throw away).
	cpi	r16, 1
	breq	rcpwm5
	cpi	r16, 2
	breq	rcpwm6
	jmp	snmpdoneanswer	; answer 0x81 error
rcpwm6:
	ld	r16, x+	; dummy read
rcpwm5:
	ld	r16, x+	; value
	cpi	r18, 0
	brne	rcpwmch1
rcpwmch0:
	mov	r22, r16
;	cpi	r16, 0	; special case
;	breq	pwm_stop
	cpi	r16, 255 ; special case
	breq	pwm_stop0
	rcall	timer2_on_rcpwm
	rjmp	pwm_nxt0
pwm_stop0:
	rcall	timer2_off
pwm_nxt0:
	rjmp	rcpwmchnxt

rcpwmch1:
	mov	r23, r16
;	cpi	r16, 0	; special case
;	breq	pwm_stop
	cpi	r16, 255 ; special case
	breq	pwm_stop1
	rcall	timer0_on_rcpwm2
	rjmp	pwm_nxt1
pwm_stop1:
	rcall	timer0_off
pwm_nxt1:

rcpwmchnxt:
	ldi	r17, 0	; divide by const.
rcpw8:
	subi	r16, 14		; <- agjust slope.
	brlo	rcpw9
	inc	r17
	rjmp	rcpw8
rcpw9:
	mov	r16, r17
	subi	r16, -17	; add 17 ; <- agjust shift.
	cpi	r18, 0
	brne	rcpwmsetch1
rcpwmsetch0:
	out	ocr2, r16	; set PWM

snmp_getrcpwm0:
	ldi	r16, 0x42	; type - unsigned 32-bit
	st	y+, r16
	ldi	r19, 2		; length
	st	y+, r19
	ldi	r16, 0
	st	y+, r16
	mov	r16, r22
	st	y+, r16
	rjmp	snmpanswer

rcpwmsetch1:
	out	ocr0, r16	; set PWM

snmp_getrcpwm1:
	ldi	r16, 0x42	; type - unsigned 32-bit
	st	y+, r16
	ldi	r19, 2		; length
	st	y+, r19
	ldi	r16, 0
	st	y+, r16
	cpi	r18, 0
	mov	r16, r23
	st	y+, r16
	rjmp	snmpanswer
.endif ; rcpwm


.ifdef irtransmit
snmp_smarthome_irtransmit:
	ld	r16, x+	;  record type
;	st	y+, r16
	cpi 	r16, 0x04	; known type
;	brne	snmpdoneanswer	; answer 0x81 error
	breq	smhm11
	jmp	snmpdoneanswer	; answer 0x81 error
smhm11:
	ld	r18, x+	; length
	lsr	r18	; divide by 2, so if odd q'ty of bytes provided, one last is not used.
	cpi	r18, 0
	brne	irtx
	rjmp	snmp_return_null
irtx:
	rcall	timer2_on
	ld	r17, x+	; only 1-byte IR data used due to increase capacity of max 127-byte SNMP packet.
pulse_txon:
	rcall	ir_delay	; 1 / 16384 s. standard LIRC grain
	dec	r17
	brne	pulse_txon

	rcall	timer2_off
	ld	r17, x+	; only 1-byte IR data used due to increase capacity of max 127-byte SNMP packet.
pulse_txoff:
	rcall	ir_delay	; 1 / 16384 s. standard LIRC grain
	dec	r17
	brne	pulse_txoff

	dec	r18
	brne	irtx

	rcall	timer2_off	; ir pulse end
;	rjmp	snmp_smarthome_readport
	rjmp	snmp_return_null
.endif ; irtransmit



.ifdef snmp_smarthome

snmp_smarthome_readencoder:
; integer answer - MSB FIRST!
;	ldi	r16, 0x42	; type - unsigned 32-bit
; only send delta value, not absolute value. just as mouse movements.
	ldi	r16, 0x02	; type - int
	st	y+, r16
;	ldi	r19, 4		; length
	ldi	r19, 1		; length
	st	y+, r19
;	ldi	r16, 0
;	st	y+, r16
;	st	y+, r16
;	st	y+, r16
	mov	r16, r01	; current encoder delta
	mov	r17, r01
	lsr	r16
	lsr	r16
	bst	r16, 5		; copy sign bit
	bld	r16, 6
	bld	r16, 7
	st	y+, r16
	andi	r17, 0b00000011
	mov	r01, r17	; after reading, reset current delta.
	rjmp	snmpanswer

snmp_smarthome_readport:
; integer answer - MSB FIRST!
	ldi	r16, 0x42	; type - unsigned 32-bit
	st	y+, r16
	ldi	r19, 4		; length
	st	y+, r19
	ldi	r16, 0
	st	y+, r16
	st	y+, r16
	st	y+, r16
;	ldi	r16, 0x33
; bits 0-3 - inputs, due to SRVCTRL compatibility.
; bits 4-7 - outs, because they have LEDs already.
	in	r16, smarthomeIOportin	; even if ports = out, read current state.
;	andi	r16, 0b00001111
	st	y+, r16
	rjmp	snmpanswer

snmp_smarthome_setport:
	ld	r16, x+	;  record type: 04 = string
;	st	y+, r16
	cpi 	r16, 0x42	; known type
;	brne	snmpdoneanswer	; answer 0x81 error
	breq	smhm1
	jmp	snmpdoneanswer	; answer 0x81 error
smhm1:
	ld	r16, x+	; length
; unfortunately, even if we set only one byte,
; if it is 128...255 (snmpset .... u 255), two bytes received 
; with first is zero (we throw away).
	cpi	r16, 1
	breq	smhm5
	cpi	r16, 2
	breq	smhm6
	jmp	snmpdoneanswer	; answer 0x81 error
smhm6:
	ld	r16, x+	; dummy read
smhm5:
	ld	r16, x+	; value
;	out	smarthomeIOport, r16
	sbrs	r16, 4
	cbi	smarthomeIOport, 4
	sbrc	r16, 4
	sbi	smarthomeIOport, 4
	sbrs	r16, 5
	cbi	smarthomeIOport, 5
	sbrc	r16, 5
	sbi	smarthomeIOport, 5
	sbrs	r16, 6
	cbi	smarthomeIOport, 6
	sbrc	r16, 6
	sbi	smarthomeIOport, 6
	sbrs	r16, 7
	cbi	smarthomeIOport, 7
	sbrc	r16, 7
	sbi	smarthomeIOport, 7
	rjmp	snmp_smarthome_readport


;;; need to 12M / 16384 = 732 tact delay (61 * 12).
; need to 14745600 / 16384 = 900 tact delay (90 * 10).
; but real delay (time grain for digitize packet) is not measured in hardware so may be not
; accurate. 

ir_delay:
	ldi	r16, 90
ir_d1:
	nop	; 1 tact  x  7
	nop
	nop
	nop
	nop
	nop
	nop
	dec	r16	; 1 tact
	brne	ir_d1	; 2 tact when loop
	ret
.endif


; ===== h/w access subroutines and other =====

.ifdef use_ds18b20_pin

snmp_ds18b20_readserial_:
; integer answer - MSB FIRST!
	rcall   ONEWIRE_RST
	cpi	r16, 0
	brne	snmp_ret_null
	ldi	r16, 0x42	; type - unsigned 32-bit
	st	y+, r16
	ldi	r19, 4		; length
	st	y+, r19
	ldi	r16, 0x33
	rcall	ONEWIRE_WR
	rcall   ONEWIRE_RD
;	st	y+, r16		; skip family code byte 28h
	rcall   ONEWIRE_RD
;	andi	r16, 0b01111111	; ser.num. should be positive.
	st	y+, r16		; use only 4 of 6 s/n bytes
	rcall   ONEWIRE_RD	; and don't care about msb/lsb byte.
	st	y+, r16
	rcall   ONEWIRE_RD
	st	y+, r16
	rcall   ONEWIRE_RD
	st	y+, r16
	rcall	ONEWIRE_RST	; done reading signal
ds18b20_readserial_done:
	rjmp	snmpanswer

snmp_ret_null:
	rjmp	snmp_return_null

snmp_ds18b20_readtemp_:
	rcall   ONEWIRE_RST
	cpi	r16, 0
	brne	snmp_ret_null
	ldi	r16, 0x02	; type - int
	st	y+, r16
	ldi	r19, 2		; int size - two byte here.
	st	y+, r19
	ldi	r16, 0xcc ;skip rom command
	rcall	ONEWIRE_WR
	ldi	r16, 0x44 ;Convert temperature command
	rcall	ONEWIRE_WR
	push	r19
	push	r18
	ldi	r18, 0
polling:
	ldi	r19, 1	; 50 ms
	call	dly
	rcall   ONEWIRE_RD_BIT
	cpi	r16, 0
	brne	polling_done
	inc	r18
	cpi	r18, 20 	; need 750 ms. 20 = 1 s.
	brne	polling
polling_done:
;	st	y+, r18		; test - polling time fetch - work
	pop	r18
	pop	r19

	rcall   ONEWIRE_RST
	ldi	r16, 0xcc ;skip rom command
	rcall	ONEWIRE_WR
	ldi	r16, 0xbe ;read scratchpad command
	rcall	ONEWIRE_WR
	rcall   ONEWIRE_RD
;	st	y+, r16
	push	r16
	rcall	ONEWIRE_RD
	st	y+, r16
	pop	r16
	st	y+, r16	; lsb last
	rcall	ONEWIRE_RST ; done reading signal
onewire_read_done:
	rjmp	snmpanswer

; subroutines

; http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=835011
;	1WIRE reset and presence pulse
ONEWIRE_RST:
	push	r18
	push	r17
	sbi	ds18b20ddr, ds18b20IObit	; out '0'
	ldi	r16, 13
	rcall	delayx50us
	cbi	ds18b20ddr, ds18b20IObit	; release wire
	ldi	r16, 60
	rcall	delayx1us

	ldi	r18, 0	; no error
	ldi	r17, 200	; timeout counter 2 ms
onewirerst1:
	sbis	ds18b20pin, ds18b20IObit
	rjmp	onewirerst2
	ldi	r16, 10
	rcall	delayx1us	; 10 us step
	dec	r17
	brne	onewirerst1
	rjmp	onewire_err
onewirerst2:
	ldi	r17, 200	; timeout counter 2 ms
onewirerst3:
	sbic	ds18b20pin, ds18b20IObit
	rjmp	onewirerst4
	ldi	r16, 10
	rcall	delayx1us	; 10 us step
	dec	r17
	brne	onewirerst3
	rjmp	onewire_err
onewirerst4:
	rjmp	onewirerstdone

onewire_err:
	ldi	r18, 1	; error
onewirerstdone:
	ldi	r16, 10		; wait Master RX 480 us min (ds18b20 fig.13)
	rcall	delayx50us
	mov	r16, r18	; result
	pop	r17
	pop	r18
	ret 

;	write data 1 byte
;	output:   r16
ONEWIRE_WR: push r18
	push	r17
	mov	r18, r16
	ldi	r17, 8   ;write 8 bit
Sub_1WireWR:
	sbi	ds18b20ddr, ds18b20IObit	; out '0'
	ldi	r16, 2
	rcall	delayx1us
	ror	r18   ;LSB frist out
	brcc	Sub_1WireWR_1
	cbi	ds18b20ddr, ds18b20IObit	; release wire
Sub_1WireWR_1:
	ldi	r16, 65
	rcall	delayx1us
	cbi	ds18b20ddr, ds18b20IObit	; release wire
	ldi	r16, 2
	rcall	delayx1us
	dec	r17
	brne	Sub_1WireWR
	pop	r17
	pop	r18
	ret

;	Read data 1 byte
;	input:   Onewire_Data
ONEWIRE_RD: 
	push	r18
	push	r17
	ldi	r17, 8   ;read 8 bit
Sub_1WireRD:
 	sbi	ds18b20ddr, ds18b20IObit	; out '0'
	ldi	r16, 2
	rcall	delayx1us
	cbi	ds18b20ddr, ds18b20IObit	; release wire
	ldi	r16, 4
	rcall	delayx1us
	clc
	sbic	ds18b20pin, ds18b20IObit
	sec
	ror	r18
;   ldi   r16,45
	ldi	r16, 60
	rcall	delayx1us
	dec	r17
	brne	Sub_1WireRD
	mov	r16, r18	; result
	pop	r17
	pop	r18
	ret 

ONEWIRE_RD_BIT: 
 	sbi	ds18b20ddr, ds18b20IObit	; out '0'
	ldi	r16, 2
	rcall	delayx1us
	cbi	ds18b20ddr, ds18b20IObit	; release wire
	ldi	r16, 4
	rcall	delayx1us
	ldi	r16, 0				
	sbic	ds18b20pin, ds18b20IObit
	ldi	r16, 1
	push	r16
;   ldi   r16,45
	ldi	r16,60
	rcall	delayx1us
	pop	r16
	ret

;	delay time
;	Note: These delay Programs use frequency = 8 mhz
delayx1us:
	push	r17
	mov	r17, r16
delayx1us_1:
	push	r17
	pop	r17
	nop
	push	r17	; 14 mhz
	pop	r17	; 14 mhz
	nop
	dec	r17
	brne	delayx1us_1
	pop	r17
	ret

delayx50us:
	push	r18
	push	r17
	mov	r18, r16
delayx50us_1:
;   ldi   r17,100
	ldi	r17, 200	; 14 mhz
delayx50us_2:
	nop
	dec	r17
	brne	delayx50us_2
	dec	r18
	brne	delayx50us_1
	pop	r17
	pop	r18
	ret 

.endif ; use_ds18b20_pin


datamemcpy:
	push	r25
	push	r24
cpcp:
	lpm	r16, z+
	st	y+, r16
	sbiw	r24, 1
	brne	cpcp
	pop	r24
	pop	r25
	ret

eep_read:
	sbic	EECR, EEWE
	rjmp	eep_read
	out	EEARH, r31
	out	EEARL, r30
	sbi	EECR, EERE
	in	r16, EEDR
	adiw	r30, 1
	ret

eep_write:
	sbic	EECR, EEWE
	rjmp	eep_write
	out	EEARH, r31
	out	EEARL, r30
	out	EEDR, r16
	sbi	EECR, EEMWE
	sbi	EECR, EEWE
	adiw	r30, 1
	ret

snmpstrings:
.ifdef snmp_mtf
;	.db "Test test oj oj oj rabotaet ojjj"
	.db "ISTOK IDU SNMP server v.20130915"
;	.db "he he... old board here yyy y yy"
	.db "Model, Year, Serial number (3 b)"
	.db "IP Addr (4 b), Subnet mask (4 b)"
	.db "Request for Simple Check        "
	.db "Reply for Simple Check      [RO]"
	.db "Main control Request / Reply    "
	.db "Temperature, (deg. C) x 16  [RO]"
	.db "Unique Serial number        [RO]"
.endif
.ifdef snmp_floks
;	.db "OSCaR AVR SNMP module. Version  "
	.db "FLOKS ODU SNMP server v.20131007"
	.db "Serial number                   "
	.db "IP Addr (4 b), Subnet mask (4 b)"
	.db "Request for Simple Check        "
	.db "Reply for Simple Check          "
	.db "Main control Request/Reply [R/W]"
	.db "Unique Serial number            "
	.db "TX AGC level, 1/100 volts       "
	.db "RX AGC level, 1/100 volts       "
	.db "Temperature #0 (deg. C) x 16    "
;	.db "Hardware ready (0=Fail, 1=Ready)"
	.db "Temperature #1 (deg. C)         "
	.db "Heater turned on (0=OFF, 1=ON)  "
;	.db "Channel # (0=manual)       [R/W]"
;	.db "Output power, -dB(max)     [R/W]"
	.db "Uptime, 1/100 s                 "
	.db " (reserved)                     "
	.db " (reserved)                     "
;	.db "VCO Lock bits xxxxDCBA, xxxxDxxA"
;	.db "VCO-A multiplier                "
;	.db "VCO-B multiplier      (optional)"
;	.db "VCO-C multiplier      (optional)"
;	.db "VCO-D multiplier                "
;	.db " (reserved)                     "
;	.db " (reserved)                     "
.endif 

.ifdef snmp_smarthome
	.db "SMARTHOME SNMP server v.20140210"
	.db "Daughterboard / model / function"
	.db "IP Addr (4 b), Subnet mask (4 b)"
	.db "Inputs bits0-3, outputs bits4-7 "
	.db "Temperature, (deg. C) x 16      "
	.db "Unique Serial number            "
	.db "Rotary Encoder Delta (-31...31) "
	.db "IR tx/rx (max 127 bytes)        "
	.db "Servo PWM ch.0 (0..254), 255=Off"
	.db "Servo PWM ch.1 (0..254), 255=Off"
.endif

.endif ; snmp

;	jmp	readmultiplepackets




; we don't need to receive anything
.ifdef matrix_keyboard
; just return
wrongpkt:
    jmp    readmultiplepackets
.endif ; matrix_keyboard


; Done processing packet in for different boards.

    jmp    readmultiplepackets

    jmp    readmultiplepackets


;----------------------------------
waitforbuffer:
    ldi    r16, low(S0_TX_FSR)
    ldi    r17, high(S0_TX_FSR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read
    cp    r16, r03    ; here r16=0x20
    brlo    waitforbuffer
    brne    bufok        ; greater than
    rcall    w5100read
    cp    r16, r02    ; here r16=0x0
    brlo    waitforbuffer
bufok:
    ret


; ------------------------------------
.ifdef additional
; display decimal number in up to five digits (0-65535)
; leading zeroz can be removed
; in = r24+r25
wdecimal:    ; full 0-5 digits
    clt    ; leading zeros remove
    ldi    r16, '0'
www40:
    subi    r24, low(10000)
    sbci    r25, high(10000)
    brlo    www41
    inc    r16
    set
    rjmp    www40
www41:
    subi    r24, 256-low(10000)
    sbci    r25, 255-high(10000)    ; its strange... but work
    brtc    www42
    rcall    wchar    ;  r16
www42:
    ldi    r16, '0'
www30:
    subi    r24, low(1000)
    sbci    r25, high(1000)
    brlo    www31
    inc    r16
    set
    rjmp    www30
www31:
    subi    r24, 256-low(1000)
    sbci    r25, 255-high(1000)    ; same strange...
    brtc    www32
    rcall    wchar    ;  r16
www32:

www33:
    ldi    r16, '0'
www2:
    subi    r24, low(100)
    sbci    r25, high(100)
    brlo    www1
    inc    r16
    set
    rjmp    www2
www1:
    subi    r24, -100    ; add 100
    brtc    www11
    rcall    wchar    ;  r16

; here only r24 uses...
www11:
    ldi    r16, '0'
www4:
    subi    r24, 10
    brlo    www3
    inc    r16
    set
    rjmp    www4
www3:
    subi    r24, -10-'0'    ; addi 10 + '0' butt addi not exist
    brtc    www12
    rcall    wchar
www12:
    mov    r16, r24
    rcall    wchar
    ret
.endif

;.ifdef SNI
.ifdef serial_setup
; changes r16
whexword:        ; write hex r24:r25
;    push    r24
    ldi    r16, '0'
    rcall    wchar
    ldi    r16, 'x'
    rcall    wchar
    mov    r16, r25
    rcall    whexbyte
    mov    r16, r24
;    pop    r24
whexbyte:        ; use r16
    push    r16
    swap    r16
    rcall    whexdigit
    pop    r16
whexdigit:
    andi    r16, 0b00001111
    subi    r16, 256-'0'
    cpi    r16,'9'+1
    brlo    whe1
    subi    r16, 256-('a'-'9'-1)
whe1:
    rcall    wchar
    ret
.endif


; --------------------------
w5100wr:
	push	r18
    ldi    r18, 255
    out    ddra, r18
	pop	r18
    ret

w5100rd:
	push	r18
    ldi    r18, 0
    out    ddra, r18
	pop	r18
    ret

w5100outmode:
    rcall    w5100wr
    cbi    w5100ctrlport, A0bit
    cbi    w5100ctrlport, A1bit
    out    porta, r16
    cbi    w5100ctrlport, CSbit
    cbi    w5100ctrlport, WRbit
nop
nop
    sbi    w5100ctrlport, WRbit
    sbi    w5100ctrlport, CSbit
    ret

w5100outaddr:
    rcall    w5100wr
    sbi    w5100ctrlport, A0bit
    cbi    w5100ctrlport, A1bit
    out    porta, r17
    cbi    w5100ctrlport, CSbit
    cbi    w5100ctrlport, WRbit
nop
nop
    sbi    w5100ctrlport, WRbit
    sbi    w5100ctrlport, CSbit

    cbi    w5100ctrlport, A0bit
    sbi    w5100ctrlport, A1bit
    out    porta, r16
    cbi    w5100ctrlport, CSbit
    cbi    w5100ctrlport, WRbit
nop
nop
    sbi    w5100ctrlport, WRbit
    sbi    w5100ctrlport, CSbit
    ret

w5100outdata:
    sbi    w5100ctrlport, A0bit
    sbi    w5100ctrlport, A1bit
    out    porta, r16
    cbi    w5100ctrlport, CSbit
    cbi    w5100ctrlport, WRbit
nop
nop
    sbi    w5100ctrlport, WRbit
    sbi    w5100ctrlport, CSbit
    ret

w5100read:    ; dont forget to use  'w5100rd'  before
    sbi    w5100ctrlport, A0bit
    sbi    w5100ctrlport, A1bit
    cbi    w5100ctrlport, CSbit
    cbi    w5100ctrlport,  RDbit
    nop    ; don't remove
nop

;sbi ledTCPCONport, ledTCPCONbit
;df: rjmp df


    in    r16, pina
    sbi    w5100ctrlport,  RDbit
    sbi    w5100ctrlport, CSbit
    ret


;txterr1:
;.db "Error: No TCP connection or No link.",13,10,0,0

; -----------------------------------
int_timer0_ovf:
    cbi    ledRDYport, ledRDYbit
.ifdef udp
    sbi    ledTCPCONport, ledTCPCONbit ; test?...
.endif

.ifdef rotary_encoder
; test:	inc	r01	; may be uninitialized
	push	r18
	push	r17
	push	r16
; r01 contains previous encoder two bits and 6-bit result:
; bits 0 & 1 are prev bits; bits 2-7 is result. (should be signed when used as result).
; hope we use pullups.
	in	r16, smarthomeIOportin	; bit0 and bit1 are encoder inputs.
	andi	r16, 0b00000011
	mov	r17, r16	; save
	bst	r01, 0
	bld	r16, 2	; prev. bit 0
	bst	r01, 1
	bld	r16, 3	; prev. bit 1
; get current result (delta) value for compare for limits
	mov	r18, r01
	lsr	r18
	lsr	r18	
; now search for known phase changes which mean atomic rotations.
	cpi	r16, 0b00000001
	breq	rot_cw
	cpi	r16, 0b00000111
	breq	rot_cw
	cpi	r16, 0b00001110
	breq	rot_cw
	cpi	r16, 0b00001000
	breq	rot_cw
	cpi	r16, 0b00000100
	breq	rot_ccw
	cpi	r16, 0b00001101
	breq	rot_ccw
	cpi	r16, 0b00001011
	breq	rot_ccw
	cpi	r16, 0b00000010
	breq	rot_ccw
; here is no rotation detected. Still need to save new encoder state,
; because it may be not initialized yet, or was double step.	
	bst	r17, 0	; save new encoder state
	bld	r01, 0
	bst	r17, 1
	bld	r01, 1
	rjmp	no_rot
rot_cw:
	ldi	r16, 1
	cpi	r18, 31	; max
	breq	cont
	inc	r01	; this don't touches bits 0 & 1
	inc	r01
	inc	r01
	inc	r01	; bits 0 & 1 here should remains same.
	rjmp	cont
rot_ccw:
	ldi	r16, -1
	cpi	r18, 64-31	; min (it's negative if we use only 6 bits)
	breq	cont
	dec	r01
	dec	r01
	dec	r01
	dec	r01
	rjmp	cont
cont:
	mov	r18, r16
	bst	r17, 0	; save new encoder state
	bld	r01, 0
	bst	r17, 1
	bld	r01, 1

.ifdef snmptrap
; when rotation detect, send snmp trap (snmptrap)
	ldi	r16, low(S0_DIPR)	; dest addr and dest port.
	ldi	r17, high(S0_DIPR)
	rcall	w5100outaddr
	rcall    w5100rd    ; port dir. change
	rcall    w5100read
	cpi	r16, 0
	breq	still_no_have_requester_addr
	rcall    w5100read
	cpi	r16, 0
	breq	still_no_have_requester_addr
	rcall    w5100read
	cpi	r16, 0
	breq	still_no_have_requester_addr
	rcall    w5100read
	cpi	r16, 0
	breq	still_no_have_requester_addr

	ldi	r16, low(S0_DPORT)
	ldi	r17, high(S0_DPORT)
	rcall	w5100outaddr
	ldi	r16, 0
	rcall	w5100outdata
	ldi	r16, 162
	rcall	w5100outdata
	rjmp	snmptrap2
	
still_no_have_requester_addr:
	jmp	still_no_have_requester_addr_


snmptrap2:
.equ trappktsz=57
	ldi	r28, low(txbuf)
	ldi	r29, high(txbuf)
	ldi	r24, trappktsz ; pkt sz
	ldi	r25, 0

	ldi	r16, 0x30
	st	y+, r16
	ldi	r16, trappktsz-2
	st	y+, r16
	ldi	r16, 0x02
	st	y+, r16
	ldi	r16, 0x01
	st	y+, r16
	st	y+, r16
	ldi	r16, 0x04
	st	y+, r16
	ldi	r16, 0x06
	st	y+, r16
	ldi	r16, 'p'
	st	y+, r16
	ldi	r16, 'u'
	st	y+, r16
	ldi	r16, 'b'
	st	y+, r16
	ldi	r16, 'l'
	st	y+, r16
	ldi	r16, 'i'
	st	y+, r16
	ldi	r16, 'c'
	st	y+, r16
	ldi	r16, 0xa7 ; type: snmpv2-trap
	st	y+, r16
	ldi	r16, trappktsz-2-13	; length
	st	y+, r16
	ldi	r16, 0x02
	st	y+, r16
	ldi	r16, 0x04
	st	y+, r16
	ldi	r16, 55	; request-id
	st	y+, r16
	ldi	r16, 56
	st	y+, r16
	ldi	r16, 57
	st	y+, r16
	ldi	r16, 58
	st	y+, r16
	ldi	r16, 0x02
	st	y+, r16
	ldi	r16, 0x01
	st	y+, r16
	ldi	r16, 0
	st	y+, r16
	ldi	r16, 0x02
	st	y+, r16
	ldi	r16, 0x01
	st	y+, r16
	ldi	r16, 0
	st	y+, r16

	ldi	r16, 0x30
	st	y+, r16
	ldi	r16, trappktsz-2-13-14	; length
	st	y+, r16

	ldi	r16, 0x30
	st	y+, r16
	ldi	r16, 		15	; length
	st	y+, r16
	ldi	r16, 0x06
	st	y+, r16
	ldi	r16, 0x0a
	st	y+, r16
	ldi	r16, 0x2b
	st	y+, r16
	ldi	r16, 6
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 6
	st	y+, r16
	ldi	r16, 3
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 4
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 0
	st	y+, r16

	ldi	r16, 6
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 0
	st	y+, r16

	ldi	r16, 0x30
	st	y+, r16
	ldi	r16, 		9	; length
	st	y+, r16
	ldi	r16, 6
	st	y+, r16
	ldi	r16, 1
	st	y+, r16
	ldi	r16, 0
	st	y+, r16


;	ldi	r16, 0x04	; type - string
	ldi	r16, 0x02	; type - signed int
	st	y+, r16
	ldi	r16, 		4	; length
;	ldi	r16, 		1	; length
	st	y+, r16
	ldi	r17, -1
	cpi	r18, -1
	breq	sn2
	ldi	r17, 0
sn2:
	st	y+, r17
	st	y+, r17
	st	y+, r17
	st	y+, r18


	rcall    tx_packet_data

; nothing to be send because not have address to send.
still_no_have_requester_addr_:

.endif

no_rot:
	pop	r16
	pop	r17
	pop	r18
.endif


.ifdef autosend

.ifdef aura_deprecated
; test for connection open! - but works even without it.

; timer0 disable here??

    inc    r00        ; may be uninitialized
    mov    r16, r00
    cpi    r16, 7    ; timer overflows q'ty
    brne    au1
; now r00 may be used. but don't forget to zero it before return.

ldi    r28, low(txbuf)
ldi    r29, high(txbuf)
ldi    r24,0 ; pkt sz
ldi    r25,1

ldi r16, 254
mov r00, r16

au2:
;ldi r16, 0x55
in r16, aura0pin
andi r16, 0x0f
subi r16, 256-'0'
st y+, r16

; delay
; hope r17 can be used??
;    ldi    r17, 1 ; agjust
;au4:
    ldi    r16, 0
au3:
    nop
    nop
    dec    r16
    brne    au3
;    dec    r17
;    brne    au4


dec r00
brne au2

ldi r16, 13
st y+, r16
ldi r16, 10
st y+, r16

    rcall    tx_packet_data
; timer0 enable here??
au1:
.endif ;aura

.ifdef matrix_keyboard
; no neet test for connection open - due to it is multicast,
; so no TCP connection.
    ldi    r28, low(mkstate)
    ldi    r29, high(mkstate)
    ldi    r18, 0    ; row #

    rcall    mk_findfirstchangedbit
; moved after keys detection.
; due to keyboard matrix have capacitance, best time to
; test for key pressed in current row - it just before switching to next row
; allowing bits to charge and be stable.
    sbi    mkout0port, mkout0bit0 ; prepare next row (only one, active low)
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit1

    rcall    mk_findfirstchangedbit
    sbi    mkout0port, mkout0bit1
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit2

    rcall    mk_findfirstchangedbit
    sbi    mkout0port, mkout0bit2
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit3

    rcall    mk_findfirstchangedbit
    sbi    mkout0port, mkout0bit3
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit4

    rcall    mk_findfirstchangedbit
    sbi    mkout0port, mkout0bit4
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit5

    rcall    mk_findfirstchangedbit
    sbi    mkout0port, mkout0bit5
    cpi    r19, 8
    brne    mk_key
    cbi    mkout1port, mkout1bit6

    rcall    mk_findfirstchangedbit
    sbi    mkout1port, mkout1bit6
    cpi    r19, 8
    brne    mk_key
    cbi    mkout1port, mkout1bit7

    rcall    mk_findfirstchangedbit
    sbi    mkout1port, mkout1bit7
    cpi    r19, 8
    brne    mk_key
    cbi    mkout0port, mkout0bit0

; no key changes detected...
    rjmp    mk_done

mk_key:
    rjmp    mk_key2
; possible ways:
;1) compare only one bit in cycle
;2) compare all bits one-by-one and sent packet for each changed bit in one cycle.
;(problematic - many push/pop registers need).
mk_findfirstchangedbit:
    nop    ; pre-charge row capacitance
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    in    r16, mkinpin    ; current
    ld    r17, y        ; old, stored in ram for current row
;mov r23, r17
    ldi    r19, 0 ; bit number and part of scancode
; keycode in r19 if r19 = 0..7, r19=8 - no state change.
; flag T set = keypress, T=0 - key release.
    ldi    r21, 0b00000001 ; test bit pattern

mkf1:
    mov    r22, r21
    and    r22, r16
    brne    mkf2

; currently key pressed, test if it was pressed before
    mov    r22, r21
    and    r22, r17
    brne    mkf3

; was pressed before. so no chanke in key state. do nothing. check next bit/key in row.
    rjmp    mkf_nextbit

; was unpressed before (1), but now is pressed (0).
; so fire key press.
mkf3:
; first, we need to remember that we know this bit/key change
; for not to fire it next time. so we must save this only bit in r17.
    eor    r17, r21
    st    y, r17
    set    ; set T flag
    rjmp    mkf_keydetect

; currently key unpressed, test if it was pressed before
mkf2:
    mov    r22, r21
    and    r22, r17
    breq    mkf4
; here no chanke in key state. do nothing. check next bit/key in row.
    rjmp    mkf_nextbit

; was pressed before (0), but now is unpressed (1).
; so fire key release.
mkf4:
; first, we need to remember that we know this bit/key change
; for not to fire it next time. so we must save this only bit in r17.
    eor    r17, r21
    st    y, r17
    clt    ; clear T flag
    rjmp    mkf_keydetect

mkf_nextbit:
    lsl    r21 ; shift detecting pattern
    inc    r19
    cpi    r19, 8
    brne    mkf1

    inc    r18
    adiw    r28, 1

mkf_keydetect:
    ret

mk_key2:
; take scancode.
; here we hope r19=0..7 and is valid column code.
; r18 = row code.
; in your keyboard layout and wire order, you must correct this
; to get needed scancodes.
    andi    r19, 0b00001111
    andi    r18, 0b00001111
    rol    r18
    rol    r18
    rol    r18
    add    r19, r18
    ldi    r17, 103 ; midi trial-and-error agjust
    sub    r17, r19
; done: r17 = scancode. (and here is also just midi note).


; sent 3-byte midi packet.
    ldi    r28, low(txbuf)
    ldi    r29, high(txbuf)
;    ldi    r24,3 ; pkt sz
    ldi    r24,12 ; pkt sz
    ldi    r25,0
ldi    r30, low(mkstate)
ldi    r31, high(mkstate)
; 0x90 note 0x7f - note on;
; 0x80 note 0x00 - note off.
ldi    r16, 0x80
bld    r16, 4    ; depend on flag T, 0x80 or 0x90 - key pressed/released
    st    y+, r16

    st    y+, r17    ; keycode

    ldi    r16, 0x7f
;mov r16, r23
    st    y+, r16

ldi    r16, 0x55
st    y+, r16

ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16
ld    r16, z+
st    y+, r16


    rcall    tx_packet_data
    rjmp    mk_done

mk_done:
.endif ; matrix_keyboard

.endif ;autosend

    reti	; int_timer0_ovf

;------------------------------------
int_timer1_ovf:
    cbi    ledRDYport, ledRDYbit
;.ifdef udp ;;; why? timer1 not work when udp ?!
;    sbi    ledTCPCONport, ledTCPCONbit
;.endif


; if socket closed, initially or after close connection, we need to (re)open
; don't forget to disable this timer in main rx/tx and other long procedures.
;.ifdef multicast
.ifdef udp
; nothing
.else
    ldi    r16, low(S0_SR)
    ldi    r17, high(S0_SR)
    rcall    w5100outaddr
    rcall    w5100rd
    rcall    w5100read

;    cpi    r16, SR_SOCK_CLOSED
;    brne    ttt2

    cpi    r16, SR_SOCK_ESTABLISHED
    breq    ttt2

    rcall    tcpopen
    rjmp    ttt3

ttt2:

.ifdef SNI
; if socket open too long time, it may be bad and indicate dead connection
; if you connect via router, because when external connection drops suddenly,
; cheap routers not reset their internal connection with our device,
; then we unable to connect anymore due to port is busy.
; so try to calculate some time when user input characters not arrives,
; then close IP connection.
; - OR -
; you go away and not close telnet session... you then can't use it from
; other place. So again need to reset when inactive (no input in telnet)
; for some time.

; r00 - number of timer1 timeouts.

    inc    r00
    mov    r16, r00
    cpi    r16, 255 ; approx. (seconds) Modify this.
    brne    ttt4

;    cbi    ledTCPCONport, ledTCPCONbit
;    rcall    tcpclose
    rcall    tcpdisconnect
ttt4:
.endif

ttt3:
.endif
    reti



timer0_int_enable:
    in    r16, timsk
    ori    r16, 0b00000001    ; toie0
td:
    out    timsk, r16
    ret
timer0_int_disable:
    in    r16, timsk
    andi    r16, 0b11111110
;    out    timsk, r16
;    ret
    rjmp td
timer1_int_enable:
    in    r16, timsk
    ori    r16, 0b00010000    ; ocie1a
;    out    timsk, r16
;    ret
    rjmp td

timer1_int_disable:
    in    r16, timsk
    andi    r16, 0b11101111
;    out    timsk, r16
;    ret
    rjmp td

; using timer2 added 03-03-2014, maybe it will work for IR transmit.
; not need interrupts, just need on-off timer ?
;timer2_....:		
;    in    r16, timsk
;    andi    r16, 0b11111110
;    out    timsk, r16
;    ret
;    rjmp td



; --------------------------------------
; Wiznet w5100 in indirect mode, TCP telnet serial network interface.
.equ    MR = 0x0000    ; MR (Mode Register) [R/W] [0x0000] [0x00]
.equ    GWR = 0x0001    ; GWR (Gateway IP Address Register) [R/W] [0x0001 – 0x0004] [0x00]
.equ    SUBR = 0x0005    ; SUBR (Subnet Mask Register) [R/W] [0x0005 – 0x0008] [0x00]
.equ    SHAR = 0x0009    ; SHAR (Source Hardware Address Register) [R/W] [0x0009 – 0x000E] [0x00]
.equ    SIPR = 0x000f    ; SIPR (Source IP Address Register) [R/W] [0x000F – 0x0012] [0x00]
;.equ    IR = 0x0015    ; IR (Interrupt Register) [R] [0x0015] [0x00]
;7    6    5    4    3    2    1    0
;CONFLICT UNREACH PPPoE Reserved S3_INT S2_INT S1_INT S0_INT
.equ    S0_IR = 0x0402    ;Sn_IR (Socket n Interrupt Register) [R] [0x0402, 0x0502, 0x0602, 0x0702] [0x00]
.equ INTERRUPT_RECV_BIT = 2
.equ INTERRUPT_SEND_OK_BIT = 4
.equ INTERRUPT_CON_BIT = 0
.equ INTERRUPT_DISCON_BIT = 1
.equ INTERRUPT_TIMEOUT_BIT = 3
.equ    IMR = 0x0016    ; IMR (Interrupt Mask Register) [R/W] [0x0016] [0x00]
.equ    RMSR = 0x001A    ; RMSR(RX Memory Size Register) [R/W] [0x001A] [0x55]
.equ    TMSR = 0x001B    ; TMSR(TX Memory Size Register) [R/W] [0x001B] [0x55]
.equ    S0_DIPR = 0x040C;Sn_DIPR (Socket n Destination IP Address Register) [R/W] [0x040C–0x040F, 0x050C–0x050F, 0x060C–0x060F, 0x070C–0x070F] [0x00]
;Sn_DPORT (Socket n Destination Port Register) [R/W] [0x0410–0x0411, 0x0510–0x0511,
;0x0610–0x0611, 0x0710–0x0711] [0x00]
.equ    S0_MR = 0x0400    ;Sn_MR (Socket n Mode Register) [R/W] [0x0400, 0x0500, 0x0600, 0x0700] [0x00] 2
.equ    S0_PORT = 0x0404;Sn_PORT (Socket n Source Port Register) [R/W]
;[0x0404–0x0405, 0x0504–0x0505, 0x0604–0x0605, 0x0704–0x0705] [0x00]
.equ    S0_CR = 0x0401    ;Sn_CR (Socket n Command Register) [R/W] [0x0401, 0x0501, 0x0601, 0x0701] [0x00]

.equ    S0_DHAR = 0x0406
.equ    S0_DPORT = 0x0410

.equ    CR_OPEN = 0x01
.equ    CR_LISTEN = 0x02
.equ    CR_CONNECT = 0x04
.equ    CR_DISCON = 0x08
.equ    CR_CLOSE = 0x10
.equ    CR_RECV = 0x40
.equ    CR_SEND = 0x20

.equ    S0_SR = 0x0403
;Sn_SR (Socket n Status Register) [R] [0x0403, 0x0503, 0x0603, 0x0703] [0x00]
.equ    SR_SOCK_UDP = 0x22
.equ    SR_SOCK_INIT = 0x13
.equ    SR_SOCK_LISTEN = 0x14
.equ    SR_SOCK_ESTABLISHED = 0x17
.equ    SR_SOCK_CLOSE_WAIT = 0x1C
.equ    SR_SOCK_CLOSED = 0

.equ    S0_RX_RSR = 0x0426;Sn_RX_RSR (RX Received Size Register) [R] [0x0426-0x0427, 0x0526-0x0527, 0x0626-0x0627, 0x0726-0x0727] [0x0000]
.equ    S0_RX_RD = 0x0428 ;Sn_RX_RD (Socket n RX Read Pointer Register) [R/W] [0x0428-0x0429,  0x0528-0x0529, 0x0628-0x0629, 0x0728-0x0729] [0x0000]
.equ    S0_TX_FSR = 0x0420;Sn_TX_FSR (Socket n TX Free Size Register) [R] [0x0420-0x0421, 0x0520-0x0521, 0x0620-0x0621, 0x0720-0x0721] [0x0800]
.equ    S0_TX_RR = 0x0422 ;Sn_TX_RR (Socket n TX Read Pointer Register) [R] [0x0422-0x0423, 0x0522-0x0523, 0x0622-0x0623, 0x0722-0x0723] [0x0000]
.equ    S0_TX_WR = 0x0424 ;Sn_TX_WR (Socket n TX Write Pointer Register) [R/W] [0x0424-0x0425, 0x0524-0x0525, 0x0624-0x0625, 0x0724-0x0725] [0x0000]
.equ    S0_RX_BASE = 0x6000
.equ    S0_RX_LENGTH = 0x2000
.equ    S0_TX_BASE = 0x4000
.equ    S0_TX_LENGTH = 0x2000



; SNMP record type:
; http://searchcode.com/codesearch/view/6142910
;  05 - NULL, (trailing with zero i.e. next byte means zero length)
;  04 - string,
;  06 - OID, 
;  0x43 - timeticks (variable length 1 to 4 bytes),
;  02 - integer32 (variable length 1 to 4 bytes), MSB FIRST! or even length=0. then value assumed 0.
;  0x42 - gauge32 (seen as 4-byte with end fill of zeroes),
;  0x40 - ip address 4 bytes,
;
;  0x82 0x00 - end of MIB list!

; END.

; sudo apt-get remove brltty
; sudo chmod 666 /dev/ttyS0

; sudo avrdude -p m32 -c usbasp -U eeprom:r:eep.bin:r
; sudo avrdude -p m32 -c usbasp -U eeprom:w:eep.bin
; sudo avrdude -p m32 -c usbasp -U flash:w:w5100uni.hex
; sudo avrdude -p m16 -c usbasp -U flash:w:w5100uni.hex

;sudo avrdude -p m32 -c usbasp -U hfuse:r:hf.hex:i
; modify to 14.7456 external xtal
; sudo avrdude -p m32 -c usbasp -U hfuse:w:0xc1:m
; sudo avrdude -p m32 -c usbasp -U lfuse:w:0xed:m
; sudo avrdude -p m16 -c usbasp -U hfuse:w:0xc1:m
; sudo avrdude -p m16 -c usbasp -U lfuse:w:0xed:m

; how to get source of bin file!
; hexdump rf8.fnt -e '16/1 "0x%02x, " "\n"'