;
; i0.3.IO.44.thtpv4.asm
; i0 three-wire I/O node demonstration code
; IPv4 version
; 2-16-2 encoding
;
; Neil Gershenfeld
; CBA MIT 11/30/08
;
; (c) Massachusetts Institute of Technology 2008
; Permission granted for experimental and personal use;
; license for commercial sale available from MIT.
;
.include "tn44def.inc"
;
; definitions
;
.equ Web_port = 80 ; Web server port
.equ set_source_address_port = 1000 ; port to set board's source address
.equ set_destination_address_port = 1001 ; port to set board's destination address
.equ toggle_port = 1002 ; port to toggle the light
.equ set_destination_flag = 1 ; status flag for setting destination address
.equ set_source_flag = 2 ; status flag for setting source address
.equ click_pin = PA0 ; i0 click pin
.equ click_count = 5 ; loop count to wait during click
.equ settle_count = 5 ; loop count to wait for click to settle
.equ delay_count = 10 ; loop count to wait between clicks
.equ char_delay_count = 15 ; loop count for character delay
.equ csma_count = 20 ; loop count for CSMA check
.equ button_bit = 5 ; button bit
.equ button_pin = PA5 ; button pin
.equ button_gnd = PA4 ; button ground
.equ mosfet_pin = PA7 ; MOSFET pin
.equ LED_pin = PA2 ; LED pin
.equ LED_gnd = PA1 ; LED ground
.equ END = 192 ; SLIP definitions
.equ ESC = 219 ; "
.equ ESC_END = 220 ; "
.equ ESC_ESC = 221 ; "
.equ eeprom_source_address = 0 ; EEPROM addresses
.equ eeprom_destination_address = eeprom_source_address + 4 ; "
;
; registers
;
.def zero = R1 ; 0
.def one = R2 ; 1
.def double_count = R3 ; double loop count
.def triple_space = R4 ; triple click spacing
.def check_lo = R5 ; lo checksum accumulator
.def check_hi = R6 ; hi checksum accumulator
.def check_carry = R7 ; checksum carry accumulator
.def bit_count = R16 ; bit counter
.def byte_count = R17 ; byte counter
.def txbyte = R18 ; transmit byte
.def rxbyte = R19 ; receive byte
.def temp = R20 ; temporary storage
.def temp1 = R21 ; temporary storage
.def temp2 = R22 ; temporary storage
.def temp3 = R23 ; temporary storage
.def flags = R24 ; status flags
.def click_space = R25 ; click spacing
.def count = R26 ; loop counter (X low)
.def count_hi = R27 ; loop counter (X high)
; R28, 29 used for Y pointer
; R30, 31 used for Z pointer
;
; macros
;
; copy
;
.macro copy
;
; copy bytes between two memory locations
; copy destination, source
;
ldi zh, high(@1)
ldi zl, low(@1)
ld temp, z
ldi zh, high(@0)
ldi zl, low(@0)
st z, temp
.endmacro
;
; compare
;
.macro compare
;
; compare two memory locations
;
ldi zh, high(@1)
ldi zl, low(@1)
ld temp, z
ldi zh, high(@0)
ldi zl, low(@0)
ld temp1, z
cp temp, temp1
.endmacro
;
; compare_immediate
;
.macro compare_immediate
;
; compare memory location with a constant
;
ldi zh, high(@0)
ldi zl, low(@0)
ld temp, z
cpi temp, @1
.endmacro
;
; store_immediate
;
.macro store_immediate
;
; store immediate constant to memory
;
ldi temp, @1
sts @0, temp
.endmacro
;
; set_data
;
.macro set_data
;
; set Y registers to point to data
;
ldi yh, high(@0*2)
ldi yl, low(@0*2)
.endmacro
;
; putslip
;
.macro putslip
;
; putslip
; click char in txbyte, with SLIP mapping
;
ldi temp, END
cpse txbyte, temp
rjmp putslipchar
;
; END char
;
mov temp, txbyte
ldi txbyte, ESC
rcall putclick
rcall char_delay
ldi txbyte, ESC_END
rcall putclick
rcall char_delay
mov txbyte, temp
rjmp endputslip
ldi temp, ESC
cpse txbyte, temp
rjmp putslipchar
;
; ESC char
;
mov temp, txbyte
ldi txbyte, ESC
rcall putclick
rcall char_delay
ldi txbyte, ESC_ESC
rcall putclick
rcall char_delay
mov txbyte, temp
rjmp endputslip
putslipchar:
;
; ordinary char, no escape needed
;
rcall putclick
rcall char_delay
endputslip:
.endmacro
;
; read_eeprom
;
.macro read_eeprom
;
; read EEPROM location to register
;
read_eeprom_loop: ; make sure EEPROM is ready for writing
sbic EECR, EEPE
rjmp read_eeprom_loop
ldi temp, high(@1)
out EEARH, temp
ldi temp, low(@1)
out EEARL, temp
sbi EECR, EERE
in @0, EEDR
.endmacro
;
; write_eeprom
;
.macro write_eeprom
;
; write register to EEPROM
;
write_eeprom_loop: ; make sure EEPROM is ready for writing
sbic EECR, EEPE
rjmp write_eeprom_loop
cbi EECR, EEPM1
cbi EECR, EEPM0
ldi temp, high(@0)
out EEARH, temp
ldi temp, low(@0)
out EEARL, temp
out EEDR, @1
sbi EECR, EEMPE
sbi EECR, EEPE
.endmacro
;
; write_sram_to_eeprom
;
.macro write_sram_to_eeprom
;
; write SRAM location to EEPROM
;
write_sram_to_eeprom_loop: ; make sure EEPROM is ready for writing
sbic EECR, EEPE
rjmp write_sram_to_eeprom_loop
cbi EECR, EEPM1
cbi EECR, EEPM0
ldi temp, high(@0)
out EEARH, temp
ldi temp, low(@0)
out EEARL, temp
ldi zh, high(@1)
ldi zl, low(@1)
ld temp, z
out EEDR, temp
sbi EECR, EEMPE
sbi EECR, EEPE
.endmacro
;
; code segment
;
.cseg
.org 0
rjmp reset
;
; init_packet
; initialize outgoing packet in SRAM
;
init_packet:
.equ ip_header_size = 20
.equ ip_header_size_before_checksum = 10
.equ ip_header_size_after_checksum = 8
.equ udp_header_size = 8
.equ outgoing_ip_start = SRAM_START;
.equ outgoing_ip_length = outgoing_ip_start + 2
.equ outgoing_ip_checksum = outgoing_ip_start + 10
.equ outgoing_source_address = outgoing_ip_start + 12
.equ outgoing_destination_address = outgoing_ip_start + 16
.equ outgoing_udp_start = outgoing_ip_start + 20
.equ outgoing_source_port = outgoing_udp_start
.equ outgoing_destination_port = outgoing_udp_start + 2
.equ outgoing_udp_length = outgoing_udp_start + 4
ldi zl, low(outgoing_ip_start)
ldi zh, high(outgoing_ip_start)
;
; IP
;
ldi temp, 0x45 ; version = 4 (4 bits), header length = 5 32-bit words (4 bits)
st z+, temp
ldi temp, 0 ; type of service
st z+, temp
ldi temp, 0 ; packet length high byte (to be calculated)
st z+, temp
ldi temp, 0 ; packet length low byte (to be calculated)
st z+, temp
ldi temp, 0 ; identification (high byte)
st z+, temp
ldi temp, 0 ; identification (low byte)
st z+, temp
ldi temp, 0 ; flag (3 bits), fragment offset (13 bits) (high byte)
st z+, temp
ldi temp, 0 ; flag (3 bits), fragment offset (13 bits) (low byte)
st z+, temp
ldi temp, 255 ; time to live
st z+, temp
ldi temp, 17 ; protocol = 17 for UDP
st z+, temp
ldi temp, 0 ; header checksum (to be calculated)
st z+, temp
ldi temp, 0 ; header checksum (to be calculated)
st z+, temp
read_eeprom temp, eeprom_source_address ; source address byte 1
st z+, temp
read_eeprom temp, eeprom_source_address+1 ; source address byte 2
st z+, temp
read_eeprom temp, eeprom_source_address+2 ; source address byte 3
st z+, temp
read_eeprom temp, eeprom_source_address+3 ; source address byte 4
st z+, temp
read_eeprom temp, eeprom_destination_address ; destination address byte 1
st z+, temp
read_eeprom temp, eeprom_destination_address+1 ; destination address byte 2
st z+, temp
read_eeprom temp, eeprom_destination_address+2 ; destination address byte 3
st z+, temp
read_eeprom temp, eeprom_destination_address+3 ; destination address byte 4
st z+, temp
;
; UDP
;
ldi temp, 0 ; source port
st z+, temp
ldi temp, 0 ; source port
st z+, temp
ldi temp, 0 ; destination port
st z+, temp
ldi temp, 0 ; destination port
st z+, temp
ldi temp, 0 ; payload length high byte (to be calculated)
st z+, temp
ldi temp, 0 ; payload length low byte (to be calculated)
st z+, temp
ldi temp, 0 ; payload checksum (not used)
st z+, temp
ldi temp, 0 ; payload checksum (not used)
st z+, temp
;
; null-terminated data messages
;
empty_message:
.db 0
on_message:
.db "HTTP/1.1 200 OK",13,10,"Content-Type: text/html",13,10,13,10,"
light is on",13,10,0
off_message:
.db "HTTP/1.1 200 OK",13,10,"Content-Type: text/html",13,10,13,10,"light is off",13,10,0
ret
;
; get_I0_packet
; read an I0 packet to SRAM following starting SLIP END character,
; removing SLIP mapping
;
get_packet:
.equ incoming_start = outgoing_ip_start + ip_header_size + udp_header_size
.equ incoming_source_address = incoming_start + 12
.equ incoming_destination_address = incoming_source_address + 4
.equ incoming_destination_port = incoming_destination_address + 6
;
; set Z to point to start of SRAM
;
ldi zl, low(incoming_start)
ldi zh, high(incoming_start)
clr byte_count
get_packet_mainloop:
;
; wait for a click
;
clr count
ldi count_hi, 1
get_packet_waitloop:
add count, one
adc count_hi, zero
breq get_packet_timeout ; time-out if loop count overflows
sbic PINA, click_pin ; check i0 pin for click
rjmp get_packet_waitloop
;
; read next byte
;
rcall getclick
;
; return if byte count overflows
;
inc byte_count
breq get_packet_timeout
;
; check for SLIP escape
;
cpi rxbyte, ESC
brne get_packet_store_byte
;
; found escape, read next character after next click
;
get_packet_waitloop1:
sbic PINA, click_pin ; check i0 pin for click
rjmp get_packet_waitloop1
rcall getclick
cpi rxbyte, ESC_ESC
brne get_packet_END
;
; store an ESC
;
ldi rxbyte, ESC
st z+, rxbyte
rjmp get_packet_mainloop
get_packet_END:
;
; store an END
;
ldi rxbyte, END
st z+, rxbyte
rjmp get_packet_mainloop
;
; store byte
;
get_packet_store_byte:
st z+, rxbyte
;
; go back for next byte if not END
;
ldi temp, END
cpse rxbyte, temp
rjmp get_packet_mainloop
ret
get_packet_timeout:
clr byte_count
ret
;
; click_duration
; delay during click
;
click_duration:
ldi temp, click_count
click_duration_loop:
dec temp
brne click_duration_loop
ret
;
; click_delay
; delay between clicks
;
click_delay:
ldi temp, delay_count
click_delay_loop:
dec temp
brne click_delay_loop
ret
;
; putclick
; send char in txbyte clicks
;
putclick:
ldi bit_count, 8
sec; set start bit
;
; set click pin to output
;
sbi DDRA, click_pin
;
; send start clicks
;
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
;
; send data clicks
;
putclick0:
lsr txbyte; get next bit
brcc putclick1 ; if carry set, send a 1 click
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
sbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
rjmp putclick2; otherwise ...
putclick1:
sbi PORTA, click_pin ; ... send a 0 click
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
putclick2:
dec bit_count; if not all bits sent
brne putclick0; send next bit
;
; send stop clicks
;
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
cbi PORTA, click_pin
rcall click_duration
sbi PORTA, click_pin
rcall click_delay
;
; set click pin to input with pull-up
;
cbi DDRA, click_pin
;
; return
;
ret
;
; getclick
; input an i0 byte following first click
;
getclick:
;
; delay for first click to settle
;
ldi count, settle_count
getclick_settle_start:
dec count
nop ; to even out timing for breq
brne getclick_settle_start
;
; time arrivial of second start click
;
ldi click_space, (settle_count+1) ; +1 for overhead
getclick_time_start:
inc click_space
breq getclick_timeout ; check for overflow
sbic PINA, click_pin ; check for click
rjmp getclick_time_start
mov triple_space, click_space
add triple_space, click_space
add triple_space, click_space
;
; decode data clicks
;
clr rxbyte
ldi bit_count, 8
getclick_bitloop:
;
; delay for click to settle
;
ldi count, settle_count
getclick_settle:
dec count
nop ; to even out timing for breq
brne getclick_settle
;
; time arrivial of next click
;
ldi count, settle_count
getclick_time:
inc count
breq getclick_timeout ; check for overflow
sbic PINA, click_pin ; check for click
rjmp getclick_time
;
; determine bit delay
;
mov double_count, count
add double_count, count
cp double_count, triple_space
brsh getclick_zero
;
; one bit
;
sec ; set carry
ror rxbyte ; shift in carry
;
; even out 0/1 timing
;
mov count, click_space
getclick_space:
dec count
nop ; to even out timing for breq
brne getclick_space
;
; decrement counter and output if byte received
;
dec bit_count
brne getclick_bitloop
rjmp getclick_end
getclick_zero:
;
; zero bit
;
clc ; clear carry
ror rxbyte ; shift in carry
;
; decrement counter and output if byte received
;
dec bit_count
brne getclick_bitloop
getclick_end:
;
; wait for stop clicks and return
;
getclick_end_0_up:
sbis PINA, click_pin
rjmp getclick_end_0_up
getclick_end_1_down:
sbic PINA, click_pin
rjmp getclick_end_1_down
getclick_end_1_up:
sbis PINA, click_pin
rjmp getclick_end_1_up
getclick_end_2_down:
sbic PINA, click_pin
rjmp getclick_end_2_down
getclick_end_2_up:
sbis PINA, click_pin
rjmp getclick_end_2_up
ret
getclick_timeout:
ldi rxbyte, 0
ret
;
; char_delay
; delay between characters
;
char_delay:
ldi temp, char_delay_count
char_delay_loop:
dec temp
brne char_delay_loop
ret
;
; packet_delay
; delay between packets
;
packet_delay:
ldi temp, 255
packet_delayloop:
ldi temp1, 255
packet_delayloop1:
dec temp1
brne packet_delayloop1
dec temp
brne packet_delayloop
ret
;
; print_packet
; send a packet, calculating header checksum and doing SLIP encoding
; Y registers point to data
;
print_packet:
;
; count data length and store in packet
;
mov zl, yl
mov zh, yh
clr count
clr count_hi
count_data_loop:
adiw count, 1
lpm temp, z+
cpi temp, 0
brne count_data_loop
sbiw count,1 ; don't count the null termination
adiw count, udp_header_size
sts outgoing_udp_length, count_hi
sts outgoing_udp_length+1, count
adiw count, ip_header_size
sts outgoing_ip_length, count_hi
sts outgoing_ip_length+1, count
;
; find the IP header checksum and store in packet
;
ldi zh, high(outgoing_ip_start)
ldi zl, low(outgoing_ip_start)
ldi count, ip_header_size
clr check_lo
clr check_hi
clr check_carry
ip_checksum_loop:
adiw zl, 1
ld temp, z
dec count
sbiw zl, 1
ld temp1, z
add check_lo, temp
adc check_hi, temp1
adc check_carry, zero
adiw zl, 2
dec count
brne ip_checksum_loop
add check_lo, check_carry
adc check_hi, zero
com check_lo
com check_hi
sts outgoing_ip_checksum, check_hi
sts outgoing_ip_checksum+1, check_lo
;
; CSMA check
;
print_packet_CSMA:
ldi temp, csma_count
print_packet_CSMA_loop:
sbis PINA, click_pin
rjmp print_packet_CSMA_delay
dec temp
brne print_packet_CSMA_loop
rjmp print_packet_CSMA_continue
print_packet_CSMA_delay:
ldi temp, csma_count
print_packet_CSMA_delay_loop:
dec temp
brne print_packet_CSMA_delay_loop
rjmp print_packet_CSMA
print_packet_CSMA_continue:
;
; send the packet
;
ldi txbyte, END ; SLIP start
rcall putclick
rcall char_delay
ldi zh, high(outgoing_ip_start)
ldi zl, low(outgoing_ip_start)
ldi count, (ip_header_size + udp_header_size)
print_header_loop: ; IP + UDP header
ld txbyte, z
putslip
adiw zl, 1
dec count
brne print_header_loop
mov zl, yl
mov zh, yh
print_data_loop: ; data
lpm txbyte, z+
cpi txbyte, 0
breq print_data_continue
putslip
rjmp print_data_loop
print_data_continue:
ldi txbyte, END ; SLIP end
rcall putclick
rcall char_delay
ret
;
; handle button actions
;
button_pressed:
;
; is there a pending set source packet?
;
sbrc flags, set_source_flag
rjmp button_pressed_set_source_address
;
; is there a pending set destination packet?
;
sbrc flags, set_destination_flag
rjmp button_pressed_set_destination_address
;
; is the destination address not set?
;
compare_immediate outgoing_destination_address, 255
breq button_pressed_send_set_destination
rjmp button_pressed_send_packet
;
; otherwise send a set destination packet
;
button_pressed_send_set_destination:
;
; blink the light to acknowledge
;
rcall blink
rcall blink
;
; set up and send set destination packet
;
store_immediate outgoing_source_port, high(set_destination_address_port)
store_immediate outgoing_source_port+1, low(set_destination_address_port)
store_immediate outgoing_destination_port, high(set_destination_address_port)
store_immediate outgoing_destination_port+1, low(set_destination_address_port)
set_data(empty_message)
rcall print_packet
ret
button_pressed_set_source_address:
;
; blink the light to acknowledge
;
rcall blink
rcall blink
;
; set source address to destination address from last received packet
;
copy outgoing_source_address, incoming_destination_address
copy outgoing_source_address+1, incoming_destination_address+1
copy outgoing_source_address+2, incoming_destination_address+2
copy outgoing_source_address+3, incoming_destination_address+3
;
; save source address to EEPROM
;
write_sram_to_eeprom eeprom_source_address, outgoing_source_address
write_sram_to_eeprom eeprom_source_address+1, outgoing_source_address+1
write_sram_to_eeprom eeprom_source_address+2, outgoing_source_address+2
write_sram_to_eeprom eeprom_source_address+3, outgoing_source_address+3
;
; clear flags and return
;
clr flags
ret
button_pressed_set_destination_address:
;
; blink the light to acknowledge
;
rcall blink
rcall blink
;
; set destination address to source address from last received packet
;
copy outgoing_destination_address, incoming_source_address
copy outgoing_destination_address+1, incoming_source_address+1
copy outgoing_destination_address+2, incoming_source_address+2
copy outgoing_destination_address+3, incoming_source_address+3
;
; save destination address to EEPROM
;
write_sram_to_eeprom eeprom_destination_address, outgoing_destination_address
write_sram_to_eeprom eeprom_destination_address+1, outgoing_destination_address+1
write_sram_to_eeprom eeprom_destination_address+2, outgoing_destination_address+2
write_sram_to_eeprom eeprom_destination_address+3, outgoing_destination_address+3
;
; clear flags and return
;
clr flags
ret
button_pressed_send_packet:
;
; blink the light to acknowledge
;
rcall blink
;
; set up and send toggle packet
;
store_immediate outgoing_source_port, high(toggle_port)
store_immediate outgoing_source_port+1, low(toggle_port)
store_immediate outgoing_destination_port, high(toggle_port)
store_immediate outgoing_destination_port+1, low(toggle_port)
set_data(empty_message)
rcall print_packet
ret
;
; blink the light
;
blink:
in temp, PORTA
ldi temp1, ((1 << LED_pin) | (1 << mosfet_pin))
eor temp, temp1
out PORTA, temp
rcall packet_delay
in temp, PORTA
ldi temp1, ((1 << LED_pin) | (1 << mosfet_pin))
eor temp, temp1
out PORTA, temp
rcall packet_delay
ret
;
; send the Web page
;
send_Web_page:
;
; blink the light to acknowledge
;
rcall blink
rcall blink
;
; set up and send Web page
;
store_immediate outgoing_source_port, high(Web_port)
store_immediate outgoing_source_port+1, low(Web_port)
store_immediate outgoing_destination_port, high(Web_port)
store_immediate outgoing_destination_port+1, low(Web_port)
sbic PORTA, LED_pin
rjmp Web_send_on
Web_send_off:
set_data(off_message)
rjmp Web_send_continue
Web_send_on:
set_data(on_message)
Web_send_continue:
rcall print_packet
ret
;
; toggle the light
;
toggle_light:
in temp, PORTA
ldi temp1, ((1 << LED_pin) | (1 << mosfet_pin))
eor temp, temp1
out PORTA, temp
ret
;
; main program
;
reset:
;
; set fuse low byte to 0x7E for 20 MHz resonator
;
; set clock divider to /1
;
ldi temp, (1 << CLKPCE)
ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
out CLKPR, temp
out CLKPR, temp1
;
; set stack pointer to top of RAM
;
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, low(RAMEND)
out SPL, temp
;
; init click pin for input with pull-up
;
sbi PORTA, click_pin
cbi DDRA, click_pin
;
; init button for input with pull-up
;
sbi PORTA, button_pin
cbi DDRA, button_pin
cbi PORTA, button_gnd
sbi DDRA, button_gnd
;
; init LED for output
;
cbi PORTA, LED_pin
sbi DDRA, LED_pin
cbi PORTA, LED_gnd
sbi DDRA, LED_gnd
;
; init MOSFET pin for output
;
cbi PORTA, mosfet_pin
sbi DDRA, mosfet_pin
;
; init registers
;
clr zero ; 0
clr one ; 1
inc one ; "
;
; set source address if not assigned
;
read_eeprom temp, eeprom_source_address
cpi temp, 255
brne source_address_assigned
source_address_not_assigned:
;
; turn on light, start counter, and wait for button to be pressed
;
sbi PORTA, LED_pin
clr temp1
clr temp2
clr temp3
source_address_not_assigned_loop:
add temp1, one
adc temp2, zero
adc temp3, zero
sbic PINA, button_bit
rjmp source_address_not_assigned_loop
;
; wait for button to be released
;
source_address_not_button_release:
sbis PINA, button_bit
rjmp source_address_not_button_release
;
; move address to EEPROM, acknowledge and turn off light
;
write_eeprom eeprom_source_address+3, temp1
write_eeprom eeprom_source_address+2, temp2
write_eeprom eeprom_source_address+1, temp3
ldi temp1, 169
write_eeprom eeprom_source_address, temp1
rcall blink
rcall blink
cbi PORTA, LED_pin
source_address_assigned:
;
; init the packet
;
rcall init_packet
;
; start event loop
;
clr flags ; clear status flags
mainloop:
;
; wait for the button to be pressed or a click to arrive
;
waitloop:
sbis PINA, click_pin ; check i0 pin for click
rjmp click
sbic PINA, button_bit ; check for button
rjmp waitloop
;
; button pressed
;
button:
;
; wait for button to be released
;
button_release:
sbis PINA, button_bit
rjmp button_release
rcall button_pressed
rjmp mainloop
;
; click arrived
;
click:
;
; check for i0 SLIP start of packet (END character)
;
rcall getclick
ldi temp, END
cpse rxbyte, temp
;
; not start of packet, go back and wait for next char
;
rjmp mainloop
;
; found start, get rest of i0 packet
;
rcall get_packet
;
; return to mainloop if byte_count is zero
;
tst byte_count
breq mainloop
;
; valid packet received, check for address assignment packets
;
clr flags ; clear status flags
check_set_destination_address_port:
compare_immediate incoming_destination_port, high(set_destination_address_port)
brne check_set_source_address_port
compare_immediate incoming_destination_port+1, low(set_destination_address_port)
brne check_set_source_address_port
sbr flags, (1 << set_destination_flag)
rcall blink
rcall blink
rjmp mainloop
check_set_source_address_port:
compare_immediate incoming_destination_port, high(set_source_address_port)
brne check_address
compare_immediate incoming_destination_port+1, low(set_source_address_port)
brne check_address
sbr flags, (1 << set_source_flag)
rcall blink
rcall blink
rjmp mainloop
;
; check to see if incoming destination address matches
;
check_address:
mainloop_test_1:
compare outgoing_source_address, incoming_destination_address
breq mainloop_test_2
rjmp mainloop
mainloop_test_2:
compare outgoing_source_address+1, incoming_destination_address+1
breq mainloop_test_3
rjmp mainloop
mainloop_test_3:
compare outgoing_source_address+2, incoming_destination_address+2
breq mainloop_test_4
rjmp mainloop
mainloop_test_4:
compare outgoing_source_address+3, incoming_destination_address+3
breq address_matches
rjmp mainloop
;
; address matches, check port
;
address_matches:
check_Web_port:
compare_immediate incoming_destination_port, high(Web_port)
brne check_toggle_port
compare_immediate incoming_destination_port+1, low(Web_port)
brne check_toggle_port
rcall send_Web_page
rjmp mainloop
check_toggle_port:
compare_immediate incoming_destination_port, high(toggle_port)
brne port_not_assigned
compare_immediate incoming_destination_port+1, low(toggle_port)
brne port_not_assigned
rcall toggle_light
rjmp mainloop
port_not_assigned:
rjmp mainloop